git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 3/5] match-trees: use hashcpy to splice trees

From
Jeff King <peff@peff.net>
Date
Jan 11, 2019, 14:51 UTC
Message-ID
<20190111145106.GB16754@sigill.intra.peff.net>
In-Reply-To
<20190110235551.GM423984@genre.crustytoothpaste.net>
On Thu, Jan 10, 2019 at 11:55:51PM +0000, brian m. carlson wrote:
Show 12 quoted lines
> > I think the only reason they are "struct object_id" is because that's
> > what tree_entry_extract() returns. Should we be providing another
> > function to allow more byte-oriented access?
> 
> The reason is we recursively call splice_tree, passing rewrite_here as
> the first argument. That argument is then used for read_object_file,
> which requires a struct object_id * (because it is, logically, an object
> ID).
> 
> I *think* we could fix this by copying an unsigned char *rewrite_here
> into a temporary struct object_id before we recurse, but it's not
> obvious to me if that's safe to do.

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:
diff --git a/match-trees.c b/match-trees.c
index 03e81b56e1..129b13a970 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);
@@ -224,7 +231,7 @@ static int splice_tree(const struct object_id *oid1, const char *prefix,
 	} 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;

I think if I were trying to write this in a less-subtle way, I'd
probably stop trying to do it in-place, and have a copy loop more like:

  for entry in src_tree
    if match_entry(entry, prefix)
      entry = rewrite_entry(entry) /* either oid2 or subtree */
    push_entry(dst_tree)

We may even have to go that way eventually if we might ever be rewriting
to a tree with a different hash size (i.e., there is a hidden assumption
here that rewrite_here points to exactly the_hash_algo->rawsz bytes of
hash). But I think for now it's not necessary, and it's way outside the
scope of what you're trying to do here.

-Peff
Previous: brian m. carlsonNext: Jeff King
Message 19 of 41 in “What's cooking in git.git (Jan 2019, #01; Mon, 7)”
  1. Junio C HamanoJan 7, 2019
  2. tg/checkout-no-overlay, was Re: What's cooking in git.git (Jan 2019, #01; Mon, 7)Thomas Gummerer, Jan 8, 2019
  3. Junio C HamanoJan 8, 2019
  4. ag/sequencer-reduce-rewriting-todo Re: What's cooking in git.git (Jan 2019, #01; Mon, 7)Alban Gruin, Jan 8, 2019
  5. sb/more-repo-in-api, was Re: What's cooking in git.git (Jan 2019, #01; Mon, 7)Jonathan Tan, Jan 8, 2019
  6. Junio C HamanoJan 8, 2019
  7. Stefan BellerJan 9, 2019
  8. Martin ÅgrenJan 9, 2019
  9. Martin ÅgrenJan 9, 2019
  10. brian m. carlsonJan 10, 2019
  11. Junio C HamanoJan 10, 2019
  12. Martin ÅgrenJan 10, 2019
  13. 0/5 tree-walk object_id refactorbrian m. carlson, Jan 10, 2019
  14. 1/5 tree-walk: copy object ID before usebrian m. carlson, Jan 10, 2019
  15. 2/5 match-trees: compute buffer offset correctly when splicingbrian m. carlson, Jan 10, 2019
  16. 3/5 match-trees: use hashcpy to splice treesbrian m. carlson, Jan 10, 2019
  17. Jeff KingJan 10, 2019
  18. brian m. carlsonJan 10, 2019
  19. Jeff KingJan 11, 2019
  20. Jeff KingJan 11, 2019
  21. brian m. carlsonJan 14, 2019
  22. Jeff KingJan 14, 2019
  23. 4/5 tree-walk: store object_id in a separate memberbrian m. carlson, Jan 10, 2019
  24. Jeff KingJan 10, 2019
  25. brian m. carlsonJan 10, 2019
  26. 5/5 cache: make oidcpy always copy GIT_MAX_RAWSZ bytesbrian m. carlson, Jan 10, 2019
  27. Jeff KingJan 10, 2019
  28. Jeff KingJan 10, 2019
  29. brian m. carlsonJan 11, 2019
  30. Jeff KingJan 11, 2019
  31. 0/5 tree-walk object_id refactorbrian m. carlson, Jan 15, 2019
  32. 1/5 tree-walk: copy object ID before usebrian m. carlson, Jan 15, 2019
  33. 2/5 match-trees: compute buffer offset correctly when splicingbrian m. carlson, Jan 15, 2019
  34. 4/5 tree-walk: store object_id in a separate memberbrian m. carlson, Jan 15, 2019
  35. 5/5 cache: make oidcpy always copy GIT_MAX_RAWSZ bytesbrian m. carlson, Jan 15, 2019
  36. 3/5 match-trees: use hashcpy to splice treesbrian m. carlson, Jan 15, 2019
  37. Junio C HamanoJan 15, 2019
  38. Jeff KingJan 9, 2019
  39. Junio C HamanoJan 10, 2019
  40. Junio C HamanoJan 10, 2019
  41. Stefan BellerJan 10, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.