On Fri, Jan 11, 2019 at 09:51:06AM -0500, Jeff King wrote: > I think rewrite_here needs to be a direct pointer into the buffer, since > we plan to modify it. > > I think rewrite_with is correct to be an object_id. It's either the oid > passed in from the caller, or the subtree we generated (in which case > it's the result from write_object_file). > > So the "most correct" thing is probably something like this: Of course, it would be nice if what I sent compiled. ;) rewrite_here does double duty: it's the pointer in the tree that we need to rewrite, and it's also the oid we pass down recursively. So we have to handle both cases, like so: diff --git a/match-trees.c b/match-trees.c index 03e81b56e1..3e0ed889b4 100644 --- a/match-trees.c +++ b/match-trees.c @@ -179,7 +179,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix, char *buf; unsigned long sz; struct tree_desc desc; - struct object_id *rewrite_here; + unsigned char *rewrite_here; const struct object_id *rewrite_with; struct object_id subtree; enum object_type type; @@ -206,9 +206,16 @@ static int splice_tree(const struct object_id *oid1, const char *prefix, if (!S_ISDIR(mode)) die("entry %s in tree %s is not a tree", name, oid_to_hex(oid1)); - rewrite_here = (struct object_id *)(desc.entry.path + - strlen(desc.entry.path) + - 1); + /* + * We cast here for two reasons: + * + * - to flip the "char *" (for the path) to "unsigned + * char *" (for the hash stored after it) + * + * - to discard the "const"; this is OK because we + * know it points into our non-const "buf" + */ + rewrite_here = (unsigned char *)desc.entry.path + strlen(desc.entry.path) + 1; break; } update_tree_entry(&desc); @@ -217,14 +224,16 @@ static int splice_tree(const struct object_id *oid1, const char *prefix, die("entry %.*s not found in tree %s", toplen, prefix, oid_to_hex(oid1)); if (*subpath) { - status = splice_tree(rewrite_here, subpath, oid2, &subtree); + struct object_id tree_oid; + hashcpy(tree_oid.hash, rewrite_here); + status = splice_tree(&tree_oid, subpath, oid2, &subtree); if (status) return status; rewrite_with = &subtree; } else { rewrite_with = oid2; } - hashcpy(rewrite_here->hash, rewrite_with->hash); + hashcpy(rewrite_here, rewrite_with->hash); status = write_object_file(buf, sz, tree_type, result); free(buf); return status;