diff options
Diffstat (limited to 'commit.c')
-rw-r--r-- | commit.c | 153 |
1 files changed, 84 insertions, 69 deletions
@@ -11,6 +11,7 @@ #include "commit-slab.h" #include "prio-queue.h" #include "sha1-lookup.h" +#include "wt-status.h" static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **); @@ -18,38 +19,38 @@ int save_commit_buffer = 1; const char *commit_type = "commit"; -struct commit *lookup_commit_reference_gently(const unsigned char *sha1, +struct commit *lookup_commit_reference_gently(const struct object_id *oid, int quiet) { - struct object *obj = deref_tag(parse_object(sha1), NULL, 0); + struct object *obj = deref_tag(parse_object(oid), NULL, 0); if (!obj) return NULL; return object_as_type(obj, OBJ_COMMIT, quiet); } -struct commit *lookup_commit_reference(const unsigned char *sha1) +struct commit *lookup_commit_reference(const struct object_id *oid) { - return lookup_commit_reference_gently(sha1, 0); + return lookup_commit_reference_gently(oid, 0); } -struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name) +struct commit *lookup_commit_or_die(const struct object_id *oid, const char *ref_name) { - struct commit *c = lookup_commit_reference(sha1); + struct commit *c = lookup_commit_reference(oid); if (!c) die(_("could not parse %s"), ref_name); - if (hashcmp(sha1, c->object.oid.hash)) { + if (oidcmp(oid, &c->object.oid)) { warning(_("%s %s is not a commit!"), - ref_name, sha1_to_hex(sha1)); + ref_name, oid_to_hex(oid)); } return c; } -struct commit *lookup_commit(const unsigned char *sha1) +struct commit *lookup_commit(const struct object_id *oid) { - struct object *obj = lookup_object(sha1); + struct object *obj = lookup_object(oid->hash); if (!obj) - return create_object(sha1, alloc_commit_node()); + return create_object(oid->hash, alloc_commit_node()); return object_as_type(obj, OBJ_COMMIT, 0); } @@ -58,15 +59,15 @@ struct commit *lookup_commit_reference_by_name(const char *name) struct object_id oid; struct commit *commit; - if (get_sha1_committish(name, oid.hash)) + if (get_oid_committish(name, &oid)) return NULL; - commit = lookup_commit_reference(oid.hash); + commit = lookup_commit_reference(&oid); if (parse_commit(commit)) return NULL; return commit; } -static unsigned long parse_commit_date(const char *buf, const char *tail) +static timestamp_t parse_commit_date(const char *buf, const char *tail) { const char *dateptr; @@ -89,8 +90,8 @@ static unsigned long parse_commit_date(const char *buf, const char *tail) /* nada */; if (buf >= tail) return 0; - /* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */ - return strtoul(dateptr, NULL, 10); + /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */ + return parse_timestamp(dateptr, NULL, 10); } static struct commit_graft **commit_graft; @@ -133,47 +134,53 @@ int register_commit_graft(struct commit_graft *graft, int ignore_dups) return 0; } -struct commit_graft *read_graft_line(char *buf, int len) +struct commit_graft *read_graft_line(struct strbuf *line) { /* The format is just "Commit Parent1 Parent2 ...\n" */ - int i; + int i, phase; + const char *tail = NULL; struct commit_graft *graft = NULL; - const int entry_size = GIT_SHA1_HEXSZ + 1; + struct object_id dummy_oid, *oid; - while (len && isspace(buf[len-1])) - buf[--len] = '\0'; - if (buf[0] == '#' || buf[0] == '\0') + strbuf_rtrim(line); + if (!line->len || line->buf[0] == '#') return NULL; - if ((len + 1) % entry_size) - goto bad_graft_data; - i = (len + 1) / entry_size - 1; - graft = xmalloc(st_add(sizeof(*graft), st_mult(GIT_SHA1_RAWSZ, i))); - graft->nr_parent = i; - if (get_oid_hex(buf, &graft->oid)) - goto bad_graft_data; - for (i = GIT_SHA1_HEXSZ; i < len; i += entry_size) { - if (buf[i] != ' ') - goto bad_graft_data; - if (get_sha1_hex(buf + i + 1, graft->parent[i/entry_size].hash)) + /* + * phase 0 verifies line, counts hashes in line and allocates graft + * phase 1 fills graft + */ + for (phase = 0; phase < 2; phase++) { + oid = graft ? &graft->oid : &dummy_oid; + if (parse_oid_hex(line->buf, oid, &tail)) goto bad_graft_data; + for (i = 0; *tail != '\0'; i++) { + oid = graft ? &graft->parent[i] : &dummy_oid; + if (!isspace(*tail++) || parse_oid_hex(tail, oid, &tail)) + goto bad_graft_data; + } + if (!graft) { + graft = xmalloc(st_add(sizeof(*graft), + st_mult(sizeof(struct object_id), i))); + graft->nr_parent = i; + } } return graft; bad_graft_data: - error("bad graft data: %s", buf); - free(graft); + error("bad graft data: %s", line->buf); + assert(!graft); return NULL; } static int read_graft_file(const char *graft_file) { - FILE *fp = fopen(graft_file, "r"); + FILE *fp = fopen_or_warn(graft_file, "r"); struct strbuf buf = STRBUF_INIT; if (!fp) return -1; while (!strbuf_getwholeline(&buf, fp, '\n')) { /* The format is just "Commit Parent1 Parent2 ...\n" */ - struct commit_graft *graft = read_graft_line(buf.buf, buf.len); + struct commit_graft *graft = read_graft_line(&buf); if (!graft) continue; if (register_commit_graft(graft, 1)) @@ -198,11 +205,11 @@ static void prepare_commit_graft(void) commit_graft_prepared = 1; } -struct commit_graft *lookup_commit_graft(const unsigned char *sha1) +struct commit_graft *lookup_commit_graft(const struct object_id *oid) { int pos; prepare_commit_graft(); - pos = commit_graft_pos(sha1); + pos = commit_graft_pos(oid->hash); if (pos < 0) return NULL; return commit_graft[pos]; @@ -216,15 +223,14 @@ int for_each_commit_graft(each_commit_graft_fn fn, void *cb_data) return ret; } -int unregister_shallow(const unsigned char *sha1) +int unregister_shallow(const struct object_id *oid) { - int pos = commit_graft_pos(sha1); + int pos = commit_graft_pos(oid->hash); if (pos < 0) return -1; if (pos + 1 < commit_graft_nr) - memmove(commit_graft + pos, commit_graft + pos + 1, - sizeof(struct commit_graft *) - * (commit_graft_nr - pos - 1)); + MOVE_ARRAY(commit_graft + pos, commit_graft + pos + 1, + commit_graft_nr - pos - 1); commit_graft_nr--; return 0; } @@ -286,8 +292,7 @@ void free_commit_buffer(struct commit *commit) { struct commit_buffer *v = buffer_slab_peek(&buffer_slab, commit); if (v) { - free(v->buffer); - v->buffer = NULL; + FREE_AND_NULL(v->buffer); v->size = 0; } } @@ -331,11 +336,11 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s if (get_sha1_hex(bufptr + 5, parent.hash) < 0) return error("bad tree pointer in commit %s", oid_to_hex(&item->object.oid)); - item->tree = lookup_tree(parent.hash); + item->tree = lookup_tree(&parent); bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */ pptr = &item->parents; - graft = lookup_commit_graft(item->object.oid.hash); + graft = lookup_commit_graft(&item->object.oid); while (bufptr + parent_entry_len < tail && !memcmp(bufptr, "parent ", 7)) { struct commit *new_parent; @@ -350,7 +355,7 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s */ if (graft && (graft->nr_parent < 0 || grafts_replace_parents)) continue; - new_parent = lookup_commit(parent.hash); + new_parent = lookup_commit(&parent); if (new_parent) pptr = &commit_list_insert(new_parent, pptr)->next; } @@ -358,7 +363,7 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s int i; struct commit *new_parent; for (i = 0; i < graft->nr_parent; i++) { - new_parent = lookup_commit(graft->parent[i].hash); + new_parent = lookup_commit(&graft->parent[i]); if (!new_parent) continue; pptr = &commit_list_insert(new_parent, pptr)->next; @@ -415,8 +420,7 @@ int find_commit_subject(const char *commit_buffer, const char **subject) p++; if (*p) { p = skip_blank_lines(p + 2); - for (eol = p; *eol && *eol != '\n'; eol++) - ; /* do nothing */ + eol = strchrnul(p, '\n'); } else eol = p; @@ -474,8 +478,8 @@ struct commit_list * commit_list_insert_by_date(struct commit *item, struct comm static int commit_list_compare_by_date(const void *a, const void *b) { - unsigned long a_date = ((const struct commit_list *)a)->item->date; - unsigned long b_date = ((const struct commit_list *)b)->item->date; + timestamp_t a_date = ((const struct commit_list *)a)->item->date; + timestamp_t b_date = ((const struct commit_list *)b)->item->date; if (a_date < b_date) return 1; if (a_date > b_date) @@ -563,7 +567,7 @@ void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark) for (i = 0; i < a->nr; i++) { object = a->objects[i].item; - commit = lookup_commit_reference_gently(object->oid.hash, 1); + commit = lookup_commit_reference_gently(&object->oid, 1); if (commit) clear_commit_marks(commit, mark); } @@ -599,7 +603,7 @@ static void record_author_date(struct author_date_slab *author_date, const char *ident_line; size_t ident_len; char *date_end; - unsigned long date; + timestamp_t date; ident_line = find_commit_header(buffer, "author", &ident_len); if (!ident_line) @@ -608,7 +612,7 @@ static void record_author_date(struct author_date_slab *author_date, !ident.date_begin || !ident.date_end) goto fail_exit; /* malformed "author" line */ - date = strtoul(ident.date_begin, &date_end, 10); + date = parse_timestamp(ident.date_begin, &date_end, 10); if (date_end != ident.date_end) goto fail_exit; /* malformed date */ *(author_date_slab_at(author_date, commit)) = date; @@ -622,8 +626,8 @@ static int compare_commits_by_author_date(const void *a_, const void *b_, { const struct commit *a = a_, *b = b_; struct author_date_slab *author_date = cb_data; - unsigned long a_date = *(author_date_slab_at(author_date, a)); - unsigned long b_date = *(author_date_slab_at(author_date, b)); + timestamp_t a_date = *(author_date_slab_at(author_date, a)); + timestamp_t b_date = *(author_date_slab_at(author_date, b)); /* newer commits with larger date first */ if (a_date < b_date) @@ -1082,9 +1086,17 @@ struct commit_list *reduce_heads(struct commit_list *heads) num_head = remove_redundant(array, num_head); for (i = 0; i < num_head; i++) tail = &commit_list_insert(array[i], tail)->next; + free(array); return result; } +void reduce_heads_replace(struct commit_list **heads) +{ + struct commit_list *result = reduce_heads(*heads); + free_commit_list(*heads); + *heads = result; +} + static const char gpg_sig_header[] = "gpgsig"; static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1; @@ -1566,10 +1578,13 @@ int commit_tree_extended(const char *msg, size_t msg_len, if (encoding_is_utf8 && !verify_utf8(&buffer)) fprintf(stderr, _(commit_utf8_warn)); - if (sign_commit && do_sign_commit(&buffer, sign_commit)) - return -1; + if (sign_commit && do_sign_commit(&buffer, sign_commit)) { + result = -1; + goto out; + } result = write_sha1_file(buffer.buf, buffer.len, commit_type, ret); +out: strbuf_release(&buffer); return result; } @@ -1588,9 +1603,9 @@ struct commit *get_merge_parent(const char *name) struct object *obj; struct commit *commit; struct object_id oid; - if (get_sha1(name, oid.hash)) + if (get_oid(name, &oid)) return NULL; - obj = parse_object(oid.hash); + obj = parse_object(&oid); commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT); if (commit && !commit->util) set_merge_remote_desc(commit, name, obj); @@ -1649,10 +1664,9 @@ const char *find_commit_header(const char *msg, const char *key, size_t *out_len /* * Inspect the given string and determine the true "end" of the log message, in * order to find where to put a new Signed-off-by: line. Ignored are - * trailing comment lines and blank lines, and also the traditional - * "Conflicts:" block that is not commented out, so that we can use - * "git commit -s --amend" on an existing commit that forgot to remove - * it. + * trailing comment lines and blank lines. To support "git commit -s + * --amend" on an existing commit, we also ignore "Conflicts:". To + * support "git commit -v", we truncate at cut lines. * * Returns the number of bytes from the tail to ignore, to be fed as * the second parameter to append_signoff(). @@ -1662,8 +1676,9 @@ int ignore_non_trailer(const char *buf, size_t len) int boc = 0; int bol = 0; int in_old_conflicts_block = 0; + size_t cutoff = wt_status_locate_end(buf, len); - while (bol < len) { + while (bol < cutoff) { const char *next_line = memchr(buf + bol, '\n', len - bol); if (!next_line) @@ -1689,5 +1704,5 @@ int ignore_non_trailer(const char *buf, size_t len) } bol = next_line - buf; } - return boc ? len - boc : 0; + return boc ? len - boc : len - cutoff; } |