This function tries to lookup sha1-cache. If it's found, struct commit is filled, no actual commit parsing is done. Otherwise parse_commit() is called. Because sha1-cache only has information enough for rev machinery (tree, parent and date), this function is hardly suitable for general use. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@xxxxxxxxx> --- builtin/reflog.c | 2 +- commit.c | 36 +++++++++++++++++++++++++++++++----- commit.h | 1 + log-tree.c | 2 +- revision.c | 10 +++++----- upload-pack.c | 2 +- walker.c | 2 +- 7 files changed, 41 insertions(+), 14 deletions(-) diff --git a/builtin/reflog.c b/builtin/reflog.c index 062d7da..b15ff98 100644 --- a/builtin/reflog.c +++ b/builtin/reflog.c @@ -240,7 +240,7 @@ static void mark_reachable(struct expire_reflog_cb *cb) free(entry); if (commit->object.flags & REACHABLE) continue; - if (parse_commit(commit)) + if (parse_commit_limited(commit)) continue; commit->object.flags |= REACHABLE; if (commit->date < expire_limit) { diff --git a/commit.c b/commit.c index 946ea70..aa32658 100644 --- a/commit.c +++ b/commit.c @@ -7,6 +7,7 @@ #include "revision.h" #include "notes.h" #include "gpg-interface.h" +#include "sha1_cache.h" int save_commit_buffer = 1; @@ -28,7 +29,11 @@ static struct commit *check_commit(struct object *obj, struct commit *lookup_commit_reference_gently(const unsigned char *sha1, int quiet) { - struct object *obj = deref_tag(parse_object(sha1), NULL, 0); + struct object *obj; + struct commit *c = lookup_commit(sha1); + if (c) + return c; + obj = deref_tag(parse_object(sha1), NULL, 0); if (!obj) return NULL; @@ -258,6 +263,12 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s if (item->object.parsed) return 0; + + if (item->parents) { + free_commit_list(item->parents); + item->parents = NULL; + } + item->object.parsed = 1; tail += size; if (tail <= bufptr + 46 || memcmp(bufptr, "tree ", 5) || bufptr[45] != '\n') @@ -332,6 +343,21 @@ int parse_commit(struct commit *item) return ret; } +int parse_commit_limited(struct commit *c) +{ + unsigned char tree[20]; + unsigned char parent[20]; + + if (c->object.parsed || c->parents) + return 0; + if (has_commit_cache(c->object.sha1, tree, parent, &c->date)) { + commit_list_insert(lookup_commit(parent), &c->parents); + c->tree = lookup_tree(tree); + return 0; + } + return parse_commit(c); +} + int find_commit_subject(const char *commit_buffer, const char **subject) { const char *eol; @@ -413,7 +439,7 @@ struct commit *pop_most_recent_commit(struct commit_list **list, while (parents) { struct commit *commit = parents->item; - if (!parse_commit(commit) && !(commit->object.flags & mark)) { + if (!parse_commit_limited(commit) && !(commit->object.flags & mark)) { commit->object.flags |= mark; commit_list_insert_by_date(commit, list); } @@ -605,10 +631,10 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co return commit_list_insert(one, &result); } - if (parse_commit(one)) + if (parse_commit_limited(one)) return NULL; for (i = 0; i < n; i++) { - if (parse_commit(twos[i])) + if (parse_commit_limited(twos[i])) return NULL; } @@ -645,7 +671,7 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co parents = parents->next; if ((p->object.flags & flags) == flags) continue; - if (parse_commit(p)) + if (parse_commit_limited(p)) return NULL; p->object.flags |= flags; commit_list_insert_by_date(p, &list); diff --git a/commit.h b/commit.h index 154c0e3..113303b 100644 --- a/commit.h +++ b/commit.h @@ -47,6 +47,7 @@ struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_n int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size); int parse_commit(struct commit *item); +int parse_commit_limited(struct commit *item); /* Find beginning and length of commit subject. */ int find_commit_subject(const char *commit_buffer, const char **subject); diff --git a/log-tree.c b/log-tree.c index cea8756..047ddec 100644 --- a/log-tree.c +++ b/log-tree.c @@ -643,7 +643,7 @@ void show_log(struct rev_info *opt) show_mergetag(opt, commit); } - if (!commit->buffer) + if (!commit->buffer && parse_commit(commit) < 0) return; /* diff --git a/revision.c b/revision.c index c97d834..4c229fd 100644 --- a/revision.c +++ b/revision.c @@ -273,7 +273,7 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object */ if (object->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)object; - if (parse_commit(commit) < 0) + if (parse_commit_limited(commit) < 0) die("unable to parse commit %s", name); if (flags & UNINTERESTING) { commit->object.flags |= UNINTERESTING; @@ -465,7 +465,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) */ if (revs->first_parent_only && nth_parent++) break; - if (parse_commit(p) < 0) + if (parse_commit_limited(p) < 0) die("cannot simplify commit %s (because of %s)", sha1_to_hex(commit->object.sha1), sha1_to_hex(p->object.sha1)); @@ -498,7 +498,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) * IOW, we pretend this parent is a * "root" commit. */ - if (parse_commit(p) < 0) + if (parse_commit_limited(p) < 0) die("cannot simplify commit %s (invalid %s)", sha1_to_hex(commit->object.sha1), sha1_to_hex(p->object.sha1)); @@ -561,7 +561,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, parent = parent->next; if (p) p->object.flags |= UNINTERESTING; - if (parse_commit(p) < 0) + if (parse_commit_limited(p) < 0) continue; if (p->parents) mark_parents_uninteresting(p); @@ -588,7 +588,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, for (parent = commit->parents; parent; parent = parent->next) { struct commit *p = parent->item; - if (parse_commit(p) < 0) + if (parse_commit_limited(p) < 0) return -1; if (revs->show_source && !p->util) p->util = commit->util; diff --git a/upload-pack.c b/upload-pack.c index bb08e2e..d30e604 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -694,7 +694,7 @@ static void receive_needs(void) /* make sure the real parents are parsed */ unregister_shallow(object->sha1); object->parsed = 0; - if (parse_commit((struct commit *)object)) + if (parse_commit_limited((struct commit *)object)) die("invalid commit"); parents = ((struct commit *)object)->parents; while (parents) { diff --git a/walker.c b/walker.c index be389dc..7b818f5 100644 --- a/walker.c +++ b/walker.c @@ -71,7 +71,7 @@ static struct commit_list *complete = NULL; static int process_commit(struct walker *walker, struct commit *commit) { - if (parse_commit(commit)) + if (parse_commit_limited(commit)) return -1; while (complete && complete->item->date >= commit->date) { -- 1.7.3.1.256.g2539c.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html