Skip to content

Commit e37d0b8

Browse files
ttaylorrgitster
authored andcommitted
builtin/index-pack.c: write reverse indexes
Teach 'git index-pack' to optionally write and verify reverse index with '--[no-]rev-index', as well as respecting the 'pack.writeReverseIndex' configuration option. Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 84d5449 commit e37d0b8

File tree

3 files changed

+131
-8
lines changed

3 files changed

+131
-8
lines changed

Documentation/git-index-pack.txt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ git-index-pack - Build pack index file for an existing packed archive
99
SYNOPSIS
1010
--------
1111
[verse]
12-
'git index-pack' [-v] [-o <index-file>] <pack-file>
12+
'git index-pack' [-v] [-o <index-file>] [--[no-]rev-index] <pack-file>
1313
'git index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
14-
[<pack-file>]
14+
[--[no-]rev-index] [<pack-file>]
1515

1616

1717
DESCRIPTION
1818
-----------
1919
Reads a packed archive (.pack) from the specified file, and
20-
builds a pack index file (.idx) for it. The packed archive
21-
together with the pack index can then be placed in the
22-
objects/pack/ directory of a Git repository.
20+
builds a pack index file (.idx) for it. Optionally writes a
21+
reverse-index (.rev) for the specified pack. The packed
22+
archive together with the pack index can then be placed in
23+
the objects/pack/ directory of a Git repository.
2324

2425

2526
OPTIONS
@@ -35,6 +36,13 @@ OPTIONS
3536
fails if the name of packed archive does not end
3637
with .pack).
3738

39+
--[no-]rev-index::
40+
When this flag is provided, generate a reverse index
41+
(a `.rev` file) corresponding to the given pack. If
42+
`--verify` is given, ensure that the existing
43+
reverse index is correct. Takes precedence over
44+
`pack.writeReverseIndex`.
45+
3846
--stdin::
3947
When this flag is provided, the pack is read from stdin
4048
instead and a copy is then written to <pack-file>. If

builtin/index-pack.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "promisor-remote.h"
1818

1919
static const char index_pack_usage[] =
20-
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
20+
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
2121

2222
struct object_entry {
2323
struct pack_idx_entry idx;
@@ -1484,12 +1484,14 @@ static void write_special_file(const char *suffix, const char *msg,
14841484

14851485
static void final(const char *final_pack_name, const char *curr_pack_name,
14861486
const char *final_index_name, const char *curr_index_name,
1487+
const char *final_rev_index_name, const char *curr_rev_index_name,
14871488
const char *keep_msg, const char *promisor_msg,
14881489
unsigned char *hash)
14891490
{
14901491
const char *report = "pack";
14911492
struct strbuf pack_name = STRBUF_INIT;
14921493
struct strbuf index_name = STRBUF_INIT;
1494+
struct strbuf rev_index_name = STRBUF_INIT;
14931495
int err;
14941496

14951497
if (!from_stdin) {
@@ -1524,6 +1526,16 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
15241526
} else
15251527
chmod(final_index_name, 0444);
15261528

1529+
if (curr_rev_index_name) {
1530+
if (final_rev_index_name != curr_rev_index_name) {
1531+
if (!final_rev_index_name)
1532+
final_rev_index_name = odb_pack_name(&rev_index_name, hash, "rev");
1533+
if (finalize_object_file(curr_rev_index_name, final_rev_index_name))
1534+
die(_("cannot store reverse index file"));
1535+
} else
1536+
chmod(final_rev_index_name, 0444);
1537+
}
1538+
15271539
if (do_fsck_object) {
15281540
struct packed_git *p;
15291541
p = add_packed_git(final_index_name, strlen(final_index_name), 0);
@@ -1553,6 +1565,7 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
15531565
}
15541566
}
15551567

1568+
strbuf_release(&rev_index_name);
15561569
strbuf_release(&index_name);
15571570
strbuf_release(&pack_name);
15581571
}
@@ -1578,6 +1591,12 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
15781591
}
15791592
return 0;
15801593
}
1594+
if (!strcmp(k, "pack.writereverseindex")) {
1595+
if (git_config_bool(k, v))
1596+
opts->flags |= WRITE_REV;
1597+
else
1598+
opts->flags &= ~WRITE_REV;
1599+
}
15811600
return git_default_config(k, v, cb);
15821601
}
15831602

@@ -1695,12 +1714,14 @@ static void show_pack_info(int stat_only)
16951714

