@@ -82,8 +82,15 @@ func cmdCollect(args []string) error {
8282
8383 applyModeLabel (mode )
8484
85+ resources , rest , err := parseResourceFlags (rest , resourceFlagOptions {
86+ defaultSelection : resourceSelection {skills : true },
87+ })
88+ if err != nil {
89+ return err
90+ }
91+
8592 if mode == modeProject {
86- err := cmdCollectProject (rest , cwd )
93+ err := cmdCollectProject (rest , cwd , resources )
8794 logCollectOp (config .ProjectConfigPath (cwd ), start , err )
8895 return err
8996 }
@@ -116,6 +123,20 @@ func cmdCollect(args []string) error {
116123 force = true
117124 }
118125
126+ if resources .onlyManaged () {
127+ if targetName != "" || collectAll {
128+ return fmt .Errorf ("target selection is only supported when collecting skills" )
129+ }
130+ if jsonOutput {
131+ result , collectErr := collectManagedResources ("" , resources , dryRun , force )
132+ logCollectOp (config .ConfigPath (), start , collectErr )
133+ return collectOutputJSON (result , dryRun , start , collectErr )
134+ }
135+ err := executeManagedCollect ("" , resources , dryRun , force )
136+ logCollectOp (config .ConfigPath (), start , err )
137+ return err
138+ }
139+
119140 cfg , err := config .Load ()
120141 if err != nil {
121142 if jsonOutput {
@@ -146,48 +167,83 @@ func cmdCollect(args []string) error {
146167 if sp != nil {
147168 sp .Success ("No local skills found" )
148169 }
149- if jsonOutput {
150- return collectOutputJSON (nil , dryRun , start , nil )
170+ if ! resources .includesManaged () {
171+ if jsonOutput {
172+ return collectOutputJSON (nil , dryRun , start , nil )
173+ }
174+ return nil
151175 }
152- return nil
153- }
154-
155- if sp != nil {
176+ } else if sp != nil {
156177 sp .Success (fmt .Sprintf ("Found %d local skill(s)" , len (allLocalSkills )))
157178 displayLocalSkills (allLocalSkills )
158179 }
159180
160181 if dryRun {
161182 if jsonOutput {
162- names := make ([]string , len (allLocalSkills ))
163- for i , s := range allLocalSkills {
164- names [i ] = s .Name
183+ var result * sync.PullResult
184+ if len (allLocalSkills ) > 0 {
185+ names := make ([]string , len (allLocalSkills ))
186+ for i , s := range allLocalSkills {
187+ names [i ] = s .Name
188+ }
189+ result = & sync.PullResult {Pulled : names , Failed : make (map [string ]error )}
190+ }
191+ if resources .includesManaged () {
192+ managedResult , managedErr := collectManagedResources ("" , resources , true , force )
193+ result = mergePullResults (result , managedResult )
194+ logCollectOp (config .ConfigPath (), start , managedErr )
195+ return collectOutputJSON (result , true , start , managedErr )
165196 }
166197 logCollectOp (config .ConfigPath (), start , nil )
167- return collectOutputJSON (& sync.PullResult {Pulled : names }, true , start , nil )
198+ return collectOutputJSON (result , true , start , nil )
199+ }
200+ if resources .includesManaged () {
201+ err := executeManagedCollect ("" , resources , true , force )
202+ logCollectOp (config .ConfigPath (), start , err )
203+ return err
168204 }
169205 ui .Info ("Dry run - no changes made" )
170206 return nil
171207 }
172208
173209 // Confirm unless --force (JSON implies force)
174- if ! force {
210+ if ! force && len ( allLocalSkills ) > 0 {
175211 if ! confirmCollect () {
176212 ui .Info ("Cancelled" )
177213 return nil
178214 }
179215 }
180216
181217 if jsonOutput {
182- result , collectErr := sync .PullSkills (allLocalSkills , cfg .Source , sync.PullOptions {
183- DryRun : dryRun ,
184- Force : force ,
185- })
186- logCollectOp (config .ConfigPath (), start , collectErr )
187- return collectOutputJSON (result , dryRun , start , collectErr )
218+ var result * sync.PullResult
219+ var collectErr error
220+ if len (allLocalSkills ) > 0 {
221+ result , collectErr = sync .PullSkills (allLocalSkills , cfg .Source , sync.PullOptions {
222+ DryRun : dryRun ,
223+ Force : force ,
224+ })
225+ collectErr = combineCollectErrors (collectErr , collectResultError (result ))
226+ }
227+ var managedErr error
228+ if resources .includesManaged () {
229+ var managedResult * sync.PullResult
230+ managedResult , managedErr = collectManagedResources ("" , resources , dryRun , force )
231+ result = mergePullResults (result , managedResult )
232+ }
233+ err = combineCollectErrors (collectErr , managedErr )
234+ logCollectOp (config .ConfigPath (), start , err )
235+ return collectOutputJSON (result , dryRun , start , err )
188236 }
189237
190- err = executeCollect (allLocalSkills , cfg .Source , dryRun , force )
238+ var collectErr error
239+ if len (allLocalSkills ) > 0 {
240+ collectErr = executeCollect (allLocalSkills , cfg .Source , dryRun , force )
241+ }
242+ var managedErr error
243+ if resources .includesManaged () {
244+ managedErr = executeManagedCollect ("" , resources , dryRun , force )
245+ }
246+ err = combineCollectErrors (collectErr , managedErr )
191247 logCollectOp (config .ConfigPath (), start , err )
192248 return err
193249}
@@ -261,7 +317,7 @@ func executeCollect(skills []sync.LocalSkillInfo, source string, dryRun, force b
261317 showCollectNextSteps (source )
262318 }
263319
264- return nil
320+ return collectResultError ( result )
265321}
266322
267323// collectOutputJSON converts a collect result to JSON and writes to stdout.
@@ -290,12 +346,58 @@ func showCollectNextSteps(source string) {
290346 ui .Info ("Run 'skillshare sync' to distribute to all targets" )
291347
292348 // Check if source has git
349+ if strings .TrimSpace (source ) == "" {
350+ return
351+ }
293352 gitDir := filepath .Join (source , ".git" )
294353 if _ , err := os .Stat (gitDir ); err == nil {
295354 ui .Info ("Commit changes: cd %s && git add . && git commit" , source )
296355 }
297356}
298357
358+ func mergePullResults (left , right * sync.PullResult ) * sync.PullResult {
359+ switch {
360+ case left == nil :
361+ return right
362+ case right == nil :
363+ return left
364+ }
365+
366+ merged := & sync.PullResult {
367+ Pulled : append (append ([]string {}, left .Pulled ... ), right .Pulled ... ),
368+ Skipped : append (append ([]string {}, left .Skipped ... ), right .Skipped ... ),
369+ Failed : make (map [string ]error , len (left .Failed )+ len (right .Failed )),
370+ }
371+ for name , err := range left .Failed {
372+ merged .Failed [name ] = err
373+ }
374+ for name , err := range right .Failed {
375+ merged .Failed [name ] = err
376+ }
377+ return merged
378+ }
379+
380+ func collectResultError (result * sync.PullResult ) error {
381+ if result == nil || len (result .Failed ) == 0 {
382+ return nil
383+ }
384+ return fmt .Errorf ("some skills failed to collect" )
385+ }
386+
387+ func combineCollectErrors (errs ... error ) error {
388+ messages := make ([]string , 0 , len (errs ))
389+ for _ , err := range errs {
390+ if err == nil {
391+ continue
392+ }
393+ messages = append (messages , err .Error ())
394+ }
395+ if len (messages ) == 0 {
396+ return nil
397+ }
398+ return fmt .Errorf ("%s" , strings .Join (messages , "; " ))
399+ }
400+
299401func printCollectHelp () {
300402 fmt .Println (`Usage: skillshare collect [target] [options]
301403
0 commit comments