001    package org.apache.maven.scm.provider.svn.svnexe.command.branch;
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.ScmBranch;
028    import org.apache.maven.scm.ScmBranchParameters;
029    import org.apache.maven.scm.ScmException;
030    import org.apache.maven.scm.ScmFile;
031    import org.apache.maven.scm.ScmFileSet;
032    import org.apache.maven.scm.ScmFileStatus;
033    import org.apache.maven.scm.ScmResult;
034    import org.apache.maven.scm.command.branch.AbstractBranchCommand;
035    import org.apache.maven.scm.command.branch.BranchScmResult;
036    import org.apache.maven.scm.provider.ScmProviderRepository;
037    import org.apache.maven.scm.provider.svn.SvnCommandUtils;
038    import org.apache.maven.scm.provider.svn.SvnTagBranchUtils;
039    import org.apache.maven.scm.provider.svn.command.SvnCommand;
040    import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
041    import org.apache.maven.scm.provider.svn.svnexe.command.SvnCommandLineUtils;
042    import org.codehaus.plexus.util.FileUtils;
043    import org.codehaus.plexus.util.StringUtils;
044    import org.codehaus.plexus.util.cli.CommandLineException;
045    import org.codehaus.plexus.util.cli.CommandLineUtils;
046    import org.codehaus.plexus.util.cli.Commandline;
047    
048    /**
049     * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse</a>
050     * @author Olivier Lamy
051     * @version $Id: SvnBranchCommand.java 1057938 2011-01-11 23:45:29Z olamy $
052     * @todo since this is just a copy, use that instead.
053     */
054    public class SvnBranchCommand
055        extends AbstractBranchCommand
056        implements SvnCommand
057    {
058        
059        public ScmResult executeBranchCommand( ScmProviderRepository repo, ScmFileSet fileSet, String branch, ScmBranchParameters scmBranchParameters )
060        throws ScmException
061        {
062            if ( branch == null || StringUtils.isEmpty( branch.trim() ) )
063            {
064                throw new ScmException( "branch name must be specified" );
065            }
066    
067            if ( !fileSet.getFileList().isEmpty() )
068            {
069                throw new ScmException( "This provider doesn't support branching subsets of a directory" );
070            }
071    
072            SvnScmProviderRepository repository = (SvnScmProviderRepository) repo;
073    
074            File messageFile = FileUtils.createTempFile( "maven-scm-", ".commit", null );
075    
076            try
077            {
078                FileUtils.fileWrite( messageFile.getAbsolutePath(), scmBranchParameters.getMessage() );
079            }
080            catch ( IOException ex )
081            {
082                return new BranchScmResult( null, "Error while making a temporary file for the commit message: "
083                    + ex.getMessage(), null, false );
084            }
085    
086            Commandline cl = createCommandLine( repository, fileSet.getBasedir(), branch, messageFile, scmBranchParameters );
087    
088            CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
089    
090            CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
091    
092            if ( getLogger().isInfoEnabled() )
093            {
094                getLogger().info( "Executing: " + SvnCommandLineUtils.cryptPassword( cl ) );
095                getLogger().info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
096            }
097    
098            int exitCode;
099    
100            try
101            {
102                exitCode = SvnCommandLineUtils.execute( cl, stdout, stderr, getLogger() );
103            }
104            catch ( CommandLineException ex )
105            {
106                throw new ScmException( "Error while executing command.", ex );
107            }
108            finally
109            {
110                try
111                {
112                    FileUtils.forceDelete( messageFile );
113                }
114                catch ( IOException ex )
115                {
116                    // ignore
117                }
118            }
119    
120            if ( exitCode != 0 )
121            {
122                return new BranchScmResult( cl.toString(), "The svn branch command failed.", stderr.getOutput(), false );
123            }
124    
125            List<ScmFile> fileList = new ArrayList<ScmFile>();
126    
127            List<File> files = null;
128    
129            try
130            {
131                @SuppressWarnings( "unchecked" )
132                List<File> listFiles = FileUtils.getFiles( fileSet.getBasedir(), "**", "**/.svn/**", false );
133                files = listFiles;
134            }
135            catch ( IOException e )
136            {
137                throw new ScmException( "Error while executing command.", e );
138            }
139    
140            for ( File f : files )
141            {
142                fileList.add( new ScmFile( f.getPath(), ScmFileStatus.TAGGED ) );
143            }
144    
145            return new BranchScmResult( cl.toString(), fileList );
146        }
147        
148        /** {@inheritDoc} */
149        public ScmResult executeBranchCommand( ScmProviderRepository repo, ScmFileSet fileSet, String branch,
150                                               String message )
151            throws ScmException
152        {
153            ScmBranchParameters scmBranchParameters = new ScmBranchParameters( message );
154            return executeBranchCommand( repo, fileSet, branch, scmBranchParameters );
155        }
156    
157        // ----------------------------------------------------------------------
158        //
159        // ----------------------------------------------------------------------
160    
161        public static Commandline createCommandLine( SvnScmProviderRepository repository, File workingDirectory,
162                                                     String branch, File messageFile )
163        {
164            ScmBranchParameters scmBranchParameters = new ScmBranchParameters();
165            scmBranchParameters.setRemoteBranching( false );
166            return createCommandLine( repository, workingDirectory, branch, messageFile, scmBranchParameters );
167        }
168        
169        public static Commandline createCommandLine( SvnScmProviderRepository repository, File workingDirectory,
170                                                     String branch, File messageFile, ScmBranchParameters scmBranchParameters )
171        {
172            Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine( workingDirectory, repository );
173    
174            cl.createArg().setValue( "copy" );
175    
176            cl.createArg().setValue( "--file" );
177    
178            cl.createArg().setValue( messageFile.getAbsolutePath() );
179    
180            if ( scmBranchParameters != null && scmBranchParameters.isRemoteBranching() )
181            {
182                if (StringUtils.isNotBlank( scmBranchParameters.getScmRevision() ) )
183                {
184                    cl.createArg().setValue( "--revision" );
185                    cl.createArg().setValue( scmBranchParameters.getScmRevision() );
186                }
187                cl.createArg().setValue( repository.getUrl() );
188            }
189            else
190            {
191                cl.createArg().setValue( "." );
192            }
193            // Note: this currently assumes you have the branch base checked out too
194            String branchUrl = SvnTagBranchUtils.resolveBranchUrl( repository, new ScmBranch( branch ) );
195            cl.createArg().setValue( SvnCommandUtils.fixUrl( branchUrl, repository.getUser() ) );
196    
197            return cl;
198        }    
199    }