Skip to content

Commit ca11b21

Browse files
Nicolas Pitregitster
authored andcommitted
let pack-objects do the writing of unreachable objects as loose objects
Commit ccc1297 changed the behavior of 'git repack -A' so unreachable objects are stored as loose objects. However it did so in a naive and inn efficient way by making packs about to be deleted inaccessible and feeding their content through 'git unpack-objects'. While this works, there are major flaws with this approach: - It is unacceptably sloooooooooooooow. In the Linux kernel repository with no actual unreachable objects, doing 'git repack -A -d' before: real 2m33.220s user 2m21.675s sys 0m3.510s And with this change: real 0m36.849s user 0m24.365s sys 0m1.950s For reference, here's the timing for 'git repack -a -d': real 0m35.816s user 0m22.571s sys 0m2.011s This is explained by the fact that 'git unpack-objects' was used to unpack _every_ objects even if (almost) 100% of them were thrown away. - There is a black out period. Between the removal of the .idx file for the redundant pack and the completion of its unpacking, the unreachable objects become completely unaccessible. This is not a big issue as we're talking about unreachable objects, but some consistency is always good. - There is no way to easily set a sensible mtime for the newly created unreachable loose objects. So, while having a command called "pack-objects" to perform object unpacking looks really odd, this is probably the best compromize to be able to solve the above issues in an efficient way. Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent bbac731 commit ca11b21

File tree

2 files changed

+45
-17
lines changed

2 files changed

+45
-17
lines changed

builtin-pack-objects.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ git-pack-objects [{ -q | --progress | --all-progress }] \n\
2828
[--window=N] [--window-memory=N] [--depth=N] \n\
2929
[--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
3030
[--threads=N] [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\
31-
[--stdout | base-name] [--include-tag] [--keep-unreachable] \n\
31+
[--stdout | base-name] [--include-tag] \n\
32+
[--keep-unreachable | --unpack-unreachable] \n\
3233
[<ref-list | <object-list]";
3334

3435
struct object_entry {
@@ -65,7 +66,7 @@ static struct pack_idx_entry **written_list;
6566
static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
6667

6768
static int non_empty;
68-
static int no_reuse_delta, no_reuse_object, keep_unreachable, include_tag;
69+
static int no_reuse_delta, no_reuse_object, keep_unreachable, unpack_unreachable, include_tag;
6970
static int local;
7071
static int incremental;
7172
static int allow_ofs_delta;
@@ -1905,6 +1906,32 @@ static void add_objects_in_unpacked_packs(struct rev_info *revs)
19051906
free(in_pack.array);
19061907
}
19071908

1909+
static void loosen_unused_packed_objects(struct rev_info *revs)
1910+
{
1911+
struct packed_git *p;
1912+
uint32_t i;
1913+
const unsigned char *sha1;
1914+
1915+
for (p = packed_git; p; p = p->next) {
1916+
for (i = 0; i < revs->num_ignore_packed; i++) {
1917+
if (matches_pack_name(p, revs->ignore_packed[i]))
1918+
break;
1919+
}
1920+
if (revs->num_ignore_packed <= i)
1921+
continue;
1922+
1923+
if (open_pack_index(p))
1924+
die("cannot open pack index");
1925+
1926+
for (i = 0; i < p->num_objects; i++) {
1927+
sha1 = nth_packed_object_sha1(p, i);
1928+
if (!locate_object_entry(sha1))
1929+
if (force_object_loose(sha1, p->mtime))
1930+
die("unable to force loose object");
1931+
}
1932+
}
1933+
}
1934+
19081935
static void get_object_list(int ac, const char **av)
19091936
{
19101937
struct rev_info revs;
@@ -1939,6 +1966,8 @@ static void get_object_list(int ac, const char **av)
19391966

19401967
if (keep_unreachable)
19411968
add_objects_in_unpacked_packs(&revs);
1969+
if (unpack_unreachable)
1970+
loosen_unused_packed_objects(&revs);
19421971
}
19431972

19441973
static int adjust_perm(const char *path, mode_t mode)
@@ -2073,6 +2102,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
20732102
keep_unreachable = 1;
20742103
continue;
20752104
}
2105+
if (!strcmp("--unpack-unreachable", arg)) {
2106+
unpack_unreachable = 1;
2107+
continue;
2108+
}
20762109
if (!strcmp("--include-tag", arg)) {
20772110
include_tag = 1;
20782111
continue;
@@ -2138,6 +2171,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
21382171
if (!pack_to_stdout && thin)
21392172
die("--thin cannot be used to build an indexable pack.");
21402173

2174+
if (keep_unreachable && unpack_unreachable)
2175+
die("--keep-unreachable and --unpack-unreachable are incompatible.");
2176+
21412177
#ifdef THREADED_DELTA_SEARCH
21422178
if (!delta_search_threads) /* --threads=0 means autodetect */
21432179
delta_search_threads = online_cpus();

git-repack.sh

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ OPTIONS_SPEC="\
88
git-repack [options]
99
--
1010
a pack everything in a single pack
11-
A same as -a, and keep unreachable objects too
11+
A same as -a, and turn unreachable objects loose
1212
d remove redundant packs, and run git-prune-packed
1313
f pass --no-reuse-delta to git-pack-objects
1414
q,quiet be quiet
@@ -22,15 +22,15 @@ max-pack-size= maximum size of each packfile
2222
SUBDIRECTORY_OK='Yes'
2323
. git-sh-setup
2424

25-
no_update_info= all_into_one= remove_redundant= keep_unreachable=
25+
no_update_info= all_into_one= remove_redundant= unpack_unreachable=
2626
local= quiet= no_reuse= extra=
2727
while test $# != 0
2828
do
2929
case "$1" in
3030
-n) no_update_info=t ;;
3131
-a) all_into_one=t ;;
3232
-A) all_into_one=t
33-
keep_unreachable=t ;;
33+
unpack_unreachable=--unpack-unreachable ;;
3434
-d) remove_redundant=t ;;
3535
-q) quiet=-q ;;
3636
-f) no_reuse=--no-reuse-object ;;
@@ -78,6 +78,9 @@ case ",$all_into_one," in
7878
if test -z "$args"
7979
then
8080
args='--unpacked --incremental'
81+
elif test -n "$unpack_unreachable"
82+
then
83+
args="$args $unpack_unreachable"
8184
fi
8285
;;
8386
esac
@@ -127,18 +130,7 @@ then
127130
do
128131
case " $fullbases " in
129132
*" $e "*) ;;
130-
*)
131-
rm -f "$e.idx" "$e.keep"
132-
if test -n "$keep_unreachable" &&
133-
test -f "$e.pack"
134-
then
135-
git unpack-objects < "$e.pack" || {
136-
echo >&2 "Failed unpacking unreachable objects from redundant pack file $e.pack"
137-
exit 1
138-
}
139-
fi
140-
rm -f "$e.pack"
141-
;;
133+
*) rm -f "$e.pack" "$e.idx" "$e.keep" ;;
142134
esac
143135
done
144136
)

0 commit comments

Comments
 (0)