X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=commit.c;h=67e11d7a4f211c1d2cf62635029f60597ff618de;hb=8e1618f9612a78ea09b2a926797c781fe06027c9;hp=56192587afa7454e5db8c5ac3e4a937c1f0694ea;hpb=10d781b9caa4f71495c7b34963bef137216f86a8;p=git.git diff --git a/commit.c b/commit.c index 56192587..67e11d7a 100644 --- a/commit.c +++ b/commit.c @@ -1,7 +1,8 @@ -#include +#include "cache.h" #include "tag.h" #include "commit.h" -#include "cache.h" + +int save_commit_buffer = 1; struct sort_node { @@ -33,6 +34,8 @@ enum cmit_fmt get_commit_format(const char *arg) return CMIT_FMT_SHORT; if (!strcmp(arg, "=full")) return CMIT_FMT_FULL; + if (!strcmp(arg, "=fuller")) + return CMIT_FMT_FULLER; if (!strcmp(arg, "=oneline")) return CMIT_FMT_ONELINE; die("invalid --pretty format"); @@ -54,7 +57,7 @@ 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)); + struct object *obj = deref_tag(parse_object(sha1), NULL, 0); if (!obj) return NULL; @@ -102,7 +105,7 @@ static unsigned long parse_commit_date(const char *buf) static struct commit_graft { unsigned char sha1[20]; int nr_parent; - unsigned char parent[][20]; /* more */ + unsigned char parent[0][20]; /* more */ } **commit_graft; static int commit_graft_alloc, commit_graft_nr; @@ -201,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; @@ -211,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; @@ -227,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) { @@ -238,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; } @@ -264,7 +280,7 @@ int parse_commit(struct commit *item) sha1_to_hex(item->object.sha1)); } ret = parse_commit_buffer(item, buffer, size); - if (!ret) { + if (save_commit_buffer && !ret) { item->buffer = buffer; return 0; } @@ -336,6 +352,21 @@ 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) { + struct commit *parent = parents->item; + if (parent && parent->object.parsed && + (parent->object.flags & mark)) + clear_commit_marks(parent, mark); + parents = parents->next; + } +} + /* * Generic support for pretty-printing the header */ @@ -357,9 +388,10 @@ static int get_one_line(const char *msg, unsigned long len) static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const char *line) { char *date; - unsigned int namelen; + int namelen; unsigned long time; int tz, ret; + const char *filler = " "; if (fmt == CMIT_FMT_ONELINE) return 0; @@ -370,9 +402,20 @@ static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf, const c time = strtoul(date, &date, 10); tz = strtol(date, NULL, 10); - ret = sprintf(buf, "%s: %.*s\n", what, namelen, line); - if (fmt == CMIT_FMT_MEDIUM) + ret = sprintf(buf, "%s: %.*s%.*s\n", what, + (fmt == CMIT_FMT_FULLER) ? 4 : 0, + filler, namelen, line); + switch (fmt) { + case CMIT_FMT_MEDIUM: ret += sprintf(buf + ret, "Date: %s\n", show_date(time, tz)); + break; + case CMIT_FMT_FULLER: + ret += sprintf(buf + ret, "%sDate: %s\n", what, show_date(time, tz)); + break; + default: + /* notin' */ + break; + } return ret; } @@ -383,33 +426,37 @@ static int is_empty_line(const char *line, int len) return !len; } -static int add_parent_info(enum cmit_fmt fmt, char *buf, const char *line, int parents) +static int add_merge_info(enum cmit_fmt fmt, char *buf, const struct commit *commit, int abbrev) { - int offset = 0; + struct commit_list *parent = commit->parents; + int offset; - if (fmt == CMIT_FMT_ONELINE) - return offset; - switch (parents) { - case 1: - break; - case 2: - /* Go back to the previous line: 40 characters of previous parent, and one '\n' */ - offset = sprintf(buf, "Merge: %.40s\n", line-41); - /* Fallthrough */ - default: - /* Replace the previous '\n' with a space */ - buf[offset-1] = ' '; - offset += sprintf(buf + offset, "%.40s\n", line+7); + if ((fmt == CMIT_FMT_ONELINE) || !parent || !parent->next) + return 0; + + offset = sprintf(buf, "Merge:"); + + while (parent) { + struct commit *p = parent->item; + const char *hex = abbrev + ? find_unique_abbrev(p->object.sha1, abbrev) + : sha1_to_hex(p->object.sha1); + char *dots = (abbrev && strlen(hex) != 40) ? "..." : ""; + parent = parent->next; + + offset += sprintf(buf + offset, " %s%s", hex, dots); } + buf[offset++] = '\n'; return offset; } -unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned long len, char *buf, unsigned long space) +unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, unsigned long len, char *buf, unsigned long space, int abbrev) { int hdr = 1, body = 0; unsigned long offset = 0; - int parents = 0; int indent = (fmt == CMIT_FMT_ONELINE) ? 0 : 4; + int parents_shown = 0; + const char *msg = commit->buffer; for (;;) { const char *line = msg; @@ -445,14 +492,29 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const char *msg, unsigned l if (!memcmp(line, "parent ", 7)) { if (linelen != 48) die("bad parent line in commit"); - offset += add_parent_info(fmt, buf + offset, line, ++parents); + continue; } - if (!memcmp(line, "author ", 7)) - offset += add_user_info("Author", fmt, buf + offset, line + 7); - if (fmt == CMIT_FMT_FULL) { - if (!memcmp(line, "committer ", 10)) - offset += add_user_info("Commit", fmt, buf + offset, line + 10); + + if (!parents_shown) { + offset += add_merge_info(fmt, buf + offset, + commit, abbrev); + parents_shown = 1; + continue; } + /* + * MEDIUM == DEFAULT shows only author with dates. + * FULL shows both authors but not dates. + * FULLER shows both authors and dates. + */ + if (!memcmp(line, "author ", 7)) + offset += add_user_info("Author", fmt, + buf + offset, + line + 7); + if (!memcmp(line, "committer ", 10) && + (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) + offset += add_user_info("Commit", fmt, + buf + offset, + line + 10); continue; } @@ -512,7 +574,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; @@ -523,6 +585,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 */ @@ -556,11 +621,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; }