From e0020b2f82910f50bc697d86aff70c3796fbdc41 Mon Sep 17 00:00:00 2001 From: Emily Shaffer Date: Fri, 14 Feb 2020 17:00:13 -0800 Subject: [PATCH 1/2] prefix_path: show gitdir when arg is outside repo When developing a script, it can be painful to understand why Git thinks something is outside the current repo, if the current repo isn't what the user thinks it is. Since this can be tricky to diagnose, especially in cases like submodules or nested worktrees, let's give the user a hint about which repository is offended about that path. Signed-off-by: Emily Shaffer Acked-by: brian m. carlson Signed-off-by: Junio C Hamano --- pathspec.c | 3 ++- setup.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pathspec.c b/pathspec.c index 128f27fcb7..166d255642 100644 --- a/pathspec.c +++ b/pathspec.c @@ -439,7 +439,8 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags, match = prefix_path_gently(prefix, prefixlen, &prefixlen, copyfrom); if (!match) - die(_("%s: '%s' is outside repository"), elt, copyfrom); + die(_("%s: '%s' is outside repository at '%s'"), elt, + copyfrom, absolute_path(get_git_work_tree())); } item->match = match; diff --git a/setup.c b/setup.c index e2a479a64f..17814a080b 100644 --- a/setup.c +++ b/setup.c @@ -121,7 +121,8 @@ char *prefix_path(const char *prefix, int len, const char *path) { char *r = prefix_path_gently(prefix, len, NULL, path); if (!r) - die(_("'%s' is outside repository"), path); + die(_("'%s' is outside repository at '%s'"), path, + absolute_path(get_git_work_tree())); return r; } From 5c20398699165a91af2d81ea2d20385bc8dd3627 Mon Sep 17 00:00:00 2001 From: Emily Shaffer Date: Mon, 2 Mar 2020 20:05:06 -0800 Subject: [PATCH 2/2] prefix_path: show gitdir if worktree unavailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If there is no worktree at present, we can still hint the user about Git's current directory by showing them the absolute path to the Git directory. Even though the Git directory doesn't make it as easy to locate the worktree in question, it can still help a user figure out what's going on while developing a script. This fixes a segmentation fault introduced in e0020b2f ("prefix_path: show gitdir when arg is outside repo", 2020-02-14). Signed-off-by: Emily Shaffer [jc: added minimum tests, with help from Szeder Gábor] Signed-off-by: Junio C Hamano --- pathspec.c | 8 ++++++-- setup.c | 8 ++++++-- t/t6136-pathspec-in-bare.sh | 38 +++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100755 t/t6136-pathspec-in-bare.sh diff --git a/pathspec.c b/pathspec.c index 166d255642..8243e06eab 100644 --- a/pathspec.c +++ b/pathspec.c @@ -438,9 +438,13 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags, } else { match = prefix_path_gently(prefix, prefixlen, &prefixlen, copyfrom); - if (!match) + if (!match) { + const char *hint_path = get_git_work_tree(); + if (!hint_path) + hint_path = get_git_dir(); die(_("%s: '%s' is outside repository at '%s'"), elt, - copyfrom, absolute_path(get_git_work_tree())); + copyfrom, absolute_path(hint_path)); + } } item->match = match; diff --git a/setup.c b/setup.c index 17814a080b..f4897287f7 100644 --- a/setup.c +++ b/setup.c @@ -120,9 +120,13 @@ char *prefix_path_gently(const char *prefix, int len, char *prefix_path(const char *prefix, int len, const char *path) { char *r = prefix_path_gently(prefix, len, NULL, path); - if (!r) + if (!r) { + const char *hint_path = get_git_work_tree(); + if (!hint_path) + hint_path = get_git_dir(); die(_("'%s' is outside repository at '%s'"), path, - absolute_path(get_git_work_tree())); + absolute_path(hint_path)); + } return r; } diff --git a/t/t6136-pathspec-in-bare.sh b/t/t6136-pathspec-in-bare.sh new file mode 100755 index 0000000000..b117251366 --- /dev/null +++ b/t/t6136-pathspec-in-bare.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +test_description='diagnosing out-of-scope pathspec' + +. ./test-lib.sh + +test_expect_success 'setup a bare and non-bare repository' ' + test_commit file1 && + git clone --bare . bare +' + +test_expect_success 'log and ls-files in a bare repository' ' + ( + cd bare && + test_must_fail git log -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err && + + test_must_fail git ls-files -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err + ) +' + +test_expect_success 'log and ls-files in .git directory' ' + ( + cd .git && + test_must_fail git log -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err && + + test_must_fail git ls-files -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err + ) +' + +test_done