From d6daefcc704d4b599c5e91386a57200cd83f3cd2 Mon Sep 17 00:00:00 2001 From: Henning Schmiedehausen Date: Sun, 22 Feb 2015 19:10:21 -0800 Subject: [PATCH 1/6] Add integration test to compare native and jgit output. Also fixes a bug in the sandbox preparation with empty directories. --- .../maven/git/FileSystemMavenSandbox.java | 11 +- .../maven/git/NativeAndJGitProviderTest.java | 152 ++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java diff --git a/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java b/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java index 580d9981..0ffaba82 100644 --- a/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java +++ b/src/test/java/pl/project13/maven/git/FileSystemMavenSandbox.java @@ -25,6 +25,8 @@ import java.io.File; import java.io.IOException; +import com.google.common.io.Files; + /** * Quick and dirty maven projects tree structure to create on disk during integration tests * Can have both parent and child projects set up @@ -118,7 +120,14 @@ public FileSystemMavenSandbox create(CleanUp cleanupMode) throws RuntimeExceptio private void createGitRepoIfRequired() throws IOException { if (gitRepoTargetDir != null) { - FileUtils.copyDirectory(gitRepoSourceDir, new File(gitRepoTargetDir, ".git")); + File gitFolder = new File(gitRepoTargetDir, ".git"); + FileUtils.copyDirectory(gitRepoSourceDir, gitFolder); + // As the WITH_NO_CHANGES and WITH_CHANGES git trees contain empty + // folders whose existence is crucial for the native git to run (jgit does not mind) + // *and* because empty folders are silently omitted from git checkins, ensure that + // these folders exist + Files.createParentDirs(new File(gitFolder, "refs/heads")); + Files.createParentDirs(new File(gitFolder, "refs/tags")); } } diff --git a/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java new file mode 100644 index 00000000..6cf2c234 --- /dev/null +++ b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java @@ -0,0 +1,152 @@ +/* + * This file is part of git-commit-id-plugin by Konrad Malawski + * + * git-commit-id-plugin is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * git-commit-id-plugin is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with git-commit-id-plugin. If not, see . + */ + +package pl.project13.maven.git; + +import static org.fest.assertions.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.mockito.internal.util.reflection.Whitebox.setInternalState; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Properties; + +import org.apache.maven.project.MavenProject; +import org.junit.Assert; +import org.junit.Test; + +import pl.project13.maven.git.FileSystemMavenSandbox.CleanUp; + +public class NativeAndJGitProviderTest extends GitIntegrationTest +{ + public static final String[] GIT_KEYS = new String[] { + "git.build.time", + "git.branch", + "git.commit.id", + "git.commit.id.abbrev", + "git.commit.id.describe", + "git.build.user.name", + "git.build.user.email", + "git.commit.user.name", + "git.commit.user.email", + "git.commit.message.full", + "git.commit.message.short", + "git.commit.time", + "git.remote.origin.url" + }; + + // Can't be static, not thread safe. + public final DateFormat DEFAULT_FORMAT = new SimpleDateFormat("dd.MM.yyyy '@' HH:mm:ss z"); + + @Test + public void testCompareBasic() throws Exception + { + // Test on all available basic repos to ensure that the output is identical. + for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { + mavenSandbox.withParentProject("my-basic-project", "jar").withNoChildProject().withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); + MavenProject targetProject = mavenSandbox.getParentProject(); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); + } + } + + @Test + public void testCompareSubrepoInRoot() throws Exception + { + for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { + if (testRepo == AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) { + continue; // Don't create a subrepo based off the plugin repo itself. + } + mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); + MavenProject targetProject = mavenSandbox.getParentProject(); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); + } + } + + @Test + public void testCompareSubrepoInChild() throws Exception + { + for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { + if (testRepo == AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) { + continue; // Don't create a subrepo based off the plugin repo itself. + } + mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); + MavenProject targetProject = mavenSandbox.getChildProject(); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); + } + } + + + private void verifyNativeAndJGit(MavenProject targetProject, DateFormat format) throws Exception + { + setProjectToExecuteMojoIn(targetProject); + + alterMojoSettings("useNativeGit", false); + alterMojoSettings("skipPoms", false); + mojo.execute(); + Properties jgitProps = createCopy(targetProject.getProperties()); + + alterMojoSettings("useNativeGit", true); + mojo.execute(); + Properties nativeProps = createCopy(targetProject.getProperties()); + + assertGitPropertiesPresentInProject(jgitProps); + assertGitPropertiesPresentInProject(nativeProps); + + for (String key : GIT_KEYS) { + if (!key.equals("git.build.time")) { // git.build.time is excused because the two runs happened at different times. + assertEquals("Key difference for key: '" + key + "'", jgitProps.getProperty(key), nativeProps.getProperty(key)); + } + else { + // Ensure that the date formats are parseable and within reason. If running all the git commands on the + // native provider takes more than 60 seconds, then something is seriously wrong. + long jGitBuildTimeInMs = format.parse(jgitProps.getProperty(key)).getTime(); + long nativeBuildTimeInMs = format.parse(nativeProps.getProperty(key)).getTime(); + Assert.assertTrue("Time ran backwards, jgitTime after nativeTime!", jGitBuildTimeInMs <= nativeBuildTimeInMs); + Assert.assertTrue("Build ran too slow.", (nativeBuildTimeInMs - jGitBuildTimeInMs) < 60000L); // If native takes more than 1 minute, something is wrong. + } + } + + // Check the commit time to be equal in ms, too. + long jGitCommitTimeInMs = format.parse(jgitProps.getProperty("git.commit.time")).getTime(); + long nativeCommitTimeInMs = format.parse(nativeProps.getProperty("git.commit.time")).getTime(); + + assertEquals("commit times parse to different time stamps", jGitCommitTimeInMs, nativeCommitTimeInMs); + } + + private void alterMojoSettings(String parameterName, Object parameterValue) + { + setInternalState(mojo, parameterName, parameterValue); + } + + private Properties createCopy(Properties orig) + { + Properties p = new Properties(); + for (Object o : orig.keySet()) { + String key = o.toString(); + p.setProperty(key, orig.getProperty(key)); + } + + return p; + } + + private void assertGitPropertiesPresentInProject(Properties properties) + { + for (String key : GIT_KEYS) { + assertThat(properties).satisfies(new ContainsKeyCondition(key)); + } + } +} From c9b35d4442b3ce9282b1e23fa902a08ba6d77489 Mon Sep 17 00:00:00 2001 From: Henning Schmiedehausen Date: Sun, 8 Feb 2015 19:45:23 -0800 Subject: [PATCH 2/6] Fix differences in the output of native and jgit On my box (using git 1.9.3), for a small project, there are the following differences between jgit and native output: field | jgit | native git.build.user.name | Henning Schmiedehausen | "Henning Schmiedehausen" git.build.user.email | henning@schmiedehausen.org | "henning@schmiedehausen.org" git.dirty | true | false git.commit.user.name | Henning Schmiedehausen | "Henning Schmiedehausen" git.commit.user.email | henning@schmiedehausen.org | "henning@schmiedehausen.org" git.commit.message.full | Create README.md | "Create README.md" git.commit.message.short| Create README.md | "Create README.md" git.commit.time | 2014-11-21T18:47:34-0800 | "2014-11-21 18:47:34 -0800" git.tags | bar,foo | foo,bar,origin/master,origin/ This uses the following custom settings: yyyy-MM-dd'T'HH:mm:ssZZ 10 true 7 -dirty false Especially the "git.dirty" and "git.tags" is catastrophic but all the other fields also make it hard to parse *any* information across different settings of the git provider. This patch fixes all the differences. Now the output of jgit and native are identical. Not a single unit test broke with these output changes. This is worrisome because it implies that test coverage at least for the native provider is not good. --- .../pl/project13/maven/git/JGitProvider.java | 4 +- .../maven/git/NativeGitProvider.java | 65 ++++++------------- 2 files changed, 23 insertions(+), 46 deletions(-) diff --git a/src/main/java/pl/project13/maven/git/JGitProvider.java b/src/main/java/pl/project13/maven/git/JGitProvider.java index 891b0d6b..6db53af9 100644 --- a/src/main/java/pl/project13/maven/git/JGitProvider.java +++ b/src/main/java/pl/project13/maven/git/JGitProvider.java @@ -142,13 +142,13 @@ protected String getCommitAuthorEmail() { @Override protected String getCommitMessageFull() { String fullMessage = headCommit.getFullMessage(); - return fullMessage; + return fullMessage.trim(); } @Override protected String getCommitMessageShort() { String shortMessage = headCommit.getShortMessage(); - return shortMessage; + return shortMessage.trim(); } @Override diff --git a/src/main/java/pl/project13/maven/git/NativeGitProvider.java b/src/main/java/pl/project13/maven/git/NativeGitProvider.java index 87413e8b..17a9f017 100644 --- a/src/main/java/pl/project13/maven/git/NativeGitProvider.java +++ b/src/main/java/pl/project13/maven/git/NativeGitProvider.java @@ -1,18 +1,15 @@ package pl.project13.maven.git; -import com.google.common.base.Function; -import com.google.common.base.Joiner; -import com.google.common.base.Predicate; import com.google.common.base.Splitter; -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; + import org.apache.maven.plugin.MojoExecutionException; import org.jetbrains.annotations.NotNull; + import pl.project13.maven.git.log.LoggerBridge; import java.io.*; -import java.util.Arrays; +import java.text.SimpleDateFormat; public class NativeGitProvider extends GitDataProvider { @@ -55,12 +52,12 @@ protected void init() throws MojoExecutionException { @Override protected String getBuildAuthorName() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%an\""); + return tryToRunGitCommand(canonical, "config user.name"); } @Override protected String getBuildAuthorEmail() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%ae\""); + return tryToRunGitCommand(canonical, "config user.email"); } @Override @@ -150,58 +147,35 @@ protected boolean isDirty() throws MojoExecutionException { @Override protected String getCommitAuthorName() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%cn\""); + return tryToRunGitCommand(canonical, "log -1 --pretty=format:%an"); } @Override protected String getCommitAuthorEmail() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%ce\""); + return tryToRunGitCommand(canonical, "log -1 --pretty=format:%ae"); } @Override protected String getCommitMessageFull() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%B\""); + return tryToRunGitCommand(canonical, "log -1 --pretty=format:%B"); } @Override protected String getCommitMessageShort() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%s\""); + return tryToRunGitCommand(canonical, "log -1 --pretty=format:%s"); } @Override protected String getCommitTime() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%ci\""); + String value = tryToRunGitCommand(canonical, "log -1 --pretty=format:%ct"); + SimpleDateFormat smf = new SimpleDateFormat(dateFormat); + return smf.format(Long.parseLong(value)*1000L); } @Override protected String getTags() throws MojoExecutionException { - final String branch = tryToRunGitCommand(canonical, "rev-parse --abbrev-ref HEAD"); - - String out = tryToRunGitCommand(canonical, "log -n 1 --pretty=format:'%d'"); - String[] nms = out - .replaceAll("HEAD", "") - .replaceAll("\\)", "") - .replaceAll("\\(", "") - .replaceAll("'", "") - .replaceAll("tag: ", "") - .replaceAll(",", "") - .trim() - .split(" "); - - - ImmutableList cleanTags = FluentIterable.from(Arrays.asList(nms)). - transform(new Function() { - @Override public String apply(String input) { - return input.trim(); - } - }). - filter(new Predicate() { - @Override public boolean apply(String input) { - return !input.equals(branch); - } - }).toList(); - - return Joiner.on(",").join(cleanTags); + final String result = tryToRunGitCommand(canonical, "tag --contains"); + return result.replace('\n', ','); } @Override @@ -249,16 +223,19 @@ private String tryToRunGitCommand(File directory, String gitCommand) { /** * Runs a maven command and returns {@code true} if output was non empty. * Can be used to short cut reading output from command when we know it may be a rather long one. - * */ + * + * Return true if the result is empty. + * + **/ private boolean tryCheckEmptyRunGitCommand(File directory, String gitCommand) { try { String env = System.getenv("GIT_PATH"); String exec = (env == null) ? "git" : env; String command = String.format("%s %s", exec, gitCommand); - boolean empty = getRunner().runEmpty(directory, command); - return !empty; + return getRunner().runEmpty(directory, command); } catch (IOException ex) { + // Error means "non-empty" return false; // do nothing... } @@ -311,7 +288,7 @@ public String run(File directory, String command) throws IOException { final StringBuilder commandResult = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { - commandResult.append(line); + commandResult.append(line).append("\n"); } if (proc.exitValue() != 0) { From 68c4a4454c14c00fa5d99821fbb35c521fe523d5 Mon Sep 17 00:00:00 2001 From: Henning Schmiedehausen Date: Sun, 22 Feb 2015 20:35:27 -0800 Subject: [PATCH 3/6] Fix missing .gitconfig file If no .gitconfig file is present, getBuildAuthorName and getBuildAutorEmail either fail (native provider) or return null (jgit provider). In any case, all sorts of bad things happen, especially all unit tests break. This is why the travis ci build fails. Now it should no longer do that. :-) --- .../pl/project13/maven/git/JGitProvider.java | 7 +- .../maven/git/NativeGitProvider.java | 141 +++++++++++------- 2 files changed, 95 insertions(+), 53 deletions(-) diff --git a/src/main/java/pl/project13/maven/git/JGitProvider.java b/src/main/java/pl/project13/maven/git/JGitProvider.java index 6db53af9..838068bf 100644 --- a/src/main/java/pl/project13/maven/git/JGitProvider.java +++ b/src/main/java/pl/project13/maven/git/JGitProvider.java @@ -3,8 +3,10 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Joiner; +import com.google.common.base.Objects; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; + import org.apache.maven.plugin.MojoExecutionException; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; @@ -18,6 +20,7 @@ import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.jetbrains.annotations.NotNull; + import pl.project13.jgit.DescribeCommand; import pl.project13.jgit.DescribeResult; import pl.project13.maven.git.log.LoggerBridge; @@ -66,13 +69,13 @@ protected void init() throws MojoExecutionException { @Override protected String getBuildAuthorName() { String userName = git.getConfig().getString("user", null, "name"); - return userName; + return Objects.firstNonNull(userName, ""); } @Override protected String getBuildAuthorEmail() { String userEmail = git.getConfig().getString("user", null, "email"); - return userEmail; + return Objects.firstNonNull(userEmail, ""); } @Override diff --git a/src/main/java/pl/project13/maven/git/NativeGitProvider.java b/src/main/java/pl/project13/maven/git/NativeGitProvider.java index 17a9f017..205be385 100644 --- a/src/main/java/pl/project13/maven/git/NativeGitProvider.java +++ b/src/main/java/pl/project13/maven/git/NativeGitProvider.java @@ -1,6 +1,7 @@ package pl.project13.maven.git; import com.google.common.base.Splitter; +import com.google.common.base.Throwables; import com.google.common.collect.Lists; import org.apache.maven.plugin.MojoExecutionException; @@ -52,12 +53,26 @@ protected void init() throws MojoExecutionException { @Override protected String getBuildAuthorName() { - return tryToRunGitCommand(canonical, "config user.name"); + try { + return runGitCommand(canonical, "config --get user.name"); + } catch (NativeCommandException e) { + if (e.getExitCode() == 1) { // No config file found + return ""; + } + throw Throwables.propagate(e); + } } @Override protected String getBuildAuthorEmail() { - return tryToRunGitCommand(canonical, "config user.email"); + try { + return runGitCommand(canonical, "config --get user.email"); + } catch (NativeCommandException e) { + if (e.getExitCode() == 1) { // No config file found + return ""; + } + throw Throwables.propagate(e); + } } @Override @@ -72,21 +87,24 @@ protected String getBranchName() throws IOException { private String getBranch(File canonical) { String branch = null; try{ - branch = tryToRunGitCommand(canonical, "symbolic-ref HEAD"); + branch = runGitCommand(canonical, "symbolic-ref HEAD"); if (branch != null) { branch = branch.replace("refs/heads/", ""); } - }catch(RuntimeException e){ - // it seems that git repro is in 'DETACHED HEAD'-State, using Commid-Id as Branch - branch = getCommitId(); + } catch(NativeCommandException e) { + // it seems that git repro is in 'DETACHED HEAD'-State, using Commid-Id as Branch + if (e.getExitCode() == 1) { + branch = getCommitId(); + } + throw Throwables.propagate(e); } return branch; } @Override - protected String getGitDescribe() throws MojoExecutionException { + protected String getGitDescribe() { final String argumentsForGitDescribe = getArgumentsForGitDescribe(gitDescribe); - final String gitDescribe = tryToRunGitCommand(canonical, "describe" + argumentsForGitDescribe); + final String gitDescribe = runQuietGitCommand(canonical, "describe" + argumentsForGitDescribe); return gitDescribe; } @@ -123,11 +141,11 @@ private String getArgumentsForGitDescribe(GitDescribeConfig describeConfig) { @Override protected String getCommitId() { - return tryToRunGitCommand(canonical, "rev-parse HEAD"); + return runQuietGitCommand(canonical, "rev-parse HEAD"); } @Override - protected String getAbbrevCommitId() throws MojoExecutionException { + protected String getAbbrevCommitId() { // we could run: tryToRunGitCommand(canonical, "rev-parse --short="+abbrevLength+" HEAD"); // but minimum length for --short is 4, our abbrevLength could be 2 String commitId = getCommitId(); @@ -147,34 +165,34 @@ protected boolean isDirty() throws MojoExecutionException { @Override protected String getCommitAuthorName() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:%an"); + return runQuietGitCommand(canonical, "log -1 --pretty=format:%an"); } @Override protected String getCommitAuthorEmail() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:%ae"); + return runQuietGitCommand(canonical, "log -1 --pretty=format:%ae"); } @Override protected String getCommitMessageFull() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:%B"); + return runQuietGitCommand(canonical, "log -1 --pretty=format:%B"); } @Override protected String getCommitMessageShort() { - return tryToRunGitCommand(canonical, "log -1 --pretty=format:%s"); + return runQuietGitCommand(canonical, "log -1 --pretty=format:%s"); } @Override protected String getCommitTime() { - String value = tryToRunGitCommand(canonical, "log -1 --pretty=format:%ct"); + String value = runQuietGitCommand(canonical, "log -1 --pretty=format:%ct"); SimpleDateFormat smf = new SimpleDateFormat(dateFormat); return smf.format(Long.parseLong(value)*1000L); } @Override - protected String getTags() throws MojoExecutionException { - final String result = tryToRunGitCommand(canonical, "tag --contains"); + protected String getTags() { + final String result = runQuietGitCommand(canonical, "tag --contains"); return result.replace('\n', ','); } @@ -189,37 +207,23 @@ protected void finalCleanUp() { private String getOriginRemote(File directory) throws MojoExecutionException { String remoteUrl = null; - try { - String remotes = runGitCommand(directory, "remote -v"); + String remotes = runQuietGitCommand(directory, "remote -v"); - // welcome to text output parsing hell! - no `\n` is not enough - for (String line : Splitter.onPattern("\\((fetch|push)\\)?").split(remotes)) { + // welcome to text output parsing hell! - no `\n` is not enough + for (String line : Splitter.onPattern("\\((fetch|push)\\)?").split(remotes)) { String trimmed = line.trim(); if (trimmed.startsWith("origin")) { - String[] splited = trimmed.split("\\s+"); - if (splited.length != REMOTE_COLS - 1) { // because (fetch/push) was trimmed - throw new MojoExecutionException("Unsupported GIT output (verbose remote address): " + line); - } - remoteUrl = splited[1]; + String[] splited = trimmed.split("\\s+"); + if (splited.length != REMOTE_COLS - 1) { // because (fetch/push) was trimmed + throw new MojoExecutionException("Unsupported GIT output (verbose remote address): " + line); + } + remoteUrl = splited[1]; } - } - } catch (Exception e) { - throw new MojoExecutionException("Error while obtaining origin remote", e); } return remoteUrl; } - private String tryToRunGitCommand(File directory, String gitCommand) { - String retValue = ""; - try { - retValue = runGitCommand(directory, gitCommand); - } catch (MojoExecutionException ex) { - // do nothing - } - return retValue; - } - /** * Runs a maven command and returns {@code true} if output was non empty. * Can be used to short cut reading output from command when we know it may be a rather long one. @@ -241,24 +245,33 @@ private boolean tryCheckEmptyRunGitCommand(File directory, String gitCommand) { } } - private String runGitCommand(File directory, String gitCommand) throws MojoExecutionException { - try { + private String runQuietGitCommand(File directory, String gitCommand) { final String env = System.getenv("GIT_PATH"); final String exec = (env == null) ? "git" : env; final String command = String.format("%s %s", exec, gitCommand); - final String result = getRunner().run(directory, command.trim()).trim(); - return result; - } catch (IOException ex) { - if (ex.getMessage().contains("exited with invalid status")) { - throw new RuntimeException("Failed to execute git command (`git " + gitCommand + "` @ " + directory +")!", ex); - } else { - throw new MojoExecutionException("Could not run GIT command - GIT is not installed or not exists in system path? " + - "Tried to run: 'git " + gitCommand + "'", ex); + try { + return getRunner().run(directory, command.trim()).trim(); + } catch (IOException e) { + throw Throwables.propagate(e); } - } } + private String runGitCommand(File directory, String gitCommand) throws NativeCommandException { + final String env = System.getenv("GIT_PATH"); + final String exec = (env == null) ? "git" : env; + final String command = String.format("%s %s", exec, gitCommand); + + try { + return getRunner().run(directory, command.trim()).trim(); + } catch (NativeCommandException e) { + throw e; + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + + private ProcessRunner getRunner() { if (runner == null) { runner = new JavaProcessRunner(); @@ -273,6 +286,32 @@ public interface ProcessRunner { boolean runEmpty(File directory, String command) throws IOException; } + public static class NativeCommandException extends IOException + { + private final int exitCode; + private final String command; + private final File directory; + + public NativeCommandException(int exitCode, String command, File directory, String message) { + super(message); + this.exitCode = exitCode; + this.command = command; + this.directory = directory; + } + + public int getExitCode() { + return exitCode; + } + + public String getCommand() { + return command; + } + + public File getDirectory() { + return directory; + } + } + protected static class JavaProcessRunner implements ProcessRunner { @Override public String run(File directory, String command) throws IOException { @@ -295,7 +334,7 @@ public String run(File directory, String command) throws IOException { final StringBuilder errMsg = readStderr(err); final String message = String.format("Git command exited with invalid status [%d]: stdout: `%s`, stderr: `%s`", proc.exitValue(), output, errMsg.toString()); - throw new IOException(message); + throw new NativeCommandException(proc.exitValue(), command, directory, message); } output = commandResult.toString(); } catch (InterruptedException ex) { From 4fd8a5f27f9e8d7cf728f885df45007323443509 Mon Sep 17 00:00:00 2001 From: Henning Schmiedehausen Date: Sun, 22 Feb 2015 21:06:07 -0800 Subject: [PATCH 4/6] Make unit test pass in detached state. travis-ci runs unit tests in detached state. - fix bad test that built a child repo from the plugin - use latest tags, travis-ci only does a shallow clone - fix response code checking for symbolic-ref, it actually returns 128. --- .../maven/git/NativeGitProvider.java | 38 +++++++++++++++---- .../git/GitCommitIdMojoIntegrationTest.java | 12 +++--- .../maven/git/NativeAndJGitProviderTest.java | 3 +- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main/java/pl/project13/maven/git/NativeGitProvider.java b/src/main/java/pl/project13/maven/git/NativeGitProvider.java index 205be385..82eb8adf 100644 --- a/src/main/java/pl/project13/maven/git/NativeGitProvider.java +++ b/src/main/java/pl/project13/maven/git/NativeGitProvider.java @@ -1,5 +1,7 @@ package pl.project13.maven.git; +import static java.lang.String.format; + import com.google.common.base.Splitter; import com.google.common.base.Throwables; import com.google.common.collect.Lists; @@ -93,10 +95,12 @@ private String getBranch(File canonical) { } } catch(NativeCommandException e) { // it seems that git repro is in 'DETACHED HEAD'-State, using Commid-Id as Branch - if (e.getExitCode() == 1) { + String err = e.getStderr(); + if (err != null && err.contains("ref HEAD is not a symbolic ref")) { branch = getCommitId(); + } else { + throw Throwables.propagate(e); } - throw Throwables.propagate(e); } return branch; } @@ -291,12 +295,19 @@ public static class NativeCommandException extends IOException private final int exitCode; private final String command; private final File directory; - - public NativeCommandException(int exitCode, String command, File directory, String message) { - super(message); + private final String stdout; + private final String stderr; + + public NativeCommandException(int exitCode, + String command, + File directory, + String stdout, + String stderr) { this.exitCode = exitCode; this.command = command; this.directory = directory; + this.stdout = stdout; + this.stderr = stderr; } public int getExitCode() { @@ -310,6 +321,19 @@ public String getCommand() { public File getDirectory() { return directory; } + + public String getStdout() { + return stdout; + } + + public String getStderr() { + return stderr; + } + + @Override + public String getMessage() { + return format("Git command exited with invalid status [%d]: stdout: `%s`, stderr: `%s`", exitCode, stdout, stderr); + } } protected static class JavaProcessRunner implements ProcessRunner { @@ -332,9 +356,7 @@ public String run(File directory, String command) throws IOException { if (proc.exitValue() != 0) { final StringBuilder errMsg = readStderr(err); - - final String message = String.format("Git command exited with invalid status [%d]: stdout: `%s`, stderr: `%s`", proc.exitValue(), output, errMsg.toString()); - throw new NativeCommandException(proc.exitValue(), command, directory, message); + throw new NativeCommandException(proc.exitValue(), command, directory, output, errMsg.toString()); } output = commandResult.toString(); } catch (InterruptedException ex) { diff --git a/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java b/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java index 3c2dbfd9..38943057 100644 --- a/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java +++ b/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java @@ -622,17 +622,17 @@ public void shouldExtractTagsOnGivenCommit(boolean useNativeGit) throws Exceptio @Parameters(method = "useNativeGit") public void runGitDescribeWithMatchOption(boolean useNativeGit) throws Exception { // given - mavenSandbox.withParentProject("my-pom-project", "pom") - .withChildProject("my-jar-module", "jar") - .withGitRepoInChild(AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) + mavenSandbox.withParentProject("my-plugin-project", "jar") + .withNoChildProject() + .withGitRepoInParent(AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) .create(CleanUp.CLEANUP_FIRST); - MavenProject targetProject = mavenSandbox.getChildProject(); + MavenProject targetProject = mavenSandbox.getParentProject(); setProjectToExecuteMojoIn(targetProject); Map gitTagMap = new HashMap(); - gitTagMap.put("v2.1.8", "4f787aa37d5d9c06780278f0cf92553d304820a2"); - gitTagMap.put("v2.1.9", "a9dba4a25b64ab288d90cd503785b830d2e189a2"); + gitTagMap.put("v2.1.11", "56c5a491720ce35ae8f8626be1d3414728f1b953"); + gitTagMap.put("v2.1.12", "e9879658209ee81d7bf50ceedd028737f0b1cd0c"); for (Map.Entry entry : gitTagMap.entrySet()) { String gitDescribeMatchNeedle = entry.getKey(); diff --git a/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java index 6cf2c234..278fcf7c 100644 --- a/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java +++ b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java @@ -135,8 +135,7 @@ private void alterMojoSettings(String parameterName, Object parameterValue) private Properties createCopy(Properties orig) { Properties p = new Properties(); - for (Object o : orig.keySet()) { - String key = o.toString(); + for (String key : orig.stringPropertyNames()) { p.setProperty(key, orig.getProperty(key)); } From c38736a162001d0647c5ac37cc8b3ed8d9eb3b22 Mon Sep 17 00:00:00 2001 From: Henning Schmiedehausen Date: Sun, 22 Feb 2015 21:31:38 -0800 Subject: [PATCH 5/6] fix indenting to 2 spaces --- .../maven/git/NativeGitProvider.java | 165 +++++++------- .../maven/git/NativeAndJGitProviderTest.java | 209 +++++++++--------- 2 files changed, 186 insertions(+), 188 deletions(-) diff --git a/src/main/java/pl/project13/maven/git/NativeGitProvider.java b/src/main/java/pl/project13/maven/git/NativeGitProvider.java index 82eb8adf..3cfdd6e9 100644 --- a/src/main/java/pl/project13/maven/git/NativeGitProvider.java +++ b/src/main/java/pl/project13/maven/git/NativeGitProvider.java @@ -55,26 +55,26 @@ protected void init() throws MojoExecutionException { @Override protected String getBuildAuthorName() { - try { - return runGitCommand(canonical, "config --get user.name"); - } catch (NativeCommandException e) { - if (e.getExitCode() == 1) { // No config file found - return ""; - } - throw Throwables.propagate(e); + try { + return runGitCommand(canonical, "config --get user.name"); + } catch (NativeCommandException e) { + if (e.getExitCode() == 1) { // No config file found + return ""; } + throw Throwables.propagate(e); + } } @Override protected String getBuildAuthorEmail() { - try { - return runGitCommand(canonical, "config --get user.email"); - } catch (NativeCommandException e) { - if (e.getExitCode() == 1) { // No config file found - return ""; - } - throw Throwables.propagate(e); + try { + return runGitCommand(canonical, "config --get user.email"); + } catch (NativeCommandException e) { + if (e.getExitCode() == 1) { // No config file found + return ""; } + throw Throwables.propagate(e); + } } @Override @@ -94,13 +94,13 @@ private String getBranch(File canonical) { branch = branch.replace("refs/heads/", ""); } } catch(NativeCommandException e) { - // it seems that git repro is in 'DETACHED HEAD'-State, using Commid-Id as Branch - String err = e.getStderr(); - if (err != null && err.contains("ref HEAD is not a symbolic ref")) { - branch = getCommitId(); - } else { - throw Throwables.propagate(e); - } + // it seems that git repro is in 'DETACHED HEAD'-State, using Commid-Id as Branch + String err = e.getStderr(); + if (err != null && err.contains("ref HEAD is not a symbolic ref")) { + branch = getCommitId(); + } else { + throw Throwables.propagate(e); + } } return branch; } @@ -215,15 +215,15 @@ private String getOriginRemote(File directory) throws MojoExecutionException { // welcome to text output parsing hell! - no `\n` is not enough for (String line : Splitter.onPattern("\\((fetch|push)\\)?").split(remotes)) { - String trimmed = line.trim(); + String trimmed = line.trim(); - if (trimmed.startsWith("origin")) { - String[] splited = trimmed.split("\\s+"); - if (splited.length != REMOTE_COLS - 1) { // because (fetch/push) was trimmed - throw new MojoExecutionException("Unsupported GIT output (verbose remote address): " + line); - } - remoteUrl = splited[1]; + if (trimmed.startsWith("origin")) { + String[] splited = trimmed.split("\\s+"); + if (splited.length != REMOTE_COLS - 1) { // because (fetch/push) was trimmed + throw new MojoExecutionException("Unsupported GIT output (verbose remote address): " + line); } + remoteUrl = splited[1]; + } } return remoteUrl; } @@ -250,32 +250,31 @@ private boolean tryCheckEmptyRunGitCommand(File directory, String gitCommand) { } private String runQuietGitCommand(File directory, String gitCommand) { - final String env = System.getenv("GIT_PATH"); - final String exec = (env == null) ? "git" : env; - final String command = String.format("%s %s", exec, gitCommand); + final String env = System.getenv("GIT_PATH"); + final String exec = (env == null) ? "git" : env; + final String command = String.format("%s %s", exec, gitCommand); - try { - return getRunner().run(directory, command.trim()).trim(); - } catch (IOException e) { - throw Throwables.propagate(e); - } + try { + return getRunner().run(directory, command.trim()).trim(); + } catch (IOException e) { + throw Throwables.propagate(e); + } } private String runGitCommand(File directory, String gitCommand) throws NativeCommandException { - final String env = System.getenv("GIT_PATH"); - final String exec = (env == null) ? "git" : env; - final String command = String.format("%s %s", exec, gitCommand); + final String env = System.getenv("GIT_PATH"); + final String exec = (env == null) ? "git" : env; + final String command = String.format("%s %s", exec, gitCommand); - try { - return getRunner().run(directory, command.trim()).trim(); - } catch (NativeCommandException e) { - throw e; - } catch (IOException e) { - throw Throwables.propagate(e); - } + try { + return getRunner().run(directory, command.trim()).trim(); + } catch (NativeCommandException e) { + throw e; + } catch (IOException e) { + throw Throwables.propagate(e); + } } - private ProcessRunner getRunner() { if (runner == null) { runner = new JavaProcessRunner(); @@ -292,48 +291,48 @@ public interface ProcessRunner { public static class NativeCommandException extends IOException { - private final int exitCode; - private final String command; - private final File directory; - private final String stdout; - private final String stderr; - - public NativeCommandException(int exitCode, - String command, - File directory, - String stdout, - String stderr) { - this.exitCode = exitCode; - this.command = command; - this.directory = directory; - this.stdout = stdout; - this.stderr = stderr; - } + private final int exitCode; + private final String command; + private final File directory; + private final String stdout; + private final String stderr; + + public NativeCommandException(int exitCode, + String command, + File directory, + String stdout, + String stderr) { + this.exitCode = exitCode; + this.command = command; + this.directory = directory; + this.stdout = stdout; + this.stderr = stderr; + } - public int getExitCode() { - return exitCode; - } + public int getExitCode() { + return exitCode; + } - public String getCommand() { - return command; - } + public String getCommand() { + return command; + } - public File getDirectory() { - return directory; - } + public File getDirectory() { + return directory; + } - public String getStdout() { - return stdout; - } + public String getStdout() { + return stdout; + } - public String getStderr() { - return stderr; - } + public String getStderr() { + return stderr; + } - @Override - public String getMessage() { - return format("Git command exited with invalid status [%d]: stdout: `%s`, stderr: `%s`", exitCode, stdout, stderr); - } + @Override + public String getMessage() { + return format("Git command exited with invalid status [%d]: stdout: `%s`, stderr: `%s`", exitCode, stdout, stderr); + } } protected static class JavaProcessRunner implements ProcessRunner { diff --git a/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java index 278fcf7c..2ec18d98 100644 --- a/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java +++ b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java @@ -33,119 +33,118 @@ public class NativeAndJGitProviderTest extends GitIntegrationTest { - public static final String[] GIT_KEYS = new String[] { - "git.build.time", - "git.branch", - "git.commit.id", - "git.commit.id.abbrev", - "git.commit.id.describe", - "git.build.user.name", - "git.build.user.email", - "git.commit.user.name", - "git.commit.user.email", - "git.commit.message.full", - "git.commit.message.short", - "git.commit.time", - "git.remote.origin.url" - }; - - // Can't be static, not thread safe. - public final DateFormat DEFAULT_FORMAT = new SimpleDateFormat("dd.MM.yyyy '@' HH:mm:ss z"); - - @Test - public void testCompareBasic() throws Exception - { - // Test on all available basic repos to ensure that the output is identical. - for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { - mavenSandbox.withParentProject("my-basic-project", "jar").withNoChildProject().withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); - MavenProject targetProject = mavenSandbox.getParentProject(); - verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); - } + public static final String[] GIT_KEYS = new String[] { + "git.build.time", + "git.branch", + "git.commit.id", + "git.commit.id.abbrev", + "git.commit.id.describe", + "git.build.user.name", + "git.build.user.email", + "git.commit.user.name", + "git.commit.user.email", + "git.commit.message.full", + "git.commit.message.short", + "git.commit.time", + "git.remote.origin.url" + }; + + // Can't be static, not thread safe. + public final DateFormat DEFAULT_FORMAT = new SimpleDateFormat("dd.MM.yyyy '@' HH:mm:ss z"); + + @Test + public void testCompareBasic() throws Exception + { + // Test on all available basic repos to ensure that the output is identical. + for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { + mavenSandbox.withParentProject("my-basic-project", "jar").withNoChildProject().withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); + MavenProject targetProject = mavenSandbox.getParentProject(); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); } - - @Test - public void testCompareSubrepoInRoot() throws Exception - { - for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { - if (testRepo == AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) { - continue; // Don't create a subrepo based off the plugin repo itself. - } - mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); - MavenProject targetProject = mavenSandbox.getParentProject(); - verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); - } + } + + @Test + public void testCompareSubrepoInRoot() throws Exception + { + for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { + if (testRepo == AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) { + continue; // Don't create a subrepo based off the plugin repo itself. + } + mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); + MavenProject targetProject = mavenSandbox.getParentProject(); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); } - - @Test - public void testCompareSubrepoInChild() throws Exception - { - for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { - if (testRepo == AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) { - continue; // Don't create a subrepo based off the plugin repo itself. - } - mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); - MavenProject targetProject = mavenSandbox.getChildProject(); - verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); - } + } + + @Test + public void testCompareSubrepoInChild() throws Exception + { + for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { + if (testRepo == AvailableGitTestRepo.MAVEN_GIT_COMMIT_ID_PLUGIN) { + continue; // Don't create a subrepo based off the plugin repo itself. + } + mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); + MavenProject targetProject = mavenSandbox.getChildProject(); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); } - - - private void verifyNativeAndJGit(MavenProject targetProject, DateFormat format) throws Exception - { - setProjectToExecuteMojoIn(targetProject); - - alterMojoSettings("useNativeGit", false); - alterMojoSettings("skipPoms", false); - mojo.execute(); - Properties jgitProps = createCopy(targetProject.getProperties()); - - alterMojoSettings("useNativeGit", true); - mojo.execute(); - Properties nativeProps = createCopy(targetProject.getProperties()); - - assertGitPropertiesPresentInProject(jgitProps); - assertGitPropertiesPresentInProject(nativeProps); - - for (String key : GIT_KEYS) { - if (!key.equals("git.build.time")) { // git.build.time is excused because the two runs happened at different times. - assertEquals("Key difference for key: '" + key + "'", jgitProps.getProperty(key), nativeProps.getProperty(key)); - } - else { - // Ensure that the date formats are parseable and within reason. If running all the git commands on the - // native provider takes more than 60 seconds, then something is seriously wrong. - long jGitBuildTimeInMs = format.parse(jgitProps.getProperty(key)).getTime(); - long nativeBuildTimeInMs = format.parse(nativeProps.getProperty(key)).getTime(); - Assert.assertTrue("Time ran backwards, jgitTime after nativeTime!", jGitBuildTimeInMs <= nativeBuildTimeInMs); - Assert.assertTrue("Build ran too slow.", (nativeBuildTimeInMs - jGitBuildTimeInMs) < 60000L); // If native takes more than 1 minute, something is wrong. - } - } - - // Check the commit time to be equal in ms, too. - long jGitCommitTimeInMs = format.parse(jgitProps.getProperty("git.commit.time")).getTime(); - long nativeCommitTimeInMs = format.parse(nativeProps.getProperty("git.commit.time")).getTime(); - - assertEquals("commit times parse to different time stamps", jGitCommitTimeInMs, nativeCommitTimeInMs); + } + + private void verifyNativeAndJGit(MavenProject targetProject, DateFormat format) throws Exception + { + setProjectToExecuteMojoIn(targetProject); + + alterMojoSettings("useNativeGit", false); + alterMojoSettings("skipPoms", false); + mojo.execute(); + Properties jgitProps = createCopy(targetProject.getProperties()); + + alterMojoSettings("useNativeGit", true); + mojo.execute(); + Properties nativeProps = createCopy(targetProject.getProperties()); + + assertGitPropertiesPresentInProject(jgitProps); + assertGitPropertiesPresentInProject(nativeProps); + + for (String key : GIT_KEYS) { + if (!key.equals("git.build.time")) { // git.build.time is excused because the two runs happened at different times. + assertEquals("Key difference for key: '" + key + "'", jgitProps.getProperty(key), nativeProps.getProperty(key)); + } + else { + // Ensure that the date formats are parseable and within reason. If running all the git commands on the + // native provider takes more than 60 seconds, then something is seriously wrong. + long jGitBuildTimeInMs = format.parse(jgitProps.getProperty(key)).getTime(); + long nativeBuildTimeInMs = format.parse(nativeProps.getProperty(key)).getTime(); + Assert.assertTrue("Time ran backwards, jgitTime after nativeTime!", jGitBuildTimeInMs <= nativeBuildTimeInMs); + Assert.assertTrue("Build ran too slow.", (nativeBuildTimeInMs - jGitBuildTimeInMs) < 60000L); // If native takes more than 1 minute, something is wrong. + } } - private void alterMojoSettings(String parameterName, Object parameterValue) - { - setInternalState(mojo, parameterName, parameterValue); - } + // Check the commit time to be equal in ms, too. + long jGitCommitTimeInMs = format.parse(jgitProps.getProperty("git.commit.time")).getTime(); + long nativeCommitTimeInMs = format.parse(nativeProps.getProperty("git.commit.time")).getTime(); + + assertEquals("commit times parse to different time stamps", jGitCommitTimeInMs, nativeCommitTimeInMs); + } - private Properties createCopy(Properties orig) - { - Properties p = new Properties(); - for (String key : orig.stringPropertyNames()) { - p.setProperty(key, orig.getProperty(key)); - } + private void alterMojoSettings(String parameterName, Object parameterValue) + { + setInternalState(mojo, parameterName, parameterValue); + } - return p; + private Properties createCopy(Properties orig) + { + Properties p = new Properties(); + for (String key : orig.stringPropertyNames()) { + p.setProperty(key, orig.getProperty(key)); } - private void assertGitPropertiesPresentInProject(Properties properties) - { - for (String key : GIT_KEYS) { - assertThat(properties).satisfies(new ContainsKeyCondition(key)); - } + return p; + } + + private void assertGitPropertiesPresentInProject(Properties properties) + { + for (String key : GIT_KEYS) { + assertThat(properties).satisfies(new ContainsKeyCondition(key)); } + } } From a0f7db71c4e570da24b57f2d68d5204fc653159c Mon Sep 17 00:00:00 2001 From: Henning Schmiedehausen Date: Sun, 22 Feb 2015 21:40:31 -0800 Subject: [PATCH 6/6] Add integration test for changed date format. Make sure that both git providers obey dateFormat changes. --- .../maven/git/NativeAndJGitProviderTest.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java index 2ec18d98..cea32faa 100644 --- a/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java +++ b/src/test/java/pl/project13/maven/git/NativeAndJGitProviderTest.java @@ -49,8 +49,8 @@ public class NativeAndJGitProviderTest extends GitIntegrationTest "git.remote.origin.url" }; - // Can't be static, not thread safe. - public final DateFormat DEFAULT_FORMAT = new SimpleDateFormat("dd.MM.yyyy '@' HH:mm:ss z"); + public static final String DEFAULT_FORMAT_STRING = "dd.MM.yyyy '@' HH:mm:ss z"; + public static final String ISO8601_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ssZZ"; @Test public void testCompareBasic() throws Exception @@ -59,7 +59,7 @@ public void testCompareBasic() throws Exception for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { mavenSandbox.withParentProject("my-basic-project", "jar").withNoChildProject().withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); MavenProject targetProject = mavenSandbox.getParentProject(); - verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT_STRING); } } @@ -72,7 +72,7 @@ public void testCompareSubrepoInRoot() throws Exception } mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); MavenProject targetProject = mavenSandbox.getParentProject(); - verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT_STRING); } } @@ -85,16 +85,31 @@ public void testCompareSubrepoInChild() throws Exception } mavenSandbox.withParentProject("my-pom-project", "pom").withChildProject("my-jar-module", "jar").withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); MavenProject targetProject = mavenSandbox.getChildProject(); - verifyNativeAndJGit(targetProject, DEFAULT_FORMAT); + verifyNativeAndJGit(targetProject, DEFAULT_FORMAT_STRING); } } - private void verifyNativeAndJGit(MavenProject targetProject, DateFormat format) throws Exception + @Test + public void testCompareISO8601Time() throws Exception + { + // Test on all available basic repos to ensure that the output is identical. + for (AvailableGitTestRepo testRepo : AvailableGitTestRepo.values()) { + mavenSandbox.withParentProject("my-basic-project", "jar").withNoChildProject().withGitRepoInParent(testRepo).create(CleanUp.CLEANUP_FIRST); + MavenProject targetProject = mavenSandbox.getParentProject(); + verifyNativeAndJGit(targetProject, ISO8601_FORMAT_STRING); + } + } + + private void verifyNativeAndJGit(MavenProject targetProject, String formatString) throws Exception { setProjectToExecuteMojoIn(targetProject); - alterMojoSettings("useNativeGit", false); alterMojoSettings("skipPoms", false); + alterMojoSettings("dateFormat", formatString); + + DateFormat format = new SimpleDateFormat(formatString); + + alterMojoSettings("useNativeGit", false); mojo.execute(); Properties jgitProps = createCopy(targetProject.getProperties());