MCPcopy
hub / github.com/cli/cli / installLocalSkill

Function installLocalSkill

internal/skills/installer/installer.go:180–249  ·  view source on GitHub ↗
(sourceRoot string, skill discovery.Skill, baseDir string)

Source from the content-addressed store, hash-verified

178}
179
180func installLocalSkill(sourceRoot string, skill discovery.Skill, baseDir string) error {
181 // Use skill.Name (not InstallName) so skills are always installed flat.
182 // Most agent clients only discover immediate subdirectories of their
183 // skills folder and do not find skills nested under namespace directories.
184 skillDir := filepath.Join(baseDir, skill.Name)
185 if err := os.MkdirAll(skillDir, 0o755); err != nil {
186 return fmt.Errorf("could not create directory %s: %w", skillDir, err)
187 }
188
189 srcDir := filepath.Join(sourceRoot, filepath.FromSlash(skill.Path))
190 absSource, err := filepath.Abs(srcDir)
191 if err != nil {
192 return fmt.Errorf("could not resolve source path: %w", err)
193 }
194
195 safeSkillDir, err := safepaths.ParseAbsolute(skillDir)
196 if err != nil {
197 return fmt.Errorf("could not resolve target path: %w", err)
198 }
199
200 return filepath.WalkDir(srcDir, func(p string, d os.DirEntry, walkErr error) error {
201 if walkErr != nil {
202 return walkErr
203 }
204 if d.Type()&os.ModeSymlink != 0 {
205 return nil
206 }
207 if d.IsDir() {
208 return nil
209 }
210
211 relPath, err := filepath.Rel(srcDir, p)
212 if err != nil {
213 return err
214 }
215
216 // Defensive: filepath.WalkDir cannot produce traversal paths, but we
217 // guard against it in case the walk input is ever changed.
218 safeDest, err := safeSkillDir.Join(relPath)
219 if err != nil {
220 var traversalErr safepaths.PathTraversalError
221 if errors.As(err, &traversalErr) {
222 return fmt.Errorf("blocked path traversal in %q", relPath)
223 }
224 return fmt.Errorf("could not resolve destination path: %w", err)
225 }
226 destPath := safeDest.String()
227
228 if dir := filepath.Dir(destPath); dir != skillDir {
229 if err := os.MkdirAll(dir, 0o755); err != nil {
230 return fmt.Errorf("could not create directory: %w", err)
231 }
232 }
233
234 content, err := os.ReadFile(p)
235 if err != nil {
236 return fmt.Errorf("could not read %s: %w", p, err)
237 }

Callers 1

InstallLocalFunction · 0.85

Calls 7

ParseAbsoluteFunction · 0.92
InjectLocalMetadataFunction · 0.92
JoinMethod · 0.80
BaseMethod · 0.80
ErrorfMethod · 0.65
TypeMethod · 0.45
StringMethod · 0.45

Tested by

no test coverage detected