All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Sunshine <sunshine@sunshineco.com>
To: Rafael Silva <rafaeloliveira.cs@gmail.com>
Cc: Git List <git@vger.kernel.org>
Subject: Re: [PATCH 2/7] worktree: implement worktree_prune_reason() wrapper
Date: Wed, 6 Jan 2021 02:08:22 -0500	[thread overview]
Message-ID: <CAPig+cRNJeDS+TJL24_QGVE+goD2qBV7aorr+EKr9ORTTmusNg@mail.gmail.com> (raw)
In-Reply-To: <20210104162128.95281-3-rafaeloliveira.cs@gmail.com>

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

> 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.

> 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.

> 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().

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);

> 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`.

> @@ -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.

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.

  reply	other threads:[~2021-01-06  7:09 UTC|newest]

Thread overview: 88+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-04 16:21 [PATCH 0/7] teach `worktree list` verbose mode and prunable annotations Rafael Silva
2021-01-04 16:21 ` [PATCH 1/7] worktree: move should_prune_worktree() to worktree.c Rafael Silva
2021-01-06  5:58   ` Eric Sunshine
2021-01-08  7:40     ` Rafael Silva
2021-01-06  6:55   ` Eric Sunshine
2021-01-07  7:24     ` Eric Sunshine
2021-01-08  7:41     ` Rafael Silva
2021-01-04 16:21 ` [PATCH 2/7] worktree: implement worktree_prune_reason() wrapper Rafael Silva
2021-01-06  7:08   ` Eric Sunshine [this message]
2021-01-08  7:42     ` Rafael Silva
2021-01-04 16:21 ` [PATCH 3/7] worktree: teach worktree_lock_reason() to gently handle main worktree Rafael Silva
2021-01-06  7:29   ` Eric Sunshine
2021-01-08  7:43     ` Rafael Silva
2021-01-04 16:21 ` [PATCH 4/7] worktree: teach `list` prunable annotation and verbose Rafael Silva
2021-01-06  8:31   ` Eric Sunshine
2021-01-08  7:45     ` Rafael Silva
2021-01-04 16:21 ` [PATCH 5/7] worktree: `list` escape lock reason in --porcelain Rafael Silva
2021-01-05 10:29   ` Phillip Wood
2021-01-05 11:02     ` [PATCH] worktree: add -z option for list subcommand Phillip Wood
2021-01-07  3:34       ` Eric Sunshine
2021-01-08 10:33         ` Phillip Wood
2021-01-10  7:27           ` Eric Sunshine
2021-01-06  9:07     ` [PATCH 5/7] worktree: `list` escape lock reason in --porcelain Eric Sunshine
2021-01-08  7:47     ` Rafael Silva
2021-01-06  8:59   ` Eric Sunshine
2021-01-04 16:21 ` [PATCH 6/7] worktree: add tests for `list` verbose and annotations Rafael Silva
2021-01-06  9:39   ` Eric Sunshine
2021-01-07  4:09     ` Eric Sunshine
2021-01-08  7:49     ` Rafael Silva
2021-01-04 16:21 ` [PATCH 7/7] worktree: document `list` verbose and prunable annotations Rafael Silva
2021-01-06  9:57   ` Eric Sunshine
2021-01-08  7:49     ` Rafael Silva
2021-01-06  5:36 ` [PATCH 0/7] teach `worktree list` verbose mode " Eric Sunshine
2021-01-08  7:38   ` Rafael Silva
2021-01-08  8:19     ` Eric Sunshine
2021-01-17 23:42 ` [PATCH v2 0/6] " Rafael Silva
2021-01-17 23:42   ` [PATCH v2 1/6] worktree: libify should_prune_worktree() Rafael Silva
2021-01-17 23:42   ` [PATCH v2 2/6] worktree: teach worktree to lazy-load "prunable" reason Rafael Silva
2021-01-18  2:57     ` Eric Sunshine
2021-01-19  7:57       ` Rafael Silva
2021-01-17 23:42   ` [PATCH v2 3/6] worktree: teach worktree_lock_reason() to gently handle main worktree Rafael Silva
2021-01-17 23:42   ` [PATCH v2 4/6] worktree: teach `list --porcelain` to annotate locked worktree Rafael Silva
2021-01-18  3:55     ` Eric Sunshine
2021-01-19  8:20       ` Rafael Silva
2021-01-19 17:16         ` Eric Sunshine
2021-01-17 23:42   ` [PATCH v2 5/6] worktree: teach `list` to annotate prunable worktree Rafael Silva
2021-01-18  4:45     ` Eric Sunshine
2021-01-19 10:26       ` Rafael Silva
2021-01-19 17:23         ` Eric Sunshine
2021-01-17 23:42   ` [PATCH v2 6/6] worktree: teach `list` verbose mode Rafael Silva
2021-01-18  5:15     ` Eric Sunshine
2021-01-18 19:40       ` Eric Sunshine
2021-01-18  5:33   ` [PATCH v2 0/6] teach `worktree list` verbose mode and prunable annotations Eric Sunshine
2021-01-19 16:44     ` Rafael Silva
2021-01-19 21:27   ` [PATCH v3 0/7] " Rafael Silva
2021-01-19 21:27     ` [PATCH v3 1/7] worktree: libify should_prune_worktree() Rafael Silva
2021-01-19 21:27     ` [PATCH v3 2/7] worktree: teach worktree to lazy-load "prunable" reason Rafael Silva
2021-01-19 21:27     ` [PATCH v3 3/7] worktree: teach worktree_lock_reason() to gently handle main worktree Rafael Silva
2021-01-19 21:27     ` [PATCH v3 4/7] t2402: ensure locked worktree is properly cleaned up Rafael Silva
2021-01-24  7:50       ` Eric Sunshine
2021-01-24 10:19         ` Rafael Silva
2021-01-19 21:27     ` [PATCH v3 5/7] worktree: teach `list --porcelain` to annotate locked worktree Rafael Silva
2021-01-20 11:00       ` Phillip Wood
2021-01-21  3:18         ` Junio C Hamano
2021-01-21 15:25         ` Rafael Silva
2021-01-24  8:24         ` Eric Sunshine
2021-01-24  8:10       ` Eric Sunshine
2021-01-24 10:20         ` Rafael Silva
2021-01-19 21:27     ` [PATCH v3 6/7] worktree: teach `list` to annotate prunable worktree Rafael Silva
2021-01-21  3:28       ` Junio C Hamano
2021-01-21 15:09         ` Rafael Silva
2021-01-21 22:18           ` Junio C Hamano
2021-01-19 21:27     ` [PATCH v3 7/7] worktree: teach `list` verbose mode Rafael Silva
2021-01-24  8:42       ` Eric Sunshine
2021-01-24 10:21         ` Rafael Silva
2021-01-24  8:51     ` [PATCH v3 0/7] teach `worktree list` verbose mode and prunable annotations Eric Sunshine
2021-01-27  8:08       ` Rafael Silva
2021-01-27  8:03     ` Rafael Silva
2021-01-27  8:03       ` [PATCH v4 1/7] worktree: libify should_prune_worktree() Rafael Silva
2021-01-27  8:03       ` [PATCH v4 2/7] worktree: teach worktree to lazy-load "prunable" reason Rafael Silva
2021-01-27  8:03       ` [PATCH v4 3/7] worktree: teach worktree_lock_reason() to gently handle main worktree Rafael Silva
2021-01-27  8:03       ` [PATCH v4 4/7] t2402: ensure locked worktree is properly cleaned up Rafael Silva
2021-01-27  8:03       ` [PATCH v4 5/7] worktree: teach `list --porcelain` to annotate locked worktree Rafael Silva
2021-01-27  8:03       ` [PATCH v4 6/7] worktree: teach `list` to annotate prunable worktree Rafael Silva
2021-01-27  8:03       ` [PATCH v4 7/7] worktree: teach `list` verbose mode Rafael Silva
2021-01-30  7:04       ` [PATCH v3 0/7] teach `worktree list` verbose mode and prunable annotations Eric Sunshine
2021-01-30  9:42         ` Rafael Silva
2021-01-30 17:50         ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAPig+cRNJeDS+TJL24_QGVE+goD2qBV7aorr+EKr9ORTTmusNg@mail.gmail.com \
    --to=sunshine@sunshineco.com \
    --cc=git@vger.kernel.org \
    --cc=rafaeloliveira.cs@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.