feat(go): implement unlink

This commit is contained in:
Micheal Wilkinson
2026-03-19 14:11:49 +00:00
parent dbc77a1b34
commit 919f033c8b
3 changed files with 209 additions and 4 deletions

View File

@@ -173,8 +173,44 @@ func (a *App) LinkCastle(castle string) error {
return nil
}
func (a *App) Unlink(string) error {
return errors.New("unlink is not implemented in Go yet")
func (a *App) Unlink(castle string) error {
if strings.TrimSpace(castle) == "" {
castle = "dotfiles"
}
return a.UnlinkCastle(castle)
}
func (a *App) UnlinkCastle(castle string) error {
castleHome := filepath.Join(a.ReposDir, castle, "home")
info, err := os.Stat(castleHome)
if err != nil || !info.IsDir() {
return fmt.Errorf("could not symlink %s, expected %s to exist and contain dotfiles", castle, castleHome)
}
subdirs, err := readSubdirs(filepath.Join(a.ReposDir, castle, ".homesick_subdir"))
if err != nil {
return err
}
if err := a.unlinkEach(castleHome, castleHome, subdirs); err != nil {
return err
}
for _, subdir := range subdirs {
base := filepath.Join(castleHome, subdir)
if _, err := os.Stat(base); err != nil {
if errors.Is(err, os.ErrNotExist) {
continue
}
return err
}
if err := a.unlinkEach(castleHome, base, subdirs); err != nil {
return err
}
}
return nil
}
func (a *App) Track(string, string) error {
@@ -220,6 +256,61 @@ func (a *App) linkEach(castleHome string, baseDir string, subdirs []string) erro
return nil
}
func (a *App) unlinkEach(castleHome string, baseDir string, subdirs []string) error {
entries, err := os.ReadDir(baseDir)
if err != nil {
return err
}
for _, entry := range entries {
name := entry.Name()
if name == "." || name == ".." {
continue
}
source := filepath.Join(baseDir, name)
ignore, err := matchesIgnoredDir(castleHome, source, subdirs)
if err != nil {
return err
}
if ignore {
continue
}
relDir, err := filepath.Rel(castleHome, baseDir)
if err != nil {
return err
}
destination := filepath.Join(a.HomeDir, relDir, name)
if relDir == "." {
destination = filepath.Join(a.HomeDir, name)
}
if err := unlinkPath(destination); err != nil {
return err
}
}
return nil
}
func unlinkPath(destination string) error {
info, err := os.Lstat(destination)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return nil
}
return err
}
if info.Mode()&os.ModeSymlink == 0 {
return nil
}
return os.Remove(destination)
}
func (a *App) linkPath(source string, destination string) error {
absSource, err := filepath.Abs(source)
if err != nil {