Skip to content

Commit f424d1d

Browse files
committed
Ensure repository currency
To support students working on the lecture assignment, this commit does verify that the repository is current by checking for a specific git commit hash. If the hash is missing, users will be prompted to update their repository. Change-Id: Ib2d4a66620610998fe0b8315192d23293466241f
1 parent 0b8be2c commit f424d1d

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

qtest.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,6 +1173,108 @@ static void usage(char *cmd)
11731173
exit(0);
11741174
}
11751175

1176+
extern char **environ;
1177+
1178+
/* Returns true if the hash is exactly 40 hexadecimal characters. */
1179+
static inline bool is_valid_sha1(const char *hash)
1180+
{
1181+
size_t len = strlen(hash);
1182+
if (len != 40)
1183+
return false;
1184+
for (size_t i = 0; i < len; i++) {
1185+
char c = hash[i];
1186+
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
1187+
(c >= 'A' && c <= 'F'))) {
1188+
return false;
1189+
}
1190+
}
1191+
return true;
1192+
}
1193+
1194+
/* Checks if a specific SHA-1 commit exists in the git log. */
1195+
bool commit_exists(const char *commit_hash)
1196+
{
1197+
/* Verify the commit_hash is a valid SHA-1 hash */
1198+
if (!is_valid_sha1(commit_hash))
1199+
return false;
1200+
1201+
int pipefd[2];
1202+
if (pipe(pipefd) == -1) {
1203+
/* Error creating pipe */
1204+
perror("pipe");
1205+
return false;
1206+
}
1207+
1208+
posix_spawn_file_actions_t actions;
1209+
if (posix_spawn_file_actions_init(&actions) != 0) {
1210+
/* Error initializing spawn file actions */
1211+
perror("posix_spawn_file_actions_init");
1212+
close(pipefd[0]);
1213+
close(pipefd[1]);
1214+
return false;
1215+
}
1216+
1217+
/* Redirect child's stdout to the pipe's write end */
1218+
if (posix_spawn_file_actions_adddup2(&actions, pipefd[1], STDOUT_FILENO) !=
1219+
0) {
1220+
perror("posix_spawn_file_actions_adddup2");
1221+
posix_spawn_file_actions_destroy(&actions);
1222+
close(pipefd[0]);
1223+
close(pipefd[1]);
1224+
return false;
1225+
}
1226+
1227+
/* Close unused pipe ends in the child */
1228+
if (posix_spawn_file_actions_addclose(&actions, pipefd[0]) != 0 ||
1229+
posix_spawn_file_actions_addclose(&actions, pipefd[1]) != 0) {
1230+
perror("posix_spawn_file_actions_addclose");
1231+
posix_spawn_file_actions_destroy(&actions);
1232+
close(pipefd[0]);
1233+
close(pipefd[1]);
1234+
return false;
1235+
}
1236+
1237+
pid_t pid;
1238+
/* Use "--no-abbrev-commit" to ensure full SHA-1 hash is printed */
1239+
char *argv[] = {"git", "log", "--pretty=oneline", "--no-abbrev-commit",
1240+
NULL};
1241+
int spawn_ret = posix_spawnp(&pid, "git", &actions, NULL, argv, environ);
1242+
posix_spawn_file_actions_destroy(&actions);
1243+
if (spawn_ret != 0) {
1244+
/* Error spawning git process */
1245+
fprintf(stderr, "posix_spawnp failed: %s\n", strerror(spawn_ret));
1246+
close(pipefd[0]);
1247+
return false;
1248+
}
1249+
1250+
/* Parent process: close the write end of the pipe */
1251+
close(pipefd[1]);
1252+
1253+
FILE *stream = fdopen(pipefd[0], "r");
1254+
if (stream == NULL) {
1255+
/* Error converting file descriptor to stream */
1256+
perror("fdopen");
1257+
return false;
1258+
}
1259+
1260+
bool found = false;
1261+
char buffer[1024];
1262+
while (fgets(buffer, sizeof(buffer), stream)) {
1263+
/* Compare the first 40 characters of each line with commit_hash */
1264+
if (strncmp(buffer, commit_hash, 40) == 0) {
1265+
found = true;
1266+
break;
1267+
}
1268+
}
1269+
fclose(stream);
1270+
1271+
/* Wait for the child process to finish */
1272+
int status;
1273+
waitpid(pid, &status, 0);
1274+
1275+
return found;
1276+
}
1277+
11761278
#define GIT_HOOK ".git/hooks/"
11771279
static bool sanity_check()
11781280
{
@@ -1202,6 +1304,13 @@ static bool sanity_check()
12021304
}
12031305
return false;
12041306
}
1307+
#define COPYRIGHT_COMMIT_SHA1 "50c5ac53d31adf6baac4f8d3db6b3ce2215fee40"
1308+
if (!commit_exists(COPYRIGHT_COMMIT_SHA1)) {
1309+
fprintf(stderr,
1310+
"FATAL: The repository is outdated. Please update properly.\n");
1311+
return false;
1312+
}
1313+
12051314
return true;
12061315
}
12071316

0 commit comments

Comments
 (0)