diff options
Diffstat (limited to 'commit.c')
-rw-r--r-- | commit.c | 62 |
1 files changed, 55 insertions, 7 deletions
@@ -19,6 +19,7 @@ #include "advice.h" #include "refs.h" #include "commit-reach.h" +#include "run-command.h" static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **); @@ -358,14 +359,15 @@ struct tree *repo_get_commit_tree(struct repository *r, struct object_id *get_commit_tree_oid(const struct commit *commit) { - return &get_commit_tree(commit)->object.oid; + struct tree *tree = get_commit_tree(commit); + return tree ? &tree->object.oid : NULL; } void release_commit_memory(struct parsed_object_pool *pool, struct commit *c) { set_commit_tree(c, NULL); - c->index = 0; free_commit_buffer(pool, c); + c->index = 0; free_commit_list(c->parents); c->object.parsed = 0; @@ -400,10 +402,22 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b struct commit_graft *graft; const int tree_entry_len = the_hash_algo->hexsz + 5; const int parent_entry_len = the_hash_algo->hexsz + 7; + struct tree *tree; if (item->object.parsed) return 0; - item->object.parsed = 1; + + if (item->parents) { + /* + * Presumably this is leftover from an earlier failed parse; + * clear it out in preparation for us re-parsing (we'll hit the + * same error, but that's good, since it lets our caller know + * the result cannot be trusted. + */ + free_commit_list(item->parents); + item->parents = NULL; + } + tail += size; if (tail <= bufptr + tree_entry_len + 1 || memcmp(bufptr, "tree ", 5) || bufptr[tree_entry_len] != '\n') @@ -411,7 +425,12 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b if (get_oid_hex(bufptr + 5, &parent) < 0) return error("bad tree pointer in commit %s", oid_to_hex(&item->object.oid)); - set_commit_tree(item, lookup_tree(r, &parent)); + tree = lookup_tree(r, &parent); + if (!tree) + return error("bad tree pointer %s in commit %s", + oid_to_hex(&parent), + oid_to_hex(&item->object.oid)); + set_commit_tree(item, tree); bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */ pptr = &item->parents; @@ -431,8 +450,11 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b if (graft && (graft->nr_parent < 0 || grafts_replace_parents)) continue; new_parent = lookup_commit(r, &parent); - if (new_parent) - pptr = &commit_list_insert(new_parent, pptr)->next; + if (!new_parent) + return error("bad parent %s in commit %s", + oid_to_hex(&parent), + oid_to_hex(&item->object.oid)); + pptr = &commit_list_insert(new_parent, pptr)->next; } if (graft) { int i; @@ -441,7 +463,9 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b new_parent = lookup_commit(r, &graft->parent[i]); if (!new_parent) - continue; + return error("bad graft parent %s in commit %s", + oid_to_hex(&graft->parent[i]), + oid_to_hex(&item->object.oid)); pptr = &commit_list_insert(new_parent, pptr)->next; } } @@ -450,6 +474,7 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b if (check_graph) load_commit_graph_info(r, item); + item->object.parsed = 1; return 0; } @@ -1580,3 +1605,26 @@ size_t ignore_non_trailer(const char *buf, size_t len) } return boc ? len - boc : len - cutoff; } + +int run_commit_hook(int editor_is_used, const char *index_file, + const char *name, ...) +{ + struct argv_array hook_env = ARGV_ARRAY_INIT; + va_list args; + int ret; + + argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", index_file); + + /* + * Let the hook know that no editor will be launched. + */ + if (!editor_is_used) + argv_array_push(&hook_env, "GIT_EDITOR=:"); + + va_start(args, name); + ret = run_hook_ve(hook_env.argv,name, args); + va_end(args); + argv_array_clear(&hook_env); + + return ret; +} |