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

[PATCH v5 3/8] fast-import: allow unquoted empty path for root

From
Thalia Archibald <thalia@archibald.dev>
Date
Apr 14, 2024, 01:11 UTC
Message-ID
<cae5764cec349d295035f2b910a5a00f12cb7908.1713056559.git.thalia@archibald.dev>
In-Reply-To
<cover.1713056559.git.thalia@archibald.dev>

Ever since filerename was added in f39a946a1f (Support wholesale directory renames in fast-import, 2007-07-09) and filecopy in b6f3481bb4 (Teach fast-import to recursively copy files/directories, 2007-07-15), both have produced an error when the destination path is empty. Later, when support for targeting the root directory with an empty string was added in 2794ad5244 (fast-import: Allow filemodify to set the root, 2010-10-10), this had the effect of allowing the quoted empty string (`""`), but forbidding its unquoted variant (``). This seems to have been intended as simple data validation for parsing two paths, rather than a syntax restriction, because it was not extended to the other operations.

All other occurrences of paths (in filemodify, filedelete, the source of filecopy and filerename, and ls) allow both.

For most of this feature's lifetime, the documentation has not prescribed the use of quoted empty strings. In e5959106d6 (Documentation/fast-import: put explanation of M 040000 <dataref> "" in context, 2011-01-15), its documentation was changed from “`<path>` may also be an empty string (`""`) to specify the root of the tree” to “The root of the tree can be represented by an empty string as `<path>`”.

Thus, we should assume that some front-ends have depended on this behavior.

Remove this restriction for the destination paths of filecopy and filerename and change tests targeting the root to test `""` and ``.

Signed-off-by: Thalia Archibald <thalia@archibald.dev>
---
 builtin/fast-import.c  |   3 -
 t/t9300-fast-import.sh | 363 +++++++++++++++++++++--------------------
 2 files changed, 190 insertions(+), 176 deletions(-)
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 765429a66c..c8a1e3ef3d 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -2423,9 +2423,6 @@ static void file_change_cr(const char *p, struct branch *b, int rename)
 
 	strbuf_reset(&source);
 	parse_path_space(&source, p, &p, "source");
-
-	if (!*p)
-		die("Missing dest: %s", command_buf.buf);
 	strbuf_reset(&dest);
 	parse_path_eol(&dest, p, "dest");
 
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index de2f1304e8..13f98e6688 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1059,30 +1059,33 @@ test_expect_success 'M: rename subdirectory to new subdirectory' '
 	compare_diff_raw expect actual
 '
 
-test_expect_success 'M: rename root to subdirectory' '
-	cat >input <<-INPUT_END &&
-	commit refs/heads/M4
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	rename root
-	COMMIT
+for root in '""' ''
+do
+	test_expect_success "M: rename root ($root) to subdirectory" '
+		cat >input <<-INPUT_END &&
+		commit refs/heads/M4
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		rename root
+		COMMIT
 
-	from refs/heads/M2^0
-	R "" sub
+		from refs/heads/M2^0
+		R $root sub
 
-	INPUT_END
+		INPUT_END
 
-	cat >expect <<-EOF &&
-	:100644 100644 $oldf $oldf R100	file2/oldf	sub/file2/oldf
-	:100755 100755 $f4id $f4id R100	file4	sub/file4
-	:100755 100755 $newf $newf R100	i/am/new/to/you	sub/i/am/new/to/you
-	:100755 100755 $f6id $f6id R100	newdir/exec.sh	sub/newdir/exec.sh
-	:100644 100644 $f5id $f5id R100	newdir/interesting	sub/newdir/interesting
-	EOF
-	git fast-import <input &&
-	git diff-tree -M -r M4^ M4 >actual &&
-	compare_diff_raw expect actual
-'
+		cat >expect <<-EOF &&
+		:100644 100644 $oldf $oldf R100	file2/oldf	sub/file2/oldf
+		:100755 100755 $f4id $f4id R100	file4	sub/file4
+		:100755 100755 $newf $newf R100	i/am/new/to/you	sub/i/am/new/to/you
+		:100755 100755 $f6id $f6id R100	newdir/exec.sh	sub/newdir/exec.sh
+		:100644 100644 $f5id $f5id R100	newdir/interesting	sub/newdir/interesting
+		EOF
+		git fast-import <input &&
+		git diff-tree -M -r M4^ M4 >actual &&
+		compare_diff_raw expect actual
+	'
+done
 
 ###
 ### series N
@@ -1259,49 +1262,52 @@ test_expect_success PIPE 'N: empty directory reads as missing' '
 	test_cmp expect actual
 '
 
