X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=commit.c;h=56efc69f1f4bf1568eaa549bed16f7cc2cd669ba;hb=5a2282de13c4da13f979185e652c8a08e2481fd1;hp=534c03ea59efc3898857e4853536ec4f4c189937;hpb=f7a2eb735982e921ae4379f1dcf5f7a023610393;p=git.git diff --git a/commit.c b/commit.c index 534c03ea..56efc69f 100644 --- a/commit.c +++ b/commit.c @@ -1,6 +1,6 @@ +#include "cache.h" #include "tag.h" #include "commit.h" -#include "cache.h" int save_commit_buffer = 1; @@ -204,6 +204,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) unsigned char parent[20]; struct commit_list **pptr; struct commit_graft *graft; + unsigned n_refs = 0; if (item->object.parsed) return 0; @@ -214,7 +215,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) return error("bad tree pointer in commit %s\n", sha1_to_hex(item->object.sha1)); item->tree = lookup_tree(parent); if (item->tree) - add_ref(&item->object, &item->tree->object); + n_refs++; bufptr += 46; /* "tree " + "hex sha1" + "\n" */ pptr = &item->parents; @@ -230,7 +231,7 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) new_parent = lookup_commit(parent); if (new_parent) { pptr = &commit_list_insert(new_parent, pptr)->next; - add_ref(&item->object, &new_parent->object); + n_refs++; } } if (graft) { @@ -241,10 +242,22 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) if (!new_parent) continue; pptr = &commit_list_insert(new_parent, pptr)->next; - add_ref(&item->object, &new_parent->object); + n_refs++; } } item->date = parse_commit_date(bufptr); + + if (track_object_refs) { + unsigned i = 0; + struct commit_list *p; + struct object_refs *refs = alloc_object_refs(n_refs); + if (item->tree) + refs->ref[i++] = &item->tree->object; + for (p = item->parents; p; p = p->next) + refs->ref[i++] = &p->item->object; + set_object_refs(&item->object, refs); + } + return 0; } @@ -339,6 +352,19 @@ struct commit *pop_most_recent_commit(struct commit_list **list, return ret; } +void clear_commit_marks(struct commit *commit, unsigned int mark) +{ + struct commit_list *parents; + + parents = commit->parents; + commit->object.flags &= ~mark; + while (parents) { + if (parents->item && parents->item->object.parsed) + clear_commit_marks(parents->item, mark); + parents = parents->next; + } +} + /* * Generic support for pretty-printing the header */ @@ -536,7 +562,7 @@ int count_parents(struct commit * commit) void sort_in_topological_order(struct commit_list ** list) { struct commit_list * next = *list; - struct commit_list * work = NULL; + struct commit_list * work = NULL, **insert; struct commit_list ** pptr = list; struct sort_node * nodes; struct sort_node * next_nodes; @@ -547,6 +573,9 @@ void sort_in_topological_order(struct commit_list ** list) next = next->next; count++; } + + if (!count) + return; /* allocate an array to help sort the list */ nodes = xcalloc(count, sizeof(*nodes)); /* link the list to the array */ @@ -580,11 +609,12 @@ void sort_in_topological_order(struct commit_list ** list) * the tips serve as a starting set for the work queue. */ next=*list; + insert = &work; while (next) { struct sort_node * node = (struct sort_node *)next->item->object.util; if (node->indegree == 0) { - commit_list_insert(next->item, &work); + insert = &commit_list_insert(next->item, insert)->next; } next=next->next; }