diff mbox series

[v5,16/18] tree-walk.h API: add a get_tree_entry_path() function

Message ID patch-16.19-3ba77fd3a47-20210331T190531Z-avarab@gmail.com (mailing list archive)
State New, archived
Headers show
Series tree-walk.h: slimmed down | expand

Commit Message

Ævar Arnfjörð Bjarmason March 31, 2021, 7:09 p.m. UTC
Add a get_tree_entry_path() variant in addition to
get_tree_entry_path_mode(). This is for those callers that don't need
the "mode" filled for them.

There are callers here which don't need the "struct object_id" filled
either, but let's leave that for now. I'm focusing downstream code
that depends on "mode" (or "enum object_type").

The code being modified here was introduced in:

 - shift_tree(): 68faf68938e (A new merge stragety[sic] 'subtree'.,
    2007-02-15) for the shift_tree()

 - tree_has_path(): 96e7ffbdc31 (merge-recursive: check for directory
   level conflicts, 2018-04-19)

 - init_notes(): fd53c9eb445 (Speed up git notes lookup, 2009-10-09)

 - diagnose_invalid_oid_path(): 009fee4774d (Detailed diagnosis when
   parsing an object name fails., 2009-12-07)

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 match-trees.c     | 4 +---
 merge-recursive.c | 6 ++----
 notes.c           | 3 +--
 object-name.c     | 3 +--
 tree-walk.c       | 9 +++++++++
 tree-walk.h       | 3 +++
 6 files changed, 17 insertions(+), 11 deletions(-)

Comments

Junio C Hamano April 1, 2021, 8:41 p.m. UTC | #1
Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:

> -		if (get_tree_entry_mode(r, hash2, del_prefix, shifted, &mode))
> +		if (get_tree_entry_path(r, hash2, del_prefix, shifted))
>  			die("cannot find path %s in tree %s",
>  			    del_prefix, oid_to_hex(hash2));

The observation that many "get_tree_entry()" users do not need the
mode bits and the code can be simplified by taking advantage of
that fact is good.

It does not automatically follow that it is a good implementation of
that simplification to introduce a variant that does not take the
mode pointer.  The original function could have just been taught to
accept NULL in the field the caller is not interested in, as in many
other functions do.

Besides, get_tree_entry_mode() vs get_tree_entry_path() does not
make any sense as pair of functions with contrasting names.  If it
were that unlike the former that returns mode, the latter returns
path instead, it would have made sense, but that is not what is
going on.  The former returns object name and mode, the latter only
returns object name without mode.

In any case, at this point in the series, it is highly dubious that
an extra function is an improvement.  Teaching get_tree_entry() (do
not even rename it) to take NULL in *mode pointer would make a lot
more sense.
Ævar Arnfjörð Bjarmason April 2, 2021, 9:41 a.m. UTC | #2
On Thu, Apr 01 2021, Junio C Hamano wrote:

> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
>
>> -		if (get_tree_entry_mode(r, hash2, del_prefix, shifted, &mode))
>> +		if (get_tree_entry_path(r, hash2, del_prefix, shifted))
>>  			die("cannot find path %s in tree %s",
>>  			    del_prefix, oid_to_hex(hash2));
>
> The observation that many "get_tree_entry()" users do not need the
> mode bits and the code can be simplified by taking advantage of
> that fact is good.
>
> It does not automatically follow that it is a good implementation of
> that simplification to introduce a variant that does not take the
> mode pointer.  The original function could have just been taught to
> accept NULL in the field the caller is not interested in, as in many
> other functions do.
>
> Besides, get_tree_entry_mode() vs get_tree_entry_path() does not
> make any sense as pair of functions with contrasting names.  If it
> were that unlike the former that returns mode, the latter returns
> path instead, it would have made sense, but that is not what is
> going on.  The former returns object name and mode, the latter only
> returns object name without mode.
>
> In any case, at this point in the series, it is highly dubious that
> an extra function is an improvement.  Teaching get_tree_entry() (do
> not even rename it) to take NULL in *mode pointer would make a lot
> more sense.

Thanks. Yes that makes a lot more sense.

This whole path of introducing multiple functions is an oversight of
mine. I did it because in 7146e66f086 (tree-walk: finally switch over
tree descriptors to contain a pre-parsed entry, 2014-02-06) we removed
canon_mode() from the inline function to make it trivially inline-able.

So I assumed without testing that introducing conditionals in that
function would matter to a compiler, and wanted to not introduce any
performance regressions (however small) in this series.

