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