Skip to content

Commit d907bf8

Browse files
committed
Merge branch 'jc/index-pack'
* jc/index-pack: verify-pack: use index-pack --verify index-pack: show histogram when emulating "verify-pack -v" index-pack: start learning to emulate "verify-pack -v" index-pack: a miniscule refactor index-pack --verify: read anomalous offsets from v2 idx file write_idx_file: need_large_offset() helper function index-pack: --verify write_idx_file: introduce a struct to hold idx customization options index-pack: group the delta-base array entries also by type Conflicts: builtin/verify-pack.c cache.h sha1_file.c
2 parents 54dbc1f + 3de89c9 commit d907bf8

File tree

11 files changed

+395
-249
lines changed

11 files changed

+395
-249
lines changed

builtin/index-pack.c

Lines changed: 208 additions & 42 deletions
Large diffs are not rendered by default.

builtin/pack-objects.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ static int local;
7070
static int incremental;
7171
static int ignore_packed_keep;
7272
static int allow_ofs_delta;
73+
static struct pack_idx_option pack_idx_opts;
7374
static const char *base_name;
7475
static int progress = 1;
7576
static int window = 10;
@@ -493,8 +494,8 @@ static void write_pack_file(void)
493494
const char *idx_tmp_name;
494495
char tmpname[PATH_MAX];
495496

496-
idx_tmp_name = write_idx_file(NULL, written_list,
497-
nr_written, sha1);
497+
idx_tmp_name = write_idx_file(NULL, written_list, nr_written,
498+
&pack_idx_opts, sha1);
498499

499500
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
500501
base_name, sha1_to_hex(sha1));
@@ -1884,10 +1885,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
18841885
return 0;
18851886
}
18861887
if (!strcmp(k, "pack.indexversion")) {
1887-
pack_idx_default_version = git_config_int(k, v);
1888-
if (pack_idx_default_version > 2)
1888+
pack_idx_opts.version = git_config_int(k, v);
1889+
if (pack_idx_opts.version > 2)
18891890
die("bad pack.indexversion=%"PRIu32,
1890-
pack_idx_default_version);
1891+
pack_idx_opts.version);
18911892
return 0;
18921893
}
18931894
if (!strcmp(k, "pack.packsizelimit")) {
@@ -2134,6 +2135,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
21342135
rp_av[1] = "--objects"; /* --thin will make it --objects-edge */
21352136
rp_ac = 2;
21362137

2138+
reset_pack_idx_option(&pack_idx_opts);
21372139
git_config(git_pack_config, NULL);
21382140
if (!pack_compression_seen && core_compression_seen)
21392141
pack_compression_level = core_compression_level;
@@ -2278,12 +2280,12 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
22782280
}
22792281
if (!prefixcmp(arg, "--index-version=")) {
22802282
char *c;
2281-
pack_idx_default_version = strtoul(arg + 16, &c, 10);
2282-
if (pack_idx_default_version > 2)
2283+
pack_idx_opts.version = strtoul(arg + 16, &c, 10);
2284+
if (pack_idx_opts.version > 2)
22832285
die("bad %s", arg);
22842286
if (*c == ',')
2285-
pack_idx_off32_limit = strtoul(c+1, &c, 0);
2286-
if (*c || pack_idx_off32_limit & 0x80000000)
2287+
pack_idx_opts.off32_limit = strtoul(c+1, &c, 0);
2288+
if (*c || pack_idx_opts.off32_limit & 0x80000000)
22872289
die("bad %s", arg);
22882290
continue;
22892291
}

builtin/verify-pack.c

Lines changed: 25 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,134 +1,53 @@
11
#include "builtin.h"
22
#include "cache.h"
3-
#include "pack.h"
4-
#include "pack-revindex.h"
3+
#include "run-command.h"
54
#include "parse-options.h"
65

7-
#define MAX_CHAIN 50
8-
96
#define VERIFY_PACK_VERBOSE 01
107
#define VERIFY_PACK_STAT_ONLY 02
118

