1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2026-06-17 10:06:06 -05:00
Files
VeraCrypt/src/Build/Tools/source_date_epoch.sh
T
Mounir IDRASSI f77d0c0760 Build: replace fixed SOURCE_DATE_EPOCH fallback
Keep caller-provided SOURCE_DATE_EPOCH authoritative and derive the automatic default through a shared helper used by the Makefile, direct CMake/CPack packaging, and the deb packaging wrapper.

When repository metadata is available, use the HEAD commit timestamp without relying on git -C. Resolve the source root before probing Git so symlinked source paths still use the checkout HEAD. For source tarballs without .git, derive the fallback timestamp from the release date encoded in Common/Tcdefs.h instead of the stale 2020-01-01 constant.

Add TC_RELEASE_DATE_DAY and validate it together with TC_RELEASE_DATE_YEAR, TC_RELEASE_DATE_MONTH, and TC_STR_RELEASE_DATE. Abort when no valid timestamp can be derived.

For direct CMake invocation, initialize SOURCEPATH when the wrapper has not provided it, use the shared helper for derivation, validate the result, and export it for package targets. Also persist the configured epoch through CPACK_PROJECT_CONFIG_FILE so later standalone cpack --config runs export the same value before invoking package generators.

Document that automatic git-checkout builds and release-tarball builds intentionally use different epochs; release reproducers should build from the tarball or set SOURCE_DATE_EPOCH explicitly.
2026-06-05 23:51:51 +09:00

122 lines
4.1 KiB
Bash
Executable File

#!/bin/sh
#
# Derive SOURCE_DATE_EPOCH for VeraCrypt build and packaging paths.
# Precedence inside this helper is git HEAD, then the release date encoded in
# Common/Tcdefs.h. Callers remain responsible for honoring an explicit
# SOURCE_DATE_EPOCH before invoking this helper. The source root is resolved
# before probing Git so symlinked build paths still use the checkout HEAD,
# while release tarballs unpacked below unrelated repositories ignore the
# parent repository and fall back to Common/Tcdefs.h.
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <source-root>" >&2
exit 2
fi
SOURCE_ROOT_INPUT=${1%/}
if [ -z "$SOURCE_ROOT_INPUT" ]; then
SOURCE_ROOT_INPUT=/
fi
SOURCE_ROOT=$(cd "$SOURCE_ROOT_INPUT" 2>/dev/null && pwd -P) || {
echo "Error: $1 is not a readable directory" >&2
exit 1
}
TCDEFS_H="$SOURCE_ROOT/Common/Tcdefs.h"
GIT_WORKTREE=
GIT_SOURCE_PREFIX=
SOURCE_ROOT_BASENAME=${SOURCE_ROOT##*/}
if [ -e "$SOURCE_ROOT/.git" ]; then
GIT_WORKTREE="$SOURCE_ROOT"
elif [ -e "$SOURCE_ROOT/../.git" ]; then
GIT_WORKTREE=$(cd "$SOURCE_ROOT/.." 2>/dev/null && pwd -P)
GIT_SOURCE_PREFIX="$SOURCE_ROOT_BASENAME/"
fi
GIT_EPOCH=
if [ -n "$GIT_WORKTREE" ] &&
(cd "$GIT_WORKTREE" &&
git rev-parse --is-inside-work-tree >/dev/null 2>&1 &&
git ls-files --error-unmatch \
"${GIT_SOURCE_PREFIX}Common/Tcdefs.h" \
"${GIT_SOURCE_PREFIX}Build/Tools/source_date_epoch.sh" >/dev/null 2>&1); then
GIT_EPOCH=$(cd "$GIT_WORKTREE" && git log -1 --pretty=%ct 2>/dev/null)
fi
case "$GIT_EPOCH" in
''|*[!0-9]*)
;;
*)
printf '%s\n' "$GIT_EPOCH"
exit 0
;;
esac
if [ ! -r "$TCDEFS_H" ]; then
echo "Error: $TCDEFS_H is not readable" >&2
exit 1
fi
RELEASE_EPOCH=$(awk '
function leap(y) { return ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) }
function month_number(name) {
return (name == "January" ? 1 : name == "February" ? 2 : name == "March" ? 3 :
name == "April" ? 4 : name == "May" ? 5 : name == "June" ? 6 :
name == "July" ? 7 : name == "August" ? 8 : name == "September" ? 9 :
name == "October" ? 10 : name == "November" ? 11 : name == "December" ? 12 : 0);
}
function mdays(m, y) { return (m == 2 ? 28 + leap(y) : (m == 4 || m == 6 || m == 9 || m == 11 ? 30 : 31)) }
function epoch(y, m, d, days, i) {
days = 0;
for (i = 1970; i < y; i++) days += 365 + leap(i);
for (i = 1; i < m; i++) days += mdays(i, y);
days += d - 1;
return days * 86400;
}
function is_number(value) { return (value ~ /^[0-9]+$/) }
/^[[:space:]]*#define[[:space:]]+TC_STR_RELEASE_DATE[[:space:]]+L"/ {
date = $0;
sub(/^.*L"/, "", date);
sub(/".*$/, "", date);
split(date, parts, /[ ,]+/);
if (month_number(parts[1]) == 0 || !is_number(parts[2]) || !is_number(parts[3])) exit 1;
date_month = month_number(parts[1]);
date_day = parts[2] + 0;
date_year = parts[3] + 0;
seen_date = 1;
}
/^[[:space:]]*#define[[:space:]]+TC_RELEASE_DATE_YEAR[[:space:]]+/ {
if (!is_number($3)) exit 1;
year = $3 + 0;
seen_year = 1;
}
/^[[:space:]]*#define[[:space:]]+TC_RELEASE_DATE_MONTH[[:space:]]+/ {
if (!is_number($3)) exit 1;
month = $3 + 0;
seen_month = 1;
}
/^[[:space:]]*#define[[:space:]]+TC_RELEASE_DATE_DAY[[:space:]]+/ {
if (!is_number($3)) exit 1;
day = $3 + 0;
seen_day = 1;
}
END {
if (!seen_date || !seen_year || !seen_month || !seen_day) exit 1;
if (year < 1970 || month < 1 || month > 12 || day < 1 || day > mdays(month, year)) exit 1;
if (date_month != month || date_day != day || date_year != year) exit 1;
printf "%d", epoch(year, month, day);
}' "$TCDEFS_H") || {
echo "Error: unable to derive SOURCE_DATE_EPOCH from $TCDEFS_H" >&2
exit 1
}
case "$RELEASE_EPOCH" in
''|*[!0-9]*)
echo "Error: unable to derive SOURCE_DATE_EPOCH from $TCDEFS_H" >&2
exit 1
;;
esac
printf '%s\n' "$RELEASE_EPOCH"