Compare commits
9 Commits
validate-e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 093d283977 | |||
|
|
d48097695b | ||
| 1622c1244f | |||
|
|
f712aa0822 | ||
|
|
8aba6e98d1 | ||
| 31e44f9b70 | |||
|
|
4437b66f67 | ||
|
|
aabd314dde | ||
| ac5e6a6a89 |
@@ -42,7 +42,10 @@ if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi
|
||||
. "$DIR/timestamping"
|
||||
|
||||
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"
|
||||
@@ -62,6 +65,16 @@ while [[ $# -gt 0 ]]; do
|
||||
shift # past argument
|
||||
shift # past value
|
||||
;;
|
||||
-max|--maxcommits)
|
||||
INTEGER_REGEX='^[0-9]+$'
|
||||
if ! [[ "$2" =~ $INTEGER_REGEX ]]; then
|
||||
echo_error "$KEY: expected positive integer"
|
||||
exit 1
|
||||
fi
|
||||
MAX_COMMITS_TO_CHECK="$2"
|
||||
shift # past argument
|
||||
shift # past value
|
||||
;;
|
||||
-v|--verbose)
|
||||
OUT_STREAM=/dev/stdout
|
||||
shift # past argument
|
||||
@@ -284,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."
|
||||
@@ -300,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"
|
||||
|
||||
@@ -307,6 +327,7 @@ validate_commit_and_parents() {
|
||||
if ! validate_commit "$COMMIT_HASH"; then
|
||||
ALL_PASSED=false
|
||||
fi
|
||||
NUM_COMMITS_CHECKED=${#PROCESSED_COMMIT[@]}
|
||||
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
|
||||
@@ -322,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
|
||||
@@ -333,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
|
||||
|
||||
Reference in New Issue
Block a user