diff --git a/qtest.c b/qtest.c index 6b6815bfc..8237aafa7 100644 --- a/qtest.c +++ b/qtest.c @@ -1252,7 +1252,7 @@ bool commit_exists(const char *commit_hash) close(pipefd[1]); FILE *stream = fdopen(pipefd[0], "r"); - if (stream == NULL) { + if (!stream) { /* Error converting file descriptor to stream */ perror("fdopen"); return false; @@ -1276,6 +1276,26 @@ bool commit_exists(const char *commit_hash) return found; } +static bool check_commitlog(void) +{ + pid_t pid; + int status; + char *script_path = "scripts/check-commitlog.sh"; + char *argv[] = {script_path, NULL}; + + int spawn_ret = posix_spawnp(&pid, script_path, NULL, NULL, argv, environ); + if (spawn_ret != 0) + return false; + + if (waitpid(pid, &status, 0) == -1) + return false; + + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + return false; + + return true; +} + #define GIT_HOOK ".git/hooks/" static bool sanity_check() { @@ -1314,6 +1334,14 @@ static bool sanity_check() "FATAL: The repository is outdated. Please update properly.\n"); return false; } + if (!check_commitlog()) { + fprintf(stderr, "FATAL: The git commit history is chaotic.\n"); + fprintf(stderr, + "Please install the required git hooks per the assignment " + "instructions and make your commits from the terminal " + "instead of using the GitHub web interface.\n"); + return false; + } } return true; diff --git a/scripts/check-commitlog.sh b/scripts/check-commitlog.sh new file mode 100755 index 000000000..e12589250 --- /dev/null +++ b/scripts/check-commitlog.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Check that every non-merge commit after the specified base commit has a commit +# message ending with a valid Change-Id line. A valid Change-Id line must be the +# last non-empty line of the commit message and follow the format: +# +# Change-Id: I +# +# Merge commits are excluded from this check. + +# Base commit from which to start checking. +BASE_COMMIT="0b8be2c15160c216e8b6ec82c99a000e81c0e429" + +# Get a list of non-merge commit hashes after BASE_COMMIT. +commits=$(git rev-list --no-merges "${BASE_COMMIT}"..HEAD) + +failed=0 + +for commit in $commits; do + # Retrieve the commit message for the given commit. + commit_msg=$(git log -1 --format=%B "${commit}") + + # Extract the last non-empty line from the commit message. + last_line=$(echo "$commit_msg" | awk 'NF {line=$0} END {print line}') + + # Check if the last line matches the expected Change-Id format. + if [[ ! $last_line =~ ^Change-Id:\ I[0-9a-fA-F]+$ ]]; then + subject=$(git log -1 --format=%s "${commit}") + short_hash=$(git rev-parse --short "${commit}") + echo "Commit ${short_hash} with subject '$subject' does not end with a valid Change-Id." + failed=1 + fi +done + +if [ $failed -ne 0 ]; then + echo + echo "Some commits are missing a valid Change-Id. Please amend the commit messages accordingly." + echo + exit 1 +fi + +exit 0 diff --git a/scripts/checksums b/scripts/checksums index 1180befdd..56f3b46b8 100644 --- a/scripts/checksums +++ b/scripts/checksums @@ -1,2 +1,3 @@ db6784ff3917888db4d1dceaa0570d99ed40e762 queue.h bfb6df45d64356868c86a7173455d39970bd0270 list.h +3bb0192cee08d165fd597a9f6fbb404533e28fcf scripts/check-commitlog.sh