Skip to content

Add support for per-module versions to core #247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/main/java/pl/project13/core/GitCommitIdPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,22 @@ default Map<String, String> getSystemEnv() {
boolean shouldPropertiesEscapeUnicode();

boolean shouldFailOnNoGitDirectory();

/**
* When set to {@code true}, the plugin will consider only commits affecting
* the folder containing this module.
*
* When set to {@code false}, the plugin will consider all commits in the
* repository.
*
* @return Controls whether the plugin only considers commits in the current module's directory.
*/
boolean getPerModuleVersions();

/**
* @return Base directory (folder) of the current module.
*/
File getModuleBaseDir();
}

protected static final Pattern allowedCharactersForEvaluateOnCommit = Pattern.compile("[a-zA-Z0-9\\_\\-\\^\\/\\.]+");
Expand Down Expand Up @@ -367,6 +383,9 @@ private static void loadGitDataWithNativeGit(
@Nonnull Callback cb,
@Nonnull File dotGitDirectory,
@Nonnull Properties properties) throws GitCommitIdExecutionException {
if (cb.getPerModuleVersions()) {
throw new GitCommitIdExecutionException("The native git provider does not support per module versions.");
}
GitDataProvider nativeGitProvider = NativeGitProvider
.on(dotGitDirectory, cb.getNativeGitTimeoutInMs(), cb.getLogInterface())
.setPrefixDot(cb.getPrefixDot())
Expand All @@ -378,6 +397,7 @@ private static void loadGitDataWithNativeGit(
.setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment())
.setExcludeProperties(cb.getExcludeProperties())
.setIncludeOnlyProperties(cb.getIncludeOnlyProperties())
.setModuleBaseDir(cb.getModuleBaseDir())
.setOffline(cb.isOffline());

nativeGitProvider.loadGitData(cb.getEvaluateOnCommit(), cb.getSystemEnv(), properties);
Expand All @@ -398,6 +418,8 @@ private static void loadGitDataWithJGit(
.setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment())
.setExcludeProperties(cb.getExcludeProperties())
.setIncludeOnlyProperties(cb.getIncludeOnlyProperties())
.setPerModuleVersions(cb.getPerModuleVersions())
.setModuleBaseDir(cb.getModuleBaseDir())
.setOffline(cb.isOffline());

jGitProvider.loadGitData(cb.getEvaluateOnCommit(), cb.getSystemEnv(), properties);
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/pl/project13/core/GitDataProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import pl.project13.core.util.PropertyManager;

import javax.annotation.Nonnull;

import java.io.File;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -108,6 +110,20 @@ public abstract class GitDataProvider implements GitProvider {
*/
protected List<String> includeOnlyProperties;

/**
* When set to {@code true}, the plugin will consider only commits affecting
* the folder containing this module.
*
* When set to {@code false}, the plugin will consider all commits in the
* repository.
*/
protected boolean perModuleVersions = false;

/**
* The directory containing this project.
*/
protected File moduleBaseDir;

/**
* When set to {@code true}, the plugin will not try to contact any remote repositories.
* Any operations will only use the local state of the repo.
Expand Down Expand Up @@ -242,6 +258,31 @@ public GitDataProvider setOffline(boolean offline) {
return this;
}

/**
* When set to {@code true}, the plugin will consider only commits affecting
* the folder containing this module.
*
* When set to {@code false}, the plugin will consider all commits in the
* repository.
* @param perModuleVersions Only consider commits affecting the folder containing this module.
* @return The {@code GitProvider} with the corresponding {@code perModuleVersions} flag set.
*/
public GitDataProvider setPerModuleVersions(boolean perModuleVersions) {
this.perModuleVersions = perModuleVersions;
return this;
}

/**
* Path to the module base directory.
*
* @param moduleBaseDir The path to the directory containing this module.
* @return The {@code GitProvider} with the corresponding {@code moduleBaseDir} set.
*/
public GitDataProvider setModuleBaseDir(File moduleBaseDir) {
this.moduleBaseDir = moduleBaseDir;
return this;
}

/**
* Main function that will attempt to load the desired properties from the git repository.
*
Expand Down
79 changes: 59 additions & 20 deletions src/main/java/pl/project13/core/JGitProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,29 +84,13 @@ public String getBuildAuthorEmail() throws GitCommitIdExecutionException {
@Override
public void prepareGitToExtractMoreDetailedRepoInformation() throws GitCommitIdExecutionException {
try {
// more details parsed out bellow
Ref evaluateOnCommitReference = git.findRef(evaluateOnCommit);
ObjectId evaluateOnCommitResolvedObjectId = git.resolve(evaluateOnCommit);

if ((evaluateOnCommitReference == null) && (evaluateOnCommitResolvedObjectId == null)) {
throw new GitCommitIdExecutionException(
"Could not get " + evaluateOnCommit + " Ref, are you sure you have set the dotGitDirectory " +
"property of this plugin to a valid path (currently set to " + dotGitDirectory + ")?");
}
// more details parsed out below
revWalk = new RevWalk(git);
ObjectId headObjectId;
if (evaluateOnCommitReference != null) {
headObjectId = evaluateOnCommitReference.getObjectId();
if (perModuleVersions && moduleBaseDir != null) {
evalCommit = getCommitFromModuleDirectory(moduleBaseDir);
} else {
headObjectId = evaluateOnCommitResolvedObjectId;
}

if (headObjectId == null) {
throw new GitCommitIdExecutionException(
"Could not get " + evaluateOnCommit + " Ref, are you sure you have some " +
"commits in the dotGitDirectory (currently set to " + dotGitDirectory + ")?");
evalCommit = getCommitFromRef();
}
evalCommit = revWalk.parseCommit(headObjectId);
revWalk.markStart(evalCommit);
} catch (GitCommitIdExecutionException e) {
throw e;
Expand All @@ -115,6 +99,61 @@ public void prepareGitToExtractMoreDetailedRepoInformation() throws GitCommitIdE
}
}

private RevCommit getCommitFromModuleDirectory(File moduleBaseDir) throws GitAPIException, GitCommitIdExecutionException {
//retrieve last commit in folder moduleBaseDir
try (Git gitInstance = new Git(git)) {
String relativePath = git.getDirectory().getParentFile().getAbsoluteFile().toPath().relativize(moduleBaseDir.getAbsoluteFile().toPath()).toString();
Iterator<RevCommit> iterator;
if (relativePath.trim().isEmpty()) {
// if the relative path is empty, we are in the root of the repository
iterator = gitInstance.log().call().iterator();
} else {
// otherwise, we need to specify the path to get commits for that specific directory
iterator = gitInstance.log()
.addPath(relativePath).call().iterator();
}
if (!iterator.hasNext()) {
throw new GitCommitIdExecutionException(
"Could not get commit from folder " + relativePath + " , are you sure you have some " +
"commits in the folder " + moduleBaseDir + "?");
}

RevCommit revCommit = iterator.next();
if (revCommit == null) {
throw new GitCommitIdExecutionException(
"Could not get commit from folder " + relativePath +
" , are you sure you have some commits in the folder " + moduleBaseDir + "?");
}

return revCommit;
}
}

private RevCommit getCommitFromRef() throws IOException, GitCommitIdExecutionException {
// more details parsed out below
Ref evaluateOnCommitReference = git.findRef(evaluateOnCommit);
ObjectId evaluateOnCommitResolvedObjectId = git.resolve(evaluateOnCommit);

if ((evaluateOnCommitReference == null) && (evaluateOnCommitResolvedObjectId == null)) {
throw new GitCommitIdExecutionException(
"Could not get " + evaluateOnCommit + " Ref, are you sure you have set the dotGitDirectory " +
"property of this plugin to a valid path (currently set to " + dotGitDirectory + ")?");
}
ObjectId headObjectId;
if (evaluateOnCommitReference != null) {
headObjectId = evaluateOnCommitReference.getObjectId();
} else {
headObjectId = evaluateOnCommitResolvedObjectId;
}

if (headObjectId == null) {
throw new GitCommitIdExecutionException(
"Could not get " + evaluateOnCommit + " Ref, are you sure you have some " +
"commits in the dotGitDirectory (currently set to " + dotGitDirectory + ")?");
}
return revWalk.parseCommit(headObjectId);
}

@Override
public String getBranchName() throws GitCommitIdExecutionException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,39 @@ public void verifyAllowedCharactersForEvaluateOnCommit() {
Assertions.assertFalse(p.matcher("&&cat /etc/passwd").matches());
}

@Test
public void shouldGiveCommitIdForEachFolderWhenPerModuleVersionsEnabled() throws Exception {
// given
File dotGitDirectory = createTmpDotGitDirectory(AvailableGitTestRepo.GIT_COMMIT_ID);

GitCommitIdPlugin.Callback cbSrc =
new GitCommitIdTestCallback()
.setDotGitDirectory(dotGitDirectory)
.setUseNativeGit(false)
.setPerModuleVersions(true)
.setModuleBaseDir(dotGitDirectory.getParentFile().toPath().resolve("src").toFile())
.build();
Properties propertiesSrcFolder = new Properties();

GitCommitIdPlugin.Callback cbSrcTest =
new GitCommitIdTestCallback()
.setDotGitDirectory(dotGitDirectory)
.setUseNativeGit(false)
.setPerModuleVersions(true)
.setModuleBaseDir(dotGitDirectory.getParentFile().toPath().resolve("src/test").toFile())
.build();
Properties propertiesSrcTestFolder = new Properties();

// when
GitCommitIdPlugin.runPlugin(cbSrc, propertiesSrcFolder);
GitCommitIdPlugin.runPlugin(cbSrcTest, propertiesSrcTestFolder);

// then
assertThat(propertiesSrcFolder).containsKey("git.commit.id");
assertThat(propertiesSrcTestFolder).containsKey("git.commit.id");
assertThat(propertiesSrcFolder.getProperty("git.commit.id")).isNotEqualTo(propertiesSrcTestFolder.getProperty("git.commit.id"));
}

private GitDescribeConfig createGitDescribeConfig(boolean forceLongFormat, int abbrev) {
GitDescribeConfig gitDescribeConfig = new GitDescribeConfig();
gitDescribeConfig.setTags(true);
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/pl/project13/core/GitCommitIdTestCallback.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ public class GitCommitIdTestCallback {
private Charset propertiesSourceCharset = StandardCharsets.UTF_8;
private boolean shouldPropertiesEscapeUnicode = false;
private boolean shouldFailOnNoGitDirectory = false;
private boolean perModuleVersions = false;
private File moduleBaseDir;

public GitCommitIdTestCallback() {
try {
Expand Down Expand Up @@ -200,6 +202,16 @@ public GitCommitIdTestCallback setShouldFailOnNoGitDirectory(boolean shouldFailO
return this;
}

public GitCommitIdTestCallback setPerModuleVersions(boolean perModuleVersions) {
this.perModuleVersions = perModuleVersions;
return this;
}

public GitCommitIdTestCallback setModuleBaseDir(File moduleBaseDir) {
this.moduleBaseDir = moduleBaseDir;
return this;
}

public GitCommitIdPlugin.Callback build() {
return new GitCommitIdPlugin.Callback() {
@Override
Expand Down Expand Up @@ -353,6 +365,16 @@ public boolean shouldPropertiesEscapeUnicode() {
public boolean shouldFailOnNoGitDirectory() {
return shouldFailOnNoGitDirectory;
}

@Override
public boolean getPerModuleVersions() {
return perModuleVersions;
}

@Override
public File getModuleBaseDir() {
return moduleBaseDir;
}
};
}

Expand Down