001    package org.apache.maven.scm.provider.svn.svnexe.command.tag;
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.Iterator;
026    import java.util.List;
027    
028    import org.apache.maven.scm.ScmException;
029    import org.apache.maven.scm.ScmFile;
030    import org.apache.maven.scm.ScmFileSet;
031    import org.apache.maven.scm.ScmFileStatus;
032    import org.apache.maven.scm.ScmResult;
033    import org.apache.maven.scm.ScmTag;
034    import org.apache.maven.scm.ScmTagParameters;
035    import org.apache.maven.scm.command.tag.AbstractTagCommand;
036    import org.apache.maven.scm.command.tag.TagScmResult;
037    import org.apache.maven.scm.provider.ScmProviderRepository;
038    import org.apache.maven.scm.provider.svn.SvnCommandUtils;
039    import org.apache.maven.scm.provider.svn.SvnTagBranchUtils;
040    import org.apache.maven.scm.provider.svn.command.SvnCommand;
041    import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
042    import org.apache.maven.scm.provider.svn.svnexe.command.SvnCommandLineUtils;
043    import org.codehaus.plexus.util.FileUtils;
044    import org.codehaus.plexus.util.StringUtils;
045    import org.codehaus.plexus.util.cli.CommandLineException;
046    import org.codehaus.plexus.util.cli.CommandLineUtils;
047    import org.codehaus.plexus.util.cli.Commandline;
048    
049    /**
050     * @author <a href="mailto:brett@apache.org">Brett Porter</a>
051     * @author Olivier Lamy
052     * @version $Id: SvnTagCommand.java 1057940 2011-01-11 23:45:48Z olamy $
053     * @todo since this is just a copy, use that instead.
054     */
055    public class SvnTagCommand
056        extends AbstractTagCommand
057        implements SvnCommand
058    {
059        
060        public ScmResult executeTagCommand( ScmProviderRepository repo, ScmFileSet fileSet, String tag, String message )
061            throws ScmException
062        {
063            ScmTagParameters scmTagParameters = new ScmTagParameters( message );
064            // force false to preserve backward comp
065            scmTagParameters.setRemoteTagging( false );
066            return executeTagCommand( repo, fileSet, tag, scmTagParameters );
067        }
068        
069        /** {@inheritDoc} */
070        public ScmResult executeTagCommand( ScmProviderRepository repo, ScmFileSet fileSet, String tag,
071                                            ScmTagParameters scmTagParameters )
072            throws ScmException
073        {
074            // NPE free
075            if (scmTagParameters == null)
076            {
077                getLogger().debug( "SvnTagCommand :: scmTagParameters is null create an empty one" );
078                scmTagParameters = new ScmTagParameters();
079                scmTagParameters.setRemoteTagging( false );
080              
081            }
082            else
083            {
084                getLogger().debug(
085                                   "SvnTagCommand :: scmTagParameters.remoteTagging : "
086                                       + scmTagParameters.isRemoteTagging() );
087            }
088            if ( tag == null || StringUtils.isEmpty( tag.trim() ) )
089            {
090                throw new ScmException( "tag must be specified" );
091            }
092    
093            if ( !fileSet.getFileList().isEmpty() )
094            {
095                throw new ScmException( "This provider doesn't support tagging subsets of a directory" );
096            }
097    
098            SvnScmProviderRepository repository = (SvnScmProviderRepository) repo;
099    
100            File messageFile = FileUtils.createTempFile( "maven-scm-", ".commit", null );
101    
102            try
103            {
104                FileUtils.fileWrite( messageFile.getAbsolutePath(), scmTagParameters == null ? "" : scmTagParameters
105                    .getMessage() );
106            }
107            catch ( IOException ex )
108            {
109                return new TagScmResult( null, "Error while making a temporary file for the commit message: "
110                    + ex.getMessage(), null, false );
111            }
112           
113            Commandline cl = createCommandLine( repository, fileSet.getBasedir(), tag, messageFile, scmTagParameters );
114            
115            CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
116    
117            CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
118    
119            if ( getLogger().isInfoEnabled() )
120            {
121                getLogger().info( "Executing: " + SvnCommandLineUtils.cryptPassword( cl ) );
122                getLogger().info( "Working directory: " + cl.getWorkingDirectory().getAbsolutePath() );
123            }
124    
125            int exitCode;
126    
127            try
128            {
129                exitCode = SvnCommandLineUtils.execute( cl, stdout, stderr, getLogger() );
130            }
131            catch ( CommandLineException ex )
132            {
133                throw new ScmException( "Error while executing command.", ex );
134            }
135            finally
136            {
137                try
138                {
139                    FileUtils.forceDelete( messageFile );
140                }
141                catch ( IOException ex )
142                {
143                    // ignore
144                }
145            }
146    
147            if ( exitCode != 0 )
148            {
149                // TODO: Improve this error message
150                return new TagScmResult( cl.toString(), "The svn tag command failed.", stderr.getOutput(), false );
151            }
152    
153            List<ScmFile> fileList = new ArrayList<ScmFile>();
154    
155            List<File> files = null;
156    
157            try
158            {
159                if ( StringUtils.isNotEmpty( fileSet.getExcludes() ) )
160                {
161                    @SuppressWarnings( "unchecked" )
162                    List<File> list =
163                        FileUtils.getFiles( fileSet.getBasedir(),
164                                            ( StringUtils.isEmpty( fileSet.getIncludes() ) ? "**"
165                                                            : fileSet.getIncludes() ), fileSet.getExcludes()
166                                                + ",**/.svn/**", false );
167                    files = list;
168                }
169                else
170                {
171                    @SuppressWarnings( "unchecked" )
172                    List<File> list =
173                        FileUtils.getFiles( fileSet.getBasedir(),
174                                            ( StringUtils.isEmpty( fileSet.getIncludes() ) ? "**"
175                                                            : fileSet.getIncludes() ), "**/.svn/**", false );
176                    files = list;
177                }
178            }
179            catch ( IOException e )
180            {
181                throw new ScmException( "Error while executing command.", e );
182            }
183    
184            for ( Iterator<File> i = files.iterator(); i.hasNext(); )
185            {
186                File f = i.next();
187    
188                fileList.add( new ScmFile( f.getPath(), ScmFileStatus.TAGGED ) );
189            }
190    
191            return new TagScmResult( cl.toString(), fileList );
192        }
193    
194        // ----------------------------------------------------------------------
195        //
196        // ----------------------------------------------------------------------
197    
198        /**
199         * @deprecated
200         * @param repository
201         * @param workingDirectory
202         * @param tag
203         * @param messageFile
204         * @return
205         */
206        public static Commandline createCommandLine( SvnScmProviderRepository repository, File workingDirectory, String tag,
207                                                     File messageFile )
208        {
209            Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine( workingDirectory, repository );
210    
211            cl.createArg().setValue( "copy" );
212    
213            cl.createArg().setValue( "--file" );
214    
215            cl.createArg().setValue( messageFile.getAbsolutePath() );
216    
217            cl.createArg().setValue( "." );
218    
219            // Note: this currently assumes you have the tag base checked out too
220            String tagUrl = SvnTagBranchUtils.resolveTagUrl( repository, new ScmTag( tag ) );
221            cl.createArg().setValue( SvnCommandUtils.fixUrl( tagUrl, repository.getUser() ) );
222    
223            return cl;
224        }
225    
226        
227        public static Commandline createCommandLine( SvnScmProviderRepository repository, File workingDirectory,
228                                                     String tag, File messageFile, ScmTagParameters scmTagParameters )
229        {
230            Commandline cl = SvnCommandLineUtils.getBaseSvnCommandLine( workingDirectory, repository );
231    
232            cl.createArg().setValue( "copy" );
233    
234            cl.createArg().setValue( "--file" );
235    
236            cl.createArg().setValue( messageFile.getAbsolutePath() );
237    
238            // SCM-487 olamy : this need a svn 1.5 cli 
239            //cl.createArg().setValue( "--parents" );
240            
241            if ( scmTagParameters != null && scmTagParameters.getScmRevision() != null )
242            {
243                cl.createArg().setValue( "--revision" );
244                
245                cl.createArg().setValue( scmTagParameters.getScmRevision() );
246                
247            }
248            
249    
250            if ( scmTagParameters != null && scmTagParameters.isRemoteTagging() )
251            {
252                cl.createArg().setValue( repository.getUrl() );
253            }
254            else
255            {
256                cl.createArg().setValue( "." );
257            }
258    
259            // Note: this currently assumes you have the tag base checked out too
260            String tagUrl = SvnTagBranchUtils.resolveTagUrl( repository, new ScmTag( tag ) );
261            cl.createArg().setValue( SvnCommandUtils.fixUrl( tagUrl, repository.getUser() ) );
262    
263            return cl;
264        }    
265    }