Skip to content

Commit 804a185

Browse files
committed
1 parent 246e87e commit 804a185

File tree

10 files changed

+460
-211
lines changed

10 files changed

+460
-211
lines changed

src/main/java/pl/project13/core/GitCommitIdPlugin.java

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import javax.annotation.Nullable;
2828
import java.io.File;
2929
import java.nio.charset.Charset;
30+
import java.nio.file.Path;
3031
import java.text.SimpleDateFormat;
3132
import java.util.*;
3233
import java.util.function.Supplier;
@@ -284,20 +285,14 @@ default Map<String, String> getSystemEnv() {
284285
boolean shouldFailOnNoGitDirectory();
285286

286287
/**
287-
* When set to {@code true}, the plugin will consider only commits affecting
288-
* the folder containing this module.
289-
*
290-
* When set to {@code false}, the plugin will consider all commits in the
291-
* repository.
288+
* When set to {@code true}, the plugin will only consider commits affecting
289+
* paths within the current project's base directory.
292290
*
293-
* @return Controls whether the plugin only considers commits in the current module's directory.
291+
* <p>This is useful for multi-module projects stored in a single git repository where you want
292+
+ properties like {@code git.commit.id.*} and {@code git.total.commit.count} to be based on the
293+
+ latest commit that touched this module, not the whole repository.
294294
*/
295-
boolean getPerModuleVersions();
296-
297-
/**
298-
* @return Base directory (folder) of the current module.
299-
*/
300-
File getModuleBaseDir();
295+
boolean isPerModuleVersions();
301296
}
302297

303298
protected static final Pattern allowedCharactersForEvaluateOnCommit = Pattern.compile("[a-zA-Z0-9\\_\\-\\^\\/\\.]+");
@@ -384,19 +379,9 @@ private static void loadGitDataWithNativeGit(
384379
@Nonnull File dotGitDirectory,
385380
@Nonnull Properties properties) throws GitCommitIdExecutionException {
386381
GitDataProvider nativeGitProvider = NativeGitProvider
387-
.on(dotGitDirectory, cb.getNativeGitTimeoutInMs(), cb.getLogInterface())
388-
.setPrefixDot(cb.getPrefixDot())
389-
.setAbbrevLength(cb.getAbbrevLength())
390-
.setDateFormat(cb.getDateFormat())
391-
.setDateFormatTimeZone(cb.getDateFormatTimeZone())
392-
.setGitDescribe(cb.getGitDescribe())
393-
.setCommitIdGenerationMode(cb.getCommitIdGenerationMode())
394-
.setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment())
395-
.setExcludeProperties(cb.getExcludeProperties())
396-
.setIncludeOnlyProperties(cb.getIncludeOnlyProperties())
397-
.setPerModuleVersions(cb.getPerModuleVersions())
398-
.setModuleBaseDir(cb.getModuleBaseDir())
399-
.setOffline(cb.isOffline());
382+
.on(dotGitDirectory, cb.getNativeGitTimeoutInMs(), cb.getLogInterface());
383+
384+
configureCommonProvider(nativeGitProvider, cb, dotGitDirectory);
400385

401386
nativeGitProvider.loadGitData(cb.getEvaluateOnCommit(), cb.getSystemEnv(), properties);
402387
}
@@ -406,7 +391,18 @@ private static void loadGitDataWithJGit(
406391
@Nonnull File dotGitDirectory,
407392
@Nonnull Properties properties) throws GitCommitIdExecutionException {
408393
GitDataProvider jGitProvider = JGitProvider
409-
.on(dotGitDirectory, cb.getLogInterface())
394+
.on(dotGitDirectory, cb.getLogInterface());
395+
396+
configureCommonProvider(jGitProvider, cb, dotGitDirectory);
397+
398+
jGitProvider.loadGitData(cb.getEvaluateOnCommit(), cb.getSystemEnv(), properties);
399+
}
400+
401+
private static void configureCommonProvider(
402+
@Nonnull GitDataProvider provider,
403+
@Nonnull Callback cb,
404+
@Nonnull File dotGitDirectory) {
405+
provider
410406
.setPrefixDot(cb.getPrefixDot())
411407
.setAbbrevLength(cb.getAbbrevLength())
412408
.setDateFormat(cb.getDateFormat())
@@ -416,10 +412,57 @@ private static void loadGitDataWithJGit(
416412
.setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment())
417413
.setExcludeProperties(cb.getExcludeProperties())
418414
.setIncludeOnlyProperties(cb.getIncludeOnlyProperties())
419-
.setPerModuleVersions(cb.getPerModuleVersions())
420-
.setModuleBaseDir(cb.getModuleBaseDir())
421-
.setOffline(cb.isOffline());
415+
.setOffline(cb.isOffline())
416+
.setPathFilter(
417+
cb.isPerModuleVersions()
418+
? resolveRelativeModulePath(cb, dotGitDirectory)
419+
: null);
420+
}
422421

