diff options
Diffstat (limited to 'tree-diff.c')
| -rw-r--r-- | tree-diff.c | 154 |
1 files changed, 37 insertions, 117 deletions
diff --git a/tree-diff.c b/tree-diff.c index d9237ffd9b..e00fc2f450 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -48,8 +48,8 @@ free((x)); \ } while(0) -static struct combine_diff_path *ll_diff_tree_paths( - struct combine_diff_path *p, const struct object_id *oid, +static void ll_diff_tree_paths( + struct combine_diff_path ***tail, const struct object_id *oid, const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt, int depth); @@ -125,72 +125,6 @@ static int emit_diff_first_parent_only(struct diff_options *opt, struct combine_ /* - * Make a new combine_diff_path from path/mode/sha1 - * and append it to paths list tail. - * - * Memory for created elements could be reused: - * - * - if last->next == NULL, the memory is allocated; - * - * - if last->next != NULL, it is assumed that p=last->next was returned - * earlier by this function, and p->next was *not* modified. - * The memory is then reused from p. - * - * so for clients, - * - * - if you do need to keep the element - * - * p = path_appendnew(p, ...); - * process(p); - * p->next = NULL; - * - * - if you don't need to keep the element after processing - * - * pprev = p; - * p = path_appendnew(p, ...); - * process(p); - * p = pprev; - * ; don't forget to free tail->next in the end - * - * p->parent[] remains uninitialized. - */ -static struct combine_diff_path *path_appendnew(struct combine_diff_path *last, - int nparent, const struct strbuf *base, const char *path, int pathlen, - unsigned mode, const struct object_id *oid) -{ - struct combine_diff_path *p; - size_t len = st_add(base->len, pathlen); - size_t alloclen = combine_diff_path_size(nparent, len); - - /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */ - p = last->next; - if (p && (alloclen > (intptr_t)p->next)) { - FREE_AND_NULL(p); - } - - if (!p) { - p = xmalloc(alloclen); - - /* - * until we go to it next round, .next holds how many bytes we - * allocated (for faster realloc - we don't need copying old data). - */ - p->next = (struct combine_diff_path *)(intptr_t)alloclen; - } - - last->next = p; - - p->path = (char *)&(p->parent[nparent]); - memcpy(p->path, base->buf, base->len); - memcpy(p->path + base->len, path, pathlen); - p->path[len] = 0; - p->mode = mode; - oidcpy(&p->oid, oid ? oid : null_oid()); - - return p; -} - -/* * new path should be added to combine diff * * 3 cases on how/when it should be called and behaves: @@ -200,10 +134,10 @@ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last, * t, tp -> path modified/added * (M for tp[i]=tp[imin], A otherwise) */ -static struct combine_diff_path *emit_path(struct combine_diff_path *p, - struct strbuf *base, struct diff_options *opt, int nparent, - struct tree_desc *t, struct tree_desc *tp, - int imin, int depth) +static void emit_path(struct combine_diff_path ***tail, + struct strbuf *base, struct diff_options *opt, + int nparent, struct tree_desc *t, struct tree_desc *tp, + int imin, int depth) { unsigned short mode; const char *path; @@ -243,8 +177,13 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, if (emitthis) { int keep; - struct combine_diff_path *pprev = p; - p = path_appendnew(p, nparent, base, path, pathlen, mode, oid); + struct combine_diff_path *p; + + strbuf_add(base, path, pathlen); + p = combine_diff_path_new(base->buf, base->len, mode, + oid ? oid : null_oid(the_hash_algo), + nparent); + strbuf_setlen(base, old_baselen); for (i = 0; i < nparent; ++i) { /* @@ -267,7 +206,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, mode_i = tp[i].entry.mode; } else { - oid_i = null_oid(); + oid_i = null_oid(the_hash_algo); mode_i = 0; } @@ -279,21 +218,12 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, if (opt->pathchange) keep = opt->pathchange(opt, p); - /* - * If a path was filtered or consumed - we don't need to add it - * to the list and can reuse its memory, leaving it as - * pre-allocated element on the tail. - * - * On the other hand, if path needs to be kept, we need to - * correct its .next to NULL, as it was pre-initialized to how - * much memory was allocated. - * - * see path_appendnew() for details. - */ - if (!keep) - p = pprev; - else - p->next = NULL; + if (keep) { + **tail = p; + *tail = &p->next; + } else { + free(p); + } } if (recurse) { @@ -309,13 +239,12 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, strbuf_add(base, path, pathlen); strbuf_addch(base, '/'); - p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt, - depth + 1); + ll_diff_tree_paths(tail, oid, parents_oid, nparent, base, opt, + depth + 1); FAST_ARRAY_FREE(parents_oid, nparent); } strbuf_setlen(base, old_baselen); - return p; } static void skip_uninteresting(struct tree_desc *t, struct strbuf *base, @@ -428,8 +357,8 @@ static inline void update_tp_entries(struct tree_desc *tp, int nparent) update_tree_entry(&tp[i]); } -static struct combine_diff_path *ll_diff_tree_paths( - struct combine_diff_path *p, const struct object_id *oid, +static void ll_diff_tree_paths( + struct combine_diff_path ***tail, const struct object_id *oid, const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt, int depth) @@ -533,8 +462,8 @@ static struct combine_diff_path *ll_diff_tree_paths( } /* D += {δ(t,pi) if pi=p[imin]; "+a" if pi > p[imin]} */ - p = emit_path(p, base, opt, nparent, - &t, tp, imin, depth); + emit_path(tail, base, opt, nparent, + &t, tp, imin, depth); skip_emit_t_tp: /* t↓, ∀ pi=p[imin] pi↓ */ @@ -545,8 +474,8 @@ static struct combine_diff_path *ll_diff_tree_paths( /* t < p[imin] */ else if (cmp < 0) { /* D += "+t" */ - p = emit_path(p, base, opt, nparent, - &t, /*tp=*/NULL, -1, depth); + emit_path(tail, base, opt, nparent, + &t, /*tp=*/NULL, -1, depth); /* t↓ */ update_tree_entry(&t); @@ -561,8 +490,8 @@ static struct combine_diff_path *ll_diff_tree_paths( goto skip_emit_tp; } - p = emit_path(p, base, opt, nparent, - /*t=*/NULL, tp, imin, depth); + emit_path(tail, base, opt, nparent, + /*t=*/NULL, tp, imin, depth); skip_emit_tp: /* ∀ pi=p[imin] pi↓ */ @@ -575,24 +504,16 @@ static struct combine_diff_path *ll_diff_tree_paths( free(tptree[i]); FAST_ARRAY_FREE(tptree, nparent); FAST_ARRAY_FREE(tp, nparent); - - return p; } struct combine_diff_path *diff_tree_paths( - struct combine_diff_path *p, const struct object_id *oid, + const struct object_id *oid, const struct object_id **parents_oid, int nparent, struct strbuf *base, struct diff_options *opt) { - p = ll_diff_tree_paths(p, oid, parents_oid, nparent, base, opt, 0); - - /* - * free pre-allocated last element, if any - * (see path_appendnew() for details about why) - */ - FREE_AND_NULL(p->next); - - return p; + struct combine_diff_path *head = NULL, **tail = &head; + ll_diff_tree_paths(&tail, oid, parents_oid, nparent, base, opt, 0); + return head; } /* @@ -708,14 +629,13 @@ static void ll_diff_tree_oid(const struct object_id *old_oid, const struct object_id *new_oid, struct strbuf *base, struct diff_options *opt) { - struct combine_diff_path phead, *p; + struct combine_diff_path *paths, *p; pathchange_fn_t pathchange_old = opt->pathchange; - phead.next = NULL; opt->pathchange = emit_diff_first_parent_only; - diff_tree_paths(&phead, new_oid, &old_oid, 1, base, opt); + paths = diff_tree_paths(new_oid, &old_oid, 1, base, opt); - for (p = phead.next; p;) { + for (p = paths; p;) { struct combine_diff_path *pprev = p; p = p->next; free(pprev); |
