001    package 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    
022    import java.io.File;
023    import java.io.IOException;
024    import java.util.ArrayList;
025    import java.util.List;
026    
027    import org.apache.maven.scm.ScmException;
028    import org.apache.maven.scm.ScmFile;
029    import org.apache.maven.scm.ScmFileSet;
030    import org.apache.maven.scm.ScmVersion;
031    import org.apache.maven.scm.command.checkin.AbstractCheckInCommand;
032    import org.apache.maven.scm.command.checkin.CheckInScmResult;
033    import org.apache.maven.scm.provider.ScmProviderRepository;
034    import org.apache.maven.scm.provider.vss.commands.VssCommandLineUtils;
035    import org.apache.maven.scm.provider.vss.commands.VssConstants;
036    import org.apache.maven.scm.provider.vss.repository.VssScmProviderRepository;
037    import org.codehaus.plexus.util.cli.CommandLineUtils;
038    import 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     */
047    public 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    }