423-
jGitProvider.loadGitData(cb.getEvaluateOnCommit(), cb.getSystemEnv(), properties);
422+
/**
423+
* Resolves the relative module path from repository root to project base directory.
424+
* This is used for per-module filtering to limit git operations to the current project.
425+
* Returns null if the project directory is not within the repository or if resolution fails.
426+
*/
427+
@Nullable
428+
private static String resolveRelativeModulePath(@Nonnull Callback cb, @Nonnull File dotGitDirectory) {
429+
try {
430+
// Determine repository work tree
431+
// If dotGitDirectory is named ".git", the work tree is its parent
432+
// Otherwise, dotGitDirectory might be the work tree itself (for bare repos or special cases)
433+
File repoWorkTree;
434+
if (dotGitDirectory.getName().equals(".git")) {
435+
repoWorkTree = dotGitDirectory.getParentFile();
436+
} else {
437+
repoWorkTree = dotGitDirectory;
438+
}
439+
440+
if (repoWorkTree == null || !repoWorkTree.exists()) {
441+
cb.getLogInterface().warn("Could not determine repository work tree from dotGitDirectory: " + dotGitDirectory);
442+
return null;
443+
}
444+
445+
Path repoRoot = repoWorkTree.toPath().toAbsolutePath().normalize();
446+
Path moduleDir = cb.getProjectBaseDir().toPath().toAbsolutePath().normalize();
447+
448+
if (!moduleDir.startsWith(repoRoot)) {
449+
cb.getLogInterface()
450+
.warn("Project directory is not within repository work tree. " +
451+
"Project: " + moduleDir + ", Repo: " + repoRoot + ". " +
452+
"Falling back to normal behavior.");
453+
return null;
454+
}
455+
456+
String relative = repoRoot.relativize(moduleDir).toString();
457+
if (relative.isEmpty()) {
458+
relative = ".";
459+
}
460+
return relative.replace(File.separatorChar, '/');
461+
} catch (Exception e) {
462+
cb.getLogInterface()
463+
.warn("Failed to resolve relative module path: " + e.getMessage() +
464+
". Falling back to normal behavior.");
465+
return null;
466+
}
424467
}
425468
}

src/main/java/pl/project13/core/GitDataProvider.java

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
import pl.project13.core.util.PropertyManager;
2525

2626
import javax.annotation.Nonnull;
27-
28-
import java.io.File;
2927
import java.net.URI;
3028
import java.net.URLEncoder;
3129
import java.nio.charset.StandardCharsets;
@@ -110,20 +108,6 @@ public abstract class GitDataProvider implements GitProvider {
110108
*/
111109
protected List<String> includeOnlyProperties;
112110

113-
/**
114-
* When set to {@code true}, the plugin will consider only commits affecting
115-
* the folder containing this module.
116-
*
117-
* When set to {@code false}, the plugin will consider all commits in the
118-
* repository.
119-
*/
120-
protected boolean perModuleVersions = false;
121-
122-
/**
123-
* The directory containing this project.
124-
*/
125-
protected File moduleBaseDir;
126-
127111
/**
128112
* When set to {@code true}, the plugin will not try to contact any remote repositories.
129113
* Any operations will only use the local state of the repo.
@@ -132,6 +116,12 @@ public abstract class GitDataProvider implements GitProvider {
132116
*/
133117
protected boolean offline;
134118

119+
/**
120+
* Optional path filter to limit certain computations (e.g. total commit count) to commits
121+
* affecting a specific path.
122+
*/
123+
protected String pathFilter;
124+
135125
/**
136126
* Constructor to encapsulates all references required to dertermine all git-data.
137127
* @param log logging provider which will be used to log events
@@ -259,27 +249,13 @@ public GitDataProvider setOffline(boolean offline) {
259249
}
260250

261251
/**
262-
* When set to {@code true}, the plugin will consider only commits affecting
263-
* the folder containing this module.
264-
*
265-
* When set to {@code false}, the plugin will consider all commits in the
266-
* repository.
267-
* @param perModuleVersions Only consider commits affecting the folder containing this module.
268-
* @return The {@code GitProvider} with the corresponding {@code perModuleVersions} flag set.
269-
*/
270-
public GitDataProvider setPerModuleVersions(boolean perModuleVersions) {
271-
this.perModuleVersions = perModuleVersions;
272-
return this;
273-
}
274-
275-
/**
276-
* Path to the module base directory.
252+
* Sets an optional path filter.
277253
*
278-
* @param moduleBaseDir The path to the directory containing this module.
279-
* @return The {@code GitProvider} with the corresponding {@code moduleBaseDir} set.
254+
* @param pathFilter path relative to repository root using forward slashes (git-style)
255+
* @return The {@code GitProvider} with the corresponding path filter set.
280256
*/
281-
public GitDataProvider setModuleBaseDir(File moduleBaseDir) {
282-
this.moduleBaseDir = moduleBaseDir;
257+
public GitDataProvider setPathFilter(String pathFilter) {
258+
this.pathFilter = pathFilter;
283259
return this;
284260
}
285261

0 commit comments

Comments
 (0)