-test_expect_success 'N: copy root directory by tree hash' '
-	cat >expect <<-EOF &&
-	:100755 000000 $newf $zero D	file3/newf
-	:100644 000000 $oldf $zero D	file3/oldf
-	EOF
-	root=$(git rev-parse refs/heads/branch^0^{tree}) &&
-	cat >input <<-INPUT_END &&
-	commit refs/heads/N6
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	copy root directory by tree hash
-	COMMIT
+for root in '""' ''
+do
+	test_expect_success "N: copy root ($root) by tree hash" '
+		cat >expect <<-EOF &&
+		:100755 000000 $newf $zero D	file3/newf
+		:100644 000000 $oldf $zero D	file3/oldf
+		EOF
+		root_tree=$(git rev-parse refs/heads/branch^0^{tree}) &&
+		cat >input <<-INPUT_END &&
+		commit refs/heads/N6
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		copy root directory by tree hash
+		COMMIT
 
-	from refs/heads/branch^0
-	M 040000 $root ""
-	INPUT_END
-	git fast-import <input &&
-	git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
-	compare_diff_raw expect actual
-'
+		from refs/heads/branch^0
+		M 040000 $root_tree $root
+		INPUT_END
+		git fast-import <input &&
+		git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
+		compare_diff_raw expect actual
+	'
 
-test_expect_success 'N: copy root by path' '
-	cat >expect <<-EOF &&
-	:100755 100755 $newf $newf C100	file2/newf	oldroot/file2/newf
-	:100644 100644 $oldf $oldf C100	file2/oldf	oldroot/file2/oldf
-	:100755 100755 $f4id $f4id C100	file4	oldroot/file4
-	:100755 100755 $f6id $f6id C100	newdir/exec.sh	oldroot/newdir/exec.sh
-	:100644 100644 $f5id $f5id C100	newdir/interesting	oldroot/newdir/interesting
-	EOF
-	cat >input <<-INPUT_END &&
-	commit refs/heads/N-copy-root-path
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	copy root directory by (empty) path
-	COMMIT
+	test_expect_success "N: copy root ($root) by path" '
+		cat >expect <<-EOF &&
+		:100755 100755 $newf $newf C100	file2/newf	oldroot/file2/newf
+		:100644 100644 $oldf $oldf C100	file2/oldf	oldroot/file2/oldf
+		:100755 100755 $f4id $f4id C100	file4	oldroot/file4
+		:100755 100755 $f6id $f6id C100	newdir/exec.sh	oldroot/newdir/exec.sh
+		:100644 100644 $f5id $f5id C100	newdir/interesting	oldroot/newdir/interesting
+		EOF
+		cat >input <<-INPUT_END &&
+		commit refs/heads/N-copy-root-path
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		copy root directory by (empty) path
+		COMMIT
 
-	from refs/heads/branch^0
-	C "" oldroot
-	INPUT_END
-	git fast-import <input &&
-	git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual &&
-	compare_diff_raw expect actual
-'
+		from refs/heads/branch^0
+		C $root oldroot
+		INPUT_END
+		git fast-import <input &&
+		git diff-tree -C --find-copies-harder -r branch N-copy-root-path >actual &&
+		compare_diff_raw expect actual
+	'
+done
 
 test_expect_success 'N: delete directory by copying' '
 	cat >expect <<-\EOF &&
@@ -1431,98 +1437,102 @@ test_expect_success 'N: reject foo/ syntax in ls argument' '
 	INPUT_END
 '
 
-test_expect_success 'N: copy to root by id and modify' '
-	echo "hello, world" >expect.foo &&
-	echo hello >expect.bar &&
-	git fast-import <<-SETUP_END &&
-	commit refs/heads/N7
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	hello, tree
-	COMMIT
+for root in '""' ''
+do
+	test_expect_success "N: copy to root ($root) by id and modify" '
+		echo "hello, world" >expect.foo &&
+		echo hello >expect.bar &&
+		git fast-import <<-SETUP_END &&
+		commit refs/heads/N7
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		hello, tree
+		COMMIT
 
-	deleteall
-	M 644 inline foo/bar
-	data <<EOF
-	hello
-	EOF
-	SETUP_END
+		deleteall
+		M 644 inline foo/bar
+		data <<EOF
+		hello
+		EOF
+		SETUP_END
 
-	tree=$(git rev-parse --verify N7:) &&
-	git fast-import <<-INPUT_END &&
-	commit refs/heads/N8
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	copy to root by id and modify
-	COMMIT
+		tree=$(git rev-parse --verify N7:) &&
+		git fast-import <<-INPUT_END &&
+		commit refs/heads/N8
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		copy to root by id and modify
+		COMMIT
 
