From patchwork Wed Jun 10 06:30:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sunshine X-Patchwork-Id: 11597211 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 90C6292A for ; Wed, 10 Jun 2020 06:32:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6EF1020760 for ; Wed, 10 Jun 2020 06:32:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IWyr+mCU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726109AbgFJGb7 (ORCPT ); Wed, 10 Jun 2020 02:31:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46044 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726072AbgFJGb5 (ORCPT ); Wed, 10 Jun 2020 02:31:57 -0400 Received: from mail-io1-xd41.google.com (mail-io1-xd41.google.com [IPv6:2607:f8b0:4864:20::d41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 478D2C03E96F for ; Tue, 9 Jun 2020 23:31:57 -0700 (PDT) Received: by mail-io1-xd41.google.com with SMTP id y5so890991iob.12 for ; Tue, 09 Jun 2020 23:31:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XPtcdgftzoBqPW91YoLmZSnHgjxijrfF1mPTpDpKyk0=; b=IWyr+mCU2W9F0zEpgVo/K+lZwiT0j+kopa1XPjNBqsy1VaY4kMeP3SW+CopxqrXxNX pL51LhP9ybXbAIrj87+t79opTGAg01nUcRT6lCugIPMTX3bNqFqDH73wbzx8kNJmtyIZ 42qMSNz/lchqlKIPgg/MfWjHg4GPyTKZouNYKnWTASNn5FWDbx8c1BC4hOBNIdoCUOb8 JF6dGRy3OMzTHAd9g8S+jjKOLfrDhDBomHFvlWHUc1DX1Xpw0YqUc8HqqCYlA38taIm3 MPa7B+QQFwNqxUlTbg9Fa/xjTFoIlFDR+1L8pWo7cGiBSC6kEa3t51KrthCYwS/jBLdA gzVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=XPtcdgftzoBqPW91YoLmZSnHgjxijrfF1mPTpDpKyk0=; b=pEPM+WTnyufqBHoyTeVMDPwFFBuYXY1h2Epn8O/D684mDXl5WM8Zx50TO2oxwIw1tr Qrv0qgslTKyOWO/286FOTkoDAUg/Nn+uVC0MKowjclSWl4wKHrCR1ExKVbkX22paP7t0 8cRGb4DhMkFlI2FCo1NmfKygWE/scl2jqgxOv60tVTRh68LdcHoI7d1VUDAM6KCxjwGr qGIDpiU6sVO4f4KyslTdvo4SPcT5vU59yFI2i0HjobpgcEfZfhW/kFwJVerMmrD3E4Cs 9vAovuOR8oaDR5cfDk65fBTi9+PJ3q6tNpUvDDlR3Uul5DJpvbY45kw0BNPMqPilMeb6 QYbA== X-Gm-Message-State: AOAM530FX2sfTPXbF0XNh2ux9fZhOqgSfDIZTf8oY52wBG1gqsdWaCiQ R/rEIhkQzezBc3M0HCPUMiIaCklZno0= X-Google-Smtp-Source: ABdhPJwbsUEbcWXj8pbs07zx1gOWGhcJMznQxUM4RuULrAbSfHd/U5wu1RDkNmG/FEOh4t5EN79jtw== X-Received: by 2002:a6b:6414:: with SMTP id t20mr1832316iog.101.1591770716014; Tue, 09 Jun 2020 23:31:56 -0700 (PDT) Received: from localhost.localdomain (user-12l2dpj.cable.mindspring.com. [69.81.55.51]) by smtp.gmail.com with ESMTPSA id f22sm8497868iob.18.2020.06.09.23.31.54 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Jun 2020 23:31:55 -0700 (PDT) From: Eric Sunshine To: git@vger.kernel.org Cc: Duy Nguyen , =?utf-8?q?Jonathan_M=C3=BCller?= , Shourya Shukla , Junio C Hamano , Ramsay Jones , Eric Sunshine Subject: [PATCH v2 1/7] worktree: factor out repeated string literal Date: Wed, 10 Jun 2020 02:30:43 -0400 Message-Id: <20200610063049.74666-2-sunshine@sunshineco.com> X-Mailer: git-send-email 2.27.0.90.gabb59f83a2 In-Reply-To: <20200610063049.74666-1-sunshine@sunshineco.com> References: <20200610063049.74666-1-sunshine@sunshineco.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org For each worktree removed by "git worktree prune", it reports the reason for the removal. All reasons share the common prefix "Removing worktrees/%s:". As new removal reasons are added, this prefix needs to be duplicated, which is error-prone and potentially cumbersome. Therefore, factor out the common prefix. Although this change seems to increase the "sentence lego quotient", it should be reasonably safe, as the reason for removal is a distinct clause, not strictly related to the prefix. Moreover, the "worktrees" in "Removing worktrees/%s:" is a path literal which ought not be localized, so by factoring it out, we can more easily avoid exposing that path fragment to translators. Signed-off-by: Eric Sunshine --- builtin/worktree.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index d99db35668..9b15f19fc5 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -76,19 +76,19 @@ static int prune_worktree(const char *id, struct strbuf *reason) ssize_t read_result; if (!is_directory(git_path("worktrees/%s", id))) { - strbuf_addf(reason, _("Removing worktrees/%s: not a valid directory"), 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_addf(reason, _("Removing worktrees/%s: gitdir file does not exist"), id); + 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, _("Removing worktrees/%s: unable to read gitdir file (%s)"), - id, strerror(errno)); + strbuf_addf(reason, _("unable to read gitdir file (%s)"), + strerror(errno)); return 1; } len = xsize_t(st.st_size); @@ -96,8 +96,8 @@ static int prune_worktree(const char *id, struct strbuf *reason) read_result = read_in_full(fd, path, len); if (read_result < 0) { - strbuf_addf(reason, _("Removing worktrees/%s: unable to read gitdir file (%s)"), - id, strerror(errno)); + strbuf_addf(reason, _("unable to read gitdir file (%s)"), + strerror(errno)); close(fd); free(path); return 1; @@ -106,15 +106,15 @@ static int prune_worktree(const char *id, struct strbuf *reason) if (read_result != len) { strbuf_addf(reason, - _("Removing worktrees/%s: short read (expected %"PRIuMAX" bytes, read %"PRIuMAX")"), - id, (uintmax_t)len, (uintmax_t)read_result); + _("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_addf(reason, _("Removing worktrees/%s: invalid gitdir file"), id); + strbuf_addstr(reason, _("invalid gitdir file")); free(path); return 1; } @@ -123,7 +123,7 @@ static int prune_worktree(const char *id, struct strbuf *reason) free(path); if (stat(git_path("worktrees/%s/index", id), &st) || st.st_mtime <= expire) { - strbuf_addf(reason, _("Removing worktrees/%s: gitdir file points to non-existent location"), id); + strbuf_addstr(reason, _("gitdir file points to non-existent location")); return 1; } else { return 0; @@ -147,7 +147,8 @@ static void prune_worktrees(void) if (!prune_worktree(d->d_name, &reason)) continue; if (show_only || verbose) - printf("%s\n", reason.buf); + printf_ln(_("Removing %s/%s: %s"), + "worktrees", d->d_name, reason.buf); if (show_only) continue; delete_git_dir(d->d_name); From patchwork Wed Jun 10 06:30:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sunshine X-Patchwork-Id: 11597215 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5C14490 for ; Wed, 10 Jun 2020 06:32:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 41731207ED for ; Wed, 10 Jun 2020 06:32:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="HiX3faV0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726272AbgFJGcF (ORCPT ); Wed, 10 Jun 2020 02:32:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726072AbgFJGcA (ORCPT ); Wed, 10 Jun 2020 02:32:00 -0400 Received: from mail-io1-xd41.google.com (mail-io1-xd41.google.com [IPv6:2607:f8b0:4864:20::d41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AB9C0C03E96B for ; Tue, 9 Jun 2020 23:31:58 -0700 (PDT) Received: by mail-io1-xd41.google.com with SMTP id s18so936308ioe.2 for ; Tue, 09 Jun 2020 23:31:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=G0AJ7z17PvhrhwgSYQy1/yJUXiwj9MUj5AnxIybjMak=; b=HiX3faV0h3Hm4kSpjn4iT5m0TqXSfuYLnw6L/eSZHcHutnyQRuXu8nIpZHcun1u+nz lQz1havsX1aGmZIq+7XyUIYRpo/6mjCsuD0eKMeqOr1l3axIMre/1YlT2KfGEyZWgHhW 2SHD3NikQBmU6nTmkY8RR2rhmn0JfRlZVJRV7WxfMnUkJ7ev6eoAOHplHQW+zgB2oeEw BfgW5zw2pVcY2mtPsQUIDqFCObiiMv+FZwNQ/7l3XLDW04JuSJNZmFMQPxodVJrXco1+ L05qW1snqz+NNbFjCoLAXkkWLvlXlQO/sfK5EwP2Az2FfuyYRgp/lbmt2YlXf+EvjjQ0 y2Xg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=G0AJ7z17PvhrhwgSYQy1/yJUXiwj9MUj5AnxIybjMak=; b=WKNcX14l1cpvxjuWnCSYHBokS2RVR21xC54brkrrSw/4O/Y+bDyYxGsFbkKAa6mpZz GUgsCb+lUZtLuj6f39+4AHDM5TGrMTtr6miXKuJUoIBxxBx7CvE7sihQ/CnB3V0QCiVK lCrTvfcfSLtAtLjXecUPpWmory4RGpzRCpamsVHv2dYkdTl7G+2j8vRKt2uBuuFIPnIh GWd4DKB06VS0tWh2OWiVCb0o+2w/dKRCByQBVfuAIVmPsiShhzFi9/8DOBU2kS0kk0bb llfS/MjNfkCwiN6IAdO7t0AFljJ1RoNTXa00NTeTh6mYE8Lfua6HH4SYt4AmirjSQxVm 0Xsw== X-Gm-Message-State: AOAM533R39+VDcX6vtrwUPcxW2fVGnToQ1yKi4JDsPHhYarzQXvo0iu2 sFCCOM5YOB5UevAjh1fujWfZZj9bpvw= X-Google-Smtp-Source: ABdhPJwP5Ws2nmYOsOQ2ON4tf2eTKErpYMdQmGdaJqK7U4YJQe8+a1EI/9GxwMWjip93b5WeE4dpPQ== X-Received: by 2002:a05:6602:1243:: with SMTP id o3mr1782349iou.89.1591770717624; Tue, 09 Jun 2020 23:31:57 -0700 (PDT) Received: from localhost.localdomain (user-12l2dpj.cable.mindspring.com. [69.81.55.51]) by smtp.gmail.com with ESMTPSA id f22sm8497868iob.18.2020.06.09.23.31.56 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Jun 2020 23:31:56 -0700 (PDT) From: Eric Sunshine To: git@vger.kernel.org Cc: Duy Nguyen , =?utf-8?q?Jonathan_M=C3=BCller?= , Shourya Shukla , Junio C Hamano , Ramsay Jones , Eric Sunshine Subject: [PATCH v2 2/7] worktree: give "should be pruned?" function more meaningful name Date: Wed, 10 Jun 2020 02:30:44 -0400 Message-Id: <20200610063049.74666-3-sunshine@sunshineco.com> X-Mailer: git-send-email 2.27.0.90.gabb59f83a2 In-Reply-To: <20200610063049.74666-1-sunshine@sunshineco.com> References: <20200610063049.74666-1-sunshine@sunshineco.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Readers of the name prune_worktree() are likely to expect the function to actually prune a worktree, however, it only answers the question "should this worktree be pruned?". Give it a name more reflective of its true purpose to avoid such confusion. Signed-off-by: Eric Sunshine --- builtin/worktree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index 9b15f19fc5..35d38607e7 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -67,7 +67,7 @@ static void delete_worktrees_dir_if_empty(void) rmdir(git_path("worktrees")); /* ignore failed removal */ } -static int prune_worktree(const char *id, struct strbuf *reason) +static int should_prune_worktree(const char *id, struct strbuf *reason) { struct stat st; char *path; @@ -144,7 +144,7 @@ static void prune_worktrees(void) if (is_dot_or_dotdot(d->d_name)) continue; strbuf_reset(&reason); - if (!prune_worktree(d->d_name, &reason)) + if (!should_prune_worktree(d->d_name, &reason)) continue; if (show_only || verbose) printf_ln(_("Removing %s/%s: %s"), From patchwork Wed Jun 10 06:30:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sunshine X-Patchwork-Id: 11597219 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E324892A for ; Wed, 10 Jun 2020 06:32:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CA5CA20801 for ; Wed, 10 Jun 2020 06:32:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="jLs6T4/D" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726276AbgFJGcJ (ORCPT ); Wed, 10 Jun 2020 02:32:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726186AbgFJGcA (ORCPT ); Wed, 10 Jun 2020 02:32:00 -0400 Received: from mail-io1-xd41.google.com (mail-io1-xd41.google.com [IPv6:2607:f8b0:4864:20::d41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 07805C03E96F for ; Tue, 9 Jun 2020 23:32:00 -0700 (PDT) Received: by mail-io1-xd41.google.com with SMTP id m81so942452ioa.1 for ; Tue, 09 Jun 2020 23:31:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cLAkRSj+dy1kBdSQ1ANW//gviag+baogLOvlX0pXP4A=; b=jLs6T4/DU1TRlh298y6tR7XKokIOqNHH9vgaI2NaR9f2NmSVjPQJpuy3CMnVRPewgq OWJuKHqov8s0yNVEZ5fqxmNrqwc0HQ4cnlmUIvUo6C72fA2U7xlhIv4WIsqf3ptKBafj bOO0Jj0t+KPCCb/mt1aS04BqFSzyZAWGerxoaLydQtkBlX6C1hMJedeOhfIlgh3HhI18 xWnRNxYeDeyWi29NfrZ8U6IVWXnLvurcLKi/gYnfeDqKZh6R6mFCytDxkJ1E/4PWd3rw eUy3uO4nt9nmroh/BE8iHsXkuHMumtIOqEu+tcXrIpZ3nI+TBza35EAtz6Ke2iAJB7mU AREg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=cLAkRSj+dy1kBdSQ1ANW//gviag+baogLOvlX0pXP4A=; b=AqIY25fkM7v+x6mGcKnWGaXkX6HT2VWQRqzW3zsMOt6M2R96ZO7bUJ/QLOHxK53TtG cO77YSSJiUc+YYAs0xNznO0J1IR03wCWIglKxBpWZWB0EwONNhnXyw5U4IasQyC32det g0o18gms7I6qs4oJZgOkgD7tZyTNTGeB1qCsCdBRb8GKcVS2xXPCoHew8meUybDhNX3t C5XX/WQmi4qip8qdgxOTRKx6g+x5SISLqLqKL71uOqsGQEsEI2/nb6klSDNCkLj7ZoNi BZKgadzhP+FOC4mrBYMZqxr7FgiNDLz+vLCC/dFNsX8TE9F5q41M/pG8IexmjWNVUlO8 73uw== X-Gm-Message-State: AOAM5319Hb0RGXOug/45OXrnXAy/1tYBRUd6BHdpfYt/kK0y2JAAlZvb +BEKmr5b1pFLSEc3kl9PNu3Ao6vGnBI= X-Google-Smtp-Source: ABdhPJzAzbP6qzJNfN9XHDu+9RTOxsI1OBXKM6YCaDH7NlgjudXwHrPTLGB7uG1oo9/5O0Y3wge/NQ== X-Received: by 2002:a05:6638:dd3:: with SMTP id m19mr1782939jaj.106.1591770718963; Tue, 09 Jun 2020 23:31:58 -0700 (PDT) Received: from localhost.localdomain (user-12l2dpj.cable.mindspring.com. [69.81.55.51]) by smtp.gmail.com with ESMTPSA id f22sm8497868iob.18.2020.06.09.23.31.57 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Jun 2020 23:31:58 -0700 (PDT) From: Eric Sunshine To: git@vger.kernel.org Cc: Duy Nguyen , =?utf-8?q?Jonathan_M=C3=BCller?= , Shourya Shukla , Junio C Hamano , Ramsay Jones , Eric Sunshine Subject: [PATCH v2 3/7] worktree: make high-level pruning re-usable Date: Wed, 10 Jun 2020 02:30:45 -0400 Message-Id: <20200610063049.74666-4-sunshine@sunshineco.com> X-Mailer: git-send-email 2.27.0.90.gabb59f83a2 In-Reply-To: <20200610063049.74666-1-sunshine@sunshineco.com> References: <20200610063049.74666-1-sunshine@sunshineco.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The low-level logic for removing a worktree is well encapsulated in delete_git_dir(). However, high-level details related to pruning a worktree -- such as dealing with verbosity and dry-run mode -- are not encapsulated. Factor out this high-level logic into its own function so it can be re-used as new worktree corruption detectors are added. Signed-off-by: Eric Sunshine --- builtin/worktree.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index 35d38607e7..706ac68751 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -133,6 +133,14 @@ static int should_prune_worktree(const char *id, struct strbuf *reason) return 0; } +static void prune_worktree(const char *id, const char *reason) +{ + if (show_only || verbose) + printf_ln(_("Removing %s/%s: %s"), "worktrees", id, reason); + if (!show_only) + delete_git_dir(id); +} + static void prune_worktrees(void) { struct strbuf reason = STRBUF_INIT; @@ -146,12 +154,7 @@ static void prune_worktrees(void) strbuf_reset(&reason); if (!should_prune_worktree(d->d_name, &reason)) continue; - if (show_only || verbose) - printf_ln(_("Removing %s/%s: %s"), - "worktrees", d->d_name, reason.buf); - if (show_only) - continue; - delete_git_dir(d->d_name); + prune_worktree(d->d_name, reason.buf); } closedir(dir); if (!show_only) From patchwork Wed Jun 10 06:30:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sunshine X-Patchwork-Id: 11597225 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3752E90 for ; Wed, 10 Jun 2020 06:32:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 158E320760 for ; Wed, 10 Jun 2020 06:32:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="tFib/155" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726288AbgFJGcO (ORCPT ); Wed, 10 Jun 2020 02:32:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46066 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726251AbgFJGcD (ORCPT ); Wed, 10 Jun 2020 02:32:03 -0400 Received: from mail-io1-xd43.google.com (mail-io1-xd43.google.com [IPv6:2607:f8b0:4864:20::d43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 756FCC08C5C1 for ; Tue, 9 Jun 2020 23:32:01 -0700 (PDT) Received: by mail-io1-xd43.google.com with SMTP id r2so928013ioo.4 for ; Tue, 09 Jun 2020 23:32:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VwHeaJTqJaoEYdbx4lhU8YbWZPxvvvv2zKngKjjXxsU=; b=tFib/1553u/IFCDRAv6u3E+O45Bul4x7BCzsOvEKZd4chMweQ+iiltpc2j9ELWos24 v0P0W4cpCV72l4LiTxy8SeAJZLRw5CQiwPiNnZxAvWnoX1cPmSTMLY69BgnLg+nqhE63 Qe2yf44TYoqcZtQ7jpx6FfVQmTg3qOMZhnGi1iNBaY3o2GfNrBvVrsGDuAIyvzULCyoc 3UacOFUpkoOqZARwkSjXEUti+/YEeVMrCPdwhRPmCVVitnUujS6qZz7+yyzAA/XmEmt6 sANsDy1SsykNZYV/d5EdsYLHXNKR0p4ngYkH9cxAQC1Eryan6ONqSaMdcZU4AtADUK29 owNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=VwHeaJTqJaoEYdbx4lhU8YbWZPxvvvv2zKngKjjXxsU=; b=WaGsqyodUA/yna+Ee6OKkolnSPLpqC3gMoYFuF+lbI7dkvPNSkuegBHDrI9pLOTFaO NqNyPPUWytHnlxGV/+NfGIbVEXrUrWlYQw8mVQnCBZxwl9tFVF8UwmKmxYT6+IFxKMty HUaeqCajMRSfuFgOkPO52Fs3o6c1Y/jK3tGtfoXm/TJzZ2pUQxwSPPfymkXZEigutUYm tGOJ0DF+QBGfBxOIWArLD7E0PExvDDgHewqfDImFbfhM+VU5RJ4/4MlG6Z6YCoJZtlg+ /f2dvOUX58tsArCjy/sXtY3l58qrOgLXCHRuZULnqvDW2WrJrPMq9bq/zGAKfq44GDAF lvlw== X-Gm-Message-State: AOAM5314+vfuP0mxLKpBiVc+FE/T/Bp2tkGSV/rgiiA0LT/PEId1nnCK J/hjAdc0B7Ldb+n/+hK6+QEUckjXK4w= X-Google-Smtp-Source: ABdhPJwnt/FRl+hdeCMfTnwwnriGgCXWlwSDrUkpOd9iCeLl6xU0GfFZaVYB2Br907t+V8QOJtLt/Q== X-Received: by 2002:a05:6602:2f0a:: with SMTP id q10mr1837071iow.134.1591770720135; Tue, 09 Jun 2020 23:32:00 -0700 (PDT) Received: from localhost.localdomain (user-12l2dpj.cable.mindspring.com. [69.81.55.51]) by smtp.gmail.com with ESMTPSA id f22sm8497868iob.18.2020.06.09.23.31.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Jun 2020 23:31:59 -0700 (PDT) From: Eric Sunshine To: git@vger.kernel.org Cc: Duy Nguyen , =?utf-8?q?Jonathan_M=C3=BCller?= , Shourya Shukla , Junio C Hamano , Ramsay Jones , Eric Sunshine Subject: [PATCH v2 4/7] worktree: prune duplicate entries referencing same worktree path Date: Wed, 10 Jun 2020 02:30:46 -0400 Message-Id: <20200610063049.74666-5-sunshine@sunshineco.com> X-Mailer: git-send-email 2.27.0.90.gabb59f83a2 In-Reply-To: <20200610063049.74666-1-sunshine@sunshineco.com> References: <20200610063049.74666-1-sunshine@sunshineco.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org A fundamental restriction of linked working trees is that there must only ever be a single worktree associated with a particular path, thus "git worktree add" explicitly disallows creation of a new worktree at the same location as an existing registered worktree. Nevertheless, users can still "shoot themselves in the foot" by mucking with administrative files in .git/worktree//. Worse, "git worktree move" is careless[1] and allows a worktree to be moved atop a registered but missing worktree (which can happen, for instance, if the worktree is on removable media). For instance: $ git clone foo.git $ cd foo $ git worktree add ../bar $ git worktree add ../baz $ rm -rf ../bar $ git worktree move ../baz ../bar $ git worktree list .../foo beefd00f [master] .../bar beefd00f [bar] .../bar beefd00f [baz] Help users recover from this form of corruption by teaching "git worktree prune" to detect when multiple worktrees are associated with the same path. [1]: A subsequent commit will fix "git worktree move" validation to be more strict. Signed-off-by: Eric Sunshine --- builtin/worktree.c | 49 ++++++++++++++++++++++++++++++++++----- t/t2401-worktree-prune.sh | 12 ++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index 706ac68751..65492752a7 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -67,7 +67,12 @@ static void delete_worktrees_dir_if_empty(void) rmdir(git_path("worktrees")); /* ignore failed removal */ } -static int should_prune_worktree(const char *id, struct strbuf *reason) +/* + * 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; @@ -75,6 +80,7 @@ static int should_prune_worktree(const char *id, struct strbuf *reason) 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; @@ -120,16 +126,17 @@ static int should_prune_worktree(const char *id, struct strbuf *reason) } path[len] = '\0'; if (!file_exists(path)) { - free(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; } } - free(path); + *wtpath = path; return 0; } @@ -141,22 +148,52 @@ static void prune_worktree(const char *id, const char *reason) delete_git_dir(id); } +static int prune_cmp(const void *a, const void *b) +{ + const struct string_list_item *x = a; + const struct string_list_item *y = b; + int c; + + if ((c = fspathcmp(x->string, y->string))) + return c; + /* paths same; sort by .git/worktrees/ */ + return strcmp(x->util, y->util); +} + +static void prune_dups(struct string_list *l) +{ + int i; + + QSORT(l->items, l->nr, prune_cmp); + for (i = 1; i < l->nr; i++) { + if (!fspathcmp(l->items[i].string, l->items[i - 1].string)) + prune_worktree(l->items[i].util, "duplicate entry"); + } +} + static void prune_worktrees(void) { struct strbuf reason = STRBUF_INIT; + struct string_list kept = STRING_LIST_INIT_NODUP; DIR *dir = opendir(git_path("worktrees")); struct dirent *d; if (!dir) return; while ((d = readdir(dir)) != NULL) { + char *path; if (is_dot_or_dotdot(d->d_name)) continue; strbuf_reset(&reason); - if (!should_prune_worktree(d->d_name, &reason)) - continue; - prune_worktree(d->d_name, reason.buf); + if (should_prune_worktree(d->d_name, &reason, &path)) + prune_worktree(d->d_name, reason.buf); + else if (path) + string_list_append(&kept, path)->util = xstrdup(d->d_name); } closedir(dir); + + prune_dups(&kept); + string_list_clear(&kept, 1); + if (!show_only) delete_worktrees_dir_if_empty(); strbuf_release(&reason); diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh index b7d6d5d45a..fd3916fee0 100755 --- a/t/t2401-worktree-prune.sh +++ b/t/t2401-worktree-prune.sh @@ -92,4 +92,16 @@ test_expect_success 'not prune proper checkouts' ' test -d .git/worktrees/nop ' +test_expect_success 'prune duplicate (linked/linked)' ' + test_when_finished rm -fr .git/worktrees w1 w2 && + git worktree add --detach w1 && + git worktree add --detach w2 && + sed "s/w2/w1/" .git/worktrees/w2/gitdir >.git/worktrees/w2/gitdir.new && + mv .git/worktrees/w2/gitdir.new .git/worktrees/w2/gitdir && + git worktree prune --verbose >actual && + test_i18ngrep "duplicate entry" actual && + test -d .git/worktrees/w1 && + ! test -d .git/worktrees/w2 +' + test_done From patchwork Wed Jun 10 06:30:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Eric Sunshine X-Patchwork-Id: 11597221 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D831A92A for ; Wed, 10 Jun 2020 06:32:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C005720801 for ; Wed, 10 Jun 2020 06:32:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="sx9L9/o2" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726279AbgFJGcM (ORCPT ); Wed, 10 Jun 2020 02:32:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726265AbgFJGcE (ORCPT ); Wed, 10 Jun 2020 02:32:04 -0400 Received: from mail-io1-xd41.google.com (mail-io1-xd41.google.com [IPv6:2607:f8b0:4864:20::d41]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DADD7C08C5C3 for ; Tue, 9 Jun 2020 23:32:02 -0700 (PDT) Received: by mail-io1-xd41.google.com with SMTP id r2so928056ioo.4 for ; Tue, 09 Jun 2020 23:32:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ESEjbUB+uaU4CQwHyqqq5yhy/KHYQrDWTfZ/In/tZiw=; b=sx9L9/o242zM0Lf1GugUuHWkwi1YSlhFFt8xcUBwnignhicMQ2DxLVnlpP+LHxdIPV 8U2LO0J/cPivXcifmDj+vvc+V8shy2B2f6ZH1P07LvSb9NiLwxtJkPc6qGCYkmy71WCN IHGWVzgPNKSgbi0EeN9CT8+UBrFMvuocx2LlLCHh4dg1qKtetQLFoGdenKf8fMlYxy/a 0U8Kg/j3X9xQ2IT/hooilNabe1T3WhReYRAy6E4Knbl7UVp18v31+y23eoyOtyMjc2vq HYkI1jUO7qiiDqd3//Ao0fyyAUiAcFlmpsiDMn/oQ5TsytlPbdDpy+1TG2oTqvAtm+EA CpQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=ESEjbUB+uaU4CQwHyqqq5yhy/KHYQrDWTfZ/In/tZiw=; b=ktZq0tFIoZU2v0qUwNaEmyyQCxdG/wPH6Da7YLkVvlYdBdPGEnF+rOFkLILnLIEbG0 WJseTNq+N1lAjJjaxNr6tDNDbfN7+uvrrpG0AHNUvn6ebboXZqAgA2pGkpWGjAONdn0S F33acYFA/oZz1JvytW+rrbY9V0YPBG+5pVy0AhP6E/dIF+rXDWbmuIQbahfts14pcO6N cAmPdShX501Pvk0cMJJpa37JFRwTb0eHOW7liIUxoUY5PtDJlhfKCZCiu6p9HuoWIfX8 /QcRH1eBWdkrlLQvtg3Qnei4HxRsuJolZfB3A3PWoqHcx6Np5+XQH4SE95s5gUpenNNS CyPw== X-Gm-Message-State: AOAM531D1BU0W7XQTvVYgbDTWODA0szenp+FyJhUhibN4/BRdDKcLDNU fzTWav2u0QJxcAOclD1oHIXy/BNQ4SE= X-Google-Smtp-Source: ABdhPJyyLwQZkt+dBTzDbZajPW5UeawcC09m7HiBWHzE9Y+c6DcTCkd5txOHZpXqroRbKk8amOA7Lw== X-Received: by 2002:a5d:9819:: with SMTP id a25mr1757062iol.85.1591770721624; Tue, 09 Jun 2020 23:32:01 -0700 (PDT) Received: from localhost.localdomain (user-12l2dpj.cable.mindspring.com. [69.81.55.51]) by smtp.gmail.com with ESMTPSA id f22sm8497868iob.18.2020.06.09.23.32.00 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Jun 2020 23:32:00 -0700 (PDT) From: Eric Sunshine To: git@vger.kernel.org Cc: Duy Nguyen , =?utf-8?q?Jonathan_M=C3=BCller?= , Shourya Shukla , Junio C Hamano , Ramsay Jones , Eric Sunshine Subject: [PATCH v2 5/7] worktree: prune linked worktree referencing main worktree path Date: Wed, 10 Jun 2020 02:30:47 -0400 Message-Id: <20200610063049.74666-6-sunshine@sunshineco.com> X-Mailer: git-send-email 2.27.0.90.gabb59f83a2 In-Reply-To: <20200610063049.74666-1-sunshine@sunshineco.com> References: <20200610063049.74666-1-sunshine@sunshineco.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org "git worktree prune" detects when multiple entries are associated with the same path and prunes the duplicates, however, it does not detect when a linked worktree points at the path of the main worktree. Although "git worktree add" disallows creating a new worktree with the same path as the main worktree, such a case can arise outside the control of Git even without the user mucking with .git/worktree// administrative files. For instance: $ git clone foo.git $ git -C foo worktree add ../bar $ rm -rf bar $ mv foo bar $ git -C bar worktree list .../bar deadfeeb [master] .../bar deadfeeb [bar] Help the user recover from such corruption by extending "git worktree prune" to also detect when a linked worktree is associated with the path of the main worktree. Reported-by: Jonathan Müller Signed-off-by: Eric Sunshine --- builtin/worktree.c | 15 +++++++++++++++ t/t2401-worktree-prune.sh | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/builtin/worktree.c b/builtin/worktree.c index 65492752a7..350108eba0 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -156,6 +156,16 @@ static int prune_cmp(const void *a, const void *b) if ((c = fspathcmp(x->string, y->string))) return c; + /* + * paths same; prune_dupes() removes all but the first worktree entry + * having the same path, so sort main worktree ('util' is NULL) above + * linked worktrees ('util' not NULL) since main worktree can't be + * removed + */ + if (!x->util) + return -1; + if (!y->util) + return 1; /* paths same; sort by .git/worktrees/ */ return strcmp(x->util, y->util); } @@ -174,6 +184,7 @@ static void prune_dups(struct string_list *l) static void prune_worktrees(void) { struct strbuf reason = STRBUF_INIT; + struct strbuf main_path = STRBUF_INIT; struct string_list kept = STRING_LIST_INIT_NODUP; DIR *dir = opendir(git_path("worktrees")); struct dirent *d; @@ -191,6 +202,10 @@ static void prune_worktrees(void) } closedir(dir); + strbuf_add_absolute_path(&main_path, get_git_common_dir()); + /* massage main worktree absolute path to match 'gitdir' content */ + strbuf_strip_suffix(&main_path, "/."); + string_list_append(&kept, strbuf_detach(&main_path, NULL)); prune_dups(&kept); string_list_clear(&kept, 1); diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh index fd3916fee0..a6ce7f590b 100755 --- a/t/t2401-worktree-prune.sh +++ b/t/t2401-worktree-prune.sh @@ -104,4 +104,16 @@ test_expect_success 'prune duplicate (linked/linked)' ' ! test -d .git/worktrees/w2 ' +test_expect_success 'prune duplicate (main/linked)' ' + test_when_finished rm -fr repo wt && + test_create_repo repo && + test_commit -C repo x && + git -C repo worktree add --detach ../wt && + rm -fr wt && + mv repo wt && + git -C wt worktree prune --verbose >actual && + test_i18ngrep "duplicate entry" actual && + ! test -d .git/worktrees/wt +' + test_done From patchwork Wed Jun 10 06:30:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sunshine X-Patchwork-Id: 11597217 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 46F9290 for ; Wed, 10 Jun 2020 06:32:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2C44F207ED for ; Wed, 10 Jun 2020 06:32:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="FxRDf897" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726277AbgFJGcK (ORCPT ); Wed, 10 Jun 2020 02:32:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726269AbgFJGcE (ORCPT ); Wed, 10 Jun 2020 02:32:04 -0400 Received: from mail-io1-xd2d.google.com (mail-io1-xd2d.google.com [IPv6:2607:f8b0:4864:20::d2d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD7D6C03E96B for ; Tue, 9 Jun 2020 23:32:04 -0700 (PDT) Received: by mail-io1-xd2d.google.com with SMTP id c8so916739iob.6 for ; Tue, 09 Jun 2020 23:32:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=t+xcHyuPhg6SK//5Suj/L9/GdfySTIIoSEgRhmG8Ea8=; b=FxRDf897A86xnu6Lb1e0lIkanJzN3ls+Q/Pp6IqTv8WtCwYVOO2vRh75jenG9bzr0/ /H+AN/cMie9i48Dl0pc6f0mIip14NqXXDe9JC+q+x+FdjQs5HEA7nykpchir9Mu8NcI8 t77stvsNbtI3x93RN3+rU3POfPCYxgm5IDStl9gPo16LFGZrtQSHhUpzeKKvK4EhJKQX TdIKWRIaoZA2qnw9I8f8qbojWW68xekdqcO7ucRYRFrOv2JO+urkJhRWb+w8thjQGmUp c6xrB37s+ZNzHxdcmoxHOPMutMUl4YswQN9yVDzxGVlgW9qsSi5pzVz2GGt2YxQEOXID jg2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=t+xcHyuPhg6SK//5Suj/L9/GdfySTIIoSEgRhmG8Ea8=; b=hAafd5iOG3ld+cksJgchRG1unOEj5/J8aJMkbqFomgIJnZFRr6b2Kfq1EzArNo6ndA f68OZrZak+WiRWMLi7LhG0LXS8XA+Qeg25jf1wKazOOiVXm4cEwdhk4zZ7zV5tPCr8bZ NAgv7o6VJvtlloZcLwJIOUudexJ9H+XHlveFFtQFcvdMKi4eO0TQyOioNrNeg4JcXNn1 hYTwJ6Pu5VNilSkhoj46yUO2x1nsy2GZrFrpCVY0a69WKDyjjAdklYKWwfcZgTRD8Yze r5HxyBtMvY6B0/2fL0bRqW58wSw1/fonI9LWnnrWR0CNWkDmnzAQyado3r/0rTzjPG/O iigg== X-Gm-Message-State: AOAM5332gpEOcFcn6r9lJTvf9GdH2i0TkQSd8nLyifl/qhpyfbKyq8L+ 4VtqXt3xMmRwndEk1fJ5cPcnoS6elZg= X-Google-Smtp-Source: ABdhPJxsZm22a6wu9+QoFM/5Qw97PjocsxKXbadGGsdDTcM4jrYWkRubCCfAClgQO9sZD8Qqzc77LQ== X-Received: by 2002:a02:810:: with SMTP id 16mr1755095jac.17.1591770723009; Tue, 09 Jun 2020 23:32:03 -0700 (PDT) Received: from localhost.localdomain (user-12l2dpj.cable.mindspring.com. [69.81.55.51]) by smtp.gmail.com with ESMTPSA id f22sm8497868iob.18.2020.06.09.23.32.01 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Jun 2020 23:32:02 -0700 (PDT) From: Eric Sunshine To: git@vger.kernel.org Cc: Duy Nguyen , =?utf-8?q?Jonathan_M=C3=BCller?= , Shourya Shukla , Junio C Hamano , Ramsay Jones , Eric Sunshine Subject: [PATCH v2 6/7] worktree: generalize candidate worktree path validation Date: Wed, 10 Jun 2020 02:30:48 -0400 Message-Id: <20200610063049.74666-7-sunshine@sunshineco.com> X-Mailer: git-send-email 2.27.0.90.gabb59f83a2 In-Reply-To: <20200610063049.74666-1-sunshine@sunshineco.com> References: <20200610063049.74666-1-sunshine@sunshineco.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org "git worktree add" checks that the specified path is a valid location for a new worktree by ensuring that the path does not already exist and is not already registered to another worktree (a path can be registered but missing, for instance, if it resides on removable media). Since "git worktree add" is not the only command which should perform such validation ("git worktree move" ought to also), generalize the the validation function for use by other callers, as well. Signed-off-by: Eric Sunshine --- builtin/worktree.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/builtin/worktree.c b/builtin/worktree.c index 350108eba0..8fcf3f38fb 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -280,34 +280,33 @@ static const char *worktree_basename(const char *path, int *olen) return name; } -static void validate_worktree_add(const char *path, const struct add_opts *opts) +/* check that path is viable location for worktree */ +static void check_candidate_path(const char *path, + int force, + struct worktree **worktrees, + const char *cmd) { - struct worktree **worktrees; struct worktree *wt; int locked; if (file_exists(path) && !is_empty_dir(path)) die(_("'%s' already exists"), path); - worktrees = get_worktrees(0); wt = find_worktree_by_path(worktrees, path); if (!wt) - goto done; + return; locked = !!worktree_lock_reason(wt); - if ((!locked && opts->force) || (locked && opts->force > 1)) { + if ((!locked && force) || (locked && force > 1)) { if (delete_git_dir(wt->id)) - die(_("unable to re-add worktree '%s'"), path); - goto done; + die(_("unusable worktree destination '%s'"), path); + return; } if (locked) - die(_("'%s' is a missing but locked worktree;\nuse 'add -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), path); + die(_("'%s' is a missing but locked worktree;\nuse '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), cmd, path); else - die(_("'%s' is a missing but already registered worktree;\nuse 'add -f' to override, or 'prune' or 'remove' to clear"), path); - -done: - free_worktrees(worktrees); + die(_("'%s' is a missing but already registered worktree;\nuse '%s -f' to override, or 'prune' or 'remove' to clear"), cmd, path); } static int add_worktree(const char *path, const char *refname, @@ -324,8 +323,12 @@ static int add_worktree(const char *path, const char *refname, struct commit *commit = NULL; int is_branch = 0; struct strbuf sb_name = STRBUF_INIT; + struct worktree **worktrees; - validate_worktree_add(path, opts); + worktrees = get_worktrees(0); + check_candidate_path(path, opts->force, worktrees, "add"); + free_worktrees(worktrees); + worktrees = NULL; /* is 'refname' a branch or commit? */ if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) && From patchwork Wed Jun 10 06:30:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Sunshine X-Patchwork-Id: 11597223 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5127814E3 for ; Wed, 10 Jun 2020 06:32:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 365C820801 for ; Wed, 10 Jun 2020 06:32:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ve5hwd6G" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726284AbgFJGcN (ORCPT ); Wed, 10 Jun 2020 02:32:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46054 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726273AbgFJGcF (ORCPT ); Wed, 10 Jun 2020 02:32:05 -0400 Received: from mail-io1-xd43.google.com (mail-io1-xd43.google.com [IPv6:2607:f8b0:4864:20::d43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 42C89C03E96F for ; Tue, 9 Jun 2020 23:32:05 -0700 (PDT) Received: by mail-io1-xd43.google.com with SMTP id o5so911079iow.8 for ; Tue, 09 Jun 2020 23:32:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=m4mCa6+Xibe7dd4u6/EznwsHbw1TA/1Laf7a6SNQ3sc=; b=ve5hwd6Gr2WVaZDjJJsG3dP7VrXitws9875i8MZQ7MqZkpgjt0xcQlbgBjj7FDiw2j 1h2N49hNjBaYCxYt5e4dWpV6KgYC9KdYTY7dx5BHNWS9/AsEDorxDPpAntv16W/CyPoZ rLN1aPfxA9QyUy1QvzI48JB54gYgwJgrAH9KHF4fOyVsB8rcwboNkobGKOP/139TKR8M I5X+NSFyoiHhYjRhg9tepHIGS8hRQWxSdWT3BQD+/+9BeLna0YnH2iSm0ZYCl80SuUtM Ef8aR99nuVYCtY3cDMafjQhqVhS+nSXz3LePnf6126Qxu2gXzdQBw9KvNhjikWpHjrsI g0KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-transfer-encoding; bh=m4mCa6+Xibe7dd4u6/EznwsHbw1TA/1Laf7a6SNQ3sc=; b=a5N4LwNVhoQzB5jREvU59JviXYgClQshMrLr3nKCOSfrvgmzyy0ubErQFdAFytH7Ye PG2gDM91lK5flhIY+BAo5+eCd5NZK7tv1T9Z5RYfFTs5NKP0CXUvKhQF15E+yh1lUfwE WGIGJx+Asoz8aAGFJS2n0VTb9ZwuZB6AOw6hp1B0mp1k3UooW3qjpmA971QD5judjv7Q REQqtUZsrs5Kxd9rXgm4O23pmZ7SNnO3a7EzknQgfRyDj0Ix6ibtlht794MH3hRKUd99 BWIiYimBqxmNohuRkbKuaMHgPWN69EOuzv5zQnwgpQO1Xr6+dLVx4I2IhFMAcR+6LkO9 m6hA== X-Gm-Message-State: AOAM533GVzwdySzDax/xcfSROkY53J1OhMNK5d1TiHdskQxuHkFBUkfc q9htY6x3j1ifo/WNca1+zZahQXuulLk= X-Google-Smtp-Source: ABdhPJz9xMY4lzUiGmJaRyonqXvPkugC64SSxERdxX97HfmgdbcMS/Nz3L/j8BojFM/25KwBJQJasA== X-Received: by 2002:a02:c004:: with SMTP id y4mr1676454jai.81.1591770724147; Tue, 09 Jun 2020 23:32:04 -0700 (PDT) Received: from localhost.localdomain (user-12l2dpj.cable.mindspring.com. [69.81.55.51]) by smtp.gmail.com with ESMTPSA id f22sm8497868iob.18.2020.06.09.23.32.03 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Jun 2020 23:32:03 -0700 (PDT) From: Eric Sunshine To: git@vger.kernel.org Cc: Duy Nguyen , =?utf-8?q?Jonathan_M=C3=BCller?= , Shourya Shukla , Junio C Hamano , Ramsay Jones , Eric Sunshine Subject: [PATCH v2 7/7] worktree: make "move" refuse to move atop missing registered worktree Date: Wed, 10 Jun 2020 02:30:49 -0400 Message-Id: <20200610063049.74666-8-sunshine@sunshineco.com> X-Mailer: git-send-email 2.27.0.90.gabb59f83a2 In-Reply-To: <20200610063049.74666-1-sunshine@sunshineco.com> References: <20200610063049.74666-1-sunshine@sunshineco.com> MIME-Version: 1.0 Sender: git-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org "git worktree add" takes special care to avoid creating a new worktree at a location already registered to an existing worktree even if that worktree is missing (which can happen, for instance, if the worktree resides on removable media). "git worktree move", however, is not so careful when validating the destination location and will happily move the source worktree atop the location of a missing worktree. This leads to the anomalous situation of multiple worktrees being associated with the same path, which is expressly forbidden by design. For example: $ git clone foo.git $ cd foo $ git worktree add ../bar $ git worktree add ../baz $ rm -rf ../bar $ git worktree move ../baz ../bar $ git worktree list .../foo beefd00f [master] .../bar beefd00f [bar] .../bar beefd00f [baz] $ git worktree remove ../bar fatal: validation failed, cannot remove working tree: '.../bar' does not point back to '.git/worktrees/bar' Fix this shortcoming by enhancing "git worktree move" to perform the same additional validation of the destination directory as done by "git worktree add". While at it, add a test to verify that "git worktree move" won't move a worktree atop an existing (non-worktree) path -- a restriction which has always been in place but was never tested. Signed-off-by: Eric Sunshine --- Documentation/git-worktree.txt | 4 +++- builtin/worktree.c | 3 +-- t/t2403-worktree-move.sh | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt index 85d92c9761..4796c3c05e 100644 --- a/Documentation/git-worktree.txt +++ b/Documentation/git-worktree.txt @@ -126,7 +126,9 @@ OPTIONS locked working tree path, specify `--force` twice. + `move` refuses to move a locked working tree unless `--force` is specified -twice. +twice. If the destination is already assigned to some other working tree but is +missing (for instance, if `` was deleted manually), then `--force` +allows the move to proceed; use --force twice if the destination is locked. + `remove` refuses to remove an unclean working tree unless `--force` is used. To remove a locked working tree, specify `--force` twice. diff --git a/builtin/worktree.c b/builtin/worktree.c index 8fcf3f38fb..1238b6bab1 100644 --- a/builtin/worktree.c +++ b/builtin/worktree.c @@ -863,8 +863,7 @@ static int move_worktree(int ac, const char **av, const char *prefix) strbuf_trim_trailing_dir_sep(&dst); strbuf_addstr(&dst, sep); } - if (file_exists(dst.buf)) - die(_("target '%s' already exists"), dst.buf); + check_candidate_path(dst.buf, force, worktrees, "move"); validate_no_submodules(wt); diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh index 939d18d728..a4e1a178e0 100755 --- a/t/t2403-worktree-move.sh +++ b/t/t2403-worktree-move.sh @@ -112,6 +112,27 @@ test_expect_success 'move locked worktree (force)' ' git worktree move --force --force flump ploof ' +test_expect_success 'refuse to move worktree atop existing path' ' + >bobble && + git worktree add --detach beeble && + test_must_fail git worktree move beeble bobble +' + +test_expect_success 'move atop existing but missing worktree' ' + git worktree add --detach gnoo && + git worktree add --detach pneu && + rm -fr pneu && + test_must_fail git worktree move gnoo pneu && + git worktree move --force gnoo pneu && + + git worktree add --detach nu && + git worktree lock nu && + rm -fr nu && + test_must_fail git worktree move pneu nu && + test_must_fail git worktree --force move pneu nu && + git worktree move --force --force pneu nu +' + test_expect_success 'move a repo with uninitialized submodule' ' git init withsub && (