summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-repack.txt3
-rw-r--r--builtin/pack-objects.c31
-rw-r--r--builtin/repack.c1
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh13
4 files changed, 47 insertions, 1 deletions
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index 68702eab19..b58b6b5972 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -138,7 +138,8 @@ other objects in that pack they already have locally.
--keep-unreachable::
When used with `-ad`, any unreachable objects from existing
packs will be appended to the end of the packfile instead of
- being removed.
+ being removed. In addition, any unreachable loose objects will
+ be packed (and their loose counterparts removed).
Configuration
-------------
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 8f5e358e22..a2f8cfdec0 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -44,6 +44,7 @@ static int non_empty;
static int reuse_delta = 1, reuse_object = 1;
static int keep_unreachable, unpack_unreachable, include_tag;
static unsigned long unpack_unreachable_expiration;
+static int pack_loose_unreachable;
static int local;
static int incremental;
static int ignore_packed_keep;
@@ -2378,6 +2379,32 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
free(in_pack.array);
}
+static int add_loose_object(const unsigned char *sha1, const char *path,
+ void *data)
+{
+ enum object_type type = sha1_object_info(sha1, NULL);
+
+ if (type < 0) {
+ warning("loose object at %s could not be examined", path);
+ return 0;
+ }
+
+ add_object_entry(sha1, type, "", 0);
+ return 0;
+}
+
+/*
+ * We actually don't even have to worry about reachability here.
+ * add_object_entry will weed out duplicates, so we just add every
+ * loose object we find.
+ */
+static void add_unreachable_loose_objects(void)
+{
+ for_each_loose_file_in_objdir(get_object_directory(),
+ add_loose_object,
+ NULL, NULL, NULL);
+}
+
static int has_sha1_pack_kept_or_nonlocal(const unsigned char *sha1)
{
static struct packed_git *last_found = (void *)1;
@@ -2547,6 +2574,8 @@ static void get_object_list(int ac, const char **av)
if (keep_unreachable)
add_objects_in_unpacked_packs(&revs);
+ if (pack_loose_unreachable)
+ add_unreachable_loose_objects();
if (unpack_unreachable)
loosen_unused_packed_objects(&revs);
@@ -2647,6 +2676,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
N_("include tag objects that refer to objects to be packed")),
OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
N_("keep unreachable objects")),
+ OPT_BOOL(0, "pack-loose-unreachable", &pack_loose_unreachable,
+ N_("pack loose unreachable objects")),
{ OPTION_CALLBACK, 0, "unpack-unreachable", NULL, N_("time"),
N_("unpack unreachable objects newer than <time>"),
PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
diff --git a/builtin/repack.c b/builtin/repack.c
index 573e66c1b4..f7b7409cb7 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -248,6 +248,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
"--unpack-unreachable");
} else if (keep_unreachable) {
argv_array_push(&cmd.args, "--keep-unreachable");
+ argv_array_push(&cmd.args, "--pack-loose-unreachable");
} else {
argv_array_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
}
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index f13df43299..987573c41f 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -137,4 +137,17 @@ test_expect_success 'repack -k keeps unreachable packed objects' '
test_must_fail git cat-file -p $sha1
'
+test_expect_success 'repack -k packs unreachable loose objects' '
+ # create loose unreachable object
+ sha1=$(echo would-be-deleted-loose | git hash-object -w --stdin) &&
+ objpath=.git/objects/$(echo $sha1 | sed "s,..,&/,") &&
+ test_path_is_file $objpath &&
+
+ # and confirm that the loose object goes away, but we can
+ # still access it (ergo, it is packed)
+ git repack -adk &&
+ test_path_is_missing $objpath &&
+ git cat-file -p $sha1
+'
+
test_done