-	M 040000 $tree ""
-	M 644 inline foo/foo
-	data <<EOF
-	hello, world
-	EOF
-	INPUT_END
-	git show N8:foo/foo >actual.foo &&
-	git show N8:foo/bar >actual.bar &&
-	test_cmp expect.foo actual.foo &&
-	test_cmp expect.bar actual.bar
-'
+		M 040000 $tree $root
+		M 644 inline foo/foo
+		data <<EOF
+		hello, world
+		EOF
+		INPUT_END
+		git show N8:foo/foo >actual.foo &&
+		git show N8:foo/bar >actual.bar &&
+		test_cmp expect.foo actual.foo &&
+		test_cmp expect.bar actual.bar
+	'
 
-test_expect_success 'N: extract subtree' '
-	branch=$(git rev-parse --verify refs/heads/branch^{tree}) &&
-	cat >input <<-INPUT_END &&
-	commit refs/heads/N9
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	extract subtree branch:newdir
-	COMMIT
+	test_expect_success "N: extract subtree to the root ($root)" '
+		branch=$(git rev-parse --verify refs/heads/branch^{tree}) &&
+		cat >input <<-INPUT_END &&
+		commit refs/heads/N9
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		extract subtree branch:newdir
+		COMMIT
 
-	M 040000 $branch ""
-	C "newdir" ""
-	INPUT_END
-	git fast-import <input &&
-	git diff --exit-code branch:newdir N9
-'
+		M 040000 $branch $root
+		C "newdir" $root
+		INPUT_END
+		git fast-import <input &&
+		git diff --exit-code branch:newdir N9
+	'
 
-test_expect_success 'N: modify subtree, extract it, and modify again' '
-	echo hello >expect.baz &&
-	echo hello, world >expect.qux &&
-	git fast-import <<-SETUP_END &&
-	commit refs/heads/N10
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	hello, tree
-	COMMIT
+	test_expect_success "N: modify subtree, extract it to the root ($root), and modify again" '
+		echo hello >expect.baz &&
+		echo hello, world >expect.qux &&
+		git fast-import <<-SETUP_END &&
+		commit refs/heads/N10
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		hello, tree
+		COMMIT
 
-	deleteall
-	M 644 inline foo/bar/baz
-	data <<EOF
-	hello
-	EOF
-	SETUP_END
+		deleteall
+		M 644 inline foo/bar/baz
+		data <<EOF
+		hello
+		EOF
+		SETUP_END
 
-	tree=$(git rev-parse --verify N10:) &&
-	git fast-import <<-INPUT_END &&
-	commit refs/heads/N11
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	copy to root by id and modify
-	COMMIT
+		tree=$(git rev-parse --verify N10:) &&
+		git fast-import <<-INPUT_END &&
+		commit refs/heads/N11
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		copy to root by id and modify
+		COMMIT
 
-	M 040000 $tree ""
-	M 100644 inline foo/bar/qux
-	data <<EOF
-	hello, world
-	EOF
-	R "foo" ""
-	C "bar/qux" "bar/quux"
-	INPUT_END
-	git show N11:bar/baz >actual.baz &&
-	git show N11:bar/qux >actual.qux &&
-	git show N11:bar/quux >actual.quux &&
-	test_cmp expect.baz actual.baz &&
-	test_cmp expect.qux actual.qux &&
-	test_cmp expect.qux actual.quux'
+		M 040000 $tree $root
+		M 100644 inline foo/bar/qux
+		data <<EOF
+		hello, world
+		EOF
+		R "foo" $root
+		C "bar/qux" "bar/quux"
+		INPUT_END
+		git show N11:bar/baz >actual.baz &&
+		git show N11:bar/qux >actual.qux &&
+		git show N11:bar/quux >actual.quux &&
+		test_cmp expect.baz actual.baz &&
+		test_cmp expect.qux actual.qux &&
+		test_cmp expect.qux actual.quux
+	'
+done
 
 ###
 ### series O
@@ -3067,6 +3077,7 @@ test_expect_success 'S: ls with garbage after sha1 must fail' '
 # There are two sorts of ways a path can be parsed, depending on whether it is
 # the last field on the line. Additionally, ls without a <dataref> has a special
 # case. Test every occurrence of <path> in the grammar against every error case.
+# Paths for the root (empty strings) are tested elsewhere.
 #
 
 #
@@ -3321,16 +3332,19 @@ test_path_eol_quoted_fail 'ls (without dataref in commit)' 'ls ' path
 ###
 # Setup is carried over from series S.
 
