Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit ee34a2b

Browse files
peffgitster
authored andcommitted
repack: add repack.packKeptObjects config var
The git-repack command always passes `--honor-pack-keep` to pack-objects. This has traditionally been a good thing, as we do not want to duplicate those objects in a new pack, and we are not going to delete the old pack. However, when bitmaps are in use, it is important for a full repack to include all reachable objects, even if they may be duplicated in a .keep pack. Otherwise, we cannot generate the bitmaps, as the on-disk format requires the set of objects in the pack to be fully closed. Even if the repository does not generally have .keep files, a simultaneous push could cause a race condition in which a .keep file exists at the moment of a repack. The repack may try to include those objects in one of two situations: 1. The pushed .keep pack contains objects that were already in the repository (e.g., blobs due to a revert of an old commit). 2. Receive-pack updates the refs, making the objects reachable, but before it removes the .keep file, the repack runs. In either case, we may prefer to duplicate some objects in the new, full pack, and let the next repack (after the .keep file is cleaned up) take care of removing them. This patch introduces both a command-line and config option to disable the `--honor-pack-keep` option. By default, it is triggered when pack.writeBitmaps (or `--write-bitmap-index` is turned on), but specifying it explicitly can override the behavior (e.g., in cases where you prefer .keep files to bitmaps, but only when they are present). Note that this option just disables the pack-objects behavior. We still leave packs with a .keep in place, as we do not necessarily know that we have duplicated all of their objects. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 6b5b3a2 commit ee34a2b

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

Documentation/config.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,6 +2128,13 @@ repack.usedeltabaseoffset::
21282128
"false" and repack. Access from old Git versions over the
21292129
native protocol are unaffected by this option.
21302130

2131+
repack.packKeptObjects::
2132+
If set to true, makes `git repack` act as if
2133+
`--pack-kept-objects` was passed. See linkgit:git-repack[1] for
2134+
details. Defaults to `false` normally, but `true` if a bitmap
2135+
index is being written (either via `--write-bitmap-index` or
2136+
`pack.writeBitmaps`).
2137+
21312138
rerere.autoupdate::
21322139
When set to true, `git-rerere` updates the index with the
21332140
resulting contents after it cleanly resolves conflicts using

Documentation/git-repack.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,14 @@ other objects in that pack they already have locally.
117117
must be able to refer to all reachable objects. This option
118118
overrides the setting of `pack.writebitmaps`.
119119

120+
--pack-kept-objects::
121+
Include objects in `.keep` files when repacking. Note that we
122+
still do not delete `.keep` packs after `pack-objects` finishes.
123+
This means that we may duplicate objects, but this makes the
124+
option safe to use when there are concurrent pushes or fetches.
125+
This option is generally only useful if you are writing bitmaps
126+
with `-b` or `pack.writebitmaps`, as it ensures that the
127+
bitmapped packfile has the necessary objects.
120128

121129
Configuration
122130
-------------

builtin/repack.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "argv-array.h"
1010

1111
static int delta_base_offset = 1;
12+
static int pack_kept_objects = -1;
1213
static char *packdir, *packtmp;
1314

1415
static const char *const git_repack_usage[] = {
@@ -22,6 +23,10 @@ static int repack_config(const char *var, const char *value, void *cb)
2223
delta_base_offset = git_config_bool(var, value);
2324
return 0;
2425
}
26+
if (!strcmp(var, "repack.packkeptobjects")) {
27+
pack_kept_objects = git_config_bool(var, value);
28+
return 0;
29+
}
2530
return git_default_config(var, value, cb);
2631
}
2732

@@ -175,6 +180,8 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
175180
N_("limits the maximum delta depth")),
176181
OPT_INTEGER(0, "max-pack-size", &max_pack_size,
177182
N_("maximum size of each packfile")),
183+
OPT_BOOL(0, "pack-kept-objects", &pack_kept_objects,
184+
N_("repack objects in packs marked with .keep")),
178185
OPT_END()
179186
};
180187

@@ -183,14 +190,18 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
183190
argc = parse_options(argc, argv, prefix, builtin_repack_options,
184191
git_repack_usage, 0);
185192

193+
if (pack_kept_objects < 0)
194+
pack_kept_objects = write_bitmap;
195+
186196
packdir = mkpathdup("%s/pack", get_object_directory());
187197
packtmp = mkpathdup("%s/.tmp-%d-pack", packdir, (int)getpid());
188198

189199
sigchain_push_common(remove_pack_on_signal);
190200

191201
argv_array_push(&cmd_args, "pack-objects");
192202
argv_array_push(&cmd_args, "--keep-true-parents");
193-
argv_array_push(&cmd_args, "--honor-pack-keep");
203+
if (!pack_kept_objects)
204+
argv_array_push(&cmd_args, "--honor-pack-keep");
194205
argv_array_push(&cmd_args, "--non-empty");
195206
argv_array_push(&cmd_args, "--all");
196207
argv_array_push(&cmd_args, "--reflog");

t/t7700-repack.sh

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
2121
objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
2222
sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
2323
mv pack-* .git/objects/pack/ &&
24-
git repack -A -d -l &&
24+
git repack --no-pack-kept-objects -A -d -l &&
2525
git prune-packed &&
2626
for p in .git/objects/pack/*.idx; do
2727
idx=$(basename $p)
@@ -35,6 +35,22 @@ test_expect_success 'objects in packs marked .keep are not repacked' '
3535
test -z "$found_duplicate_object"
3636
'
3737

38+
test_expect_success 'writing bitmaps can duplicate .keep objects' '
39+
# build on $objsha1, $packsha1, and .keep state from previous
40+
git repack -Adl &&
41+
test_when_finished "found_duplicate_object=" &&
42+
for p in .git/objects/pack/*.idx; do
43+
idx=$(basename $p)
44+
test "pack-$packsha1.idx" = "$idx" && continue
45+
if git verify-pack -v $p | egrep "^$objsha1"; then
46+
found_duplicate_object=1
47+
echo "DUPLICATE OBJECT FOUND"
48+
break
49+
fi
50+
done &&
51+
test "$found_duplicate_object" = 1
52+
'
53+
3854
test_expect_success 'loose objects in alternate ODB are not repacked' '
3955
mkdir alt_objects &&
4056
echo `pwd`/alt_objects > .git/objects/info/alternates &&

0 commit comments

Comments
 (0)