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 * @version $Id
045 * 
046 */
047public class VssCheckInCommand
048    extends AbstractCheckInCommand
049{
050
051    /**
052     * (non-Javadoc)
053     * 
054     * @see org.apache.maven.scm.command.checkin.AbstractCheckInCommand# executeCheckInCommand
055     * (org.apache.maven.scm.provider.ScmProviderRepository, org.apache.maven.scm.ScmFileSet,
056     * java.lang.String, org.apache.maven.scm.ScmVersion)
057     */
058    protected CheckInScmResult executeCheckInCommand( ScmProviderRepository repository, ScmFileSet fileSet,
059                                                      String message, ScmVersion scmVersion )
060        throws ScmException
061    {
062        if ( getLogger().isDebugEnabled() )
063        {
064            getLogger().debug( "executing checkin command..." );
065        }
066
067        VssScmProviderRepository repo = (VssScmProviderRepository) repository;
068
069        List<Commandline> commandLines = buildCmdLine( repo, fileSet, scmVersion );
070
071        VssCheckInConsumer consumer = new VssCheckInConsumer( repo, getLogger() );
072
073        //      TODO handle deleted files from VSS
074        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
075
076        int exitCode;
077
078        StringBuilder sb = new StringBuilder();
079        for ( Commandline cl : commandLines )
080        {
081
082            if ( getLogger().isDebugEnabled() )
083            {
084                getLogger().debug( "Executing: " + cl.getWorkingDirectory().getAbsolutePath() + ">>" + cl.toString() );
085            }
086
087            exitCode = VssCommandLineUtils.executeCommandline( cl, consumer, stderr, getLogger() );
088
089            if ( exitCode != 0 )
090            {
091                String error = stderr.getOutput();
092
093                if ( getLogger().isDebugEnabled() )
094                {
095                    getLogger().debug( "VSS returns error: [" + error + "] return code: [" + exitCode + "]" );
096                }
097                if ( error.indexOf( "A writable copy of" ) < 0 )
098                {
099                    return new CheckInScmResult( cl.toString(), "The vss command failed.", error, false );
100                }
101                // print out the writable copy for manual handling
102                if ( getLogger().isWarnEnabled() )
103                {
104                    getLogger().warn( error );
105                }
106            }
107
108        }
109        return new CheckInScmResult( sb.toString(), new ArrayList<ScmFile>() );
110    }
111
112    public List<Commandline> buildCmdLine( VssScmProviderRepository repo, ScmFileSet fileSet, ScmVersion version )
113        throws ScmException
114    {
115
116        List<File> files = fileSet.getFileList();
117        List<Commandline> commands = new ArrayList<Commandline>();
118
119        if ( files.size() > 0 )
120        {
121
122            String base;
123            try
124            {
125                base = fileSet.getBasedir().getCanonicalPath();
126            }
127            catch ( IOException e )
128            {
129                throw new ScmException( "Invalid canonical path", e );
130            }
131
132            for ( File file : files )
133            {
134
135                Commandline command = new Commandline();
136
137                try
138                {
139                    command.addSystemEnvironment();
140                }
141                catch ( Exception e )
142                {
143                    throw new ScmException( "Can't add system environment.", e );
144                }
145
146                command.addEnvironment( "SSDIR", repo.getVssdir() );
147
148                String ssDir = VssCommandLineUtils.getSsDir();
149
150                command.setExecutable( ssDir + VssConstants.SS_EXE );
151
152                command.createArg().setValue( VssConstants.COMMAND_CHECKIN );
153
154                String absolute;
155                try
156                {
157                    absolute = file.getCanonicalPath();
158                    String relative;
159                    int index = absolute.indexOf( base );
160                    if ( index >= 0 )
161                    {
162                        relative = absolute.substring( index + base.length() );
163                    }
164                    else
165                    {
166                        relative = file.getPath();
167                    }
168
169                    relative = relative.replace( '\\', '/' );
170
171                    if ( !relative.startsWith( "/" ) )
172                    {
173                        relative = '/' + relative;
174                    }
175
176                    String relativeFolder = relative.substring( 0, relative.lastIndexOf( '/' ) );
177
178                    command.setWorkingDirectory( new File( fileSet.getBasedir().getAbsolutePath() + File.separatorChar
179                        + relativeFolder ).getCanonicalPath() );
180
181                    command.createArg().setValue( VssConstants.PROJECT_PREFIX + repo.getProject() + relative );
182                }
183                catch ( IOException e )
184                {
185                    throw new ScmException( "Invalid canonical path", e );
186                }
187
188                //User identification to get access to vss repository
189                if ( repo.getUserPassword() != null )
190                {
191                    command.createArg().setValue( VssConstants.FLAG_LOGIN + repo.getUserPassword() );
192                }
193
194                // Ignore: Do not ask for input under any circumstances.
195                command.createArg().setValue( VssConstants.FLAG_AUTORESPONSE_DEF );
196
197                // Ignore: Do not touch local writable files.
198                command.createArg().setValue( VssConstants.FLAG_REPLACE_WRITABLE );
199
200                commands.add( command );
201
202            }
203
204        }
205        else
206        {
207            Commandline command = new Commandline();
208
209            command.setWorkingDirectory( fileSet.getBasedir().getAbsolutePath() );
210
211            try
212            {
213                command.addSystemEnvironment();
214            }
215            catch ( Exception e )
216            {
217                throw new ScmException( "Can't add system environment.", e );
218            }
219
220            command.addEnvironment( "SSDIR", repo.getVssdir() );
221
222            String ssDir = VssCommandLineUtils.getSsDir();
223
224            command.setExecutable( ssDir + VssConstants.SS_EXE );
225
226            command.createArg().setValue( VssConstants.COMMAND_CHECKIN );
227
228            command.createArg().setValue( VssConstants.PROJECT_PREFIX + repo.getProject() );
229            //Display the history of an entire project list
230            command.createArg().setValue( VssConstants.FLAG_RECURSION );
231
232            //User identification to get access to vss repository
233            if ( repo.getUserPassword() != null )
234            {
235                command.createArg().setValue( VssConstants.FLAG_LOGIN + repo.getUserPassword() );
236            }
237
238            // Ignore: Do not ask for input under any circumstances.
239            command.createArg().setValue( VssConstants.FLAG_AUTORESPONSE_DEF );
240
241            // Ignore: Do not touch local writable files.
242            command.createArg().setValue( VssConstants.FLAG_REPLACE_WRITABLE );
243
244            commands.add( command );
245
246        }
247
248        return commands;
249
250    }
251}