-test_expect_success 'T: ls root tree' '
-	sed -e "s/Z\$//" >expect <<-EOF &&
-	040000 tree $(git rev-parse S^{tree})	Z
-	EOF
-	sha1=$(git rev-parse --verify S) &&
-	git fast-import --import-marks=marks <<-EOF >actual &&
-	ls $sha1 ""
-	EOF
-	test_cmp expect actual
-'
+for root in '""' ''
+do
+	test_expect_success "T: ls root ($root) tree" '
+		sed -e "s/Z\$//" >expect <<-EOF &&
+		040000 tree $(git rev-parse S^{tree})	Z
+		EOF
+		sha1=$(git rev-parse --verify S) &&
+		git fast-import --import-marks=marks <<-EOF >actual &&
+		ls $sha1 $root
+		EOF
+		test_cmp expect actual
+	'
+done
 
 test_expect_success 'T: delete branch' '
 	git branch to-delete &&
@@ -3432,30 +3446,33 @@ test_expect_success 'U: validate directory delete result' '
 	compare_diff_raw expect actual
 '
 
-test_expect_success 'U: filedelete root succeeds' '
-	cat >input <<-INPUT_END &&
-	commit refs/heads/U
-	committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
-	data <<COMMIT
-	must succeed
-	COMMIT
-	from refs/heads/U^0
-	D ""
+for root in '""' ''
+do
+	test_expect_success "U: filedelete root ($root) succeeds" '
+		cat >input <<-INPUT_END &&
+		commit refs/heads/U-delete-root
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		must succeed
+		COMMIT
+		from refs/heads/U^0
+		D $root
 
-	INPUT_END
+		INPUT_END
 
-	git fast-import <input
-'
+		git fast-import <input
+	'
 
-test_expect_success 'U: validate root delete result' '
-	cat >expect <<-EOF &&
-	:100644 000000 $f7id $ZERO_OID D	hello.c
-	EOF
+	test_expect_success "U: validate root ($root) delete result" '
+		cat >expect <<-EOF &&
+		:100644 000000 $f7id $ZERO_OID D	hello.c
+		EOF
 
-	git diff-tree -M -r U^1 U >actual &&
+		git diff-tree -M -r U U-delete-root >actual &&
 
-	compare_diff_raw expect actual
-'
+		compare_diff_raw expect actual
+	'
+done
 
 ###
 ### series V (checkpoint)
