summaryrefslogtreecommitdiff
path: root/builtin/rev-list.c
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2012-03-14 21:40:55 +0700
committerJunio C Hamano <gitster@pobox.com>2012-03-15 11:29:32 -0700
commit752661636262ef92f1d69ccd36fd651599805fcc (patch)
treee58051e3c69cd6d7dd0a31676a2bf4ace40ba20b /builtin/rev-list.c
parenta46034819ecce6872bff099f3d75589f4d38c00c (diff)
downloadgit-nd/optim-connected.tar.gz
{fetch,receive}-pack: skip sha-1 integrity test on objects from new packnd/optim-connected
When we fetch or push, usually "git rev-list --verify-objects --not --all --stdin" is used to make sure that all objects between existing refs and new refs are good. This means no gaps in between, all objects are well-formed, object content agrees with its sha-1 signature. For the last one, --verify-objects calls check_sha1_signature() via parse_object(). check_sha1_signature() is an expensive operation, especially when new refs are far away from existing ones because all objects in between are re-hashed. Because objects coming from the new pack are already hashed by index-pack, we can trust their integrity. The only objects left to check are existing ones in repo but has no connection to any current refs. Pass the new pack id down to--verify-objects and skip check_sha1_signature() on objects from that pack. As an (extreme) example, a repository is created with only one commit: e83c516 (Initial revision of "git", the information manager from hell - 2005-04-07). The rest of git.git is fetched on top. Without the patch: $ time git fetch file:///home/pclouds/w/git/.git remote: Counting objects: 125656, done. remote: Compressing objects: 100% (33280/33280), done. remote: Total 125656 (delta 92585), reused 123464 (delta 90682) Receiving objects: 100% (125656/125656), 34.60 MiB | 8.47 MiB/s, done. Resolving deltas: 100% (92585/92585), done. >From file:///home/pclouds/t/test/ * branch HEAD -> FETCH_HEAD real 1m30.437s user 1m31.338s sys 0m1.687s With the patch: $ time git fetch file:///home/pclouds/w/git/.git remote: Counting objects: 125656, done. remote: Compressing objects: 100% (33280/33280), done. remote: Total 125656 (delta 92585), reused 123464 (delta 90682) Receiving objects: 100% (125656/125656), 34.60 MiB | 7.86 MiB/s, done. Resolving deltas: 100% (92585/92585), done. >From file:///home/pclouds/t/test/ * branch HEAD -> FETCH_HEAD real 0m52.182s user 0m53.151s sys 0m1.465s Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/rev-list.c')
-rw-r--r--builtin/rev-list.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 4c4d404afc..21d714b528 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -180,8 +180,24 @@ static void finish_object(struct object *obj,
struct rev_list_info *info = cb_data;
if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1))
die("missing blob object '%s'", sha1_to_hex(obj->sha1));
- if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
- parse_object(obj->sha1);
+ if (info->revs->verify_objects &&
+ !obj->parsed && obj->type != OBJ_COMMIT) {
+ const char *safe_pack = info->revs->safe_pack;
+ struct object_info oi;
+ int safe = 0;
+ memset(&oi, 0, sizeof(oi));
+ if (*safe_pack &&
+ sha1_object_info_extended(obj->sha1, &oi) >= 0 &&
+ oi.whence == OI_PACKED) {
+ const char *pack = oi.u.packed.pack->pack_name;
+ int len = strlen(pack);
+ assert(strncmp(pack + len - 51, "/pack-", 6) == 0);
+ assert(strcmp(pack + len - 5, ".pack") == 0);
+ safe = !memcmp(safe_pack, pack + len - 45, 40);
+ }
+ if (!safe)
+ parse_object(obj->sha1);
+ }
}
static void show_object(struct object *obj,