As we build the multi-pack-index feature by adding chunks at a time, we want to test that the data is being written correctly. Create struct midxed_git to store an in-memory representation of a multi-pack-index and a memory-map of the binary file. Initialize this struct in load_midxed_git(object_dir). Create the 'git midx read' subcommand to output basic information about the multi-pack-index file. This will be expanded as more information is written to the file. Signed-off-by: Derrick Stolee <dstolee@xxxxxxxxxxxxx> --- Documentation/git-midx.txt | 11 +++++++ builtin/midx.c | 23 +++++++++++++- midx.c | 65 ++++++++++++++++++++++++++++++++++++++ midx.h | 9 ++++++ object-store.h | 19 +++++++++++ t/t5319-midx.sh | 12 ++++++- 6 files changed, 137 insertions(+), 2 deletions(-) diff --git a/Documentation/git-midx.txt b/Documentation/git-midx.txt index dcaeb1a91b..919283fdd8 100644 --- a/Documentation/git-midx.txt +++ b/Documentation/git-midx.txt @@ -23,6 +23,11 @@ OPTIONS <dir>/packs/multi-pack-index for the current MIDX file, and <dir>/packs for the pack-files to index. +read:: + When given as the verb, read the current MIDX file and output + basic information about its contents. Used for debugging + purposes only. + write:: When given as the verb, write a new MIDX file to <dir>/packs/multi-pack-index. @@ -43,6 +48,12 @@ $ git midx write $ git midx --object-dir <alt> write ------------------------------------------- +* Read the MIDX file in the .git/objects folder. ++ +------------------------------------------- +$ git midx read +------------------------------------------- + GIT --- diff --git a/builtin/midx.c b/builtin/midx.c index dc0a5acd3f..c7002f664a 100644 --- a/builtin/midx.c +++ b/builtin/midx.c @@ -6,7 +6,7 @@ #include "midx.h" static char const * const builtin_midx_usage[] ={ - N_("git midx [--object-dir <dir>] [write]"), + N_("git midx [--object-dir <dir>] [read|write]"), NULL }; @@ -14,6 +14,25 @@ static struct opts_midx { const char *object_dir; } opts; +static int read_midx_file(const char *object_dir) +{ + struct midxed_git *m = load_midxed_git(object_dir); + + if (!m) + return 0; + + printf("header: %08x %d %d %d %d\n", + m->signature, + m->version, + m->hash_version, + m->num_chunks, + m->num_packs); + + printf("object_dir: %s\n", m->object_dir); + + return 0; +} + int cmd_midx(int argc, const char **argv, const char *prefix) { static struct option builtin_midx_options[] = { @@ -38,6 +57,8 @@ int cmd_midx(int argc, const char **argv, const char *prefix) if (argc == 0) return 0; + if (!strcmp(argv[0], "read")) + return read_midx_file(opts.object_dir); if (!strcmp(argv[0], "write")) return write_midx_file(opts.object_dir); diff --git a/midx.c b/midx.c index 3e55422a21..fa18770f1d 100644 --- a/midx.c +++ b/midx.c @@ -3,12 +3,15 @@ #include "dir.h" #include "csum-file.h" #include "lockfile.h" +#include "object-store.h" #include "midx.h" #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */ #define MIDX_VERSION 1 #define MIDX_HASH_VERSION 1 /* SHA-1 */ #define MIDX_HEADER_SIZE 12 +#define MIDX_HASH_LEN 20 +#define MIDX_MIN_SIZE (MIDX_HEADER_SIZE + MIDX_HASH_LEN) static char *get_midx_filename(const char *object_dir) { @@ -18,6 +21,68 @@ static char *get_midx_filename(const char *object_dir) return strbuf_detach(&midx_name, NULL); } +struct midxed_git *load_midxed_git(const char *object_dir) +{ + struct midxed_git *m; + int fd; + struct stat st; + size_t midx_size; + void *midx_map; + const char *midx_name = get_midx_filename(object_dir); + + fd = git_open(midx_name); + if (fd < 0) + return NULL; + if (fstat(fd, &st)) { + close(fd); + return NULL; + } + midx_size = xsize_t(st.st_size); + + if (midx_size < MIDX_MIN_SIZE) { + close(fd); + die("multi-pack-index file %s is too small", midx_name); + } + + midx_map = xmmap(NULL, midx_size, PROT_READ, MAP_PRIVATE, fd, 0); + + m = xcalloc(1, sizeof(*m) + strlen(object_dir) + 1); + strcpy(m->object_dir, object_dir); + m->data = midx_map; + + m->signature = get_be32(m->data); + if (m->signature != MIDX_SIGNATURE) { + error("multi-pack-index signature %X does not match signature %X", + m->signature, MIDX_SIGNATURE); + goto cleanup_fail; + } + + m->version = *(m->data + 4); + if (m->version != MIDX_VERSION) { + error("multi-pack-index version %d not recognized", + m->version); + goto cleanup_fail; + } + + m->hash_version = *(m->data + 5); + if (m->hash_version != MIDX_HASH_VERSION) { + error("hash version %d not recognized", m->hash_version); + goto cleanup_fail; + } + m->hash_len = MIDX_HASH_LEN; + + m->num_chunks = *(m->data + 6); + m->num_packs = get_be32(m->data + 8); + + return m; + +cleanup_fail: + FREE_AND_NULL(m); + munmap(midx_map, midx_size); + close(fd); + exit(1); +} + static size_t write_midx_header(struct hashfile *f, unsigned char num_chunks, uint32_t num_packs) diff --git a/midx.h b/midx.h index 3a63673952..a1d18ed991 100644 --- a/midx.h +++ b/midx.h @@ -1,4 +1,13 @@ +#ifndef MIDX_H +#define MIDX_H + +#include "git-compat-util.h" #include "cache.h" +#include "object-store.h" #include "packfile.h" +struct midxed_git *load_midxed_git(const char *object_dir); + int write_midx_file(const char *object_dir); + +#endif diff --git a/object-store.h b/object-store.h index d683112fd7..77cb82621a 100644 --- a/object-store.h +++ b/object-store.h @@ -84,6 +84,25 @@ struct packed_git { char pack_name[FLEX_ARRAY]; /* more */ }; +struct midxed_git { + struct midxed_git *next; + + int fd; + + const unsigned char *data; + size_t data_len; + + uint32_t signature; + unsigned char version; + unsigned char hash_version; + unsigned char hash_len; + unsigned char num_chunks; + uint32_t num_packs; + uint32_t num_objects; + + char object_dir[FLEX_ARRAY]; +}; + struct raw_object_store { /* * Path to the repository's object store. diff --git a/t/t5319-midx.sh b/t/t5319-midx.sh index 80f9389837..e78514d8e9 100755 --- a/t/t5319-midx.sh +++ b/t/t5319-midx.sh @@ -3,9 +3,19 @@ test_description='multi-pack-indexes' . ./test-lib.sh +midx_read_expect() { + cat >expect <<- EOF + header: 4d494458 1 1 0 0 + object_dir: . + EOF + git midx read --object-dir=. >actual && + test_cmp expect actual +} + test_expect_success 'write midx with no packs' ' git midx --object-dir=. write && - test_path_is_file pack/multi-pack-index + test_path_is_file pack/multi-pack-index && + midx_read_expect ' test_done -- 2.18.0.rc1