-- 
2.44.0
Previous: Thalia ArchibaldNext: Thalia Archibald
Message 76 of 84 in “fast-import: tighten parsing of paths”
  1. 0/6 fast-import: tighten parsing of pathsThalia Archibald, Mar 22, 2024
  2. 1/6 fast-import: tighten parsing of pathsThalia Archibald, Mar 22, 2024
  3. Thalia ArchibaldMar 22, 2024
  4. Patrick SteinhardtMar 28, 2024
  5. 3/6 fast-import: release unfreed strbufsThalia Archibald, Mar 22, 2024
  6. Patrick SteinhardtMar 28, 2024
  7. Thalia ArchibaldApr 1, 2024
  8. 2/6 fast-import: directly use strbufs for pathsThalia Archibald, Mar 22, 2024
  9. Patrick SteinhardtMar 28, 2024
  10. 4/6 fast-import: remove dead strbufThalia Archibald, Mar 22, 2024
  11. Patrick SteinhardtMar 28, 2024
  12. 6/6 fast-import: forbid escaped NUL in pathsThalia Archibald, Mar 22, 2024
  13. 5/6 fast-import: document C-style escapes for pathsThalia Archibald, Mar 22, 2024
  14. Patrick SteinhardtMar 28, 2024
  15. Thalia ArchibaldApr 1, 2024
  16. 0/8 fast-import: tighten parsing of pathsThalia Archibald, Apr 1, 2024
  17. 1/8 fast-import: tighten path unquotingThalia Archibald, Apr 1, 2024
  18. Patrick SteinhardtApr 10, 2024
  19. Chris TorekApr 10, 2024
  20. Thalia ArchibaldApr 10, 2024
  21. Chris TorekApr 10, 2024
  22. Thalia ArchibaldApr 10, 2024
  23. Patrick SteinhardtApr 10, 2024
  24. Thalia ArchibaldApr 10, 2024
  25. Thalia ArchibaldApr 10, 2024
  26. 2/8 fast-import: directly use strbufs for pathsThalia Archibald, Apr 1, 2024
  27. Patrick SteinhardtApr 10, 2024
  28. Thalia ArchibaldApr 10, 2024
  29. Patrick SteinhardtApr 10, 2024
  30. 3/8 fast-import: allow unquoted empty path for rootThalia Archibald, Apr 1, 2024
  31. Patrick SteinhardtApr 10, 2024
  32. 4/8 fast-import: remove dead strbufThalia Archibald, Apr 1, 2024
  33. 5/8 fast-import: improve documentation for unquoted pathsThalia Archibald, Apr 1, 2024
  34. 6/8 fast-import: document C-style escapes for pathsThalia Archibald, Apr 1, 2024
  35. 7/8 fast-import: forbid escaped NUL in pathsThalia Archibald, Apr 1, 2024
  36. 8/8 fast-import: make comments more preciseThalia Archibald, Apr 1, 2024
  37. Thalia ArchibaldApr 7, 2024
  38. Eric SunshineApr 7, 2024
  39. Patrick SteinhardtApr 8, 2024
  40. Thalia ArchibaldApr 8, 2024
  41. Patrick SteinhardtApr 8, 2024
  42. Junio C HamanoApr 8, 2024
  43. 0/8 fast-import: tighten parsing of pathsThalia Archibald, Apr 10, 2024
  44. 1/8 fast-import: tighten path unquotingThalia Archibald, Apr 10, 2024
  45. 2/8 fast-import: directly use strbufs for pathsThalia Archibald, Apr 10, 2024
  46. 3/8 fast-import: allow unquoted empty path for rootThalia Archibald, Apr 10, 2024
  47. Junio C HamanoApr 11, 2024
  48. 5/8 fast-import: improve documentation for unquoted pathsThalia Archibald, Apr 10, 2024
  49. Junio C HamanoApr 11, 2024
  50. 6/8 fast-import: document C-style escapes for pathsThalia Archibald, Apr 10, 2024
  51. Junio C HamanoApr 10, 2024
  52. Thalia ArchibaldApr 10, 2024
  53. Junio C HamanoApr 11, 2024
  54. Patrick SteinhardtApr 11, 2024
  55. 7/8 fast-import: forbid escaped NUL in pathsThalia Archibald, Apr 10, 2024
  56. Junio C HamanoApr 10, 2024
  57. 8/8 fast-import: make comments more preciseThalia Archibald, Apr 10, 2024
  58. Junio C HamanoApr 10, 2024
  59. 4/8 fast-import: remove dead strbufThalia Archibald, Apr 10, 2024
  60. Junio C HamanoApr 11, 2024
  61. 0/8 fast-import: tighten parsing of pathsThalia Archibald, Apr 12, 2024
  62. 2/8 fast-import: directly use strbufs for pathsThalia Archibald, Apr 12, 2024
  63. 3/8 fast-import: allow unquoted empty path for rootThalia Archibald, Apr 12, 2024
  64. 4/8 fast-import: remove dead strbufThalia Archibald, Apr 12, 2024
  65. 5/8 fast-import: improve documentation for path quotingThalia Archibald, Apr 12, 2024
  66. 6/8 fast-import: document C-style escapes for pathsThalia Archibald, Apr 12, 2024
  67. 7/8 fast-import: forbid escaped NUL in pathsThalia Archibald, Apr 12, 2024
  68. 8/8 fast-import: make comments more preciseThalia Archibald, Apr 12, 2024
  69. 1/8 fast-import: tighten path unquotingThalia Archibald, Apr 12, 2024
  70. Junio C HamanoApr 12, 2024
  71. Thalia ArchibaldApr 13, 2024
  72. Junio C HamanoApr 13, 2024
  73. 0/8 fast-import: tighten parsing of pathsThalia Archibald, Apr 14, 2024
  74. 2/8 fast-import: directly use strbufs for pathsThalia Archibald, Apr 14, 2024
  75. 1/8 fast-import: tighten path unquotingThalia Archibald, Apr 14, 2024
  76. 3/8 fast-import: allow unquoted empty path for rootThalia Archibald, Apr 14, 2024
  77. 4/8 fast-import: remove dead strbufThalia Archibald, Apr 14, 2024
  78. 5/8 fast-import: improve documentation for path quotingThalia Archibald, Apr 14, 2024
  79. 6/8 fast-import: document C-style escapes for pathsThalia Archibald, Apr 14, 2024
  80. 7/8 fast-import: forbid escaped NUL in pathsThalia Archibald, Apr 14, 2024
  81. 8/8 fast-import: make comments more preciseThalia Archibald, Apr 14, 2024
  82. Patrick SteinhardtApr 15, 2024
  83. Junio C HamanoApr 15, 2024
  84. Thalia ArchibaldApr 1, 2024

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.