Skip to content

Commit 74cd9ad

Browse files
gnodetcstamas
andauthored
feat(jgit): Add configurable timestamp formats with named patterns (#76)
This reverts commit 12bd034. feat(jgit): add configurable timestamp formats with named patterns - Add support for configurable date formats via nisse.source.jgit.dateFormat - Support named patterns: git (default), iso8601, iso8601-offset, custom - Add nisse.source.jgit.dateFormat.pattern for custom patterns - ISO-8601 format automatically converts to UTC (e.g., 2025-05-22T11:23:54Z) - Robust error handling with fallback to default format - Backward compatible - existing behavior unchanged - Add comprehensive test coverage for all format options - Add complete Git configuration documentation Closes: timestamp format configuration request * Dump dateValue * Fix UT --------- Co-authored-by: Tamas Cservenak <tamas@cservenak.net>
1 parent 0ea722a commit 74cd9ad

File tree

3 files changed

+348
-17
lines changed

3 files changed

+348
-17
lines changed

GIT_CONFIGURATION.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Git Configuration (JGit Source)
2+
3+
The JGit property source provides Git repository information and supports dynamic version generation based on Git tags and commits. This document covers all configuration options and features.
4+
5+
## Overview
6+
7+
The JGit source (`jgit`) extracts information from the Git repository and provides the following properties:
8+
9+
- `commit`: The SHA-1 hash of the latest commit
10+
- `date`: The commit date (configurable format)
11+
- `author`: The commit author information
12+
- `committer`: The commit committer information
13+
- `dynamicVersion`: Dynamically generated version based on Git tags (optional)
14+
15+
## Basic Properties
16+
17+
### Always Available Properties
18+
19+
| Property | Description | Example |
20+
|----------|-------------|---------|
21+
| `commit` | Latest commit SHA-1 hash | `a1b2c3d4e5f6789012345678901234567890abcd` |
22+
| `date` | Commit timestamp | `Mon May 27 18:20:45 2024 +0200` (default format) |
23+
| `author` | Commit author | `John Doe <john.doe@example.com>` |
24+
| `committer` | Commit committer | `John Doe <john.doe@example.com>` |
25+
26+
## Configuration Properties
27+
28+
### Date Format Configuration
29+
30+
#### `nisse.source.jgit.dateFormat`
31+
32+
Controls the timestamp format for the `date` property.
33+
34+
**Supported values:**
35+
36+
- **`git`** (default): Traditional Git format
37+
- Pattern: `EEE MMM dd HH:mm:ss yyyy Z`
38+
- Example: `Mon May 27 18:20:45 2024 +0200`
39+
40+
- **`iso8601`**: ISO-8601 format in UTC
41+
- Pattern: `yyyy-MM-dd'T'HH:mm:ss'Z'`
42+
- Example: `2024-05-27T16:20:45Z`
43+
- Note: Automatically converts to UTC timezone
44+
45+
- **`iso8601-offset`**: ISO-8601 format with timezone offset
46+
- Pattern: `yyyy-MM-dd'T'HH:mm:ssXXX`
47+
- Example: `2024-05-27T18:20:45+02:00`
48+
49+
- **`custom`**: Use custom pattern specified by `nisse.source.jgit.dateFormat.pattern`
50+
51+
#### `nisse.source.jgit.dateFormat.pattern`
52+
53+
Custom date format pattern when `dateFormat` is set to `custom`. Uses Java `DateTimeFormatter` syntax.
54+
55+
**Examples:**
56+
- `yyyy/MM/dd HH:mm``2024/05/27 18:20`
57+
- `dd-MM-yyyy``27-05-2024`
58+
- `HH:mm:ss``18:20:45`
59+
60+
### Dynamic Version Configuration
61+
62+
#### `nisse.source.jgit.dynamicVersion`
63+
64+
**Default:** `false`
65+
66+
Set to `true` to enable dynamic version generation. When enabled, adds the `dynamicVersion` property.
67+
68+
**Dynamic version logic:**
69+
1. Searches Git history for semantic version tags (e.g., `v1.2.3`, `1.2.3`)
70+
2. If current commit has a version tag, uses that version
71+
3. If current commit doesn't have a tag, increments patch version and adds build number
72+
4. Falls back to `0.0.1-{commitCount}` if no version tags found
73+
74+
#### `nisse.source.jgit.appendSnapshot`
75+
76+
**Default:** `true`
77+
78+
Controls whether to append `-SNAPSHOT` qualifier to dynamic versions when the current commit is not tagged.
79+
80+
**Examples:**
81+
- `true`: `1.2.4-5-SNAPSHOT` (5 commits since v1.2.3 tag)
82+
- `false`: `1.2.4-5` (no SNAPSHOT qualifier)
83+
84+
#### `nisse.source.jgit.useVersion`
85+
86+
Override dynamic version resolution with a specific version string.
87+
88+
**Example:** `nisse.source.jgit.useVersion=2.0.0-BETA`
89+
90+
## Version Tag Pattern
91+
92+
The JGit source recognizes semantic version tags matching the pattern:
93+
- `refs/tags/v?((\\d+\\.\\d+\\.\\d+)(.*))`
94+
- Supports optional `v` prefix: `v1.2.3` or `1.2.3`
95+
- Supports additional qualifiers: `1.2.3-alpha`, `v2.0.0-RC1`
96+
97+
## Usage Examples
98+
99+
### Maven Command Line
100+
101+
```bash
102+
# Enable dynamic versioning with ISO-8601 timestamps
103+
mvn compile -Dnisse.source.jgit.dynamicVersion=true -Dnisse.source.jgit.dateFormat=iso8601
104+
105+
# Use custom date format
106+
mvn compile -Dnisse.source.jgit.dateFormat=custom -Dnisse.source.jgit.dateFormat.pattern="yyyy/MM/dd HH:mm"
107+
108+
# Override version and disable SNAPSHOT
109+
mvn compile -Dnisse.source.jgit.useVersion=1.0.0 -Dnisse.source.jgit.appendSnapshot=false
110+
```
111+
112+
### Maven Properties
113+
114+
```xml
115+
<properties>
116+
<nisse.source.jgit.dynamicVersion>true</nisse.source.jgit.dynamicVersion>
117+
<nisse.source.jgit.dateFormat>iso8601</nisse.source.jgit.dateFormat>
118+
<nisse.source.jgit.appendSnapshot>false</nisse.source.jgit.appendSnapshot>
119+
</properties>
120+
```
121+
122+
### System Properties
123+
124+
```java
125+
System.setProperty("nisse.source.jgit.dynamicVersion", "true");
126+
System.setProperty("nisse.source.jgit.dateFormat", "iso8601");
127+
```
128+
129+
## Error Handling
130+
131+
- **Invalid date format**: Falls back to default `git` format with warning
132+
- **Invalid custom pattern**: Falls back to default `git` format with warning
133+
- **No Git repository**: Source is ignored (logged at debug level)
134+
- **Git errors**: Logged and may cause build failure depending on configuration
135+
136+
## Complete Example
137+
138+
```xml
139+
<properties>
140+
<!-- Enable all JGit features -->
141+
<nisse.source.jgit.dynamicVersion>true</nisse.source.jgit.dynamicVersion>
142+
<nisse.source.jgit.appendSnapshot>true</nisse.source.jgit.appendSnapshot>
143+
<nisse.source.jgit.dateFormat>iso8601</nisse.source.jgit.dateFormat>
144+
</properties>
145+
```
146+
147+
This configuration provides:
148+
- `nisse.jgit.commit`: Latest commit hash
149+
- `nisse.jgit.date`: ISO-8601 formatted timestamp in UTC
150+
- `nisse.jgit.author`: Commit author
151+
- `nisse.jgit.committer`: Commit committer
152+
- `nisse.jgit.dynamicVersion`: Semantic version with SNAPSHOT qualifier
153+
154+
## Integration with Maven
155+
156+
The JGit properties can be used in Maven builds:
157+
158+
```xml
159+
<version>${nisse.jgit.dynamicVersion}</version>
160+
161+
<properties>
162+
<build.timestamp>${nisse.jgit.date}</build.timestamp>
163+
<build.commit>${nisse.jgit.commit}</build.commit>
164+
</properties>
165+
```

sources/jgit-source/src/main/java/eu/maveniverse/maven/nisse/source/jgit/JGitPropertySource.java

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import eu.maveniverse.maven.nisse.core.NisseConfiguration;
1111
import eu.maveniverse.maven.nisse.core.PropertySource;
1212
import java.time.Instant;
13-
import java.time.ZoneId;
1413
import java.time.ZonedDateTime;
1514
import java.time.format.DateTimeFormatter;
1615
import java.util.Collections;
@@ -52,8 +51,6 @@ public class JGitPropertySource implements PropertySource {
5251

5352
private static final String JGIT_DATE = "date";
5453

55-
private static final String JGIT_DATE_ISO_8601 = "dateIso8601";
56-
5754
private static final String JGIT_AUTHOR = "author";
5855

5956
private static final String JGIT_COMMITTER = "committer";
@@ -83,6 +80,22 @@ public class JGitPropertySource implements PropertySource {
8380
*/
8481
private static final String JGIT_CONF_SYSTEM_PROPERTY_USE_VERSION = "nisse.source.jgit.useVersion";
8582

83+
/**
84+
* Configure the timestamp format for the date property. Supports named patterns:
85+
* - "git" (default): EEE MMM dd HH:mm:ss yyyy Z
86+
* - "iso8601": yyyy-MM-dd'T'HH:mm:ss'Z' (UTC)
87+
* - "iso8601-offset": yyyy-MM-dd'T'HH:mm:ssXXX (with timezone offset)
88+
* - "custom": use the pattern specified in nisse.source.jgit.dateFormat.pattern
89+
*/
90+
private static final String JGIT_CONF_SYSTEM_PROPERTY_DATE_FORMAT = "nisse.source.jgit.dateFormat";
91+
92+
/**
93+
* Custom date format pattern when dateFormat is set to "custom".
94+
*/
95+
private static final String JGIT_CONF_SYSTEM_PROPERTY_DATE_FORMAT_PATTERN = "nisse.source.jgit.dateFormat.pattern";
96+
97+
private static final String DEFAULT_DATE_FORMAT = "git";
98+
8699
/**
87100
* Pattern for standard semantic versions, with an optional {@code "v"} prefix.
88101
*/
@@ -115,20 +128,7 @@ public Map<String, String> getProperties(NisseConfiguration configuration) {
115128
RevCommit lastCommit = getLastCommit(repository);
116129

117130
result.put(JGIT_COMMIT, lastCommit.getName());
118-
Instant commitTime = Instant.ofEpochSecond(lastCommit.getCommitTime());
119-
result.put(
120-
JGIT_DATE,
121-
ZonedDateTime.ofInstant(
122-
commitTime,
123-
lastCommit
124-
.getAuthorIdent()
125-
.getTimeZone()
126-
.toZoneId())
127-
.format(DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy Z")));
128-
result.put(
129-
JGIT_DATE_ISO_8601,
130-
ZonedDateTime.ofInstant(commitTime, ZoneId.of("UTC"))
131-
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX")));
131+
result.put(JGIT_DATE, formatCommitDate(configuration, lastCommit));
132132
result.put(
133133
JGIT_COMMITTER,
134134
lastCommit.getCommitterIdent().toExternalString().split(">")[0] + ">");
@@ -154,6 +154,76 @@ private RevCommit getLastCommit(Repository repository) throws NoHeadException, G
154154
return Git.wrap(repository).log().setMaxCount(1).call().iterator().next();
155155
}
156156

157+
/**
158+
* Formats the commit date according to the configured format.
159+
*
160+
* @param configuration the Nisse configuration
161+
* @param commit the commit to format the date for
162+
* @return the formatted date string
163+
*/
164+
private String formatCommitDate(NisseConfiguration configuration, RevCommit commit) {
165+
DateTimeFormatter formatter = resolveDateTimeFormatter(configuration);
166+
String dateFormat = configuration
167+
.getConfiguration()
168+
.getOrDefault(JGIT_CONF_SYSTEM_PROPERTY_DATE_FORMAT, DEFAULT_DATE_FORMAT);
169+
170+
ZonedDateTime commitDateTime = ZonedDateTime.ofInstant(
171+
Instant.ofEpochSecond(commit.getCommitTime()),
172+
commit.getAuthorIdent().getTimeZone().toZoneId());
173+
174+
// For ISO-8601 format, convert to UTC
175+
if ("iso8601".equalsIgnoreCase(dateFormat)) {
176+
commitDateTime = commitDateTime.withZoneSameInstant(java.time.ZoneOffset.UTC);
177+
}
178+
179+
return commitDateTime.format(formatter);
180+
}
181+
182+
/**
183+
* Resolves the DateTimeFormatter based on the configuration.
184+
*
185+
* @param configuration the Nisse configuration
186+
* @return the configured DateTimeFormatter
187+
*/
188+
private DateTimeFormatter resolveDateTimeFormatter(NisseConfiguration configuration) {
189+
String dateFormat = configuration
190+
.getConfiguration()
191+
.getOrDefault(JGIT_CONF_SYSTEM_PROPERTY_DATE_FORMAT, DEFAULT_DATE_FORMAT);
192+
193+
switch (dateFormat.toLowerCase()) {
194+
case "git":
195+
return DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy Z");
196+
case "iso8601":
197+
return DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
198+
case "iso8601-offset":
199+
return DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
200+
case "custom":
201+
String customPattern =
202+
configuration.getConfiguration().get(JGIT_CONF_SYSTEM_PROPERTY_DATE_FORMAT_PATTERN);
203+
if (customPattern != null && !customPattern.trim().isEmpty()) {
204+
try {
205+
return DateTimeFormatter.ofPattern(customPattern);
206+
} catch (IllegalArgumentException e) {
207+
logger.warn(
208+
"Invalid custom date format pattern '{}', falling back to default 'git' format",
209+
customPattern,
210+
e);
211+
return DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy Z");
212+
}
213+
} else {
214+
logger.warn(
215+
"Custom date format specified but no pattern provided via '{}', falling back to default 'git' format",
216+
JGIT_CONF_SYSTEM_PROPERTY_DATE_FORMAT_PATTERN);
217+
return DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy Z");
218+
}
219+
default:
220+
logger.warn(
221+
"Unknown date format '{}', falling back to default 'git' format. Supported formats: git, iso8601, iso8601-offset, custom",
222+
dateFormat);
223+
return DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss yyyy Z");
224+
}
225+
}
226+
157227
public String resolveDynamicVersion(NisseConfiguration configuration, Repository repository) throws Exception {
158228
VersionInformation vi;
159229

0 commit comments

Comments
 (0)