001    package org.apache.maven.scm.provider.jazz.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 org.apache.maven.scm.ScmException;
023    import org.apache.maven.scm.ScmFile;
024    import org.apache.maven.scm.ScmFileSet;
025    import org.apache.maven.scm.ScmFileStatus;
026    import org.apache.maven.scm.ScmResult;
027    import org.apache.maven.scm.ScmTagParameters;
028    import org.apache.maven.scm.command.tag.AbstractTagCommand;
029    import org.apache.maven.scm.command.tag.TagScmResult;
030    import org.apache.maven.scm.provider.ScmProviderRepository;
031    import org.apache.maven.scm.provider.jazz.command.JazzConstants;
032    import org.apache.maven.scm.provider.jazz.command.JazzScmCommand;
033    import org.apache.maven.scm.provider.jazz.command.consumer.DebugLoggerConsumer;
034    import org.apache.maven.scm.provider.jazz.command.consumer.ErrorConsumer;
035    import org.apache.maven.scm.provider.jazz.repository.JazzScmProviderRepository;
036    import org.codehaus.plexus.util.cli.StreamConsumer;
037    
038    import java.io.File;
039    import java.util.ArrayList;
040    import java.util.List;
041    
042    // The Maven SCM Plugin "tag" goal is equivalent to the RTC "create snapshot" command.
043    //
044    // Once the tag (snapshot in RTC terms) has been created, a repository workspace is then created
045    // based upon that snapshot. This is done to allow the checkout of a tag (maven release plugin) to function.
046    // As, currently, the underlying scm command does not allow us to check out (load in RTC terms) a snapshot directly.
047    //
048    // See the following links for additional information on the RTC "create snapshot" command:
049    // RTC 2.0.0.2:
050    // http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_create.html
051    // RTC 3.0:
052    // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_create.html
053    // RTC 3.0.1:
054    // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_create.html
055    //
056    // See the following links for additional information on the RTC "deliver" command:
057    // RTC 2.0.0.2:
058    // http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_deliver.html
059    // RTC 3.0:
060    // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_deliver.html
061    // RTC 3.0.1:
062    // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_deliver.html
063    
064    /**
065     * @author <a href="mailto:ChrisGWarp@gmail.com">Chris Graham</a>
066     */
067    public class JazzTagCommand
068        extends AbstractTagCommand
069    {
070        /**
071         * {@inheritDoc}
072         */
073        protected ScmResult executeTagCommand( ScmProviderRepository repo, ScmFileSet fileSet, String tag,
074                                               ScmTagParameters scmTagParameters )
075            throws ScmException
076        {
077            if ( getLogger().isDebugEnabled() )
078            {
079                getLogger().debug( "Executing tag command..." );
080            }
081    
082            JazzScmProviderRepository jazzRepo = (JazzScmProviderRepository) repo;
083    
084            getLogger().debug( "Creating Snapshot..." );
085            StreamConsumer tagConsumer =
086                new DebugLoggerConsumer( getLogger() );      // No need for a dedicated consumer for this
087            ErrorConsumer errConsumer = new ErrorConsumer( getLogger() );
088            JazzScmCommand tagCreateSnapshotCmd =
089                createTagCreateSnapshotCommand( jazzRepo, fileSet, tag, scmTagParameters );
090            int status = tagCreateSnapshotCmd.execute( tagConsumer, errConsumer );
091    
092            if ( status != 0 || errConsumer.hasBeenFed() )
093            {
094                return new TagScmResult( tagCreateSnapshotCmd.getCommandString(),
095                                         "Error code for Jazz SCM tag (SNAPSHOT) command - " + status,
096                                         errConsumer.getOutput(), false );
097            }
098    
099            // ------------------------------------------------------------------
100            // We create the workspace based on the tag here, as the scm tool
101            // can not currently check directly out from a snapshot (only a workspace).
102            getLogger().debug( "Creating Workspace from Snapshot..." );
103            JazzScmCommand tagCreateWorkspaceCmd = createTagCreateWorkspaceCommand( jazzRepo, fileSet, tag );
104            errConsumer = new ErrorConsumer( getLogger() );
105            status = tagCreateWorkspaceCmd.execute( tagConsumer, errConsumer );
106    
107            if ( status != 0 || errConsumer.hasBeenFed() )
108            {
109                return new TagScmResult( tagCreateWorkspaceCmd.getCommandString(),
110                                         "Error code for Jazz SCM tag (WORKSPACE) command - " + status,
111                                         errConsumer.getOutput(), false );
112            }
113            // ------------------------------------------------------------------
114    
115            if ( jazzRepo.isPushChangesAndHaveFlowTargets() )
116            {
117                // isPushChanges = true, and we have something to deliver and promote to.
118                getLogger().debug( "Promoting and delivering..." );
119    
120                // So we deliver the code to the target stream (or workspace)
121                getLogger().debug( "Delivering..." );
122                JazzScmCommand tagDeliverCommand = createTagDeliverCommand( jazzRepo, fileSet, tag );
123                errConsumer = new ErrorConsumer( getLogger() );
124                status = tagDeliverCommand.execute( tagConsumer, errConsumer );
125                if ( status != 0 || errConsumer.hasBeenFed() )
126                {
127                    return new TagScmResult( tagDeliverCommand.getCommandString(),
128                                             "Error code for Jazz SCM deliver command - " + status, errConsumer.getOutput(),
129                                             false );
130                }
131    
132                // And now we promote the snapshot to the target stream (or workspace)
133                getLogger().debug( "Promoting snapshot..." );
134                JazzScmCommand tagSnapshotPromoteCommand = createTagSnapshotPromoteCommand( jazzRepo, fileSet, tag );
135                errConsumer = new ErrorConsumer( getLogger() );
136                status = tagSnapshotPromoteCommand.execute( tagConsumer, errConsumer );
137                if ( status != 0 || errConsumer.hasBeenFed() )
138                {
139                    return new TagScmResult( tagSnapshotPromoteCommand.getCommandString(),
140                                             "Error code for Jazz SCM snapshot promote command - " + status,
141                                             errConsumer.getOutput(), false );
142                }
143            }
144    
145            // We don't have a JazzTagConsumer so just build up all the files...
146            List<ScmFile> taggedFiles = new ArrayList<ScmFile>( fileSet.getFileList().size() );
147            for ( File f : fileSet.getFileList() )
148            {
149                taggedFiles.add( new ScmFile( f.getPath(), ScmFileStatus.TAGGED ) );
150            }
151    
152            // We return the "main" or "primary" command executed.
153            // This is similar to the git provider, where the main command is returned.
154            // So we return tagSnapshotCmd and not tagWorkspaceCmd.
155            return new TagScmResult( tagCreateSnapshotCmd.getCommandString(), taggedFiles );
156        }
157    
158        // Create the JazzScmCommand to execute the "scm create snapshot ..." command
159        // This will create a snapshot of the remote repository
160        public JazzScmCommand createTagCreateSnapshotCommand( JazzScmProviderRepository repo, ScmFileSet fileSet,
161                                                              String tag, ScmTagParameters scmTagParameters )
162        {
163            JazzScmCommand command =
164                new JazzScmCommand( JazzConstants.CMD_CREATE, JazzConstants.CMD_SUB_SNAPSHOT, repo, fileSet, getLogger() );
165    
166            if ( tag != null && !tag.trim().equals( "" ) )
167            {
168                command.addArgument( JazzConstants.ARG_SNAPSHOT_NAME );
169                command.addArgument( tag );
170            }
171    
172            String message = scmTagParameters.getMessage();
173            if ( message != null && !message.trim().equals( "" ) )
174            {
175                command.addArgument( JazzConstants.ARG_SNAPSHOT_DESCRIPTION );
176                command.addArgument( message );
177            }
178    
179            command.addArgument( repo.getRepositoryWorkspace() );
180    
181            return command;
182        }
183    
184        // Create the JazzScmCommand to execute the "scm snapshot promote ..." command
185        // This will promote the snapshot to the flow target (the stream or other workspace).
186        public JazzScmCommand createTagSnapshotPromoteCommand( JazzScmProviderRepository repo, ScmFileSet fileSet,
187                                                               String tag )
188        {
189            JazzScmCommand command =
190                new JazzScmCommand( JazzConstants.CMD_SNAPSHOT, JazzConstants.CMD_SUB_PROMOTE, repo, fileSet, getLogger() );
191    
192            if ( repo.getFlowTarget() != null && !repo.getFlowTarget().equals( "" ) )
193            {
194                command.addArgument( repo.getFlowTarget() );
195            }
196            if ( tag != null && !tag.trim().equals( "" ) )
197            {
198                command.addArgument( tag );
199            }
200    
201            return command;
202        }
203    
204        // Create the JazzScmCommand to execute the "scm deliver ..." command
205        // This will deliver the changes to the flow target (stream or other workspace).
206        public JazzScmCommand createTagDeliverCommand( JazzScmProviderRepository repo, ScmFileSet fileSet, String tag )
207        {
208            JazzScmCommand command = new JazzScmCommand( JazzConstants.CMD_DELIVER, repo, fileSet, getLogger() );
209    
210            if ( repo.getWorkspace() != null && !repo.getWorkspace().equals( "" ) )
211            {
212                // Don't deliver from the workspace, as it has the release.properties etc files in it
213                // and jazz will choke on them, so use the workspace that we just created (tag) instead.
214                command.addArgument( JazzConstants.ARG_DELIVER_SOURCE );
215                command.addArgument( tag );
216            }
217    
218            if ( repo.getFlowTarget() != null && !repo.getFlowTarget().equals( "" ) )
219            {
220                command.addArgument( JazzConstants.ARG_DELIVER_TARGET );
221                command.addArgument( repo.getFlowTarget() );
222            }
223    
224            return command;
225        }
226    
227        // Create the JazzScmCommand to execute the "scm create workspace ..." command
228        // This will create a workspace of the same name as the tag.
229        public JazzScmCommand createTagCreateWorkspaceCommand( JazzScmProviderRepository repo, ScmFileSet fileSet,
230                                                               String tag )
231        {
232            JazzScmCommand command =
233                new JazzScmCommand( JazzConstants.CMD_CREATE, JazzConstants.CMD_SUB_WORKSPACE, repo, fileSet, getLogger() );
234    
235            if ( tag != null && !tag.trim().equals( "" ) )
236            {
237                command.addArgument( tag );
238                command.addArgument( JazzConstants.ARG_WORKSPACE_SNAPSHOT );
239                command.addArgument( tag );
240            }
241    
242            return command;
243        }
244    
245    }