But looking at the generated *.s code under GCC -O3 it makes no
difference if you've got an "if (ptr) *ptr = xyz" there. The compiler
sees that and produces the same machine code.

So I'll re-roll this to do as you suggested, thanks.
diff mbox series

Patch

diff --git a/match-trees.c b/match-trees.c
index d4457eba997..240922f7080 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -288,12 +288,10 @@  void shift_tree(struct repository *r,
 
 	if (add_score < del_score) {
 		/* We need to pick a subtree of two */
-		unsigned short mode;
-
 		if (!*del_prefix)
 			return;
 
-		if (get_tree_entry_mode(r, hash2, del_prefix, shifted, &mode))
+		if (get_tree_entry_path(r, hash2, del_prefix, shifted))
 			die("cannot find path %s in tree %s",
 			    del_prefix, oid_to_hex(hash2));
 		return;
diff --git a/merge-recursive.c b/merge-recursive.c
index c2e9f5d22d0..28ed69ddfaa 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1882,11 +1882,9 @@  static int tree_has_path(struct repository *r, struct tree *tree,
 			 const char *path)
 {
 	struct object_id hashy;
-	unsigned short mode_o;
-
-	return !get_tree_entry_mode(r,
+	return !get_tree_entry_path(r,
 				    &tree->object.oid, path,
-				    &hashy, &mode_o);
+				    &hashy);
 }
 
 /*
diff --git a/notes.c b/notes.c
index e6244624055..6766b1b478f 100644
--- a/notes.c
+++ b/notes.c
@@ -994,7 +994,6 @@  void init_notes(struct notes_tree *t, const char *notes_ref,
 		combine_notes_fn combine_notes, int flags)
 {
 	struct object_id oid, object_oid;
-	unsigned short mode;
 	struct leaf_node root_tree;
 
 	if (!t)
@@ -1021,7 +1020,7 @@  void init_notes(struct notes_tree *t, const char *notes_ref,
 		return;
 	if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, &object_oid))
 		die("Cannot use notes ref %s", notes_ref);
-	if (get_tree_entry_mode(the_repository, &object_oid, "", &oid, &mode))
+	if (get_tree_entry_path(the_repository, &object_oid, "", &oid))
 		die("Failed to read notes tree referenced by %s (%s)",
 		    notes_ref, oid_to_hex(&object_oid));
 
diff --git a/object-name.c b/object-name.c
index 7e3b2d6d739..9ff5f83c1ff 100644
--- a/object-name.c
+++ b/object-name.c
@@ -1693,7 +1693,6 @@  static void diagnose_invalid_oid_path(struct repository *r,
 				      int object_name_len)
 {
 	struct object_id oid;
-	unsigned short mode;
 
 	if (!prefix)
 		prefix = "";
@@ -1704,7 +1703,7 @@  static void diagnose_invalid_oid_path(struct repository *r,
 	if (is_missing_file_error(errno)) {
 		char *fullname = xstrfmt("%s%s", prefix, filename);
 
-		if (!get_tree_entry_mode(r, tree_oid, fullname, &oid, &mode)) {
+		if (!get_tree_entry_path(r, tree_oid, fullname, &oid)) {
 			die(_("path '%s' exists, but not '%s'\n"
 			    "hint: Did you mean '%.*s:%s' aka '%.*s:./%s'?"),
 			    fullname,
diff --git a/tree-walk.c b/tree-walk.c
index 30e3bb64e49..d0dc0c35318 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -628,6 +628,15 @@  int get_tree_entry_mode(struct repository *r,
 	return retval;
 }
 
+int get_tree_entry_path(struct repository *r,
+			const struct object_id *tree_oid,
+			const char *name,
+			struct object_id *oid)
+{
+	unsigned short mode;
+	return get_tree_entry_mode(r, tree_oid, name, oid, &mode);
+}
+
 /*
  * This is Linux's built-in max for the number of symlinks to follow.
  * That limit, of course, does not affect git, but it's a reasonable
diff --git a/tree-walk.h b/tree-walk.h
index a01f2f226ec..c60667cba8f 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -172,8 +172,11 @@  struct traverse_info {
  * You always need a pointer to an appropriate variable to fill in
  * (NULL won't do!). That variable is:
  *
+ * get_tree_entry_path(): <no extra argument, just get the common 'path'>
  * get_tree_entry_mode(): unsigned short mode
  */
+int get_tree_entry_path(struct repository *, const struct object_id *, const char *,
+			struct object_id *);
 int get_tree_entry_mode(struct repository *, const struct object_id *, const char *,
 			struct object_id *,
 			unsigned short *);