Support unlinking package subpaths

This commit is contained in:
2026-02-19 17:07:38 +00:00
parent c5d1aef52b
commit 6f2be07272

83
main.go
View File

@@ -87,11 +87,33 @@ func parsePackageFlags(args []string) (packageFlags, string, error) {
pkg = arg
}
if pkg == "" {
return flags, "", errors.New("missing package name")
return flags, "", errors.New("missing package")
}
return flags, pkg, nil
}
func splitPackageSpec(spec string) (string, string, error) {
if spec == "" {
return "", "", errors.New("missing package")
}
parts := strings.SplitN(spec, ":", 2)
pkg := parts[0]
rel := ""
if len(parts) == 2 {
rel = parts[1]
}
pkg = strings.Trim(pkg, "/")
rel = strings.TrimPrefix(rel, "/")
if pkg == "" {
return "", "", errors.New("invalid package")
}
return pkg, rel, nil
}
func applyCmd(args []string) error {
prune := false
for _, arg := range args {
@@ -275,7 +297,12 @@ func addCmd(args []string) error {
}
func unlinkCmd(args []string) error {
flags, pkgName, err := parsePackageFlags(args)
flags, pkgSpec, err := parsePackageFlags(args)
if err != nil {
return err
}
pkgName, relPath, err := splitPackageSpec(pkgSpec)
if err != nil {
return err
}
@@ -302,7 +329,11 @@ func unlinkCmd(args []string) error {
return err
}
if relPath == "" {
return restorePackage(filesDir, targetRoot, flags.dryRun)
}
return restorePath(filesDir, targetRoot, relPath, flags.dryRun)
}
func removeCmd(args []string) error {
@@ -708,7 +739,52 @@ func restorePackage(filesDir, targetRoot string, dryRun bool) error {
return err
}
targetPath := filepath.Join(targetRoot, rel)
return restoreOne(path, targetPath, filesAbs, dryRun)
})
}
func restorePath(filesDir, targetRoot, relPath string, dryRun bool) error {
filesAbs, err := filepath.Abs(filesDir)
if err != nil {
return err
}
relPath = filepath.Clean(relPath)
if strings.HasPrefix(relPath, "..") || filepath.IsAbs(relPath) {
return fmt.Errorf("invalid relative path %q", relPath)
}
sourcePath := filepath.Join(filesDir, relPath)
info, err := os.Lstat(sourcePath)
if err != nil {
return err
}
if info.IsDir() {
return filepath.WalkDir(sourcePath, func(path string, entry fs.DirEntry, err error) error {
if err != nil {
return err
}
if entry.IsDir() {
return nil
}
rel, err := filepath.Rel(filesDir, path)
if err != nil {
return err
}
targetPath := filepath.Join(targetRoot, rel)
return restoreOne(path, targetPath, filesAbs, dryRun)
})
}
rel, err := filepath.Rel(filesDir, sourcePath)
if err != nil {
return err
}
return restoreOne(sourcePath, filepath.Join(targetRoot, rel), filesAbs, dryRun)
}
func restoreOne(sourcePath, targetPath, filesAbs string, dryRun bool) error {
info, err := os.Lstat(targetPath)
if errors.Is(err, os.ErrNotExist) {
return nil
@@ -742,8 +818,7 @@ func restorePackage(filesDir, targetRoot string, dryRun bool) error {
return err
}
return copyFile(path, targetPath)
})
return copyFile(sourcePath, targetPath)
}
func copyFile(src, dst string) error {