@@ -1173,6 +1173,108 @@ static void usage(char *cmd)
1173
1173
exit (0 );
1174
1174
}
1175
1175
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
+
1176
1278
#define GIT_HOOK ".git/hooks/"
1177
1279
static bool sanity_check ()
1178
1280
{
@@ -1202,6 +1304,13 @@ static bool sanity_check()
1202
1304
}
1203
1305
return false;
1204
1306
}
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
+
1205
1314
return true;
1206
1315
}
1207
1316
0 commit comments