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 <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
84d544943c
commit
e37d0b8730
@ -9,17 +9,18 @@ git-index-pack - Build pack index file for an existing packed archive
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git index-pack' [-v] [-o <index-file>] <pack-file>
|
'git index-pack' [-v] [-o <index-file>] [--[no-]rev-index] <pack-file>
|
||||||
'git index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
|
'git index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
|
||||||
[<pack-file>]
|
[--[no-]rev-index] [<pack-file>]
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Reads a packed archive (.pack) from the specified file, and
|
Reads a packed archive (.pack) from the specified file, and
|
||||||
builds a pack index file (.idx) for it. The packed archive
|
builds a pack index file (.idx) for it. Optionally writes a
|
||||||
together with the pack index can then be placed in the
|
reverse-index (.rev) for the specified pack. The packed
|
||||||
objects/pack/ directory of a Git repository.
|
archive together with the pack index can then be placed in
|
||||||
|
the objects/pack/ directory of a Git repository.
|
||||||
|
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
@ -35,6 +36,13 @@ OPTIONS
|
|||||||
fails if the name of packed archive does not end
|
fails if the name of packed archive does not end
|
||||||
with .pack).
|
with .pack).
|
||||||
|
|
||||||
|
--[no-]rev-index::
|
||||||
|
When this flag is provided, generate a reverse index
|
||||||
|
(a `.rev` file) corresponding to the given pack. If
|
||||||
|
`--verify` is given, ensure that the existing
|
||||||
|
reverse index is correct. Takes precedence over
|
||||||
|
`pack.writeReverseIndex`.
|
||||||
|
|
||||||
--stdin::
|
--stdin::
|
||||||
When this flag is provided, the pack is read from stdin
|
When this flag is provided, the pack is read from stdin
|
||||||
instead and a copy is then written to <pack-file>. If
|
instead and a copy is then written to <pack-file>. If
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include "promisor-remote.h"
|
#include "promisor-remote.h"
|
||||||
|
|
||||||
static const char index_pack_usage[] =
|
static const char index_pack_usage[] =
|
||||||
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
|
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
|
||||||
|
|
||||||
struct object_entry {
|
struct object_entry {
|
||||||
struct pack_idx_entry idx;
|
struct pack_idx_entry idx;
|
||||||
@ -1484,12 +1484,14 @@ static void write_special_file(const char *suffix, const char *msg,
|
|||||||
|
|
||||||
static void final(const char *final_pack_name, const char *curr_pack_name,
|
static void final(const char *final_pack_name, const char *curr_pack_name,
|
||||||
const char *final_index_name, const char *curr_index_name,
|
const char *final_index_name, const char *curr_index_name,
|
||||||
|
const char *final_rev_index_name, const char *curr_rev_index_name,
|
||||||
const char *keep_msg, const char *promisor_msg,
|
const char *keep_msg, const char *promisor_msg,
|
||||||
unsigned char *hash)
|
unsigned char *hash)
|
||||||
{
|
{
|
||||||
const char *report = "pack";
|
const char *report = "pack";
|
||||||
struct strbuf pack_name = STRBUF_INIT;
|
struct strbuf pack_name = STRBUF_INIT;
|
||||||
struct strbuf index_name = STRBUF_INIT;
|
struct strbuf index_name = STRBUF_INIT;
|
||||||
|
struct strbuf rev_index_name = STRBUF_INIT;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!from_stdin) {
|
if (!from_stdin) {
|
||||||
@ -1524,6 +1526,16 @@ static void final(const char *final_pack_name, const char *curr_pack_name,
|
|||||||
} else
|
} else
|
||||||
chmod(final_index_name, 0444);
|
chmod(final_index_name, 0444);
|
||||||
|
|
||||||
|
if (curr_rev_index_name) {
|
||||||
|
if (final_rev_index_name != curr_rev_index_name) {
|
||||||
|
if (!final_rev_index_name)
|
||||||
|
final_rev_index_name = odb_pack_name(&rev_index_name, hash, "rev");
|
||||||
|
if (finalize_object_file(curr_rev_index_name, final_rev_index_name))
|
||||||
|
die(_("cannot store reverse index file"));
|
||||||
|
} else
|
||||||
|
chmod(final_rev_index_name, 0444);
|
||||||
|
}
|
||||||
|
|
||||||
if (do_fsck_object) {
|
if (do_fsck_object) {
|
||||||
struct packed_git *p;
|
struct packed_git *p;
|
||||||
p = add_packed_git(final_index_name, strlen(final_index_name), 0);
|
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strbuf_release(&rev_index_name);
|
||||||
strbuf_release(&index_name);
|
strbuf_release(&index_name);
|
||||||
strbuf_release(&pack_name);
|
strbuf_release(&pack_name);
|
||||||
}
|
}
|
||||||
@ -1578,6 +1591,12 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(k, "pack.writereverseindex")) {
|
||||||
|
if (git_config_bool(k, v))
|
||||||
|
opts->flags |= WRITE_REV;
|
||||||
|
else
|
||||||
|
opts->flags &= ~WRITE_REV;
|
||||||
|
}
|
||||||
return git_default_config(k, v, cb);
|
return git_default_config(k, v, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1695,12 +1714,14 @@ static void show_pack_info(int stat_only)
|
|||||||
|
|
||||||
int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i, fix_thin_pack = 0, verify = 0, stat_only = 0;
|
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
|
||||||
const char *curr_index;
|
const char *curr_index;
|
||||||
const char *index_name = NULL, *pack_name = NULL;
|
const char *curr_rev_index = NULL;
|
||||||
|
const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
|
||||||
const char *keep_msg = NULL;
|
const char *keep_msg = NULL;
|
||||||
const char *promisor_msg = NULL;
|
const char *promisor_msg = NULL;
|
||||||
struct strbuf index_name_buf = STRBUF_INIT;
|
struct strbuf index_name_buf = STRBUF_INIT;
|
||||||
|
struct strbuf rev_index_name_buf = STRBUF_INIT;
|
||||||
struct pack_idx_entry **idx_objects;
|
struct pack_idx_entry **idx_objects;
|
||||||
struct pack_idx_option opts;
|
struct pack_idx_option opts;
|
||||||
unsigned char pack_hash[GIT_MAX_RAWSZ];
|
unsigned char pack_hash[GIT_MAX_RAWSZ];
|
||||||
@ -1727,6 +1748,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
if (prefix && chdir(prefix))
|
if (prefix && chdir(prefix))
|
||||||
die(_("Cannot come back to cwd"));
|
die(_("Cannot come back to cwd"));
|
||||||
|
|
||||||
|
rev_index = !!(opts.flags & (WRITE_REV_VERIFY | WRITE_REV));
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
|
|
||||||
@ -1805,6 +1828,10 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
if (hash_algo == GIT_HASH_UNKNOWN)
|
if (hash_algo == GIT_HASH_UNKNOWN)
|
||||||
die(_("unknown hash algorithm '%s'"), arg);
|
die(_("unknown hash algorithm '%s'"), arg);
|
||||||
repo_set_hash_algo(the_repository, hash_algo);
|
repo_set_hash_algo(the_repository, hash_algo);
|
||||||
|
} else if (!strcmp(arg, "--rev-index")) {
|
||||||
|
rev_index = 1;
|
||||||
|
} else if (!strcmp(arg, "--no-rev-index")) {
|
||||||
|
rev_index = 0;
|
||||||
} else
|
} else
|
||||||
usage(index_pack_usage);
|
usage(index_pack_usage);
|
||||||
continue;
|
continue;
|
||||||
@ -1826,6 +1853,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
if (!index_name && pack_name)
|
if (!index_name && pack_name)
|
||||||
index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
|
index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
|
||||||
|
|
||||||
|
opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY);
|
||||||
|
if (rev_index) {
|
||||||
|
opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV;
|
||||||
|
if (index_name)
|
||||||
|
rev_index_name = derive_filename(index_name,
|
||||||
|
"idx", "rev",
|
||||||
|
&rev_index_name_buf);
|
||||||
|
}
|
||||||
|
|
||||||
if (verify) {
|
if (verify) {
|
||||||
if (!index_name)
|
if (!index_name)
|
||||||
die(_("--verify with no packfile name given"));
|
die(_("--verify with no packfile name given"));
|
||||||
@ -1878,11 +1914,16 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
for (i = 0; i < nr_objects; i++)
|
for (i = 0; i < nr_objects; i++)
|
||||||
idx_objects[i] = &objects[i].idx;
|
idx_objects[i] = &objects[i].idx;
|
||||||
curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash);
|
curr_index = write_idx_file(index_name, idx_objects, nr_objects, &opts, pack_hash);
|
||||||
|
if (rev_index)
|
||||||
|
curr_rev_index = write_rev_file(rev_index_name, idx_objects,
|
||||||
|
nr_objects, pack_hash,
|
||||||
|
opts.flags);
|
||||||
free(idx_objects);
|
free(idx_objects);
|
||||||
|
|
||||||
if (!verify)
|
if (!verify)
|
||||||
final(pack_name, curr_pack,
|
final(pack_name, curr_pack,
|
||||||
index_name, curr_index,
|
index_name, curr_index,
|
||||||
|
rev_index_name, curr_rev_index,
|
||||||
keep_msg, promisor_msg,
|
keep_msg, promisor_msg,
|
||||||
pack_hash);
|
pack_hash);
|
||||||
else
|
else
|
||||||
@ -1893,10 +1934,13 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
free(objects);
|
free(objects);
|
||||||
strbuf_release(&index_name_buf);
|
strbuf_release(&index_name_buf);
|
||||||
|
strbuf_release(&rev_index_name_buf);
|
||||||
if (pack_name == NULL)
|
if (pack_name == NULL)
|
||||||
free((void *) curr_pack);
|
free((void *) curr_pack);
|
||||||
if (index_name == NULL)
|
if (index_name == NULL)
|
||||||
free((void *) curr_index);
|
free((void *) curr_index);
|
||||||
|
if (rev_index_name == NULL)
|
||||||
|
free((void *) curr_rev_index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let the caller know this pack is not self contained
|
* Let the caller know this pack is not self contained
|
||||||
|
71
t/t5325-reverse-index.sh
Executable file
71
t/t5325-reverse-index.sh
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='on-disk reverse index'
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
packdir=.git/objects/pack
|
||||||
|
|
||||||
|
test_expect_success 'setup' '
|
||||||
|
test_commit base &&
|
||||||
|
|
||||||
|
pack=$(git pack-objects --all $packdir/pack) &&
|
||||||
|
rev=$packdir/pack-$pack.rev &&
|
||||||
|
|
||||||
|
test_path_is_missing $rev
|
||||||
|
'
|
||||||
|
|
||||||
|
test_index_pack () {
|
||||||
|
rm -f $rev &&
|
||||||
|
conf=$1 &&
|
||||||
|
shift &&
|
||||||
|
# remove the index since Windows won't overwrite an existing file
|
||||||
|
rm $packdir/pack-$pack.idx &&
|
||||||
|
git -c pack.writeReverseIndex=$conf index-pack "$@" \
|
||||||
|
$packdir/pack-$pack.pack
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success 'index-pack with pack.writeReverseIndex' '
|
||||||
|
test_index_pack "" &&
|
||||||
|
test_path_is_missing $rev &&
|
||||||
|
|
||||||
|
test_index_pack false &&
|
||||||
|
test_path_is_missing $rev &&
|
||||||
|
|
||||||
|
test_index_pack true &&
|
||||||
|
test_path_is_file $rev
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'index-pack with --[no-]rev-index' '
|
||||||
|
for conf in "" true false
|
||||||
|
do
|
||||||
|
test_index_pack "$conf" --rev-index &&
|
||||||
|
test_path_exists $rev &&
|
||||||
|
|
||||||
|
test_index_pack "$conf" --no-rev-index &&
|
||||||
|
test_path_is_missing $rev
|
||||||
|
done
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'index-pack can verify reverse indexes' '
|
||||||
|
test_when_finished "rm -f $rev" &&
|
||||||
|
test_index_pack true &&
|
||||||
|
|
||||||
|
test_path_is_file $rev &&
|
||||||
|
git index-pack --rev-index --verify $packdir/pack-$pack.pack &&
|
||||||
|
|
||||||
|
# Intentionally corrupt the reverse index.
|
||||||
|
chmod u+w $rev &&
|
||||||
|
printf "xxxx" | dd of=$rev bs=1 count=4 conv=notrunc &&
|
||||||
|
|
||||||
|
test_must_fail git index-pack --rev-index --verify \
|
||||||
|
$packdir/pack-$pack.pack 2>err &&
|
||||||
|
grep "validation error" err
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'index-pack infers reverse index name with -o' '
|
||||||
|
git index-pack --rev-index -o other.idx $packdir/pack-$pack.pack &&
|
||||||
|
test_path_is_file other.idx &&
|
||||||
|
test_path_is_file other.rev
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user