12-
static void show_pack_info(struct packed_git *p, unsigned int flags)
13-
{
14-
uint32_t nr_objects, i;
15-
int cnt;
16-
int stat_only = flags & VERIFY_PACK_STAT_ONLY;
17-
unsigned long chain_histogram[MAX_CHAIN+1], baseobjects;
18-
19-
nr_objects = p->num_objects;
20-
memset(chain_histogram, 0, sizeof(chain_histogram));
21-
baseobjects = 0;
22-
23-
for (i = 0; i < nr_objects; i++) {
24-
const unsigned char *sha1;
25-
unsigned char base_sha1[20];
26-
const char *type;
27-
unsigned long size;
28-
unsigned long store_size;
29-
off_t offset;
30-
unsigned int delta_chain_length;
31-
32-
sha1 = nth_packed_object_sha1(p, i);
33-
if (!sha1)
34-
die("internal error pack-check nth-packed-object");
35-
offset = nth_packed_object_offset(p, i);
36-
type = typename(packed_object_info_detail(p, offset, &size, &store_size,
37-
&delta_chain_length,
38-
base_sha1));
39-
if (!stat_only)
40-
printf("%s ", sha1_to_hex(sha1));
41-
if (!delta_chain_length) {
42-
if (!stat_only)
43-
printf("%-6s %lu %lu %"PRIuMAX"\n",
44-
type, size, store_size, (uintmax_t)offset);
45-
baseobjects++;
46-
}
47-
else {
48-
if (!stat_only)
49-
printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
50-
type, size, store_size, (uintmax_t)offset,
51-
delta_chain_length, sha1_to_hex(base_sha1));
52-
if (delta_chain_length <= MAX_CHAIN)
53-
chain_histogram[delta_chain_length]++;
54-
else
55-
chain_histogram[0]++;
56-
}
57-
}
58-
59-
if (baseobjects)
60-
printf("non delta: %lu object%s\n",
61-
baseobjects, baseobjects > 1 ? "s" : "");
62-
63-
for (cnt = 1; cnt <= MAX_CHAIN; cnt++) {
64-
if (!chain_histogram[cnt])
65-
continue;
66-
printf("chain length = %d: %lu object%s\n", cnt,
67-
chain_histogram[cnt],
68-
chain_histogram[cnt] > 1 ? "s" : "");
69-
}
70-
if (chain_histogram[0])
71-
printf("chain length > %d: %lu object%s\n", MAX_CHAIN,
72-
chain_histogram[0],
73-
chain_histogram[0] > 1 ? "s" : "");
74-
}
75-
769
static int verify_one_pack(const char *path, unsigned int flags)
7710
{
78-
char arg[PATH_MAX];
79-
int len;
11+
struct child_process index_pack;
12+
const char *argv[] = {"index-pack", NULL, NULL, NULL };
13+
struct strbuf arg = STRBUF_INIT;
8014
int verbose = flags & VERIFY_PACK_VERBOSE;
8115
int stat_only = flags & VERIFY_PACK_STAT_ONLY;
82-
struct packed_git *pack;
8316
int err;
8417

85-
len = strlcpy(arg, path, PATH_MAX);
86-
if (len >= PATH_MAX)
87-
return error("name too long: %s", path);
88-
89-
/*
90-
* In addition to "foo.idx" we accept "foo.pack" and "foo";
91-
* normalize these forms to "foo.idx" for add_packed_git().
92-
*/
93-
if (has_extension(arg, ".pack")) {
94-
strcpy(arg + len - 5, ".idx");
95-
len--;
96-
} else if (!has_extension(arg, ".idx")) {
97-
if (len + 4 >= PATH_MAX)
98-
return error("name too long: %s.idx", arg);
99-
strcpy(arg + len, ".idx");
100-
len += 4;
101-
}
18+
if (stat_only)
19+
argv[1] = "--verify-stat-only";
20+
else if (verbose)
21+
argv[1] = "--verify-stat";
22+
else
23+
argv[1] = "--verify";
10224

10325
/*
104-
* add_packed_git() uses our buffer (containing "foo.idx") to
105-
* build the pack filename ("foo.pack"). Make sure it fits.
26+
* In addition to "foo.pack" we accept "foo.idx" and "foo";
27+
* normalize these forms to "foo.pack" for "index-pack --verify".
10628
*/
107-
if (len + 1 >= PATH_MAX) {
108-
arg[len - 4] = '\0';
109-
return error("name too long: %s.pack", arg);
110-
}
111-
112-
pack = add_packed_git(arg, len, 1);
113-
if (!pack)
114-
return error("packfile %s not found.", arg);
29+
strbuf_addstr(&arg, path);
30+
if (has_extension(arg.buf, ".idx"))
31+
strbuf_splice(&arg, arg.len - 3, 3, "pack", 4);
32+
else if (!has_extension(arg.buf, ".pack"))
33+
strbuf_add(&arg, ".pack", 5);
34+
argv[2] = arg.buf;
11535

116-
install_packed_git(pack);
36+
memset(&index_pack, 0, sizeof(index_pack));
37+
index_pack.argv = argv;
38+
index_pack.git_cmd = 1;
11739

118-
if (!stat_only)
119-
err = verify_pack(pack);
120-
else
121-
err = open_pack_index(pack);
40+
err = run_command(&index_pack);
12241

12342
if (verbose || stat_only) {
12443
if (err)
125-
printf("%s: bad\n", pack->pack_name);
44+
printf("%s: bad\n", arg.buf);
12645
else {
127-
show_pack_info(pack, flags);
12846
if (!stat_only)
129-
printf("%s: ok\n", pack->pack_name);
47+
printf("%s: ok\n", arg.buf);
13048
}
13149
}
50+
strbuf_release(&arg);
13251

13352
return err;
13453
}
@@ -159,7 +78,6 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
15978
for (i = 0; i < argc; i++) {
16079
if (verify_one_pack(argv[i], flags))
16180
err = 1;
162-
discard_revindex();
16381
}
16482

