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;

Reply via email to