Merge pull request #1112 from barrbrain/odb-pack-read-header odb-pack: resurrect pack_backend__read_header
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
diff --git a/src/delta-apply.c b/src/delta-apply.c
index 815ca8f..85e2ef8 100644
--- a/src/delta-apply.c
+++ b/src/delta-apply.c
@@ -36,6 +36,19 @@ static int hdr_sz(
return 0;
}
+int git__delta_read_header(
+ const unsigned char *delta,
+ size_t delta_len,
+ size_t *base_sz,
+ size_t *res_sz)
+{
+ const unsigned char *delta_end = delta + delta_len;
+ if ((hdr_sz(base_sz, &delta, delta_end) < 0) ||
+ (hdr_sz(res_sz, &delta, delta_end) < 0))
+ return -1;
+ return 0;
+}
+
int git__delta_apply(
git_rawobj *out,
const unsigned char *base,
diff --git a/src/delta-apply.h b/src/delta-apply.h
index 66fa76d..9aea4ac 100644
--- a/src/delta-apply.h
+++ b/src/delta-apply.h
@@ -30,4 +30,21 @@ extern int git__delta_apply(
const unsigned char *delta,
size_t delta_len);
+/**
+ * Read the header of a git binary delta.
+ *
+ * @param delta the delta to execute copy/insert instructions from.
+ * @param delta_len total number of bytes in the delta.
+ * @param base_sz pointer to store the base size field.
+ * @param res_sz pointer to store the result size field.
+ * @return
+ * - 0 on a successful decoding the header.
+ * - GIT_ERROR if the delta is corrupt.
+ */
+extern int git__delta_read_header(
+ const unsigned char *delta,
+ size_t delta_len,
+ size_t *base_sz,
+ size_t *res_sz);
+
#endif
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 35bf158..fc282dd 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -384,19 +384,18 @@ cleanup:
*
***********************************************************/
-/*
-int pack_backend__read_header(git_rawobj *obj, git_odb_backend *backend, const git_oid *oid)
+static int pack_backend__read_header(size_t *len_p, git_otype *type_p, struct git_odb_backend *backend, const git_oid *oid)
{
- pack_location location;
+ struct git_pack_entry e;
+ int error;
- assert(obj && backend && oid);
+ assert(len_p && type_p && backend && oid);
- if (locate_packfile(&location, (struct pack_backend *)backend, oid) < 0)
- return GIT_ENOTFOUND;
+ if ((error = pack_entry_find(&e, (struct pack_backend *)backend, oid)) < 0)
+ return error;
- return read_header_packed(obj, &location);
+ return git_packfile_resolve_header(len_p, type_p, e.p, e.offset);
}
-*/
static int pack_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
{
@@ -579,7 +578,7 @@ int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
backend->parent.read = &pack_backend__read;
backend->parent.read_prefix = &pack_backend__read_prefix;
- backend->parent.read_header = NULL;
+ backend->parent.read_header = &pack_backend__read_header;
backend->parent.exists = &pack_backend__exists;
backend->parent.foreach = &pack_backend__foreach;
backend->parent.free = &pack_backend__free;
@@ -616,7 +615,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend->parent.read = &pack_backend__read;
backend->parent.read_prefix = &pack_backend__read_prefix;
- backend->parent.read_header = NULL;
+ backend->parent.read_header = &pack_backend__read_header;
backend->parent.exists = &pack_backend__exists;
backend->parent.foreach = &pack_backend__foreach;
backend->parent.writepack = &pack_backend__writepack;
diff --git a/src/pack.c b/src/pack.c
index 6cb46d3..d7d3939 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -277,6 +277,56 @@ int git_packfile_unpack_header(
return 0;
}
+int git_packfile_resolve_header(
+ size_t *size_p,
+ git_otype *type_p,
+ struct git_pack_file *p,
+ git_off_t offset)
+{
+ git_mwindow *w_curs = NULL;
+ git_off_t curpos = offset;
+ size_t size;
+ git_otype type;
+ git_off_t base_offset;
+ int error;
+
+ error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
+ git_mwindow_close(&w_curs);
+ if (error < 0)
+ return error;
+
+ if (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
+ size_t base_size;
+ git_rawobj delta;
+ base_offset = get_delta_base(p, &w_curs, &curpos, type, offset);
+ git_mwindow_close(&w_curs);
+ error = packfile_unpack_compressed(&delta, p, &w_curs, &curpos, size, type);
+ git_mwindow_close(&w_curs);
+ if (error < 0)
+ return error;
+ error = git__delta_read_header(delta.data, delta.len, &base_size, size_p);
+ git__free(delta.data);
+ if (error < 0)
+ return error;
+ } else
+ *size_p = size;
+
+ while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
+ curpos = base_offset;
+ error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
+ git_mwindow_close(&w_curs);
+ if (error < 0)
+ return error;
+ if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA)
+ break;
+ base_offset = get_delta_base(p, &w_curs, &curpos, type, base_offset);
+ git_mwindow_close(&w_curs);
+ }
+ *type_p = type;
+
+ return error;
+}
+
static int packfile_unpack_delta(
git_rawobj *obj,
struct git_pack_file *p,
diff --git a/src/pack.h b/src/pack.h
index 9fb26b6..c1277fd 100644
--- a/src/pack.h
+++ b/src/pack.h
@@ -83,6 +83,12 @@ int git_packfile_unpack_header(
git_mwindow **w_curs,
git_off_t *curpos);
+int git_packfile_resolve_header(
+ size_t *size_p,
+ git_otype *type_p,
+ struct git_pack_file *p,
+ git_off_t offset);
+
int git_packfile_unpack(git_rawobj *obj, struct git_pack_file *p, git_off_t *obj_offset);
int packfile_unpack_compressed(
git_rawobj *obj,