Skip to content

Commit 067fbd4

Browse files
peffgitster
authored andcommitted
introduce "preciousObjects" repository extension
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 00a09d5 commit 067fbd4

File tree

8 files changed

+50
-9
lines changed

8 files changed

+50
-9
lines changed

Documentation/technical/repository-version.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,10 @@ The defined extensions are:
7979

8080
This extension does not change git's behavior at all. It is useful only
8181
for testing format-1 compatibility.
82+
83+
`preciousObjects`
84+
~~~~~~~~~~~~~~~~~
85+
86+
When the config key `extensions.preciousObjects` is set to `true`,
87+
objects in the repository MUST NOT be deleted (e.g., by `git-prune` or
88+
`git repack -d`).

builtin/gc.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -352,15 +352,17 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
352352
if (gc_before_repack())
353353
return -1;
354354

355-
if (run_command_v_opt(repack.argv, RUN_GIT_CMD))
356-
return error(FAILED_RUN, repack.argv[0]);
357-
358-
if (prune_expire) {
359-
argv_array_push(&prune, prune_expire);
360-
if (quiet)
361-
argv_array_push(&prune, "--no-progress");
362-
if (run_command_v_opt(prune.argv, RUN_GIT_CMD))
363-
return error(FAILED_RUN, prune.argv[0]);
355+
if (!repository_format_precious_objects) {
356+
if (run_command_v_opt(repack.argv, RUN_GIT_CMD))
357+
return error(FAILED_RUN, repack.argv[0]);
358+
359+
if (prune_expire) {
360+
argv_array_push(&prune, prune_expire);
361+
if (quiet)
362+
argv_array_push(&prune, "--no-progress");
363+
if (run_command_v_opt(prune.argv, RUN_GIT_CMD))
364+
return error(FAILED_RUN, prune.argv[0]);
365+
}
364366
}
365367

366368
if (prune_worktrees_expire) {

builtin/prune.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
218218
return 0;
219219
}
220220

221+
if (repository_format_precious_objects)
222+
die(_("cannot prune in a precious-objects repo"));
223+
221224
while (argc--) {
222225
unsigned char sha1[20];
223226
const char *name = *argv++;

builtin/repack.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
193193
argc = parse_options(argc, argv, prefix, builtin_repack_options,
194194
git_repack_usage, 0);
195195

196+
if (delete_redundant && repository_format_precious_objects)
197+
die(_("cannot delete packs in a precious-objects repo"));
198+
196199
if (pack_kept_objects < 0)
197200
pack_kept_objects = write_bitmaps;
198201

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ extern int grafts_replace_parents;
694694
#define GIT_REPO_VERSION 0
695695
#define GIT_REPO_VERSION_READ 1
696696
extern int repository_format_version;
697+
extern int repository_format_precious_objects;
697698
extern int check_repository_format(void);
698699

699700
#define MTIME_CHANGED 0x0001

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int warn_ambiguous_refs = 1;
2626
int warn_on_object_refname_ambiguity = 1;
2727
int ref_paranoia = -1;
2828
int repository_format_version;
29+
int repository_format_precious_objects;
2930
const char *git_commit_encoding;
3031
const char *git_log_output_encoding;
3132
int shared_repository = PERM_UMASK;

setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ static int check_repo_format(const char *var, const char *value, void *cb)
367367
*/
368368
if (!strcmp(ext, "noop"))
369369
;
370+
else if (!strcmp(ext, "preciousobjects"))
371+
repository_format_precious_objects = git_config_bool(var, value);
370372
else
371373
string_list_append(&unknown_extensions, ext);
372374
}

t/t1302-repo-version.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,26 @@ abort 1 no-such-extension
105105
allow 0 no-such-extension
106106
EOF
107107

108+
test_expect_success 'precious-objects allowed' '
109+
mkconfig 1 preciousObjects >.git/config &&
110+
check_allow
111+
'
112+
113+
test_expect_success 'precious-objects blocks destructive repack' '
114+
test_must_fail git repack -ad
115+
'
116+
117+
test_expect_success 'other repacks are OK' '
118+
test_commit foo &&
119+
git repack
120+
'
121+
122+
test_expect_success 'precious-objects blocks prune' '
123+
test_must_fail git prune
124+
'
125+
126+
test_expect_success 'gc runs without complaint' '
127+
git gc
128+
'
129+
108130
test_done

0 commit comments

Comments
 (0)