@@ -33,6 +33,7 @@ import (
3333 "github.com/arduino/arduino-create-agent/gen/tools"
3434 "github.com/arduino/arduino-create-agent/index"
3535 "github.com/arduino/arduino-create-agent/utilities"
36+ "github.com/arduino/go-paths-helper"
3637 "github.com/codeclysm/extract/v3"
3738)
3839
@@ -222,12 +223,36 @@ func (t *Tools) install(ctx context.Context, path, url, checksum string) (*tools
222223 return nil , err
223224 }
224225
225- err = extract .Archive (ctx , & buffer , t .folder , rename (path ))
226+ tempPath := paths .TempDir ()
227+ // Create a temporary dir to extract package
228+ if err := tempPath .MkdirAll (); err != nil {
229+ return nil , fmt .Errorf ("creating temp dir for extraction: %s" , err )
230+ }
231+ tempDir , err := tempPath .MkTempDir ("package-" )
226232 if err != nil {
227- os .RemoveAll (safePath )
233+ return nil , fmt .Errorf ("creating temp dir for extraction: %s" , err )
234+ }
235+ defer tempDir .RemoveAll ()
236+
237+ err = extract .Archive (ctx , & buffer , tempDir .String (), nil )
238+ if err != nil {
239+ os .RemoveAll (tempDir .String ())
228240 return nil , err
229241 }
230242
243+ // Check package content and find package root dir
244+ root , err := findPackageRoot (tempDir )
245+ if err != nil {
246+ return nil , fmt .Errorf ("searching package root dir: %s" , err )
247+ }
248+
249+ location := paths .New (safePath )
250+ if err := root .Rename (location ); err != nil {
251+ if err := root .CopyDirTo (location ); err != nil {
252+ return nil , fmt .Errorf ("moving extracted archive to destination dir: %s" , err )
253+ }
254+ }
255+
231256 // Write installed.json for retrocompatibility with v1
232257 err = writeInstalled (t .folder , path )
233258 if err != nil {
@@ -253,15 +278,6 @@ func (t *Tools) Remove(ctx context.Context, payload *tools.ToolPayload) (*tools.
253278 return & tools.Operation {Status : "ok" }, nil
254279}
255280
256- func rename (base string ) extract.Renamer {
257- return func (path string ) string {
258- parts := strings .Split (filepath .ToSlash (path ), "/" )
259- path = strings .Join (parts [1 :], "/" )
260- path = filepath .Join (base , path )
261- return path
262- }
263- }
264-
265281func writeInstalled (folder , path string ) error {
266282 // read installed.json
267283 installed := map [string ]string {}
@@ -295,3 +311,17 @@ func writeInstalled(folder, path string) error {
295311
296312 return os .WriteFile (installedFile , data , 0644 )
297313}
314+
315+ func findPackageRoot (parent * paths.Path ) (* paths.Path , error ) {
316+ files , err := parent .ReadDir ()
317+ if err != nil {
318+ return nil , fmt .Errorf ("reading package root dir: %s" , err )
319+ }
320+ files .FilterOutPrefix ("__MACOSX" )
321+
322+ // if there is only one dir, it is the root dir
323+ if len (files ) == 1 && files [0 ].IsDir () {
324+ return files [0 ], nil
325+ }
326+ return parent , nil
327+ }
0 commit comments