Prompt per stale link during apply

This commit is contained in:
2026-02-19 17:18:37 +00:00
parent 05da6b2c53
commit dd470f39c7

108
main.go
View File

@@ -188,15 +188,7 @@ func applyCmd(args []string) error {
} }
fmt.Printf("Stale links found: %d\n", len(stales)) fmt.Printf("Stale links found: %d\n", len(stales))
ok, err := promptYesNo("Prune them?", false) return handleStaleLinks(stales)
if err != nil {
return err
}
if ok {
return removeLinks(stales, false)
}
return nil
} }
func addCmd(args []string) error { func addCmd(args []string) error {
@@ -761,6 +753,104 @@ func removeLinks(paths []string, dryRun bool) error {
return nil return nil
} }
func handleStaleLinks(stales []string) error {
if len(stales) == 0 {
return nil
}
repo, err := repoPath()
if err != nil {
return err
}
reader := bufio.NewReader(os.Stdin)
for _, path := range stales {
fmt.Printf("stale: %s\n", path)
fmt.Print("action [p=prune, u=unlink, i=ignore]: ")
choice, err := reader.ReadString('\n')
if err != nil {
return err
}
choice = strings.TrimSpace(strings.ToLower(choice))
if choice == "" || choice == "i" {
continue
}
if choice == "p" {
if err := os.Remove(path); err != nil {
return err
}
fmt.Printf("removed %s\n", path)
continue
}
if choice == "u" {
if err := unlinkStale(path, repo); err != nil {
return err
}
continue
}
fmt.Println("invalid choice; skipping")
}
return nil
}
func unlinkStale(targetPath, repo string) error {
info, err := os.Lstat(targetPath)
if err != nil {
return err
}
if info.Mode()&os.ModeSymlink == 0 {
return nil
}
src, err := os.Readlink(targetPath)
if err != nil {
return err
}
if !filepath.IsAbs(src) {
src = filepath.Join(filepath.Dir(targetPath), src)
}
src = filepath.Clean(src)
repoAbs, err := filepath.Abs(repo)
if err != nil {
return err
}
rel, err := filepath.Rel(repoAbs, src)
if err != nil {
return err
}
if strings.HasPrefix(rel, "..") {
return nil
}
parts := strings.Split(rel, string(os.PathSeparator))
if len(parts) < 3 {
return nil
}
if parts[1] != filesDirName {
return nil
}
repoPath := filepath.Join(repoAbs, rel)
if err := os.Remove(targetPath); err != nil {
return err
}
if err := copyFile(repoPath, targetPath); err != nil {
return err
}
if err := os.Remove(repoPath); err != nil {
return err
}
fmt.Printf("unlinked %s (removed %s)\n", targetPath, repoPath)
return nil
}
func restorePackage(filesDir, targetRoot string, dryRun bool) error { func restorePackage(filesDir, targetRoot string, dryRun bool) error {
filesAbs, err := filepath.Abs(filesDir) filesAbs, err := filepath.Abs(filesDir)
if err != nil { if err != nil {