MCPcopy
hub / github.com/kagent-dev/kagent / applySubPath

Function applySubPath

go/core/internal/skillsinit/git.go:65–112  ·  view source on GitHub ↗

applySubPath replaces dest with the contents of dest/subPath. The result is that dest contains only the requested subdirectory. We materialize the content into a sibling tmp dir under the same parent so the final rename is atomic on the same filesystem.

(dest, subPath string)

Source from the content-addressed store, hash-verified

63// content into a sibling tmp dir under the same parent so the final rename is
64// atomic on the same filesystem.
65func applySubPath(dest, subPath string) error {
66 // Defense in depth: filepath.IsLocal rejects absolute paths, ".."
67 // segments, and reserved names — exactly the set we want to refuse.
68 if !filepath.IsLocal(subPath) {
69 return fmt.Errorf("invalid subPath %q", subPath)
70 }
71 clean := filepath.Clean(subPath)
72 src := filepath.Join(dest, clean)
73 info, err := os.Stat(src)
74 if err != nil {
75 return fmt.Errorf("stat subPath: %w", err)
76 }
77 if !info.IsDir() {
78 return fmt.Errorf("subPath %q is not a directory", subPath)
79 }
80
81 parent := filepath.Dir(dest)
82 tmp, err := os.MkdirTemp(parent, ".skill-subpath-*")
83 if err != nil {
84 return fmt.Errorf("mktemp: %w", err)
85 }
86 // Best-effort cleanup if we fail before the rename.
87 cleanupTmp := tmp
88 defer func() {
89 if cleanupTmp != "" {
90 os.RemoveAll(cleanupTmp)
91 }
92 }()
93
94 // cp -rL: follow symlinks (matches the original behavior); both paths
95 // are constructed by us, never user-supplied, and are passed as argv —
96 // no shell, no metacharacter risk. Trailing "/." copies *contents* of
97 // src into tmp, not src itself.
98 cp := exec.Command("cp", "-rL", "--", src+"/.", tmp)
99 cp.Stdout = os.Stdout
100 cp.Stderr = os.Stderr
101 if err := cp.Run(); err != nil {
102 return fmt.Errorf("cp subPath contents: %w", err)
103 }
104 if err := os.RemoveAll(dest); err != nil {
105 return err
106 }
107 if err := os.Rename(tmp, dest); err != nil {
108 return err
109 }
110 cleanupTmp = ""
111 return nil
112}

Callers 3

CloneGitFunction · 0.85

Calls 2

JoinMethod · 0.45
RunMethod · 0.45