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. Helped-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Rafael Silva <rafaeloliveira.cs@gmail.com> Reviewed-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Rafael Silva committed Jan 19, 2021 at 22:27 UTC fc0c7d5e9e9e396afdd669019e7635773b1d1423
2 files changed +29
worktree.c
+20
@@ -15,6 +15,7 @@ void free_worktrees(struct worktree **worktrees)
15 free(worktrees[i]->id);
16 free(worktrees[i]->head_ref);
17 free(worktrees[i]->lock_reason);
18 + free(worktrees[i]->prune_reason);
19 free(worktrees[i]);
20 }
21 free (worktrees);
@@ -245,6 +246,25 @@ const char *worktree_lock_reason(struct worktree *wt)
246 return wt->lock_reason;
247 }
248
249 +const char *worktree_prune_reason(struct worktree *wt, timestamp_t expire)
250 +{
251 + struct strbuf reason = STRBUF_INIT;
252 + char *path = NULL;
253 +
254 + if (is_main_worktree(wt))
255 + return NULL;
256 + if (wt->prune_reason_valid)
257 + return wt->prune_reason;
258 +
259 + if (should_prune_worktree(wt->id, &reason, &path, expire))
260 + wt->prune_reason = strbuf_detach(&reason, NULL);
261 + wt->prune_reason_valid = 1;
262 +
263 + strbuf_release(&reason);
264 + free(path);
265 + return wt->prune_reason;
266 +}
267 +
268 /* convenient wrapper to deal with NULL strbuf */
269 static void strbuf_addf_gently(struct strbuf *buf, const char *fmt, ...)
270 {
worktree.h
+9
@@ -11,11 +11,13 @@ struct worktree {
11 char *id;
12 char *head_ref; /* NULL if HEAD is broken or detached */
13 char *lock_reason; /* private - use worktree_lock_reason */
14 + char *prune_reason; /* private - use worktree_prune_reason */
15 struct object_id head_oid;
16 int is_detached;
17 int is_bare;
18 int is_current;
19 int lock_reason_valid; /* private */
20 + int prune_reason_valid; /* private */
21 };
22
23 /*
@@ -73,6 +75,13 @@ int is_main_worktree(const struct worktree *wt);
75 */
76 const char *worktree_lock_reason(struct worktree *wt);
77
78 +/*
79 + * Return the reason string if the given worktree should be pruned, otherwise
80 + * NULL if it should not be pruned. `expire` defines a grace period to prune
81 + * the worktree when its path does not exist.
82 + */
83 +const char *worktree_prune_reason(struct worktree *wt, timestamp_t expire);
84 +
85 /*
86 * Return true if worktree entry should be pruned, along with the reason for
87 * pruning. Otherwise, return false and the worktree's path in `wtpath`, or