diff --git a/cmd/vinegar/binary_setup.go b/cmd/vinegar/binary_setup.go index 25b2398e..c0175384 100644 --- a/cmd/vinegar/binary_setup.go +++ b/cmd/vinegar/binary_setup.go @@ -59,8 +59,8 @@ func (b *Binary) Setup() error { return fmt.Errorf("apply fflags: %w", err) } - if err := dirs.OverlayDir(b.Dir); err != nil { - return fmt.Errorf("overlay dir: %w", err) + if err := dirs.OverlayDir(dirs.Overlay, b.Dir); err != nil { + return err } if err := b.SetupDxvk(); err != nil { diff --git a/internal/dirs/copy.go b/internal/dirs/copy.go index ef31b64f..f1ec30aa 100644 --- a/internal/dirs/copy.go +++ b/internal/dirs/copy.go @@ -2,14 +2,41 @@ package dirs import ( "errors" - "log/slog" "os" + "log/slog" + "path/filepath" + cp "github.com/otiai10/copy" ) -func OverlayDir(dir string) error { - _, err := os.Stat(Overlay) +func CompareLink(src, dest string) (bool, error) { + info, err := os.Stat(src) + if err != nil { + return false, err + } + + if info.Mode()&os.ModeSymlink != 0 { + srcSymPath, err := filepath.EvalSymlinks(src) + if err != nil { + return false, err + } + + destSymPath, err := filepath.EvalSymlinks(dest) + if err != nil { + return false, err + } + + if destSymPath != srcSymPath { + return false, nil + } + } + + return true, nil +} + +func OverlayDir(overlay, dir string) error { + _, err := os.Stat(overlay) if errors.Is(err, os.ErrNotExist) { return nil } else if err != nil { @@ -18,5 +45,20 @@ func OverlayDir(dir string) error { slog.Info("Copying Overlay directory's files", "dir", dir) - return cp.Copy(Overlay, dir) + return cp.Copy(overlay, dir, cp.Options{ + Sync: true, + PreserveOwner: true, + PreserveTimes: true, + Skip: func(info os.FileInfo, src, dest string) (bool, error) { + if info.IsDir() { + return false, nil + } + + if res, err := CompareLink(src, dest); err == nil && res { + return true, nil + } + + return false, nil + }, + }) } diff --git a/internal/dirs/copy_test.go b/internal/dirs/copy_test.go new file mode 100644 index 00000000..8adf74b2 --- /dev/null +++ b/internal/dirs/copy_test.go @@ -0,0 +1,62 @@ +package dirs + +import ( + "os" + "testing" + + "path/filepath" +) + +func createTestFile(t *testing.T, overlay, dest string) (string, string) { + if err := Mkdirs(filepath.Join(overlay, "content"), filepath.Join(dest, "content")); err != nil { + t.Fatal(err) + } + + srcPath := filepath.Join(overlay, "content", "test_content.txt") + destPath := filepath.Join(dest, "content", "test_content.txt") + + file, err := os.OpenFile(srcPath, os.O_CREATE|os.O_WRONLY, 0o755) + if err != nil { + t.Fatal(err) + } + + if _, err := file.WriteString("MEOWMEOW TESTING YAHH!!"); err != nil { + file.Close() + t.Fatal(err) + } + + if err := file.Close(); err != nil { + t.Fatal(err) + } + + return srcPath, destPath +} + +func test(t *testing.T, overlay, dest, srcPath, destPath string) { + if err := OverlayDir(overlay, dest); err != nil { + t.Fatal(err) + } + + + if res, err := CompareLink(srcPath, destPath); err != nil && !res { + t.Fatal(err) + } +} + +func TestDefault(t *testing.T) { + overlay := t.TempDir() + dest := t.TempDir() + + srcPath, destPath := createTestFile(t, overlay, dest) + test(t, overlay, dest, srcPath, destPath) +} + +func TestAlreadyExists(t *testing.T) { + overlay := t.TempDir() + dest := t.TempDir() + + srcPath, destPath := createTestFile(t, overlay, dest) + + test(t, overlay, dest, srcPath, destPath) + test(t, overlay, dest, srcPath, destPath) +}