introduce "preciousObjects" repository extension
authorJeff King <peff@peff.net>
Tue, 23 Jun 2015 10:54:11 +0000 (06:54 -0400)
committerJunio C Hamano <gitster@pobox.com>
Thu, 25 Jun 2015 00:09:35 +0000 (17:09 -0700)
If this extension is used in a repository, then no
operations should run which may drop objects from the object
storage. This can be useful if you are sharing that storage
with other repositories whose refs you cannot see.

For instance, if you do:

$ git clone -s parent child
$ git -C parent config extensions.preciousObjects true
$ git -C parent config core.repositoryformatversion 1

you now have additional safety when running git in the
parent repository. Prunes and repacks will bail with an
error, and `git gc` will skip those operations (it will
continue to pack refs and do other non-object operations).
Older versions of git, when run in the repository, will
fail on every operation.

Note that we do not set the preciousObjects extension by
default when doing a "clone -s", as doing so breaks
backwards compatibility. It is a decision the user should
make explicitly.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/technical/repository-version.txt
builtin/gc.c
builtin/prune.c
builtin/repack.c
cache.h
environment.c
setup.c
t/t1302-repo-version.sh
index 3d7106d93d6ffa42c16c4a9afcd3c76068e89978..00ad37986efdcebb440c95629acd16213028c239 100644 (file)
@@ -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`).
index 36fe33300f644fc9c7e5139b452a9703548ba2a2..8b8dc6b6100814e5e3169b4befaecea366bc92ad 100644 (file)
@@ -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 (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 (!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_worktrees_expire) {
index 0c73246c721b3307f0d68b4e58f7c684aebce2e9..6a58e75108c2f5dd9d6777fee92f6d948c89a13f 100644 (file)
@@ -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++;
index af7340c7bafbfbbf991f782139775e18b6ac570a..3beda2c65ab15f7ca5b6b2f6637249234a4e6c41 100644 (file)
@@ -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 996584c1ceaced7a8be6d03c684c94e9272fa1fe..b1bc40105507089836af9efba108fd3ca80eb0e3 100644 (file)
--- 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
index 61c685b8d93091666891f0091d5005fe62543fc2..da66e829d173142c3849d15306a9772b40aafff4 100644 (file)
@@ -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 0d5384683ce2e48268e3298dbff18daedabc9513..8b8dca9fd21570c8109d17ccfb848ca0e32f65b2 100644 (file)
--- 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);
        }
index 8dd6fd7baa61294afe41bd25b88a535c5f74a843..9bcd34969f56038d3933471bc32641a277d413ba 100755 (executable)
@@ -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