Resolve candidate paths in traversal order
This commit is contained in:
@@ -174,3 +174,59 @@ func TestResolveDestinationIgnoresNeighboringFiles(t *testing.T) {
|
||||
t.Fatalf("neighbor changed resolution: absent=%#v present=%#v", gotWithoutNeighbor, gotWithNeighbor)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveDestinationPreservesParentTraversalOrder(t *testing.T) {
|
||||
repository := newTreeRepository(t)
|
||||
for _, name := range []string{"README.md", "docs/file.md", "nested/file.md", "nested/inner/item.txt"} {
|
||||
writeTreeFile(t, repository, name, []byte("captured\n"))
|
||||
}
|
||||
for name, target := range map[string]string{
|
||||
"docs/link": "../nested/inner",
|
||||
"docs/parent-link": "link/../file.md",
|
||||
"escape": "../neighbor",
|
||||
} {
|
||||
if err := os.Symlink(target, filepath.Join(repository, filepath.FromSlash(name))); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
gitTree(t, repository, "add", "--all")
|
||||
gitTree(t, repository, "commit", "-m", "capture parent traversal")
|
||||
tree, err := ReadCandidateTree(t.Context(), repository, strings.TrimSpace(gitTree(t, repository, "rev-parse", "HEAD")))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, test := range []struct {
|
||||
destination string
|
||||
kind DestinationKind
|
||||
resolved string
|
||||
}{
|
||||
{"docs/link/../file.md", DestinationEntry, "nested/file.md"},
|
||||
{"docs/parent-link", DestinationEntry, "nested/file.md"},
|
||||
{"escape/../README.md", DestinationOutsideCheckout, ""},
|
||||
{"missing/../README.md", DestinationMissing, ""},
|
||||
{"README.md/../README.md", DestinationMissing, ""},
|
||||
{"README.md/.", DestinationMissing, ""},
|
||||
} {
|
||||
t.Run(test.destination, func(t *testing.T) {
|
||||
got, err := tree.ResolveDestination(t.Context(), "README.md", test.destination)
|
||||
if err != nil || got.Kind != test.kind || (test.resolved != "" && got.Path != test.resolved) {
|
||||
t.Fatalf("resolution = %#v, %v; want %s %q", got, err, test.kind, test.resolved)
|
||||
}
|
||||
})
|
||||
}
|
||||
before, err := tree.ResolveDestination(t.Context(), "README.md", "escape/../README.md")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
neighbor := filepath.Join(filepath.Dir(repository), "neighbor")
|
||||
if err := os.MkdirAll(neighbor, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(neighbor, "file.md"), []byte("neighbor"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
after, err := tree.ResolveDestination(t.Context(), "README.md", "escape/../README.md")
|
||||
if err != nil || before != after {
|
||||
t.Fatalf("neighbor changed resolution: %#v -> %#v, %v", before, after, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user