From patchwork Mon Jan 4 16:21:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Silva X-Patchwork-Id: 11997047 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4F0F0C433E0 for ; Mon, 4 Jan 2021 16:24:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0DD3E22473 for ; Mon, 4 Jan 2021 16:24:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728921AbhADQYG (ORCPT ); Mon, 4 Jan 2021 11:24:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49294 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728173AbhADQXG (ORCPT ); Mon, 4 Jan 2021 11:23:06 -0500 Received: from mail-ej1-x636.google.com (mail-ej1-x636.google.com [IPv6:2a00:1450:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 59679C061798 for ; Mon, 4 Jan 2021 08:22:17 -0800 (PST) Received: by mail-ej1-x636.google.com with SMTP id jx16so37499837ejb.10 for ; Mon, 04 Jan 2021 08:22:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=iAZUxbYxxP993P+SZX2kUgkP5uykVNagpbF61jA3dLw=; b=tgYJpdtqelD0AZp4h+d5+xeouciwq82Z2wM2QFdAHNR/VvojzFgd/24Rs4A+NhNzLL IzM6k2XtGKoqlX78tmx+thgfU8k1pKV5nJL5lJT6bgGJXMGrufo+/w//At+62hVtiUTo H214hwmEdl7IjtlC1mM7GgRfSupDpuRGPutwHNhyZ1YA8jjphDX9VfZz0DThee98DWLm 0zKA9HwNVg9RN9NMFo105VAcy8jhOoEhlN8qdTVpZFagAu6tRyDFys1DtLIFE+Ixb7Xr D13fjlgFKfTUpyCUU+ipqrSdFSiZ+99r0haJ7rSe/gbg/1UcOUYpdMBttB2VQTQW5fIr MYCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=iAZUxbYxxP993P+SZX2kUgkP5uykVNagpbF61jA3dLw=; b=uOp2X666AQOAJiPOees+oo1rZ6nYUYljL3UEPXAQQNx2LBHX1H3cBxG0Ayehk7A/9g T5QZulXKChQtsQG60kjupv1ExcAfpJL0JLe/TSKxNLkGyi1Km6QhasAr3j1Z2QijmWtR kybEcEcg6MBLQJg4lSAwCag449KMxfJ9nDrAaw/7I41T+vkP2tt1EL4Dkehbtr5AaiJC cmZUrtW22wr2/OWsjTJXOmel84I2OLqQOc42tPHoDIaHA91B4/Klw4YUDyl8Xi2bydJe aLUQqqsuQjHoFPSmpgiubN7WsLtVkVC0HZFBIxrSB2mfwJTztJ/vlhHDAdlUndQfI51J XdZg== X-Gm-Message-State: AOAM5337s0QyYyeqriLzYc131LTRUfqfzHkpCweySJvOVG9opJ9KlR5t KP56MD9OIceclEGYrX5NrfFS8yoGt+s= X-Google-Smtp-Source: ABdhPJzhidi+BQX3Rx9yp5qecRVohy2UIqBit4hZjsS4QsXG8zB8koQbF3QCOE/vLZaGV+RX3FKOLg== X-Received: by 2002:a17:906:3ac3:: with SMTP id z3mr36709411ejd.449.1609777335731; Mon, 04 Jan 2021 08:22:15 -0800 (PST) Received: from localhost.localdomain ([79.140.115.191]) by smtp.gmail.com with ESMTPSA id bn21sm23931677ejb.47.2021.01.04.08.22.14 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Jan 2021 08:22:15 -0800 (PST) From: Rafael Silva To: git@vger.kernel.org Cc: Eric Sunshine , Rafael Silva Subject: [PATCH 1/7] worktree: move should_prune_worktree() to worktree.c Date: Mon, 4 Jan 2021 17:21:22 +0100 Message-Id: <20210104162128.95281-2-rafaeloliveira.cs@gmail.com> X-Mailer: git-send-email 2.30.0.391.g469bf2a980 In-Reply-To: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> References: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org 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. This function will be used by another API function, implemented in the next patch that will accept a pointer to "worktree" structure directly making it easier to implement the "prunable" annotations. should_prune_worktree() knows how to select the given worktree for pruning based on an expiration date, however the expiration value is stored on a global 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. Signed-off-by: Rafael Silva --- builtin/worktree.c | 75 +--------------------------------------------- worktree.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ worktree.h | 10 +++++++ 3 files changed, 84 insertions(+), 74 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index 197fd24a55..eeb3ffaed0 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -67,79 +67,6 @@ static void delete_worktrees_dir_if_empty(void) rmdir(git_path("worktrees")); /* ignore failed removal */ } -/* - * Return true if worktree entry should be pruned, along with the reason for - * pruning. Otherwise, return false and the worktree's path, or NULL if it - * cannot be determined. Caller is responsible for freeing returned path. - */ -static int should_prune_worktree(const char *id, struct strbuf *reason, char **wtpath) -{ - 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; -} - static void prune_worktree(const char *id, const char *reason) { if (show_only || verbose) @@ -195,7 +122,7 @@ static void prune_worktrees(void) if (is_dot_or_dotdot(d->d_name)) continue; strbuf_reset(&reason); - if (should_prune_worktree(d->d_name, &reason, &path)) + if (should_prune_worktree(d->d_name, &reason, &path, expire)) prune_worktree(d->d_name, reason.buf); else if (path) string_list_append(&kept, path)->util = xstrdup(d->d_name); diff --git a/worktree.c b/worktree.c index f84ceae87d..5764b0dc7c 100644 --- a/worktree.c +++ b/worktree.c @@ -700,3 +700,76 @@ void repair_worktree_at_path(const char *path, strbuf_release(&realdotgit); strbuf_release(&dotgit); } + +/* + * Return true if worktree entry should be pruned, along with the reason for + * pruning. Otherwise, return false and the worktree's path, or NULL if it + * cannot be determined. Caller is responsible for freeing returned path. + */ +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; +} diff --git a/worktree.h b/worktree.h index f38e6fd5a2..e5f4320725 100644 --- a/worktree.h +++ b/worktree.h @@ -73,6 +73,16 @@ int is_main_worktree(const struct worktree *wt); */ const char *worktree_lock_reason(struct worktree *wt); +/* + * Return true if worktree entry should be pruned, along with the reason for + * pruning. Otherwise, return false and the worktree's path, or NULL if it + * cannot be determined. Caller is responsible for freeing returned path. + */ +int should_prune_worktree(const char *id, + struct strbuf *reason, + char **wtpath, + timestamp_t expire); + #define WT_VALIDATE_WORKTREE_MISSING_OK (1 << 0) /* From patchwork Mon Jan 4 16:21:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Silva X-Patchwork-Id: 11997049 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4297BC433E9 for ; Mon, 4 Jan 2021 16:24:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 06B1922473 for ; Mon, 4 Jan 2021 16:24:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727950AbhADQYG (ORCPT ); Mon, 4 Jan 2021 11:24:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49296 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728180AbhADQXG (ORCPT ); Mon, 4 Jan 2021 11:23:06 -0500 Received: from mail-ej1-x62f.google.com (mail-ej1-x62f.google.com [IPv6:2a00:1450:4864:20::62f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CC04C06179A for ; Mon, 4 Jan 2021 08:22:18 -0800 (PST) Received: by mail-ej1-x62f.google.com with SMTP id q22so37595091eja.2 for ; Mon, 04 Jan 2021 08:22:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=oW39KQP7yO2RUmoP4PcY4iPmMSQ4QaQyHWG+YOGjU+w=; b=WGowcHOlqibkLLnHxyN6Gk7NMpEgPHlYS/ImOU/k//htETctpPx9yaskcyV3ksYKwE 0dSdQFcCoPGAXfTWW6Bx30eVmBSwcVPS5164VFjpePXLApcIixHM84znxgyBN5ZeCHtD fJ/jcixYsnZaQXXjEumNo566nvnDxttBX3fnOl060B9++lzjAFDsLUxxFGq4yNMaqIBn 5yz8NlItcgtLCTc3sxAfM/y1b2kutYWFi28gf2WEaqCciURtIrwBggqkEeM7b5xTDsGT G8/XN2d8rlGzm+wPuCU3P72hLH8jHggRcgQFf3XpP3nk1E6CO1wgA4jyAq4YpLwRDAmm zOXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=oW39KQP7yO2RUmoP4PcY4iPmMSQ4QaQyHWG+YOGjU+w=; b=IMWw3hz4EaV/zIkcgsbDug8ioAyY5AZMAl+QjuMkIBTe9SAPUSUNG5yayf8i4Vzjag rT7Wcnk1oUqpvSb4APQBYED4H5o9h+4IhkzQRvvuLEaHAsBHf3emYN5HXknc1SauHZ/T KcOvMMmu87s+jUHRkY46PrsNx1RTrX85IGgTf5nmonfp+PDSTlPM4Sx1Us1xK+h5jpUp 5+zi1fsXEWsRRrx3me5R2yE/q5h+Hwat6N07HKK/nSw6HiHx/pKTXszyGQ0gn6tYifvZ 9DX6vM/v8TFuSXlf1k8PVZAz3tJqWo0A2kh+up2LJSAFafQcyMcioByFc7eFVPJd6i8L ycCA== X-Gm-Message-State: AOAM531bH/OajGiSgAOn9Orz/YB36x5W7WnoFDpKvLUtbJqA1X1JZILi pIsc7t3cMyyTHRXMmx4nttlai9Qoaj4= X-Google-Smtp-Source: ABdhPJw18Ccs+muhMNMCp9Q8L1EwfUqRU/CIZFZcDD3Gyws/J9dEQd7TOSJu+X6x9Mkhj2+1cG6d0Q== X-Received: by 2002:a17:906:a8e:: with SMTP id y14mr66054874ejf.47.1609777336824; Mon, 04 Jan 2021 08:22:16 -0800 (PST) Received: from localhost.localdomain ([79.140.115.191]) by smtp.gmail.com with ESMTPSA id bn21sm23931677ejb.47.2021.01.04.08.22.15 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Jan 2021 08:22:16 -0800 (PST) From: Rafael Silva To: git@vger.kernel.org Cc: Eric Sunshine , Rafael Silva Subject: [PATCH 2/7] worktree: implement worktree_prune_reason() wrapper Date: Mon, 4 Jan 2021 17:21:23 +0100 Message-Id: <20210104162128.95281-3-rafaeloliveira.cs@gmail.com> X-Mailer: git-send-email 2.30.0.391.g469bf2a980 In-Reply-To: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> References: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org 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. 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. Signed-off-by: Rafael Silva --- worktree.c | 19 +++++++++++++++++++ worktree.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/worktree.c b/worktree.c index 5764b0dc7c..ee14db3ab5 100644 --- a/worktree.c +++ b/worktree.c @@ -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); @@ -245,6 +246,24 @@ const char *worktree_lock_reason(struct worktree *wt) return wt->lock_reason; } +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; +} + /* convenient wrapper to deal with NULL strbuf */ static void strbuf_addf_gently(struct strbuf *buf, const char *fmt, ...) { diff --git a/worktree.h b/worktree.h index e5f4320725..24ded0f3c6 100644 --- 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 */ struct object_id head_oid; int is_detached; int is_bare; @@ -73,6 +74,12 @@ int is_main_worktree(const struct worktree *wt); */ const char *worktree_lock_reason(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); + /* * Return true if worktree entry should be pruned, along with the reason for * pruning. Otherwise, return false and the worktree's path, or NULL if it From patchwork Mon Jan 4 16:21:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Silva X-Patchwork-Id: 11997035 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EEA9EC433E6 for ; Mon, 4 Jan 2021 16:23:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C0CE9221F9 for ; Mon, 4 Jan 2021 16:23:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729212AbhADQXK (ORCPT ); Mon, 4 Jan 2021 11:23:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49298 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728247AbhADQXH (ORCPT ); Mon, 4 Jan 2021 11:23:07 -0500 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5D84C06179E for ; Mon, 4 Jan 2021 08:22:19 -0800 (PST) Received: by mail-ej1-x62b.google.com with SMTP id g20so37592683ejb.1 for ; Mon, 04 Jan 2021 08:22:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=oIPaibn7JGfpaKfX5xdKBe0Sk9eCp/Iyw6JnAccoprc=; b=E6QuMnwJgj6KJuqwN21LiHaGEP58sRaymnyXcV8+N+MuE6fq1S9whoN1oOGCuXQ7dk 6LjpsxeWxzrjRvexgdKkxjpxChY6WfeHGQ3f/AfrBSu7VzWMGgDvD14/UqoMF2R2lXqn 25wSM8ZwdQSUjgzbqesKhB0E7rN5W+g6c0Zvg+jZlDaF0nYkS1tvbtXJf+4xaJOMs0Km KGqpkGVm+MQt0OlH22iOLalnHImlp4nbbRWPeuDkQ8bMMuxroXygYljL6akT0EuZkGZw LBnSnXJr6xOvsg6tMrtFeZgZYxasKU5Ic4eU112znRCK6/zPIM2HEaXLKuSiJw4LEDC+ Ecuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=oIPaibn7JGfpaKfX5xdKBe0Sk9eCp/Iyw6JnAccoprc=; b=iKr4p9l/7oKrpR6duq4rqEU4223vjFdjmsC43zr+yQ9i7dNUq9SeYH1e2rL5Scmqlj ERZYU9MfhaEJHXJ3mQaJkh05LukA4bfhTGddexsp9TiEnMvCvz6msZQXAiEiH7aFskBC hsb9t1TVniSI9nyF5H6Z5wiPsUG+YJuLQVzXWRqweHuMallxfDJ8f4bnWeb2/LYA+NW4 W2XvIvwXWauzj3+3S/E772q83g6t+67VkQI4HceoM1siwqOoUhpPe7IRZzm1K2z1hlTT 50PWQOtqeVPmqiphL4qUdw0bnNv1W2gKIqH1qGnh0WZNqkRP/63PGVj50G+K9RcmrVqy h8+w== X-Gm-Message-State: AOAM530XojOnwfoWYIDkkYgg8DJOjBwDGWZEtN79DR3cgcdsh0GQF42r fZzIkXGpUA+N+oKkcJ1YGB9pfHn6ASc= X-Google-Smtp-Source: ABdhPJwUXt3HBwxgdsQ/CCRABN1IZ/6QAAT9OLpclCon7bnGyENW1xgDRW3dXJrAjBal+dL+XVkjsg== X-Received: by 2002:a17:906:aeda:: with SMTP id me26mr66260054ejb.11.1609777338264; Mon, 04 Jan 2021 08:22:18 -0800 (PST) Received: from localhost.localdomain ([79.140.115.191]) by smtp.gmail.com with ESMTPSA id bn21sm23931677ejb.47.2021.01.04.08.22.16 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Jan 2021 08:22:17 -0800 (PST) From: Rafael Silva To: git@vger.kernel.org Cc: Eric Sunshine , Rafael Silva Subject: [PATCH 3/7] worktree: teach worktree_lock_reason() to gently handle main worktree Date: Mon, 4 Jan 2021 17:21:24 +0100 Message-Id: <20210104162128.95281-4-rafaeloliveira.cs@gmail.com> X-Mailer: git-send-email 2.30.0.391.g469bf2a980 In-Reply-To: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> References: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The main worktree should not be locked and the worktree_lock_reason() API is aware of this fact and avoids running the check code for the main worktree. This checks is done via assert() macro, Therefore the caller needs to ensure the function is never called, usually by additional code. We can handle that case more gently by just returning false for the main worktree and not bother checking if the "locked" file exists. This will allowed further simplification from the caller as they will not need to ensure the main worktree is never passed to the API. Teach worktree_lock_reason() to be more gently and just return false for the main working tree. Signed-off-by: Rafael Silva --- worktree.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/worktree.c b/worktree.c index ee14db3ab5..78be83ba16 100644 --- a/worktree.c +++ b/worktree.c @@ -225,9 +225,7 @@ int is_main_worktree(const struct worktree *wt) const char *worktree_lock_reason(struct worktree *wt) { - assert(!is_main_worktree(wt)); - - if (!wt->lock_reason_valid) { + if (!is_main_worktree(wt) && !wt->lock_reason_valid) { struct strbuf path = STRBUF_INIT; strbuf_addstr(&path, worktree_git_path(wt, "locked")); From patchwork Mon Jan 4 16:21:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rafael Silva X-Patchwork-Id: 11997041 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 121F0C433E0 for ; Mon, 4 Jan 2021 16:23:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DA95020769 for ; Mon, 4 Jan 2021 16:23:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729155AbhADQXJ (ORCPT ); Mon, 4 Jan 2021 11:23:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728289AbhADQXH (ORCPT ); Mon, 4 Jan 2021 11:23:07 -0500 Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 48A30C06179F for ; Mon, 4 Jan 2021 08:22:21 -0800 (PST) Received: by mail-ej1-x635.google.com with SMTP id w1so37497497ejf.11 for ; Mon, 04 Jan 2021 08:22:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=20MuWJcDUdUJggPiKq2RTg+GTfdVam2cdrzyU6abDoY=; b=ehUqYfDkfOmLY3EL8+SI1BAnqyfMbT1yns135wpkKCHte4uaNRy0y6hWW+DsTL1aCu YGJYRP5XggfSJn+80OEZmNd5rreFwlrK866R0Vrc3SpR0oUrmDEi07wnfwB8Dmx+BFNr FP6KI8QghokWNbPtdo8hj3AeAsc3HDwJSSRpop0o03/jSleqiNryfyyWCgCzgfMGGs0Z 4iEB/ZH1TAd+SUZt5Gu6hXe5G1fseeZ/XIbw11AAMx1BsOlMWvEDnx965Gm/2iCujOMa c4OKwqxiib41TdOudzDMMa1N0bZYGhJkJvDCPjAw5TWFkKrTQE/39KeOGREDpjhoQ3WH tfeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=20MuWJcDUdUJggPiKq2RTg+GTfdVam2cdrzyU6abDoY=; b=lMMknarFnP/eJ1CjrQMrh4/aRfT2z8QycleZFyqCWSgeFEyeiY0FbSCI1p2FC7ydiy q1jLZfnIB8znBzj7hKu0ElTnVdq++RgYdjBz+xB4qlqpMezoHDgCBkg67aY3a/LFiTjT zt38VdS3AnTDH09jKxOt1RgjNS56AmELiPi/0jlawVKYLPgdLY44/nMEcGVXrgZDMgV8 UbvZHdBjOm6n50iTXyJL/gXwsyL2FwqcuDZU0PXPbbUcY2rgqk7vRom8MviILMlrvRZU aTKncmsAplrNQ6HZ5D3qoPnUQz6JAuC6fGiqrSDopPmfXjShAw+YwCtKiy4oCP6yqk6Z n47w== X-Gm-Message-State: AOAM5307/KbPo1wgECSHAXOxV1QkDs7rl5lXuvGU75eFeUQ9ToWLZw6w Olei+2ffp93tCSHu3ZRdTAWXyJoc/Tw= X-Google-Smtp-Source: ABdhPJx5d4x0yOZTPl6k087xmKiC5mpxE0GMyf6tJWmNHbZXW2qi5pbcIWTxQW/9UciY1cjHp5FEHg== X-Received: by 2002:a17:906:f1c8:: with SMTP id gx8mr68266587ejb.524.1609777339708; Mon, 04 Jan 2021 08:22:19 -0800 (PST) Received: from localhost.localdomain ([79.140.115.191]) by smtp.gmail.com with ESMTPSA id bn21sm23931677ejb.47.2021.01.04.08.22.18 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Jan 2021 08:22:19 -0800 (PST) From: Rafael Silva To: git@vger.kernel.org Cc: Eric Sunshine , Rafael Silva Subject: [PATCH 4/7] worktree: teach `list` prunable annotation and verbose Date: Mon, 4 Jan 2021 17:21:25 +0100 Message-Id: <20210104162128.95281-5-rafaeloliveira.cs@gmail.com> X-Mailer: git-send-email 2.30.0.391.g469bf2a980 In-Reply-To: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> References: <20210104162128.95281-1-rafaeloliveira.cs@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The "git worktree list" command shows the absolute path to the worktree, the commit that is checked out, the name of the branch, and a "locked" annotation if the worktree is locked. It is not clear whether a worktree, if any, is prunable. The "prune" command will remove a worktree in case is a prunable candidate unless --dry-run option is specified. This could lead to a worktree being removed without the user realizing before is to late, in case the user forgets to pass --dry-run for instance. If the "list" command shows which worktree is prunable, the user could verify before running "git worktree prune" and hopefully prevents the working tree to be removed "accidently" on the worse case scenario. Let's teach "git worktree list" to show when a worktree is prunable by appending "prunable" text to its output by default and show a prunable label for the porcelain format followed by the reason, if the avaiable. While at it, let's do the same for the "locked" annotation. Also, the worktree_prune_reason() stores the reason why git is selecting the worktree to be pruned, so let's leverage that and also display this information to the user. However, the reason is human readable text that can take virtually any size which might make harder to extend the "list" command with additional annotations and not fit nicely on the screen. In order to address this shortcoming, let's teach "git worktree list" to take a verbose option that will output the prune reason on the next line indented, if the reason is available, otherwise the annotation is kept on the same line. While at it, let's do the same for the "locked" annotation. The output of "git worktree list" with verbose becomes like so: $ git worktree list --verbose /path/to/main aba123 [main] /path/to/locked acb124 [branch-a] locked /path/to/locked-reason acc125 [branch-b] locked: worktree with locked reason /path/to/prunable acd126 [branch-c] prunable /path/to/prunable-reason ace127 [branch-d] prunable: gitdir file points to non-existent location And the output of the "git worktree list --porcelain" becomes like so: $ git worktree list --porcelain worktree /path/to/main HEAD abc1234abc1234abc1234abc1234abc1234abc12 branch refs/heads/main worktree /path/to/linked HEAD 123abc456def789abc1234def5678abc9123abce branch refs/heads/linked worktree /path/to/locked HEAD 123abcdea123abcd123acbd123acbda123abcd12 detached locked lock reason worktree /path/to/prunable HEAD def1234def1234def1234def1234def1234def1a detached prunable prunable reason Signed-off-by: Rafael Silva --- builtin/worktree.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index eeb3ffaed0..dedd4089e5 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -578,6 +578,20 @@ static void show_worktree_porcelain(struct worktree *wt) printf("detached\n"); else if (wt->head_ref) printf("branch %s\n", wt->head_ref); + + if (worktree_lock_reason(wt)) { + if (*wt->lock_reason) + printf("locked %s\n", wt->lock_reason); + else + printf("locked\n"); + } + + if (worktree_prune_reason(wt, expire)) { + if (*wt->prune_reason) + printf("prunable %s\n", wt->prune_reason); + else + printf("prunable\n"); + } } printf("\n"); } @@ -604,8 +618,19 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len) strbuf_addstr(&sb, "(error)"); } - if (!is_main_worktree(wt) && worktree_lock_reason(wt)) - strbuf_addstr(&sb, " locked"); + if (worktree_lock_reason(wt)) { + if (verbose && *wt->lock_reason) + strbuf_addf(&sb, "\n\tlocked: %s", wt->lock_reason); + else + strbuf_addstr(&sb, " locked"); + } + + if (worktree_prune_reason(wt, expire)) { + if (verbose && *wt->prune_reason) + strbuf_addf(&sb, "\n\tprunable: %s", wt->prune_reason); + else + strbuf_addstr(&sb, " prunable"); + } printf("%s\n", sb.buf); strbuf_release(&sb); @@ -650,12 +675,18 @@ static int list(int ac, const char **av, const char *prefix) struct option options[] = { OPT_BOOL(0, "porcelain", &porcelain, N_("machine-readable output")), + OPT__VERBOSE(&verbose, N_("show extended annotations and reasons, if available")), + OPT_EXPIRY_DATE(0, "expire", &expire, + N_("show working trees that is candidate to be pruned older than