mirror of https://github.com/Marcusk19/dotctl
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
8.9 KiB
Go
283 lines
8.9 KiB
Go
package test
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/Marcusk19/dotctl/cmd"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestLinkDotfiles_MissingTarget(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
// Create source dir in dotfileRoot
|
|
dotPath := filepath.Join(dotfileRoot, "nvim")
|
|
require.NoError(t, os.MkdirAll(dotPath, 0755))
|
|
|
|
// Target does not exist yet
|
|
targetPath := filepath.Join(targetRoot, ".config", "nvim")
|
|
|
|
links := map[string]string{"nvim": targetPath}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, false)
|
|
|
|
assert.Equal(t, 1, result.Linked, "should have linked 1")
|
|
assert.Equal(t, 0, result.Skipped)
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// Verify symlink was actually created and points to the right place
|
|
linkTarget, err := os.Readlink(targetPath)
|
|
require.NoError(t, err, "symlink should exist at targetPath")
|
|
assert.Equal(t, dotPath, linkTarget, "symlink should point to dotPath")
|
|
}
|
|
|
|
func TestLinkDotfiles_AlreadyLinked(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
dotPath := filepath.Join(dotfileRoot, "nvim")
|
|
require.NoError(t, os.MkdirAll(dotPath, 0755))
|
|
|
|
targetPath := filepath.Join(targetRoot, ".config", "nvim")
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(targetPath), 0755))
|
|
|
|
// Pre-create correct symlink
|
|
require.NoError(t, os.Symlink(dotPath, targetPath))
|
|
|
|
links := map[string]string{"nvim": targetPath}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, false)
|
|
|
|
assert.Equal(t, 0, result.Linked)
|
|
assert.Equal(t, 1, result.Skipped, "should have skipped 1 (already linked)")
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// Symlink should still point to dotPath
|
|
linkTarget, err := os.Readlink(targetPath)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, dotPath, linkTarget)
|
|
|
|
assert.Contains(t, buf.String(), "already linked")
|
|
}
|
|
|
|
func TestLinkDotfiles_WrongSymlink_NoOverwrite(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
dotPath := filepath.Join(dotfileRoot, "nvim")
|
|
require.NoError(t, os.MkdirAll(dotPath, 0755))
|
|
|
|
wrongPath := filepath.Join(t.TempDir(), "wrong")
|
|
require.NoError(t, os.MkdirAll(wrongPath, 0755))
|
|
|
|
targetPath := filepath.Join(targetRoot, ".config", "nvim")
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(targetPath), 0755))
|
|
|
|
// Pre-create symlink pointing to the wrong place
|
|
require.NoError(t, os.Symlink(wrongPath, targetPath))
|
|
|
|
links := map[string]string{"nvim": targetPath}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, false)
|
|
|
|
assert.Equal(t, 0, result.Linked)
|
|
assert.Equal(t, 1, result.Skipped, "should have skipped 1 (wrong symlink, no overwrite)")
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// Symlink should still point to the wrong path (unchanged)
|
|
linkTarget, err := os.Readlink(targetPath)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, wrongPath, linkTarget)
|
|
}
|
|
|
|
func TestLinkDotfiles_WrongSymlink_Overwrite(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
dotPath := filepath.Join(dotfileRoot, "nvim")
|
|
require.NoError(t, os.MkdirAll(dotPath, 0755))
|
|
|
|
wrongPath := filepath.Join(t.TempDir(), "wrong")
|
|
require.NoError(t, os.MkdirAll(wrongPath, 0755))
|
|
|
|
targetPath := filepath.Join(targetRoot, ".config", "nvim")
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(targetPath), 0755))
|
|
|
|
// Pre-create symlink pointing to the wrong place
|
|
require.NoError(t, os.Symlink(wrongPath, targetPath))
|
|
|
|
links := map[string]string{"nvim": targetPath}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, true, false, false)
|
|
|
|
assert.Equal(t, 1, result.Linked, "should have relinked 1")
|
|
assert.Equal(t, 0, result.Skipped)
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// Symlink should now point to dotPath
|
|
linkTarget, err := os.Readlink(targetPath)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, dotPath, linkTarget, "symlink should now point to dotPath")
|
|
}
|
|
|
|
func TestLinkDotfiles_RealFile_WithBackup(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
dotPath := filepath.Join(dotfileRoot, "nvim")
|
|
require.NoError(t, os.MkdirAll(dotPath, 0755))
|
|
|
|
targetPath := filepath.Join(targetRoot, ".config", "nvim")
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(targetPath), 0755))
|
|
|
|
// Create a real file at the target path
|
|
require.NoError(t, os.WriteFile(targetPath, []byte("original content"), 0644))
|
|
|
|
links := map[string]string{"nvim": targetPath}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, false)
|
|
|
|
assert.Equal(t, 0, result.Linked)
|
|
assert.Equal(t, 0, result.Skipped)
|
|
assert.Equal(t, 1, result.Backed, "should have backed up 1")
|
|
|
|
// Backup file should exist with original content
|
|
backupPath := targetPath + ".dotctl.bak"
|
|
backupContent, err := os.ReadFile(backupPath)
|
|
require.NoError(t, err, "backup file should exist")
|
|
assert.Equal(t, "original content", string(backupContent))
|
|
|
|
// Target should now be a symlink to dotPath
|
|
linkTarget, err := os.Readlink(targetPath)
|
|
require.NoError(t, err, "target should be a symlink now")
|
|
assert.Equal(t, dotPath, linkTarget)
|
|
}
|
|
|
|
func TestLinkDotfiles_RealFile_NoBackup(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
dotPath := filepath.Join(dotfileRoot, "nvim")
|
|
require.NoError(t, os.MkdirAll(dotPath, 0755))
|
|
|
|
targetPath := filepath.Join(targetRoot, ".config", "nvim")
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(targetPath), 0755))
|
|
|
|
// Create a real file at the target path
|
|
require.NoError(t, os.WriteFile(targetPath, []byte("original content"), 0644))
|
|
|
|
links := map[string]string{"nvim": targetPath}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, true, false)
|
|
|
|
assert.Equal(t, 0, result.Linked)
|
|
assert.Equal(t, 1, result.Skipped, "should have skipped 1 (noBackup)")
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// Original file should be untouched
|
|
content, err := os.ReadFile(targetPath)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "original content", string(content))
|
|
|
|
// No backup file should exist
|
|
backupPath := targetPath + ".dotctl.bak"
|
|
_, err = os.Stat(backupPath)
|
|
assert.True(t, os.IsNotExist(err), "backup file should not exist")
|
|
}
|
|
|
|
func TestLinkDotfiles_DryRun(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
dotPath := filepath.Join(dotfileRoot, "nvim")
|
|
require.NoError(t, os.MkdirAll(dotPath, 0755))
|
|
|
|
targetPath := filepath.Join(targetRoot, ".config", "nvim")
|
|
// Do NOT create parent dirs - dryRun should not create them either
|
|
|
|
links := map[string]string{"nvim": targetPath}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, true)
|
|
|
|
assert.Equal(t, 1, result.Linked, "should count 1 linked even in dry run")
|
|
assert.Equal(t, 0, result.Skipped)
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// No symlink should actually be created
|
|
_, err := os.Lstat(targetPath)
|
|
assert.True(t, os.IsNotExist(err), "symlink should NOT be created in dry run")
|
|
|
|
assert.Contains(t, buf.String(), "would link")
|
|
}
|
|
|
|
func TestLinkDotfiles_SkipsGitAndDotctl(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
links := map[string]string{
|
|
".git": filepath.Join(targetRoot, ".git"),
|
|
"dotctl": filepath.Join(targetRoot, "dotctl"),
|
|
}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, false)
|
|
|
|
assert.Equal(t, 0, result.Linked)
|
|
assert.Equal(t, 0, result.Skipped)
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// Nothing should be created
|
|
_, err := os.Lstat(filepath.Join(targetRoot, ".git"))
|
|
assert.True(t, os.IsNotExist(err))
|
|
_, err = os.Lstat(filepath.Join(targetRoot, "dotctl"))
|
|
assert.True(t, os.IsNotExist(err))
|
|
}
|
|
|
|
func TestLinkDotfiles_EmptyTargetPath(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
|
|
links := map[string]string{"nvim": ""}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, false)
|
|
|
|
assert.Equal(t, 0, result.Linked)
|
|
assert.Equal(t, 1, result.Skipped, "empty target should be skipped")
|
|
assert.Equal(t, 0, result.Backed)
|
|
}
|
|
|
|
func TestLinkDotfiles_MultipleEntries(t *testing.T) {
|
|
dotfileRoot := t.TempDir()
|
|
targetRoot := t.TempDir()
|
|
|
|
// Create two source dirs
|
|
require.NoError(t, os.MkdirAll(filepath.Join(dotfileRoot, "nvim"), 0755))
|
|
require.NoError(t, os.MkdirAll(filepath.Join(dotfileRoot, "zsh"), 0755))
|
|
|
|
nvimTarget := filepath.Join(targetRoot, ".config", "nvim")
|
|
zshTarget := filepath.Join(targetRoot, ".zshrc")
|
|
|
|
links := map[string]string{
|
|
"nvim": nvimTarget,
|
|
"zsh": zshTarget,
|
|
}
|
|
var buf bytes.Buffer
|
|
result := cmd.LinkDotfiles(&buf, dotfileRoot, links, false, false, false)
|
|
|
|
assert.Equal(t, 2, result.Linked, "should have linked 2 entries")
|
|
assert.Equal(t, 0, result.Skipped)
|
|
assert.Equal(t, 0, result.Backed)
|
|
|
|
// Verify both symlinks
|
|
linkTarget, err := os.Readlink(nvimTarget)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, filepath.Join(dotfileRoot, "nvim"), linkTarget)
|
|
|
|
linkTarget, err = os.Readlink(zshTarget)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, filepath.Join(dotfileRoot, "zsh"), linkTarget)
|
|
}
|