Skip to content

Commit 252a80f

Browse files
committed
make tools.Tools struct properties unexported and use a "constructor"
1 parent 09d5009 commit 252a80f

File tree

3 files changed

+89
-93
lines changed

3 files changed

+89
-93
lines changed

main.go

+7-10
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,14 @@ func loop() {
180180
// Instantiate Index
181181
Index = index.Init(*indexURL, config.GetDataDir())
182182

183-
// Instantiate Tools
184-
Tools = tools.Tools{
185-
Directory: config.GetDataDir().String(),
186-
Index: Index,
187-
Logger: func(msg string) {
188-
mapD := map[string]string{"DownloadStatus": "Pending", "Msg": msg}
189-
mapB, _ := json.Marshal(mapD)
190-
h.broadcastSys <- mapB
191-
},
183+
logger := func(msg string) {
184+
mapD := map[string]string{"DownloadStatus": "Pending", "Msg": msg}
185+
mapB, _ := json.Marshal(mapD)
186+
h.broadcastSys <- mapB
192187
}
193-
Tools.Init()
188+
189+
// Instantiate Tools
190+
Tools = *tools.New(config.GetDataDir(), Index, logger)
194191

195192
// Let's handle the config
196193
configDir := config.GetDefaultConfigDir()

tools/download.go

+18-24
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func pathExists(path string) bool {
7878
// if it already exists.
7979
func (t *Tools) Download(pack, name, version, behaviour string) error {
8080

81-
body, err := t.Index.Read()
81+
body, err := t.index.Read()
8282
if err != nil {
8383
return err
8484
}
@@ -90,29 +90,25 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
9090
correctTool, correctSystem := findTool(pack, name, version, data)
9191

9292
if correctTool.Name == "" || correctSystem.URL == "" {
93-
t.Logger("We couldn't find a tool with the name " + name + " and version " + version + " packaged by " + pack)
93+
t.logger("We couldn't find a tool with the name " + name + " and version " + version + " packaged by " + pack)
9494
return nil
9595
}
9696

9797
key := correctTool.Name + "-" + correctTool.Version
9898

9999
// Check if it already exists
100100
if behaviour == "keep" {
101-
t.mutex.RLock()
102-
location, ok := t.installed[key]
103-
t.mutex.RUnlock()
101+
location, ok := t.getMapValue(key)
104102
if ok && pathExists(location) {
105103
// overwrite the default tool with this one
106-
t.mutex.Lock()
107-
t.installed[correctTool.Name] = location
108-
t.mutex.Unlock()
109-
t.Logger("The tool is already present on the system")
104+
t.setMapValue(correctTool.Name, location)
105+
t.logger("The tool is already present on the system")
110106
return t.writeMap()
111107
}
112108
}
113109

114110
// Download the tool
115-
t.Logger("Downloading tool " + name + " from " + correctSystem.URL)
111+
t.logger("Downloading tool " + name + " from " + correctSystem.URL)
116112
resp, err := http.Get(correctSystem.URL)
117113
if err != nil {
118114
return err
@@ -134,9 +130,9 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
134130
}
135131

136132
// Decompress
137-
t.Logger("Unpacking tool " + name)
133+
t.logger("Unpacking tool " + name)
138134

139-
location := path.Join(dir(), pack, correctTool.Name, correctTool.Version)
135+
location := t.directory.Join(pack, correctTool.Name, correctTool.Version).String()
140136
err = os.RemoveAll(location)
141137

142138
if err != nil {
@@ -150,18 +146,18 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
150146

151147
switch srcType {
152148
case "application/zip":
153-
location, err = extractZip(t.Logger, body, location)
149+
location, err = extractZip(t.logger, body, location)
154150
case "application/x-bz2":
155151
case "application/octet-stream":
156-
location, err = extractBz2(t.Logger, body, location)
152+
location, err = extractBz2(t.logger, body, location)
157153
case "application/x-gzip":
158-
location, err = extractTarGz(t.Logger, body, location)
154+
location, err = extractTarGz(t.logger, body, location)
159155
default:
160156
return errors.New("Unknown extension for file " + correctSystem.URL)
161157
}
162158

163159
if err != nil {
164-
t.Logger("Error extracting the archive: " + err.Error())
160+
t.logger("Error extracting the archive: " + err.Error())
165161
return err
166162
}
167163

@@ -171,15 +167,13 @@ func (t *Tools) Download(pack, name, version, behaviour string) error {
171167
}
172168

173169
// Ensure that the files are executable
174-
t.Logger("Ensure that the files are executable")
170+
t.logger("Ensure that the files are executable")
175171

176172
// Update the tool map
177-
t.Logger("Updating map with location " + location)
173+
t.logger("Updating map with location " + location)
178174

179-
t.mutex.Lock()
180-
t.installed[name] = location
181-
t.installed[name+"-"+correctTool.Version] = location
182-
t.mutex.Unlock()
175+
t.setMapValue(name, location)
176+
t.setMapValue(name+"-"+correctTool.Version, location)
183177
return t.writeMap()
184178
}
185179

@@ -475,11 +469,11 @@ func (t *Tools) installDrivers(location string) error {
475469
preamble = "./"
476470
}
477471
if _, err := os.Stat(filepath.Join(location, "post_install"+extension)); err == nil {
478-
t.Logger("Installing drivers")
472+
t.logger("Installing drivers")
479473
ok := MessageBox("Installing drivers", "We are about to install some drivers needed to use Arduino/Genuino boards\nDo you want to continue?")
480474
if ok == OkPressed {
481475
os.Chdir(location)
482-
t.Logger(preamble + "post_install" + extension)
476+
t.logger(preamble + "post_install" + extension)
483477
oscmd := exec.Command(preamble + "post_install" + extension)
484478
if OS != "linux" {
485479
// spawning a shell could be the only way to let the user type his password

tools/tools.go

+64-59
Original file line numberDiff line numberDiff line change
@@ -17,49 +17,89 @@ package tools
1717

1818
import (
1919
"encoding/json"
20-
"fmt"
21-
"os"
22-
"os/user"
23-
"path"
2420
"path/filepath"
2521
"strings"
2622
"sync"
2723

2824
"github.com/arduino/arduino-create-agent/index"
25+
"github.com/arduino/go-paths-helper"
2926
"github.com/xrash/smetrics"
3027
)
3128

3229
// Tools handle the tools necessary for an upload on a board.
3330
// It provides a means to download a tool from the arduino servers.
3431
//
35-
// - *Directory* contains the location where the tools are downloaded.
36-
// - *IndexURL* contains the url where the tools description is contained.
37-
// - *Logger* is a StdLogger used for reporting debug and info messages
38-
// - *installed* contains a map of the tools and their exact location
32+
// - *directory* contains the location where the tools are downloaded.
33+
// - *indexURL* contains the url where the tools description is contained.
34+
// - *logger* is a StdLogger used for reporting debug and info messages
35+
// - *installed* contains a map[string]string of the tools installed and their exact location
3936
//
4037
// Usage:
41-
// You have to instantiate the struct by passing it the required parameters:
42-
// _tools := tools.Tools{
43-
// Directory: "/home/user/.arduino-create",
44-
// IndexURL: "https://downloads.arduino.cc/packages/package_index.json"
45-
// Logger: log.Logger
46-
// }
38+
// You have to call the New() function passing it the required parameters:
39+
//
40+
// index = index.Init("https://downloads.arduino.cc/packages/package_staging_index.json", dataDir)
41+
// tools := tools.New(dataDir, index, logger)
4742

4843
// Tools will represent the installed tools
4944
type Tools struct {
50-
Directory string
51-
Index *index.Resource
52-
Logger func(msg string)
45+
directory *paths.Path
46+
index *index.Resource
47+
logger func(msg string)
5348
installed map[string]string
5449
mutex sync.RWMutex
5550
}
5651

57-
// Init creates the Installed map and populates it from a file in .arduino-create
58-
func (t *Tools) Init() {
52+
// New will return a Tool object, allowing the caller to execute operations on it.
53+
// The New functions accept the directory to use to host the tools,
54+
// an index (used to download the tools),
55+
// and a logger to log the operations
56+
func New(directory *paths.Path, index *index.Resource, logger func(msg string)) *Tools {
57+
t := &Tools{
58+
directory: directory,
59+
index: index,
60+
logger: logger,
61+
installed: map[string]string{},
62+
mutex: sync.RWMutex{},
63+
}
64+
_ = t.readMap()
65+
return t
66+
}
67+
68+
func (t *Tools) setMapValue(key, value string) {
5969
t.mutex.Lock()
60-
t.installed = make(map[string]string)
70+
t.installed[key] = value
6171
t.mutex.Unlock()
62-
t.readMap()
72+
}
73+
74+
func (t *Tools) getMapValue(key string) (string, bool) {
75+
t.mutex.RLock()
76+
defer t.mutex.RUnlock()
77+
value, ok := t.installed[key]
78+
return value, ok
79+
}
80+
81+
// writeMap() writes installed map to the json file "installed.json"
82+
func (t *Tools) writeMap() error {
83+
t.mutex.RLock()
84+
defer t.mutex.RUnlock()
85+
b, err := json.Marshal(t.installed)
86+
if err != nil {
87+
return err
88+
}
89+
filePath := t.directory.Join("installed.json")
90+
return filePath.WriteFile(b)
91+
}
92+
93+
// readMap() reads the installed map from json file "installed.json"
94+
func (t *Tools) readMap() error {
95+
t.mutex.Lock()
96+
defer t.mutex.Unlock()
97+
filePath := t.directory.Join("installed.json")
98+
b, err := filePath.ReadFile()
99+
if err != nil {
100+
return err
101+
}
102+
return json.Unmarshal(b, &t.installed)
63103
}
64104

65105
// GetLocation extracts the toolname from a command like
@@ -71,22 +111,16 @@ func (t *Tools) GetLocation(command string) (string, error) {
71111
var ok bool
72112

73113
// Load installed
74-
t.mutex.RLock()
75-
fmt.Println(t.installed)
76-
t.mutex.RUnlock()
77-
78114
err := t.readMap()
79115
if err != nil {
80116
return "", err
81117
}
82118

83-
t.mutex.RLock()
84-
defer t.mutex.RUnlock()
85-
fmt.Println(t.installed)
86-
87119
// use string similarity to resolve a runtime var with a "similar" map element
88-
if location, ok = t.installed[command]; !ok {
120+
if location, ok = t.getMapValue(command); !ok {
89121
maxSimilarity := 0.0
122+
t.mutex.RLock()
123+
defer t.mutex.RUnlock()
90124
for i, candidate := range t.installed {
91125
similarity := smetrics.Jaro(command, i)
92126
if similarity > 0.8 && similarity > maxSimilarity {
@@ -97,32 +131,3 @@ func (t *Tools) GetLocation(command string) (string, error) {
97131
}
98132
return filepath.ToSlash(location), nil
99133
}
100-
101-
// writeMap() writes installed map to the json file "installed.json"
102-
func (t *Tools) writeMap() error {
103-
t.mutex.Lock()
104-
b, err := json.Marshal(t.installed)
105-
defer t.mutex.Unlock()
106-
if err != nil {
107-
return err
108-
}
109-
filePath := path.Join(dir(), "installed.json")
110-
return os.WriteFile(filePath, b, 0644)
111-
}
112-
113-
// readMap() reads the installed map from json file "installed.json"
114-
func (t *Tools) readMap() error {
115-
t.mutex.Lock()
116-
defer t.mutex.Unlock()
117-
filePath := path.Join(dir(), "installed.json")
118-
b, err := os.ReadFile(filePath)
119-
if err != nil {
120-
return err
121-
}
122-
return json.Unmarshal(b, &t.installed)
123-
}
124-
125-
func dir() string {
126-
usr, _ := user.Current()
127-
return path.Join(usr.HomeDir, ".arduino-create")
128-
}

0 commit comments

Comments
 (0)