[JENKINS-11549] Add MERCURIAL_CHANGESET_NUMBER to exported environment variables #23

Merged
merged 12 commits into from May 1, 2012
@@ -169,19 +169,33 @@ public ProcStarter run(ArgumentListBuilder args) {
}
/**
- * Gets the revision ID of the tip of the workspace.
+ * Gets the revision ID or node of the tip of the workspace.
+ * A 40-character hexadecimal string
* @param rev the revision to identify; defaults to {@code .}, i.e. working copy
*/
public @CheckForNull String tip(FilePath repository, @Nullable String rev) throws IOException, InterruptedException {
String id = popen(repository, listener, false, new ArgumentListBuilder("log", "--rev", rev != null ? rev : ".", "--template", "{node}"));
- if (!REVISIONID_PATTERN.matcher(id).matches()) {
+ if (!NODEID_PATTERN.matcher(id).matches()) {
listener.error("Expected to get an id but got '" + id + "' instead.");
return null; // HUDSON-7723
}
return id;
}
/**
+ * Gets the revision number of the tip of the workspace.
+ * @param rev the revision to identify; defaults to {@code .}, i.e. working copy
+ */
+ public @CheckForNull String tipNumber(FilePath repository, @Nullable String rev) throws IOException, InterruptedException {
+ String id = popen(repository, listener, false, new ArgumentListBuilder("log", "--rev", rev != null ? rev : ".", "--template", "{rev}"));
+ if (!REVISION_NUMBER_PATTERN.matcher(id).matches()) {
+ listener.error("Expected to get a revision number but got '" + id + "' instead.");
+ return null;
+ }
+ return id;
+ }
+
+ /**
* Gets the current value of a specified config item.
*/
public String config(FilePath repository, String name) throws IOException, InterruptedException {
@@ -238,7 +252,8 @@ synchronized static Capability get(HgExe hg) {
/**
* Pattern that matches revision ID.
*/
- private static final Pattern REVISIONID_PATTERN = Pattern.compile("[0-9a-f]{40}");
+ private static final Pattern NODEID_PATTERN = Pattern.compile("[0-9a-f]{40}");
+ private static final Pattern REVISION_NUMBER_PATTERN = Pattern.compile("[0-9]+");
/**
* Checks whether a normalized path URL matches what a config file requested.
@@ -261,5 +276,4 @@ static boolean pathEquals(@NonNull String pathURL, @NonNull String pathAsInConfi
}
return false;
}
-
@jglick
jglick May 1, 2012 Member

Gratuitous.

}
@@ -219,7 +219,8 @@ public SCMRevisionState calcRevisionsFromBuild(AbstractBuild<?, ?> build, Launch
// tag action is added during checkout, so this shouldn't be called, but just in case.
HgExe hg = new HgExe(this, launcher, build, listener, build.getEnvironment(listener));
String tip = hg.tip(workspace2Repo(build.getWorkspace()), null);
- return tip != null ? new MercurialTagAction(tip, subdir) : null;
+ String rev = hg.tipNumber(workspace2Repo(build.getWorkspace()), null);
+ return tip != null && rev != null ? new MercurialTagAction(tip, rev, subdir) : null;
}
@Override
@@ -266,15 +267,19 @@ protected PollingResult compareRemoteRevisionWith(AbstractProject<?, ?> project,
private PollingResult compare(Launcher launcher, TaskListener listener, MercurialTagAction baseline, PrintStream output, Node node, FilePath repository) throws IOException, InterruptedException {
HgExe hg = new HgExe(this, launcher, node, listener, /*XXX*/new EnvVars());
String remote = hg.tip(repository, getBranch());
+ String rev = hg.tipNumber(repository, getBranch());
if (remote == null) {
throw new IOException("failed to find ID of branch head");
}
+ if (rev == null) {
+ throw new IOException("failed to find revision of branch head");
+ }
if (remote.equals(baseline.id)) { // shortcut
- return new PollingResult(baseline, new MercurialTagAction(remote, subdir), Change.NONE);
+ return new PollingResult(baseline, new MercurialTagAction(remote, rev, subdir), Change.NONE);
}
Set<String> changedFileNames = parseStatus(hg.popen(repository, listener, false, new ArgumentListBuilder("status", "--rev", baseline.id, "--rev", remote)));
- MercurialTagAction cur = new MercurialTagAction(remote, subdir);
+ MercurialTagAction cur = new MercurialTagAction(remote, rev, subdir);
return new PollingResult(baseline,cur,computeDegreeOfChanges(changedFileNames,output));
}
@@ -526,8 +531,9 @@ private void update(AbstractBuild<?, ?> build, Launcher launcher, FilePath repos
}
String tip = hg.tip(repository, null);
- if (tip != null) {
- build.addAction(new MercurialTagAction(tip, subdir));
+ String rev = hg.tipNumber(repository, null);
+ if (tip != null && rev != null) {
+ build.addAction(new MercurialTagAction(tip, rev, subdir));
}
}
@@ -605,8 +611,9 @@ private void clone(AbstractBuild<?,?> build, Launcher launcher, FilePath reposit
hg.run(upArgs).pwd(repository).join();
String tip = hg.tip(repository, null);
- if (tip != null) {
- build.addAction(new MercurialTagAction(tip, subdir));
+ String rev = hg.tipNumber(repository, null);
+ if (tip != null && rev != null) {
+ build.addAction(new MercurialTagAction(tip, rev, subdir));
}
}
@@ -615,6 +622,7 @@ public void buildEnvVars(AbstractBuild<?,?> build, Map<String, String> env) {
MercurialTagAction a = findTag(build);
if (a != null) {
env.put("MERCURIAL_REVISION", a.id);
+ env.put("MERCURIAL_REVISION_NUMBER", a.rev);
}
}
@@ -24,12 +24,18 @@
public final String id;
/**
+ * Integer revision number. The repository-local changeset number.
+ */
+ public final String rev;
@jglick
jglick Apr 30, 2012 Member

Did you check for deserialization compatibility, i.e. run the old plugin, then update and browse this action using the new plugin? I think it will be OK (just set to null by XStream) but ought to check it.

+
+ /**
* Matches {@link MercurialSCM#subdir}.
*/
public final String subdir;
- public MercurialTagAction(@NonNull String id, @Nullable String subdir) {
+ public MercurialTagAction(@NonNull String id, @NonNull String rev, @Nullable String subdir) {
@jglick
jglick Apr 30, 2012 Member

You do not consistently check rev for null when creating tags; either do so, or make it nullable.

@geofflane
geofflane Apr 30, 2012 Contributor

Will check all constructor calls for null like is being done for id parameter.

this.id = id;
+ this.rev = rev;
this.subdir = subdir;
}
@@ -38,6 +44,11 @@ public String getId() {
return id;
}
+ @Exported(name = "mercurialRevisionNumber")
+ public String getRev() {
@jglick
jglick Apr 30, 2012 Member

Do you want to include this in hudson/plugins/mercurial/MercurialTagAction/index.jelly? Not necessary, of course, but might be desirable.

@geofflane
geofflane Apr 30, 2012 Contributor

Sure, I'll add it as ${it.rev}:${it.id} which mimics the default changeset format of hg log.

+ return rev;
+ }
+
@Exported
public String getSubdir() {
return subdir;
@@ -6,7 +6,7 @@
<h1>Mercurial Build Data</h1>
<b>Revision:</b>
- ${it.id}
+ ${it.rev}:${it.id}
</l:main-panel>
</l:layout>
</j:jelly>