Refuse a path with a . segment (closes #208)
check / check (push) Waiting to run

ValidatePath refused a .. segment but accepted a . segment, so a
manifest could list ./a.txt. check then verified a.txt and also
reported it as an extra file, and one file could be listed twice under
two spellings despite the listed-once rule. A . segment is now refused
when a manifest is written and when it is loaded, and the Path Rules
in docs/FORMAT.md list it.

Two fetch tests listed ./ paths to check name clashes; such manifests
can no longer be built, so those cases are removed.

Model: opus-5-5
This commit is contained in:
2026-10-13 17:55:10 +00:00
parent 24496880c5
commit befae2886d
6 changed files with 26 additions and 11 deletions
+8 -11
View File
@@ -1243,10 +1243,10 @@ func TestFetchRequireSignature(t *testing.T) {
// TestFetchRefusesListedManifestName fetches manifests that list, at the
// top of the tree, the name fetch saves the manifest under or that name's
// temp file: as a file, as a directory, in capitals, and with a leading
// "./". Saving the manifest would replace or remove what is listed there,
// so fetch must refuse the manifest before it creates the destination or
// requests any file.
// temp file: as a file, as a directory and in capitals. Saving the
// manifest would replace or remove what is listed there, so fetch must
// refuse the manifest before it creates the destination or requests any
// file.
func TestFetchRefusesListedManifestName(t *testing.T) {
t.Parallel()
@@ -1255,7 +1255,6 @@ func TestFetchRefusesListedManifestName(t *testing.T) {
tempPathFor(defaultManifestName),
defaultManifestName + "/" + testFileTxt,
"INDEX.MF",
"./" + defaultManifestName,
} {
t.Run(listed, func(t *testing.T) {
t.Parallel()
@@ -1331,9 +1330,9 @@ func TestFetchRefusesListedTempName(t *testing.T) {
// directory, one of them under a spelling the manifest does not list,
// and check reports that file as not in the manifest. So fetch must
// refuse each on every filesystem before it creates the destination or
// requests any file. A file and a directory with the same name, and a
// file listed twice, are refused the same way. A manifest whose names
// differ in more than letter case is fetched in full.
// requests any file. A file and a directory with the same name are
// refused the same way. A manifest whose names differ in more than
// letter case is fetched in full.
func TestFetchRefusesNamesEqualIgnoringCase(t *testing.T) {
t.Parallel()
@@ -1343,7 +1342,6 @@ func TestFetchRefusesNamesEqualIgnoringCase(t *testing.T) {
{"Dir", "dir/x", "dir/x (the file Dir)"},
{"Dir/a.txt", "dir/b.txt", "dir/b.txt (the directory Dir)"},
{"dir", "dir/x", "dir/x (the file dir)"},
{"./x.txt", "x.txt", "x.txt (the file ./x.txt)"},
} {
t.Run(tc.first+" and "+tc.second, func(t *testing.T) {
t.Parallel()
@@ -1573,8 +1571,7 @@ func manifestWithMode(t *testing.T, path string, content []byte, mode uint32) []
}
// builtManifest returns a manifest of files, built directly rather than
// scanned, since a scan lists no hidden files and never a path starting
// with "./".
// scanned, since a scan lists no hidden files.
func builtManifest(t *testing.T, files map[string][]byte) []byte {
t.Helper()