Commit 9188bd7879dac13c9b727f55056edaa8ffd81b25

Stefan Sperling 2021-07-03T22:51:03

add support for the preciousObjects Git extension to 'gotadmin cleanup'

diff --git a/gotadmin/gotadmin.1 b/gotadmin/gotadmin.1
index 4852f9d..1290b70 100644
--- a/gotadmin/gotadmin.1
+++ b/gotadmin/gotadmin.1
@@ -238,6 +238,12 @@ will only purge corresponding objects once such references have been
 deleted with
 .Cm got ref -d .
 .Pp
+The
+.Dq preciousObjects
+Git extension is intended to prevent the removal of objects from a repository.
+.Cm gotadmin cleanup 
+will refuse to operate on repositories where this extension is active.
+.Pp
 The options for
 .Cm gotadmin cleanup
 are as follows:
diff --git a/gotadmin/gotadmin.c b/gotadmin/gotadmin.c
index 22ab038..3a8fe22 100644
--- a/gotadmin/gotadmin.c
+++ b/gotadmin/gotadmin.c
@@ -971,6 +971,8 @@ cmd_cleanup(int argc, char *argv[])
 	char scaled_before[FMT_SCALED_STRSIZE];
 	char scaled_after[FMT_SCALED_STRSIZE];
 	char scaled_diff[FMT_SCALED_STRSIZE];
+	char **extensions;
+	int nextensions, i;
 
 	while ((ch = getopt(argc, argv, "r:nq")) != -1) {
 		switch (ch) {
@@ -1015,6 +1017,17 @@ cmd_cleanup(int argc, char *argv[])
 	if (error)
 		goto done;
 
+	got_repo_get_gitconfig_extensions(&extensions, &nextensions,
+	    repo);
+	for (i = 0; i < nextensions; i++) {
+		if (strcasecmp(extensions[i], "preciousObjects") == 0) {
+			error = got_error_msg(GOT_ERR_GIT_REPO_EXT,
+			    "the preciousObjects Git extension is enabled; "
+			    "this implies that objects must not be deleted");
+			goto done;
+		}
+	}
+
 	memset(&cpa, 0, sizeof(cpa));
 	cpa.last_ncommits = -1;
 	cpa.last_npurged = -1;
diff --git a/include/got_repository.h b/include/got_repository.h
index 2584e7c..daa3c37 100644
--- a/include/got_repository.h
+++ b/include/got_repository.h
@@ -50,6 +50,10 @@ const char *got_repo_get_global_gitconfig_author_email(struct got_repository *);
 /* Obtain repository owner name if parsed from gitconfig, else NULL. */
 const char *got_repo_get_gitconfig_owner(struct got_repository *);
 
+/* Obtain the list of enabled Git extensions parsed from gitconfig. */
+void got_repo_get_gitconfig_extensions(char ***, int *,
+    struct got_repository *);
+
 /* Information about one remote repository. */
 struct got_remote_repo {
 	char *name;
diff --git a/lib/repository.c b/lib/repository.c
index a8727af..11cc9cb 100644
--- a/lib/repository.c
+++ b/lib/repository.c
@@ -112,6 +112,14 @@ got_repo_get_gitconfig_owner(struct got_repository *repo)
 	return repo->gitconfig_owner;
 }
 
+void
+got_repo_get_gitconfig_extensions(char ***extensions, int *nextensions,
+    struct got_repository *repo)
+{
+	*extensions = repo->extensions;
+	*nextensions = repo->nextensions;
+}
+
 int
 got_repo_is_bare(struct got_repository *repo)
 {
diff --git a/regress/cmdline/cleanup.sh b/regress/cmdline/cleanup.sh
index c3bf21f..b55cfe1 100755
--- a/regress/cmdline/cleanup.sh
+++ b/regress/cmdline/cleanup.sh
@@ -233,6 +233,35 @@ test_cleanup_redundant_loose_objects() {
 	test_done "$testroot" "$ret"
 }
 
+test_cleanup_precious_objects() {
+	local testroot=`test_init cleanup_precious_objects`
+
+	# enable Git's preciousObjects extension
+	(cd $testroot/repo && git config extensions.preciousObjects true)
+
+	# cleanup should now refuse to purge objects
+	gotadmin cleanup -q -r $testroot/repo > $testroot/stdout \
+		2> $testroot/stderr
+	ret="$?"
+	if [ "$ret" == "0" ]; then
+		echo "gotadmin cleanup succeeded unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	echo -n "gotadmin: the preciousObjects Git extension is enabled; " \
+		> $testroot/stderr.expected
+	echo "this implies that objects must not be deleted" \
+		>> $testroot/stderr.expected
+	cmp -s $testroot/stderr.expected $testroot/stderr
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stderr.expected $testroot/stderr
+	fi
+	test_done "$testroot" "$ret"
+}
+
 test_parseargs "$@"
 run_test test_cleanup_unreferenced_loose_objects
 run_test test_cleanup_redundant_loose_objects
+run_test test_cleanup_precious_objects