16
16
package tools
17
17
18
18
import (
19
- "bytes"
20
19
"context"
21
- "crypto/sha256"
22
- "encoding/hex"
23
- "encoding/json"
24
20
"errors"
25
- "fmt"
26
- "io"
27
- "net/http"
28
21
"os"
29
22
"os/exec"
30
23
"path/filepath"
31
24
"runtime"
32
25
26
+ "github.com/arduino/arduino-create-agent/gen/tools"
27
+ "github.com/arduino/arduino-create-agent/utilities"
33
28
"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"
37
29
)
38
30
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
-
56
31
// Download will parse the index at the indexURL for the tool to download.
57
32
// It will extract it in a folder in .arduino-create, and it will update the
58
33
// Installed map.
@@ -70,97 +45,21 @@ func pathExists(path string) bool {
70
45
// if it already exists.
71
46
func (t * Tools ) Download (pack , name , version , behaviour string ) error {
72
47
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 })
105
50
if err != nil {
106
51
return err
107
52
}
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 ()
134
53
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 )
145
56
if err != nil {
146
57
return err
147
58
}
148
59
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
-
161
60
// if the tool contains a post_install script, run it: it means it is a tool that needs to install drivers
162
61
// AFAIK this is only the case for the windows-driver tool
163
- err = t .installDrivers (location . String () )
62
+ err = t .installDrivers (safePath )
164
63
if err != nil {
165
64
return err
166
65
}
@@ -169,63 +68,20 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
169
68
t .logger ("Ensure that the files are executable" )
170
69
171
70
// 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 )
178
72
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 )
185
75
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
221
77
}
222
78
223
79
func (t * Tools ) installDrivers (location string ) error {
224
80
OkPressed := 6
225
81
extension := ".bat"
226
82
// add .\ to force locality
227
83
preamble := ".\\ "
228
- if OS != "windows" {
84
+ if runtime . GOOS != "windows" {
229
85
extension = ".sh"
230
86
// add ./ to force locality
231
87
preamble = "./"
@@ -237,7 +93,7 @@ func (t *Tools) installDrivers(location string) error {
237
93
os .Chdir (location )
238
94
t .logger (preamble + "post_install" + extension )
239
95
oscmd := exec .Command (preamble + "post_install" + extension )
240
- if OS != "linux" {
96
+ if runtime . GOOS != "linux" {
241
97
// spawning a shell could be the only way to let the user type his password
242
98
TellCommandNotToSpawnShell (oscmd )
243
99
}
0 commit comments