From: Junio C Hamano Date: Thu, 11 Jun 2015 16:29:58 +0000 (-0700) Subject: Merge branch 'jk/squelch-missing-link-warning-for-unreachable' X-Git-Tag: v2.5.0-rc0~41 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/43262d8d6511212f49d519779505f8a557c8dc84?ds=inline;hp=-c Merge branch 'jk/squelch-missing-link-warning-for-unreachable' Recent "git prune" traverses young unreachable objects to safekeep old objects in the reachability chain from them, which sometimes caused error messages that are unnecessarily alarming. * jk/squelch-missing-link-warning-for-unreachable: suppress errors on missing UNINTERESTING links silence broken link warnings with revs->ignore_missing_links add quieter versions of parse_{tree,commit} --- 43262d8d6511212f49d519779505f8a557c8dc84 diff --combined commit.c index 2d9de807ae,388819c4e9..6e2103cef6 --- a/commit.c +++ b/commit.c @@@ -55,12 -55,12 +55,12 @@@ struct commit *lookup_commit(const unsi struct commit *lookup_commit_reference_by_name(const char *name) { - unsigned char sha1[20]; + struct object_id oid; struct commit *commit; - if (get_sha1_committish(name, sha1)) + if (get_sha1_committish(name, oid.hash)) return NULL; - commit = lookup_commit_reference(sha1); + commit = lookup_commit_reference(oid.hash); if (parse_commit(commit)) return NULL; return commit; @@@ -99,7 -99,7 +99,7 @@@ static int commit_graft_alloc, commit_g static const unsigned char *commit_graft_sha1_access(size_t index, void *table) { struct commit_graft **commit_graft_table = table; - return commit_graft_table[index]->sha1; + return commit_graft_table[index]->oid.hash; } static int commit_graft_pos(const unsigned char *sha1) @@@ -110,7 -110,7 +110,7 @@@ int register_commit_graft(struct commit_graft *graft, int ignore_dups) { - int pos = commit_graft_pos(graft->sha1); + int pos = commit_graft_pos(graft->oid.hash); if (0 <= pos) { if (ignore_dups) @@@ -138,23 -138,22 +138,23 @@@ struct commit_graft *read_graft_line(ch /* The format is just "Commit Parent1 Parent2 ...\n" */ int i; struct commit_graft *graft = NULL; + const int entry_size = GIT_SHA1_HEXSZ + 1; while (len && isspace(buf[len-1])) buf[--len] = '\0'; if (buf[0] == '#' || buf[0] == '\0') return NULL; - if ((len + 1) % 41) + if ((len + 1) % entry_size) goto bad_graft_data; - i = (len + 1) / 41 - 1; - graft = xmalloc(sizeof(*graft) + 20 * i); + i = (len + 1) / entry_size - 1; + graft = xmalloc(sizeof(*graft) + GIT_SHA1_RAWSZ * i); graft->nr_parent = i; - if (get_sha1_hex(buf, graft->sha1)) + if (get_oid_hex(buf, &graft->oid)) goto bad_graft_data; - for (i = 40; i < len; i += 41) { + 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/41])) + if (get_sha1_hex(buf + i + 1, graft->parent[i/entry_size].hash)) goto bad_graft_data; } return graft; @@@ -303,42 -302,39 +303,42 @@@ int parse_commit_buffer(struct commit * { const char *tail = buffer; const char *bufptr = buffer; - unsigned char parent[20]; + struct object_id parent; struct commit_list **pptr; struct commit_graft *graft; + const int tree_entry_len = GIT_SHA1_HEXSZ + 5; + const int parent_entry_len = GIT_SHA1_HEXSZ + 7; if (item->object.parsed) return 0; item->object.parsed = 1; tail += size; - if (tail <= bufptr + 46 || memcmp(bufptr, "tree ", 5) || bufptr[45] != '\n') + if (tail <= bufptr + tree_entry_len + 1 || memcmp(bufptr, "tree ", 5) || + bufptr[tree_entry_len] != '\n') return error("bogus commit object %s", sha1_to_hex(item->object.sha1)); - if (get_sha1_hex(bufptr + 5, parent) < 0) + if (get_sha1_hex(bufptr + 5, parent.hash) < 0) return error("bad tree pointer in commit %s", sha1_to_hex(item->object.sha1)); - item->tree = lookup_tree(parent); - bufptr += 46; /* "tree " + "hex sha1" + "\n" */ + item->tree = lookup_tree(parent.hash); + bufptr += tree_entry_len + 1; /* "tree " + "hex sha1" + "\n" */ pptr = &item->parents; graft = lookup_commit_graft(item->object.sha1); - while (bufptr + 48 < tail && !memcmp(bufptr, "parent ", 7)) { + while (bufptr + parent_entry_len < tail && !memcmp(bufptr, "parent ", 7)) { struct commit *new_parent; - if (tail <= bufptr + 48 || - get_sha1_hex(bufptr + 7, parent) || - bufptr[47] != '\n') + if (tail <= bufptr + parent_entry_len + 1 || + get_sha1_hex(bufptr + 7, parent.hash) || + bufptr[parent_entry_len] != '\n') return error("bad parents in commit %s", sha1_to_hex(item->object.sha1)); - bufptr += 48; + bufptr += parent_entry_len + 1; /* * The clone is shallow if nr_parent < 0, and we must * not traverse its real parents even when we unhide them. */ if (graft && (graft->nr_parent < 0 || grafts_replace_parents)) continue; - new_parent = lookup_commit(parent); + new_parent = lookup_commit(parent.hash); if (new_parent) pptr = &commit_list_insert(new_parent, pptr)->next; } @@@ -346,7 -342,7 +346,7 @@@ int i; struct commit *new_parent; for (i = 0; i < graft->nr_parent; i++) { - new_parent = lookup_commit(graft->parent[i]); + new_parent = lookup_commit(graft->parent[i].hash); if (!new_parent) continue; pptr = &commit_list_insert(new_parent, pptr)->next; @@@ -357,7 -353,7 +357,7 @@@ return 0; } - int parse_commit(struct commit *item) + int parse_commit_gently(struct commit *item, int quiet_on_missing) { enum object_type type; void *buffer; @@@ -370,7 -366,8 +370,8 @@@ return 0; buffer = read_sha1_file(item->object.sha1, &type, &size); if (!buffer) - return error("Could not read %s", + return quiet_on_missing ? -1 : + error("Could not read %s", sha1_to_hex(item->object.sha1)); if (type != OBJ_COMMIT) { free(buffer); @@@ -871,7 -868,7 +872,7 @@@ struct commit_list *get_octopus_merge_b for (j = ret; j; j = j->next) { struct commit_list *bases; - bases = get_merge_bases(i->item, j->item, 1); + bases = get_merge_bases(i->item, j->item); if (!new) new = bases; else @@@ -940,10 -937,10 +941,10 @@@ static int remove_redundant(struct comm return filled; } -struct commit_list *get_merge_bases_many(struct commit *one, - int n, - struct commit **twos, - int cleanup) +static struct commit_list *get_merge_bases_many_0(struct commit *one, + int n, + struct commit **twos, + int cleanup) { struct commit_list *list; struct commit **rslt; @@@ -981,23 -978,10 +982,23 @@@ return result; } -struct commit_list *get_merge_bases(struct commit *one, struct commit *two, - int cleanup) +struct commit_list *get_merge_bases_many(struct commit *one, + int n, + struct commit **twos) { - return get_merge_bases_many(one, 1, &two, cleanup); + return get_merge_bases_many_0(one, n, twos, 1); +} + +struct commit_list *get_merge_bases_many_dirty(struct commit *one, + int n, + struct commit **twos) +{ + return get_merge_bases_many_0(one, n, twos, 0); +} + +struct commit_list *get_merge_bases(struct commit *one, struct commit *two) +{ + return get_merge_bases_many_0(one, 1, &two, 1); } /* @@@ -1584,10 -1568,10 +1585,10 @@@ struct commit *get_merge_parent(const c { struct object *obj; struct commit *commit; - unsigned char sha1[20]; - if (get_sha1(name, sha1)) + struct object_id oid; + if (get_sha1(name, oid.hash)) return NULL; - obj = parse_object(sha1); + obj = parse_object(oid.hash); commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT); if (commit && !commit->util) { struct merge_remote_desc *desc; @@@ -1657,49 -1641,3 +1658,49 @@@ const char *find_commit_header(const ch } return NULL; } + +/* + * Inspect sb 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. + * + * Returns the number of bytes from the tail to ignore, to be fed as + * the second parameter to append_signoff(). + */ +int ignore_non_trailer(struct strbuf *sb) +{ + int boc = 0; + int bol = 0; + int in_old_conflicts_block = 0; + + while (bol < sb->len) { + char *next_line; + + if (!(next_line = memchr(sb->buf + bol, '\n', sb->len - bol))) + next_line = sb->buf + sb->len; + else + next_line++; + + if (sb->buf[bol] == comment_line_char || sb->buf[bol] == '\n') { + /* is this the first of the run of comments? */ + if (!boc) + boc = bol; + /* otherwise, it is just continuing */ + } else if (starts_with(sb->buf + bol, "Conflicts:\n")) { + in_old_conflicts_block = 1; + if (!boc) + boc = bol; + } else if (in_old_conflicts_block && sb->buf[bol] == '\t') { + ; /* a pathname in the conflicts block */ + } else if (boc) { + /* the previous was not trailing comment */ + boc = 0; + in_old_conflicts_block = 0; + } + bol = next_line - sb->buf; + } + return boc ? sb->len - boc : 0; +} diff --combined commit.h index ed3a1d59a5,61bda25b34..9a1fa961d2 --- a/commit.h +++ b/commit.h @@@ -59,7 -59,11 +59,11 @@@ struct commit *lookup_commit_reference_ struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name); int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size); - int parse_commit(struct commit *item); + int parse_commit_gently(struct commit *item, int quiet_on_missing); + static inline int parse_commit(struct commit *item) + { + return parse_commit_gently(item, 0); + } void parse_commit_or_die(struct commit *item); /* @@@ -226,9 -230,9 +230,9 @@@ enum rev_sort_order void sort_in_topological_order(struct commit_list **, enum rev_sort_order); struct commit_graft { - unsigned char sha1[20]; + struct object_id oid; int nr_parent; /* < 0 if shallow commit */ - unsigned char parent[FLEX_ARRAY][20]; /* more */ + struct object_id parent[FLEX_ARRAY]; /* more */ }; typedef int (*each_commit_graft_fn)(const struct commit_graft *, void *); @@@ -236,13 -240,10 +240,13 @@@ struct commit_graft *read_graft_line(ch int register_commit_graft(struct commit_graft *, int); struct commit_graft *lookup_commit_graft(const unsigned char *sha1); -extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup); -extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos, int cleanup); +extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2); +extern struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos); extern struct commit_list *get_octopus_merge_bases(struct commit_list *in); +/* To be used only when object flags after this call no longer matter */ +extern struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos); + /* largest positive number a signed 32-bit integer can contain */ #define INFINITE_DEPTH 0x7fffffff @@@ -254,6 -255,7 +258,6 @@@ extern int for_each_commit_graft(each_c extern int is_repository_shallow(void); extern struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); -extern void check_shallow_file_for_update(void); extern void set_alternate_shallow_file(const char *path, int override); extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol, const struct sha1_array *extra); @@@ -339,9 -341,6 +343,9 @@@ extern void free_commit_extra_headers(s extern const char *find_commit_header(const char *msg, const char *key, size_t *out_len); +/* Find the end of the log message, the right place for a new trailer. */ +extern int ignore_non_trailer(struct strbuf *sb); + typedef void (*each_mergetag_fn)(struct commit *commit, struct commit_extra_header *extra, void *cb_data); diff --combined list-objects.c index 2a139b6ced,90c21abc5c..41736d2372 --- a/list-objects.c +++ b/list-objects.c @@@ -81,7 -81,7 +81,7 @@@ static void process_tree(struct rev_inf die("bad tree object"); if (obj->flags & (UNINTERESTING | SEEN)) return; - if (parse_tree(tree) < 0) { + if (parse_tree_gently(tree, revs->ignore_missing_links) < 0) { if (revs->ignore_missing_links) return; die("bad tree object %s", sha1_to_hex(obj->sha1)); @@@ -157,7 -157,7 +157,7 @@@ void mark_edges_uninteresting(struct re if (commit->object.flags & UNINTERESTING) { mark_tree_uninteresting(commit->tree); - if (revs->edge_hint && !(commit->object.flags & SHOWN)) { + if (revs->edge_hint_aggressive && !(commit->object.flags & SHOWN)) { commit->object.flags |= SHOWN; show_edge(commit); } @@@ -165,7 -165,7 +165,7 @@@ } mark_edge_parents_uninteresting(commit, revs, show_edge); } - if (revs->edge_hint) { + if (revs->edge_hint_aggressive) { for (i = 0; i < revs->cmdline.nr; i++) { struct object *obj = revs->cmdline.rev[i].item; struct commit *commit = (struct commit *)obj; diff --combined revision.c index 1d903cf311,9f5476dc70..3ff8723da4 --- a/revision.c +++ b/revision.c @@@ -345,24 -345,14 +345,24 @@@ static struct commit *handle_commit(str die("%s is unknown object", name); } -static int everybody_uninteresting(struct commit_list *orig) +static int everybody_uninteresting(struct commit_list *orig, + struct commit **interesting_cache) { struct commit_list *list = orig; + + if (*interesting_cache) { + struct commit *commit = *interesting_cache; + if (!(commit->object.flags & UNINTERESTING)) + return 0; + } + while (list) { struct commit *commit = list->item; list = list->next; if (commit->object.flags & UNINTERESTING) continue; + if (interesting_cache) + *interesting_cache = commit; return 0; } return 1; @@@ -817,7 -807,7 +817,7 @@@ static int add_parents_to_list(struct r parent = parent->next; if (p) p->object.flags |= UNINTERESTING; - if (parse_commit(p) < 0) + if (parse_commit_gently(p, 1) < 0) continue; if (p->parents) mark_parents_uninteresting(p); @@@ -844,7 -834,7 +844,7 @@@ for (parent = commit->parents; parent; parent = parent->next) { struct commit *p = parent->item; - if (parse_commit(p) < 0) + if (parse_commit_gently(p, revs->ignore_missing_links) < 0) return -1; if (revs->show_source && !p->util) p->util = commit->util; @@@ -950,8 -940,7 +950,8 @@@ static void cherry_pick_list(struct com /* How many extra uninteresting commits we want to see.. */ #define SLOP 5 -static int still_interesting(struct commit_list *src, unsigned long date, int slop) +static int still_interesting(struct commit_list *src, unsigned long date, int slop, + struct commit **interesting_cache) { /* * No source list at all? We're definitely done.. @@@ -970,7 -959,7 +970,7 @@@ * Does the source list still have interesting commits in * it? Definitely not done.. */ - if (!everybody_uninteresting(src)) + if (!everybody_uninteresting(src, interesting_cache)) return SLOP; /* Ok, we're closing in.. */ @@@ -1089,7 -1078,6 +1089,7 @@@ static int limit_list(struct rev_info * struct commit_list *newlist = NULL; struct commit_list **p = &newlist; struct commit_list *bottom = NULL; + struct commit *interesting_cache = NULL; if (revs->ancestry_path) { bottom = collect_bottom_commits(list); @@@ -1106,9 -1094,6 +1106,9 @@@ list = list->next; free(entry); + if (commit == interesting_cache) + interesting_cache = NULL; + if (revs->max_age != -1 && (commit->date < revs->max_age)) obj->flags |= UNINTERESTING; if (add_parents_to_list(revs, commit, &list, NULL) < 0) @@@ -1117,7 -1102,7 +1117,7 @@@ mark_parents_uninteresting(commit); if (revs->show_all) p = &commit_list_insert(commit, p)->next; - slop = still_interesting(list, date, slop); + slop = still_interesting(list, date, slop, &interesting_cache); if (slop) continue; /* If showing all, add the whole pending list to the end */ @@@ -1218,8 -1203,7 +1218,8 @@@ int ref_excluded(struct string_list *re return 0; } -static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) +static int handle_one_ref(const char *path, const struct object_id *oid, + int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; struct object *object; @@@ -1227,9 -1211,9 +1227,9 @@@ if (ref_excluded(cb->all_revs->ref_excludes, path)) return 0; - object = get_reference(cb->all_revs, path, sha1, cb->all_flags); + object = get_reference(cb->all_revs, path, oid->hash, cb->all_flags); add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags); - add_pending_sha1(cb->all_revs, path, sha1, cb->all_flags); + add_pending_sha1(cb->all_revs, path, oid->hash, cb->all_flags); return 0; } @@@ -1293,8 -1277,7 +1293,8 @@@ static int handle_one_reflog_ent(unsign return 0; } -static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data) +static int handle_one_reflog(const char *path, const struct object_id *oid, + int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; cb->warned_bad_reflog = 0; @@@ -1306,7 -1289,6 +1306,7 @@@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags) { struct all_refs_cb cb; + cb.all_revs = revs; cb.all_flags = flags; for_each_reflog(handle_one_reflog, &cb); @@@ -1459,7 -1441,7 +1459,7 @@@ static void prepare_show_merge(struct r other = lookup_commit_or_die(sha1, "MERGE_HEAD"); add_pending_object(revs, &head->object, "HEAD"); add_pending_object(revs, &other->object, "MERGE_HEAD"); - bases = get_merge_bases(head, other, 1); + bases = get_merge_bases(head, other); add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM); add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM); free_commit_list(bases); @@@ -1564,7 -1546,7 +1564,7 @@@ int handle_revision_arg(const char *arg : lookup_commit_reference(b_obj->sha1)); if (!a || !b) goto missing; - exclude = get_merge_bases(a, b, 1); + exclude = get_merge_bases(a, b); add_rev_cmdline_list(revs, exclude, REV_CMD_MERGE_BASE, flags_exclude); @@@ -1871,12 -1853,6 +1871,12 @@@ static int handle_revision_opt(struct r revs->tree_objects = 1; revs->blob_objects = 1; revs->edge_hint = 1; + } else if (!strcmp(arg, "--objects-edge-aggressive")) { + revs->tag_objects = 1; + revs->tree_objects = 1; + revs->blob_objects = 1; + revs->edge_hint = 1; + revs->edge_hint_aggressive = 1; } else if (!strcmp(arg, "--verify-objects")) { revs->tag_objects = 1; revs->tree_objects = 1; @@@ -2035,8 -2011,6 +2035,8 @@@ grep_set_pattern_type_option(GREP_PATTERN_TYPE_PCRE, &revs->grep_filter); } else if (!strcmp(arg, "--all-match")) { revs->grep_filter.all_match = 1; + } else if (!strcmp(arg, "--invert-grep")) { + revs->invert_grep = 1; } else if ((argcount = parse_long_opt("encoding", argv, &optarg))) { if (strcmp(optarg, "none")) git_log_output_encoding = xstrdup(optarg); @@@ -2357,14 -2331,9 +2357,14 @@@ int setup_revisions(int argc, const cha if (revs->reflog_info && revs->graph) die("cannot combine --walk-reflogs with --graph"); + if (revs->no_walk && revs->graph) + die("cannot combine --no-walk with --graph"); if (!revs->reflog_info && revs->grep_filter.use_reflog_filter) die("cannot use --grep-reflog without --walk-reflogs"); + if (revs->first_parent_only && revs->bisect) + die(_("--first-parent is incompatible with --bisect")); + return left; } @@@ -2940,7 -2909,7 +2940,7 @@@ static int commit_match(struct commit * (char *)message, strlen(message)); strbuf_release(&buf); unuse_commit_buffer(commit, message); - return retval; + return opt->invert_grep ? !retval : retval; } static inline int want_ancestry(const struct rev_info *revs) @@@ -2993,61 -2962,6 +2993,61 @@@ enum commit_action get_commit_action(st return commit_show; } +define_commit_slab(saved_parents, struct commit_list *); + +#define EMPTY_PARENT_LIST ((struct commit_list *)-1) + +/* + * You may only call save_parents() once per commit (this is checked + * for non-root commits). + */ +static void save_parents(struct rev_info *revs, struct commit *commit) +{ + struct commit_list **pp; + + if (!revs->saved_parents_slab) { + revs->saved_parents_slab = xmalloc(sizeof(struct saved_parents)); + init_saved_parents(revs->saved_parents_slab); + } + + pp = saved_parents_at(revs->saved_parents_slab, commit); + + /* + * When walking with reflogs, we may visit the same commit + * several times: once for each appearance in the reflog. + * + * In this case, save_parents() will be called multiple times. + * We want to keep only the first set of parents. We need to + * store a sentinel value for an empty (i.e., NULL) parent + * list to distinguish it from a not-yet-saved list, however. + */ + if (*pp) + return; + if (commit->parents) + *pp = copy_commit_list(commit->parents); + else + *pp = EMPTY_PARENT_LIST; +} + +static void free_saved_parents(struct rev_info *revs) +{ + if (revs->saved_parents_slab) + clear_saved_parents(revs->saved_parents_slab); +} + +struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit) +{ + struct commit_list *parents; + + if (!revs->saved_parents_slab) + return commit->parents; + + parents = *saved_parents_at(revs->saved_parents_slab, commit); + if (parents == EMPTY_PARENT_LIST) + return NULL; + return parents; +} + enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit) { enum commit_action action = get_commit_action(revs, commit); @@@ -3347,3 -3261,54 +3347,3 @@@ void put_revision_mark(const struct rev fputs(mark, stdout); putchar(' '); } - -define_commit_slab(saved_parents, struct commit_list *); - -#define EMPTY_PARENT_LIST ((struct commit_list *)-1) - -void save_parents(struct rev_info *revs, struct commit *commit) -{ - struct commit_list **pp; - - if (!revs->saved_parents_slab) { - revs->saved_parents_slab = xmalloc(sizeof(struct saved_parents)); - init_saved_parents(revs->saved_parents_slab); - } - - pp = saved_parents_at(revs->saved_parents_slab, commit); - - /* - * When walking with reflogs, we may visit the same commit - * several times: once for each appearance in the reflog. - * - * In this case, save_parents() will be called multiple times. - * We want to keep only the first set of parents. We need to - * store a sentinel value for an empty (i.e., NULL) parent - * list to distinguish it from a not-yet-saved list, however. - */ - if (*pp) - return; - if (commit->parents) - *pp = copy_commit_list(commit->parents); - else - *pp = EMPTY_PARENT_LIST; -} - -struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit) -{ - struct commit_list *parents; - - if (!revs->saved_parents_slab) - return commit->parents; - - parents = *saved_parents_at(revs->saved_parents_slab, commit); - if (parents == EMPTY_PARENT_LIST) - return NULL; - return parents; -} - -void free_saved_parents(struct rev_info *revs) -{ - if (revs->saved_parents_slab) - clear_saved_parents(revs->saved_parents_slab); -} diff --combined tree.c index 58ebfce1bc,194a84074d..413a5b1fa6 --- a/tree.c +++ b/tree.c @@@ -30,12 -30,9 +30,12 @@@ static int read_one_entry_opt(const uns return add_cache_entry(ce, opt); } -static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) +static int read_one_entry(const unsigned char *sha1, struct strbuf *base, + const char *pathname, unsigned mode, int stage, + void *context) { - return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, + return read_one_entry_opt(sha1, base->buf, base->len, pathname, + mode, stage, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); } @@@ -43,12 -40,9 +43,12 @@@ * This is used when the caller knows there is no existing entries at * the stage that will conflict with the entry being added. */ -static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context) +static int read_one_entry_quick(const unsigned char *sha1, struct strbuf *base, + const char *pathname, unsigned mode, int stage, + void *context) { - return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage, + return read_one_entry_opt(sha1, base->buf, base->len, pathname, + mode, stage, ADD_CACHE_JUST_APPEND); } @@@ -76,7 -70,7 +76,7 @@@ static int read_tree_1(struct tree *tre continue; } - switch (fn(entry.sha1, base->buf, base->len, + switch (fn(entry.sha1, base, entry.path, entry.mode, stage, context)) { case 0: continue; @@@ -204,7 -198,7 +204,7 @@@ int parse_tree_buffer(struct tree *item return 0; } - int parse_tree(struct tree *item) + int parse_tree_gently(struct tree *item, int quiet_on_missing) { enum object_type type; void *buffer; @@@ -214,7 -208,8 +214,8 @@@ return 0; buffer = read_sha1_file(item->object.sha1, &type, &size); if (!buffer) - return error("Could not read %s", + return quiet_on_missing ? -1 : + error("Could not read %s", sha1_to_hex(item->object.sha1)); if (type != OBJ_TREE) { free(buffer); diff --combined tree.h index d24125f84f,35332fba87..d24786cba2 --- a/tree.h +++ b/tree.h @@@ -4,7 -4,6 +4,7 @@@ #include "object.h" extern const char *tree_type; +struct strbuf; struct tree { struct object object; @@@ -16,14 -15,18 +16,18 @@@ struct tree *lookup_tree(const unsigne int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size); - int parse_tree(struct tree *tree); + int parse_tree_gently(struct tree *tree, int quiet_on_missing); + static inline int parse_tree(struct tree *tree) + { + return parse_tree_gently(tree, 0); + } void free_tree_buffer(struct tree *tree); /* Parses and returns the tree in the given ent, chasing tags and commits. */ struct tree *parse_tree_indirect(const unsigned char *sha1); #define READ_TREE_RECURSIVE 1 -typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *); +typedef int (*read_tree_fn_t)(const unsigned char *, struct strbuf *, const char *, unsigned int, int, void *); extern int read_tree_recursive(struct tree *tree, const char *base, int baselen,