From 7ee11ec89e0f6cea6dc56260fca6703208203d54 Mon Sep 17 00:00:00 2001 From: Konrad 'ktoso' Malawski Date: Tue, 21 Oct 2014 22:41:53 +0200 Subject: [PATCH] Implemented #133 tags on current commit in jgit and native It's hacky as in native... oh well, <3 jgit. Resolves #133 --- README.md | 12 +- pom.xml | 46 +++---- release.properties | 8 -- .../pl/project13/jgit/DescribeCommand.java | 47 ++----- .../pl/project13/jgit/DescribeResult.java | 8 +- .../project13/maven/git/GitCommitIdMojo.java | 62 ++++----- .../project13/maven/git/GitDataProvider.java | 30 ++-- .../maven/git/GitDescribeConfig.java | 8 +- .../maven/git/GitRepositoryState.java | 15 ++ .../pl/project13/maven/git/JGitProvider.java | 129 +++++++++++------- .../maven/git/NativeGitProvider.java | 42 ++++++ .../git/GitCommitIdMojoIntegrationTest.java | 35 +++++ .../maven/git/GitIntegrationTest.java | 4 + .../project13/test/utils/AssertException.java | 2 +- 14 files changed, 276 insertions(+), 172 deletions(-) delete mode 100644 release.properties diff --git a/README.md b/README.md index 9a08fb75..90e8b3ab 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ maven git commit id plugin ================================== [![Build Status](https://secure.travis-ci.org/ktoso/maven-git-commit-id-plugin.svg?branch=master)](http://travis-ci.org/ktoso/maven-git-commit-id-plugin) -git-commit-id-plugin is a plugin quite similar to https://fisheye.codehaus.org/browse/mojo/tags/buildnumber-maven-plugin-1.0-beta-4 fo example but as buildnumber only supports svn (which is very sad) and cvs (which is even more sad, and makes bunnies cry) I had to quickly develop an git version of such a plugin. For those who don't know the previous plugins, let me explain what this plugin does: +git-commit-id-plugin is a plugin quite similar to https://fisheye.codehaus.org/browse/mojo/tags/buildnumber-maven-plugin-1.0-beta-4 fo example but as buildnumber at the time when I started this plugin only supported CVS and SVN, something had to be done. +I had to quickly develop an git version of such a plugin. For those who don't know the previous plugins, let me explain what this plugin does: Use cases ========= @@ -35,7 +36,7 @@ A detailed description of using the pluing is available in the + @@ -300,6 +303,7 @@ import org.codehaus.jackson.annotate.JsonWriteNullProperties; @JsonWriteNullProperties(true) public class GitRepositoryState { String branch; // =${git.branch} + String branch; // =${git.tags} // comma separated tag names String describe; // =${git.commit.id.describe} String shortDescribe; // =${git.commit.id.describe-short} String commitId; // =${git.commit.id} @@ -352,6 +356,7 @@ In the end *this is what this service would return*: ```json { "branch" : "testing-maven-git-plugin", + "tags" : "v2.1.11,testing", "describe" : "v2.1.0-2-g2346463", "describeShort" : "v2.1.0-2", "commitTime" : "06.01.1970 @ 16:16:26 CET", @@ -416,6 +421,7 @@ You'd have to add such an constructor to your GitRepositoryState bean: public GitRepositoryState(Properties properties) { this.branch = properties.get("git.branch").toString(); + this.tags = properties.get("git.tags").toString(); this.describe = properties.get("git.commit.id.describe").toString(); this.describeShort = properties.get("git.commit.id.describe-short").toString(); this.commitId = properties.get("git.commit.id").toString(); diff --git a/pom.xml b/pom.xml index 97c75c86..c94e0e42 100644 --- a/pom.xml +++ b/pom.xml @@ -14,8 +14,8 @@ Git Commit Id Plugin Maven Mojo git-commit-id-plugin is a plugin quite similar to - https://fisheye.codehaus.org/browse/mojo/tags/buildnumber-maven-plugin-1.0-beta-4 for example but as buildnumber - only supports svn (which is very sad) and cvs (which is even more sad). + https://fisheye.codehaus.org/browse/mojo/tags/buildnumber-maven-plugin-1.0-beta-4 for example but as buildnumber at + the time when I started this plugin only supported CVS and SVN, something had to be done. This plugin makes basic repository information available through maven resources. This can be used to display "what version is this?" or "who has deployed this and when, from which branch?" information at runtime - making it easy to find things like "oh, that isn't deployed yet, I'll test it tomorrow" and making both testers and @@ -46,7 +46,7 @@ ktoso Konrad Malawski konrad.malawski@java.pl - Project13.pl + project13.pl http://blog.project13.pl @@ -100,12 +100,6 @@ 2.2.3 - - com.google.inject - guice - 2.0 - - joda-time @@ -165,7 +159,7 @@ - org.apache.commons + commons-io commons-io 1.3.2 jar @@ -247,22 +241,22 @@ - - maven-plugin-plugin - 3.2 - - - generated-helpmojo - - helpmojo - - - git-commit-id - pl.project13.maven - - - - + + + + + + + + + + + + + + + + diff --git a/release.properties b/release.properties deleted file mode 100644 index 00839282..00000000 --- a/release.properties +++ /dev/null @@ -1,8 +0,0 @@ -#release configuration -#Mon Jun 02 01:40:03 CEST 2014 -preparationGoals=clean verify -scm.commentPrefix=[maven-release-plugin] -remoteTagging=true -exec.additionalArguments=-Psonatype-oss-release -completedPhase=create-backup-poms -scm.url=scm\:git\:git@github.com\:ktoso/maven-git-commit-id-plugin.git diff --git a/src/main/java/pl/project13/jgit/DescribeCommand.java b/src/main/java/pl/project13/jgit/DescribeCommand.java index 902d50dc..46fdf876 100644 --- a/src/main/java/pl/project13/jgit/DescribeCommand.java +++ b/src/main/java/pl/project13/jgit/DescribeCommand.java @@ -54,25 +54,8 @@ /** * Implements git's
describe
command. - *

