From patchwork Thu Nov 25 08:39:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638669 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B96B7C433F5 for ; Thu, 25 Nov 2021 08:41:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353564AbhKYIob (ORCPT ); Thu, 25 Nov 2021 03:44:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38350 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353354AbhKYImb (ORCPT ); Thu, 25 Nov 2021 03:42:31 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4467AC06175A for ; Thu, 25 Nov 2021 00:39:20 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id a9so9883699wrr.8 for ; Thu, 25 Nov 2021 00:39:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=VXX2CU3k0Z32m3gnSDBpkEW1vXu+aZ0opDUrWO9BhnM=; b=ci6ICVkVlde59Yr2X2oiK+88spNTXnRER4E0BQGZroF2r8eFeOOJPey5FWY0FlC7pZ DAI2+lwkiHS2cj23EawWPtmFcqY2OUyAzoh32PcCjexAKFEImLxWorPIz5TayfzLzM6k Vn/nZbOj/tNdpC3QenZbgJrgdSwy7NMpwsulEXEsTkeCXo3d9JLMNLTLMbmxgdFPTDqx 7ymcs1243DuU5NnXXTCQO1opARK9D+KnQ17FJJFv3TtKtgG01rB+Q3xV/lpk603tkQJ7 U4h2QjB9i+OI/AAUX4DdoMf4cQikxKlrtk3m4RSjUthSL2oTuQquap9B9NekY4tv9GPT nEJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=VXX2CU3k0Z32m3gnSDBpkEW1vXu+aZ0opDUrWO9BhnM=; b=H9WExw3LRTxTdnB9r8rxJjroGfhSOdNAlZJRYymX184vVqLevQzCXCBRkodWwngT1f FWBpM4tirCBP49MRxXKjtwX2HgQGHl0XUO9yQm/9rNPYvKyd3DPsZIVsdleSBfVmzV/u C2d0hvYgHplRheEExbCWDqaomQFqLbpEsAzhrrPO1cGKmkNgJ6//sGcnxf3jxAOxtz4s yWarIT/sXy8rowpKOp0KQC1kAXqGJnZ0H9ABizk6WKNxViS7PmBf5lSsmHZ8Ssh3mA/v M+QPj0m1nKLcdXrDsHns+Phn5dJJYs2pvDnBtbTsl1fA7VeemvszlOWFp/km4FPliSwg v90w== X-Gm-Message-State: AOAM533gIJvAB/EralDWZCE9iMS/GRr1q1QMp93hOwhDyKajlpTzTrjj fX8kHy55rB3gB4kUDigsKQI/SBGlGXA= X-Google-Smtp-Source: ABdhPJyCSl5U+U1iejJrN7322gYP0qOd9/Aco4gEZjABLtuLdkrF2qc2GIDsdXNgT105EBysgmpLGg== X-Received: by 2002:adf:fbc5:: with SMTP id d5mr4927930wrs.291.1637829558661; Thu, 25 Nov 2021 00:39:18 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id e3sm2198431wrp.8.2021.11.25.00.39.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:18 -0800 (PST) Message-Id: <38a120f5c0379daabc1f9730039ff7166037410d.1637829556.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:08 +0000 Subject: [PATCH v2 1/9] t2501: add various tests for removing the current working directory Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Numerous commands will remove empty working directories, especially if they are in the way of placing needed files. That is normally fine, but removing the current working directory can cause confusion for the user when they run subsequent commands. For example, after one git process has removed the current working directory, git status/log/diff will all abort with the message: fatal: Unable to read current working directory: No such file or directory Since there are several code paths that can result in the current working directory being removed, add several tests of various different codepaths that check for the behavior we would instead like to see. This include a number of new error messages that we will be adding in subsequent commits as we implement the desired checks. Signed-off-by: Elijah Newren --- t/t2501-cwd-empty.sh | 255 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100755 t/t2501-cwd-empty.sh diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh new file mode 100755 index 00000000000..5dfb456a691 --- /dev/null +++ b/t/t2501-cwd-empty.sh @@ -0,0 +1,255 @@ +#!/bin/sh + +test_description='Test handling of the current working directory becoming empty' + +. ./test-lib.sh + +test_expect_success setup ' + test_commit init && + mkdir subdir && + test_commit subdir/file && + + git branch fd_conflict && + + mkdir -p foo/bar && + test_commit foo/bar/baz && + + git revert HEAD && + git tag reverted && + + git checkout fd_conflict && + git rm subdir/file.t && + echo not-a-directory >dirORfile && + git add dirORfile && + git commit -m dirORfile +' + +test_expect_failure 'checkout does not clean cwd incidentally' ' + git checkout foo/bar/baz && + test_path_is_dir foo/bar && + + ( + cd foo && + git checkout init && + cd .. + ) && + test_path_is_missing foo/bar/baz && + test_path_is_missing foo/bar && + test_path_is_dir foo +' + +test_expect_failure 'checkout fails if cwd needs to be removed' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + mkdir dirORfile && + ( + cd dirORfile && + + test_must_fail git checkout fd_conflict 2>../error && + grep "Refusing to remove the current working directory" ../error + ) && + + test_path_is_dir dirORfile +' + +test_expect_failure 'reset --hard does not clean cwd incidentally' ' + git checkout foo/bar/baz && + test_path_is_dir foo/bar && + + ( + cd foo && + git reset --hard init && + cd .. + ) && + test_path_is_missing foo/bar/baz && + test_path_is_missing foo/bar && + test_path_is_dir foo +' + +test_expect_failure 'reset --hard fails if cwd needs to be removed' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + mkdir dirORfile && + ( + cd dirORfile && + + test_must_fail git reset --hard fd_conflict 2>../error && + grep "Refusing to remove.*the current working directory" ../error + ) && + + test_path_is_dir dirORfile +' + +test_expect_failure 'merge does not remove cwd incidentally' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + ( + cd subdir && + git merge fd_conflict + ) && + + test_path_is_missing subdir/file.t && + test_path_is_dir subdir +' + +test_expect_failure 'merge fails if cwd needs to be removed' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + mkdir dirORfile && + ( + cd dirORfile && + test_must_fail git merge fd_conflict 2>../error && + grep "Refusing to remove the current working directory" ../error + ) && + + test_path_is_dir dirORfile +' + +test_expect_failure 'cherry-pick does not remove cwd incidentally' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + ( + cd subdir && + git cherry-pick fd_conflict + ) && + + test_path_is_missing subdir/file.t && + test_path_is_dir subdir +' + +test_expect_failure 'cherry-pick fails if cwd needs to be removed' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + mkdir dirORfile && + ( + cd dirORfile && + test_must_fail git cherry-pick fd_conflict 2>../error && + grep "Refusing to remove the current working directory" ../error + ) && + + test_path_is_dir dirORfile +' + +test_expect_failure 'rebase does not remove cwd incidentally' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + ( + cd subdir && + git rebase foo/bar/baz fd_conflict + ) && + + test_path_is_missing subdir/file.t && + test_path_is_dir subdir +' + +test_expect_failure 'rebase fails if cwd needs to be removed' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + mkdir dirORfile && + ( + cd dirORfile && + test_must_fail git rebase foo/bar/baz fd_conflict 2>../error && + grep "Refusing to remove the current working directory" ../error + ) && + + test_path_is_dir dirORfile +' + +test_expect_failure 'revert does not remove cwd incidentally' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + ( + cd subdir && + git revert subdir/file + ) && + + test_path_is_missing subdir/file.t && + test_path_is_dir subdir +' + +test_expect_failure 'revert fails if cwd needs to be removed' ' + git checkout fd_conflict && + git revert HEAD && + test_when_finished "git clean -fdx" && + + mkdir dirORfile && + ( + cd dirORfile && + test_must_fail git revert HEAD 2>../error && + grep "Refusing to remove the current working directory" ../error + ) && + + test_path_is_dir dirORfile +' + +test_expect_failure 'rm does not remove cwd incidentally' ' + test_when_finished "git reset --hard" && + git checkout foo/bar/baz && + + ( + cd foo && + git rm bar/baz.t + ) && + + test_path_is_missing foo/bar/baz && + test_path_is_missing foo/bar && + test_path_is_dir foo +' + +test_expect_failure 'apply does not remove cwd incidentally' ' + test_when_finished "git reset --hard" && + git checkout foo/bar/baz && + + ( + cd subdir && + git diff subdir/file init | git apply + ) && + + test_path_is_missing subdir/file.t && + test_path_is_dir subdir +' + +test_expect_failure 'clean does not remove cwd incidentally' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + mkdir empty && + mkdir untracked && + >untracked/random && + ( + cd untracked && + git clean -fd -e warnings :/ >../warnings && + grep "Refusing to remove current working directory" ../warnings + ) && + + test_path_is_missing empty && + test_path_is_missing untracked/random && + test_path_is_dir untracked +' + +test_expect_failure 'stash does not remove cwd incidentally' ' + git checkout foo/bar/baz && + test_when_finished "git clean -fdx" && + + mkdir untracked && + >untracked/random && + ( + cd untracked && + git stash --include-untracked && + git status + ) && + + test_path_is_missing untracked/random && + test_path_is_dir untracked +' + +test_done From patchwork Thu Nov 25 08:39:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638673 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6071CC433FE for ; Thu, 25 Nov 2021 08:41:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353579AbhKYIod (ORCPT ); Thu, 25 Nov 2021 03:44:33 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38358 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353356AbhKYImc (ORCPT ); Thu, 25 Nov 2021 03:42:32 -0500 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 40690C06175C for ; Thu, 25 Nov 2021 00:39:21 -0800 (PST) Received: by mail-wm1-x329.google.com with SMTP id y196so4843960wmc.3 for ; Thu, 25 Nov 2021 00:39:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=8XVljRNRP03QkD5N2mWUjNprvwcPNj5TXePdLPaYnmk=; b=XqMI5AHQt3U67JUkk7ph7AhGPTqJKxCOatV1wpx87GsfW16ipUCQXbNaX9WxiquPyo 2d7V282nhWlm/OAbpofn53sIjTApFF2yv68c9tPaANywIO14YWyO5L99YnAy3B3/LPjm I+PW94YmEGE+8bVH/6pZXJ5F77rssnxcnpTMP9B2CTeKjqcJ91T4HxAqwOx4woWdZuoD Q0IA/VJC6ardWmffot+rSQQumUHPVjowD82XS/qG9DhYppXcWNhjFafvtM1Eldbqbo5E paplIf3DDmP2g3qlsN/jcnjK2GS60TjswYiqJddZ7SXyO/J2ikH10X6irbiEVv7vs9qq dePQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=8XVljRNRP03QkD5N2mWUjNprvwcPNj5TXePdLPaYnmk=; b=4/T2LUO5LHeCGm4RV16PGSQywNOo3kjFX1cO08DMdeZv1BwqTgrzPM3q5HQw7gJJ1W M74LJLRvAWnVInFuVF4CmOtmC/pn4wtXrOGTuYAyd1BrxcI0zT0iI94kelvgC3NH+QAh FqwPtFq7a9jrhVyaS3mHTlDll+oQZ98847FXjFHcgO3KAsPIn/Emtx//5rqVnzkHaLOq Y+gjnjjUrl1fSjwpDPJVZ+wujS9TChfYKmNtEJBFdatxTeMuL1IrgyHSflGuSj8F1nBT GI8DO0KHeVgaaFSAQt/sxXy6E7fME5iKnvBmoAyj2cKzUmZ8NpLjIxnYAk4Mp/12roQ3 UBjQ== X-Gm-Message-State: AOAM531e91U/FIBNIQI/0aa5PkfYsKD+stdQDvUpmwaOK2nZyuGcXT5W 5Wz6A7zbzr0KHOoyNOFDmSRJwUU9PZo= X-Google-Smtp-Source: ABdhPJy92fiTDQlzJmk8x57yZGQvlyC8cfyE4upmO+UHua/dR5j3PJCfLxBxwEJTyYWro7t9ZMnF4g== X-Received: by 2002:a05:600c:4154:: with SMTP id h20mr5046610wmm.189.1637829559565; Thu, 25 Nov 2021 00:39:19 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id h18sm2435900wre.46.2021.11.25.00.39.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:19 -0800 (PST) Message-Id: In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:09 +0000 Subject: [PATCH v2 2/9] setup: introduce startup_info->original_cwd Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Removing the current working directory causes all subsequent git commands run from that directory to get confused and fail with a message about being unable to read the current working directory: $ git status fatal: Unable to read current working directory: No such file or directory Non-git commands likely have similar warnings or even errors, e.g. $ bash -c 'echo hello' shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory hello This confuses end users, particularly since the command they get the error from is not the one that caused the problem; the problem came from the side-effect of some previous command. We would like to avoid removing the current working directory of our parent process; towards this end, introduce a new variable, startup_info->original_cwd, that tracks the current working directory that we inherited from our parent process. For convenience of later comparisons, we prefer that this new variable store a path relative to the toplevel working directory (thus much like 'prefix'), except without the trailing slash. Subsequent commits will make use of this new variable. Signed-off-by: Elijah Newren --- cache.h | 1 + git.c | 2 ++ setup.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/cache.h b/cache.h index eba12487b99..d7903c65b57 100644 --- a/cache.h +++ b/cache.h @@ -1834,6 +1834,7 @@ void overlay_tree_on_index(struct index_state *istate, struct startup_info { int have_repository; const char *prefix; + const char *original_cwd; }; extern struct startup_info *startup_info; diff --git a/git.c b/git.c index 5ff21be21f3..2c98ab48936 100644 --- a/git.c +++ b/git.c @@ -866,6 +866,8 @@ int cmd_main(int argc, const char **argv) trace_command_performance(argv); + startup_info->original_cwd = xgetcwd(); + /* * "git-xxxx" is the same as "git xxxx", but we obviously: * diff --git a/setup.c b/setup.c index 347d7181ae9..f30657723ea 100644 --- a/setup.c +++ b/setup.c @@ -432,6 +432,54 @@ void setup_work_tree(void) initialized = 1; } +static void setup_original_cwd(void) +{ + struct strbuf tmp = STRBUF_INIT; + const char *worktree = NULL; + int offset = -1; + + /* + * startup_info->original_cwd wass set early on in cmd_main(), unless + * we're an auxiliary tool like git-remote-http or test-tool. + */ + if (!startup_info->original_cwd) + return; + + /* + * startup_info->original_cwd points to the current working + * directory we inherited from our parent process, which is a + * directory we want to avoid incidentally removing. + * + * For convience, we would like to have the path relative to the + * worktree instead of an absolute path. + * + * Yes, startup_info->original_cwd is usually the same as 'prefix', + * but differs in two ways: + * - prefix has a trailing '/' + * - if the user passes '-C' to git, that modifies the prefix but + * not startup_info->original_cwd. + */ + + /* Normalize the directory */ + strbuf_realpath(&tmp, startup_info->original_cwd, 1); + free((char*)startup_info->original_cwd); + startup_info->original_cwd = strbuf_detach(&tmp, NULL); + + /* Find out if this is in the worktree */ + worktree = get_git_work_tree(); + if (worktree) + offset = dir_inside_of(startup_info->original_cwd, worktree); + if (offset >= 0) { + /* + * original_cwd was inside worktree; precompose it just as + * we do prefix so that built up paths will match + */ + startup_info->original_cwd = \ + precompose_string_if_needed(startup_info->original_cwd + + offset); + } +} + static int read_worktree_config(const char *var, const char *value, void *vdata) { struct repository_format *data = vdata; @@ -1330,6 +1378,7 @@ const char *setup_git_directory_gently(int *nongit_ok) setenv(GIT_PREFIX_ENVIRONMENT, "", 1); } + setup_original_cwd(); strbuf_release(&dir); strbuf_release(&gitdir); From patchwork Thu Nov 25 08:39:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638675 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51D4CC433F5 for ; Thu, 25 Nov 2021 08:41:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353583AbhKYIog (ORCPT ); Thu, 25 Nov 2021 03:44:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38364 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353361AbhKYImd (ORCPT ); Thu, 25 Nov 2021 03:42:33 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C409C061761 for ; Thu, 25 Nov 2021 00:39:22 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id u18so9898628wrg.5 for ; Thu, 25 Nov 2021 00:39:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=pGZm9gqf6Zg1QWoZPxdqgWYYWEoJTRxsD2IfU0/75HQ=; b=gum124UDEpNlfiJL75IXehel0e1kEf7DHoN8ESAmYnhVYhjC813dWfIUDV+9OsyT5S LpY/nmQE0lxMCzP3e1FZ1TVta/lMhf+WJEOjbKN7SVlpLJuxS40fK9zuas3MSZOP/JwU QORfSytySurL3XF73u1hFxL0FVRwLMQABildu865awVDLyBQgF9+LqlZzidzkBxzIo5G FTJCCFCiexASX+MTrXw4TXKKA3SKtrSCNDDIr00jzeBWXcbnUl1DVDV5fd8+uygRQG8e B5IwbNnc5vlNwzxWMLvGltPOMaJO17hdj9O6Wjy7y6z6CY59YHaKxsAIkJhXcBjjjKtg YF3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=pGZm9gqf6Zg1QWoZPxdqgWYYWEoJTRxsD2IfU0/75HQ=; b=hfDS0UqokzVAQvB1KOycYDZhWljvobtXQUmYpoNx4UFvTw683vBGy9w1wyKK1Cy5vo 7oRYy3JDuPgqWb5w8fPCfmJ5D1tGAk1Voh94MPXuwbtR0v9Si3rk/d9AFCMTzQFS3XGZ 1TfiT/UW2aDWwo0q6I5bc74Z5f2N19p6qxtSEqPbIY97mbK1QaWZbsjUddJ+DiWGnceT BwYS3vNRWwJGUNPenVUaeichm35XQ71ddpNU0X9B5fvMKuZVuJ/z87x/ibrR9yKO4gW0 +4/JBLWV4WNsTAxSIuOMOZkSIQDcHkOYcfpzuCKXhUt8+aW8zK8581uT/LdyIs3DIXx2 WZoQ== X-Gm-Message-State: AOAM532a5mu4jXKuMHZ7szBTgHvYqps17VwcDvbCoBx2NHXmYbMhl0Mb 60OKZACAD7EeP1LaWy9Bdl4PsJT+jPo= X-Google-Smtp-Source: ABdhPJwLvrZQ4nZMbozk2h/vxBYyJ75YT3nzKBHx7yJKMEvpxyscVUB9rRL1t3RFVPjBzxt9ic91uA== X-Received: by 2002:adf:9bc4:: with SMTP id e4mr4609147wrc.476.1637829560521; Thu, 25 Nov 2021 00:39:20 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id o1sm2139077wrn.63.2021.11.25.00.39.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:20 -0800 (PST) Message-Id: In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:10 +0000 Subject: [PATCH v2 3/9] unpack-trees: refuse to remove startup_info->original_cwd Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren In the past, when a directory needs to be removed to make room for a file, we have always errored out when that directory contains any untracked (but not ignored) files. Add an extra condition on that: also error out if the directory is the current working directory we inherited from our parent process. Signed-off-by: Elijah Newren --- t/t2501-cwd-empty.sh | 10 +++++----- unpack-trees.c | 17 +++++++++++++---- unpack-trees.h | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index 5dfb456a691..212676d71c3 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -38,7 +38,7 @@ test_expect_failure 'checkout does not clean cwd incidentally' ' test_path_is_dir foo ' -test_expect_failure 'checkout fails if cwd needs to be removed' ' +test_expect_success 'checkout fails if cwd needs to be removed' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && @@ -95,7 +95,7 @@ test_expect_failure 'merge does not remove cwd incidentally' ' test_path_is_dir subdir ' -test_expect_failure 'merge fails if cwd needs to be removed' ' +test_expect_success 'merge fails if cwd needs to be removed' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && @@ -122,7 +122,7 @@ test_expect_failure 'cherry-pick does not remove cwd incidentally' ' test_path_is_dir subdir ' -test_expect_failure 'cherry-pick fails if cwd needs to be removed' ' +test_expect_success 'cherry-pick fails if cwd needs to be removed' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && @@ -149,7 +149,7 @@ test_expect_failure 'rebase does not remove cwd incidentally' ' test_path_is_dir subdir ' -test_expect_failure 'rebase fails if cwd needs to be removed' ' +test_expect_success 'rebase fails if cwd needs to be removed' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && @@ -176,7 +176,7 @@ test_expect_failure 'revert does not remove cwd incidentally' ' test_path_is_dir subdir ' -test_expect_failure 'revert fails if cwd needs to be removed' ' +test_expect_success 'revert fails if cwd needs to be removed' ' git checkout fd_conflict && git revert HEAD && test_when_finished "git clean -fdx" && diff --git a/unpack-trees.c b/unpack-trees.c index 89ca95ce90b..6bc16f3a714 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -36,6 +36,9 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_WARNING_TYPES] = { /* ERROR_NOT_UPTODATE_DIR */ "Updating '%s' would lose untracked files in it", + /* ERROR_CWD_IN_THE_WAY */ + "Refusing to remove '%s' since it is the current working directory.", + /* ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN */ "Untracked working tree file '%s' would be overwritten by merge.", @@ -131,6 +134,9 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, msgs[ERROR_NOT_UPTODATE_DIR] = _("Updating the following directories would lose untracked files in them:\n%s"); + msgs[ERROR_CWD_IN_THE_WAY] = + _("Refusing to remove the current working directory:\n%s"); + if (!strcmp(cmd, "checkout")) msg = advice_enabled(ADVICE_COMMIT_BEFORE_MERGE) ? _("The following untracked working tree files would be removed by checkout:\n%%s" @@ -2146,10 +2152,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce, cnt++; } - /* - * Then we need to make sure that we do not lose a locally - * present file that is not ignored. - */ + /* Do not lose a locally present file that is not ignored. */ pathbuf = xstrfmt("%.*s/", namelen, ce->name); memset(&d, 0, sizeof(d)); @@ -2160,6 +2163,12 @@ static int verify_clean_subdirectory(const struct cache_entry *ce, free(pathbuf); if (i) return add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name); + + /* Do not lose startup_info->original_cwd */ + if (startup_info->original_cwd && + !strcmp(startup_info->original_cwd, ce->name)) + return add_rejected_path(o, ERROR_CWD_IN_THE_WAY, ce->name); + return cnt; } diff --git a/unpack-trees.h b/unpack-trees.h index 71ffb7eeb0c..efb9edfbb27 100644 --- a/unpack-trees.h +++ b/unpack-trees.h @@ -19,6 +19,7 @@ enum unpack_trees_error_types { ERROR_WOULD_OVERWRITE = 0, ERROR_NOT_UPTODATE_FILE, ERROR_NOT_UPTODATE_DIR, + ERROR_CWD_IN_THE_WAY, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, ERROR_WOULD_LOSE_UNTRACKED_REMOVED, ERROR_BIND_OVERLAP, From patchwork Thu Nov 25 08:39:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638677 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D87ECC433F5 for ; Thu, 25 Nov 2021 08:41:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353602AbhKYIoj (ORCPT ); Thu, 25 Nov 2021 03:44:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38368 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353366AbhKYIme (ORCPT ); Thu, 25 Nov 2021 03:42:34 -0500 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5AE88C061763 for ; Thu, 25 Nov 2021 00:39:23 -0800 (PST) Received: by mail-wr1-x42d.google.com with SMTP id u18so9898723wrg.5 for ; Thu, 25 Nov 2021 00:39:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=OMvVoWV6a4igUhCPJwdvCNYU8tR72Q0wviYGWDVUkTg=; b=UiRd/uz1EjQdLQ/By0nqTpaT19/MexBx3y8XYcLL/wF4avhUi77B1LCiwuaz9JTQ31 ww7KMPg+GPWZZYaTVD4nQIG3eRp2t2IX/LN79JnmR4FVdD8EwNAJZUwI0nfa0hLexo2u jKia48rVlIw2n00U24M7XdnUCWYGV9MkoUHjqbTXpug7HPMb0YRm9HUsUwXQqTRj2woD gCBZkYgjrhIVN9IL30YTt3+2GZhuebNyLc2suA72vdmJnYXRwwMZx8V86Tp9tR+9Odxv njTlMGzeWBVIRT92u9RAp7xqW1fU9mmynpkoj5GDS/dLcivHo9/IecthMNpNsX5LUMCv MRdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=OMvVoWV6a4igUhCPJwdvCNYU8tR72Q0wviYGWDVUkTg=; b=eG7PA14B2fMGy7IuxlStUkzu1iCnPPq98D6FTwslC8pWP151R1c6nPXwwbIIfEWfyG 53xruHuMtzw0PvyKmOGkxO3mgttViIeph/qWJlWjTZJQAFRiglDtQRZIqEHsDt87da6P 1LHWDEg193EKwhy90bSGAx/kiPBHFoZ4pZOtX8Q2YPL81aBm5ZJSEeD/XUkflE/E9z8o 2FUagZZIkrlGABqlGs5ugN/ouZ9yhDV2gJ4jdLAnOfDnlNfRSgnKTFdCpDB9ucDpvZ4X EBSW9z2AZ64Qbvz4abLWRSJVLWmPFaHbtYFSJkD7/IqladNDp5jApTZSmVY7dYdIk0E6 iZng== X-Gm-Message-State: AOAM532di+g4mu/Kl90XhEN5mKbil4/xMyiM+JwPIQBL/6vAGpuo1Cd7 MRiVktaQhVO9qR3cqj1vGVBVSv9Upt8= X-Google-Smtp-Source: ABdhPJz4JdvhYSz3ZxrPlFnu/yMgB9noQD72NuzbQl6IECBGGvdgdF8HPOBM5spKHM/PIui77AwuxA== X-Received: by 2002:adf:8bda:: with SMTP id w26mr4561841wra.440.1637829561518; Thu, 25 Nov 2021 00:39:21 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id h204sm2423637wmh.33.2021.11.25.00.39.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:21 -0800 (PST) Message-Id: In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:11 +0000 Subject: [PATCH v2 4/9] unpack-trees: add special cwd handling Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren When running commands such as `git reset --hard` from a subdirectory, if that subdirectory is in the way of adding needed files, bail with an error message. Note that this change looks kind of like it duplicates the new lines of code from the previous commit in verify_clean_subdirectory(). However, when we are preserving untracked files, we would rather any error messages about untracked files being in the way take precedence over error messages about a subdirectory that happens to be the_original_cwd being in the way. But in the UNPACK_RESET_OVERWRITE_UNTRACKED case, there is no untracked checking to be done, so we simply add a special case near the top of verify_absent_1. Signed-off-by: Elijah Newren --- t/t2501-cwd-empty.sh | 2 +- unpack-trees.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index 212676d71c3..526d8ec2ee3 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -67,7 +67,7 @@ test_expect_failure 'reset --hard does not clean cwd incidentally' ' test_path_is_dir foo ' -test_expect_failure 'reset --hard fails if cwd needs to be removed' ' +test_expect_success 'reset --hard fails if cwd needs to be removed' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && diff --git a/unpack-trees.c b/unpack-trees.c index 6bc16f3a714..5852807d2fb 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -2261,10 +2261,19 @@ static int verify_absent_1(const struct cache_entry *ce, int len; struct stat st; - if (o->index_only || !o->update || - o->reset == UNPACK_RESET_OVERWRITE_UNTRACKED) + if (o->index_only || !o->update) return 0; + if (o->reset == UNPACK_RESET_OVERWRITE_UNTRACKED) { + /* Avoid nuking startup_info->original_cwd... */ + if (startup_info->original_cwd && + !strcmp(startup_info->original_cwd, ce->name)) + return add_rejected_path(o, ERROR_CWD_IN_THE_WAY, + ce->name); + /* ...but nuke anything else. */ + return 0; + } + len = check_leading_path(ce->name, ce_namelen(ce), 0); if (!len) return 0; From patchwork Thu Nov 25 08:39:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638679 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 223DAC433EF for ; Thu, 25 Nov 2021 08:41:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353630AbhKYIoo (ORCPT ); Thu, 25 Nov 2021 03:44:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37932 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353370AbhKYImk (ORCPT ); Thu, 25 Nov 2021 03:42:40 -0500 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0A4B8C0613D7 for ; Thu, 25 Nov 2021 00:39:26 -0800 (PST) Received: by mail-wr1-x432.google.com with SMTP id j3so9940907wrp.1 for ; Thu, 25 Nov 2021 00:39:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=JsrOSNc7nQWW8eYxfSa7bNB/249vTV4VJg/WfpGDcBQ=; b=CcwvBo3M8F3CmpGYfvSce12ACBnJUWbgDNWGq+5mU/vJgL37KBtNRqScDbpeEcByll aSORt9J59TPKvlEQ5G1lnqEXA+wA3SWzTUzZheOQIVpMUaVjnlQkcX6zqNwoDlad+V5U kArDDBlsCE/SdbwZ06qTzyippWwlnHwiegHSCQ67Dmk7otxx3rX13FhCmSO7gvOnGajM 95KhvChXgPolEB1RvhfDyoIZPDc51hQusEW/gO7QpofyEYLWi2MD5HoBsGVonwn25TtI wBYFs/7NIEiGmv/JrSBTHXSRjZdBG9mNsANcrTX6knY+owbaLAHXYe2y5AtLWYkpyNQm N3OQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=JsrOSNc7nQWW8eYxfSa7bNB/249vTV4VJg/WfpGDcBQ=; b=mgLiMVdNRxX46KOGFkvistv38FeflaA8GfSb5EeM2Nq69kCigY5B1p2zuNTEVSVvKw 34Jm+SEcB3+6eoSpQXbCPHPC/UddxD43EPed54HH8rt2e6oSYlU5M6u8/Z5OcG4+cwxg BZaSOYJfqLEpIuTFE0dPO4WH2XqZ5QwWm0yXpoM3Z1TZp4aRIgPgPd9lSZ+ZU9/ha/ea GhVv9QWKcHy8KJlfQz4S4dbIwWsKGarYDoX0baeM6mQGAkUOTdY0VUtuJkxgu+2TqbvN 9DK6kfGCuiXbGRnd+h2A5jDt0dLFB7Ga/FpFyFJ51pjDFo96ErUzNy3GQv81ClLv+Jqn p8CQ== X-Gm-Message-State: AOAM531ShsiBzKlbfyc6C0N1rknCm+7tXomdPSi80W+wgTTsd9yuX7TK OXiOWR/MrtZKyE5bqs50cPONfRCwrTk= X-Google-Smtp-Source: ABdhPJxQtBd7IyjOWIo/siRPXY9pwFcbgzR81+HAEAb+X1ZB/iXRtd2eYa+HttKrHSvsrqV9Oc/DHg== X-Received: by 2002:adf:c406:: with SMTP id v6mr4625991wrf.570.1637829564420; Thu, 25 Nov 2021 00:39:24 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id x1sm2179277wru.40.2021.11.25.00.39.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:22 -0800 (PST) Message-Id: <46728f74ea175a33ef592319893ed32146229b33.1637829556.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:12 +0000 Subject: [PATCH v2 5/9] symlinks: do not include startup_info->original_cwd in dir removal Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren symlinks has a pair of schedule_dir_for_removal() and remove_scheduled_dirs() functions that ensure that directories made empty by removing other files also themselves get removed. However, we want to exclude startup_info->original_cwd and leave it around. This avoids the user getting confused by subsequent git commands (and non-git commands) that would otherwise report confusing messages about being unable to read the current working directory. Signed-off-by: Elijah Newren --- symlinks.c | 8 +++++++- t/t2501-cwd-empty.sh | 12 ++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/symlinks.c b/symlinks.c index 5232d02020c..c667baa949b 100644 --- a/symlinks.c +++ b/symlinks.c @@ -279,7 +279,9 @@ static void do_remove_scheduled_dirs(int new_len) { while (removal.len > new_len) { removal.buf[removal.len] = '\0'; - if (rmdir(removal.buf)) + if ((startup_info->original_cwd && + !strcmp(removal.buf, startup_info->original_cwd)) || + rmdir(removal.buf)) break; do { removal.len--; @@ -293,6 +295,10 @@ void schedule_dir_for_removal(const char *name, int len) { int match_len, last_slash, i, previous_slash; + if (startup_info->original_cwd && + !strcmp(name, startup_info->original_cwd)) + return; /* Do not remove the current working directory */ + match_len = last_slash = i = longest_path_match(name, len, removal.buf, removal.len, &previous_slash); diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index 526d8ec2ee3..b92e1a9bb16 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -24,7 +24,7 @@ test_expect_success setup ' git commit -m dirORfile ' -test_expect_failure 'checkout does not clean cwd incidentally' ' +test_expect_success 'checkout does not clean cwd incidentally' ' git checkout foo/bar/baz && test_path_is_dir foo/bar && @@ -53,7 +53,7 @@ test_expect_success 'checkout fails if cwd needs to be removed' ' test_path_is_dir dirORfile ' -test_expect_failure 'reset --hard does not clean cwd incidentally' ' +test_expect_success 'reset --hard does not clean cwd incidentally' ' git checkout foo/bar/baz && test_path_is_dir foo/bar && @@ -82,7 +82,7 @@ test_expect_success 'reset --hard fails if cwd needs to be removed' ' test_path_is_dir dirORfile ' -test_expect_failure 'merge does not remove cwd incidentally' ' +test_expect_success 'merge does not remove cwd incidentally' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && @@ -109,7 +109,7 @@ test_expect_success 'merge fails if cwd needs to be removed' ' test_path_is_dir dirORfile ' -test_expect_failure 'cherry-pick does not remove cwd incidentally' ' +test_expect_success 'cherry-pick does not remove cwd incidentally' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && @@ -136,7 +136,7 @@ test_expect_success 'cherry-pick fails if cwd needs to be removed' ' test_path_is_dir dirORfile ' -test_expect_failure 'rebase does not remove cwd incidentally' ' +test_expect_success 'rebase does not remove cwd incidentally' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && @@ -163,7 +163,7 @@ test_expect_success 'rebase fails if cwd needs to be removed' ' test_path_is_dir dirORfile ' -test_expect_failure 'revert does not remove cwd incidentally' ' +test_expect_success 'revert does not remove cwd incidentally' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && From patchwork Thu Nov 25 08:39:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638683 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5FC02C433EF for ; Thu, 25 Nov 2021 08:42:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353806AbhKYIpT (ORCPT ); Thu, 25 Nov 2021 03:45:19 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38528 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353422AbhKYInR (ORCPT ); Thu, 25 Nov 2021 03:43:17 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE64BC0613DD for ; Thu, 25 Nov 2021 00:39:26 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id s13so9935022wrb.3 for ; Thu, 25 Nov 2021 00:39:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=dosfbg1Z3obof3TXY/qdvWfkxJgZjSOuMMd8JDUYq6Q=; b=PZePRTlS5XJ6Mo3Nvqgq8wStxW5SgqiWIbqwoCyB59rjsfKxvC7QvZ+CKSnCCYQTah K803ylbTAq2LB4k7H24HDzMeKk1dq7d9rZsLgrMxhYvASZDPMsIiPnjafg8Hf5TQDIm/ 9cyvfmaIy/1RdVeP9c9lW3SrNmqzlpq1nR7EReuBRfLwKaO9m9gujm5yHG7p4D/Xg/yZ tcWn/4MfiWpGKJtdedJw8VodIqp7B60UVXDG88fXi9I56Mw5WtupLtOeDNKG8H4kZj9Q 1t/ymmIOIh0PycwiagIN6oYHYDENXjV80d/+WEOlnkrX0x9CoEuCXi1Z07Pe+MJmaaGm 1DUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=dosfbg1Z3obof3TXY/qdvWfkxJgZjSOuMMd8JDUYq6Q=; b=qMTcTl1X0n/RYrEUopN0vWu66vsTH5pNy70NbvLZ+ZTliReksaCQchrf4kcMFidSWZ TBST/SMCysGtnuPVyEqIm4ljrZoOoOC7ZP9GEMyWcMLPiqz4FCvHoM+w5BFFzDh0vfov NbK9tpklOiH7SiuvDhISdpDAqUw6KtQzmU95XC7zazFhuboDK+GgX7UuDurWOfXmDvl9 cisdbNAsyzM8NzHarjbtkEtatDVI07fOxTthgK77DLYBhV9D2msjOFpA5uaZVxbGHhxF FnhItCwGkWe9zss3PHbBKP4nc/mh2ubNchImlWyqnRpWe3STPtaQ2H4Zzd+44fqA8Vub XK7A== X-Gm-Message-State: AOAM530VYwWSKxcBO1MfnQB2HyqokXipf9TRT7IwdZcNqREgK7+43yhJ KrxLfG1r+9unBr6nbcC9FEWFUqbkGyQ= X-Google-Smtp-Source: ABdhPJyjzZLs+tKycaPrqB+bea/23CPdesUbmh5NbGUGLRgEXCyrknRy2tMPXPkqgWTliT2t9YvUXA== X-Received: by 2002:a5d:4989:: with SMTP id r9mr4660785wrq.14.1637829565263; Thu, 25 Nov 2021 00:39:25 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id i17sm2543923wmq.48.2021.11.25.00.39.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:24 -0800 (PST) Message-Id: <01ce9444daeafe7a11265956b847f92233f5d028.1637829556.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:13 +0000 Subject: [PATCH v2 6/9] clean: do not attempt to remove startup_info->original_cwd Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Signed-off-by: Elijah Newren --- builtin/clean.c | 47 +++++++++++++++++++++++++++++++++++--------- t/t2501-cwd-empty.sh | 2 +- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/builtin/clean.c b/builtin/clean.c index 98a2860409b..68c8d593c77 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -36,6 +36,8 @@ static const char *msg_skip_git_dir = N_("Skipping repository %s\n"); static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n"); static const char *msg_warn_remove_failed = N_("failed to remove %s"); static const char *msg_warn_lstat_failed = N_("could not lstat %s\n"); +static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n"); +static const char *msg_would_skip_cwd = N_("Would refuse to remove current working directory\n"); enum color_clean { CLEAN_COLOR_RESET = 0, @@ -153,6 +155,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, { DIR *dir; struct strbuf quoted = STRBUF_INIT; + struct strbuf realpath = STRBUF_INIT; + struct strbuf real_ocwd = STRBUF_INIT; struct dirent *e; int res = 0, ret = 0, gone = 1, original_len = path->len, len; struct string_list dels = STRING_LIST_INIT_DUP; @@ -231,16 +235,39 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, strbuf_setlen(path, original_len); if (*dir_gone) { - res = dry_run ? 0 : rmdir(path->buf); - if (!res) - *dir_gone = 1; - else { - int saved_errno = errno; - quote_path(path->buf, prefix, "ed, 0); - errno = saved_errno; - warning_errno(_(msg_warn_remove_failed), quoted.buf); + /* + * Normalize path components in path->buf, e.g. change '\' to + * '/' on Windows. + */ + strbuf_realpath(&realpath, path->buf, 1); + + /* + * path and realpath are absolute; for comparison, we want + * startup_info->original_cwd to be an absolute path too. We + * can use strbuf_realpath for this. Also, if original_cwd + * started out as the empty string, then it corresponded to + * the top of the worktree, which is protected by other means + * so we just leave it blank. + */ + if (*startup_info->original_cwd) + strbuf_realpath(&real_ocwd, + startup_info->original_cwd, 1); + + if (!strbuf_cmp(&realpath, &real_ocwd)) { + printf("%s", dry_run ? _(msg_would_skip_cwd) : _(msg_skip_cwd)); *dir_gone = 0; - ret = 1; + } else { + res = dry_run ? 0 : rmdir(path->buf); + if (!res) + *dir_gone = 1; + else { + int saved_errno = errno; + quote_path(path->buf, prefix, "ed, 0); + errno = saved_errno; + warning_errno(_(msg_warn_remove_failed), quoted.buf); + *dir_gone = 0; + ret = 1; + } } } @@ -250,6 +277,8 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, printf(dry_run ? _(msg_would_remove) : _(msg_remove), dels.items[i].string); } out: + strbuf_release(&realpath); + strbuf_release(&real_ocwd); strbuf_release("ed); string_list_clear(&dels, 0); return ret; diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index b92e1a9bb16..20e1b6adede 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -218,7 +218,7 @@ test_expect_failure 'apply does not remove cwd incidentally' ' test_path_is_dir subdir ' -test_expect_failure 'clean does not remove cwd incidentally' ' +test_expect_success 'clean does not remove cwd incidentally' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && From patchwork Thu Nov 25 08:39:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638681 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 97498C433FE for ; Thu, 25 Nov 2021 08:42:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353804AbhKYIpS (ORCPT ); Thu, 25 Nov 2021 03:45:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38074 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353425AbhKYInR (ORCPT ); Thu, 25 Nov 2021 03:43:17 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AAF8BC0613F1 for ; Thu, 25 Nov 2021 00:39:27 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id b12so9906355wrh.4 for ; Thu, 25 Nov 2021 00:39:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=k8ksTLhk6dw/Y0Uea/a7jNB64e2HNpj7JfoIEHOv3Vc=; b=arL7jaLKcZ78Kf0ahtvy5qOCDNc+XSD+c/gvrvCGrptLGCfVD9YNMVDFqVi/siajqX GB7cVTJ/nFz1LSsRNIyk488Qw07D5J/EzqNOUUlHws2C2wXfV20Fnrq5zr8fLBI1jGGb Vn73EO/2VoBm4ioJ3PgErF4RxOYOUjeUaCyKfBvuAKpgZ498SHrkIRKJxy5FUryQgCSA xflFf6jtP1vbMXzVCKnMBIAvT6uFz/SzBWAXG5HhhLtkTds4xaJbp6In3wQJNEX9qXc0 +dlHMbZOzpaAI3859LsbABZ+FySLLscjDNM/y0J6t9+R0ZjsXUe96qMjIEDludRwbMYt 1t8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=k8ksTLhk6dw/Y0Uea/a7jNB64e2HNpj7JfoIEHOv3Vc=; b=myaaYalEKTz1lhfGCMmMpUDjQyJiNa4HBkcbEQEppvw0z8rBMF5LvSQOcqTKGdZLGl tF8n77+nqasGN8f3VhpK4W3Ii6b5qgfBEZg1uuk7bePxDgdonqalliLP2dl1mNmC0rB2 PjqMSj0Vdw/Zfy3u/iCL1dwQl9FhBzvrT4yl0xvzFHtmwsw9vZe917SCy/w6p74cW7UO N90z//fe8Sjgg7LOw2/3NjimOPovqpAR1P13MQQTJxs449RSerl0mQq3y0IInrF0RpCy MBba0QMVMZSIMgo8YvUSEOW9dPPnEHAEISanm6zCvN7NQhv5cNDUSXcLzMbhbtlV1v1g KUSw== X-Gm-Message-State: AOAM530pN1IdHJ91eI1ThMJJIhjHz5Qdkb+e+60QVZySaXR4fvLzpfVB 27yTFh9gcqfL/I7fDmIJ+yw2QascyfQ= X-Google-Smtp-Source: ABdhPJyLD/GhGOheJChooxoQL7zQFpRGYqrQmoXJ/Nz8vQSHErsdQ+O4W4+mt5oFdDqaI6+Pi/Iegw== X-Received: by 2002:a05:6000:11cd:: with SMTP id i13mr94568wrx.524.1637829566083; Thu, 25 Nov 2021 00:39:26 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id b188sm2260565wmd.45.2021.11.25.00.39.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:25 -0800 (PST) Message-Id: In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:14 +0000 Subject: [PATCH v2 7/9] stash: do not attempt to remove startup_info->original_cwd Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Signed-off-by: Elijah Newren --- builtin/stash.c | 6 +++++- t/t2501-cwd-empty.sh | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/builtin/stash.c b/builtin/stash.c index a0ccc8654df..50b4875980c 100644 --- a/builtin/stash.c +++ b/builtin/stash.c @@ -1485,8 +1485,12 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q struct child_process cp = CHILD_PROCESS_INIT; cp.git_cmd = 1; + if (startup_info->original_cwd && + *startup_info->original_cwd && + !is_absolute_path(startup_info->original_cwd)) + cp.dir = startup_info->original_cwd; strvec_pushl(&cp.args, "clean", "--force", - "--quiet", "-d", NULL); + "--quiet", "-d", ":/", NULL); if (include_untracked == INCLUDE_ALL_FILES) strvec_push(&cp.args, "-x"); if (run_command(&cp)) { diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index 20e1b6adede..ff4e7cd89fa 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -236,7 +236,7 @@ test_expect_success 'clean does not remove cwd incidentally' ' test_path_is_dir untracked ' -test_expect_failure 'stash does not remove cwd incidentally' ' +test_expect_success 'stash does not remove cwd incidentally' ' git checkout foo/bar/baz && test_when_finished "git clean -fdx" && From patchwork Thu Nov 25 08:39:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638685 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE368C433F5 for ; Thu, 25 Nov 2021 08:42:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352552AbhKYIpV (ORCPT ); Thu, 25 Nov 2021 03:45:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37628 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349940AbhKYInU (ORCPT ); Thu, 25 Nov 2021 03:43:20 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87B45C0613F2 for ; Thu, 25 Nov 2021 00:39:28 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id r8so9865925wra.7 for ; Thu, 25 Nov 2021 00:39:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=RGvrnPwWwB0Ncvh15JyDu5EBYtb49RovOM1fmup/hwY=; b=Jxw8Exx3ApeDH4epOZn+d+bmfMngPgjGxcQD/8Loffg23xIveUzln845Ekd0vA/AWU uej0F8hEpP1uJTURpTPVFrpBIXL2tQutqV9rF5ZfcnIswyhKYvr+4hxmeTszb0gGA8zc os7ljszn21h+CWcT6V66dl5fxAcTPdVqx/FBoK3RJWSIUKhjEVEXc5KrfYtRHnVnd/wp BCKegVjRdN/sxr52fkq0JyPl/2PszRVknE6Hivd0fcV9WaWKJyY0TY/eAHb087vKpFlN 9apWK3gCq92fx9bRWK+Q0X32x69v9+wVGjk1xcdujhx+j91RXLSubz9GDNQmYdYG14Kn I6nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=RGvrnPwWwB0Ncvh15JyDu5EBYtb49RovOM1fmup/hwY=; b=TU7nvYFTEKS3YFASAfyyqknvZRm5HCphlGjEA59WAjzyb+QJovQ1XG2gUjVQgp7Epq gBJo38iORMjnY76glnJ97kAkZf4LQr6dQ81mvbdEGZ6sksfJ/NWkEAuXH94Xz5A1aTNe XeOCrmKxDR9MZKzlUFqqiU/yu8KqKjzxle44aUEX0tkSWRQakCwaXkVVOGd46eGoR+h1 CINaSjpoV+zsbnvCyitubWoiVm78hxjfQyMcxVKAaqo38J26rCZQ9AJkNN5L/LqNs8pJ 1lQcdTJz823fL3dRKzJ/AgEkEEzI7Qu/IK9u3aJl16+vkNfIqj5qSvNPmpK/5x8Oz2s+ K+Cw== X-Gm-Message-State: AOAM532OEy5vnMKHxHiYIwRrvPbuVD9r3mOKeIOeHTRpeeNFwCaTqtTD HfiFR3yXA5iDO3eE7++3uzXqkC4JCps= X-Google-Smtp-Source: ABdhPJwFR8vdLZWO0b1liNK8K63bXsWXOt6pVCfAmfnrNEorYFfxEjjlMDWn5rzDr0nErL7HzNd+fA== X-Received: by 2002:adf:8b1e:: with SMTP id n30mr4580354wra.75.1637829566835; Thu, 25 Nov 2021 00:39:26 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id l4sm2121232wrv.94.2021.11.25.00.39.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:26 -0800 (PST) Message-Id: <1815f18592b240145000b04d19645f31ea72823e.1637829556.git.gitgitgadget@gmail.com> In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:15 +0000 Subject: [PATCH v2 8/9] dir: avoid incidentally removing the original_cwd in remove_path() Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren Modern git often tries to avoid leaving empty directories around when removing files. Originally, it did not bother. This behavior started with commit 80e21a9ed809 (merge-recursive::removeFile: remove empty directories, 2005-11-19), stating the reason simply as: When the last file in a directory is removed as the result of a merge, try to rmdir the now-empty directory. This was reimplemented in C and renamed to remove_path() in commit e1b3a2cad7 ("Build-in merge-recursive", 2008-02-07), but was still internal to merge-recursive. This trend towards removing leading empty directories continued with commit d9b814cc97f1 (Add builtin "git rm" command, 2006-05-19), which stated the reasoning as: The other question is what to do with leading directories. The old "git rm" script didn't do anything, which is somewhat inconsistent. This one will actually clean up directories that have become empty as a result of removing the last file, but maybe we want to have a flag to decide the behaviour? remove_path() in dir.c was added in 4a92d1bfb784 (Add remove_path: a function to remove as much as possible of a path, 2008-09-27), because it was noted that we had two separate implementations of the same idea AND both were buggy. It described the purpose of the function as a function to remove as much as possible of a path Why remove as much as possible? Well, at the time we probably would have said something like: * removing leading directories makes things feel tidy * removing leading directories doesn't hurt anything so long as they had no files in them. But I don't believe those reasons hold when the empty directory happens to be the current working directory we inherited from our parent process. Leaving the parent process in a deleted directory can cause user confusion when subsequent processes fail: any git command, for example, will immediately fail with fatal: Unable to read current working directory: No such file or directory Other commands may similarly get confused. Modify remove_path() so that the empty leading directories it also deletes does not include the current working directory we inherited from our parent process. I have looked through every caller of remove_path() in the current codebase to make sure that all should take this change. Signed-off-by: Elijah Newren --- dir.c | 3 +++ dir.h | 6 +++++- t/t2501-cwd-empty.sh | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/dir.c b/dir.c index 94489298f4c..97d6b71c872 100644 --- a/dir.c +++ b/dir.c @@ -3327,6 +3327,9 @@ int remove_path(const char *name) slash = dirs + (slash - name); do { *slash = '\0'; + if (startup_info->original_cwd && + !strcmp(startup_info->original_cwd, dirs)) + break; } while (rmdir(dirs) == 0 && (slash = strrchr(dirs, '/'))); free(dirs); } diff --git a/dir.h b/dir.h index 83f46c0fb4c..d6a5d03bec2 100644 --- a/dir.h +++ b/dir.h @@ -504,7 +504,11 @@ int get_sparse_checkout_patterns(struct pattern_list *pl); */ int remove_dir_recursively(struct strbuf *path, int flag); -/* tries to remove the path with empty directories along it, ignores ENOENT */ +/* + * Tries to remove the path, along with leading empty directories so long as + * those empty directories are not startup_info->original_cwd. Ignores + * ENOENT. + */ int remove_path(const char *path); int fspathcmp(const char *a, const char *b); diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index ff4e7cd89fa..4362e7b15e5 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -191,7 +191,7 @@ test_expect_success 'revert fails if cwd needs to be removed' ' test_path_is_dir dirORfile ' -test_expect_failure 'rm does not remove cwd incidentally' ' +test_expect_success 'rm does not remove cwd incidentally' ' test_when_finished "git reset --hard" && git checkout foo/bar/baz && @@ -205,7 +205,7 @@ test_expect_failure 'rm does not remove cwd incidentally' ' test_path_is_dir foo ' -test_expect_failure 'apply does not remove cwd incidentally' ' +test_expect_success 'apply does not remove cwd incidentally' ' test_when_finished "git reset --hard" && git checkout foo/bar/baz && From patchwork Thu Nov 25 08:39:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elijah Newren X-Patchwork-Id: 12638687 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A56CBC433EF for ; Thu, 25 Nov 2021 08:42:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353830AbhKYIpY (ORCPT ); Thu, 25 Nov 2021 03:45:24 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38090 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1349985AbhKYInU (ORCPT ); Thu, 25 Nov 2021 03:43:20 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5A987C0613F3 for ; Thu, 25 Nov 2021 00:39:29 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id u1so9836544wru.13 for ; Thu, 25 Nov 2021 00:39:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:in-reply-to:references:from:date:subject:fcc :content-transfer-encoding:mime-version:to:cc; bh=qJm6PilFjX46tbJSQL7+uesjaprEBsYLqIkvPEue6kM=; b=QSQz5i9Up76p4TgeUSiGkdlaN7HOOWyGvJzGIfcCmYfJ4yQs5WLcNF3VLhJ/1chkxe 53/Y938PDggPHIOaRPTVSzz3MB9Y3N30JY3J+KnVfkCrvXMHYRe+pGr1pGBo23sR9WJw 6vs6M4FYu26OCkHglnmh55S6pDGkrR3o475taB924xyxgjpEt86kJax5TfDnwaYZyL6z OCh30Rp4imiJKf4tj6P10Sq7wRWUm2SQMnJEKfCTR12fkxnFr6rBiyZlW+cVVNA/Uatg YWkRWDyLkB6s4/6K2auuR/QhEMSgzd94li6HRqguvfehnnI6/X0Rzi7s3t5mIriKxa4r okxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:in-reply-to:references:from:date :subject:fcc:content-transfer-encoding:mime-version:to:cc; bh=qJm6PilFjX46tbJSQL7+uesjaprEBsYLqIkvPEue6kM=; b=pyT83zDa53wUEdg2gM85mUMBUy43aIM6vuMik1zXl95gSHnnxKnn0gyjYlOg3BfC1u ad7IMsXVGYRkBHYH68l2aUBWne47LG8vBBVx3/CEWgjVMdEgmaf3mDUOb5Dgy9am9/pu p2Srxi2a7W17SAU8fBJx5gZ1B7xG8Gc0qGeaVlY6FNvC6WjLRGr5KYAL0LTQ8PJrr3Ok GNm5SM2o4q2SnxkgdUkyUMUumaqHSgMrskoDw+B6T4pEp5BgyiPkXhEwvB7DBJ5lt2w7 wvUKkletXD8UaCNIV5ZONNZ4qk7WilQOw38PHW1lPpYPvMmd6NvYlBXiET4kei81iUiC RQWA== X-Gm-Message-State: AOAM531jeCNp5HJIfTTLiU4J8THOMNNMnKFpBun1eXzNFQbviwGpBKJ+ bIHfzPDmBlq+t+OmV4WbLJBKgmT5MGs= X-Google-Smtp-Source: ABdhPJzvvYiMVs9nh6Jc2kn5yE5QLaopTdooL+si6MOiQB4Ro1H/JA1ZzClwYTH+5sioC+dfpCzygw== X-Received: by 2002:adf:f20f:: with SMTP id p15mr4423614wro.187.1637829567676; Thu, 25 Nov 2021 00:39:27 -0800 (PST) Received: from [127.0.0.1] ([13.74.141.28]) by smtp.gmail.com with ESMTPSA id y15sm2621342wry.72.2021.11.25.00.39.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Nov 2021 00:39:27 -0800 (PST) Message-Id: In-Reply-To: References: Date: Thu, 25 Nov 2021 08:39:16 +0000 Subject: [PATCH v2 9/9] dir: new flag to remove_dir_recurse() to spare the original_cwd Fcc: Sent MIME-Version: 1.0 To: git@vger.kernel.org Cc: Jeff King , =?utf-8?b?UmVuw6k=?= Scharfe , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason , Elijah Newren , Glen Choo , Philip Oakley , Elijah Newren , Elijah Newren Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org From: Elijah Newren From: Elijah Newren remove_dir_recurse(), and its non-static wrapper called remove_dir_recursively(), both take flags for modifying its behavior. As with the previous commits, we would generally like to protect the original_cwd, but we want to forced user commands (e.g. 'git rm -rf ...') or other special cases to remove it. Add a flag for this purpose. After reading through every caller of remove_dir_recursively() in the current codebase, there was only one that should be adjusted and that one only in a very unusual circumstance. Add a pair of new testcases to highlight that very specific case involving submodules && --git-dir && --work-tree. Signed-off-by: Elijah Newren --- builtin/rm.c | 3 ++- dir.c | 12 +++++++++--- dir.h | 3 +++ t/t2501-cwd-empty.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/builtin/rm.c b/builtin/rm.c index 3d0967cdc11..b4132e5d8ee 100644 --- a/builtin/rm.c +++ b/builtin/rm.c @@ -399,12 +399,13 @@ int cmd_rm(int argc, const char **argv, const char *prefix) if (!index_only) { int removed = 0, gitmodules_modified = 0; struct strbuf buf = STRBUF_INIT; + int flag = force ? REMOVE_DIR_PURGE_ORIGINAL_CWD : 0; for (i = 0; i < list.nr; i++) { const char *path = list.entry[i].name; if (list.entry[i].is_submodule) { strbuf_reset(&buf); strbuf_addstr(&buf, path); - if (remove_dir_recursively(&buf, 0)) + if (remove_dir_recursively(&buf, flag)) die(_("could not remove '%s'"), path); removed = 1; diff --git a/dir.c b/dir.c index 97d6b71c872..52064345a6b 100644 --- a/dir.c +++ b/dir.c @@ -3204,6 +3204,7 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) int ret = 0, original_len = path->len, len, kept_down = 0; int only_empty = (flag & REMOVE_DIR_EMPTY_ONLY); int keep_toplevel = (flag & REMOVE_DIR_KEEP_TOPLEVEL); + int purge_original_cwd = (flag & REMOVE_DIR_PURGE_ORIGINAL_CWD); struct object_id submodule_head; if ((flag & REMOVE_DIR_KEEP_NESTED_GIT) && @@ -3259,9 +3260,14 @@ static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up) closedir(dir); strbuf_setlen(path, original_len); - if (!ret && !keep_toplevel && !kept_down) - ret = (!rmdir(path->buf) || errno == ENOENT) ? 0 : -1; - else if (kept_up) + if (!ret && !keep_toplevel && !kept_down) { + if (!purge_original_cwd && + startup_info->original_cwd && + !strcmp(startup_info->original_cwd, path->buf)) + ret = -1; /* Do not remove current working directory */ + else + ret = (!rmdir(path->buf) || errno == ENOENT) ? 0 : -1; + } else if (kept_up) /* * report the uplevel that it is not an error that we * did not rmdir() our directory. diff --git a/dir.h b/dir.h index d6a5d03bec2..8e02dfb505d 100644 --- a/dir.h +++ b/dir.h @@ -495,6 +495,9 @@ int get_sparse_checkout_patterns(struct pattern_list *pl); /* Remove the contents of path, but leave path itself. */ #define REMOVE_DIR_KEEP_TOPLEVEL 04 +/* Remove the_original_cwd too */ +#define REMOVE_DIR_PURGE_ORIGINAL_CWD 0x08 + /* * Remove path and its contents, recursively. flags is a combination * of the above REMOVE_DIR_* constants. Return 0 on success. diff --git a/t/t2501-cwd-empty.sh b/t/t2501-cwd-empty.sh index 4362e7b15e5..8da3fb1f5d3 100755 --- a/t/t2501-cwd-empty.sh +++ b/t/t2501-cwd-empty.sh @@ -252,4 +252,46 @@ test_expect_success 'stash does not remove cwd incidentally' ' test_path_is_dir untracked ' +test_expect_success 'rm -r leaves submodule if cwd inside' ' + test_when_finished "git reset --hard HEAD~1" && + test_when_finished "rm -rf .git/modules/my_submodule" && + + git checkout foo/bar/baz && + + git init my_submodule && + touch my_submodule/file && + git -C my_submodule add file && + git -C my_submodule commit -m "initial commit" && + git submodule add ./my_submodule && + git commit -m "Add the submodule" && + + ( + cd my_submodule && + test_must_fail git --git-dir=../.git --work-tree=.. rm -r ../my_submodule/ + ) && + + test_path_is_dir my_submodule +' + +test_expect_success 'rm -rf removes submodule even if cwd inside' ' + test_when_finished "git reset --hard HEAD~1" && + test_when_finished "rm -rf .git/modules/my_submodule" && + + git checkout foo/bar/baz && + + git init my_submodule && + touch my_submodule/file && + git -C my_submodule add file && + git -C my_submodule commit -m "initial commit" && + git submodule add ./my_submodule && + git commit -m "Add the submodule" && + + ( + cd my_submodule && + git --git-dir=../.git --work-tree=.. rm -rf ../my_submodule/ + ) && + + test_path_is_missing my_submodule +' + test_done