* [PATCH v2 0/4] Link worktrees with relative paths @ 2024-10-06 6:00 Caleb White 2024-10-06 6:00 ` [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf Caleb White ` (4 more replies) 0 siblings, 5 replies; 38+ messages in thread From: Caleb White @ 2024-10-06 6:00 UTC (permalink / raw) To: git; +Cc: Caleb White [-- Attachment #1: Type: text/plain, Size: 665 bytes --] This is a resubmission attempt to try to fix the damaged patch noted in previous discussions. Thanks! Caleb White (4): worktree: refactor infer_backlink() to use *strbuf worktree: link worktrees with relative paths worktree: sync worktree paths after gitdir move worktree: prevent null pointer dereference builtin/worktree.c | 17 +-- setup.c | 2 +- t/t2408-worktree-relative.sh | 39 ++++++ worktree.c | 235 +++++++++++++++++++++++++++-------- worktree.h | 10 ++ 5 files changed, 240 insertions(+), 63 deletions(-) create mode 100755 t/t2408-worktree-relative.sh -- 2.46.2 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 6:00 [PATCH v2 0/4] Link worktrees with relative paths Caleb White @ 2024-10-06 6:00 ` Caleb White 2024-10-06 15:09 ` shejialuo 2024-10-06 18:16 ` Eric Sunshine 2024-10-06 6:01 ` [PATCH v2 2/4] worktree: link worktrees with relative paths Caleb White ` (3 subsequent siblings) 4 siblings, 2 replies; 38+ messages in thread From: Caleb White @ 2024-10-06 6:00 UTC (permalink / raw) To: git; +Cc: Caleb White [-- Attachment #1: Type: text/plain, Size: 3498 bytes --] This refactors the `infer_backlink` function to return an integer result and use a pre-allocated `strbuf` for the inferred backlink path, replacing the previous `char*` return type. This lays the groundwork for the next patch, which needs the resultant backlink as a `strbuf`. There was no need to go from `strbuf -> char* -> strbuf` again. This change also aligns the function's signature with other `strbuf`-based functions. Signed-off-by: Caleb White <cdwhite3@pm.me> --- worktree.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/worktree.c b/worktree.c index 0f032cc..c6d2ede 100644 --- a/worktree.c +++ b/worktree.c @@ -642,10 +642,9 @@ static int is_main_worktree_path(const char *path) * be able to infer the gitdir by manually reading /path/to/worktree/.git, * extracting the <id>, and checking if <repo>/worktrees/<id> exists. */ -static char *infer_backlink(const char *gitfile) +static int infer_backlink(st ruct strbuf *inferred, const char *gitfile) { struct strbuf actual = STRBUF_INIT; - struct strbuf inferred = STRBUF_INIT; const char *id; if (strbuf_read_file(&actual, gitfile, 0) < 0) @@ -658,17 +657,16 @@ static char *infer_backlink(const char *gitfile) id++; /* advance past '/' to point at <id> */ if (!*id) goto error; - strbuf_git_common_path(&inferred, the_repository, "worktrees/%s", id); - if (!is_directory(inferred.buf)) + strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id); + if (!is_directory(inferred->buf)) goto error; strbuf_release(&actual); - return strbuf_detach(&inferred, NULL); + return 0; error: strbuf_release(&actual); - strbuf_release(&inferred); - return NULL; + return 1; } /* @@ -680,9 +678,10 @@ void repair_worktree_at_path(const char *path, { struct strbuf dotgit = STRBUF_INIT; struct strbuf realdotgit = STRBUF_INIT; + struct strbuf backlink = STRBUF_INIT; struct strbuf gitd ir = STRBUF_INIT; struct strbuf olddotgit = STRBUF_INIT; - char *backlink = NULL; + char *git_contents = NULL; const char *repair = NULL; int err; @@ -698,21 +697,23 @@ void repair_worktree_at_path(const char *path, goto done; } - backlink = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); + git_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); if (err == READ_GITFILE_ERR_NOT_A_FILE) { fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); goto done; } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { - if (!(backlink = infer_backlink(realdotgit.buf))) { + if (infer_backlink(&backlink, realdotgit.buf)) { fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); goto done; } } else if (err) { fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); goto done; + } else if (git_conte nts) { + strbuf_addstr(&backlink, git_contents); } - strbuf_addf(&gitdir, "%s/gitdir", backlink); + strbuf_addf(&gitdir, "%s/gitdir", backlink.buf); if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0) repair = _("gitdir unreadable"); else { @@ -726,8 +727,9 @@ void repair_worktree_at_path(const char *path, write_file(gitdir.buf, "%s", realdotgit.buf); } done: - free(backlink); + free(git_contents); strbuf_release(&olddotgit); + strbuf_release(&backlink); strbuf_release(&gitdir); strbuf_release(&realdotgit); strbuf_release(&dotgit); -- 2.46.2 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 6:00 ` [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf Caleb White @ 2024-10-06 15:09 ` shejialuo 2024-10-06 15:13 ` Kristoffer Haugsbakk ` (2 more replies) 2024-10-06 18:16 ` Eric Sunshine 1 sibling, 3 replies; 38+ messages in thread From: shejialuo @ 2024-10-06 15:09 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 06, 2024 at 06:00:57AM +0000, Caleb White wrote: > This refactors the `infer_backlink` function to return an integer > result and use a pre-allocated `strbuf` for the inferred backlink > path, replacing the previous `char*` return type. > > This lays the groundwork for the next patch, which needs the > resultant backlink as a `strbuf`. There was no need to go from > `strbuf -> char* -> strbuf` again. This change also aligns the > function's signature with other `strbuf`-based functions. > I think we should first say why we need to add the change in the commit message which means we should express our motivation in the first. It's wired to say "I have done something" and then talk about the motivation why we do this. > Signed-off-by: Caleb White <cdwhite3@pm.me> > --- > worktree.c | 26 ++++++++++++++------------ > 1 file changed, 14 insertions(+), 12 deletions(-) > > diff --git a/worktree.c b/worktree.c > index 0f032cc..c6d2ede 100644 > --- a/worktree.c > +++ b/worktree.c > @@ -642,10 +642,9 @@ static int is_main_worktree_path(const char *path) > * be able to infer the gitdir by manually reading /path/to/worktree/.git, > * extracting the <id>, and checking if <repo>/worktrees/<id> exists. > */ > -static char *infer_backlink(const char *gitfile) > +static int infer_backlink(st > ruct strbuf *inferred, const char *gitfile) This line is so strange. Why it generates a newline here? > { > struct strbuf actual = STRBUF_INIT; > - struct strbuf inferred = STRBUF_INIT; > const char *id; > > if (strbuf_read_file(&actual, gitfile, 0) < 0) > @@ -658,17 +657,16 @@ static char *infer_backlink(const char *gitfile) > id++; /* advance past '/' to point at <id> */ > if (!*id) > goto error; > - strbuf_git_common_path(&inferred, the_repository, "worktrees/%s", id); > - if (!is_directory(inferred.buf)) > + strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id); > + if (!is_directory(inferred->buf)) > goto error; > > strbuf_release(&actual); > - return strbuf_detach(&inferred, NULL); > + return 0; > > error: > strbuf_release(&actual); > - strbuf_release(&inferred); Because we leave the life cycle of the "inferred" to be outside of this function, we should not use "strbuf_release" to release the memory here. Make sense. > - return NULL; > + return 1; > } > > /* > @@ -680,9 +678,10 @@ void repair_worktree_at_path(const char *path, > { > struct strbuf dotgit = STRBUF_INIT; > struct strbuf realdotgit = STRBUF_INIT; > + struct strbuf backlink = STRBUF_INIT; Here, we replace "char *backlink" to "struct strbuf backlink", we need to align the changed "infer_backlink" function. That's OK. > struct strbuf gitd > ir = STRBUF_INIT; Another strange newline here. > struct strbuf olddotgit = STRBUF_INIT; > - char *backlink = NULL; > + char *git_contents = NULL; > const char *repair = NULL; > int err; > > @@ -698,21 +697,23 @@ void repair_worktree_at_path(const char *path, > goto done; > } > > - backlink = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); > + git_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); So, we create a new variable "git_contents" here. I suspect this is a poor design. In the original logic, we will do the following things for "backlink". 1. Call the "read_gitfile_gently" function. If it encounters error, it will return NULL and the "err" variable will be set to NON-zero. 2. If the value of "err" is 0, we would simply execute the "strbuf_addstr(&gitdir, "%s/gitdir", backlink)". 3. If not, and the "err" is "READ_GITFILE_ERR_NOT_A_REPO". We will call "infer_backlink" to set the "backlink". Because now "backlink" is "struct strbuf", we cannot just assign it by using "xstrdup_or_null(read_gitfile_gently(...))". So, we create a new variable "git_contents" here. And we will check whether "git_contents" is NULL to set the value for the "backlink". Why not simply do the following things here (I don't think "git_contents" is a good name, however I am not familiar with the worktree, I cannot give some advice here). const char *git_contents; git_contents = read_gitfile_gently(...); if (git_contents) strbuf_addstr(&backlink, git_contents); Even more, we could enhance the logic here. If "git_contents" is not NULL, there is no need for us to check the "err" variable. > if (err == READ_GITFILE_ERR_NOT_A_FILE) { > fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); > goto done; > } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { > - if (!(backlink = infer_backlink(realdotgit.buf))) { > + if (infer_backlink(&backlink, realdotgit.buf)) { > fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); > goto done; > } > } else if (err) { > fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); > goto done; > + } else if (git_conte > nts) { Another strange newline here. As I have talked about above, we should not check "git_contents" here. > + strbuf_addstr(&backlink, git_contents); > } > > - strbuf_addf(&gitdir, "%s/gitdir", backlink); > + strbuf_addf(&gitdir, "%s/gitdir", backlink.buf); > if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0) > repair = _("gitdir unreadable"); > else { > @@ -726,8 +727,9 @@ void repair_worktree_at_path(const char *path, > write_file(gitdir.buf, "%s", realdotgit.buf); > } > done: > - free(backlink); > + free(git_contents); > strbuf_release(&olddotgit); > + strbuf_release(&backlink); > strbuf_release(&gitdir); > strbuf_release(&realdotgit); > strbuf_release(&dotgit); > -- > 2.46.2 > Thanks, Jialuo ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 15:09 ` shejialuo @ 2024-10-06 15:13 ` Kristoffer Haugsbakk 2024-10-06 18:41 ` Eric Sunshine 2024-10-06 23:47 ` Caleb White 2 siblings, 0 replies; 38+ messages in thread From: Kristoffer Haugsbakk @ 2024-10-06 15:13 UTC (permalink / raw) To: shejialuo, Caleb White; +Cc: git, Eric Sunshine On Sun, Oct 6, 2024, at 17:09, shejialuo wrote: > On Sun, Oct 06, 2024 at 06:00:57AM +0000, Caleb White wrote: >> This refactors the `infer_backlink` function to return an integer >> result and use a pre-allocated `strbuf` for the inferred backlink >> path, replacing the previous `char*` return type. >> >> This lays the groundwork for the next patch, which needs the >> resultant backlink as a `strbuf`. There was no need to go from >> `strbuf -> char* -> strbuf` again. This change also aligns the >> function's signature with other `strbuf`-based functions. >> > > I think we should first say why we need to add the change in the commit > message which means we should express our motivation in the first. It's > wired to say "I have done something" and then talk about the motivation > why we do this. > >> Signed-off-by: Caleb White <cdwhite3@pm.me> >> --- >> worktree.c | 26 ++++++++++++++------------ >> 1 file changed, 14 insertions(+), 12 deletions(-) >> >> diff --git a/worktree.c b/worktree.c >> index 0f032cc..c6d2ede 100644 >> --- a/worktree.c >> +++ b/worktree.c >> @@ -642,10 +642,9 @@ static int is_main_worktree_path(const char *path) >> * be able to infer the gitdir by manually reading /path/to/worktree/.git, >> * extracting the <id>, and checking if <repo>/worktrees/<id> exists. >> */ >> -static char *infer_backlink(const char *gitfile) >> +static int infer_backlink(st >> ruct strbuf *inferred, const char *gitfile) > > This line is so strange. Why it generates a newline here? The patches got corrupted by something. See the emails from Eric Sunshine. This resubmit didn’t fix the issue. https://lore.kernel.org/git/CAPig+cTB-sA-g4cdhfEjWwY1mnbWJ41e=bOCNwp=Y8JKvpmpRg@mail.gmail.com/ -- Kristoffer Haugsbakk ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 15:09 ` shejialuo 2024-10-06 15:13 ` Kristoffer Haugsbakk @ 2024-10-06 18:41 ` Eric Sunshine 2024-10-07 2:26 ` Caleb White 2024-10-07 3:56 ` shejialuo 2024-10-06 23:47 ` Caleb White 2 siblings, 2 replies; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 18:41 UTC (permalink / raw) To: shejialuo; +Cc: Caleb White, git On Sun, Oct 6, 2024 at 11:09 AM shejialuo <shejialuo@gmail.com> wrote: > On Sun, Oct 06, 2024 at 06:00:57AM +0000, Caleb White wrote: > > - backlink = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); > > + git_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); > > So, we create a new variable "git_contents" here. I suspect this is a > poor design. In the original logic, we will do the following things for > "backlink". > > 1. Call the "read_gitfile_gently" function. If it encounters error, it > will return NULL and the "err" variable will be set to NON-zero. > 2. If the value of "err" is 0, we would simply execute the > "strbuf_addstr(&gitdir, "%s/gitdir", backlink)". > 3. If not, and the "err" is "READ_GITFILE_ERR_NOT_A_REPO". We will > call "infer_backlink" to set the "backlink". > > Because now "backlink" is "struct strbuf", we cannot just assign it by > using "xstrdup_or_null(read_gitfile_gently(...))". So, we create a new > variable "git_contents" here. > > And we will check whether "git_contents" is NULL to set the value for > the "backlink". Thanks for thinking through this logic. I have a few additional comments... > Why not simply do the following things here (I don't think > "git_contents" is a good name, however I am not familiar with the > worktree, I cannot give some advice here). I found the name "git_contents" clear enough and understood its purpose at-a-glance, so I think it's a reasonably good choice. A slightly better name might be "gitfile_contents" or perhaps "dotgit_contents" for consistency with other similarly-named variables in this function. > const char *git_contents; > git_contents = read_gitfile_gently(...); > if (git_contents) > strbuf_addstr(&backlink, git_contents); > > Even more, we could enhance the logic here. Upon reading this patch, I had a similar thought about this, that it would be more reflective of the original code to set "backlink" early here rather than waiting until the end of the if-else-cascade. However, upon reflection, I don't mind that setting "backlink" is delayed until after the if-else-chain, though I think it deserves at least one change which I will explain below. > If "git_contents" is not > NULL, there is no need for us to check the "err" variable. I'm not sure we would want to change this; the existing logic seems clear enough. > > if (err == READ_GITFILE_ERR_NOT_A_FILE) { > > fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); > > goto done; > > } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { > > - if (!(backlink = infer_backlink(realdotgit.buf))) { > > + if (infer_backlink(&backlink, realdotgit.buf)) { > > fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); > > goto done; > > } > > } else if (err) { > > fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); > > goto done; > > + } else if (git_contents) { > > + strbuf_addstr(&backlink, git_contents); > > } It certainly makes sense to check whether "git_contents" is NULL before trying to copy it into the "backlink" strbuf, however, if "git_contents" is NULL here, then what does that mean? What does it mean to leave "backlink" empty? The only way (presumably) we get this far is if read_gitfile_gently() succeeded, so (presumably) "git_contents" should not be NULL. Thus, rather than conditionally copying into "backlink", we should instead indicate clearly via BUG() that it should be impossible for "git_contents" to be NULL. So, rather than making this part of the existing if-else-cascade, we should do this as a standalone `if`: if (!git_contents) BUG(...); strbuf_addstr(&backlink, git_contents); ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 18:41 ` Eric Sunshine @ 2024-10-07 2:26 ` Caleb White 2024-10-07 4:12 ` shejialuo 2024-10-07 3:56 ` shejialuo 1 sibling, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-07 2:26 UTC (permalink / raw) To: Eric Sunshine; +Cc: shejialuo, git [-- Attachment #1.1: Type: text/plain, Size: 1378 bytes --] On Sunday, October 6th, 2024 at 13:41, Eric Sunshine <sunshine@sunshineco.com> wrote: > I found the name "git_contents" clear enough and understood its > purpose at-a-glance, so I think it's a reasonably good choice. A > slightly better name might be "gitfile_contents" or perhaps > "dotgit_contents" for consistency with other similarly-named variables > in this function. I will rename to `dotgit_contents`. > It certainly makes sense to check whether "git_contents" is NULL > before trying to copy it into the "backlink" strbuf, however, if > "git_contents" is NULL here, then what does that mean? What does it > mean to leave "backlink" empty? The only way (presumably) we get this > far is if read_gitfile_gently() succeeded, so (presumably) > "git_contents" should not be NULL. Thus, rather than conditionally > copying into "backlink", we should instead indicate clearly via BUG() > that it should be impossible for "git_contents" to be NULL. So, rather > than making this part of the existing if-else-cascade, we should do > this as a standalone `if`: > > if (!git_contents) > BUG(...); > strbuf_addstr(&backlink, git_contents); We can't use BUG because this is handled as part of the err conditions. The contents can be NULL and `backlink` could be filled with the inferred backlink. I moved this to the top and I think it reads better. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 2:26 ` Caleb White @ 2024-10-07 4:12 ` shejialuo 2024-10-07 4:19 ` Caleb White 0 siblings, 1 reply; 38+ messages in thread From: shejialuo @ 2024-10-07 4:12 UTC (permalink / raw) To: Caleb White; +Cc: Eric Sunshine, git On Mon, Oct 07, 2024 at 02:26:51AM +0000, Caleb White wrote: > On Sunday, October 6th, 2024 at 13:41, Eric Sunshine <sunshine@sunshineco.com> wrote: > > I found the name "git_contents" clear enough and understood its > > purpose at-a-glance, so I think it's a reasonably good choice. A > > slightly better name might be "gitfile_contents" or perhaps > > "dotgit_contents" for consistency with other similarly-named variables > > in this function. > > I will rename to `dotgit_contents`. > > > It certainly makes sense to check whether "git_contents" is NULL > > before trying to copy it into the "backlink" strbuf, however, if > > "git_contents" is NULL here, then what does that mean? What does it > > mean to leave "backlink" empty? The only way (presumably) we get this > > far is if read_gitfile_gently() succeeded, so (presumably) > > "git_contents" should not be NULL. Thus, rather than conditionally > > copying into "backlink", we should instead indicate clearly via BUG() > > that it should be impossible for "git_contents" to be NULL. So, rather > > than making this part of the existing if-else-cascade, we should do > > this as a standalone `if`: > > > > > if (!git_contents) > > BUG(...); > > strbuf_addstr(&backlink, git_contents); I agree with the idea that Eric proposed. It's truly we should raise a bug here. That's would be much more clear. > We can't use BUG because this is handled as part of the err > conditions. The contents can be NULL and `backlink` could be > filled with the inferred backlink. I moved this to the top > and I think it reads better. That's not correct. It is true that the contents can be NULL and `backlink` could be filled with the infer_backlink. But do you notice that if `backlink` was filled with the infer_backlink, it will jump to the "done" label. What Erie means is the following: git_contents = read_gitfile_gently(...); if (err) { if (...) { } else if (err == RAED_GITFILE_ERR_NOT_A_REPO) { // handle backlink goto done; } } if (!git_contents) BUG(...); strbuf_addstr(&backlink, git_contents); done: // cleanup operations Thanks, Jialuo ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 4:12 ` shejialuo @ 2024-10-07 4:19 ` Caleb White 2024-10-07 4:28 ` shejialuo 0 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-07 4:19 UTC (permalink / raw) To: shejialuo; +Cc: Eric Sunshine, git [-- Attachment #1.1: Type: text/plain, Size: 1375 bytes --] On Sunday, October 6th, 2024 at 23:12, shejialuo <shejialuo@gmail.com> wrote: > That's not correct. It is true that the contents can be NULL and > `backlink` could be filled with the infer_backlink. But do you notice > that if `backlink` was filled with the infer_backlink, it will jump > to the "done" label. This is not correct, if backlink is filled with `infer_backlink` it continues on with the processing. I have made this more clear: dotgit_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); if (dotgit_contents) { if (is_absolute_path(dotgit_contents)) { strbuf_addstr(&backlink, dotgit_contents); } else { strbuf_addbuf(&backlink, &realdotgit); strbuf_strip_suffix(&backlink, ".git"); strbuf_addstr(&backlink, dotgit_contents); } } else if (err == READ_GITFILE_ERR_NOT_A_FILE) { fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); goto done; } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { if (!infer_backlink(realdotgit.buf, &backlink)) { fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); goto done; } } else if (err) { fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); goto done; } [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 4:19 ` Caleb White @ 2024-10-07 4:28 ` shejialuo 2024-10-07 4:31 ` Caleb White 0 siblings, 1 reply; 38+ messages in thread From: shejialuo @ 2024-10-07 4:28 UTC (permalink / raw) To: Caleb White; +Cc: Eric Sunshine, git On Mon, Oct 07, 2024 at 04:19:22AM +0000, Caleb White wrote: > On Sunday, October 6th, 2024 at 23:12, shejialuo <shejialuo@gmail.com> wrote: > > That's not correct. It is true that the contents can be NULL and > > `backlink` could be filled with the infer_backlink. But do you notice > > that if `backlink` was filled with the infer_backlink, it will jump > > to the "done" label. > > This is not correct, if backlink is filled with `infer_backlink` it > continues on with the processing. I have made this more clear: > > dotgit_contents = xstrdup_or_null(read_gitfile_gently(realdotgit.buf, &err)); > if (dotgit_contents) { > if (is_absolute_path(dotgit_contents)) { > strbuf_addstr(&backlink, dotgit_contents); > } else { > strbuf_addbuf(&backlink, &realdotgit); > strbuf_strip_suffix(&backlink, ".git"); > strbuf_addstr(&backlink, dotgit_contents); > } > } else if (err == READ_GITFILE_ERR_NOT_A_FILE) { > fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); > goto done; > } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { > if (!infer_backlink(realdotgit.buf, &backlink)) { > fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); > goto done; > } > } else if (err) { > fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); > goto done; > } > > Thanks, you are correct here. We cannot use "BUG" here. And I think currently this is OK. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 4:28 ` shejialuo @ 2024-10-07 4:31 ` Caleb White 0 siblings, 0 replies; 38+ messages in thread From: Caleb White @ 2024-10-07 4:31 UTC (permalink / raw) To: shejialuo; +Cc: Eric Sunshine, git [-- Attachment #1.1: Type: text/plain, Size: 419 bytes --] On Sunday, October 6th, 2024 at 23:28, shejialuo <shejialuo@gmail.com> wrote: > > } else if (err) { > > fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); > > goto done; > > } > > > Thanks, you are correct here. We cannot use "BUG" here. And I think > currently this is OK. Granted, that last `else if` could just become an `else` statement now, I'll make that change. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 18:41 ` Eric Sunshine 2024-10-07 2:26 ` Caleb White @ 2024-10-07 3:56 ` shejialuo 2024-10-07 4:01 ` Caleb White 1 sibling, 1 reply; 38+ messages in thread From: shejialuo @ 2024-10-07 3:56 UTC (permalink / raw) To: Eric Sunshine; +Cc: Caleb White, git On Sun, Oct 06, 2024 at 02:41:22PM -0400, Eric Sunshine wrote: [snip] > > Why not simply do the following things here (I don't think > > "git_contents" is a good name, however I am not familiar with the > > worktree, I cannot give some advice here). > > I found the name "git_contents" clear enough and understood its > purpose at-a-glance, so I think it's a reasonably good choice. A > slightly better name might be "gitfile_contents" or perhaps > "dotgit_contents" for consistency with other similarly-named variables > in this function. > Thanks, I don't know the context here. > > If "git_contents" is not > > NULL, there is no need for us to check the "err" variable. > > I'm not sure we would want to change this; the existing logic seems > clear enough. > The reason why I don't think we need to check the "err" variable is that the "git_contents" and "err" is relevant. If "git_contents" is not NULL, the "err" must be zero unless there are bugs in "read_gitfile_gently". So, if we already check "git_contents", why do we need to check again for "err"? But, I agree with you that the existing logic is clear enough. I just explain further what I mean here. Thanks, Jialuo ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 3:56 ` shejialuo @ 2024-10-07 4:01 ` Caleb White 2024-10-07 4:19 ` shejialuo 0 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-07 4:01 UTC (permalink / raw) To: shejialuo; +Cc: Eric Sunshine, git [-- Attachment #1.1: Type: text/plain, Size: 1043 bytes --] On Sunday, October 6th, 2024 at 22:56, shejialuo <shejialuo@gmail.com> wrote: > The reason why I don't think we need to check the "err" variable is that > the "git_contents" and "err" is relevant. If "git_contents" is not NULL, > the "err" must be zero unless there are bugs in "read_gitfile_gently". > So, if we already check "git_contents", why do we need to check again > for "err"? There are two other error conditions we check, and one of them we try to find the inferred backlink (so it is not a failure path): ``` } else if (err == READ_GITFILE_ERR_NOT_A_FILE) { fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); goto done; } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { if (!infer_backlink(realdotgit.buf, &backlink)) { fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); goto done; } } else if (err) { fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); goto done; } ``` [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 4:01 ` Caleb White @ 2024-10-07 4:19 ` shejialuo 0 siblings, 0 replies; 38+ messages in thread From: shejialuo @ 2024-10-07 4:19 UTC (permalink / raw) To: Caleb White; +Cc: Eric Sunshine, git On Mon, Oct 07, 2024 at 04:01:43AM +0000, Caleb White wrote: > On Sunday, October 6th, 2024 at 22:56, shejialuo <shejialuo@gmail.com> wrote: > > The reason why I don't think we need to check the "err" variable is that > > the "git_contents" and "err" is relevant. If "git_contents" is not NULL, > > the "err" must be zero unless there are bugs in "read_gitfile_gently". > > So, if we already check "git_contents", why do we need to check again > > for "err"? > > There are two other error conditions we check, and one of them we try > to find the inferred backlink (so it is not a failure path): > > ``` > } else if (err == READ_GITFILE_ERR_NOT_A_FILE) { > fn(1, realdotgit.buf, _("unable to locate repository; .git is not a file"), cb_data); > goto done; > } else if (err == READ_GITFILE_ERR_NOT_A_REPO) { > if (!infer_backlink(realdotgit.buf, &backlink)) { > fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); > goto done; > } > } else if (err) { > fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); > goto done; > } > > ``` I am sorry that my words make you not clear here. I want to express that if "git_contents" is not NULL and there is no need for us to check "err". This means we could use the following flows: if (git_contents && !err) { ... } else if (err == xxx) { ... } However, from my perspective, the way proposed by Eric where we could use "BUG" is more robust. Because the current method assumes that "read_gitfile_gently" works as we want. Thanks, Jialuo ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 15:09 ` shejialuo 2024-10-06 15:13 ` Kristoffer Haugsbakk 2024-10-06 18:41 ` Eric Sunshine @ 2024-10-06 23:47 ` Caleb White 2 siblings, 0 replies; 38+ messages in thread From: Caleb White @ 2024-10-06 23:47 UTC (permalink / raw) To: shejialuo; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 2383 bytes --] On Sunday, October 6th, 2024 at 10:09, shejialuo <shejialuo@gmail.com> wrote: > I think we should first say why we need to add the change in the commit > message which means we should express our motivation in the first. It's > wired to say "I have done something" and then talk about the motivation > why we do this. I can reword this commit message. > Because we leave the life cycle of the "inferred" to be outside of this > function, we should not use "strbuf_release" to release the memory here. > Make sense. Yes, however, I just realized that I should likely reset the strbuf when it enters the function (or before it is written to) which is similar to what the relative_path() function does. > So, we create a new variable "git_contents" here. I suspect this is a > poor design. In the original logic, we will do the following things for > "backlink". > > 1. Call the "read_gitfile_gently" function. If it encounters error, it > will return NULL and the "err" variable will be set to NON-zero. > 2. If the value of "err" is 0, we would simply execute the > "strbuf_addstr(&gitdir, "%s/gitdir", backlink)". > 3. If not, and the "err" is "READ_GITFILE_ERR_NOT_A_REPO". We will > call "infer_backlink" to set the "backlink". > > Because now "backlink" is "struct strbuf", we cannot just assign it by > using "xstrdup_or_null(read_gitfile_gently(...))". So, we create a new > variable "git_contents" here. > > And we will check whether "git_contents" is NULL to set the value for > the "backlink". > > Why not simply do the following things here (I don't think > "git_contents" is a good name, however I am not familiar with the > worktree, I cannot give some advice here). > > const char *git_contents; > git_contents = read_gitfile_gently(...); > if (git_contents) > strbuf_addstr(&backlink, git_contents); > > Even more, we could enhance the logic here. If "git_contents" is not > NULL, there is no need for us to check the "err" variable. I was trying to not make huge changes to the logic flow, but I suppose I could revisit this if desired. I can likely move the `if(git_contents)` to the start instead of being at the end. I was not aware that if an err occurred that the function returned NULL, I thought that perhaps there was the possibility of git_contents being filled with something and an err still occurring. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 6:00 ` [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf Caleb White 2024-10-06 15:09 ` shejialuo @ 2024-10-06 18:16 ` Eric Sunshine 2024-10-07 2:42 ` Caleb White 1 sibling, 1 reply; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 18:16 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 2:01 AM Caleb White <cdwhite3@pm.me> wrote: > This refactors the `infer_backlink` function to return an integer > result and use a pre-allocated `strbuf` for the inferred backlink > path, replacing the previous `char*` return type. > > This lays the groundwork for the next patch, which needs the > resultant backlink as a `strbuf`. There was no need to go from > `strbuf -> char* -> strbuf` again. This change also aligns the > function's signature with other `strbuf`-based functions. Regarding aligning the signature with other strbuf-based functions... > Signed-off-by: Caleb White <cdwhite3@pm.me> > --- > diff --git a/worktree.c b/worktree.c > @@ -642,10 +642,9 @@ static int is_main_worktree_path(const char *path) > -static char *infer_backlink(const char *gitfile) > +static int infer_backlink(struct strbuf *inferred, const char *gitfile) ... it's subjective, but I find that placing the strbuf as the first argument makes the purpose of the function less clear. The direct purpose of all (or the majority of) functions in strbuf.h is to operate on strbufs, thus it makes sense for the strbuf to be the first argument (just like `this` is the invisible first argument of instance methods in C++ which operate on an instance of the class). However, infer_backlink()'s purpose isn't to operate on a strbuf; the fact that the original signature neither accepted nor returned a strbuf bears that out. The really important input to this function is `gitfile`, thus it makes sense for this argument to come first. The strbuf which this patch makes it use is a mere implementation detail (a micro-optimization) which doesn't otherwise change the function's original purpose, thus it belongs in a less prominent position in the argument list. > @@ -658,17 +657,16 @@ static char *infer_backlink(const char *gitfile) > - strbuf_git_common_path(&inferred, the_repository, "worktrees/%s", id); > - if (!is_directory(inferred.buf)) > + strbuf_git_common_path(inferred, the_repository, "worktrees/%s", id); > + if (!is_directory(inferred->buf)) > goto error; > strbuf_release(&actual); > - return strbuf_detach(&inferred, NULL); > + return 0; On success, we now return zero... > error: > strbuf_release(&actual); > - strbuf_release(&inferred); > - return NULL; > + return 1; ... and on failure we return 1. To avoid confusing readers who are familiar with project idioms, it would probably be better to instead follow the convention used in most of the rest of the project (and in Unix system calls in general) of returning -1. However... > @@ -698,21 +697,23 @@ void repair_worktree_at_path(const char *path, > - if (!(backlink = infer_backlink(realdotgit.buf))) { > + if (infer_backlink(&backlink, realdotgit.buf)) { > fn(1, realdotgit.buf, _("unable to locate repository; .git file does not reference a repository"), cb_data); > goto done; > } ... this code now becomes more than a little confusing to read. It says "if infer_backlink then signal error", which sounds rather backward and leaves the reader scratching his or her head. ("Why signal error if the function succeeded?"). Hence, infer_backlink() should probably return 1 on success and 0 on failure, which will make this code read more idiomatically: if (!infer_backlink(realdotgit.buf, &backlink)) { ...signal error... ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-06 18:16 ` Eric Sunshine @ 2024-10-07 2:42 ` Caleb White 2024-10-07 3:26 ` Eric Sunshine 0 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-07 2:42 UTC (permalink / raw) To: Eric Sunshine; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 1760 bytes --] On Sunday, October 6th, 2024 at 13:16, Eric Sunshine <sunshine@sunshineco.com> wrote: > ... it's subjective, but I find that placing the strbuf as the first > argument makes the purpose of the function less clear. The direct > purpose of all (or the majority of) functions in strbuf.h is to > operate on strbufs, thus it makes sense for the strbuf to be the first > argument (just like `this` is the invisible first argument of instance > methods in C++ which operate on an instance of the class). However, > infer_backlink()'s purpose isn't to operate on a strbuf; the fact that > the original signature neither accepted nor returned a strbuf bears > that out. The really important input to this function is `gitfile`, > thus it makes sense for this argument to come first. The strbuf which > this patch makes it use is a mere implementation detail (a > micro-optimization) which doesn't otherwise change the function's > original purpose, thus it belongs in a less prominent position in the > argument list. I can reverse the arguments. > ... this code now becomes more than a little confusing to read. It > says "if infer_backlink then signal error", which sounds rather > backward and leaves the reader scratching his or her head. ("Why > signal error if the function succeeded?"). Hence, infer_backlink() > should probably return 1 on success and 0 on failure, which will make > this code read more idiomatically: > > if (!infer_backlink(realdotgit.buf, &backlink)) { > ...signal error... This was my first thought, however, on unix it is fairly standard to return 0 if successful and a non-zero int if there's an error. I don't mind updating, but I want to follow what makes the most sense and would be most expected. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 2:42 ` Caleb White @ 2024-10-07 3:26 ` Eric Sunshine 2024-10-07 3:28 ` Caleb White 0 siblings, 1 reply; 38+ messages in thread From: Eric Sunshine @ 2024-10-07 3:26 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 10:42 PM Caleb White <cdwhite3@pm.me> wrote: > On Sunday, October 6th, 2024 at 13:16, Eric Sunshine <sunshine@sunshineco.com> wrote: > > ... this code now becomes more than a little confusing to read. It > > says "if infer_backlink then signal error", which sounds rather > > backward and leaves the reader scratching his or her head. ("Why > > signal error if the function succeeded?"). Hence, infer_backlink() > > should probably return 1 on success and 0 on failure, which will make > > this code read more idiomatically: > > > > if (!infer_backlink(realdotgit.buf, &backlink)) { > > ...signal error... > > This was my first thought, however, on unix it is fairly standard > to return 0 if successful and a non-zero int if there's an error. > I don't mind updating, but I want to follow what makes the most > sense and would be most expected. I mentioned it because it made my reading hiccup, but I don't feel too strongly about it one way or the other considering that this is an internal function. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf 2024-10-07 3:26 ` Eric Sunshine @ 2024-10-07 3:28 ` Caleb White 0 siblings, 0 replies; 38+ messages in thread From: Caleb White @ 2024-10-07 3:28 UTC (permalink / raw) To: Eric Sunshine; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 285 bytes --] On Sunday, October 6th, 2024 at 22:26, Eric Sunshine <sunshine@sunshineco.com> wrote: > I mentioned it because it made my reading hiccup, but I don't feel too > strongly about it one way or the other considering that this is an > internal function. I reversed the flags :thumsup: [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-06 6:00 [PATCH v2 0/4] Link worktrees with relative paths Caleb White 2024-10-06 6:00 ` [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf Caleb White @ 2024-10-06 6:01 ` Caleb White 2024-10-06 11:05 ` Eric Sunshine 2024-10-06 15:37 ` shejialuo 2024-10-06 6:01 ` [PATCH v2 3/4] worktree: sync worktree paths after gitdir move Caleb White ` (2 subsequent siblings) 4 siblings, 2 replies; 38+ messages in thread From: Caleb White @ 2024-10-06 6:01 UTC (permalink / raw) To: git; +Cc: Caleb White [-- Attachment #1: Type: text/plain, Size: 13128 bytes --] This modifies Git’s handling of worktree linking to use relative paths instead of absolute paths. Previously, when creating a worktree, Git would store the absolute paths to both the main repository and the linked worktrees. These hardcoded absolute paths cause breakages such as when the repository is moved to a different directory or during containerized development where the absolute differs between systems. By switching to relative paths, we help ensure that worktree links are more resilient when the repository is moved. While links external to the repository may still break, Git still automatically handles many common scenarios, reducing the need for manual repair. This is particularly useful in containerized or portable development environments, where the absolute path to the repository can differ between systems. Developers no longer need to reinitialize or repair worktrees after relocating the repository, improving workflow efficiency and reducing breakages. For self-contained repositories (such as using a bare repository with worktrees), where both the repository and its worktrees are located within the same directory structure, using relative paths guarantees all links remain functional regardless of where the directory is located. Signed-off-by: Caleb White <cdwhite3@pm.me> --- builtin/worktree.c | 17 ++-- t/t2408-worktree-relative.sh | 39 +++++++++ worktree.c | 152 +++++++++++++++++++++++++---------- 3 files changed, 159 insertions(+), 49 deletions(-) create mode 100755 t/t2408-worktree-relative.sh diff --git a/builtin/worktree.c b/builtin/worktree.c index fc31d07..99cee56 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -414,7 +414,8 @@ static int add_worktree(const char *path, const char *refname, const struct add_opts *opts) { struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT; - struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT; + struct strbuf sb = STRBUF_INIT, sb_tmp = STRBUF_INIT; + struct strbuf sb_path_realpath = STRBUF_INIT, sb_repo_realpath = STRBUF_INIT; const char *name; struct strvec child_env = STRVEC_INIT; unsigned int counter = 0; @@ -490,11 +491,11 @@ static int add_worktree(const char *path, const char *refname, strbuf_reset(&sb); strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); - strbuf_realpath(&realpath, sb_git.buf, 1); - write_file(sb.buf, "%s", realpath.buf); - strbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1); - write_file(sb_git.buf, "gitdir: %s/worktrees/%s", - realpath.buf, name); + strbuf_realpath(&sb_path_realpath, path, 1); + strbuf_realpath(&sb_repo_realpath, sb_repo.buf, 1); + write_file(sb.buf, "%s/.git", relative_path(sb_path_realpath.buf, sb_repo_realpath.buf, &sb_tmp)); + strbuf_reset(&sb_tmp); + write_file(sb_git.buf, "gitdir: %s", relative_path(sb_repo_realpath.buf, sb_path_realpath.buf, &sb_tmp)); strbuf_reset(&sb); strbuf_addf(&sb, "%s/commondir", sb_repo.buf); write_file(sb.buf, "../.."); @@ -578,11 +579,13 @@ static int add_worktree(const char *path, const char *refname, strvec_clear(&child_env); strbuf_release(&sb); + strbuf_release(&sb_tmp); strbuf_release(&symref); strbuf_release(&sb_repo); + strbuf_release(&sb_repo_realpath); strbuf_release(&sb_git); + strbuf_release(&sb_path_realpath); strbuf_release(&sb_name); - strbuf_release(&realpath); free_worktree(wt); return ret; } diff --git a/t/t2408-worktree-relative.sh b/t/t2408-worktree-relative.sh new file mode 100755 index 0000000..a3136db --- /dev/null +++ b/t/t2408-worktree-relative.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +test_description='test worktrees linked with relative paths' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_expect_success 'links worktrees with relative paths' ' + test_when_finished rm -rf repo && + git init repo && + ( + cd repo && + test_commit initial && + git worktree add wt1 && + echo "../../../wt1/.git" >expected_gitdir && + cat .git/worktrees/wt1/gitdir >actual_gitdir && + echo "gitdir: ../.git/worktrees/wt1" >expected_git && + cat wt1/.git >actual_git && + test_cmp expected_gitdir actual_gitdir && + test_cmp expected_git actual_git + ) +' + +test_expect_success 'move repo without breaking relative internal links' ' + test_when_finished rm -rf repo moved && + git init repo && + ( + cd repo && + test_commit initial && + git worktree add wt1 && + cd .. && + mv repo moved && + cd moved/wt1 && + git status >out 2>err && + test_must_be_empty err + ) +' + +test_done diff --git a/worktree.c b/worktree.c index c6d2ede..fc14e9a 100644 --- a/worktree.c +++ b/worktree.c @@ -110,6 +110,12 @@ struct worktree *get_linked_worktree(const char *id, strbuf_rtrim(&worktree_path); strbuf_strip_suffix(&worktree_path, "/.git"); + if (!is_absolute_path(worktree_path.buf)) { + strbuf_strip_suffix(&path, "gitdir"); + strbuf_addbuf(&path, &worktree_path); + strbuf_realpath_forgiving(&worktree_path, path.buf, 0); + } + CALLOC_ARRAY(worktree, 1); worktree->repo = the_repository; worktree->path = strbuf_detach(&worktree_path, NULL); @@ -373,18 +379,30 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, void update_worktree_location(struct worktree *wt, const char *path_) { struct strbuf path = STRBUF_INIT; + struct strbuf repo = STRBUF_INIT; + struct strbuf tmp = STRBUF_INIT; + char *file = NULL; if (is_main_worktree(wt)) BUG("can't relocate main worktree"); + strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); strbuf_realpath(&path, path_, 1); if (fspathcmp(wt->path, path.buf)) { - write_file(git_common_path("worktrees/%s/gitdir", wt->id), - "%s/.git", path.buf); + file = xstrfmt("%s/gitdir", repo.buf); + write_file(file, "%s/.git", relative_path(path.buf, repo.buf, &tmp)); + free(file); + strbuf_reset(&tmp); + file = xstrfmt("%s/.git", path.buf); + write_file(file, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp)); + free(wt->path); wt->path = strbuf_detach(&path, NULL); } + free(file); strbuf_release(&path); + strbuf_release(&repo); + strbuf_release(&tmp); } int is_worktree_being_rebased(const struct worktree *wt, @@ -564,38 +582,52 @@ static void repair_gitfile(struct worktree *wt, { struct strbuf dotgit = STRBUF_INIT; struct strbuf repo = STRBUF_INIT; - char *backlink; + struct strbuf backlink = STRBUF_INIT; + struct strbuf tmp = STRBUF_INIT; + char *git_contents = NULL; const char *repair = NULL; int err; /* missing worktree can't be repaired */ if (!file_exists(wt->path)) - return; + goto done; if (!is_directory(wt->path)) { fn(1, wt->path, _("not a directory"), cb_data); - return; + goto done; } strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); strbuf_addf(&dotgit, "%s/.git", wt->path); - backlink = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); + git_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); + + if (git_contents) { + if (is_absolute_path(git_contents)) { + strbuf_addstr(&backlink, git_contents); + } else { + strbuf_addf(&backlink, "%s/%s", wt->path, git_contents); + strbuf_realpath_forgiving(&backlink, backlink.buf, 0); + } + } if (err == READ_GITFILE_ERR_NOT_A_FILE) fn(1, wt->path, _(".git is not a file"), cb_data); else if (err) repair = _(".git file broken"); - else if (fspathcmp(backlink, repo.buf)) + else if (fspathcmp(backlink.buf, repo.buf)) repair = _(".git file incorrect"); if (repair) { fn(0, wt->path, repair, cb_data); - write_file(dotgit.buf, "gitdir: %s", repo.buf); + write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, wt->path, &tmp)); } - free(backlink); +done: + free(git_contents); strbuf_release(&repo); strbuf_release(&dotgit); + strbuf_release(&backlink); + strbuf_release(&tmp); } static void repair_noop(int iserr UNUSED, @@ -681,6 +713,8 @@ void repair_worktree_at_path(const char *path, struct strbuf backlink = STRBUF_INIT; struct strbuf gitdir = STRBUF_INIT; struct strbuf olddotgit = STRBUF_INIT; + struct strbuf realolddotgit = STRBUF_INIT; + struct strbuf tmp = STRBUF_INIT; char *git_contents = NULL; const char *repair = NULL; int err; @@ -710,97 +744,131 @@ void repair_worktree_at_path(const char *path, fn(1, realdotgit.buf, _("unable to locate repository; .git file broken"), cb_data); goto done; } else if (git_contents) { - strbuf_addstr(&backlink, git_contents); + if (is_absolute_path(git_contents)) { + strbuf_addstr(&backlink, git_contents); + } else { + strbuf_addbuf(&backlink, &realdotgit); + strbuf_strip_suffix(&backlink, ".git"); + strbuf_addstr(&backlink, git_contents); + } } + strbuf_realpath_forgiving(&backlink, backlink.buf, 0); strbuf_addf(&gitdir, "%s/gitdir", backlink.buf); if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0) repair = _("gitdir unreadable"); else { strbuf_rtrim(&olddotgit); - if (fspathcmp(olddotgit.buf, realdotgit.buf)) + if (is_absolute_path(olddotgit.buf)) { + strbuf_addbuf(&realolddotgit, &olddotgit); + } else { + strbuf_addf(&realolddotgit, "%s/%s", backlink.buf, olddotgit.buf); + strbuf_realpath_forgiving(&realolddotgit, realolddotgit.buf, 0); + } + if (fspathcmp(realolddotgit.buf, realdotgit.buf)) repair = _("gitdir incorrect"); } if (repair) { fn(0, gitdir.buf, repair, cb_data); - write_file(gitdir.buf, "%s", realdotgit.buf); + write_file(gitdir.buf, "%s", relative_path(realdotgit.buf, backlink.buf, &tmp)); } done: free(git_contents); strbuf_release(&olddotgit); + strbuf_release(&realolddotgit); strbuf_release(&backlink); strbuf_release(&gitdir); strbuf_release(&realdotgit); strbuf_release(&dotgit); + strbuf_release(&tmp); } int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, timestamp_t expire) { struct stat st; - char *path; + struct strbuf dotgit = STRBUF_INIT; + struct strbuf gitdir = STRBUF_INIT; + struct strbuf repo = STRBUF_INIT; + char *path = NULL; + char *file = NULL; + int rc = 0; int fd; size_t len; ssize_t read_result; *wtpath = NULL; - if (!is_directory(git_path("worktrees/%s", id))) { + strbuf_realpath(&repo, git_common_path("worktrees/%s", id), 1); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); + if (!is_directory(repo.buf)) { strbuf_addstr(reason, _("not a valid directory")); - return 1; + rc = 1; + goto done; } - if (file_exists(git_path("worktrees/%s/locked", id))) - return 0; - if (stat(git_path("worktrees/%s/gitdir", id), &st)) { + file = xstrfmt("%s/locked", repo.buf); + if (file_exists(file)) { + goto done; + } + if (stat(gitdir.buf, &st)) { strbuf_addstr(reason, _("gitdir file does not exist")); - return 1; + rc = 1; + goto done; } - fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY); + fd = open(gitdir.buf, O_RDONLY); if (fd < 0) { strbuf_addf(reason, _("unable to read gitdir file (%s)"), strerror(errno)); - return 1; + rc = 1; + goto done; } len = xsize_t(st.st_size); path = xmallocz(len); read_result = read_in_full(fd, path, len); + close(fd); if (read_result < 0) { strbuf_addf(reason, _("unable to read gitdir file (%s)"), strerror(errno)); - close(fd); - free(path); - return 1; - } - close(fd); - - if (read_result != len) { + rc = 1; + goto done; + } else if (read_result != len) { strbuf_addf(reason, _("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"), (uintmax_t)len, (uintmax_t)read_result); - free(path); - return 1; + rc = 1; + goto done; } while (len && (path[len - 1] == '\n' || path[len - 1] == '\r')) len--; if (!len) { strbuf_addstr(reason, _("invalid gitdir file")); - free(path); - return 1; + rc = 1; + goto done; } path[len] = '\0'; - if (!file_exists(path)) { - if (stat(git_path("worktrees/%s/index", id), &st) || - st.st_mtime <= expire) { + if (is_absolute_path(path)) { + strbuf_addstr(&dotgit, path); + } else { + strbuf_addf(&dotgit, "%s/%s", repo.buf, path); + strbuf_realpath_forgiving(&dotgit, dotgit.buf, 0); + } + if (!file_exists(dotgit.buf)) { + free(file); + file = xstrfmt("%s/index", repo.buf); + if (stat(file, &st) || st.st_mtime <= expire) { strbuf_addstr(reason, _("gitdir file points to non-existent location")); - free(path); - return 1; - } else { - *wtpath = path; - return 0; + rc = 1; + goto done; } } - *wtpath = path; - return 0; + *wtpath = strbuf_detach(&dotgit, NULL); +done: + free(path); + free(file); + strbuf_release(&dotgit); + strbuf_release(&gitdir); + strbuf_release(&repo); + return rc; } static int move_config_setting(const char *key, const char *value, -- 2.46.2 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-06 6:01 ` [PATCH v2 2/4] worktree: link worktrees with relative paths Caleb White @ 2024-10-06 11:05 ` Eric Sunshine 2024-10-06 22:37 ` Caleb White 2024-10-06 15:37 ` shejialuo 1 sibling, 1 reply; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 11:05 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 2:01 AM Caleb White <cdwhite3@pm.me> wrote: > This modifies Git’s handling of worktree linking to use relative > paths instead of absolute paths. Previously, when creating a worktree, > Git would store the absolute paths to both the main repository and the > linked worktrees. These hardcoded absolute paths cause breakages such > as when the repository is moved to a different directory or during > containerized development where the absolute differs between systems. > > By switching to relative paths, we help ensure that worktree links are > more resilient when the repository is moved. While links external to the > repository may still break, Git still automatically handles many common > scenarios, reducing the need for manual repair. This is particularly > useful in containerized or portable development environments, where the > absolute path to the repository can differ between systems. Developers > no longer need to reinitialize or repair worktrees after relocating the > repository, improving workflow efficiency and reducing breakages. > > For self-contained repositories (such as using a bare repository with > worktrees), where both the repository and its worktrees are located > within the same directory structure, using relative paths guarantees all > links remain functional regardless of where the directory is located. > > Signed-off-by: Caleb White <cdwhite3@pm.me> When you reroll, please extend the commit message to give a more detailed overview of how this patch actually changes the behavior both at a high level and at a low level. This is especially important since this patch is sufficiently long and involved that it's not easy to glean these details at-a-glance from the code changes themselves. For instance, the cover letter talked about retaining correct behavior for both absolute and relative paths, but this commit message mentions only relative paths, so it's not obvious just from reading the commit message whether absolute paths are still supported or, if they are, what exactly that support looks like or how the user controls the choice between the two path types. This sort of information should be present in the commit message. Similarly, if there is a chance that this change may break existing tooling and workflows, then the commit message should talk about those risks, as well, and what if any remediations are available. Also, if there are such risks, then Documentation/git-worktree.txt may need to be updated to warn users. Regarding what you wrote above, there seems to be a good deal of redundancy between the first two paragraphs; combining the paragraphs and folding out the duplication might make the message more streamlined. I do like the discussion about containerized environments being used as (at least one) justification for employing relative paths, and think that may be a good lead-in for the commit message. Please see [1] for some helpful hints for composing a good commit message. I'm not going to review the code itself right now since I haven't been able to apply the patches or play around with the functionality, but I wanted to get the above written up since I think this series is going to need to be rerolled anyhow. [1]: https://lore.kernel.org/git/xmqqmsm6sc0q.fsf@gitster.g/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-06 11:05 ` Eric Sunshine @ 2024-10-06 22:37 ` Caleb White 0 siblings, 0 replies; 38+ messages in thread From: Caleb White @ 2024-10-06 22:37 UTC (permalink / raw) To: Eric Sunshine; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 1100 bytes --] On Sunday, October 6th, 2024 at 06:05, Eric Sunshine <sunshine@sunshineco.com> wrote: > When you reroll, please extend the commit message to give a more > detailed overview of how this patch actually changes the behavior both > at a high level and at a low level. This is especially important since > this patch is sufficiently long and involved that it's not easy to > glean these details at-a-glance from the code changes themselves. I will do that, I was not sure how much low level detail I should dive into. > Regarding what you wrote above, there seems to be a good deal of > redundancy between the first two paragraphs; combining the paragraphs > and folding out the duplication might make the message more > streamlined. I do like the discussion about containerized environments > being used as (at least one) justification for employing relative > paths, and think that may be a good lead-in for the commit message. > Please see [1] for some helpful hints for composing a good commit > message. Thanks, I will clean up the redundancy and add more detail to the commit. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-06 6:01 ` [PATCH v2 2/4] worktree: link worktrees with relative paths Caleb White 2024-10-06 11:05 ` Eric Sunshine @ 2024-10-06 15:37 ` shejialuo 2024-10-06 23:57 ` Caleb White 1 sibling, 1 reply; 38+ messages in thread From: shejialuo @ 2024-10-06 15:37 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 06, 2024 at 06:01:17AM +0000, Caleb White wrote: > This modifies Git’s handling of worktree linking to use relative > paths instead of absolute paths. Previously, when creating a worktree, > Git would store the absolute paths to both the main repository and the > linked worktrees. These hardcoded absolute paths cause breakages such > as when the repository is moved to a different directory or during > containerized development where the absolute differs between systems. > > By switching to relative paths, we help ensure that worktree links are > more resilient when the repository is moved. While links external to the > repository may still break, Git still automatically handles many common > scenarios, reducing the need for manual repair. This is particularly > useful in containerized or portable development environments, where the > absolute path to the repository can differ between systems. Developers > no longer need to reinitialize or repair worktrees after relocating the > repository, improving workflow efficiency and reducing breakages. > > For self-contained repositories (such as using a bare repository with > worktrees), where both the repository and its worktrees are located > within the same directory structure, using relative paths guarantees all > links remain functional regardless of where the directory is located. > Eric has already commented on this commit message. I think this commit has done a lot of things which make the review painful. > Signed-off-by: Caleb White <cdwhite3@pm.me> > --- > builtin/worktree.c | 17 ++-- > t/t2408-worktree-relative.sh | 39 +++++++++ > worktree.c | 152 +++++++++++++++++++++++++---------- > 3 files changed, 159 insertions(+), 49 deletions(-) > create mode 100755 t/t2408-worktree-relative.sh > > diff --git a/builtin/worktree.c b/builtin/worktree.c > index fc31d07..99cee56 100644 > --- a/builtin/worktree.c > +++ b/builtin/worktree.c > @@ -414,7 +414,8 @@ static int add_worktree(const char *path, const char *refname, > const struct add_opts *opts) > { > struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT; > - struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT; > + struct strbuf sb = STRBUF_INIT, sb_tmp = STRBUF_INIT; > + struct strbuf sb_path_realpath = STRBUF_INIT, sb_repo_realpath = STRBUF_INIT; > const char *name; > struct strvec child_env = STRVEC_INIT; > unsigned int counter = 0; > @@ -490,11 +491,11 @@ static int add_worktree(const char *path, const char *refname, > > strbuf_reset(&sb); > strbuf_addf(&sb, "%s/gitdir", sb_repo.buf); > - strbuf_realpath(&realpath, sb_git.buf, 1); > - write_file(sb.buf, "%s", realpath.buf); > - strbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1); > - write_file(sb_git.buf, "gitdir: %s/worktrees/%s", > - realpath.buf, name); > + strbuf_realpath(&sb_path_realpath, path, 1); > + strbuf_realpath(&sb_repo_realpath, sb_repo.buf, 1); > + write_file(sb.buf, "%s/.git", relative_path(sb_path_realpath.buf, sb_repo_realpath.buf, &sb_tmp)); > + strbuf_reset(&sb_tmp); Do we need reset the "sb_tmp"? I guess we do not need, "relative_path" does not care about "sb_tmp". It will always reset the value of the "sb_tmp". So, we may delete this line. [snip] > diff --git a/worktree.c b/worktree.c > index c6d2ede..fc14e9a 100644 > --- a/worktree.c > +++ b/worktree.c > @@ -373,18 +379,30 @@ int validate_worktree(const struct worktree *wt, struct strbuf *errmsg, > void update_worktree_location(struct worktree *wt, const char *path_) > { > struct strbuf path = STRBUF_INIT; > + struct strbuf repo = STRBUF_INIT; > + struct strbuf tmp = STRBUF_INIT; > + char *file = NULL; > > if (is_main_worktree(wt)) > BUG("can't relocate main worktree"); > > + strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); > strbuf_realpath(&path, path_, 1); > if (fspathcmp(wt->path, path.buf)) { > - write_file(git_common_path("worktrees/%s/gitdir", wt->id), > - "%s/.git", path.buf); > + file = xstrfmt("%s/gitdir", repo.buf); > + write_file(file, "%s/.git", relative_path(path.buf, repo.buf, &tmp)); > + free(file); > + strbuf_reset(&tmp); > + file = xstrfmt("%s/.git", path.buf); Still, we do not need to call "strbuf_reset" again for "tmp". But there is another question here. Should we define the "file" just in this "if" block and free "file" also in the block? And I don't think it's a good idea to use "xstrfmt". Here, we need to allocate two times and free two times. Why not just define a "struct strbuf" and the use "strbuf_*" method here? > + write_file(file, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp)); > + > free(wt->path); > wt->path = strbuf_detach(&path, NULL); > } > + free(file); > strbuf_release(&path); > + strbuf_release(&repo); > + strbuf_release(&tmp); > } > > @@ -564,38 +582,52 @@ static void repair_gitfile(struct worktree *wt, > { > [snip] > strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); > strbuf_addf(&dotgit, "%s/.git", wt->path); > - backlink = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); > + git_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); Why here we need to use "xstrdup_or_null". The life cycle of the "git_contents" variable is in the "repair_gitfile" function. [snip] I omit the review for the later code, there are too many codes to review. And due to my limited knowledge about worktree, the overhead will be too big for me. Thanks, Jialuo ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-06 15:37 ` shejialuo @ 2024-10-06 23:57 ` Caleb White 2024-10-07 3:45 ` shejialuo 0 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-06 23:57 UTC (permalink / raw) To: shejialuo; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 1838 bytes --] On Sunday, October 6th, 2024 at 10:37, shejialuo <shejialuo@gmail.com> wrote > Eric has already commented on this commit message. I think this commit > has done a lot of things which make the review painful. My apologies, I will do better on this commit message. > Do we need reset the "sb_tmp"? I guess we do not need, "relative_path" > does not care about "sb_tmp". It will always reset the value of the > "sb_tmp". So, we may delete this line. You are right, this is reset by relative_path(). I originally encountered a bug and I thought not resetting this strbuf between relative_path() calls was the cause but it must have been something else that I fixed. > Still, we do not need to call "strbuf_reset" again for "tmp". But there > is another question here. Should we define the "file" just in this "if" > block and free "file" also in the block? The style this code uses seems to place most / all of the declarations at the top of the function and frees at the bottom so I think this fits in. > And I don't think it's a good idea to use "xstrfmt". Here, we need to > allocate two times and free two times. Why not just define a "struct > strbuf" and the use "strbuf_*" method here? I can use strbufs, I just wasn't sure if I really needed a strbuf for each of the paths and was just trying to reuse a var. > > strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); > > strbuf_addf(&dotgit, "%s/.git", wt->path); > > - backlink = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); > > + git_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); > > > Why here we need to use "xstrdup_or_null". The life cycle of the > "git_contents" variable is in the "repair_gitfile" function. This what the existing code used and I saw no reason to change it... [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-06 23:57 ` Caleb White @ 2024-10-07 3:45 ` shejialuo 2024-10-07 4:02 ` Eric Sunshine 2024-10-07 16:59 ` Caleb White 0 siblings, 2 replies; 38+ messages in thread From: shejialuo @ 2024-10-07 3:45 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 06, 2024 at 11:57:22PM +0000, Caleb White wrote: [snip] > > Still, we do not need to call "strbuf_reset" again for "tmp". But there > > is another question here. Should we define the "file" just in this "if" > > block and free "file" also in the block? > > The style this code uses seems to place most / all of the declarations at > the top of the function and frees at the bottom so I think this fits in. > Yes, as you have said, the code style places most / all of the declarations at the top and free at the bottom. But the trouble here is we will free the "file" in the "if" block. char *file = NULL; if (...) { file = xstrfmt(...); free(file); file = xstrfmt(...); } free(file); If we want to follow the original code style, should we create two variables at the top and free them at the bottom? > > And I don't think it's a good idea to use "xstrfmt". Here, we need to > > allocate two times and free two times. Why not just define a "struct > > strbuf" and the use "strbuf_*" method here? > > I can use strbufs, I just wasn't sure if I really needed a strbuf for > each of the paths and was just trying to reuse a var. > You don't need to create a new "strbuf" for each of the paths. You could just use "strbuf_reset" for only one "struct strbuf". struct strbuf file = STRBUF_INIT; if (...) { strbuf_addf(...); strbuf_reset(&file); strbuf_addf(...); } strbuf_release(&file); > > > strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); > > > strbuf_addf(&dotgit, "%s/.git", wt->path); > > > - backlink = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); > > > + git_contents = xstrdup_or_null(read_gitfile_gently(dotgit.buf, &err)); > > > > > > > > Why here we need to use "xstrdup_or_null". The life cycle of the > > "git_contents" variable is in the "repair_gitfile" function. > > This what the existing code used and I saw no reason to change it... Actually, I somehow understand why in the original code, it will use "xstrdup_or_null" to initialize the "backlink". Because in "read_gitfile_gently", we will use a static "struct strbuf" as the buffer. I guess the intention of the original code is that if we call again "read_gitfile_gently" in this function or we have another thread which calls this function, the content of the buffer will be changed. So we explicitly use "xstrdup_or_null" to create a copy here to avoid this. But I wonder whether we really need to consider above problem? ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-07 3:45 ` shejialuo @ 2024-10-07 4:02 ` Eric Sunshine 2024-10-07 16:59 ` Caleb White 1 sibling, 0 replies; 38+ messages in thread From: Eric Sunshine @ 2024-10-07 4:02 UTC (permalink / raw) To: shejialuo; +Cc: Caleb White, git On Sun, Oct 6, 2024 at 11:45 PM shejialuo <shejialuo@gmail.com> wrote: > Actually, I somehow understand why in the original code, it will use > "xstrdup_or_null" to initialize the "backlink". Because in > "read_gitfile_gently", we will use a static "struct strbuf" as the > buffer. > > I guess the intention of the original code is that if we call again > "read_gitfile_gently" in this function or we have another thread which > calls this function, the content of the buffer will be changed. So we > explicitly use "xstrdup_or_null" to create a copy here to avoid this. That's correct. The code is being defensive in case the static strbuf inside read_gitfile_gently() gets overwritten. > But I wonder whether we really need to consider above problem? It's easier to reason about the code in this function if we don't have to worry about the underlying static strbuf. Also, this is not a hot path so the extra allocation and string copy is not a concern. As such, it makes sense for the code to remain robust (by creating the copy) rather than becoming potentially more fragile by eliminating the string copy. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 2/4] worktree: link worktrees with relative paths 2024-10-07 3:45 ` shejialuo 2024-10-07 4:02 ` Eric Sunshine @ 2024-10-07 16:59 ` Caleb White 1 sibling, 0 replies; 38+ messages in thread From: Caleb White @ 2024-10-07 16:59 UTC (permalink / raw) To: shejialuo; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 465 bytes --] On Sunday, October 6th, 2024 at 22:45, shejialuo <shejialuo@gmail.com> wrote: > You don't need to create a new "strbuf" for each of the paths. You could > just use "strbuf_reset" for only one "struct strbuf". > > struct strbuf file = STRBUF_INIT; > > if (...) { > strbuf_addf(...); > strbuf_reset(&file); > strbuf_addf(...); > > } > > strbuf_release(&file); Ah, this is a better design---I've updated this to use a single strbuf, thanks! [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 3/4] worktree: sync worktree paths after gitdir move 2024-10-06 6:00 [PATCH v2 0/4] Link worktrees with relative paths Caleb White 2024-10-06 6:00 ` [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf Caleb White 2024-10-06 6:01 ` [PATCH v2 2/4] worktree: link worktrees with relative paths Caleb White @ 2024-10-06 6:01 ` Caleb White 2024-10-06 11:12 ` Eric Sunshine 2024-10-06 6:01 ` [PATCH v2 4/4] worktree: prevent null pointer dereference Caleb White 2024-10-06 6:18 ` [PATCH v2 0/4] Link worktrees with relative paths Eric Sunshine 4 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-06 6:01 UTC (permalink / raw) To: git; +Cc: Caleb White [-- Attachment #1: Type: text/plain, Size: 4200 bytes --] When re-initializing a repository with a separate gitdir (the original gitdir is moved to a new location), any linked worktrees become broken and must be repaired to reflect the new gitdir location. For absolute paths, this breakage is one-way, but is both ways for relative paths (the `<worktree>/.git` and the `<repo>/worktrees/<id>/gitdir`). Previously, `repair_worktrees` was being called which loops through all the worktrees in the repository and updates the `<worktree>/.git` files to point to the new gitdir. However, when both sides of the worktrees are broken, the previous gitdir location is required to reestablish the link. To fix this, the function `repair_worktrees_after_gitdir_move` is introduced. It takes the old gitdir path as an argument and repairs both sides of the worktree. This change fixes the following test cases in t0001-init.sh: - re-init to move gitdir with linked worktrees - re-init to move gitdir within linked worktree Signed-off-by: Caleb White <cdwhite3@pm.me> --- setup.c | 2 +- worktree.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ worktree.h | 10 ++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/setup.c b/setup.c index 94e79b2..7b648de 100644 --- a/setup.c +++ b/setup.c @@ -2420,7 +2420,7 @@ static void separate_git_dir(const char *git_dir, const char *git_link) if (rename(src, git_dir)) die_errno(_("unable to move %s to %s"), src, git_dir); - repair_worktrees(NULL, NULL); + repair_worktrees_after_gitdir_move(src); } write_file(git_link, "gitdir: %s", git_dir); diff --git a/worktree.c b/worktree.c index fc14e9a..b08ecce 100644 --- a/worktree.c +++ b/worktree.c @@ -650,6 +650,60 @@ void repair_worktrees(worktree_repair_fn fn, void *cb_data) free_worktrees(worktrees); } +void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path) +{ + struct strbuf path = STRBUF_INIT; + struct strbuf repo = STRBUF_ INIT; + struct strbuf gitdir = STRBUF_INIT; + struct strbuf dotgit = STRBUF_INIT; + struct strbuf olddotgit = STRBUF_INIT; + struct strbuf tmp = STRBUF_INIT; + + if (is_main_worktree(wt)) + goto done; + + strbuf_realpath(&repo, git_common_path("worktrees/%s", wt->id), 1); + strbuf_addf(&gitdir, "%s/gitdir", repo.buf); + + if (strbuf_read_file(&olddotgit, gitdir.buf, 0) < 0) + goto done; + + strbuf_rtrim(&olddotgit); + if (is_absolute_path(olddotgit.buf)) { + strbuf_addbuf(&dotgit, &olddotgit); + } else { + strbuf_addf(&dotgit, "%s/worktrees/%s/%s", old_path, wt->id, olddotgit.buf); + strbuf_realpath_forgiving(&dotgit, dotgit.buf, 0); + } + + if (!file_exists(dotgit.buf)) + goto done; + + strbuf_addbuf(&path, &dotgit); + strbuf_strip_suffix(&path, "/.git"); + + write_file(dotgit.buf, "gitdir: %s", relative_path(repo.buf, path.buf, &tmp)); + strbuf_reset(&tmp); + write_file(gitdir.buf, "%s", relative_path(dotgit.buf, repo.buf, &tmp)); +done: + strbu f_release(&path); + strbuf_release(&repo); + strbuf_release(&gitdir); + strbuf_release(&dotgit); + strbuf_release(&olddotgit); + strbuf_release(&tmp); +} + +void repair_worktrees_after_gitdir_move(const char *old_path) +{ + struct worktree **worktrees = get_worktrees_internal(1); + struct worktree **wt = worktrees + 1; /* +1 skips main worktree */ + + for (; *wt; wt++) + repair_worktree_after_gitdir_move(*wt, old_path); + free_worktrees(worktrees); +} + static int is_main_worktree_path(const char *path) { struct strbuf target = STRBUF_INIT; diff --git a/worktree.h b/worktree.h index 11279d0..e961186 100644 --- a/worktree.h +++ b/worktree.h @@ -131,6 +131,16 @@ typedef void (* worktree_repair_fn)(int iserr, const char *path, */ void repair_worktrees(worktree_repair_fn, void *cb_data); +/* + * Repair the linked worktrees after the gitdir has been moved. + */ +void repair_worktrees_after_gitdir_move(const char *old_path); + +/* + * Repair the l inked worktree after the gitdir has been moved. + */ +void repair_worktree_after_gitdir_move(struct worktree *wt, const char *old_path); + /* * Repair administrative files corresponding to the worktree at the given path. * The worktree's .git file pointing at the repository must be intact for the -- 2.46.2 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] worktree: sync worktree paths after gitdir move 2024-10-06 6:01 ` [PATCH v2 3/4] worktree: sync worktree paths after gitdir move Caleb White @ 2024-10-06 11:12 ` Eric Sunshine 2024-10-06 22:41 ` Caleb White 0 siblings, 1 reply; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 11:12 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 2:01 AM Caleb White <cdwhite3@pm.me> wrote: > When re-initializing a repository with a separate gitdir (the original > gitdir is moved to a new location), any linked worktrees become broken > and must be repaired to reflect the new gitdir location. For absolute > paths, this breakage is one-way, but is both ways for relative paths > (the `<worktree>/.git` and the `<repo>/worktrees/<id>/gitdir`). > > Previously, `repair_worktrees` was being called which loops through all > the worktrees in the repository and updates the `<worktree>/.git` files > to point to the new gitdir. However, when both sides of the worktrees > are broken, the previous gitdir location is required to reestablish the > link. > > To fix this, the function `repair_worktrees_after_gitdir_move` is > introduced. It takes the old gitdir path as an argument and repairs both > sides of the worktree. > > This change fixes the following test cases in t0001-init.sh: > - re-init to move gitdir with linked worktrees > - re-init to move gitdir within linked worktree If I understand correctly, this patch is fixing breakage resulting from the preceding patch. Unfortunately, this approach is problematic since it breaks bisectability of the project. In particular, it's not sufficient for the full test suite to pass only at the end of the patch series; rather, the entire test suite should continue to pass after application of *each* patch in a series; we don't want one patch to break the test suite and a subsequent patch to fix it again. So, if my understanding is correct, please put some thought into how to reorganize this patch series to ensure that the full test suite passes for each patch. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] worktree: sync worktree paths after gitdir move 2024-10-06 11:12 ` Eric Sunshine @ 2024-10-06 22:41 ` Caleb White 2024-10-06 22:48 ` Eric Sunshine 0 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-06 22:41 UTC (permalink / raw) To: Eric Sunshine; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 1085 bytes --] On Sunday, October 6th, 2024 at 06:12, Eric Sunshine <sunshine@sunshineco.com> wrote: > If I understand correctly, this patch is fixing breakage resulting > from the preceding patch. Unfortunately, this approach is problematic > since it breaks bisectability of the project. In particular, it's not > sufficient for the full test suite to pass only at the end of the > patch series; rather, the entire test suite should continue to pass > after application of each patch in a series; we don't want one patch > to break the test suite and a subsequent patch to fix it again. > > So, if my understanding is correct, please put some thought into how > to reorganize this patch series to ensure that the full test suite > passes for each patch. Yes, there was one edge case that broke and this patch fixed. But I understand what you mean about the bisectability. I was trying to come up with ways to split up the commits and this seemed like a good spot as it just introduced new functions with minimal changes elsewhere. But this can be squashed into the previous patch. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] worktree: sync worktree paths after gitdir move 2024-10-06 22:41 ` Caleb White @ 2024-10-06 22:48 ` Eric Sunshine 2024-10-06 23:13 ` Caleb White 0 siblings, 1 reply; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 22:48 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 6:41 PM Caleb White <cdwhite3@pm.me> wrote: > On Sunday, October 6th, 2024 at 06:12, Eric Sunshine <sunshine@sunshineco.com> wrote: > > So, if my understanding is correct, please put some thought into how > > to reorganize this patch series to ensure that the full test suite > > passes for each patch. > > Yes, there was one edge case that broke and this patch fixed. But I > understand what you mean about the bisectability. I was trying to come > up with ways to split up the commits and this seemed like a good spot as > it just introduced new functions with minimal changes elsewhere. But > this can be squashed into the previous patch. I haven't yet pored over the code in-depth, so I don't know if it is even possible, but it's typically very much preferred by reviewers if you can present a series as smaller, simpler, easier-to-digest patches than large monolithic ones. So, it would be ideal if you could figure out some good split points (especially since patch [2/4] is already uncomfortably large for a reviewer). But sometimes it's just not possible to find good splits, so a large patch may be the only choice. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] worktree: sync worktree paths after gitdir move 2024-10-06 22:48 ` Eric Sunshine @ 2024-10-06 23:13 ` Caleb White 2024-10-06 23:27 ` Eric Sunshine 0 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-06 23:13 UTC (permalink / raw) To: Eric Sunshine; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 1052 bytes --] On Sunday, October 6th, 2024 at 17:48, Eric Sunshine <sunshine@sunshineco.com> wrote: > I haven't yet pored over the code in-depth, so I don't know if it is > even possible, but it's typically very much preferred by reviewers if > you can present a series as smaller, simpler, easier-to-digest patches > than large monolithic ones. So, it would be ideal if you could figure > out some good split points (especially since patch [2/4] is already > uncomfortably large for a reviewer). But sometimes it's just not > possible to find good splits, so a large patch may be the only choice. There's really not any other good split points because it's an all or nothing kind of thing. All of these changes need to be in place at the same time or there's some edge cases that are going to fail. I suppose I could try to split the *reading* of the absolute/relative paths separate from the *writing* of the relative paths. However, I'm not sure if this would be worth the trouble as most places that read from the files also write to the files. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 3/4] worktree: sync worktree paths after gitdir move 2024-10-06 23:13 ` Caleb White @ 2024-10-06 23:27 ` Eric Sunshine 0 siblings, 0 replies; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 23:27 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 7:13 PM Caleb White <cdwhite3@pm.me> wrote: > On Sunday, October 6th, 2024 at 17:48, Eric Sunshine <sunshine@sunshineco.com> wrote: > > I haven't yet pored over the code in-depth, so I don't know if it is > > even possible, but it's typically very much preferred by reviewers if > > you can present a series as smaller, simpler, easier-to-digest patches > > than large monolithic ones. So, it would be ideal if you could figure > > out some good split points (especially since patch [2/4] is already > > uncomfortably large for a reviewer). But sometimes it's just not > > possible to find good splits, so a large patch may be the only choice. > > There's really not any other good split points because it's > an all or nothing kind of thing. All of these changes need to be in place > at the same time or there's some edge cases that are going to fail. > > I suppose I could try to split the *reading* of the absolute/relative paths > separate from the *writing* of the relative paths. However, I'm not > sure if this would be worth the trouble as most places that read from > the files also write to the files. If that's the case, then it probably wouldn't help to split it up in that fashion. Artificial splits like the one you describe are very likely to be more confusing for reviewers than helpful. ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH v2 4/4] worktree: prevent null pointer dereference 2024-10-06 6:00 [PATCH v2 0/4] Link worktrees with relative paths Caleb White ` (2 preceding siblings ...) 2024-10-06 6:01 ` [PATCH v2 3/4] worktree: sync worktree paths after gitdir move Caleb White @ 2024-10-06 6:01 ` Caleb White 2024-10-06 11:24 ` Eric Sunshine 2024-10-06 6:18 ` [PATCH v2 0/4] Link worktrees with relative paths Eric Sunshine 4 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-06 6:01 UTC (permalink / raw) To: git; +Cc: Caleb White [-- Attachment #1: Type: text/plain, Size: 625 bytes --] If worktrees is NULL, free_worktrees() should return immediately to prevent a null pointer dereference. Signed-off-by: Caleb White <cdwhite3@pm.me> --- worktree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/worktree.c b/worktree.c index b08ecce..1cf15b0 100644 --- a/worktree.c +++ b/worktree.c @@ -28,8 +28,9 @@ void free_worktree(struct worktree *worktree) void free_worktrees(struct worktree **worktrees) { - int i = 0; - for (i = 0; worktrees[i]; i++) + if (!worktrees) + return; + for (int i = 0; worktrees[i]; i++) free_worktree(worktrees[i]); free (worktrees); } -- 2.46.2 [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [PATCH v2 4/4] worktree: prevent null pointer dereference 2024-10-06 6:01 ` [PATCH v2 4/4] worktree: prevent null pointer dereference Caleb White @ 2024-10-06 11:24 ` Eric Sunshine 2024-10-06 23:03 ` Caleb White 0 siblings, 1 reply; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 11:24 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 2:01 AM Caleb White <cdwhite3@pm.me> wrote: > If worktrees is NULL, free_worktrees() should return immediately to > prevent a null pointer dereference. > > Signed-off-by: Caleb White <cdwhite3@pm.me> Critical questions: It is not clear why this patch is needed, especially coming at the end of the series. Is there some code in a patch earlier in the series which might call free_worktrees() with NULL? If so, then this patch should come before that patch. If not, then why do we need this patch at all? Devil's advocate question: Why is it the responsibility of free_worktrees() to check this condition as opposed to being the caller's responsibility? The commit message should explain the need for this patch and answer these questions, not just say what change is being made. > diff --git a/worktree.c b/worktree.c > @@ -28,8 +28,9 @@ void free_worktree(struct worktree *worktree) > void free_worktrees(struct worktree **worktrees) > { > - int i = 0; > - for (i = 0; worktrees[i]; i++) > + if (!worktrees) > + return; > + for (int i = 0; worktrees[i]; i++) > free_worktree(worktrees[i]); Although it's true that this project has recently started allowing declaration of the variable in the `for` statement, that change is unrelated to the stated purpose in the commit message. True, it's a minor thing in this case, but it causes a hiccup for reviewers when unrelated changes are piggybacked like this with the "real" change since it adds noise which obscures what the reviewer should really be focusing on. ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 4/4] worktree: prevent null pointer dereference 2024-10-06 11:24 ` Eric Sunshine @ 2024-10-06 23:03 ` Caleb White 2024-10-06 23:24 ` Eric Sunshine 0 siblings, 1 reply; 38+ messages in thread From: Caleb White @ 2024-10-06 23:03 UTC (permalink / raw) To: Eric Sunshine; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 2295 bytes --] On Sunday, October 6th, 2024 at 06:24, Eric Sunshine <sunshine@sunshineco.com> wrote: > Critical questions: It is not clear why this patch is needed, > especially coming at the end of the series. Is there some code in a > patch earlier in the series which might call free_worktrees() with > NULL? If so, then this patch should come before that patch. If not, > then why do we need this patch at all? When I was working through different solution for the 3rd patch, I encountered this issue and this was the fix for that (granted, I could've handled this on the caller side). It turned out that I had to go a different direction and this was no longer needed, but I figured it wouldn't hurt to leave this in which is why it's the last patch. However, I can just drop this if you want. > Devil's advocate question: Why is it the responsibility of > free_worktrees() to check this condition as opposed to being the > caller's responsibility? Sometimes it's cleaner to write a check once on the callee side instead of all callers having to duplicate the same check. This also follows the same pattern as free_worktree(): ``` void free_worktree(struct worktree *worktree) { if (!worktree) return; ``` > The commit message should explain the need for this patch and answer > these questions, not just say what change is being made. Will do (unless we decide to drop this). > Although it's true that this project has recently started allowing > declaration of the variable in the `for` statement, that change is > unrelated to the stated purpose in the commit message. True, it's a > minor thing in this case, but it causes a hiccup for reviewers when > unrelated changes are piggybacked like this with the "real" change > since it adds noise which obscures what the reviewer should really be > focusing on. I didn't change this originally, but then the build process threw errors that I had code before declarations (because I placed the if condition at the start of the function). I could've moved the if condition past the declaration, but it seemed weird to need to declare a variable if the function is just going to immediately return due to a NULL pointer. If we decide to keep this patch then I can keep the separate declaration. [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 4/4] worktree: prevent null pointer dereference 2024-10-06 23:03 ` Caleb White @ 2024-10-06 23:24 ` Eric Sunshine 2024-10-07 3:09 ` Caleb White 0 siblings, 1 reply; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 23:24 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 7:03 PM Caleb White <cdwhite3@pm.me> wrote: > On Sunday, October 6th, 2024 at 06:24, Eric Sunshine <sunshine@sunshineco.com> wrote: > > Critical questions: It is not clear why this patch is needed, > > especially coming at the end of the series. Is there some code in a > > patch earlier in the series which might call free_worktrees() with > > NULL? If so, then this patch should come before that patch. If not, > > then why do we need this patch at all? > > When I was working through different solution for the 3rd patch, I > encountered this issue and this was the fix for that (granted, I > could've handled this on the caller side). It turned out that I had > to go a different direction and this was no longer needed, but I > figured it wouldn't hurt to leave this in which is why it's the > last patch. However, I can just drop this if you want. Reviewers are a limited resource on this project[1], so it's ideal if submissions can be as reviewer-friendly as possible. Extraneous patches, unnecessary or unrelated changes to surrounding code, etc. all make a patch series more onerous to review, thus are best avoided. (This concern prompted all the review comments I left on this patch.) So, let's drop this patch since it adds no value to either this series or to the existing codebase. If someone needs such a change later on, they can resurrect the change. [1] There are far more people submitting patches to the project than reviewing them. For instance, according to Junio's latest "What's Cooking" report[2], the patch I submitted[3] a couple weeks ago to fix "git worktree repair" to handle manual copy operations is still awaiting review. (Since you've now been living in the worktree code a bit and have had to digest the "repair" logic, perhaps you'd be interested in reviewing that patch?) [2]: see the "es/worktree-repair-copied" entry at https://lore.kernel.org/git/xmqq7cancmoj.fsf@gitster.g/ [3]: https://lore.kernel.org/git/20240923075416.54289-1-ericsunshine@charter.net/ > > Although it's true that this project has recently started allowing > > declaration of the variable in the `for` statement, that change is > > unrelated to the stated purpose in the commit message. True, it's a > > minor thing in this case, but it causes a hiccup for reviewers when > > unrelated changes are piggybacked like this with the "real" change > > since it adds noise which obscures what the reviewer should really be > > focusing on. > > I didn't change this originally, but then the build process threw errors > that I had code before declarations (because I placed the if condition at > the start of the function). I could've moved the if condition past the > declaration, but it seemed weird to need to declare a variable if the > function is just going to immediately return due to a NULL pointer. Since this project is still following older style rules about declaring all variables up-front, it's not unusual to declare variables which don't necessarily get used in some code path (even though it might feel weird for someone who habitually declares variables only as and where needed). ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 4/4] worktree: prevent null pointer dereference 2024-10-06 23:24 ` Eric Sunshine @ 2024-10-07 3:09 ` Caleb White 0 siblings, 0 replies; 38+ messages in thread From: Caleb White @ 2024-10-07 3:09 UTC (permalink / raw) To: Eric Sunshine; +Cc: git [-- Attachment #1.1: Type: text/plain, Size: 1145 bytes --] On Sunday, October 6th, 2024 at 18:24, Eric Sunshine <sunshine@sunshineco.com> wrote: > Reviewers are a limited resource on this project[1], so it's ideal if > submissions can be as reviewer-friendly as possible. Extraneous > patches, unnecessary or unrelated changes to surrounding code, etc. > all make a patch series more onerous to review, thus are best avoided. > (This concern prompted all the review comments I left on this patch.) > So, let's drop this patch since it adds no value to either this series > or to the existing codebase. If someone needs such a change later on, > they can resurrect the change. Sounds good, dropped. > [1] There are far more people submitting patches to the project than > reviewing them. For instance, according to Junio's latest "What's > Cooking" report[2], the patch I submitted[3] a couple weeks ago to fix > "git worktree repair" to handle manual copy operations is still > awaiting review. (Since you've now been living in the worktree code a > bit and have had to digest the "repair" logic, perhaps you'd be > interested in reviewing that patch?) I'd be happy to take a look! [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 509 bytes --] ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH v2 0/4] Link worktrees with relative paths 2024-10-06 6:00 [PATCH v2 0/4] Link worktrees with relative paths Caleb White ` (3 preceding siblings ...) 2024-10-06 6:01 ` [PATCH v2 4/4] worktree: prevent null pointer dereference Caleb White @ 2024-10-06 6:18 ` Eric Sunshine 4 siblings, 0 replies; 38+ messages in thread From: Eric Sunshine @ 2024-10-06 6:18 UTC (permalink / raw) To: Caleb White; +Cc: git On Sun, Oct 6, 2024 at 2:00 AM Caleb White <cdwhite3@pm.me> wrote: > This is a resubmission attempt to try to fix the damaged > patch noted in previous discussions. For the record, for those finding this message in the mailing list archive, v1 is at: https://lore.kernel.org/git/20241006045847.159937-1-cdwhite3@pm.me/ ^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2024-10-07 16:59 UTC | newest] Thread overview: 38+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-10-06 6:00 [PATCH v2 0/4] Link worktrees with relative paths Caleb White 2024-10-06 6:00 ` [PATCH v2 1/4] worktree: refactor infer_backlink() to use *strbuf Caleb White 2024-10-06 15:09 ` shejialuo 2024-10-06 15:13 ` Kristoffer Haugsbakk 2024-10-06 18:41 ` Eric Sunshine 2024-10-07 2:26 ` Caleb White 2024-10-07 4:12 ` shejialuo 2024-10-07 4:19 ` Caleb White 2024-10-07 4:28 ` shejialuo 2024-10-07 4:31 ` Caleb White 2024-10-07 3:56 ` shejialuo 2024-10-07 4:01 ` Caleb White 2024-10-07 4:19 ` shejialuo 2024-10-06 23:47 ` Caleb White 2024-10-06 18:16 ` Eric Sunshine 2024-10-07 2:42 ` Caleb White 2024-10-07 3:26 ` Eric Sunshine 2024-10-07 3:28 ` Caleb White 2024-10-06 6:01 ` [PATCH v2 2/4] worktree: link worktrees with relative paths Caleb White 2024-10-06 11:05 ` Eric Sunshine 2024-10-06 22:37 ` Caleb White 2024-10-06 15:37 ` shejialuo 2024-10-06 23:57 ` Caleb White 2024-10-07 3:45 ` shejialuo 2024-10-07 4:02 ` Eric Sunshine 2024-10-07 16:59 ` Caleb White 2024-10-06 6:01 ` [PATCH v2 3/4] worktree: sync worktree paths after gitdir move Caleb White 2024-10-06 11:12 ` Eric Sunshine 2024-10-06 22:41 ` Caleb White 2024-10-06 22:48 ` Eric Sunshine 2024-10-06 23:13 ` Caleb White 2024-10-06 23:27 ` Eric Sunshine 2024-10-06 6:01 ` [PATCH v2 4/4] worktree: prevent null pointer dereference Caleb White 2024-10-06 11:24 ` Eric Sunshine 2024-10-06 23:03 ` Caleb White 2024-10-06 23:24 ` Eric Sunshine 2024-10-07 3:09 ` Caleb White 2024-10-06 6:18 ` [PATCH v2 0/4] Link worktrees with relative paths Eric Sunshine
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 NNTP newsgroup(s).