Rename stuff to git_indexer_ Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
diff --git a/include/git2/indexer.h b/include/git2/indexer.h
index 34f25b9..f32b1ef 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 97f08da..2418137 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;
@@ -137,27 +138,114 @@ cleanup:
}
/*
+ * 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);
}
+