16583
return err;

cache.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,7 +1010,6 @@ extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
10101010
extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
10111011
extern unsigned long unpack_object_header_buffer(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
10121012
extern unsigned long get_size_from_delta(struct packed_git *, struct pack_window **, off_t);
1013-
extern int packed_object_info_detail(struct packed_git *, off_t, unsigned long *, unsigned long *, unsigned int *, unsigned char *);
10141013
extern int unpack_object_header(struct packed_git *, struct pack_window **, off_t *, unsigned long *);
10151014

10161015
struct object_info {

csum-file.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,20 @@
1111
#include "progress.h"
1212
#include "csum-file.h"
1313

14-
static void flush(struct sha1file *f, void * buf, unsigned int count)
14+
static void flush(struct sha1file *f, void *buf, unsigned int count)
1515
{
16+
if (0 <= f->check_fd && count) {
17+
unsigned char check_buffer[8192];
18+
ssize_t ret = read_in_full(f->check_fd, check_buffer, count);
19+
20+
if (ret < 0)
21+
die_errno("%s: sha1 file read error", f->name);
22+
if (ret < count)
23+
die("%s: sha1 file truncated", f->name);
24+
if (memcmp(buf, check_buffer, count))
25+
die("sha1 file '%s' validation error", f->name);
26+
}
27+
1628
for (;;) {
1729
int ret = xwrite(f->fd, buf, count);
1830
if (ret > 0) {
@@ -59,6 +71,17 @@ int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
5971
fd = 0;
6072
} else
6173
fd = f->fd;
74+
if (0 <= f->check_fd) {
75+
char discard;
76+
int cnt = read_in_full(f->check_fd, &discard, 1);
77+
if (cnt < 0)
78+
die_errno("%s: error when reading the tail of sha1 file",
79+
f->name);
80+
if (cnt)
81+
die("%s: sha1 file has trailing garbage", f->name);
82+
if (close(f->check_fd))
83+
die_errno("%s: sha1 file error on close", f->name);
84+
}
6285
free(f);
6386
return fd;
6487
}
@@ -101,10 +124,31 @@ struct sha1file *sha1fd(int fd, const char *name)
101124
return sha1fd_throughput(fd, name, NULL);
102125
}
103126

127+
struct sha1file *sha1fd_check(const char *name)
128+
{
129+
int sink, check;
130+
struct sha1file *f;
131+
132+
sink = open("/dev/null", O_WRONLY);
133+
if (sink < 0)
134+
return NULL;
135+
check = open(name, O_RDONLY);
136+
if (check < 0) {
137+
int saved_errno = errno;
138+
close(sink);
139+
errno = saved_errno;
140+
return NULL;
141+
}
142+
f = sha1fd(sink, name);
143+
f->check_fd = check;
144+
return f;
145+
}
146+
104147
struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp)
105148
{
106149
struct sha1file *f = xmalloc(sizeof(*f));
107150
f->fd = fd;
151+
f->check_fd = -1;
108152
f->offset = 0;
109153
f->total = 0;
110154
f->tp = tp;

csum-file.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ struct progress;
66
/* A SHA1-protected file */
77
struct sha1file {
88
int fd;
9+
int check_fd;
910
unsigned int offset;
1011
git_SHA_CTX ctx;
1112
off_t total;
@@ -21,6 +22,7 @@ struct sha1file {
2122
#define CSUM_FSYNC 2
2223

2324
extern struct sha1file *sha1fd(int fd, const char *name);
25+
extern struct sha1file *sha1fd_check(const char *name);
2426
extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp);
2527
extern int sha1close(struct sha1file *, unsigned char *, unsigned int);
2628
extern int sha1write(struct sha1file *, void *, unsigned int);

fast-import.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ static unsigned int atom_cnt;
304304
static struct atom_str **atom_table;
305305

306306
/* The .pack file being generated */
307+
static struct pack_idx_option pack_idx_opts;
307308
static unsigned int pack_id;
308309
static struct sha1file *pack_file;
309310
static struct packed_git *pack_data;
@@ -896,7 +897,7 @@ static const char *create_index(void)
896897
if (c != last)
897898
die("internal consistency error creating the index");
898899

899-
tmpfile = write_idx_file(NULL, idx, object_count, pack_data->sha1);
900+
tmpfile = write_idx_file(NULL, idx, object_count, &pack_idx_opts, pack_data->sha1);
900901
free(idx);
901902
return tmpfile;
902903
}
@@ -3195,10 +3196,10 @@ static int git_pack_config(const char *k, const char *v, void *cb)
31953196
return 0;
31963197
}
31973198
if (!strcmp(k, "pack.indexversion")) {
3198-
pack_idx_default_version = git_config_int(k, v);
3199-
if (pack_idx_default_version > 2)
3199+
pack_idx_opts.version = git_config_int(k, v);
3200+
if (pack_idx_opts.version > 2)
32003201
die("bad pack.indexversion=%"PRIu32,
3201-
pack_idx_default_version);
3202+
pack_idx_opts.version);
32023203
return 0;
32033204
}
32043205
if (!strcmp(k, "pack.packsizelimit")) {
@@ -3252,6 +3253,7 @@ int main(int argc, const char **argv)
32523253
usage(fast_import_usage);
32533254

32543255
setup_git_directory();
3256+
reset_pack_idx_option(&pack_idx_opts);
32553257
git_config(git_pack_config, NULL);
32563258
if (!pack_compression_seen && core_compression_seen)
32573259
pack_compression_level = core_compression_level;

0 commit comments

Comments
 (0)