List a directory named through a symlink in gen and freshen (closes #185)
check / check (push) Waiting to run
check / check (push) Waiting to run
The walk in gen and freshen does not follow a symlink at its top. A directory given as a symlink, or a working directory whose path names one, was listed as empty and gen exited 0, while freshen removed every entry from the manifest. Each walk now resolves its starting directory with filepath.EvalSymlinks first, as check's search for extra files does, and starts at the path as named if that fails. Symlinks inside the tree are still skipped unless --follow-symlinks is given. Model: opus-5-5
This commit is contained in:
@@ -336,6 +336,48 @@ func TestFreshenResolvesEntriesAgainstManifestDirectory(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestFreshenDirectoryNamedThroughSymlink adds a file to a tree after gen
|
||||
// made its manifest, then freshens it with the tree named through a symlink,
|
||||
// given as the argument or as the working directory: the manifest lists the
|
||||
// files in the tree, and leaves out a symlink inside it, as freshen does
|
||||
// without --follow-symlinks.
|
||||
//
|
||||
//nolint:paralleltest // changes the process-global working directory
|
||||
func TestFreshenDirectoryNamedThroughSymlink(t *testing.T) {
|
||||
// Paths are relative to a temp dir holding link, a symlink to the tree.
|
||||
for name, tc := range map[string]struct {
|
||||
workDir string
|
||||
args []string
|
||||
}{
|
||||
"argument": {".", []string{"link"}},
|
||||
"working directory": {"link", nil},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
fs := afero.NewOsFs()
|
||||
tree, manifestPath := setupFreshenDir(t, fs,
|
||||
map[string]string{testFileTxt: "content1"})
|
||||
writeTestFile(t, fs, filepath.Join(tree, "added.txt"), "added")
|
||||
require.NoError(t,
|
||||
os.Symlink(testFileTxt, filepath.Join(tree, "alias.txt")))
|
||||
|
||||
root := t.TempDir()
|
||||
require.NoError(t, os.Symlink(tree, filepath.Join(root, "link")))
|
||||
|
||||
// t.Chdir sets PWD to the path it is given, as a shell does, and
|
||||
// os.Getwd returns PWD when it names the working directory.
|
||||
t.Chdir(filepath.Join(root, tc.workDir))
|
||||
|
||||
opts := testOpts(slices.Concat(
|
||||
[]string{testApp, cmdFreshen, "-q"}, tc.args,
|
||||
), fs)
|
||||
require.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts))
|
||||
|
||||
assertManifestLists(t, fs, tree, manifestPath,
|
||||
map[string]string{testFileTxt: "content1", "added.txt": "added"})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestFreshenRecordEntryMtimePresence pins the behavior of recordEntry
|
||||
// with respect to MFFilePath.Mtime, which is a message pointer with
|
||||
// proto3 field presence and may legitimately be absent.
|
||||
|
||||
Reference in New Issue
Block a user