Repository: maven-scm Updated Branches: refs/heads/master c76eb1f11 -> dd3a18d05
Change: Added consumer Project: http://git-wip-us.apache.org/repos/asf/maven-scm/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-scm/commit/8dd21b9c Tree: http://git-wip-us.apache.org/repos/asf/maven-scm/tree/8dd21b9c Diff: http://git-wip-us.apache.org/repos/asf/maven-scm/diff/8dd21b9c Branch: refs/heads/master Commit: 8dd21b9c2477539cc768c548e4cd877c29aac1ff Parents: c76eb1f Author: Chris Graham <chrisgw...@apache.org> Authored: Sat Apr 4 21:33:44 2015 +1100 Committer: Chris Graham <chrisgw...@apache.org> Committed: Wed May 6 13:29:55 2015 +1000 ---------------------------------------------------------------------- .../scm/provider/ScmProviderRepository.java | 44 ++++++++ .../prepare.groovy | 4 + .../maven/scm/plugin/AbstractScmMojo.java | 14 +++ .../provider/jazz/command/JazzConstants.java | 12 ++ .../command/checkin/JazzCheckInCommand.java | 31 ++++++ .../jazz/command/status/JazzStatusConsumer.java | 111 +++++++++++++++++-- .../repository/JazzScmProviderRepository.java | 23 +++- .../command/checkin/JazzCheckInCommandTest.java | 12 ++ .../command/status/JazzStatusCommandTest.java | 1 + 9 files changed, 242 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProviderRepository.java ---------------------------------------------------------------------- diff --git a/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProviderRepository.java b/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProviderRepository.java index 58e2a50..c55b525 100644 --- a/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProviderRepository.java +++ b/maven-scm-api/src/main/java/org/apache/maven/scm/provider/ScmProviderRepository.java @@ -22,6 +22,7 @@ package org.apache.maven.scm.provider; /** * @author <a href="mailto:tryg...@inamo.no">Trygve Laugstøl</a> * @author <a href="mailto:eveni...@apache.org">Emmanuel Venisse</a> + * @author <a href="mailto:chrisgw...@gmail.com">Chris Graham</a> * */ public abstract class ScmProviderRepository @@ -38,6 +39,31 @@ public abstract class ScmProviderRepository private boolean pushChanges = true; /** + * Some SCMs have the concept of a work item (or task) which may need to be + * specified to allow changes to be pushed or delivered to a target. + * This allows you to answer the question: For this workItem, what changed? + * Auditors have been known to love this... :) + * SCMs known to implement this are: + * <ul> + * <li>IBM Rational Team Concert (workItem) + * <li>Microsoft Team Foundation Server (workItem) + * <li>IBM Rational ClearQuest Enabled UCM ClearCase (task) + * </ul> + * There may be others that support this feature. + * <P> + * These SCMs can be configured to reject a push/deliver unless additional + * information (by way of a workItem/task) is supplied. + * <P> + * This field is only relevant when pushChanges = true. + * <P> + * It should be noted however, when pushChanges = true, a workItem does not + * need to be set, as the need for a workItem may be optional. + * + * @since 1.9.5 + */ + private String workItem; + + /** * @return The user. */ public String getUser() @@ -95,6 +121,24 @@ public abstract class ScmProviderRepository } /** + * @return The workItem. + */ + public String getWorkItem() + { + return workItem; + } + + /** + * Set the workItem. + * + * @param user The workItem. + */ + public void setWorkItem( String workItem ) + { + this.workItem = workItem; + } + + /** * Will checkouts using this repository be persisted so they can * be refreshed in the future? This property is of concern to SCMs * like Perforce and Clearcase where the server must track where a http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-plugin/src/it/scm-741-validate-scm-url-matches-working-copy/prepare.groovy ---------------------------------------------------------------------- diff --git a/maven-scm-plugin/src/it/scm-741-validate-scm-url-matches-working-copy/prepare.groovy b/maven-scm-plugin/src/it/scm-741-validate-scm-url-matches-working-copy/prepare.groovy index 40cf6ff..a4915ee 100644 --- a/maven-scm-plugin/src/it/scm-741-validate-scm-url-matches-working-copy/prepare.groovy +++ b/maven-scm-plugin/src/it/scm-741-validate-scm-url-matches-working-copy/prepare.groovy @@ -21,6 +21,8 @@ // BUT we actually don't store that special versioning directory as-is to prevent potentially confusing // (to say the least) a svn checkout of the maven-scm project. // + +println "prepare.groovy:" File dotSvnDir = new File( basedir, 'dotSvnDir' ) assert dotSvnDir.exists() assert dotSvnDir.isDirectory() @@ -28,6 +30,7 @@ assert dotSvnDir.renameTo( new File( basedir, '.svn' ) ) println "svn --version" def proc = "svn --version".execute() +proc.consumeProcessOutput() proc.waitFor() println "return code: ${ proc.exitValue()}" println "stderr: ${proc.err.text}" @@ -35,6 +38,7 @@ println "stdout: ${proc.in.text}" println "svn upgrade $basedir" proc = ["svn", "upgrade", "$basedir"].execute() +proc.consumeProcessOutput() proc.waitFor() println "return code: ${ proc.exitValue()}" println "stderr: ${proc.err.text}" http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/AbstractScmMojo.java ---------------------------------------------------------------------- diff --git a/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/AbstractScmMojo.java b/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/AbstractScmMojo.java index c7533b8..a18e319 100644 --- a/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/AbstractScmMojo.java +++ b/maven-scm-plugin/src/main/java/org/apache/maven/scm/plugin/AbstractScmMojo.java @@ -170,6 +170,15 @@ public abstract class AbstractScmMojo @Parameter( property = "pushChanges", defaultValue = "true" ) private boolean pushChanges; + /** + * A workItem for SCMs like RTC, TFS etc, that may require additional + * information to perform a pushChange operation. + * + * @since 1.9.5 + */ + @Parameter( property = "workItem" ) + private String workItem; + /** {@inheritDoc} */ public void execute() throws MojoExecutionException @@ -285,6 +294,11 @@ public abstract class AbstractScmMojo providerRepo.setPushChanges( pushChanges ); + if ( !StringUtils.isEmpty( workItem ) ) + { + providerRepo.setWorkItem( workItem ); + } + if ( !StringUtils.isEmpty( username ) ) { providerRepo.setUser( username ); http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/JazzConstants.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/JazzConstants.java b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/JazzConstants.java index 2a85f38..9e0b2ec 100644 --- a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/JazzConstants.java +++ b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/JazzConstants.java @@ -107,6 +107,11 @@ public class JazzConstants */ public static final String CMD_STATUS = "status"; + /** + * Changeset command - Modifies change sets. + */ + public static final String CMD_CHANGESET = "changeset"; + // ------------------------------------------------------------------------------------------------- // SUB-COMMANDS // ------------------------------------------------------------------------------------------------- @@ -159,6 +164,13 @@ public class JazzConstants */ public static final String CMD_SUB_PROMOTE = "promote"; + // CHANGESET sub commands + + /** + * Associate a Work Item with a change set. + */ + public static final String CMD_SUB_ASSOCIATE = "associate"; + // ------------------------------------------------------------------------------------------------- // ARGUMENTS // ------------------------------------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommand.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommand.java b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommand.java index 7f6ab3c..8d35734 100644 --- a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommand.java +++ b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommand.java @@ -115,6 +115,24 @@ public class JazzCheckInCommand errConsumer.getOutput(), false ); } + // Check to see if we've had a workItem defined (via -DworkItem=XXXX) + JazzScmProviderRepository jazzRepo = (JazzScmProviderRepository) repository; + if ( jazzRepo.isPushChangesAndHaveFlowTargets() && StringUtils.isNotEmpty( jazzRepo.getWorkItem() ) ) + { + // Associate a work item if we need too. + JazzScmCommand changesetAssociateCmd = createChangesetAssociateCommand( repository ); + outputConsumer = new DebugLoggerConsumer( getLogger() ); + errConsumer = new ErrorConsumer( getLogger() ); + + status = changesetAssociateCmd.execute( outputConsumer, errConsumer ); + if ( status != 0 || errConsumer.hasBeenFed() ) + { + return new CheckInScmResult( changesetAssociateCmd.getCommandString(), + "Error code for Jazz SCM changeset associate command - " + status, + errConsumer.getOutput(), false ); + } + } + // Now check in the files themselves. return executeCheckInCommand( repository, fileSet, scmVersion ); } @@ -161,6 +179,19 @@ public class JazzCheckInCommand return command; } + public JazzScmCommand createChangesetAssociateCommand( ScmProviderRepository repo ) + { + JazzScmCommand command = + new JazzScmCommand( JazzConstants.CMD_CHANGESET, JazzConstants.CMD_SUB_ASSOCIATE, repo, false, null, + getLogger() ); + // Add the change set alias + JazzScmProviderRepository jazzRepo = (JazzScmProviderRepository) repo; + command.addArgument( "" + jazzRepo.getChangeSetAlias() ); + // Add the work item number + command.addArgument( jazzRepo.getWorkItem() ); + return command; + } + public JazzScmCommand createCheckInCommand( ScmProviderRepository repo, ScmFileSet fileSet ) { JazzScmCommand command = http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusConsumer.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusConsumer.java b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusConsumer.java index 498a32e..0ac426f 100644 --- a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusConsumer.java +++ b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusConsumer.java @@ -65,6 +65,37 @@ public class JazzStatusConsumer // remote calls to the server. They are not to be shared across machines (ie don't make them global, public // or persistent). // +// We can also have a changeset with a work item associated with it: +// +// Workspace: (1156) "GPDBWorkspace" <-> (1157) "GPDBStream" +// Component: (1158) "GPDB" +// Baseline: (2362) 48 "GPDB-1.0.50" +// Outgoing: +// Change sets: +// (2366) *--@ 62 "Release the next release of GPDB." - "Man Created Changeset: X.Y.Z" 28-Apr-2015 07:55 PM +// +// Or not: +// +// Workspace: (1156) "GPDBWorkspace" <-> (1157) "GPDBStream" +// Component: (1158) "GPDB" +// Baseline: (2362) 48 "GPDB-1.0.50" +// Outgoing: +// Change sets: +// (2365) ---@ "This is my changeset comment." 26-Apr-2015 09:36 PM +// +// We can also have a multiple changesets, although, if the correct build procedure has been followed, namely we +// start with a clean starting point, with nothing outstanding, then we should never see this (famous last words!) +// +// Workspace: (1156) "GPDBWorkspace" <-> (1157) "GPDBStream" +// Component: (1158) "GPDB" +// Baseline: (2362) 48 "GPDB-1.0.50" +// Outgoing: +// Change sets: +// (2366) *--@ 62 "Release the next release of GPDB." - "Man Created Changeset: X.Y.Z" 28-Apr-2015 07:55 PM +// (2365) ---@ "This is my changeset comment." 26-Apr-2015 09:36 PM +// +// Because the "Change sets:" line exists by itself, and it is followed by the changeset +// lines, we need to implement a state machine... (seenChangeSets) // Workspace: (1000) "BogusRepositoryWorkspace" <-> (1000) "BogusRepositoryWorkspace" // Workspace: (1156) "GPDBWorkspace" <-> (1157) "GPDBStream" @@ -81,8 +112,13 @@ public class JazzStatusConsumer // Baseline: (1128) 27 "BogusTestJazz-3.0.0.40" private static final Pattern BASELINE_PATTERN = Pattern.compile( "\\((\\d+)\\) (\\d+) \"(.*)\"" ); - // Additional data we collect. (eye catchers) + // (2365) ---@ "This is my changeset comment." 26-Apr-2015 09:36 PM + private static final Pattern CHANGESET_PATTERN = Pattern.compile( "\\((\\d+)\\) (.*)" ); + // + // Additional data we collect. (eye catchers) + // + /** * The "Status" command output line that contains the "Workspace" name. */ @@ -94,10 +130,16 @@ public class JazzStatusConsumer public static final String STATUS_CMD_COMPONENT = "Component:"; /** - * The "Status" command output line that contains the "Workspace" name. + * The "Status" command output line that contains the "Baseline" name. */ public static final String STATUS_CMD_BASELINE = "Baseline:"; + /** + * The "Status" command output line that contains the line "Change sets:". + * This will be followed by the + */ + public static final String STATUS_CMD_CHANGE_SETS = "Change sets:"; + // File Status Commands (eye catchers) /** @@ -127,6 +169,11 @@ public class JazzStatusConsumer private List<ScmFile> fChangedFiles = new ArrayList<ScmFile>(); /** + * Implement a simple state machine: Have we seen the "Change sets:" line or not? + */ + private boolean seenChangeSets = false; + + /** * Constructor for our "scm status" consumer. * * @param repo The JazzScmProviderRepository being used. @@ -162,6 +209,14 @@ public class JazzStatusConsumer { extractChangedFile( line ); } + if ( containsChangeSets( line ) ) + { + seenChangeSets = true; + } + if ( seenChangeSets ) + { + extractChangeSetAlias( line ); + } } private boolean containsWorkspace( String line ) @@ -267,9 +322,9 @@ public class JazzStatusConsumer if ( getLogger().isDebugEnabled() ) { getLogger().debug( "Successfully parsed \"Baseline:\" line:" ); - getLogger().debug( " baselineAlias = " + baselineAlias ); - getLogger().debug( " baselineId = " + baselineId ); - getLogger().debug( " baseline = " + baseline ); + getLogger().debug( " baselineAlias = " + baselineAlias ); + getLogger().debug( " baselineId = " + baselineId ); + getLogger().debug( " baseline = " + baseline ); } jazzRepository.setBaseline( baseline ); } @@ -314,10 +369,9 @@ public class JazzStatusConsumer if ( getLogger().isDebugEnabled() ) { - getLogger().debug( " Line : '" + line + "'" ); - getLogger().debug( " Extracted filePath : '" + filePath + "'" ); - getLogger().debug( " Extracted flag : '" + flag + "'" ); - getLogger().debug( " Extracted status : '" + status + "'" ); + getLogger().debug( " Extracted filePath : '" + filePath + "'" ); + getLogger().debug( " Extracted flag : '" + flag + "'" ); + getLogger().debug( " Extracted status : '" + status + "'" ); } fChangedFiles.add( new ScmFile( filePath, status ) ); @@ -327,4 +381,43 @@ public class JazzStatusConsumer { return fChangedFiles; } + + private boolean containsChangeSets( String line ) + { + return line.trim().startsWith( STATUS_CMD_CHANGE_SETS ); + } + + private void extractChangeSetAlias( String line ) + { + // (2365) ---@ "This is my changeset comment." 26-Apr-2015 09:36 PM + + Matcher matcher = CHANGESET_PATTERN.matcher( line ); + if ( matcher.find() ) + { + JazzScmProviderRepository jazzRepository = (JazzScmProviderRepository) getRepository(); + + int changeSetAlias = Integer.parseInt( matcher.group( 1 ) ); + if ( getLogger().isDebugEnabled() ) + { + getLogger().debug( "Successfully parsed post \"Change sets:\" line:" ); + getLogger().debug( " changeSetAlias = " + changeSetAlias ); + } + jazzRepository.setChangeSetAlias( changeSetAlias ); + // This is a difficult one. Do I now turn it off or not? + seenChangeSets = false; + // For the moment I am going too. + // If we ever need to support multiple outgoing changesets, + // and I can not see how that makes sense in a maven sense, + // then we can revisit using a list. + // Also, turning if off means that we only look at the first + // (and hopefully only!) one. + // It also means that if we run across some Incoming: changes, + // then we will not pick them up accidently either. + // + // Another way around this would to be to have a specific + // consumer for the create changeset command itself. + // That way we would be totally assured that we've picked + // up the right Changet Set Alias. + } + } } http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/repository/JazzScmProviderRepository.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/repository/JazzScmProviderRepository.java b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/repository/JazzScmProviderRepository.java index 913c704..20d8208 100644 --- a/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/repository/JazzScmProviderRepository.java +++ b/maven-scm-providers/maven-scm-provider-jazz/src/main/java/org/apache/maven/scm/provider/jazz/repository/JazzScmProviderRepository.java @@ -83,6 +83,11 @@ public class JazzScmProviderRepository */ private String fBaseline; + /** + * The alias of the change set, as returned from the "scm status" command. + */ + private int fChangeSetAlias; + // TODO In the future we might expand the details of this repository. // For example we might extend the scm url to include a stream (as well as the repository workspace) // This stream could represent the desired flow target of the repository workspace. @@ -188,7 +193,7 @@ public class JazzScmProviderRepository } /** - * @param streamAlias the streamAlias to set + * @param flowTargetAlias the flowTargetAlias to set */ public void setFlowTargetAlias( int flowTargetAlias ) { @@ -244,6 +249,22 @@ public class JazzScmProviderRepository } /** + * @return The alias of the changeset, as returned from the "scm status" command. + */ + public int getChangeSetAlias() + { + return fChangeSetAlias; + } + + /** + * @param fChangeSetAlias the fChangeSetAlias to set + */ + public void setChangeSetAlias( int fChangeSetAlias ) + { + this.fChangeSetAlias = fChangeSetAlias; + } + + /** * {@inheritDoc} */ public String toString() http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommandTest.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommandTest.java b/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommandTest.java index b3d53df..55349fd 100644 --- a/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommandTest.java +++ b/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/checkin/JazzCheckInCommandTest.java @@ -55,6 +55,18 @@ public class JazzCheckInCommandTest assertCommandLine( expected, getWorkingDirectory(), cmd ); } + public void testCreateChangesetAssociateCommand() + throws Exception + { + JazzScmProviderRepository repo = getScmProviderRepository(); + // Populate the values that are normally parsed and set by the StatusConsumer. + repo.setWorkItem( "215762" ); + repo.setChangeSetAlias( 1234 ); + Commandline cmd = new JazzCheckInCommand().createChangesetAssociateCommand( repo ).getCommandline(); + String expected = "scm changeset associate --username myUserName --password myPassword 1234 215762"; + assertCommandLine( expected, getWorkingDirectory(), cmd ); + } + public void testCreateCheckInCommandCheckingInSpecificFiles() throws Exception { http://git-wip-us.apache.org/repos/asf/maven-scm/blob/8dd21b9c/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusCommandTest.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusCommandTest.java b/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusCommandTest.java index 37a8e56..acb862e 100644 --- a/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusCommandTest.java +++ b/maven-scm-providers/maven-scm-provider-jazz/src/test/java/org/apache/maven/scm/provider/jazz/command/status/JazzStatusCommandTest.java @@ -83,6 +83,7 @@ public class JazzStatusCommandTest assertEquals( "Flow Target Alias is incorrect!", 1001, repo.getFlowTargetAlias() ); assertEquals( "Component is incorrect!", "SCM Plugins", repo.getComponent() ); assertEquals( "Baseline is incorrect!", "Initial Baseline", repo.getBaseline() ); + assertEquals( "Change Set Alias is incorrect!", 1008, repo.getChangeSetAlias()); // Test the stream parsing and isPushChanges bits. assertTrue( "isPushChangesAndHaveFlowTargets is incorrect!", repo.isPushChangesAndHaveFlowTargets() );