001package org.apache.maven.scm.provider.vss.commands.checkin;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024import java.util.ArrayList;
025import java.util.List;
026
027import org.apache.maven.scm.ScmException;
028import org.apache.maven.scm.ScmFile;
029import org.apache.maven.scm.ScmFileSet;
030import org.apache.maven.scm.ScmVersion;
031import org.apache.maven.scm.command.checkin.AbstractCheckInCommand;
032import org.apache.maven.scm.command.checkin.CheckInScmResult;
033import org.apache.maven.scm.provider.ScmProviderRepository;
034import org.apache.maven.scm.provider.vss.commands.VssCommandLineUtils;
035import org.apache.maven.scm.provider.vss.commands.VssConstants;
036import org.apache.maven.scm.provider.vss.repository.VssScmProviderRepository;
037import org.codehaus.plexus.util.cli.CommandLineUtils;
038import org.codehaus.plexus.util.cli.Commandline;
039
040/**
041 * @author <a href="mailto:matpimenta@gmail.com">Mateus Pimenta</a>
042 * @author Olivier Lamy
043 * @since 1.3
044 * 
045 */
046public class VssCheckInCommand
047    extends AbstractCheckInCommand
048{
049
050    /**
051     * (non-Javadoc)
052     */
053    protected CheckInScmResult executeCheckInCommand( ScmProviderRepository repository, ScmFileSet fileSet,
054                                                      String message, ScmVersion scmVersion )
055        throws ScmException
056    {
057        if ( getLogger().isDebugEnabled() )
058        {
059            getLogger().debug( "executing checkin command..." );
060        }
061
062        VssScmProviderRepository repo = (VssScmProviderRepository) repository;
063
064        List<Commandline> commandLines = buildCmdLine( repo, fileSet, scmVersion );
065
066        VssCheckInConsumer consumer = new VssCheckInConsumer( repo, getLogger() );
067
068        //      TODO handle deleted files from VSS
069        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
070
071        int exitCode;
072
073        StringBuilder sb = new StringBuilder();
074        for ( Commandline cl : commandLines )
075        {
076
077            if ( getLogger().isDebugEnabled() )
078            {
079                getLogger().debug( "Executing: " + cl.getWorkingDirectory().getAbsolutePath() + ">>" + cl.toString() );
080            }
081
082            exitCode = VssCommandLineUtils.executeCommandline( cl, consumer, stderr, getLogger() );
083
084            if ( exitCode != 0 )
085            {
086                String error = stderr.getOutput();
087
088                if ( getLogger().isDebugEnabled() )
089                {
090                    getLogger().debug( "VSS returns error: [" + error + "] return code: [" + exitCode + "]" );
091                }
092                if ( error.indexOf( "A writable copy of" ) < 0 )
093                {
094                    return new CheckInScmResult( cl.toString(), "The vss command failed.", error, false );
095                }
096                // print out the writable copy for manual handling
097                if ( getLogger().isWarnEnabled() )
098                {
099                    getLogger().warn( error );
100                }
101            }
102
103        }
104        return new CheckInScmResult( sb.toString(), new ArrayList<ScmFile>() );
105    }
106
107    public List<Commandline> buildCmdLine( VssScmProviderRepository repo, ScmFileSet fileSet, ScmVersion version )
108        throws ScmException
109    {
110
111        List<File> files = fileSet.getFileList();
112        List<Commandline> commands = new ArrayList<Commandline>();
113
114        if ( files.size() > 0 )
115        {
116
117            String base;
118            try
119            {
120                base = fileSet.getBasedir().getCanonicalPath();
121            }
122            catch ( IOException e )
123            {
124                throw new ScmException( "Invalid canonical path", e );
125            }
126
127            for ( File file : files )
128            {
129
130                Commandline command = new Commandline();
131
132                try
133                {
134                    command.addSystemEnvironment();
135                }
136                catch ( Exception e )
137                {
138                    throw new ScmException( "Can't add system environment.", e );
139                }
140
141                command.addEnvironment( "SSDIR", repo.getVssdir() );
142
143                String ssDir = VssCommandLineUtils.getSsDir();
144
145                command.setExecutable( ssDir + VssConstants.SS_EXE );
146
147                command.createArg().setValue( VssConstants.COMMAND_CHECKIN );
148
149                String absolute;
150                try
151                {
152                    absolute = file.getCanonicalPath();
153                    String relative;
154                    int index = absolute.indexOf( base );
155                    if ( index >= 0 )
156                    {
157                        relative = absolute.substring( index + base.length() );
158                    }
159                    else
160                    {
161                        relative = file.getPath();
162                    }
163
164                    relative = relative.replace( '\\', '/' );
165
166                    if ( !relative.startsWith( "/" ) )
167                    {
168                        relative = '/' + relative;
169                    }
170
171                    String relativeFolder = relative.substring( 0, relative.lastIndexOf( '/' ) );
172
173                    command.setWorkingDirectory( new File( fileSet.getBasedir().getAbsolutePath() + File.separatorChar
174                        + relativeFolder ).getCanonicalPath() );
175
176                    command.createArg().setValue( VssConstants.PROJECT_PREFIX + repo.getProject() + relative );
177                }
178                catch ( IOException e )
179                {
180                    throw new ScmException( "Invalid canonical path", e );
181                }
182
183                //User identification to get access to vss repository
184                if ( repo.getUserPassword() != null )
185                {
186                    command.createArg().setValue( VssConstants.FLAG_LOGIN + repo.getUserPassword() );
187                }
188
189                // Ignore: Do not ask for input under any circumstances.
190                command.createArg().setValue( VssConstants.FLAG_AUTORESPONSE_DEF );
191
192                // Ignore: Do not touch local writable files.
193                command.createArg().setValue( VssConstants.FLAG_REPLACE_WRITABLE );
194
195                commands.add( command );
196
197            }
198
199        }
200        else
201        {
202            Commandline command = new Commandline();
203
204            command.setWorkingDirectory( fileSet.getBasedir().getAbsolutePath() );
205
206            try
207            {
208                command.addSystemEnvironment();
209            }
210            catch ( Exception e )
211            {
212                throw new ScmException( "Can't add system environment.", e );
213            }
214
215            command.addEnvironment( "SSDIR", repo.getVssdir() );
216
217            String ssDir = VssCommandLineUtils.getSsDir();
218
219            command.setExecutable( ssDir + VssConstants.SS_EXE );
220
221            command.createArg().setValue( VssConstants.COMMAND_CHECKIN );
222
223            command.createArg().setValue( VssConstants.PROJECT_PREFIX + repo.getProject() );
224            //Display the history of an entire project list
225            command.createArg().setValue( VssConstants.FLAG_RECURSION );
226
227            //User identification to get access to vss repository
228            if ( repo.getUserPassword() != null )
229            {
230                command.createArg().setValue( VssConstants.FLAG_LOGIN + repo.getUserPassword() );
231            }
232
233            // Ignore: Do not ask for input under any circumstances.
234            command.createArg().setValue( VssConstants.FLAG_AUTORESPONSE_DEF );
235
236            // Ignore: Do not touch local writable files.
237            command.createArg().setValue( VssConstants.FLAG_REPLACE_WRITABLE );
238
239            commands.add( command );
240
241        }
242
243        return commands;
244
245    }
246}