git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCHv2] grep: use slash for path delimiter, not colon

From
Phil Hord <hordp@cisco.com>
Date
Aug 26, 2013, 14:46 UTC
Message-ID
<1377528372-31206-1-git-send-email-hordp@cisco.com>

When a commit is grepped and matching filenames are printed, grep-objects creates the filename by prefixing the original cmdline argument to the matched path separated by a colon. Normally this forms a valid blob reference to the filename, like this:

  git grep -l foo HEAD
  HEAD:some/path/to/foo.txt
      ^

But a tree path may be given to grep instead; in this case the colon is not a valid delimiter to use since it is placed inside a path.

  git grep -l foo HEAD:some
  HEAD:some:path/to/foo.txt
           ^

The slash path delimiter should be used instead. Fix git grep to discern the correct delimiter so it can report valid object names.

  git grep -l foo HEAD:some
  HEAD:some/path/to/foo.txt
           ^

Also, prevent the delimiter being added twice, as happens now in these examples:

  git grep -l foo HEAD:
  HEAD::some/path/to/foo.txt
       ^
  git grep -l foo HEAD:some/
  HEAD:some/:path/to/foo.txt
            ^

Add a test to confirm correct path forming. --- This version is a bit more deterministic and also adds a test.

It accepts the expense of examining the path argument again to determine if it is a tree-ish + path rather than just a tree (commit). The get_sha1 call occurs one extra time for each tree-ish argument, so it's not expensive. We avoid mucking with the object_array API this way, and also do not rely on the object-type to tell us anything about the way the object name was spelled.

This one also adds a check to avoid duplicating an extant delimiter.
 builtin/grep.c  |  9 ++++++++-
 t/t7810-grep.sh | 15 +++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/builtin/grep.c b/builtin/grep.c
index 03bc442..6fc418f 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -480,8 +480,15 @@ static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
 		len = name ? strlen(name) : 0;
 		strbuf_init(&base, PATH_MAX + len + 1);
 		if (len) {
+			struct object_context ctx;
+			unsigned char sha1[20];
+			char delimiter = ':';
+			if (!get_sha1_with_context(name, 0, sha1, &ctx) &&
+				ctx.path[0]!=0)
+				delimiter='/';
 			strbuf_add(&base, name, len);
-			strbuf_addch(&base, ':');
+			if (name[len-1] != delimiter)
+				strbuf_addch(&base, delimiter);
 		}
 		init_tree_desc(&tree, data, size);
 		hit = grep_tree(opt, pathspec, &tree, &base, base.len,
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index f698001..2494bfc 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -886,6 +886,21 @@ test_expect_success 'grep -e -- -- path' '
 '
 
 cat >expected <<EOF
+HEAD:t/a/v:1:vvv
+HEAD:t/v:1:vvv
+EOF
+
+test_expect_success "grep HEAD -- path/" '
+	git grep -n -e vvv HEAD -- t/ >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success "grep HEAD:path" '
+	git grep -n -e vvv HEAD:t/ >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<EOF
 hello.c:int main(int argc, const char **argv)
 hello.c:	printf("Hello world.\n");
 EOF
-- 
1.8.4.557.g34b3a2e
Next: Jeff King
Message 1 of 11 in “[PATCHv2] grep: use slash for path delimiter, not colon”
  1. Phil HordAug 26, 2013
  2. Jeff KingAug 26, 2013
  3. Jeff KingAug 26, 2013
  4. 1/2 grep: stop using object_arrayJeff King, Aug 26, 2013
  5. 2/2 grep: use slash for path delimiter, not colonJeff King, Aug 26, 2013
  6. Johannes SixtAug 26, 2013
  7. Phil HordAug 26, 2013
  8. Jeff KingAug 26, 2013
  9. Phil HordAug 26, 2013
  10. Jeff KingAug 26, 2013
  11. Junio C HamanoAug 27, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.