Skip to content

Commit a386e95

Browse files
authored
Merge pull request #293 from arduino/cleanups
Some cleanups to the codebase
2 parents 62cdbbf + a613262 commit a386e95

File tree

26 files changed

+403
-430
lines changed

26 files changed

+403
-430
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// This file is part of libraries-repository-engine.
22
//
3-
// Copyright 2021 ARDUINO SA (http://www.arduino.cc/)
3+
// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
44
//
55
// This program is free software: you can redistribute it and/or modify
66
// it under the terms of the GNU Affero General Public License as published
@@ -21,21 +21,26 @@
2121
// Arduino software without disclosing the source code of your own applications.
2222
// To purchase a commercial license, send an email to [email protected].
2323

24-
package libraries
24+
package cli
2525

2626
import (
27-
"github.com/arduino/libraries-repository-engine/internal/libraries"
27+
checkregistry "github.com/arduino/libraries-repository-engine/internal/command/check-registry"
28+
"github.com/spf13/cobra"
2829
)
2930

30-
// LoadRepoListFromFile returns an unfiltered list of library registry entries loaded from the given data file.
31-
func LoadRepoListFromFile(filename string) ([]*Repo, error) {
32-
return libraries.LoadRepoListFromFile(filename)
33-
}
34-
35-
// Repo is the type for the library repository data.
36-
type Repo = libraries.Repo
31+
func init() {
32+
// checkRegistryCmd defines the `check-registry` CLI subcommand.
33+
var checkRegistryCmd = &cobra.Command{
34+
Short: "Check the registry.txt file format",
35+
Long: "Check the registry.txt file format",
36+
DisableFlagsInUseLine: true,
37+
Use: `check-registry FLAG... /path/to/registry.txt
3738
38-
// ListRepos returns a filtered list of library registry entries loaded from the given data file.
39-
func ListRepos(reposFilename string) ([]*Repo, error) {
40-
return libraries.ListRepos(reposFilename)
39+
Validate the registry.txt format and correctness.`,
40+
Args: cobra.ExactArgs(1),
41+
Run: func(cmd *cobra.Command, args []string) {
42+
checkregistry.CheckRegistry(args[0])
43+
},
44+
}
45+
rootCmd.AddCommand(checkRegistryCmd)
4146
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// This file is part of libraries-repository-engine.
2+
//
3+
// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
// You can be released from the requirements of the above licenses by purchasing
19+
// a commercial license. Buying such a license is mandatory if you want to
20+
// modify or otherwise use the software for commercial activities involving the
21+
// Arduino software without disclosing the source code of your own applications.
22+
// To purchase a commercial license, send an email to [email protected].
23+
24+
package checkregistry
25+
26+
import (
27+
"errors"
28+
"fmt"
29+
"os"
30+
"reflect"
31+
32+
"github.com/arduino/libraries-repository-engine/internal/libraries"
33+
)
34+
35+
// CheckRegistry runs the check-registry action
36+
func CheckRegistry(reposFile string) {
37+
if err := runcheck(reposFile); err != nil {
38+
fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
39+
os.Exit(1)
40+
}
41+
}
42+
43+
func runcheck(reposFile string) error {
44+
info, err := os.Stat(reposFile)
45+
if err != nil {
46+
return fmt.Errorf("while loading registry data file: %w", err)
47+
}
48+
49+
if info.IsDir() {
50+
return fmt.Errorf("registry data file argument %s is a folder, not a file", reposFile)
51+
}
52+
53+
rawRepos, err := libraries.LoadRepoListFromFile(reposFile)
54+
if err != nil {
55+
return fmt.Errorf("while loading registry data file: %w", err)
56+
}
57+
58+
filteredRepos, err := libraries.ListRepos(reposFile)
59+
if err != nil {
60+
return fmt.Errorf("while filtering registry data file: %w", err)
61+
}
62+
63+
if !reflect.DeepEqual(rawRepos, filteredRepos) {
64+
return errors.New("registry data file contains duplicate URLs")
65+
}
66+
67+
validTypes := map[string]bool{
68+
"Arduino": true,
69+
"Contributed": true,
70+
"Partner": true,
71+
"Recommended": true,
72+
"Retired": true,
73+
}
74+
75+
nameMap := make(map[string]bool)
76+
for _, entry := range rawRepos {
77+
// Check entry types
78+
if len(entry.Types) == 0 {
79+
return fmt.Errorf("type not specified for library '%s'", entry.LibraryName)
80+
}
81+
for _, entryType := range entry.Types {
82+
if _, valid := validTypes[entryType]; !valid {
83+
return fmt.Errorf("invalid type '%s' used by library '%s'", entryType, entry.LibraryName)
84+
}
85+
}
86+
87+
// Check library name of the entry
88+
if _, found := nameMap[entry.LibraryName]; found {
89+
return fmt.Errorf("registry data file contains duplicates of name '%s'", entry.LibraryName)
90+
}
91+
nameMap[entry.LibraryName] = true
92+
}
93+
return nil
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// This file is part of libraries-repository-engine.
2+
//
3+
// Copyright 2025 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published
7+
// by the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
// You can be released from the requirements of the above licenses by purchasing
19+
// a commercial license. Buying such a license is mandatory if you want to
20+
// modify or otherwise use the software for commercial activities involving the
21+
// Arduino software without disclosing the source code of your own applications.
22+
// To purchase a commercial license, send an email to [email protected].
23+
24+
package checkregistry
25+
26+
import (
27+
"path/filepath"
28+
"testing"
29+
30+
"github.com/stretchr/testify/require"
31+
)
32+
33+
func TestRegistryValidation(t *testing.T) {
34+
type testcase struct {
35+
Name string
36+
TestFile string
37+
ExpectedResult string
38+
}
39+
tests := []testcase{
40+
{"EmptyArg", "", "registry data file argument testdata is a folder, not a file"},
41+
{"NonExistentFile", "nonexistent.txt", "while loading registry data file: stat testdata/nonexistent.txt: no such file or directory"},
42+
{"InvalidDataFormat", "invalid-data-format.txt", "while loading registry data file: invalid line format (3 fields are required): https://github.com/arduino-libraries/SD.git|Partner;SD"},
43+
{"InvalidUrlFormat", "invalid-url-format.txt", "while filtering registry data file: Following URL are unknown or unsupported git repos:\nhttps://github.com/arduino-libraries/SD"},
44+
{"MissingType", "no-type.txt", "invalid type '' used by library 'SD'"},
45+
{"InvalidType", "invalid-type.txt", "invalid type 'foo' used by library 'SD'"},
46+
{"DuplicateRepoURL", "duplicate-url.txt", "registry data file contains duplicate URLs"},
47+
{"DuplicateLibName", "duplicate-name.txt", "registry data file contains duplicates of name 'SD'"},
48+
{"ValidList", "valid.txt", ""},
49+
}
50+
for _, test := range tests {
51+
t.Run(test.Name, func(t *testing.T) {
52+
err := runcheck(filepath.Join("testdata", test.TestFile))
53+
if test.ExpectedResult == "" {
54+
require.NoError(t, err)
55+
} else {
56+
require.EqualError(t, err, test.ExpectedResult)
57+
}
58+
})
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
https://github.com/arduino-libraries/Scheduler.git|Arduino|Scheduler
2+
https://github.com/arduino-libraries/SD.git|Partner|SD
3+
https://github.com/arduino-libraries/Servo.git|Recommended|Servo
4+
https://github.com/arduino-libraries/Foo.git|Contributed|SD
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
https://github.com/arduino-libraries/Scheduler.git|Arduino|Scheduler
2+
https://github.com/arduino-libraries/SD.git|Partner|SD
3+
https://github.com/arduino-libraries/Servo.git|Recommended|Servo
4+
https://github.com/arduino-libraries/SD.git|Contributed|Foo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/arduino-libraries/Scheduler.git|Arduino|Scheduler
2+
https://github.com/arduino-libraries/SD.git|Partner;SD
3+
https://github.com/arduino-libraries/Servo.git|Recommended|Servo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/arduino-libraries/Scheduler.git|Arduino|Scheduler
2+
https://github.com/arduino-libraries/SD.git|foo|SD
3+
https://github.com/arduino-libraries/Servo.git|Recommended|Servo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/arduino-libraries/Scheduler.git|Arduino|Scheduler
2+
https://github.com/arduino-libraries/SD|Partner|SD
3+
https://github.com/arduino-libraries/Servo.git|Recommended|Servo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/arduino-libraries/Scheduler.git|Arduino|Scheduler
2+
https://github.com/arduino-libraries/SD.git||SD
3+
https://github.com/arduino-libraries/Servo.git|Recommended|Servo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://github.com/arduino-libraries/Scheduler.git|Arduino|Scheduler
2+
https://github.com/arduino-libraries/SD.git|Partner|SD
3+
https://github.com/arduino-libraries/Servo.git|Recommended|Servo

internal/command/modify/modify.go

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import (
3737
"github.com/arduino/libraries-repository-engine/internal/libraries/archive"
3838
"github.com/arduino/libraries-repository-engine/internal/libraries/db"
3939
"github.com/arduino/libraries-repository-engine/internal/libraries/metadata"
40-
4140
"github.com/spf13/cobra"
4241
"github.com/spf13/pflag"
4342
)

internal/command/remove/remove.go

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import (
3737
"github.com/arduino/libraries-repository-engine/internal/libraries/archive"
3838
"github.com/arduino/libraries-repository-engine/internal/libraries/db"
3939
"github.com/arduino/libraries-repository-engine/internal/libraries/metadata"
40-
4140
"github.com/spf13/cobra"
4241
)
4342

internal/command/sync/sync.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ package sync
2727
import (
2828
"bytes"
2929
"encoding/json"
30+
"errors"
3031
"fmt"
31-
"io/ioutil"
3232
"log"
3333
"os"
3434
"path/filepath"
@@ -61,7 +61,7 @@ func Run(command *cobra.Command, cliArguments []string) {
6161
}
6262

6363
if len(cliArguments) > 1 {
64-
feedback.LogError(fmt.Errorf("Multiple arguments are not supported"))
64+
feedback.LogError(errors.New("multiple arguments are not supported"))
6565
os.Exit(1)
6666
}
6767

@@ -102,7 +102,7 @@ func syncLibraries(reposFile string) {
102102
syncLibrary(logger, repo, libraryDb)
103103

104104
// Output log to file
105-
if err := outputLogFile(logger, repo, buffer); err != nil {
105+
if err := outputLogFile(repo, buffer); err != nil {
106106
logger.Printf("Error writing log file: %s", err.Error())
107107
}
108108

@@ -200,13 +200,13 @@ func syncLibraryTaggedRelease(logger *log.Logger, repo *libraries.Repository, ta
200200
// Checkout desired tag
201201
logger.Printf("Checking out tag: %s", tag.Name().Short())
202202
if err := gitutils.CheckoutTag(repo.Repository, tag); err != nil {
203-
return fmt.Errorf("Error checking out repo: %s", err)
203+
return fmt.Errorf("error checking out repo: %s", err)
204204
}
205205

206206
// Create library metadata from library.properties
207207
library, err := libraries.GenerateLibraryFromRepo(repo)
208208
if err != nil {
209-
return fmt.Errorf("Error generating library from repo: %s", err)
209+
return fmt.Errorf("error generating library from repo: %s", err)
210210
}
211211
library.Types = repoMeta.Types
212212

@@ -257,10 +257,10 @@ func syncLibraryTaggedRelease(logger *log.Logger, repo *libraries.Repository, ta
257257

258258
archiveData, err := archive.New(repo, library, config)
259259
if err != nil {
260-
return fmt.Errorf("Error while configuring library release archive: %s", err)
260+
return fmt.Errorf("error while configuring library release archive: %s", err)
261261
}
262262
if err := archiveData.Create(); err != nil {
263-
return fmt.Errorf("Error while zipping library: %s", err)
263+
return fmt.Errorf("error while zipping library: %s", err)
264264
}
265265

266266
release := db.FromLibraryToRelease(library)
@@ -271,13 +271,13 @@ func syncLibraryTaggedRelease(logger *log.Logger, repo *libraries.Repository, ta
271271
release.Log = releaseLog
272272

273273
if err := libraries.UpdateLibrary(release, repo.URL, libraryDb); err != nil {
274-
return fmt.Errorf("Error while updating library DB: %s", err)
274+
return fmt.Errorf("error while updating library DB: %s", err)
275275
}
276276

277277
return nil
278278
}
279279

280-
func outputLogFile(logger *log.Logger, repoMetadata *libraries.Repo, buffer *bytes.Buffer) error {
280+
func outputLogFile(repoMetadata *libraries.Repo, buffer *bytes.Buffer) error {
281281
if config.LogsFolder == "" {
282282
return nil
283283
}
@@ -294,7 +294,7 @@ func outputLogFile(logger *log.Logger, repoMetadata *libraries.Repo, buffer *byt
294294
}
295295
logFile := filepath.Join(logFolder, "index.html")
296296
output := "<pre>\n" + buffer.String() + "\n</pre>"
297-
if err := ioutil.WriteFile(logFile, []byte(output), 0644); err != nil {
297+
if err := os.WriteFile(logFile, []byte(output), 0644); err != nil {
298298
return fmt.Errorf("write log to file: %s", err.Error())
299299
}
300300
return nil

internal/libraries/clamav.go

+3-27
Original file line numberDiff line numberDiff line change
@@ -30,43 +30,19 @@ import (
3030
"strings"
3131
)
3232

33-
func envSliceToMap(env []string) map[string]string {
34-
envMap := make(map[string]string)
35-
for _, value := range env {
36-
key := value[:strings.Index(value, "=")]
37-
value = value[strings.Index(value, "=")+1:]
38-
envMap[key] = value
39-
}
40-
return envMap
41-
}
42-
43-
func envMapToSlice(envMap map[string]string) []string {
44-
var env []string
45-
for key, value := range envMap {
46-
env = append(env, key+"="+value)
47-
}
48-
return env
49-
}
50-
51-
func modifyEnv(env []string, key, value string) []string {
52-
envMap := envSliceToMap(env)
53-
envMap[key] = value
54-
return envMapToSlice(envMap)
55-
}
56-
5733
// RunAntiVirus scans the folder for viruses.
5834
func RunAntiVirus(folder string) ([]byte, error) {
5935
cmd := exec.Command("clamdscan", "--fdpass", "-i", folder)
60-
cmd.Env = modifyEnv(os.Environ(), "LANG", "en")
36+
cmd.Env = append(os.Environ(), "LANG=en")
6137

6238
out, err := cmd.CombinedOutput()
6339
if err != nil {
6440
return out, err
6541
}
6642

6743
output := string(out)
68-
if strings.Index(output, "Infected files: 0") == -1 {
69-
return out, errors.New("Infected files found")
44+
if !strings.Contains(output, "Infected files: 0") {
45+
return out, errors.New("infected files found")
7046
}
7147

7248
return out, nil

0 commit comments

Comments
 (0)