mirror of
https://github.com/yarlson/lnk.git
synced 2025-09-01 18:02:34 +02:00
fix(init): prevent data loss when reinitializing with existing content
This commit is contained in:
@@ -3,6 +3,7 @@ package core
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -1432,6 +1433,170 @@ func (suite *CoreTestSuite) TestPreviewAddValidation() {
|
||||
suite.Contains(err.Error(), "already managed", "Error should mention already managed")
|
||||
}
|
||||
|
||||
// Task 1.1: Tests for HasUserContent() method
|
||||
func (suite *CoreTestSuite) TestHasUserContent_WithCommonTracker_ReturnsTrue() {
|
||||
// Initialize lnk repository
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Create .lnk file to simulate existing content
|
||||
lnkFile := filepath.Join(suite.tempDir, "lnk", ".lnk")
|
||||
err = os.WriteFile(lnkFile, []byte(".bashrc\n"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Call HasUserContent()
|
||||
hasContent := suite.lnk.HasUserContent()
|
||||
suite.True(hasContent, "Should detect common tracker file")
|
||||
}
|
||||
|
||||
func (suite *CoreTestSuite) TestHasUserContent_WithHostTracker_ReturnsTrue() {
|
||||
// Initialize lnk repository
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Create host-specific lnk instance
|
||||
hostLnk := NewLnk(WithHost("testhost"))
|
||||
|
||||
// Create .lnk.hostname file to simulate host-specific content
|
||||
lnkFile := filepath.Join(suite.tempDir, "lnk", ".lnk.testhost")
|
||||
err = os.WriteFile(lnkFile, []byte(".vimrc\n"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Call HasUserContent()
|
||||
hasContent := hostLnk.HasUserContent()
|
||||
suite.True(hasContent, "Should detect host-specific tracker file")
|
||||
}
|
||||
|
||||
func (suite *CoreTestSuite) TestHasUserContent_WithBothTrackers_ReturnsTrue() {
|
||||
// Initialize lnk repository
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Create both common and host-specific tracker files
|
||||
commonLnkFile := filepath.Join(suite.tempDir, "lnk", ".lnk")
|
||||
err = os.WriteFile(commonLnkFile, []byte(".bashrc\n"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
hostLnkFile := filepath.Join(suite.tempDir, "lnk", ".lnk.testhost")
|
||||
err = os.WriteFile(hostLnkFile, []byte(".vimrc\n"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Test with common instance
|
||||
hasContent := suite.lnk.HasUserContent()
|
||||
suite.True(hasContent, "Should detect common tracker file")
|
||||
|
||||
// Test with host-specific instance
|
||||
hostLnk := NewLnk(WithHost("testhost"))
|
||||
hasContent = hostLnk.HasUserContent()
|
||||
suite.True(hasContent, "Should detect host-specific tracker file")
|
||||
}
|
||||
|
||||
func (suite *CoreTestSuite) TestHasUserContent_EmptyDirectory_ReturnsFalse() {
|
||||
// Initialize lnk repository
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Call HasUserContent() on empty repository
|
||||
hasContent := suite.lnk.HasUserContent()
|
||||
suite.False(hasContent, "Should return false for empty repository")
|
||||
}
|
||||
|
||||
func (suite *CoreTestSuite) TestHasUserContent_NonTrackerFiles_ReturnsFalse() {
|
||||
// Initialize lnk repository
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Create non-tracker files
|
||||
randomFile := filepath.Join(suite.tempDir, "lnk", "random.txt")
|
||||
err = os.WriteFile(randomFile, []byte("some content"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
configFile := filepath.Join(suite.tempDir, "lnk", ".gitignore")
|
||||
err = os.WriteFile(configFile, []byte("*.log"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Call HasUserContent()
|
||||
hasContent := suite.lnk.HasUserContent()
|
||||
suite.False(hasContent, "Should return false when only non-tracker files exist")
|
||||
}
|
||||
|
||||
// Task 2.1: Tests for enhanced InitWithRemote() safety check
|
||||
func (suite *CoreTestSuite) TestInitWithRemote_HasUserContent_ReturnsError() {
|
||||
// Initialize and add content first
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Create .lnk file to simulate existing content
|
||||
lnkFile := filepath.Join(suite.tempDir, "lnk", ".lnk")
|
||||
err = os.WriteFile(lnkFile, []byte(".bashrc\n"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Try InitWithRemote - should fail
|
||||
err = suite.lnk.InitWithRemote("https://github.com/test/dotfiles.git")
|
||||
suite.Error(err, "Should fail when user content exists")
|
||||
suite.Contains(err.Error(), "already contains managed files")
|
||||
suite.Contains(err.Error(), "lnk pull")
|
||||
|
||||
// Verify .lnk file still exists (no deletion occurred)
|
||||
suite.FileExists(lnkFile)
|
||||
}
|
||||
|
||||
func (suite *CoreTestSuite) TestInitWithRemote_EmptyDirectory_Success() {
|
||||
// Create a dummy remote directory for testing
|
||||
remoteDir := filepath.Join(suite.tempDir, "remote")
|
||||
err := os.MkdirAll(remoteDir, 0755)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Initialize a bare git repository as remote
|
||||
cmd := exec.Command("git", "init", "--bare")
|
||||
cmd.Dir = remoteDir
|
||||
err = cmd.Run()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// InitWithRemote should succeed on empty directory
|
||||
err = suite.lnk.InitWithRemote(remoteDir)
|
||||
suite.NoError(err, "Should succeed when no user content exists")
|
||||
|
||||
// Verify repository was cloned
|
||||
lnkDir := filepath.Join(suite.tempDir, "lnk")
|
||||
suite.DirExists(lnkDir)
|
||||
gitDir := filepath.Join(lnkDir, ".git")
|
||||
suite.DirExists(gitDir)
|
||||
}
|
||||
|
||||
func (suite *CoreTestSuite) TestInitWithRemote_NoRemoteURL_BypassesSafetyCheck() {
|
||||
// Initialize and add content first
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Create .lnk file to simulate existing content
|
||||
lnkFile := filepath.Join(suite.tempDir, "lnk", ".lnk")
|
||||
err = os.WriteFile(lnkFile, []byte(".bashrc\n"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// InitWithRemote with empty URL should bypass safety check (this is local init)
|
||||
err = suite.lnk.InitWithRemote("")
|
||||
suite.NoError(err, "Should bypass safety check when no remote URL provided")
|
||||
}
|
||||
|
||||
func (suite *CoreTestSuite) TestInitWithRemote_ErrorMessage_ContainsSuggestedCommand() {
|
||||
// Initialize and add content first
|
||||
err := suite.lnk.Init()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Create host-specific content
|
||||
hostLnk := NewLnk(WithHost("testhost"))
|
||||
hostLnkFile := filepath.Join(suite.tempDir, "lnk", ".lnk.testhost")
|
||||
err = os.WriteFile(hostLnkFile, []byte(".vimrc\n"), 0644)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Try InitWithRemote - should fail with helpful message
|
||||
err = hostLnk.InitWithRemote("https://github.com/test/dotfiles.git")
|
||||
suite.Error(err, "Should fail when user content exists")
|
||||
suite.Contains(err.Error(), "lnk pull", "Should suggest pull command")
|
||||
suite.Contains(err.Error(), "instead of", "Should explain alternative")
|
||||
}
|
||||
|
||||
func TestCoreSuite(t *testing.T) {
|
||||
suite.Run(t, new(CoreTestSuite))
|
||||
}
|
||||
|
Reference in New Issue
Block a user