Skip to content

Commit a29a8b7

Browse files
raffsgitster
authored andcommitted
worktree: libify should_prune_worktree()
As part of teaching "git worktree list" to annotate worktree that is a candidate for pruning, let's move should_prune_worktree() from builtin/worktree.c to worktree.c in order to make part of the worktree public API. should_prune_worktree() knows how to select the given worktree for pruning based on an expiration date, however the expiration value is stored in a static file-scope variable and it is not local to the function. In order to move the function, teach should_prune_worktree() to take the expiration date as an argument and document the new parameter that is not immediately obvious. Also, change the function comment to clearly state that the worktree's path is returned in `wtpath` argument. Helped-by: Eric Sunshine <[email protected]> Signed-off-by: Rafael Silva <[email protected]> Reviewed-by: Eric Sunshine <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 66e871b commit a29a8b7

File tree

3 files changed

+83
-74
lines changed

3 files changed

+83
-74
lines changed

builtin/worktree.c

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -67,79 +67,6 @@ static void delete_worktrees_dir_if_empty(void)
6767
rmdir(git_path("worktrees")); /* ignore failed removal */
6868
}
6969

70-
/*
71-
* Return true if worktree entry should be pruned, along with the reason for
72-
* pruning. Otherwise, return false and the worktree's path, or NULL if it
73-
* cannot be determined. Caller is responsible for freeing returned path.
74-
*/
75-
static int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath)
76-
{
77-
struct stat st;
78-
char *path;
79-
int fd;
80-
size_t len;
81-
ssize_t read_result;
82-
83-
*wtpath = NULL;
84-
if (!is_directory(git_path("worktrees/%s", id))) {
85-
strbuf_addstr(reason, _("not a valid directory"));
86-
return 1;
87-
}
88-
if (file_exists(git_path("worktrees/%s/locked", id)))
89-
return 0;
90-
if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
91-
strbuf_addstr(reason, _("gitdir file does not exist"));
92-
return 1;
93-
}
94-
fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
95-
if (fd < 0) {
96-
strbuf_addf(reason, _("unable to read gitdir file (%s)"),
97-
strerror(errno));
98-
return 1;
99-
}
100-
len = xsize_t(st.st_size);
101-
path = xmallocz(len);
102-
103-
read_result = read_in_full(fd, path, len);
104-
if (read_result < 0) {
105-
strbuf_addf(reason, _("unable to read gitdir file (%s)"),
106-
strerror(errno));
107-
close(fd);
108-
free(path);
109-
return 1;
110-
}
111-
close(fd);
112-
113-
if (read_result != len) {
114-
strbuf_addf(reason,
115-
_("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"),
116-
(uintmax_t)len, (uintmax_t)read_result);
117-
free(path);
118-
return 1;
119-
}
120-
while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
121-
len--;
122-
if (!len) {
123-
strbuf_addstr(reason, _("invalid gitdir file"));
124-
free(path);
125-
return 1;
126-
}
127-
path[len] = '\0';
128-
if (!file_exists(path)) {
129-
if (stat(git_path("worktrees/%s/index", id), &st) ||
130-
st.st_mtime <= expire) {
131-
strbuf_addstr(reason, _("gitdir file points to non-existent location"));
132-
free(path);
133-
return 1;
134-
} else {
135-
*wtpath = path;
136-
return 0;
137-
}
138-
}
139-
*wtpath = path;
140-
return 0;
141-
}
142-
14370
static void prune_worktree(const char *id, const char *reason)
14471
{
14572
if (show_only || verbose)
@@ -195,7 +122,7 @@ static void prune_worktrees(void)
195122
if (is_dot_or_dotdot(d->d_name))
196123
continue;
197124
strbuf_reset(&reason);
198-
if (should_prune_worktree(d->d_name, &reason, &path))
125+
if (should_prune_worktree(d->d_name, &reason, &path, expire))
199126
prune_worktree(d->d_name, reason.buf);
200127
else if (path)
201128
string_list_append(&kept, path)->util = xstrdup(d->d_name);

worktree.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,3 +741,71 @@ void repair_worktree_at_path(const char *path,
741741
strbuf_release(&realdotgit);
742742
strbuf_release(&dotgit);
743743
}
744+
745+
int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, timestamp_t expire)
746+
{
747+
struct stat st;
748+
char *path;
749+
int fd;
750+
size_t len;
751+
ssize_t read_result;
752+
753+
*wtpath = NULL;
754+
if (!is_directory(git_path("worktrees/%s", id))) {
755+
strbuf_addstr(reason, _("not a valid directory"));
756+
return 1;
757+
}
758+
if (file_exists(git_path("worktrees/%s/locked", id)))
759+
return 0;
760+
if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
761+
strbuf_addstr(reason, _("gitdir file does not exist"));
762+
return 1;
763+
}
764+
fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
765+
if (fd < 0) {
766+
strbuf_addf(reason, _("unable to read gitdir file (%s)"),
767+
strerror(errno));
768+
return 1;
769+
}
770+
len = xsize_t(st.st_size);
771+
path = xmallocz(len);
772+
773+
read_result = read_in_full(fd, path, len);
774+
if (read_result < 0) {
775+
strbuf_addf(reason, _("unable to read gitdir file (%s)"),
776+
strerror(errno));
777+
close(fd);
778+
free(path);
779+
return 1;
780+
}
781+
close(fd);
782+
783+
if (read_result != len) {
784+
strbuf_addf(reason,
785+
_("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"),
786+
(uintmax_t)len, (uintmax_t)read_result);
787+
free(path);
788+
return 1;
789+
}
790+
while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
791+
len--;
792+
if (!len) {
793+
strbuf_addstr(reason, _("invalid gitdir file"));
794+
free(path);
795+
return 1;
796+
}
797+
path[len] = '\0';
798+
if (!file_exists(path)) {
799+
if (stat(git_path("worktrees/%s/index", id), &st) ||
800+
st.st_mtime <= expire) {
801+
strbuf_addstr(reason, _("gitdir file points to non-existent location"));
802+
free(path);
803+
return 1;
804+
} else {
805+
*wtpath = path;
806+
return 0;
807+
}
808+
}
809+
*wtpath = path;
810+
return 0;
811+
}

worktree.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,20 @@ int is_main_worktree(const struct worktree *wt);
7373
*/
7474
const char *worktree_lock_reason(struct worktree *wt);
7575

76+
/*
77+
* Return true if worktree entry should be pruned, along with the reason for
78+
* pruning. Otherwise, return false and the worktree's path in `wtpath`, or
79+
* NULL if it cannot be determined. Caller is responsible for freeing
80+
* returned path.
81+
*
82+
* `expire` defines a grace period to prune the worktree when its path
83+
* does not exist.
84+
*/
85+
int should_prune_worktree(const char *id,
86+
struct strbuf *reason,
87+
char **wtpath,
88+
timestamp_t expire);
89+
7690
#define WT_VALIDATE_WORKTREE_MISSING_OK (1 << 0)
7791

7892
/*

0 commit comments

Comments
 (0)