summaryrefslogtreecommitdiff
path: root/sha1_file.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2014-01-10 18:33:11 (GMT)
committerJunio C Hamano <gitster@pobox.com>2014-01-10 18:33:11 (GMT)
commitb2132068c6df38b24b49dfc6fbbf0645b21ec037 (patch)
tree56fc704257887e0788cc73e654393605da8171c2 /sha1_file.c
parentf06a5e607dde266884db4a99b70fbee09d5c5efc (diff)
parent65ea9c3c3d0e74b1f8c0c1d9fea6988550133dba (diff)
downloadgit-b2132068c6df38b24b49dfc6fbbf0645b21ec037.zip
git-b2132068c6df38b24b49dfc6fbbf0645b21ec037.tar.gz
git-b2132068c6df38b24b49dfc6fbbf0645b21ec037.tar.bz2
Merge branch 'jk/oi-delta-base'
Teach "cat-file --batch" to show delta-base object name for a packed object that is represented as a delta. * jk/oi-delta-base: cat-file: provide %(deltabase) batch format sha1_object_info_extended: provide delta base sha1s
Diffstat (limited to 'sha1_file.c')
-rw-r--r--sha1_file.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/sha1_file.c b/sha1_file.c
index a2ff296..e13bd2c 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1690,6 +1690,38 @@ static off_t get_delta_base(struct packed_git *p,
return base_offset;
}
+/*
+ * Like get_delta_base above, but we return the sha1 instead of the pack
+ * offset. This means it is cheaper for REF deltas (we do not have to do
+ * the final object lookup), but more expensive for OFS deltas (we
+ * have to load the revidx to convert the offset back into a sha1).
+ */
+static const unsigned char *get_delta_base_sha1(struct packed_git *p,
+ struct pack_window **w_curs,
+ off_t curpos,
+ enum object_type type,
+ off_t delta_obj_offset)
+{
+ if (type == OBJ_REF_DELTA) {
+ unsigned char *base = use_pack(p, w_curs, curpos, NULL);
+ return base;
+ } else if (type == OBJ_OFS_DELTA) {
+ struct revindex_entry *revidx;
+ off_t base_offset = get_delta_base(p, w_curs, &curpos,
+ type, delta_obj_offset);
+
+ if (!base_offset)
+ return NULL;
+
+ revidx = find_pack_revindex(p, base_offset);
+ if (!revidx)
+ return NULL;
+
+ return nth_packed_object_sha1(p, revidx->nr);
+ } else
+ return NULL;
+}
+
int unpack_object_header(struct packed_git *p,
struct pack_window **w_curs,
off_t *curpos,
@@ -1847,6 +1879,22 @@ static int packed_object_info(struct packed_git *p, off_t obj_offset,
}
}
+ if (oi->delta_base_sha1) {
+ if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
+ const unsigned char *base;
+
+ base = get_delta_base_sha1(p, &w_curs, curpos,
+ type, obj_offset);
+ if (!base) {
+ type = OBJ_BAD;
+ goto out;
+ }
+
+ hashcpy(oi->delta_base_sha1, base);
+ } else
+ hashclr(oi->delta_base_sha1);
+ }
+
out:
unuse_pack(&w_curs);
return type;
@@ -2430,6 +2478,9 @@ static int sha1_loose_object_info(const unsigned char *sha1,
git_zstream stream;
char hdr[32];
+ if (oi->delta_base_sha1)
+ hashclr(oi->delta_base_sha1);
+
/*
* If we don't care about type or size, then we don't
* need to look inside the object at all. Note that we
@@ -2481,6 +2532,8 @@ int sha1_object_info_extended(const unsigned char *sha1, struct object_info *oi,
*(oi->sizep) = co->size;
if (oi->disk_sizep)
*(oi->disk_sizep) = 0;
+ if (oi->delta_base_sha1)
+ hashclr(oi->delta_base_sha1);
oi->whence = OI_CACHED;
return 0;
}