git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH] worktree: avoid dead-code in conditional
@ 2020-06-24 19:05 Eric Sunshine
  2020-06-24 21:20 ` Junio C Hamano
  0 siblings, 1 reply; 4+ messages in thread
From: Eric Sunshine @ 2020-06-24 19:05 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Hariom verma, Eric Sunshine

get_worktrees() retrieves a list of all worktrees associated with a
repository, including the main worktree. The location of the main
worktree is determined by get_main_worktree() which needs to handle
three distinct cases for the main worktree after absolute-path
conversion:

    * <bare-repository>/.
    * <main-worktree>/.git/. (when $CWD is .git)
    * <main-worktree>/.git (when $CWD is any worktree)

They all need to be normalized to just the <path> portion, dropping any
"/." or "/.git" suffix.

It turns out, however, that get_main_worktree() was only handling the
first and last cases, i.e.:

    if (!strip_suffix(path, "/.git"))
        strip_suffix(path, "/.");

This shortcoming was addressed by 45f274fbb1 (get_main_worktree(): allow
it to be called in the Git directory, 2020-02-23) by changing the logic
to:

    strip_suffix(path, "/.");
    if (!strip_suffix(path, "/.git"))
        strip_suffix(path, "/.");

which makes the final strip_suffix() invocation dead-code.

Fix this oversight by enumerating the three distinct cases explicitly
rather than attempting to strip the suffix(es) incrementally.

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
---

This "dead-code problem" was caught during review[1], however, the patch
was never re-rolled and ended up being accepted as-is. Dscho had raised
an objection[2] to the suggested way to fix the dead-code problem but
his objection was based upon a misunderstanding[3] thus (implicitly)
withdrawn.

An alternative to enumerating the three distinct cases, as this patch
does, would be to strip suffix components incrementally like this:

    strip_suffix(path, "/.");
    strip_suffix(path, "/.git");

However, such code is relatively opaque and would require a largish
in-code comment mirroring a chunk of the comment message of this patch.
The chosen approach, on the other hand, is relatively self-documenting,
requiring only very small inline source-code comments.

[1]: https://lore.kernel.org/git/CAPig+cTh-uu-obh9aeDOV9ptbVwRmkujgucbu9ei1Qa3qSNG_A@mail.gmail.com/
[2]: https://lore.kernel.org/git/nycvar.QRO.7.76.6.2002241942120.46@tvgsbejvaqbjf.bet/
[3]: https://lore.kernel.org/git/nycvar.QRO.7.76.6.2002271658250.46@tvgsbejvaqbjf.bet/

 worktree.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/worktree.c b/worktree.c
index ee82235f26..b5cdee34de 100644
--- a/worktree.c
+++ b/worktree.c
@@ -50,9 +50,9 @@ static struct worktree *get_main_worktree(void)
 	struct strbuf worktree_path = STRBUF_INIT;
 
 	strbuf_add_absolute_path(&worktree_path, get_git_common_dir());
-	strbuf_strip_suffix(&worktree_path, "/.");
-	if (!strbuf_strip_suffix(&worktree_path, "/.git"))
-		strbuf_strip_suffix(&worktree_path, "/.");
+	if (!strbuf_strip_suffix(&worktree_path, "/.git/.") && /* in .git */
+	    !strbuf_strip_suffix(&worktree_path, "/.git")) /* in worktree */
+		strbuf_strip_suffix(&worktree_path, "/."); /* in bare repo */
 
 	worktree = xcalloc(1, sizeof(*worktree));
 	worktree->path = strbuf_detach(&worktree_path, NULL);
-- 
2.27.0.288.g4b34aa94c7


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] worktree: avoid dead-code in conditional
  2020-06-24 19:05 [PATCH] worktree: avoid dead-code in conditional Eric Sunshine
@ 2020-06-24 21:20 ` Junio C Hamano
  2020-06-24 23:00   ` Eric Sunshine
  0 siblings, 1 reply; 4+ messages in thread
From: Junio C Hamano @ 2020-06-24 21:20 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: git, Johannes Schindelin, Hariom verma

Eric Sunshine <sunshine@sunshineco.com> writes:

> get_worktrees() retrieves a list of all worktrees associated with a
> repository, including the main worktree. The location of the main
> worktree is determined by get_main_worktree() which needs to handle
> three distinct cases for the main worktree after absolute-path
> conversion:
>
>     * <bare-repository>/.
>     * <main-worktree>/.git/. (when $CWD is .git)
>     * <main-worktree>/.git (when $CWD is any worktree)

It is unclear from the above but I would assume that you are talking
about the returned path from get_git_common_dir().

I can certainly understand why there needs two distinct cases
(i.e.. bare vs non-bare), but why is this codepath (or any caller of
get_git_common_dir()) forced to care about the two cases?

I wonder if the right "fix" to this instance, at the same time
preventing similar breakages in the future, is rather make sure
get_git_common_dir() not to return the redundant path with ".git/."
suffixed?  For that matter, I do not know why the bare case must
need "/." suffix.  There seem to be about a dozen callers of the
function, but don't some of them share a similar issue?  

Let's look at the other two grep hits from worktree.c

	strbuf_reset(&path);
	strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);

	worktree = xcalloc(1, sizeof(*worktree));
	worktree->path = strbuf_detach(&worktree_path, NULL);
	worktree->id = xstrdup(id);
	add_head_info(worktree);

done:
	strbuf_release(&path);
	strbuf_release(&worktree_path);
	return worktree;
}

This looks somewhat bogus.  "sturct strbuf path" is populated, but
is released without ever getting used, isn't it?  Am I grossly
misreading the code?

The other one

	strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
	dir = opendir(path.buf);
	strbuf_release(&path);
	if (dir) {
		while ((d = readdir(dir)) != NULL) {
		...

is a regular filesystem access, but it ends up opening the directory
with a path like "foo/.git/./worktrees", where we should be using a
more reasonable "foo/.git/worktrees" to access it.  The redundant
"/./" is not wrong per-se, but it looks sloppy to depend on "not
wrong per-se".

Puzzled.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] worktree: avoid dead-code in conditional
  2020-06-24 21:20 ` Junio C Hamano
