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