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