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

Re: [PATCH 2/7] worktree: implement worktree_prune_reason() wrapper

From
Rafael Silva <rafaeloliveira.cs@gmail.com>
Date
Jan 8, 2021, 07:42 UTC
Message-ID
<gohp6kpn2gm1ky.fsf@gmail.com>
In-Reply-To
<CAPig+cRNJeDS+TJL24_QGVE+goD2qBV7aorr+EKr9ORTTmusNg@mail.gmail.com>
Eric Sunshine writes:
Show 10 quoted lines
> On Mon, Jan 4, 2021 at 11:22 AM Rafael Silva
> <rafaeloliveira.cs@gmail.com> wrote:
>> worktree: implement worktree_prune_reason() wrapper
>
> We might be able to give the reader more useful information in the
> subject by explaining a bit more the goal of this patch. Perhaps
> something like this:
>
>     worktree: teach worktree to lazy-load "prunable" reason
>
yeah, that's sounds better. will change it on the next revision.
Show 28 quoted lines
>> The should_prune_worktree() machinery is used by the "prune" command to
>> identify whether a worktree is a candidate for pruning. This function
>> however, is not prepared to work directly with "struct worktree" and
>> refactoring is required not only on the function itself, but also also
>> changing get_worktrees() to return non-valid worktrees and address the
>> changes in all "worktree" sub commands.
>>
>> Instead let's implement worktree_prune_reason() that accepts
>> "struct worktree" and uses should_prune_worktree() and returns whether
>> the given worktree is a candidate for pruning. As the "list" sub command
>> already uses a list of "struct worktree", this allow to simply check if
>> the working tree prunable by passing the structure directly without the
>> others parameters.
>
> Everything through "not prepared to work directly with `struct
> worktree`" makes sense when explaining why you are adding this wrapper
> function, however, most of what follows is describing an aborted idea
> about how you originally intended to implement this. The bit about
> get_worktrees() not being able to return non-valid worktrees is
> certainly an important limitation in the overall scheme of things, but
> doesn't really help to sell the change made by this patch, and it
> probably confuses the reader who didn't also read the cover-letter,
> especially since this patch does nothing to help that situation.
>
> It also isn't really necessary to talk about `git worktree list` at
> this stage since this patch stands on its own by fleshing out the API
> without having to cite a specific client.
>
Make sense.
Show 20 quoted lines
>> Also, let's add prune_reason field to the worktree structure that will
>> store the reason why the worktree can be pruned that is returned by
>> should_prune_worktree() when such reason is available.
>
> In my opinion, this is the real reason this patch exists, thus should
> be the focus of the commit message. All the description above this
> paragraph can likely be dropped.
>
> Taking the above comments into account, perhaps the entire commit
> message could be collapsed to something like this:
>
>     worktree: teach worktree to lazy-load "prunable" reason
>
>     Add worktree_prune_reason() to allow a caller to discover whether
>     a worktree is prunable and the reason that it is, much like
>     worktree_lock_reason() indicates whether a worktree is locked and
>     the reason for the lock. As with worktree_lock_reason(), retrieve
>     the prunable reason lazily and cache it in the `worktree`
>     structure.
>

Interesting point. Rewording the commit message like this seems better, and as you mentioned this patch can stands on its own and can be more clear about what the commit is introducing to the code instead of all the previous message trying to explain why this exists.

Thank you for suggesting this commit message. I will revise and change on the next revision.

Show 46 quoted lines
>> diff --git a/worktree.c b/worktree.c
>> @@ -15,6 +15,7 @@ void free_worktrees(struct worktree **worktrees)
>>                 free(worktrees[i]->lock_reason);
>> +               free(worktrees[i]->prune_reason);
>>                 free(worktrees[i]);
>
> Remembering to free the prune-reason. Good.
>
>> @@ -245,6 +246,24 @@ const char *worktree_lock_reason(struct worktree *wt)
>> +const char *worktree_prune_reason(struct worktree *wt, timestamp_t expire)
>> +{
>> +       if (!is_main_worktree(wt)) {
>> +               char *path;
>> +               struct strbuf reason = STRBUF_INIT;
>> +
>> +               if (should_prune_worktree(wt->id, &reason, &path, expire))
>> +                       wt->prune_reason = strbuf_detach(&reason, NULL);
>> +               else
>> +                       wt->prune_reason = NULL;
>> +
>> +               free(path);
>> +               strbuf_release(&reason);
>> +       }
>> +
>> +       return wt->prune_reason;
>> +}
>
> A couple observations...
>
> I realize you patterned this after worktree_lock_reason(), however, it
> is more common in this codebase to return early from the function for
> conditions such as `is_main_worktree(wt)` which don't require any
> additional processing. One reason is that doing so allows us to lose
> an indentation level. Another is that it is easier to reason about the
> rest of the function if we get the simple cases out of the way early,
> such that we don't have to think about them again while reading the
> remainder of the code.
>
> If I'm not mistaken, the intention here was to cache `prune_reason`
> for reuse, however, this function just overwrites it each time it's
> called for a particular worktree, thus providing no caching and
> leaking the previously-retrieved reason as well. To fix this, I think
> you need to add a private `prune_reason_valid` member to `struct
> worktree` (similar to `lock_reason_valid`) and check it before calling
> should_prune_worktree().
>

Good point. I totally missed the caching aspect of the implementation and I greed about getting the simple case out earlier in order to make it simple to reason about it.

Show 12 quoted lines
> Taking the above comments into account, perhaps it should be written like this:
>
>     if (is_main_worktree(wt))
>         return NULL;
>     if (wt->prune_reason_valid)
>         return wt->prune_reason;
>     if (should_prune_worktree(wt->id, &reason, &path, expire))
>         wt->prune_reason = strbuf_detach(&reason, NULL);
>     wt_prune_reason_valid = 1;
>     free(path);
>     strbuf_release(&reason);
>
Thanks. I will add this suggestion in the next revision. 
Show 10 quoted lines
>> diff --git a/worktree.h b/worktree.h
>> @@ -11,6 +11,7 @@ struct worktree {
>>         char *id;
>>         char *head_ref;         /* NULL if HEAD is broken or detached */
>>         char *lock_reason;      /* private - use worktree_lock_reason */
>> +       char *prune_reason;     /* private - use worktree_prune_reason */
>
> As noted above, we also probably need a new `prune_reason_valid`
> member, similar to the existing `lock_reason_valid`.
>
Indeed. will add on the next revision.
Show 10 quoted lines
>> @@ -73,6 +74,12 @@ int is_main_worktree(const struct worktree *wt);
>> +/*
>> + * Return the reason string if the given worktree should be pruned
>> + * or NULL otherwise.
>> + */
>> +const char *worktree_prune_reason(struct worktree *wt, timestamp_t expire);
>
> The documentation should also talk about `expire` since its purpose
> and meaning is unclear.
>

Good point. I missed adding the message here for the `expire` parameter, will add it.

Show 6 quoted lines
> Nit: I realize that you patterned this description after the one for
> worktree_lock_reason(), but it's a bit unclear. Perhaps rephrasing it
> like this would help:
>
>     Return the reason the worktree should be pruned, otherwise
>     NULL if it should not be pruned.
Also make sense to rephrase like this.
Thank you for this review will address all this changes on the v2.
-- 
Thanks
Rafael
Previous: Eric SunshineNext: Eric Sunshine
Message 32 of 88 in “teach `worktree list` verbose mode and prunable annotations”
  1. 0/7 teach `worktree list` verbose mode and prunable annotationsRafael Silva, Jan 4, 2021
  2. 3/7 worktree: teach worktree_lock_reason() to gently handle main worktreeRafael Silva, Jan 4, 2021
  3. Eric SunshineJan 6, 2021
  4. Rafael SilvaJan 8, 2021
  5. 6/7 worktree: add tests for `list` verbose and annotationsRafael Silva, Jan 4, 2021
  6. Eric SunshineJan 6, 2021
  7. Eric SunshineJan 7, 2021
  8. Rafael SilvaJan 8, 2021
  9. 4/7 worktree: teach `list` prunable annotation and verboseRafael Silva, Jan 4, 2021
  10. Eric SunshineJan 6, 2021
  11. Rafael SilvaJan 8, 2021
  12. 7/7 worktree: document `list` verbose and prunable annotationsRafael Silva, Jan 4, 2021
  13. Eric SunshineJan 6, 2021
  14. Rafael SilvaJan 8, 2021
  15. 5/7 worktree: `list` escape lock reason in --porcelainRafael Silva, Jan 4, 2021
  16. Phillip WoodJan 5, 2021
  17. worktree: add -z option for list subcommandPhillip Wood, Jan 5, 2021
  18. Eric SunshineJan 7, 2021
  19. Phillip WoodJan 8, 2021
  20. Eric SunshineJan 10, 2021
  21. Eric SunshineJan 6, 2021
  22. Rafael SilvaJan 8, 2021
  23. Eric SunshineJan 6, 2021
  24. 1/7 worktree: move should_prune_worktree() to worktree.cRafael Silva, Jan 4, 2021
  25. Eric SunshineJan 6, 2021
  26. Rafael SilvaJan 8, 2021
  27. Eric SunshineJan 6, 2021
  28. Eric SunshineJan 7, 2021
  29. Rafael SilvaJan 8, 2021
  30. 2/7 worktree: implement worktree_prune_reason() wrapperRafael Silva, Jan 4, 2021
  31. Eric SunshineJan 6, 2021
  32. Rafael SilvaJan 8, 2021
  33. Eric SunshineJan 6, 2021
  34. Rafael SilvaJan 8, 2021
  35. Eric SunshineJan 8, 2021
  36. 0/6 teach `worktree list` verbose mode and prunable annotationsRafael Silva, Jan 17, 2021
  37. 1/6 worktree: libify should_prune_worktree()Rafael Silva, Jan 17, 2021
  38. 4/6 worktree: teach `list --porcelain` to annotate locked worktreeRafael Silva, Jan 17, 2021
  39. Eric SunshineJan 18, 2021
  40. Rafael SilvaJan 19, 2021
  41. Eric SunshineJan 19, 2021
  42. 5/6 worktree: teach `list` to annotate prunable worktreeRafael Silva, Jan 17, 2021
  43. Eric SunshineJan 18, 2021
  44. Rafael SilvaJan 19, 2021
  45. Eric SunshineJan 19, 2021
  46. 6/6 worktree: teach `list` verbose modeRafael Silva, Jan 17, 2021
  47. Eric SunshineJan 18, 2021
  48. Eric SunshineJan 18, 2021
  49. 2/6 worktree: teach worktree to lazy-load "prunable" reasonRafael Silva, Jan 17, 2021
  50. Eric SunshineJan 18, 2021
  51. Rafael SilvaJan 19, 2021
  52. 3/6 worktree: teach worktree_lock_reason() to gently handle main worktreeRafael Silva, Jan 17, 2021
  53. Eric SunshineJan 18, 2021
  54. Rafael SilvaJan 19, 2021
  55. 0/7 teach `worktree list` verbose mode and prunable annotationsRafael Silva, Jan 19, 2021
  56. 1/7 worktree: libify should_prune_worktree()Rafael Silva, Jan 19, 2021
  57. 7/7 worktree: teach `list` verbose modeRafael Silva, Jan 19, 2021
  58. Eric SunshineJan 24, 2021
  59. Rafael SilvaJan 24, 2021
  60. 2/7 worktree: teach worktree to lazy-load "prunable" reasonRafael Silva, Jan 19, 2021
  61. 6/7 worktree: teach `list` to annotate prunable worktreeRafael Silva, Jan 19, 2021
  62. Junio C HamanoJan 21, 2021
  63. Rafael SilvaJan 21, 2021
  64. Junio C HamanoJan 21, 2021
  65. 3/7 worktree: teach worktree_lock_reason() to gently handle main worktreeRafael Silva, Jan 19, 2021
  66. 4/7 t2402: ensure locked worktree is properly cleaned upRafael Silva, Jan 19, 2021
  67. Eric SunshineJan 24, 2021
  68. Rafael SilvaJan 24, 2021
  69. 5/7 worktree: teach `list --porcelain` to annotate locked worktreeRafael Silva, Jan 19, 2021
  70. Phillip WoodJan 20, 2021
  71. Junio C HamanoJan 21, 2021
  72. Rafael SilvaJan 21, 2021
  73. Eric SunshineJan 24, 2021
  74. Eric SunshineJan 24, 2021
  75. Rafael SilvaJan 24, 2021
  76. Eric SunshineJan 24, 2021
  77. Rafael SilvaJan 27, 2021
  78. 0/7 teach `worktree list` verbose mode and prunable annotationsRafael Silva, Jan 27, 2021
  79. 2/7 worktree: teach worktree to lazy-load "prunable" reasonRafael Silva, Jan 27, 2021
  80. 6/7 worktree: teach `list` to annotate prunable worktreeRafael Silva, Jan 27, 2021
  81. 5/7 worktree: teach `list --porcelain` to annotate locked worktreeRafael Silva, Jan 27, 2021
  82. 7/7 worktree: teach `list` verbose modeRafael Silva, Jan 27, 2021
  83. 3/7 worktree: teach worktree_lock_reason() to gently handle main worktreeRafael Silva, Jan 27, 2021
  84. 1/7 worktree: libify should_prune_worktree()Rafael Silva, Jan 27, 2021
  85. 4/7 t2402: ensure locked worktree is properly cleaned upRafael Silva, Jan 27, 2021
  86. Eric SunshineJan 30, 2021
  87. Rafael SilvaJan 30, 2021
  88. Junio C HamanoJan 30, 2021

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

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