16961715
int cmd_index_pack(int argc, const char **argv, const char *prefix)
16971716
{
1698-
int i, fix_thin_pack = 0, verify = 0, stat_only = 0;
1717+
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
16991718
const char *curr_index;
1700-
const char *index_name = NULL, *pack_name = NULL;
1719+
const char *curr_rev_index = NULL;
1720+
const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
17011721
const char *keep_msg = NULL;
17021722
const char *promisor_msg = NULL;
17031723
struct strbuf index_name_buf = STRBUF_INIT;
1724+
struct strbuf rev_index_name_buf = STRBUF_INIT;
17041725
struct pack_idx_entry **idx_objects;
17051726
struct pack_idx_option opts;
17061727
unsigned char pack_hash[GIT_MAX_RAWSZ];
@@ -1727,6 +1748,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
17271748
if (prefix && chdir(prefix))
17281749
die(_("Cannot come back to cwd"));
17291750

1751+
rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV));
1752+
17301753
for (i = 1; i < argc; i++) {
17311754
const char *arg = argv[i];
17321755

@@ -1805,6 +1828,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
18051828
if (hash_algo == GIT_HASH_UNKNOWN)
18061829
die(_("unknown hash algorithm '%s'"), arg);
18071830
repo_set_hash_algo(the_repository, hash_algo);
1831+
} else if (!strcmp(arg, "--rev-index")) {
1832+
rev_index = 1;
1833+
} else if (!strcmp(arg, "--no-rev-index")) {
1834+
rev_index = 0;
18081835
} else
18091836
usage(index_pack_usage);
18101837
continue;
@@ -1826,6 +1853,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
18261853
if (!index_name && pack_name)
18271854
index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
18281855

1856+
opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY);
1857+
if (rev_index) {
1858+
opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV;
1859+
if (index_name)
1860+
rev_index_name = derive_filename(index_name,
1861+
"idx", "rev",
1862+
&rev_index_name_buf);
1863+
}
1864+
18291865
if (verify) {
18301866
if (!index_name)
18311867
die(_("--verify with no packfile name given"));
@@ -1878,11 +1914,16 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
18781914
for (i = 0; i < nr_objects; i++)
18791915
idx_objects[i] = &objects[i].idx;
18801916
curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash);
1917+
if (rev_index)
1918+
curr_rev_index = write_rev_file(rev_index_name, idx_objects,
1919+
nr_objects, pack_hash,
1920+
opts.flags);
18811921
free(idx_objects);
18821922

18831923
if (!verify)
18841924
final(pack_name, curr_pack,
18851925
index_name, curr_index,
1926+
rev_index_name, curr_rev_index,
18861927
keep_msg, promisor_msg,
18871928
pack_hash);
18881929
else
@@ -1893,10 +1934,13 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
18931934

18941935
free(objects);
18951936
strbuf_release(&index_name_buf);
1937+
strbuf_release(&rev_index_name_buf);
18961938
if (pack_name == NULL)
18971939
free((void *) curr_pack);
18981940
if (index_name == NULL)
18991941
free((void *) curr_index);
1942+
if (rev_index_name == NULL)
1943+
free((void *) curr_rev_index);
19001944

19011945
/*
19021946
* Let the caller know this pack is not self contained

t/t5325-reverse-index.sh

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/sh
2+
3+
test_description='on-disk reverse index'
4+
. ./test-lib.sh
5+
6+
packdir=.git/objects/pack
7+
8+
test_expect_success 'setup' '
9+
test_commit base &&
10+
11+
pack=$(git pack-objects --all $packdir/pack) &&
12+
rev=$packdir/pack-$pack.rev &&
13+
14+
test_path_is_missing $rev
15+
'
16+
17+
test_index_pack () {
18+
rm -f $rev &&
19+
conf=$1 &&
20+
shift &&
21+
# remove the index since Windows won't overwrite an existing file
22+
rm $packdir/pack-$pack.idx &&
23+
git -c pack.writeReverseIndex=$conf index-pack "$@" \
24+
$packdir/pack-$pack.pack
25+
}
26+
27+
test_expect_success 'index-pack with pack.writeReverseIndex' '
28+
test_index_pack "" &&
29+
test_path_is_missing $rev &&
30+
31+
test_index_pack false &&
32+
test_path_is_missing $rev &&
33+
34+
test_index_pack true &&
35+
test_path_is_file $rev
36+
'
37+
38+
test_expect_success 'index-pack with --[no-]rev-index' '
39+
for conf in "" true false
40+
do
41+
test_index_pack "$conf" --rev-index &&
42+
test_path_exists $rev &&
43+
44+
test_index_pack "$conf" --no-rev-index &&
45+
test_path_is_missing $rev
46+
done
47+
'
48+
49+
test_expect_success 'index-pack can verify reverse indexes' '
50+
test_when_finished "rm -f $rev" &&
51+
test_index_pack true &&
52+
53+
test_path_is_file $rev &&
54+
git index-pack --rev-index --verify $packdir/pack-$pack.pack &&
55+
56+
# Intentionally corrupt the reverse index.
57+
chmod u+w $rev &&
58+
printf "xxxx" | dd of=$rev bs=1 count=4 conv=notrunc &&
59+
60+
test_must_fail git index-pack --rev-index --verify \
61+
$packdir/pack-$pack.pack 2>err &&
62+
grep "validation error" err
63+
'
64+
65+
test_expect_success 'index-pack infers reverse index name with -o' '
66+
git index-pack --rev-index -o other.idx $packdir/pack-$pack.pack &&
67+
test_path_is_file other.idx &&
68+
test_path_is_file other.rev
69+
'
70+
71+
test_done

0 commit comments

Comments
 (0)