- *

- *  usage: git describe [options] *
- *  or: git describe [options] --dirty
- * 

- * --contains find the tag that comes after the commit - * --debug debug search strategy on stderr - * --all use any ref in .git/refs - * --tags use any tag in .git/refs/tags - * --long always use long format - * --abbrev[=] use digits to display SHA-1s - * --exact-match only output exact matches - * --candidates consider most recent tags (default: 10) - * --match only consider tags matching - * --always show abbreviated commit object as fallback - * --dirty[=] append on dirty working tree (default: "-dirty") - *

* - * @author
Konrad 'ktoso' Malawski + * @author Konrad Malawski */ public class DescribeCommand extends GitCommand { @@ -153,9 +136,9 @@ public DescribeCommand withLoggerBridge(LoggerBridge bridge) { /** *
--always
- *

+ * * Show uniquely abbreviated commit object as fallback. - *

+ * *

true
by default. */ @NotNull @@ -167,13 +150,13 @@ public DescribeCommand always(boolean always) { /** *
--long
- *

+ * * Always output the long format (the tag, the number of commits and the abbreviated commit name) * even when it matches a tag. This is useful when you want to see parts of the commit object name * in "describe" output, even when the commit in question happens to be a tagged version. Instead * of just emitting the tag name, it will describe such a commit as v1.2-0-gdeadbee (0th commit * since tag v1.2 that points at object deadbee....). - *

+ * *

false
by default. */ @NotNull @@ -187,11 +170,11 @@ public DescribeCommand forceLongFormat(@Nullable Boolean forceLongFormat) { /** *
--abbrev=N
- *

+ * * Instead of using the default 7 hexadecimal digits as the abbreviated object name, * use N digits, or as many digits as needed to form a unique object name. - *

- * An of 0 will suppress long format, only showing the closest tag. + * + * An `n` of 0 will suppress long format, only showing the closest tag. */ @NotNull public DescribeCommand abbrev(@Nullable Integer n) { @@ -210,22 +193,22 @@ public DescribeCommand abbrev(@Nullable Integer n) { * Instead of using only the annotated tags, use any tag found in .git/refs/tags. * This option enables matching a lightweight (non-annotated) tag. *

- *

+ * *

Searching for lightweight tags is false by default.

- *

+ * * Example: *

    *    b6a73ed - (HEAD, master)
    *    d37a598 - (v1.0-fixed-stuff) - a lightweight tag (with no message)
    *    9597545 - (v1.0) - an annotated tag
    *
-   *  > git describe
+   *  $ git describe
    *    annotated-tag-2-gb6a73ed     # the nearest "annotated" tag is found
    *
-   *  > git describe --tags
+   *  $ git describe --tags
    *    lightweight-tag-1-gb6a73ed   # the nearest tag (including lightweights) is found
    * 
- *

+ * *

* Using only annotated tags to mark builds may be useful if you're using tags to help yourself with annotating * things like "i'll get back to that" etc - you don't need such tags to be exposed. But if you want lightweight @@ -249,7 +232,7 @@ public DescribeCommand tags() { } /** - * Apply all configuration options passed in with {@param config}. + * Apply all configuration options passed in with `config`. * If a setting is null, it will not be applied - so for abbrev for example, the default 7 would be used. * * @return itself, after applying the settings @@ -342,7 +325,7 @@ public DescribeResult call() throws GitAPIException { * Prepares the final result of this command. * It tries to put as much information as possible into the result, * and will fallback to a plain commit hash if nothing better is returnable. - *

+ * * The exact logic is following what

git-describe
would do. */ private DescribeResult createDescribeResult(ObjectReader objectReader, ObjectId headCommitId, boolean dirty, @Nullable Pair howFarFromWhichTag) { diff --git a/src/main/java/pl/project13/jgit/DescribeResult.java b/src/main/java/pl/project13/jgit/DescribeResult.java index 767235a3..169ec604 100644 --- a/src/main/java/pl/project13/jgit/DescribeResult.java +++ b/src/main/java/pl/project13/jgit/DescribeResult.java @@ -33,7 +33,7 @@ /** * Represents the result of a git describe command. - *

+ * * See {@link pl.project13.jgit.DescribeResult#toString()} for a detailed information how this result looks like. */ public class DescribeResult { @@ -115,7 +115,7 @@ public DescribeResult withCommitIdAbbrev(int n) { * | |--------------- the number of commits away from the found tag. So "2414721" is 14 commits ahead of "v1.0.4", in this example. * |-------------------- the "nearest" tag, to the mentioned commit. * - *

+ * * Other outputs may look like: *

    * v1.0.4 -- if the repository is "on a tag"
@@ -123,7 +123,7 @@ public DescribeResult withCommitIdAbbrev(int n) {
    * 2414721 -- a plain commit id hash if not tags were defined (of determined "near" this commit).
    *            It does NOT include the "g" prefix, that is used in the "full" describe output format!
    * 
- *

+ * * For more details (on when what output will be returned etc), see man git-describe. * In general, you can assume it's a "best effort" approach, to give you as much info about the repo state as possible. * @@ -170,7 +170,7 @@ public String dirtyMarker() { * This is following git's behaviour - so any git tooling should be happy with this output. *

*

- * Notes about the abbriverated object id:
+ * Notes about the abbriverated object id: * Git will try to use your given abbrev lenght, but when it's to short to guarantee uniqueness - * a longer one will be used (which WILL guarantee uniqueness). * If you need the full commit id, it's always available via {@link pl.project13.jgit.DescribeResult#commitObjectId()}. diff --git a/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java b/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java index 882330f3..b7787690 100644 --- a/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java +++ b/src/main/java/pl/project13/maven/git/GitCommitIdMojo.java @@ -70,6 +70,7 @@ public class GitCommitIdMojo extends AbstractMojo { public static final String COMMIT_MESSAGE_SHORT = "commit.message.short"; public static final String COMMIT_TIME = "commit.time"; public static final String REMOTE_ORIGIN_URL = "remote.origin.url"; + public static final String TAGS = "tags"; /** * The maven project. @@ -92,7 +93,7 @@ public class GitCommitIdMojo extends AbstractMojo { /** * Tell git-commit-id to inject the git properties into all * reactor projects not just the current one. - *

+ * * For details about why you might want to skip this, read this issue: https://github.com/ktoso/maven-git-commit-id-plugin/pull/65 * Basically, injecting into all projects may slow down the build and you don't always need this feature. * @@ -124,7 +125,7 @@ public class GitCommitIdMojo extends AbstractMojo { * Specifies whether plugin should generate properties file. * By default it will not generate any additional file, * and only add properties to maven project's properties for further filtering - *

+ * * If set to "true" properties will be fully generated with no placeholders inside. * * @parameter default-value="false" @@ -136,7 +137,7 @@ public class GitCommitIdMojo extends AbstractMojo { * Decide where to generate the git.properties file. By default, the ${project.build.outputDirectory}/git.properties * file will be updated - of course you must first set generateGitPropertiesFile = true to force git-commit-id * into generateFile mode. - *

+ * * The path here is relative to your projects src directory. * * @parameter default-value="${project.build.outputDirectory}/git.properties" @@ -155,7 +156,7 @@ public class GitCommitIdMojo extends AbstractMojo { /** * Configuration for the

git-describe
command. * You can modify the dirty marker, abbrev length and other options here. - *

+ * * If not specified, default values will be used. * * @parameter @@ -168,12 +169,12 @@ public class GitCommitIdMojo extends AbstractMojo { * Configure the "git.commit.id.abbrev" property to be at least of length N. * N must be in the range of 2 to 40 (inclusive), other values will result in an Exception. *

- *

+ * *

* An Abbreviated commit is a shorter version of the commit id, it is guaranteed to be unique though. * To keep this contract, the plugin may decide to print an abbrev version that is longer than the value specified here. *

- *

+ * * Example: *

* You have a very big repository, yet you set this value to 2. It's very probable that you'll end up getting a 4 or 7 char @@ -224,10 +225,10 @@ public class GitCommitIdMojo extends AbstractMojo { * By default the plugin will fail the build if unable to obtain enough data for a complete run, * if you don't care about this - for example it's not needed during your CI builds and the CI server does weird * things to the repository, you may want to set this value to false. - *

+ * * Setting this value to `false`, causes the plugin to gracefully tell you "I did my best" and abort it's execution * if unable to obtain git meta data - yet the build will continue to run (without failing). - *

+ * * See https://github.com/ktoso/maven-git-commit-id-plugin/issues/63 for a rationale behing this flag. * * @parameter default-value="true" @@ -304,7 +305,7 @@ public void execute() throws MojoExecutionException { log("dotGitDirectory is null, aborting execution!"); return; } - + try { properties = initProperties(); @@ -332,8 +333,9 @@ public void execute() throws MojoExecutionException { } private void filterNot(Properties properties, @Nullable List exclusions) { - if (exclusions == null) + if (exclusions == null) { return; + } List> excludePredicates = Lists.transform(exclusions, new Function>() { @Override @@ -349,7 +351,7 @@ public Predicate apply(String exclude) { for (String key : properties.stringPropertyNames()) { if (shouldExclude.apply(key)) { - loggerBridge.debug("shouldExclude.apply(" + key +") = " + shouldExclude.apply(key)); + loggerBridge.debug("shouldExclude.apply(" + key + ") = " + shouldExclude.apply(key)); properties.remove(key); } } @@ -394,8 +396,7 @@ private void throwWhenRequiredDirectoryNotFound(File dotGitDirectory, Boolean re * * @return the File representation of the .git directory */ - @VisibleForTesting - File lookupGitDirectory() throws MojoExecutionException { + @VisibleForTesting File lookupGitDirectory() throws MojoExecutionException { return new GitDirLocator(project, reactorProjects).lookupGitDirectory(dotGitDirectory); } @@ -427,7 +428,7 @@ void loadBuildTimeData(@NotNull Properties properties) { SimpleDateFormat smf = new SimpleDateFormat(dateFormat); put(properties, BUILD_TIME, smf.format(commitDate)); } - + void loadShortDescribe(@NotNull Properties properties) { //removes git hash part from describe String commitDescribe = properties.getProperty(prefixDot + COMMIT_DESCRIBE); @@ -452,7 +453,7 @@ void loadShortDescribe(@NotNull Properties properties) { void loadGitData(@NotNull Properties properties) throws IOException, MojoExecutionException { if (useNativeGit) { loadGitDataWithNativeGit(properties); - }else{ + } else { loadGitDataWithJGit(properties); } } @@ -462,24 +463,24 @@ void loadGitDataWithNativeGit(@NotNull Properties properties) throws IOException NativeGitProvider nativeGitProvider = NativeGitProvider .on(basedir) .withLoggerBridge(loggerBridge) - .setVerbose(verbose) + .setVerbose(verbose) .setPrefixDot(prefixDot) .setAbbrevLength(abbrevLength) - .setDateFormat(dateFormat) + .setDateFormat(dateFormat) .setGitDescribe(gitDescribe); - nativeGitProvider.loadGitData(properties); + nativeGitProvider.loadGitData(properties); } void loadGitDataWithJGit(@NotNull Properties properties) throws IOException, MojoExecutionException { JGitProvider jGitProvider = JGitProvider - .on(dotGitDirectory) - .withLoggerBridge(loggerBridge) - .setVerbose(verbose) - .setPrefixDot(prefixDot) - .setAbbrevLength(abbrevLength) - .setDateFormat(dateFormat) - .setGitDescribe(gitDescribe); + .on(dotGitDirectory) + .withLoggerBridge(loggerBridge) + .setVerbose(verbose) + .setPrefixDot(prefixDot) + .setAbbrevLength(abbrevLength) + .setDateFormat(dateFormat) + .setGitDescribe(gitDescribe); jGitProvider.loadGitData(properties); } @@ -507,13 +508,12 @@ void generatePropertiesFile(@NotNull Properties properties, File base, String pr } } - @VisibleForTesting - File craftPropertiesOutputFile(File base, String propertiesFilename){ + @VisibleForTesting File craftPropertiesOutputFile(File base, String propertiesFilename) { File returnPath = new File(base, propertiesFilename); File currentPropertiesFilepath = new File(propertiesFilename); - if(currentPropertiesFilepath.isAbsolute()){ - returnPath = currentPropertiesFilepath; + if (currentPropertiesFilepath.isAbsolute()) { + returnPath = currentPropertiesFilepath; } return returnPath; @@ -580,11 +580,11 @@ public void setExcludeProperties(List excludeProperties) { this.excludeProperties = excludeProperties; } - public void useNativeGit(boolean useNativeGit){ + public void useNativeGit(boolean useNativeGit) { this.useNativeGit = useNativeGit; } - public LoggerBridge getLoggerBridge(){ + public LoggerBridge getLoggerBridge() { return loggerBridge; } } diff --git a/src/main/java/pl/project13/maven/git/GitDataProvider.java b/src/main/java/pl/project13/maven/git/GitDataProvider.java index c9a50be3..d1960bee 100644 --- a/src/main/java/pl/project13/maven/git/GitDataProvider.java +++ b/src/main/java/pl/project13/maven/git/GitDataProvider.java @@ -1,16 +1,14 @@ package pl.project13.maven.git; -import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.project.MavenProject; -import java.io.IOException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.*; import pl.project13.maven.git.log.LoggerBridge; -import pl.project13.maven.git.log.MavenLoggerBridge; import pl.project13.maven.git.util.PropertyManager; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + import static com.google.common.base.Strings.isNullOrEmpty; /** @@ -45,6 +43,7 @@ public abstract class GitDataProvider { protected abstract String getCommitMessageShort(); protected abstract String getCommitTime(); protected abstract String getRemoteOriginUrl() throws MojoExecutionException; + protected abstract String getTags() throws MojoExecutionException; protected abstract void finalCleanUp(); public void loadGitData(@NotNull Properties properties) throws IOException, MojoExecutionException{ @@ -53,7 +52,7 @@ public void loadGitData(@NotNull Properties properties) throws IOException, Mojo put(properties, GitCommitIdMojo.BUILD_AUTHOR_NAME, getBuildAuthorName()); // git.user.email put(properties, GitCommitIdMojo.BUILD_AUTHOR_EMAIL, getBuildAuthorEmail()); - + try { prepareGitToExtractMoreDetailedReproInformation(); validateAbbrevLength(abbrevLength); @@ -78,7 +77,10 @@ public void loadGitData(@NotNull Properties properties) throws IOException, Mojo put(properties, GitCommitIdMojo.COMMIT_TIME, getCommitTime()); // git remote.origin.url put(properties, GitCommitIdMojo.REMOTE_ORIGIN_URL, getRemoteOriginUrl()); - }finally{ + + // + put(properties, GitCommitIdMojo.TAGS, getTags()); + } finally { finalCleanUp(); } } @@ -86,7 +88,7 @@ public void loadGitData(@NotNull Properties properties) throws IOException, Mojo private void maybePutGitDescribe(@NotNull Properties properties) throws MojoExecutionException{ boolean isGitDescribeOptOutByDefault = (gitDescribe == null); boolean isGitDescribeOptOutByConfiguration = (gitDescribe != null && !gitDescribe.isSkip()); - + if (isGitDescribeOptOutByDefault || isGitDescribeOptOutByConfiguration) { put(properties, GitCommitIdMojo.COMMIT_DESCRIBE, getGitDescribe()); } @@ -103,7 +105,7 @@ void validateAbbrevLength(int abbrevLength) throws MojoExecutionException { * If running within Jenkins/Hudosn, honor the branch name passed via GIT_BRANCH env var. This * is necessary because Jenkins/Hudson alwways invoke build in a detached head state. * - * @param env + * @param env environment settings * @return results of getBranchName() or, if in Jenkins/Hudson, value of GIT_BRANCH */ protected String determineBranchName(Map env) throws IOException { @@ -116,12 +118,12 @@ protected String determineBranchName(Map env) throws IOException /** * Detects if we're running on Jenkins or Hudson, based on expected env variables. - *

+ * * TODO: How can we detect Bamboo, TeamCity etc? Pull requests welcome. * * @return true if running * @see JenkinsSetEnvironmentVariables - * @param env + * @param env environment settings */ private boolean runningOnBuildServer(Map env) { return env.containsKey("HUDSON_URL") || env.containsKey("JENKINS_URL"); @@ -129,7 +131,7 @@ private boolean runningOnBuildServer(Map env) { /** * Is "Jenkins aware", and prefers {@code GIT_BRANCH} to getting the branch via git if that enviroment variable is set. - * The {@GIT_BRANCH} variable is set by Jenkins/Hudson when put in detached HEAD state, but it still knows which branch was cloned. + * The {@code GIT_BRANCH} variable is set by Jenkins/Hudson when put in detached HEAD state, but it still knows which branch was cloned. */ protected String determineBranchNameOnBuildServer(Map env) throws IOException { String enviromentBasedBranch = env.get("GIT_BRANCH"); @@ -143,7 +145,7 @@ protected String determineBranchNameOnBuildServer(Map env) throw } void log(String... parts) { - if(loggerBridge!=null){ + if (loggerBridge != null) { loggerBridge.log((Object[]) parts); } } diff --git a/src/main/java/pl/project13/maven/git/GitDescribeConfig.java b/src/main/java/pl/project13/maven/git/GitDescribeConfig.java index 1d48ad33..0fa73860 100644 --- a/src/main/java/pl/project13/maven/git/GitDescribeConfig.java +++ b/src/main/java/pl/project13/maven/git/GitDescribeConfig.java @@ -26,7 +26,7 @@ public class GitDescribeConfig { /** * If you don't use describe, you can always disable it and make the build a bit faster. - *

+ * * Although it's highly recommended to use

git-describe
to identify your build state, * so think twice before disabeling it. * @@ -113,7 +113,7 @@ public class GitDescribeConfig { *

* *

Searching for lightweight tags is false by default.

- *

+ * * * Example: *

@@ -140,13 +140,13 @@ public class GitDescribeConfig {
 
   /**
    * 
--long
- *

+ * * Always output the long format (the tag, the number of commits and the abbreviated commit name) * even when it matches a tag. This is useful when you want to see parts of the commit object name * in "describe" output, even when the commit in question happens to be a tagged version. Instead * of just emitting the tag name, it will describe such a commit as v1.2-0-gdeadbee (0th commit * since tag v1.2 that points at object deadbee....). - *

+ * *

false
by default. */ private boolean forceLongFormat; diff --git a/src/main/java/pl/project13/maven/git/GitRepositoryState.java b/src/main/java/pl/project13/maven/git/GitRepositoryState.java index e7b6d676..f981ad41 100644 --- a/src/main/java/pl/project13/maven/git/GitRepositoryState.java +++ b/src/main/java/pl/project13/maven/git/GitRepositoryState.java @@ -19,8 +19,12 @@ //import org.codehaus.jackson.annotate.JsonWriteNullProperties; +import com.google.common.base.Joiner; import org.jetbrains.annotations.NotNull; +import java.util.List; +import java.util.Set; + /** * A spring controlled bean that will be injected * with properties about the repository state at build time. @@ -42,6 +46,7 @@ public class GitRepositoryState { String commitMessageFull; // =${git.commit.message.full} String commitMessageShort; // =${git.commit.message.short} String commitTime; // =${git.commit.time} + Set tags; // =${git.tags} String mavenProjectVersion; // =${maven.project.version} @@ -144,6 +149,14 @@ public void setMavenProjectVersion(String mavenProjectVersion) { this.mavenProjectVersion = mavenProjectVersion; } + public Set getTags() { + return tags; + } + + public void setTags(Set tags) { + this.tags = tags; + } + /** * If you need it as json but don't have jackson installed etc * @@ -165,6 +178,8 @@ public String toJson() { appendProperty(sb, "buildUserName", buildUserName); appendProperty(sb, "buildUserEmail", buildUserEmail); + appendProperty(sb, "tags", Joiner.on(",").join(tags)); + appendProperty(sb, "mavenProjectVersion", mavenProjectVersion); return sb.append("}").toString(); diff --git a/src/main/java/pl/project13/maven/git/JGitProvider.java b/src/main/java/pl/project13/maven/git/JGitProvider.java index 00363e3d..37a4a086 100644 --- a/src/main/java/pl/project13/maven/git/JGitProvider.java +++ b/src/main/java/pl/project13/maven/git/JGitProvider.java @@ -1,41 +1,32 @@ package pl.project13.maven.git; -import com.fasterxml.jackson.databind.ObjectMapper; + import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; +import com.google.common.base.Joiner; import com.google.common.base.Predicate; -import com.google.common.base.Predicates; +import com.google.common.collect.Collections2; import com.google.common.collect.Lists; -import com.google.common.io.Closeables; -import com.google.common.io.Files; -import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.project.MavenProject; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.ListTagCommand; import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.lib.AbbreviatedObjectId; -import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.lib.ObjectReader; -import org.eclipse.jgit.lib.Ref; -import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.*; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import pl.project13.jgit.DescribeCommand; import pl.project13.jgit.DescribeResult; import pl.project13.maven.git.log.LoggerBridge; -import pl.project13.maven.git.log.MavenLoggerBridge; import java.io.File; -import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.*; /** -* -* @author Konrad 'ktoso' Malawski -*/ + * @author Konrad 'ktoso' Malawski + */ public class JGitProvider extends GitDataProvider { private File dotGitDirectory; @@ -49,7 +40,7 @@ public static JGitProvider on(@NotNull File dotGitDirectory) { return new JGitProvider(dotGitDirectory); } - JGitProvider(@NotNull File dotGitDirectory){ + JGitProvider(@NotNull File dotGitDirectory) { this.dotGitDirectory = dotGitDirectory; } @@ -81,32 +72,32 @@ public JGitProvider setDateFormat(String dateFormat) { return this; } - public JGitProvider setGitDescribe(GitDescribeConfig gitDescribe){ + public JGitProvider setGitDescribe(GitDescribeConfig gitDescribe) { super.gitDescribe = gitDescribe; return this; } @Override - protected void init() throws MojoExecutionException{ + protected void init() throws MojoExecutionException { git = getGitRepository(); objectReader = git.newObjectReader(); } @Override - protected String getBuildAuthorName(){ + protected String getBuildAuthorName() { String userName = git.getConfig().getString("user", null, "name"); return userName; } @Override - protected String getBuildAuthorEmail(){ + protected String getBuildAuthorEmail() { String userEmail = git.getConfig().getString("user", null, "email"); return userEmail; } @Override - protected void prepareGitToExtractMoreDetailedReproInformation() throws MojoExecutionException{ - try{ + protected void prepareGitToExtractMoreDetailedReproInformation() throws MojoExecutionException { + try { // more details parsed out bellow Ref HEAD = git.getRef(Constants.HEAD); if (HEAD == null) { @@ -115,61 +106,61 @@ protected void prepareGitToExtractMoreDetailedReproInformation() throws MojoExec revWalk = new RevWalk(git); headCommit = revWalk.parseCommit(HEAD.getObjectId()); revWalk.markStart(headCommit); - }catch(Exception e){ + } catch (Exception e) { throw new MojoExecutionException("Error", e); } } @Override - protected String getBranchName() throws IOException{ + protected String getBranchName() throws IOException { String branch = git.getBranch(); return branch; } @Override - protected String getGitDescribe() throws MojoExecutionException{ + protected String getGitDescribe() throws MojoExecutionException { String gitDescribe = getGitDescribe(git); return gitDescribe; } @Override - protected String getCommitId(){ + protected String getCommitId() { String commitId = headCommit.getName(); return commitId; } @Override - protected String getAbbrevCommitId() throws MojoExecutionException{ + protected String getAbbrevCommitId() throws MojoExecutionException { String abbrevCommitId = getAbbrevCommitId(objectReader, headCommit, abbrevLength); return abbrevCommitId; } @Override - protected String getCommitAuthorName(){ + protected String getCommitAuthorName() { String commitAuthor = headCommit.getAuthorIdent().getName(); return commitAuthor; } @Override - protected String getCommitAuthorEmail(){ + protected String getCommitAuthorEmail() { String commitEmail = headCommit.getAuthorIdent().getEmailAddress(); return commitEmail; } @Override - protected String getCommitMessageFull(){ + protected String getCommitMessageFull() { String fullMessage = headCommit.getFullMessage(); return fullMessage; } @Override - protected String getCommitMessageShort(){ + protected String getCommitMessageShort() { String shortMessage = headCommit.getShortMessage(); return shortMessage; } @Override - protected String getCommitTime(){ + protected String getCommitTime() { long timeSinceEpoch = headCommit.getCommitTime(); Date commitDate = new Date(timeSinceEpoch * 1000); // git is "by sec" and java is "by ms" SimpleDateFormat smf = new SimpleDateFormat(dateFormat); @@ -177,26 +168,66 @@ protected String getCommitTime(){ } @Override - protected String getRemoteOriginUrl() throws MojoExecutionException{ + protected String getRemoteOriginUrl() throws MojoExecutionException { String remoteOriginUrl = git.getConfig().getString("remote", "origin", "url"); return remoteOriginUrl; } @Override - protected void finalCleanUp(){ + protected String getTags() throws MojoExecutionException { + RevWalk walk = null; + try { + Repository repo = getGitRepository(); + Git git = Git.wrap(repo); + walk = new RevWalk(repo); + List tagRefs = git.tagList().call(); + + final ObjectId headId = headCommit.toObjectId(); + final RevWalk finalWalk = walk; + Collection tagsForHeadCommit = Collections2.filter(tagRefs, new Predicate() { + @Override public boolean apply(Ref tagRef) { + boolean lightweightTag = tagRef.getObjectId().equals(headId); + + try { + // TODO make this configurable (most users shouldn't really care too much what kind of tag it is though) + return lightweightTag || finalWalk.parseTag(tagRef.getObjectId()).getObject().getId().equals(headId); // or normal tag + } catch (IOException e) { + return false; + } + } + }); + + Collection tags = Collections2.transform(tagsForHeadCommit, new Function() { + @Override public String apply(Ref input) { + return input.getName().replaceAll("refs/tags/", ""); + } + }); + + return Joiner.on(",").join(tags); + } catch (GitAPIException e) { + loggerBridge.error("Unable to extract tags from commit: " + headCommit.getName() + " (" + e.getClass().getName() + ")"); + return ""; + } finally { + if (walk != null) { + walk.dispose(); + } + } + } + + @Override + protected void finalCleanUp() { revWalk.dispose(); } - @VisibleForTesting - String getGitDescribe(@NotNull Repository repository) throws MojoExecutionException { + @VisibleForTesting String getGitDescribe(@NotNull Repository repository) throws MojoExecutionException { try { DescribeResult describeResult = DescribeCommand - .on(repository) - .withLoggerBridge(super.loggerBridge) - .setVerbose(super.verbose) - .apply(super.gitDescribe) - .call(); + .on(repository) + .withLoggerBridge(super.loggerBridge) + .setVerbose(super.verbose) + .apply(super.gitDescribe) + .call(); return describeResult.toString(); } catch (GitAPIException ex) { @@ -211,7 +242,7 @@ private String getAbbrevCommitId(ObjectReader objectReader, RevCommit headCommit return abbreviatedObjectId.name(); } catch (IOException e) { throw new MojoExecutionException("Unable to abbreviate commit id! " + - "You may want to investigate the element in your configuration.", e); + "You may want to investigate the element in your configuration.", e); } } @@ -223,10 +254,10 @@ private Repository getGitRepository() throws MojoExecutionException { FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder(); try { repository = repositoryBuilder - .setGitDir(dotGitDirectory) - .readEnvironment() // scan environment GIT_* variables - .findGitDir() // scan up the file system tree - .build(); + .setGitDir(dotGitDirectory) + .readEnvironment() // scan environment GIT_* variables + .findGitDir() // scan up the file system tree + .build(); } catch (IOException e) { throw new MojoExecutionException("Could not initialize repository...", e); } @@ -241,7 +272,7 @@ private Repository getGitRepository() throws MojoExecutionException { // SETTERS FOR TESTS ---------------------------------------------------- @VisibleForTesting - public void setRepository (Repository git){ + public void setRepository(Repository git) { this.git = git; } } diff --git a/src/main/java/pl/project13/maven/git/NativeGitProvider.java b/src/main/java/pl/project13/maven/git/NativeGitProvider.java index af789105..089f494f 100644 --- a/src/main/java/pl/project13/maven/git/NativeGitProvider.java +++ b/src/main/java/pl/project13/maven/git/NativeGitProvider.java @@ -1,11 +1,22 @@ 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.Collections2; +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.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; public class NativeGitProvider extends GitDataProvider { @@ -189,6 +200,37 @@ protected String getCommitTime() { return tryToRunGitCommand(canonical, "log -1 --pretty=format:\"%ci\""); } + @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); + } + @Override protected String getRemoteOriginUrl() throws MojoExecutionException { return getOriginRemote(canonical); diff --git a/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java b/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java index a19e16a4..7c0a5f53 100644 --- a/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java +++ b/src/test/java/pl/project13/maven/git/GitCommitIdMojoIntegrationTest.java @@ -18,12 +18,15 @@ package pl.project13.maven.git; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Splitter; import com.google.common.io.Files; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.FileUtils; +import org.eclipse.jgit.api.ResetCommand; +import org.eclipse.jgit.lib.Repository; import org.junit.Test; import org.junit.runner.RunWith; import pl.project13.maven.git.FileSystemMavenSandbox.CleanUp; @@ -564,6 +567,38 @@ public void shouldWorkWithNullGitDescribe(boolean useNativeGit) throws Exception assertGitPropertiesPresentInProject(targetProject.getProperties()); } + @Test + @Parameters(method = "useNativeGit") + public void shouldExtractTagsOnGivenCommit(boolean useNativeGit) throws Exception { + // given + mavenSandbox + .withParentProject("my-jar-project", "jar") + .withNoChildProject() + .withGitRepoInParent(AvailableGitTestRepo.WITH_COMMIT_THAT_HAS_TWO_TAGS) + .create(CleanUp.CLEANUP_FIRST); + + git("my-jar-project").reset().setMode(ResetCommand.ResetType.HARD).setRef("d37a598").call(); + + MavenProject targetProject = mavenSandbox.getParentProject(); + setProjectToExecuteMojoIn(targetProject); + + alterMojoSettings("gitDescribe", null); + alterMojoSettings("useNativeGit", useNativeGit); + + // when + mojo.execute(); + + // then + Properties properties = targetProject.getProperties(); + assertGitPropertiesPresentInProject(properties); + + assertThat(properties).satisfies(new ContainsKeyCondition("git.tags")); + assertThat(properties.get("git.tags").toString()).doesNotContain("refs/tags/"); + + assertThat(Splitter.on(",").split(properties.get("git.tags").toString())) + .containsOnly("lightweight-tag", "newest-tag"); + } + private GitDescribeConfig createGitDescribeConfig(boolean forceLongFormat, int abbrev) { GitDescribeConfig gitDescribeConfig = new GitDescribeConfig(); gitDescribeConfig.setTags(true); diff --git a/src/test/java/pl/project13/maven/git/GitIntegrationTest.java b/src/test/java/pl/project13/maven/git/GitIntegrationTest.java index a3f6a0a5..d6753b1e 100644 --- a/src/test/java/pl/project13/maven/git/GitIntegrationTest.java +++ b/src/test/java/pl/project13/maven/git/GitIntegrationTest.java @@ -44,6 +44,10 @@ public void setUp() throws Exception { initializeMojoWithDefaults(mojo); } + protected Git git(String dir) throws IOException, InterruptedException { + return Git.open(dotGitDir(Optional.of(dir))); + } + protected Git git() throws IOException, InterruptedException { return Git.open(dotGitDir(projectDir())); } diff --git a/src/test/java/pl/project13/test/utils/AssertException.java b/src/test/java/pl/project13/test/utils/AssertException.java index 510e5876..9ff3b3a2 100644 --- a/src/test/java/pl/project13/test/utils/AssertException.java +++ b/src/test/java/pl/project13/test/utils/AssertException.java @@ -27,7 +27,7 @@ * Allows expecting and intercepting exceptions in a nice way. * Use it to intercept exceptions in your tests, in a way that allows * sticking to the given/when/then flow, and validate exception throws on - *

+ * * SoftwareBirr 02.2012 * * @author Konrad Malawski (konrad.malawski@java.pl)