1616package tools
1717
1818import (
19- "bytes"
2019 "context"
21- "crypto/sha256"
22- "encoding/hex"
23- "encoding/json"
2420 "errors"
25- "fmt"
26- "io"
27- "net/http"
2821 "os"
2922 "os/exec"
3023 "path/filepath"
3124 "runtime"
3225
26+ "github.com/arduino/arduino-create-agent/gen/tools"
27+ "github.com/arduino/arduino-create-agent/utilities"
3328 "github.com/arduino/arduino-create-agent/v2/pkgs"
34- "github.com/arduino/go-paths-helper"
35- "github.com/blang/semver"
36- "github.com/codeclysm/extract/v3"
3729)
3830
39- // public vars to allow override in the tests
40- var (
41- OS = runtime .GOOS
42- Arch = runtime .GOARCH
43- )
44-
45- func pathExists (path string ) bool {
46- _ , err := os .Stat (path )
47- if err == nil {
48- return true
49- }
50- if os .IsNotExist (err ) {
51- return false
52- }
53- return true
54- }
55-
5631// Download will parse the index at the indexURL for the tool to download.
5732// It will extract it in a folder in .arduino-create, and it will update the
5833// Installed map.
@@ -70,97 +45,21 @@ func pathExists(path string) bool {
7045// if it already exists.
7146func (t * Tools ) Download (pack , name , version , behaviour string ) error {
7247
73- body , err := t .index .Read ()
74- if err != nil {
75- return err
76- }
77-
78- var data pkgs.Index
79- json .Unmarshal (body , & data )
80-
81- // Find the tool by name
82- correctTool , correctSystem := findTool (pack , name , version , data )
83-
84- if correctTool .Name == "" || correctSystem .URL == "" {
85- t .logger ("We couldn't find a tool with the name " + name + " and version " + version + " packaged by " + pack )
86- return nil
87- }
88-
89- key := correctTool .Name + "-" + correctTool .Version
90-
91- // Check if it already exists
92- if behaviour == "keep" {
93- location , ok := t .getMapValue (key )
94- if ok && pathExists (location ) {
95- // overwrite the default tool with this one
96- t .setMapValue (correctTool .Name , location )
97- t .logger ("The tool is already present on the system" )
98- return t .writeMap ()
99- }
100- }
101-
102- // Download the tool
103- t .logger ("Downloading tool " + name + " from " + correctSystem .URL )
104- resp , err := http .Get (correctSystem .URL )
48+ tool := pkgs .New (t .index , t .directory .String (), behaviour )
49+ _ , err := tool .Install (context .Background (), & tools.ToolPayload {Name : name , Version : version , Packager : pack })
10550 if err != nil {
10651 return err
10752 }
108- defer resp .Body .Close ()
109-
110- // Read the body
111- body , err = io .ReadAll (resp .Body )
112- if err != nil {
113- return err
114- }
115-
116- // Checksum
117- checksum := sha256 .Sum256 (body )
118- checkSumString := "SHA-256:" + hex .EncodeToString (checksum [:sha256 .Size ])
119-
120- if checkSumString != correctSystem .Checksum {
121- return errors .New ("checksum doesn't match" )
122- }
123-
124- tempPath := paths .TempDir ()
125- // Create a temporary dir to extract package
126- if err := tempPath .MkdirAll (); err != nil {
127- return fmt .Errorf ("creating temp dir for extraction: %s" , err )
128- }
129- tempDir , err := tempPath .MkTempDir ("package-" )
130- if err != nil {
131- return fmt .Errorf ("creating temp dir for extraction: %s" , err )
132- }
133- defer tempDir .RemoveAll ()
13453
135- t .logger ("Unpacking tool " + name )
136- ctx := context .Background ()
137- reader := bytes .NewReader (body )
138- // Extract into temp directory
139- if err := extract .Archive (ctx , reader , tempDir .String (), nil ); err != nil {
140- return fmt .Errorf ("extracting archive: %s" , err )
141- }
142-
143- location := t .directory .Join (pack , correctTool .Name , correctTool .Version )
144- err = location .RemoveAll ()
54+ path := filepath .Join (pack , name , version )
55+ safePath , err := utilities .SafeJoin (t .directory .String (), path )
14556 if err != nil {
14657 return err
14758 }
14859
149- // Check package content and find package root dir
150- root , err := findPackageRoot (tempDir )
151- if err != nil {
152- return fmt .Errorf ("searching package root dir: %s" , err )
153- }
154-
155- if err := root .Rename (location ); err != nil {
156- if err := root .CopyDirTo (location ); err != nil {
157- return fmt .Errorf ("moving extracted archive to destination dir: %s" , err )
158- }
159- }
160-
16160 // if the tool contains a post_install script, run it: it means it is a tool that needs to install drivers
16261 // AFAIK this is only the case for the windows-driver tool
163- err = t .installDrivers (location . String () )
62+ err = t .installDrivers (safePath )
16463 if err != nil {
16564 return err
16665 }
@@ -169,63 +68,20 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
16968 t .logger ("Ensure that the files are executable" )
17069
17170 // Update the tool map
172- t .logger ("Updating map with location " + location .String ())
173-
174- t .setMapValue (name , location .String ())
175- t .setMapValue (name + "-" + correctTool .Version , location .String ())
176- return t .writeMap ()
177- }
71+ t .logger ("Updating map with location " + safePath )
17872
179- func findPackageRoot (parent * paths.Path ) (* paths.Path , error ) {
180- files , err := parent .ReadDir ()
181- if err != nil {
182- return nil , fmt .Errorf ("reading package root dir: %s" , err )
183- }
184- files .FilterOutPrefix ("__MACOSX" )
73+ t .setMapValue (name , safePath )
74+ t .setMapValue (name + "-" + version , safePath )
18575
186- // if there is only one dir, it is the root dir
187- if len (files ) == 1 && files [0 ].IsDir () {
188- return files [0 ], nil
189- }
190- return parent , nil
191- }
192-
193- func findTool (pack , name , version string , data pkgs.Index ) (pkgs.Tool , pkgs.System ) {
194- var correctTool pkgs.Tool
195- correctTool .Version = "0.0"
196-
197- for _ , p := range data .Packages {
198- if p .Name != pack {
199- continue
200- }
201- for _ , t := range p .Tools {
202- if version != "latest" {
203- if t .Name == name && t .Version == version {
204- correctTool = t
205- }
206- } else {
207- // Find latest
208- v1 , _ := semver .Make (t .Version )
209- v2 , _ := semver .Make (correctTool .Version )
210- if t .Name == name && v1 .Compare (v2 ) > 0 {
211- correctTool = t
212- }
213- }
214- }
215- }
216-
217- // Find the url based on system
218- correctSystem := correctTool .GetFlavourCompatibleWith (OS , Arch )
219-
220- return correctTool , correctSystem
76+ return nil
22177}
22278
22379func (t * Tools ) installDrivers (location string ) error {
22480 OkPressed := 6
22581 extension := ".bat"
22682 // add .\ to force locality
22783 preamble := ".\\ "
228- if OS != "windows" {
84+ if runtime . GOOS != "windows" {
22985 extension = ".sh"
23086 // add ./ to force locality
23187 preamble = "./"
@@ -237,7 +93,7 @@ func (t *Tools) installDrivers(location string) error {
23793 os .Chdir (location )
23894 t .logger (preamble + "post_install" + extension )
23995 oscmd := exec .Command (preamble + "post_install" + extension )
240- if OS != "linux" {
96+ if runtime . GOOS != "linux" {
24197 // spawning a shell could be the only way to let the user type his password
24298 TellCommandNotToSpawnShell (oscmd )
24399 }
0 commit comments