View Javadoc
1   package org.apache.maven.scm.provider.jazz.command.checkin;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   * http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.List;
24  
25  import org.apache.maven.scm.ScmException;
26  import org.apache.maven.scm.ScmFileSet;
27  import org.apache.maven.scm.ScmVersion;
28  import org.apache.maven.scm.command.add.AddScmResult;
29  import org.apache.maven.scm.command.checkin.AbstractCheckInCommand;
30  import org.apache.maven.scm.command.checkin.CheckInScmResult;
31  import org.apache.maven.scm.provider.ScmProviderRepository;
32  import org.apache.maven.scm.provider.jazz.command.JazzConstants;
33  import org.apache.maven.scm.provider.jazz.command.JazzScmCommand;
34  import org.apache.maven.scm.provider.jazz.command.add.JazzAddCommand;
35  import org.apache.maven.scm.provider.jazz.command.consumer.DebugLoggerConsumer;
36  import org.apache.maven.scm.provider.jazz.command.consumer.ErrorConsumer;
37  import org.apache.maven.scm.provider.jazz.repository.JazzScmProviderRepository;
38  import org.codehaus.plexus.util.StringUtils;
39  import org.codehaus.plexus.util.cli.StreamConsumer;
40  
41  // The Maven SCM Plugin "checkin" goal is equivalent to the RTC "checkin" command.
42  //
43  // This implementation of the Maven SCM Plugin "checkin" goal creates a change set with the message provided.
44  // It then uses the Jazz "scm "checkin" command to check the files into a remote workspace.
45  // If there is a flow target defined and the pushChanges flag is true (the default), then the remote workspace
46  // will be delivered ("scm deliver") to the flow target (a stream or other workspace).
47  // 
48  // Set the pushChanges flag to false, if you do not want the repository workspace delivered.
49  //
50  // NOTE: At this point, only a SINGLE flow target is supported. Jazz itself, allows for more than one.
51  //
52  // The differences between this and the "add" goal, are:
53  //      - The add goal will only checkin into the remote repository workspace.
54  //      - The add goal will never deliver.
55  //      - The add goal does not create a change set.
56  //
57  // This is the best we can do to mimic the implementations of the other providers, that provide a working
58  // "add" function (eg "svn add").
59  //
60  // Add may have had been able to use the "scm share" command, but that is recusive and only takes directory
61  // names; we are not able to specify specific or single files.
62  //
63  // See the following links for additional information on the RTC "checkin" command.
64  // RTC 2.0.0.2:
65  // http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_checkin.html
66  // RTC 3.0:
67  // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_checkin.html
68  // RTC 3.0.1:
69  // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_checkin.html
70  //
71  // See the following links for additional information on the RTC "deliver" command.
72  // RTC 2.0.0.2:
73  // http://publib.boulder.ibm.com/infocenter/rtc/v2r0m0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_deliver.html
74  // RTC 3.0:
75  // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0/topic/com.ibm.team.scm.doc/topics/r_scm_cli_deliver.html
76  // RTC 3.0.1:
77  // http://publib.boulder.ibm.com/infocenter/clmhelp/v3r0m1/topic/com.ibm.team.scm.doc/topics/r_scm_cli_deliver.html
78  //
79  
80  /**
81   * @author <a href="mailto:ChrisGWarp@gmail.com">Chris Graham</a>
82   */
83  public class JazzCheckInCommand
84      extends AbstractCheckInCommand
85  {
86  
87      /**
88       * {@inheritDoc}
89       */
90      protected CheckInScmResult executeCheckInCommand( ScmProviderRepository repository, ScmFileSet fileSet,
91                                                        String message, ScmVersion scmVersion )
92          throws ScmException
93      {
94          if ( scmVersion != null && StringUtils.isNotEmpty( scmVersion.getName() ) )
95          {
96              throw new ScmException( "This provider command can't handle tags." );
97          }
98  
99          if ( getLogger().isDebugEnabled() )
100         {
101             getLogger().debug( "Executing checkin command..." );
102         }
103 
104         // Create a changeset. We need to do this, as otherwise the information contained in the message
105         // will be lost forever.
106         JazzScmCommand createChangesetCmd = createCreateChangesetCommand( repository, fileSet, message );
107         DebugLoggerConsumer outputConsumer = new DebugLoggerConsumer( getLogger() );
108         ErrorConsumer errConsumer = new ErrorConsumer( getLogger() );
109 
110         int status = createChangesetCmd.execute( outputConsumer, errConsumer );
111         if ( status != 0 || errConsumer.hasBeenFed() )
112         {
113             return new CheckInScmResult( createChangesetCmd.getCommandString(),
114                                          "Error code for Jazz SCM create changeset command - " + status,
115                                          errConsumer.getOutput(), false );
116         }
117 
118         // Now check in the files themselves.
119         return executeCheckInCommand( repository, fileSet, scmVersion );
120     }
121 
122     protected CheckInScmResult executeCheckInCommand( ScmProviderRepository repo, ScmFileSet fileSet,
123                                                       ScmVersion scmVersion )
124         throws ScmException
125     {
126         // Call the Add command to perform the checkin into the repository workspace.
127         JazzAddCommand addCommand = new JazzAddCommand();
128         addCommand.setLogger( getLogger() );
129         AddScmResult addResult = addCommand.executeAddCommand( repo, fileSet );
130 
131         // Now, if it has a flow target, deliver it.
132         JazzScmProviderRepository jazzRepo = (JazzScmProviderRepository) repo;
133         if ( jazzRepo.isPushChangesAndHaveFlowTargets() )
134         {
135             // Push if we need too
136             JazzScmCommand deliverCmd = createDeliverCommand( (JazzScmProviderRepository) repo, fileSet );
137             StreamConsumer deliverConsumer =
138                 new DebugLoggerConsumer( getLogger() );      // No need for a dedicated consumer for this
139             ErrorConsumer errConsumer = new ErrorConsumer( getLogger() );
140 
141             int status = deliverCmd.execute( deliverConsumer, errConsumer );
142             if ( status != 0 || errConsumer.hasBeenFed() )
143             {
144                 return new CheckInScmResult( deliverCmd.getCommandString(),
145                                              "Error code for Jazz SCM deliver command - " + status,
146                                              errConsumer.getOutput(), false );
147             }
148         }
149 
150         // Return what was added.
151         return new CheckInScmResult( addResult.getCommandLine(), addResult.getAddedFiles() );
152     }
153 
154     public JazzScmCommand createCreateChangesetCommand( ScmProviderRepository repo, ScmFileSet fileSet, String message )
155     {
156         JazzScmCommand command =
157             new JazzScmCommand( JazzConstants.CMD_CREATE, JazzConstants.CMD_SUB_CHANGESET, repo, false, fileSet,
158                                 getLogger() );
159         command.addArgument( message );
160 
161         return command;
162     }
163 
164     public JazzScmCommand createCheckInCommand( ScmProviderRepository repo, ScmFileSet fileSet )
165     {
166         JazzScmCommand command =
167             new JazzScmCommand( JazzConstants.CMD_CHECKIN, null, repo, false, fileSet, getLogger() );
168 
169         // TODO, this was taken out to quickly test how the release plugin works.
170         // The release plugin has the fileSet.getbaseDir() as the project it is checking in
171         // This happens to be a folder under the sandbox root, and so the checkin would fail because it needs
172         // to check in at the sandbox root level (not sub folders)
173         // The SCM Plugin has a basedir parameter that you can pass it, so everythig works ok from the scm-plugin alone
174         // but the release-plugin doesn't look like it lets you do that. (or I didn't have enough time
175         // to figure out how to do it properly).
176 
177         // if (fileSet != null) {
178         // command.addArgument(JazzConstants.LOAD_ROOT_DIRECTORY_ARG);
179         // command.addArgument(fileSet.getBasedir().getAbsolutePath());
180         // }
181 
182         List<File> files = fileSet.getFileList();
183         if ( files != null && !files.isEmpty() )
184         {
185             for ( File file : files )
186             {
187                 command.addArgument( file.getPath() ); // Check in only the files specified
188             }
189         }
190         else
191         {
192             command.addArgument( "." ); // This will check in all local changes
193         }
194 
195         return command;
196     }
197 
198     // Create the JazzScmCommand to execute the "scm deliver ..." command
199     // This will deliver the changes to the flow target (stream or other workspace).
200     public JazzScmCommand createDeliverCommand( JazzScmProviderRepository repo, ScmFileSet fileSet )
201     {
202         JazzScmCommand command = new JazzScmCommand( JazzConstants.CMD_DELIVER, repo, fileSet, getLogger() );
203 
204         if ( repo.getWorkspace() != null && !repo.getWorkspace().equals( "" ) )
205         {
206             command.addArgument( JazzConstants.ARG_DELIVER_SOURCE );
207             command.addArgument( repo.getWorkspace() );
208         }
209 
210         if ( repo.getFlowTarget() != null && !repo.getFlowTarget().equals( "" ) )
211         {
212             command.addArgument( JazzConstants.ARG_DELIVER_TARGET );
213             command.addArgument( repo.getFlowTarget() );
214         }
215 
216         // This command is needed so that the deliver operation will work.
217         // Files that are not under source control (a--) [temp files etc]
218         // will cause the deliver operation to fail with the error:
219         // "Cannot deliver because there are one or more items that are not checked in.
220         // Check in the changes or rerun with --overwrite-uncommitted."
221         // However, from the maven perspective, we only need files that are
222         // under source control to be delivered. Maven has already checked
223         // for this (via the status command). 
224         //
225         // So we add this argument to allow the deliver to work.
226         command.addArgument( JazzConstants.ARG_OVERWRITE_UNCOMMITTED );
227 
228         return command;
229     }
230 }