Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ test-*.html

# Configuration.java is auto-generated at build time from Configuration.java.in.
# It is NOT tracked by git to avoid constant rebase conflicts on the injected
# git hash / date / build timestamp. The build (Gradle / Maven) recreates it
# automatically from the template on a fresh clone.
# git hash / date / build timestamp. The build (Gradle / Maven) regenerates it
# from the template before compilation.
# To capture a specific build's version info: git add -f <path>/Configuration.java
src/main/java/org/perlonjava/core/Configuration.java

Expand Down
37 changes: 17 additions & 20 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -92,32 +92,31 @@ cyclonedxBom {
//
// Configuration.java is NOT tracked by git (it is listed in .gitignore).
// The canonical template is Configuration.java.in, which is tracked and contains
// placeholder values. This task copies the template to Configuration.java when
// the file is absent (e.g. after a fresh clone) and then patches in the real
// git hash, commit date, and build timestamp.
// placeholder values. Always regenerate from that template so version and other
// configuration changes cannot leave a stale generated source in an existing
// checkout, then patch in the real git hash, commit date, and build timestamp.
def configFilePath = layout.projectDirectory.file('src/main/java/org/perlonjava/core/Configuration.java')
def configTemplPath = layout.projectDirectory.file('src/main/java/org/perlonjava/core/Configuration.java.in')

tasks.register('injectGitInfo') {
description = 'Copies Configuration.java.in → Configuration.java (if needed) and injects git info'
description = 'Regenerates Configuration.java from its template and injects build metadata'
group = 'build'

// Declare inputs/outputs for configuration cache compatibility
def configFile = configFilePath.asFile
def templateFile = configTemplPath.asFile

inputs.file(configTemplPath)
outputs.file(configFilePath)
// The build timestamp and current git revision are dynamic inputs.
outputs.upToDateWhen { false }

doLast {
// If Configuration.java is absent (fresh clone, gitignored), recreate it
// from the committed template so the compiler has a valid source file.
if (!configFile.exists()) {
if (templateFile.exists()) {
configFile.text = templateFile.text
logger.lifecycle("Created Configuration.java from template")
} else {
logger.warn("Neither Configuration.java nor Configuration.java.in found; skipping git info injection")
return
}
if (!templateFile.exists()) {
throw new GradleException("Configuration template not found: ${templateFile}")
}

// Never carry configuration values forward from a previous build.
def content = templateFile.text

// Get git commit info using Runtime.exec
def gitCommitId = 'dev'
Expand All @@ -141,8 +140,6 @@ tasks.register('injectGitInfo') {

// Only update if we got valid values
if (gitCommitId && gitCommitId != 'dev') {
def content = configFile.text

// Use safe pattern matching for quoted string values
content = content.replaceAll(
/(gitCommitId\s*=\s*)"[^"]*"/,
Expand All @@ -162,10 +159,10 @@ tasks.register('injectGitInfo') {
/(buildTimestamp\s*=\s*)"[^"]*"/,
"\$1\"${buildTimestamp}\""
)

configFile.text = content
logger.lifecycle("Injected git info: ${gitCommitId} (${gitCommitDate})")
}

configFile.text = content
logger.lifecycle("Regenerated Configuration.java and injected git info: ${gitCommitId} (${gitCommitDate})")
}
}

Expand Down
27 changes: 15 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -365,22 +365,25 @@
<arguments>
<argument>-c</argument>
<argument><![CDATA[
set -e
CONFIG_FILE="src/main/java/org/perlonjava/core/Configuration.java"
TEMPLATE_FILE="src/main/java/org/perlonjava/core/Configuration.java.in"
# Configuration.java is gitignored; recreate from template on a fresh clone.
if [ ! -f "$CONFIG_FILE" ] && [ -f "$TEMPLATE_FILE" ]; then
cp "$TEMPLATE_FILE" "$CONFIG_FILE"
echo "Created Configuration.java from template"
# Configuration.java is gitignored; always regenerate it so an existing
# checkout cannot retain stale version or configuration values.
if [ ! -f "$TEMPLATE_FILE" ]; then
echo "Configuration template not found: $TEMPLATE_FILE" >&2
exit 1
fi
if [ -f "$CONFIG_FILE" ]; then
GIT_COMMIT_ID=$(git rev-parse --short HEAD 2>/dev/null || echo "dev")
GIT_COMMIT_DATE=$(git log -1 --format=%cs HEAD 2>/dev/null || echo "unknown")
if [ "$GIT_COMMIT_ID" != "dev" ]; then
perl -i -pe "s/(gitCommitId\\s*=\\s*)\"[^\"]*\"/\$1\"$GIT_COMMIT_ID\"/" "$CONFIG_FILE"
perl -i -pe "s/(gitCommitDate\\s*=\\s*)\"[^\"]*\"/\$1\"$GIT_COMMIT_DATE\"/" "$CONFIG_FILE"
echo "Injected git info: $GIT_COMMIT_ID ($GIT_COMMIT_DATE)"
fi
cp "$TEMPLATE_FILE" "$CONFIG_FILE"
GIT_COMMIT_ID=$(git rev-parse --short HEAD 2>/dev/null || echo "dev")
GIT_COMMIT_DATE=$(git log -1 --format=%cs HEAD 2>/dev/null || echo "unknown")
BUILD_TIMESTAMP=$(LC_ALL=C date "+%b %e %Y %H:%M:%S")
if [ "$GIT_COMMIT_ID" != "dev" ]; then
perl -i -pe "s/(gitCommitId\\s*=\\s*)\"[^\"]*\"/\$1\"$GIT_COMMIT_ID\"/" "$CONFIG_FILE"
perl -i -pe "s/(gitCommitDate\\s*=\\s*)\"[^\"]*\"/\$1\"$GIT_COMMIT_DATE\"/" "$CONFIG_FILE"
perl -i -pe "s/(buildTimestamp\\s*=\\s*)\"[^\"]*\"/\$1\"$BUILD_TIMESTAMP\"/" "$CONFIG_FILE"
fi
echo "Regenerated Configuration.java and injected git info: $GIT_COMMIT_ID ($GIT_COMMIT_DATE)"
]]></argument>
</arguments>
</configuration>
Expand Down
61 changes: 30 additions & 31 deletions scripts/inject-git-info.ps1
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
# inject-git-info.ps1
# Injects git commit ID and date into Configuration.java for Windows builds.
# Configuration.java is gitignored; this script recreates it from
# Configuration.java.in when the file is absent (e.g. after a fresh clone).
# Regenerates Configuration.java and injects build metadata for Windows builds.
# Configuration.java is gitignored; always recreate it from the tracked template
# so an existing checkout cannot retain stale version or configuration values.

$ConfigFile = "src/main/java/org/perlonjava/core/Configuration.java"
$TemplateFile = "src/main/java/org/perlonjava/core/Configuration.java.in"

# Recreate from template if absent (fresh clone / gitignored)
if (-not (Test-Path $ConfigFile)) {
if (Test-Path $TemplateFile) {
Copy-Item $TemplateFile $ConfigFile
Write-Host "Created Configuration.java from template"
} else {
Write-Host "Neither Configuration.java nor Configuration.java.in found; skipping"
exit 0
}
if (-not (Test-Path $TemplateFile)) {
Write-Error "Configuration template not found: $TemplateFile"
exit 1
}

if (Test-Path $ConfigFile) {
try {
$GitCommitId = git rev-parse --short HEAD 2>$null
$GitCommitDate = git log -1 --format=%cs HEAD 2>$null

if ($GitCommitId -and $GitCommitId -ne "dev") {
$content = Get-Content $ConfigFile -Raw

# Replace gitCommitId value
$content = $content -replace '(gitCommitId\s*=\s*)"[^"]*"', ('$1"' + $GitCommitId + '"')

# Replace gitCommitDate value
$content = $content -replace '(gitCommitDate\s*=\s*)"[^"]*"', ('$1"' + $GitCommitDate + '"')

Set-Content $ConfigFile -Value $content -NoNewline
Write-Host "Injected git info: $GitCommitId ($GitCommitDate)"
}
} catch {
Write-Host "Git info injection skipped: $_"
Copy-Item $TemplateFile $ConfigFile -Force -ErrorAction Stop

try {
$GitCommitId = git rev-parse --short HEAD 2>$null
$GitCommitDate = git log -1 --format=%cs HEAD 2>$null

if ($GitCommitId -and $GitCommitId -ne "dev") {
$BuildTimestamp = (Get-Date).ToString(
"MMM dd yyyy HH:mm:ss",
[System.Globalization.CultureInfo]::InvariantCulture
) -replace '^(\w{3}) 0', '$1 '
$content = Get-Content $ConfigFile -Raw

$content = $content -replace '(gitCommitId\s*=\s*)"[^"]*"', ('$1"' + $GitCommitId + '"')
$content = $content -replace '(gitCommitDate\s*=\s*)"[^"]*"', ('$1"' + $GitCommitDate + '"')
$content = $content -replace '(buildTimestamp\s*=\s*)"[^"]*"', ('$1"' + $BuildTimestamp + '"')

Set-Content $ConfigFile -Value $content -NoNewline
}
} catch {
$GitCommitId = "dev"
$GitCommitDate = "unknown"
Write-Host "Git info injection skipped: $_"
}

Write-Host "Regenerated Configuration.java and injected git info: $GitCommitId ($GitCommitDate)"
2 changes: 1 addition & 1 deletion src/main/java/org/perlonjava/core/Configuration.java.in
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public final class Configuration {

/**
* Build timestamp in Perl 5 "Compiled at" format (e.g., "Apr 7 2026 11:20:00").
* Automatically populated by Gradle during build.
* Automatically populated by Gradle/Maven during build.
* Parsed by App::perlbrew and other tools via: perl -V | grep "Compiled at"
* DO NOT EDIT MANUALLY - this value is replaced at build time.
*/
Expand Down
Loading