diff --git a/Documentation/technical/repository-version.txt b/Documentation/technical/repository-version.txt index 3d7106d93d..00ad37986e 100644 --- a/Documentation/technical/repository-version.txt +++ b/Documentation/technical/repository-version.txt @@ -79,3 +79,10 @@ The defined extensions are: This extension does not change git's behavior at all. It is useful only for testing format-1 compatibility. + +`preciousObjects` +~~~~~~~~~~~~~~~~~ + +When the config key `extensions.preciousObjects` is set to `true`, +objects in the repository MUST NOT be deleted (e.g., by `git-prune` or +`git repack -d`). diff --git a/builtin/gc.c b/builtin/gc.c index 36fe33300f..8b8dc6b610 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -352,15 +352,17 @@ int cmd_gc(int argc, const char **argv, const char *prefix) if (gc_before_repack()) return -1; - if (run_command_v_opt(repack.argv, RUN_GIT_CMD)) - return error(FAILED_RUN, repack.argv[0]); + if (!repository_format_precious_objects) { + if (run_command_v_opt(repack.argv, RUN_GIT_CMD)) + return error(FAILED_RUN, repack.argv[0]); - if (prune_expire) { - argv_array_push(&prune, prune_expire); - if (quiet) - argv_array_push(&prune, "--no-progress"); - if (run_command_v_opt(prune.argv, RUN_GIT_CMD)) - return error(FAILED_RUN, prune.argv[0]); + if (prune_expire) { + argv_array_push(&prune, prune_expire); + if (quiet) + argv_array_push(&prune, "--no-progress"); + if (run_command_v_opt(prune.argv, RUN_GIT_CMD)) + return error(FAILED_RUN, prune.argv[0]); + } } if (prune_worktrees_expire) { diff --git a/builtin/prune.c b/builtin/prune.c index 0c73246c72..6a58e75108 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -218,6 +218,9 @@ int cmd_prune(int argc, const char **argv, const char *prefix) return 0; } + if (repository_format_precious_objects) + die(_("cannot prune in a precious-objects repo")); + while (argc--) { unsigned char sha1[20]; const char *name = *argv++; diff --git a/builtin/repack.c b/builtin/repack.c index af7340c7ba..3beda2c65a 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -193,6 +193,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, builtin_repack_options, git_repack_usage, 0); + if (delete_redundant && repository_format_precious_objects) + die(_("cannot delete packs in a precious-objects repo")); + if (pack_kept_objects < 0) pack_kept_objects = write_bitmaps; diff --git a/cache.h b/cache.h index 996584c1ce..b1bc401055 100644 --- a/cache.h +++ b/cache.h @@ -694,6 +694,7 @@ extern int grafts_replace_parents; #define GIT_REPO_VERSION 0 #define GIT_REPO_VERSION_READ 1 extern int repository_format_version; +extern int repository_format_precious_objects; extern int check_repository_format(void); #define MTIME_CHANGED 0x0001 diff --git a/environment.c b/environment.c index 61c685b8d9..da66e829d1 100644 --- a/environment.c +++ b/environment.c @@ -26,6 +26,7 @@ int warn_ambiguous_refs = 1; int warn_on_object_refname_ambiguity = 1; int ref_paranoia = -1; int repository_format_version; +int repository_format_precious_objects; const char *git_commit_encoding; const char *git_log_output_encoding; int shared_repository = PERM_UMASK; diff --git a/setup.c b/setup.c index 0d5384683c..8b8dca9fd2 100644 --- a/setup.c +++ b/setup.c @@ -367,6 +367,8 @@ static int check_repo_format(const char *var, const char *value, void *cb) */ if (!strcmp(ext, "noop")) ; + else if (!strcmp(ext, "preciousobjects")) + repository_format_precious_objects = git_config_bool(var, value); else string_list_append(&unknown_extensions, ext); } diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh index 8dd6fd7baa..9bcd34969f 100755 --- a/t/t1302-repo-version.sh +++ b/t/t1302-repo-version.sh @@ -105,4 +105,26 @@ abort 1 no-such-extension allow 0 no-such-extension EOF +test_expect_success 'precious-objects allowed' ' + mkconfig 1 preciousObjects >.git/config && + check_allow +' + +test_expect_success 'precious-objects blocks destructive repack' ' + test_must_fail git repack -ad +' + +test_expect_success 'other repacks are OK' ' + test_commit foo && + git repack +' + +test_expect_success 'precious-objects blocks prune' ' + test_must_fail git prune +' + +test_expect_success 'gc runs without complaint' ' + git gc +' + test_done