6 Commits

Author SHA1 Message Date
093d283977 Merge pull request 'feature: validate commits in reverse date-time order when MAX_COMMITS_TO_CHECK is used' (#12) from date-order into main
All checks were successful
Validate Trusted Timestamps Actions Demo / Validate (push) Successful in 54m17s
Reviewed-on: #12
Reviewed-by: Artur Neumann <artur@jankaritech.eu>
2025-06-04 03:16:25 +00:00
Phil Davis
d48097695b feature: validate commits in reverse date-time order when MAX_COMMITS_TO_CHECK is used
All checks were successful
Validate Trusted Timestamps Actions Demo / Validate (push) Successful in 28m9s
This ensures that the most recent commits are the ones that are validated.
2025-06-03 17:21:42 +05:45
1622c1244f Merge pull request 'fix: stop correctly when MAX_COMMITS_TO_CHECK is reached' (#10) from respect-MAX_COMMITS_TO_CHECK into main
All checks were successful
Validate Trusted Timestamps Actions Demo / Validate (push) Successful in 22m53s
Reviewed-on: #10
Reviewed-by: Artur Neumann <artur@jankaritech.eu>
2025-06-02 11:40:09 +00:00
Phil Davis
f712aa0822 chore: adjust comment about MAX_COMMITS_TO_CHECK
All checks were successful
Validate Trusted Timestamps Actions Demo / Validate (push) Successful in 14m39s
2025-06-02 15:32:48 +05:45
Phil Davis
8aba6e98d1 fix: stop correctly when MAX_COMMITS_TO_CHECK is reached
All checks were successful
Validate Trusted Timestamps Actions Demo / Validate (push) Successful in 11m40s
2025-06-02 14:32:23 +05:45
31e44f9b70 Merge pull request 'feature: limit the number of commits to be validated' (#9) from limit-num-commits-validated into main
All checks were successful
Validate Trusted Timestamps Actions Demo / Validate (push) Successful in 14m5s
Reviewed-on: #9
Reviewed-by: Artur Neumann <artur@jankaritech.eu>
2025-06-02 04:10:47 +00:00

View File

@@ -44,6 +44,8 @@ if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
declare -i MINVERSION=$TIMESTAMPING_VERSION
declare -i MAX_COMMITS_TO_CHECK=0
declare -A PROCESSED_COMMIT
declare -A COMMITS
declare -A COMMIT_TIMES
while [[ $# -gt 0 ]]; do
KEY="$1"
@@ -295,7 +297,7 @@ validate_commit() {
if [ $NUM_VALID -gt 0 ]; then
if [ $NUM_INVALID -gt 0 ]; then
echo_warning "Warning: While commit $COMMIT_HASH contains $NUM_VALID valid timestamp tokens and thus is considered proppely timestamped, it also contains $NUM_INVALID invalid timestamp tokens."
echo_warning "Warning: While commit $COMMIT_HASH contains $NUM_VALID valid timestamp tokens and thus is considered properly timestamped, it also contains $NUM_INVALID invalid timestamp tokens."
fi
DATE_STRING=$(date -d @"$EARLIEST_VALID_UNIX_TIME")
echo_info "Commit $COMMIT_HASH, which timestamps commit $PARENT_HASH at $DATE_STRING, contains $NUM_VALID valid timestamp tokens."
@@ -311,6 +313,13 @@ validate_commit() {
# param1: commit hash
# returns: 0 if the validation of the commit and all its ancestors succeeded
validate_commit_and_parents() {
# If MAX_COMMITS_TO_CHECK is zero (or a negative number) then that is understood as "infinity".
# So finish if we have reached the limit, and if the limit is not "infinity".
NUM_COMMITS_CHECKED=${#PROCESSED_COMMIT[@]}
if [[ ${NUM_COMMITS_CHECKED} -ge ${MAX_COMMITS_TO_CHECK} ]] && [[ ${MAX_COMMITS_TO_CHECK} -ge 1 ]]; then
# enough commits have already been checked, so return early
return 0;
fi
local COMMIT_HASH="$1"
log "validate_commit_and_parents for $COMMIT_HASH"
@@ -318,19 +327,15 @@ validate_commit_and_parents() {
if ! validate_commit "$COMMIT_HASH"; then
ALL_PASSED=false
fi
# If MAX_COMMITS_TO_CHECK is zero (or a negative number) then that is understood as "infinity".
# So perform the next commit check if we have not reached the limit, or if the limit is "infinity".
NUM_COMMITS_CHECKED=${#PROCESSED_COMMIT[@]}
if [[ ${NUM_COMMITS_CHECKED} -lt ${MAX_COMMITS_TO_CHECK} ]] || [[ ${MAX_COMMITS_TO_CHECK} -lt 1 ]]; then
local PARENTS=$(git cat-file -p "$COMMIT_HASH" | awk '/^$/{exit} /parent/ {print}' | sed 's/parent //')
#iterate over all parents of commit
if [ ! -z "$PARENTS" ]; then
while read PARENT_HASH; do
if ! validate_commit_and_parents "$PARENT_HASH"; then
ALL_PASSED=false
fi
done <<< $(printf "%s" "$PARENTS")
fi
local PARENTS=$(git cat-file -p "$COMMIT_HASH" | awk '/^$/{exit} /parent/ {print}' | sed 's/parent //')
#iterate over all parents of commit
if [ ! -z "$PARENTS" ]; then
while read PARENT_HASH; do
if ! validate_commit_and_parents "$PARENT_HASH"; then
ALL_PASSED=false
fi
done <<< $(printf "%s" "$PARENTS")
fi
if [ "$ALL_PASSED" = true ]; then
return 0
@@ -338,6 +343,64 @@ validate_commit_and_parents() {
return 1
}
# Recursive function to find all ancestors of commit
# param1: commit hash
# creates an array COMMITS, key is the commit hash, value is the commit time (Unix epoch seconds)
# the array contains all commits found in all paths from the passed-in commit hash back to the root commit of the repo
# the array is global so it can be accessed after the function returns
find_all_commits() {
local COMMIT_HASH="$1"
log "find_all_commits for $COMMIT_HASH"
# git show "ct" format returns the commit time as Unix epoch seconds
COMMIT_TIME=$(git show --no-patch --format=%ct "$COMMIT_HASH")
COMMITS[$COMMIT_HASH]="${COMMIT_TIME}"
local PARENTS=$(git cat-file -p "$COMMIT_HASH" | awk '/^$/{exit} /parent/ {print}' | sed 's/parent //')
# iterate over all parents of commit
if [ ! -z "$PARENTS" ]; then
while read PARENT_HASH; do
if [[ ${COMMITS[$PARENT_HASH]} ]]; then
log "commit $PARENT_HASH has already been processed"
else
find_all_commits "$PARENT_HASH"
fi
done <<< $(printf "%s" "$PARENTS")
fi
}
# Validate the commits in the COMMITS array, up to MAX_COMMITS_TO_CHECK
# returns: 0 if the validation of the commits succeeded
validate_commits() {
ALL_PASSED=true
# create an associative array with keys using the Unix epoch commit time and value the commit hash
# this array can be easily used to sort in (forward or reverse) order of time
for HASH in "${!COMMITS[@]}"; do
UNIX_EPOCH_TIME="${COMMITS[$HASH]}"
# two commits could have the exact same Unix epoch in seconds
# so make that unique by appending an "x" and the hash
UNIQUE_KEY="${UNIX_EPOCH_TIME}x${HASH}"
COMMIT_TIMES[$UNIQUE_KEY]="${HASH}"
done
# sort into reverse order
SORTED_KEYS=($(printf "%s\n" "${!COMMIT_TIMES[@]}" | sort -r))
# process the commits from latest time to oldest time
ALL_PASSED=true
for ENTRY in "${SORTED_KEYS[@]}"; do
COMMIT_HASH=${COMMIT_TIMES[${ENTRY}]}
log "${ENTRY} has value ${COMMIT_HASH}"
NUM_COMMITS_CHECKED=${#PROCESSED_COMMIT[@]}
if [[ ${NUM_COMMITS_CHECKED} -lt ${MAX_COMMITS_TO_CHECK} ]]; then
if ! validate_commit "$COMMIT_HASH"; then
ALL_PASSED=false
fi
fi
done
if [ "$ALL_PASSED" = true ]; then
return 0
fi
return 1
}
echo_info "Checking repository integrity..."
#check git repository integrity
if ! git fsck --full --strict --no-progress --no-dangling "$COMMIT_HASH"; then
@@ -349,10 +412,21 @@ echo ""
echo_info "Validating timestamps. This may take a while..."
echo ""
if validate_commit_and_parents "$COMMIT_HASH"; then
echo_success "Validation OK: All timestamped commits in the commit history of $COMMIT_HASH contain at least one valid timestamp."
exit 0
if [[ ${MAX_COMMITS_TO_CHECK} -ge 1 ]]; then
find_all_commits "$COMMIT_HASH"
if validate_commits; then
echo_success "Validation OK: ${NUM_COMMITS_CHECKED} timestamped commits in the commit history of $COMMIT_HASH contain at least one valid timestamp."
exit 0
else
echo_error "Validation Failed: There are timestamped commits in the commit history of $COMMIT_HASH which do not contain any valid timestamps."
exit 1
fi
else
echo_error "Validation Failed: There are timestamped commits in the commit history of $COMMIT_HASH which do not contain any valid timestamps."
exit 1
if validate_commit_and_parents "$COMMIT_HASH"; then
echo_success "Validation OK: All timestamped commits in the commit history of $COMMIT_HASH contain at least one valid timestamp."
exit 0
else
echo_error "Validation Failed: There are timestamped commits in the commit history of $COMMIT_HASH which do not contain any valid timestamps."
exit 1
fi
fi