From ab525a7463492aa64c936b59165ab33f6264f1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Thu, 7 Jul 2011 19:20:13 +0200 Subject: [PATCH] Rename stuff to git_indexer_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Carlos Martín Nieto --- include/git2/indexer.h | 10 ++-- src/indexer.c | 107 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 103 insertions(+), 14 deletions(-) diff --git a/include/git2/indexer.h b/include/git2/indexer.h index 34f25b97c..f32b1ef6b 100644 --- a/include/git2/indexer.h +++ b/include/git2/indexer.h @@ -5,15 +5,15 @@ typedef struct git_indexer_stats { unsigned int total; - unsigned int parsed; + unsigned int processed; } git_indexer_stats; -typedef struct git_pack_indexer git_pack_indexer; +typedef struct git_indexer git_indexer; -GIT_EXTERN(int) git_pack_indexer_new(git_pack_indexer **out, const char *packname); -GIT_EXTERN(int) git_pack_indexer_run(git_pack_indexer *idx, int (*cb)(const git_indexer_stats *, void *), void *data); -GIT_EXTERN(void) git_pack_indexer_free(git_pack_indexer *idx); +GIT_EXTERN(int) git_indexer_new(git_indexer **out, const char *packname); +GIT_EXTERN(int) git_indexer_run(git_indexer *idx, int (*cb)(const git_indexer_stats *, void *), void *data); +GIT_EXTERN(void) git_indexer_free(git_indexer *idx); #endif diff --git a/src/indexer.c b/src/indexer.c index 97f08dae1..241813724 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -24,21 +24,22 @@ */ #include "git2/indexer.h" +#include "git2/zlib.h" #include "common.h" #include "pack.h" #include "mwindow.h" #include "posix.h" -typedef struct git_pack_indexer { +typedef struct git_indexer { struct pack_file *pack; git_vector objects; git_vector deltas; struct stat st; git_indexer_stats stats; -} git_pack_indexer; +} git_indexer; -static int parse_header(git_pack_indexer *idx) +static int parse_header(git_indexer *idx) { struct pack_header hdr; int error; @@ -81,13 +82,13 @@ cleanup: return error; } -int git_pack_indexer_new(git_pack_indexer **out, const char *packname) +int git_indexer_new(git_indexer **out, const char *packname) { - struct git_pack_indexer *idx; + git_indexer *idx; unsigned int namelen; int ret, error; - idx = git__malloc(sizeof(struct git_pack_indexer)); + idx = git__malloc(sizeof(git_indexer)); if (idx == NULL) return GIT_ENOMEM; @@ -136,28 +137,115 @@ cleanup: return error; } +/* + * Parse the variable-width length and return it. Assumes that the + * whole number exists inside the buffer. As this is the git format, + * the first byte only contains length information in the lower nibble + * because the higher one is used for type and continuation. The + * output parameter is necessary because we don't know how long the + * entry is actually going to be. + */ +static unsigned long entry_len(const char **bufout, const char *buf) +{ + unsigned long size, c; + const char *p = buf; + unsigned shift; + + c = *p; + size = c & 0xf; + shift = 4; + + /* As long as the MSB is set, we need to continue */ + while (c & 0x80) { + p++; + c = *p; + size += (c & 0x7f) << shift; + shift += 7; + } + + *bufout = p; + return size; +} + +static git_otype entry_type(const char *buf) +{ + return (*buf >> 4) & 7; +} + /* * Create the index. Every time something interesting happens * (something has been parse or resolved), the callback gets called * with some stats so it can tell the user how hard we're working */ -int git_pack_indexer_run(git_pack_indexer *idx, int (*cb)(const git_indexer_stats *, void *), void *data) +int git_indexer_run(git_indexer *idx, int (*cb)(const git_indexer_stats *, void *), void *data) { git_mwindow_file *mwf = &idx->pack->mwf; + git_mwindow *w = NULL; + off_t off = 0; int error; + const char *ptr; + unsigned int fanout[256] = {0}; error = git_mwindow_file_register(mwf); if (error < GIT_SUCCESS) return git__rethrow(error, "Failed to register mwindow file"); - /* notify early */ + /* Notify before the first one */ if (cb) cb(&idx->stats, data); + while (idx->stats.processed < idx->stats.total) { + unsigned long size; + git_otype type; + + /* 4k is a bit magic for the moment */ + ptr = git_mwindow_open(mwf, &w, idx->pack->pack_fd, 4096, off, 0, NULL); + if (ptr == NULL) { + error = GIT_ENOMEM; + goto cleanup; + } + + /* + * The size is when expanded, so we need to inflate the object + * so we know where the next one ist. + */ + type = entry_type(ptr); + size = entry_len(&data, ptr); + + switch (type) { + case GIT_OBJ_COMMIT: + case GIT_OBJ_TREE: + case GIT_OBJ_BLOB: + case GIT_OBJ_TAG: + break; + default: + error = git__throw(GIT_EOBJCORRUPTED, "Invalid object type"); + goto cleanup; + } + + /* + * Do we need to uncompress everything if we're not running in + * strict mode? Or at least can't we free the data? + */ + + /* Get a window for the compressed data */ + //ptr = git_mwindow_open(mwf, &w, idx->pack->pack_fd, size, data - ptr, 0, NULL); + + idx->stats.processed++; + + if (cb) + cb(&idx->stats, data); + + } + +cleanup: + git_mwindow_free_all(mwf); + return error; + } -void git_pack_indexer_free(git_pack_indexer *idx) +void git_indexer_free(git_indexer *idx) { p_close(idx->pack->pack_fd); git_vector_free(&idx->objects); @@ -165,3 +253,4 @@ void git_pack_indexer_free(git_pack_indexer *idx) free(idx->pack); free(idx); } +