@ 2020-06-24 23:00   ` Eric Sunshine
  2020-06-25  0:38     ` Junio C Hamano
  0 siblings, 1 reply; 4+ messages in thread
From: Eric Sunshine @ 2020-06-24 23:00 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git List, Johannes Schindelin, Hariom verma

On Wed, Jun 24, 2020 at 5:20 PM Junio C Hamano <gitster@pobox.com> wrote:
> Eric Sunshine <sunshine@sunshineco.com> writes:
> > get_worktrees() retrieves a list of all worktrees associated with a
> > repository, including the main worktree. The location of the main
> > worktree is determined by get_main_worktree() which needs to handle
> > three distinct cases for the main worktree after absolute-path
> > conversion:
> >
> >   * <bare-repository>/.
> >   * <main-worktree>/.git/. (when $CWD is .git)
> >   * <main-worktree>/.git (when $CWD is any worktree)
>
> It is unclear from the above but I would assume that you are talking
> about the returned path from get_git_common_dir().

No, I am talking about the result of strbuf_add_absolute_path()
applied to get_git_common_dir(). I intentionally explicitly stated
"after absolute-path conversion" in the commit message to be clear
about this, but perhaps I should have mentioned
strbuf_add_absolute_path() by name to avoid confusion.

> I can certainly understand why there needs two distinct cases
> (i.e.. bare vs non-bare), but why is this codepath (or any caller of
> get_git_common_dir()) forced to care about the two cases?

Callers of get_git_common_dir() aren't forced to care. But after
applying strbuf_add_absolute_path() we are forced to care. This is the
result of get_git_common_dir() for the three cases:

    .     (within bare repo)
    .git  (within any worktree)
    .     (within .git)

After applying strbuf_add_absolute_path(), we get:

    /whatever/proj.git/.   (within bare proj)
    /whatever/proj/.git    (within any worktree)
    /whatever/proj/.git/.  (within .git)

These need to be normalized, respectively, to:

    /whatever/proj.git  (within bare proj)
    /whatever/proj      (within any worktree)
    /whatever/proj      (within .git)

> I wonder if the right "fix" to this instance, at the same time
> preventing similar breakages in the future, is rather make sure
> get_git_common_dir() not to return the redundant path with ".git/."
> suffixed? For that matter, I do not know why the bare case must
> need "/." suffix. There seem to be about a dozen callers of the
> function, but don't some of them share a similar issue?
>
> Puzzled.

Your puzzlement may arise from the misunderstanding regarding
get_git_common_dir() vs. strbuf_add_absolute_path()?

It might be nice to refine strbuf_add_absolute_path() to return more
aesthetically pleasing results (i.e. not add trailing "." when
unneeded), but such a change is outside the scope of this small patch
and may have repercussions which could be a time sink (and I haven't
the time to devote to it).

> Let's look at the other two grep hits from worktree.c
>
>     strbuf_reset(&path);
>     strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
>
>     worktree = xcalloc(1, sizeof(*worktree));
>     worktree->path = strbuf_detach(&worktree_path, NULL);
>     worktree->id = xstrdup(id);
>     add_head_info(worktree);
>
> done:
>     strbuf_release(&path);
>     strbuf_release(&worktree_path);
>     return worktree;
> }
>
> This looks somewhat bogus. "sturct strbuf path" is populated, but
> is released without ever getting used, isn't it? Am I grossly
> misreading the code?

I think you're reading it just fine; that code is indeed dead. This
appears to be fallout from 5193490442 (worktree: add a function to get
worktree details, 2015-10-08), which unfortunately (I think) got
little or no review[1].

This could indeed use a "dead-code removal" patch of its own, though
it's unrelated to the current patch.

FOOTNOTES

[1] I had reviewed the very first version of the patch series which
    introduced these changes, but then effectively went offline for
    many, many months, thus was unable to review any of the re-rolls.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] worktree: avoid dead-code in conditional
  2020-06-24 23:00   ` Eric Sunshine
@ 2020-06-25  0:38     ` Junio C Hamano
  0 siblings, 0 replies; 4+ messages in thread
From: Junio C Hamano @ 2020-06-25  0:38 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: Git List, Johannes Schindelin, Hariom verma

Eric Sunshine <sunshine@sunshineco.com> writes:

> Callers of get_git_common_dir() aren't forced to care. But after
> applying strbuf_add_absolute_path() we are forced to care. This is the
> result of get_git_common_dir() for the three cases:
>
>     .     (within bare repo)
>     .git  (within any worktree)
>     .     (within .git)
>
> After applying strbuf_add_absolute_path(), we get:
>
>     /whatever/proj.git/.   (within bare proj)
>     /whatever/proj/.git    (within any worktree)
>     /whatever/proj/.git/.  (within .git)

OK, but the point still stands.  

Shouldn't strbuf_add_absolute_path() be what we want to normalize?

> Your puzzlement may arise from the misunderstanding regarding
> get_git_common_dir() vs. strbuf_add_absolute_path()?

Yes, exactly.

Thanks.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-06-25  0:38 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-24 19:05 [PATCH] worktree: avoid dead-code in conditional Eric Sunshine
2020-06-24 21:20 ` Junio C Hamano
2020-06-24 23:00   ` Eric Sunshine
2020-06-25  0:38     ` Junio C Hamano

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).