]> git.ipfire.org Git - thirdparty/git.git/blobdiff - worktree.c
Merge branch 'dl/stash-cleanup'
[thirdparty/git.git] / worktree.c
index 821b23347955a56ea3ee93fb3307afddf79c0279..e00858540ea45965f1570739caa4713a66a36105 100644 (file)
@@ -15,6 +15,7 @@ void free_worktrees(struct worktree **worktrees)
                free(worktrees[i]->id);
                free(worktrees[i]->head_ref);
                free(worktrees[i]->lock_reason);
+               free(worktrees[i]->prune_reason);
                free(worktrees[i]);
        }
        free (worktrees);
@@ -224,7 +225,8 @@ int is_main_worktree(const struct worktree *wt)
 
 const char *worktree_lock_reason(struct worktree *wt)
 {
-       assert(!is_main_worktree(wt));
+       if (is_main_worktree(wt))
+               return NULL;
 
        if (!wt->lock_reason_valid) {
                struct strbuf path = STRBUF_INIT;
@@ -245,6 +247,25 @@ const char *worktree_lock_reason(struct worktree *wt)
        return wt->lock_reason;
 }
 
+const char *worktree_prune_reason(struct worktree *wt, timestamp_t expire)
+{
+       struct strbuf reason = STRBUF_INIT;
+       char *path = NULL;
+
+       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;
+
+       strbuf_release(&reason);
+       free(path);
+       return wt->prune_reason;
+}
+
 /* convenient wrapper to deal with NULL strbuf */
 static void strbuf_addf_gently(struct strbuf *buf, const char *fmt, ...)
 {
@@ -741,3 +762,71 @@ done:
        strbuf_release(&realdotgit);
        strbuf_release(&dotgit);
 }
+
+int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath, timestamp_t expire)
+{
+       struct stat st;
+       char *path;
+       int fd;
+       size_t len;
+       ssize_t read_result;
+
+       *wtpath = NULL;
+       if (!is_directory(git_path("worktrees/%s", id))) {
+               strbuf_addstr(reason, _("not a valid directory"));
+               return 1;
+       }
+       if (file_exists(git_path("worktrees/%s/locked", id)))
+               return 0;
+       if (stat(git_path("worktrees/%s/gitdir", id), &st)) {
+               strbuf_addstr(reason, _("gitdir file does not exist"));
+               return 1;
+       }
+       fd = open(git_path("worktrees/%s/gitdir", id), O_RDONLY);
+       if (fd < 0) {
+               strbuf_addf(reason, _("unable to read gitdir file (%s)"),
+                           strerror(errno));
+               return 1;
+       }
+       len = xsize_t(st.st_size);
+       path = xmallocz(len);
+
+       read_result = read_in_full(fd, path, len);
+       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) {
+               strbuf_addf(reason,
+                           _("short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"),
+                           (uintmax_t)len, (uintmax_t)read_result);
+               free(path);
+               return 1;
+       }
+       while (len && (path[len - 1] == '\n' || path[len - 1] == '\r'))
+               len--;
+       if (!len) {
+               strbuf_addstr(reason, _("invalid gitdir file"));
+               free(path);
+               return 1;
+       }
+       path[len] = '\0';
+       if (!file_exists(path)) {
+               if (stat(git_path("worktrees/%s/index", id), &st) ||
+                   st.st_mtime <= expire) {
+                       strbuf_addstr(reason, _("gitdir file points to non-existent location"));
+                       free(path);
+                       return 1;
+               } else {
+                       *wtpath = path;
+                       return 0;
+               }
+       }
+       *wtpath = path;
+       return 0;
+}