match-trees: use hashcpy to splice trees

When we splice trees together, we operate in place on the tree buffer. If we're using SHA-1 for the hash algorithm, we may not have a full GIT_MAX_RAWSZ (32) bytes to copy. Consequently, it doesn't logically make sense for us to use a struct object_id to represent this type, since it isn't a complete object. Represent this value as a unsigned char pointer instead and copy it when necessary. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

brian m. carlson committed Jan 15, 2019 at 00:39 UTC f55ac4311ad173529cbac7a619d422674a4252ad
1 file changed +18 -6
match-trees.c
+18 -6
@@ -179,7 +179,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
179 char *buf;
180 unsigned long sz;
181 struct tree_desc desc;
182 - struct object_id *rewrite_here;
182 + unsigned char *rewrite_here;
183 const struct object_id *rewrite_with;
184 struct object_id subtree;
185 enum object_type type;
@@ -206,9 +206,19 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
206 if (!S_ISDIR(mode))
207 die("entry %s in tree %s is not a tree", name,
208 oid_to_hex(oid1));
209 - rewrite_here = (struct object_id *)(desc.entry.path +
210 - strlen(desc.entry.path) +
211 - 1);
209 +
210 + /*
211 + * We cast here for two reasons:
212 + *
213 + * - to flip the "char *" (for the path) to "unsigned
214 + * char *" (for the hash stored after it)
215 + *
216 + * - to discard the "const"; this is OK because we
217 + * know it points into our non-const "buf"
218 + */
219 + rewrite_here = (unsigned char *)(desc.entry.path +
220 + strlen(desc.entry.path) +
221 + 1);
222 break;
223 }
224 update_tree_entry(&desc);
@@ -217,14 +227,16 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
227 die("entry %.*s not found in tree %s", toplen, prefix,
228 oid_to_hex(oid1));
229 if (*subpath) {
220 - status = splice_tree(rewrite_here, subpath, oid2, &subtree);
230 + struct object_id tree_oid;
231 + hashcpy(tree_oid.hash, rewrite_here);
232 + status = splice_tree(&tree_oid, subpath, oid2, &subtree);
233 if (status)
234 return status;
235 rewrite_with = &subtree;
236 } else {
237 rewrite_with = oid2;
238 }
227 - oidcpy(rewrite_here, rewrite_with);
239 + hashcpy(rewrite_here, rewrite_with->hash);
240 status = write_object_file(buf, sz, tree_type, result);
241 free(buf);
242 return status;