multi-pack-index: load into memory

Create a new multi_pack_index struct for loading multi-pack-indexes into memory. Create a test-tool builtin for reading basic information about that multi-pack-index to verify the correct data is written. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Jul 12, 2018 at 15:39 UTC 4d80560c546179654c32499132a6bdaf3c45b16f
8 files changed +143 -1
Makefile
+1
@@ -717,6 +717,7 @@ TEST_BUILTINS_OBJS += test-online-cpus.o
717 TEST_BUILTINS_OBJS += test-path-utils.o
718 TEST_BUILTINS_OBJS += test-prio-queue.o
719 TEST_BUILTINS_OBJS += test-read-cache.o
720 +TEST_BUILTINS_OBJS += test-read-midx.o
721 TEST_BUILTINS_OBJS += test-ref-store.o
722 TEST_BUILTINS_OBJS += test-regex.o
723 TEST_BUILTINS_OBJS += test-revision-walking.o
midx.c
+79
@@ -1,18 +1,97 @@
1 #include "cache.h"
2 #include "csum-file.h"
3 #include "lockfile.h"
4 +#include "object-store.h"
5 #include "midx.h"
6
7 #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
8 #define MIDX_VERSION 1
9 +#define MIDX_BYTE_FILE_VERSION 4
10 +#define MIDX_BYTE_HASH_VERSION 5
11 +#define MIDX_BYTE_NUM_CHUNKS 6
12 +#define MIDX_BYTE_NUM_PACKS 8
13 #define MIDX_HASH_VERSION 1
14 #define MIDX_HEADER_SIZE 12
15 +#define MIDX_HASH_LEN 20
16 +#define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + MIDX_HASH_LEN)
17
18 static char *get_midx_filename(const char *object_dir)
19 {
20 return xstrfmt("%s/pack/multi-pack-index", object_dir);
21 }
22
23 +struct multi_pack_index *load_multi_pack_index(const char *object_dir)
24 +{
25 + struct multi_pack_index *m = NULL;
26 + int fd;
27 + struct stat st;
28 + size_t midx_size;
29 + void *midx_map = NULL;
30 + uint32_t hash_version;
31 + char *midx_name = get_midx_filename(object_dir);
32 +
33 + fd = git_open(midx_name);
34 +
35 + if (fd < 0)
36 + goto cleanup_fail;
37 + if (fstat(fd, &st)) {
38 + error_errno(_("failed to read %s"), midx_name);
39 + goto cleanup_fail;
40 + }
41 +
42 + midx_size = xsize_t(st.st_size);
43 +
44 + if (midx_size < MIDX_MIN_SIZE) {
45 + error(_("multi-pack-index file %s is too small"), midx_name);
46 + goto cleanup_fail;
47 + }
48 +
49 + FREE_AND_NULL(midx_name);
50 +
51 + midx_map = xmmap(NULL, midx_size, PROT_READ, MAP_PRIVATE, fd, 0);
52 +
53 + FLEX_ALLOC_MEM(m, object_dir, object_dir, strlen(object_dir));
54 + m->fd = fd;
55 + m->data = midx_map;
56 + m->data_len = midx_size;
57 +
58 + m->signature = get_be32(m->data);
59 + if (m->signature != MIDX_SIGNATURE) {
60 + error(_("multi-pack-index signature 0x%08x does not match signature 0x%08x"),
61 + m->signature, MIDX_SIGNATURE);
62 + goto cleanup_fail;
63 + }
64 +
65 + m->version = m->data[MIDX_BYTE_FILE_VERSION];
66 + if (m->version != MIDX_VERSION) {
67 + error(_("multi-pack-index version %d not recognized"),
68 + m->version);
69 + goto cleanup_fail;
70 + }
71 +
72 + hash_version = m->data[MIDX_BYTE_HASH_VERSION];
73 + if (hash_version != MIDX_HASH_VERSION) {
74 + error(_("hash version %u does not match"), hash_version);
75 + goto cleanup_fail;
76 + }
77 + m->hash_len = MIDX_HASH_LEN;
78 +
79 + m->num_chunks = m->data[MIDX_BYTE_NUM_CHUNKS];
80 +
81 + m->num_packs = get_be32(m->data + MIDX_BYTE_NUM_PACKS);
82 +
83 + return m;
84 +
85 +cleanup_fail:
86 + free(m);
87 + free(midx_name);
88 + if (midx_map)
89 + munmap(midx_map, midx_size);
90 + if (0 <= fd)
91 + close(fd);
92 + return NULL;
93 +}
94 +
95 static size_t write_midx_header(struct hashfile *f,
96 unsigned char num_chunks,
97 uint32_t num_packs)
midx.h
+18
@@ -1,6 +1,24 @@
1 #ifndef __MIDX_H__
2 #define __MIDX_H__
3
4 +struct multi_pack_index {
5 + int fd;
6 +
7 + const unsigned char *data;
8 + size_t data_len;
9 +
10 + uint32_t signature;
11 + unsigned char version;
12 + unsigned char hash_len;
13 + unsigned char num_chunks;
14 + uint32_t num_packs;
15 + uint32_t num_objects;
16 +
17 + char object_dir[FLEX_ARRAY];
18 +};
19 +
20 +struct multi_pack_index *load_multi_pack_index(const char *object_dir);
21 +
22 int write_midx_file(const char *object_dir);
23
24 #endif
object-store.h
+2
@@ -84,6 +84,8 @@ struct packed_git {
84 char pack_name[FLEX_ARRAY]; /* more */
85 };
86
87 +struct multi_pack_index;
88 +
89 struct raw_object_store {
90 /*
91 * Path to the repository's object store.
t/helper/test-read-midx.c new
+31
@@ -0,0 +1,31 @@
1 +#include "test-tool.h"
2 +#include "cache.h"
3 +#include "midx.h"
4 +#include "repository.h"
5 +#include "object-store.h"
6 +
7 +static int read_midx_file(const char *object_dir)
8 +{
9 + struct multi_pack_index *m = load_multi_pack_index(object_dir);
10 +
11 + if (!m)
12 + return 1;
13 +
14 + printf("header: %08x %d %d %d\n",
15 + m->signature,
16 + m->version,
17 + m->num_chunks,
18 + m->num_packs);
19 +
20 + printf("object-dir: %s\n", m->object_dir);
21 +
22 + return 0;
23 +}
24 +
25 +int cmd__read_midx(int argc, const char **argv)
26 +{
27 + if (argc != 2)
28 + usage("read-midx <object-dir>");
29 +
30 + return read_midx_file(argv[1]);
31 +}
t/helper/test-tool.c
+1
@@ -27,6 +27,7 @@ static struct test_cmd cmds[] = {
27 { "path-utils", cmd__path_utils },
28 { "prio-queue", cmd__prio_queue },
29 { "read-cache", cmd__read_cache },
30 + { "read-midx", cmd__read_midx },
31 { "ref-store", cmd__ref_store },
32 { "regex", cmd__regex },
33 { "revision-walking", cmd__revision_walking },
t/helper/test-tool.h
+1
@@ -21,6 +21,7 @@ int cmd__online_cpus(int argc, const char **argv);
21 int cmd__path_utils(int argc, const char **argv);
22 int cmd__prio_queue(int argc, const char **argv);
23 int cmd__read_cache(int argc, const char **argv);
24 +int cmd__read_midx(int argc, const char **argv);
25 int cmd__ref_store(int argc, const char **argv);
26 int cmd__regex(int argc, const char **argv);
27 int cmd__revision_walking(int argc, const char **argv);
t/t5319-multi-pack-index.sh
+10 -1
@@ -3,10 +3,19 @@
3 test_description='multi-pack-indexes'
4 . ./test-lib.sh
5
6 +midx_read_expect () {
7 + cat >expect <<-EOF
8 + header: 4d494458 1 0 0
9 + object-dir: .
10 + EOF
11 + test-tool read-midx . >actual &&
12 + test_cmp expect actual
13 +}
14 +
15 test_expect_success 'write midx with no packs' '
16 test_when_finished rm -f pack/multi-pack-index &&
17 git multi-pack-index --object-dir=. write &&
9 - test_path_is_file pack/multi-pack-index
18 + midx_read_expect
19 '
20
21 test_done