Skip to content

Commit d0f3044

Browse files
committed
Make archive package object oriented
The change resulted in an import cycle in `internal/libraries/git_integration_test.go`. I changed its package name as a workaround.
1 parent 0027587 commit d0f3044

File tree

5 files changed

+168
-33
lines changed

5 files changed

+168
-33
lines changed

internal/command/sync/sync.go

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -268,23 +268,19 @@ func syncLibraryTaggedRelease(logger *log.Logger, repo *libraries.Repository, ta
268268
releaseLog += formattedReport
269269
}
270270

271-
zipName := archive.ZipFolderName(library)
272-
lib := filepath.Base(filepath.Clean(filepath.Join(repo.FolderPath, "..")))
273-
host := filepath.Base(filepath.Clean(filepath.Join(repo.FolderPath, "..", "..")))
274-
zipFilePath, err := archive.ZipRepo(repo.FolderPath, filepath.Join(config.LibrariesFolder, host, lib), zipName)
271+
archiveData, err := archive.New(repo, library, config)
275272
if err != nil {
273+
return fmt.Errorf("Error while configuring library release archive: %s", err)
274+
}
275+
if err := archiveData.Create(); err != nil {
276276
return fmt.Errorf("Error while zipping library: %s", err)
277277
}
278278

279-
size, checksum, err := archive.GetSizeAndCalculateChecksum(zipFilePath)
280-
if err != nil {
281-
return fmt.Errorf("Error while calculating checksums: %s", err)
282-
}
283279
release := db.FromLibraryToRelease(library)
284-
release.URL = config.BaseDownloadURL + host + "/" + lib + "/" + zipName + ".zip"
285-
release.ArchiveFileName = zipName + ".zip"
286-
release.Size = size
287-
release.Checksum = checksum
280+
release.URL = archiveData.URL
281+
release.ArchiveFileName = archiveData.FileName
282+
release.Size = archiveData.Size
283+
release.Checksum = archiveData.Checksum
288284
release.Log = releaseLog
289285

290286
if err := libraries.UpdateLibrary(release, repo.URL, libraryDb); err != nil {

internal/libraries/archive/archive.go

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,38 +25,83 @@
2525
package archive
2626

2727
import (
28+
"net/url"
2829
"os"
2930
"path/filepath"
3031
"regexp"
3132

33+
"github.com/arduino/libraries-repository-engine/internal/configuration"
34+
"github.com/arduino/libraries-repository-engine/internal/libraries"
3235
"github.com/arduino/libraries-repository-engine/internal/libraries/hash"
3336
"github.com/arduino/libraries-repository-engine/internal/libraries/metadata"
3437
"github.com/arduino/libraries-repository-engine/internal/libraries/zip"
3538
)
3639

37-
// ZipRepo creates a ZIP archive of the repo folder and returns its path.
38-
func ZipRepo(repoFolder string, baseFolder string, zipFolderName string) (string, error) {
39-
err := os.MkdirAll(baseFolder, os.FileMode(0755))
40+
// Archive is the type for library release archive data.
41+
type Archive struct {
42+
SourcePath string
43+
RootName string // Name of the root folder inside the archive.
44+
FileName string
45+
Path string // Full path of the archive.
46+
URL string // URL the archive will have on the download server.
47+
Size int64
48+
Checksum string
49+
}
50+
51+
// New initializes and returns an Archive object.
52+
func New(repository *libraries.Repository, libraryMetadata *metadata.LibraryMetadata, config *configuration.Config) (*Archive, error) {
53+
repositoryURLData, err := url.Parse(repository.URL)
54+
if err != nil {
55+
return nil, err
56+
}
57+
// e.g., https://github.com/arduino-libraries/Servo.git -> github.com
58+
repositoryHost := repositoryURLData.Host
59+
// e.g., https://github.com/arduino-libraries/Servo.git -> arduino-libraries
60+
repositoryParent := filepath.Base(filepath.Dir(repositoryURLData.Path))
61+
62+
// Unlike the other path components, the filename is based on library name, not repository name URL.
63+
fileName := zipFolderName(libraryMetadata) + ".zip"
64+
65+
return &Archive{
66+
SourcePath: repository.FolderPath,
67+
RootName: zipFolderName(libraryMetadata),
68+
FileName: fileName,
69+
Path: filepath.Join(config.LibrariesFolder, repositoryHost, repositoryParent, fileName),
70+
URL: config.BaseDownloadURL + repositoryHost + "/" + repositoryParent + "/" + fileName,
71+
}, nil
72+
}
73+
74+
// Create makes an archive file according to the data of the Archive object and updates the object with the size and
75+
// checksum for the resulting file.
76+
func (archive *Archive) Create() error {
77+
err := os.MkdirAll(filepath.Dir(archive.Path), os.FileMode(0755))
4078
if err != nil {
41-
return "", err
79+
return err
80+
}
81+
82+
if err := zip.Directory(archive.SourcePath, archive.RootName, archive.Path); err != nil {
83+
os.Remove(archive.Path)
84+
return err
4285
}
43-
absoluteFileName := filepath.Join(baseFolder, zipFolderName+".zip")
44-
if err := zip.Directory(repoFolder, zipFolderName, absoluteFileName); err != nil {
45-
os.Remove(absoluteFileName)
46-
return "", err
86+
87+
size, checksum, err := getSizeAndCalculateChecksum(archive.Path)
88+
if err != nil {
89+
return err
4790
}
91+
archive.Size = size
92+
archive.Checksum = checksum
4893

49-
return absoluteFileName, nil
94+
return nil
5095
}
5196

52-
// ZipFolderName returns the name to use for the folder.
53-
func ZipFolderName(library *metadata.LibraryMetadata) string {
97+
// zipFolderName returns the name to use for the folder.
98+
func zipFolderName(library *metadata.LibraryMetadata) string {
5499
pattern := regexp.MustCompile("[^a-zA-Z0-9]")
55100
return pattern.ReplaceAllString(library.Name, "_") + "-" + library.Version
56101
}
57102

58-
// GetSizeAndCalculateChecksum returns the size and SHA-256 checksum for the given file.
59-
func GetSizeAndCalculateChecksum(filePath string) (int64, string, error) {
103+
// getSizeAndCalculateChecksum returns the size and SHA-256 checksum for the given file.
104+
func getSizeAndCalculateChecksum(filePath string) (int64, string, error) {
60105
info, err := os.Stat(filePath)
61106
if err != nil {
62107
return -1, "", err
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// This file is part of libraries-repository-engine.
2+
//
3+
// Copyright 2021 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 license@arduino.cc.
23+
24+
package archive
25+
26+
import (
27+
"os"
28+
"path/filepath"
29+
"testing"
30+
31+
"github.com/arduino/libraries-repository-engine/internal/configuration"
32+
"github.com/arduino/libraries-repository-engine/internal/libraries"
33+
"github.com/arduino/libraries-repository-engine/internal/libraries/metadata"
34+
"github.com/stretchr/testify/assert"
35+
"github.com/stretchr/testify/require"
36+
)
37+
38+
var testDataPath string
39+
40+
func init() {
41+
workingDirectory, err := os.Getwd()
42+
if err != nil {
43+
panic(err)
44+
}
45+
testDataPath = filepath.Join(workingDirectory, "testdata")
46+
}
47+
48+
func TestNew(t *testing.T) {
49+
repository := libraries.Repository{
50+
FolderPath: "/qux/repos/some-repo",
51+
URL: "https://github.com/Foo/Bar.git",
52+
}
53+
libraryMetadata := metadata.LibraryMetadata{
54+
Name: "Foo Bar",
55+
Version: "1.2.3",
56+
}
57+
config := configuration.Config{
58+
LibrariesFolder: "/baz/libs/",
59+
BaseDownloadURL: "https://example/com/libraries/",
60+
}
61+
62+
archiveObject, err := New(&repository, &libraryMetadata, &config)
63+
require.NoError(t, err)
64+
assert.Equal(t, "/qux/repos/some-repo", archiveObject.SourcePath)
65+
assert.Equal(t, "Foo_Bar-1.2.3", archiveObject.RootName)
66+
assert.Equal(t, "Foo_Bar-1.2.3.zip", archiveObject.FileName)
67+
assert.Equal(t, filepath.Join("/baz/libs/github.com/Foo/Foo_Bar-1.2.3.zip"), archiveObject.Path)
68+
assert.Equal(t, "https://example/com/libraries/github.com/Foo/Foo_Bar-1.2.3.zip", archiveObject.URL)
69+
}
70+
71+
func TestCreate(t *testing.T) {
72+
archiveDir := filepath.Join(os.TempDir(), "TestCreateArchiveDir")
73+
defer os.RemoveAll(archiveDir)
74+
archivePath := filepath.Join(archiveDir, "TestCreateArchive.zip")
75+
76+
archiveObject := Archive{
77+
Path: archivePath,
78+
SourcePath: filepath.Join(testDataPath, "gitclones", "SomeRepository"),
79+
RootName: "SomeLibrary",
80+
}
81+
82+
err := archiveObject.Create()
83+
require.NoError(t, err, "This test must be run as administrator on Windows to have symlink creation privilege.")
84+
85+
assert.FileExists(t, archivePath)
86+
assert.Greater(t, archiveObject.Size, int64(0))
87+
assert.NotEmpty(t, archiveObject.Checksum)
88+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This is some arbitrary source content to stand in for a library release. It is not intended to be a Git repository
2+
because that is not convenient to have in the repository and not relevant to testing this package.

internal/libraries/git_integration_test.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,24 @@
2121
// Arduino software without disclosing the source code of your own applications.
2222
// To purchase a commercial license, send an email to license@arduino.cc.
2323

24-
package libraries
24+
package libraries_test
2525

2626
import (
2727
"io/ioutil"
2828
"os"
2929
"path/filepath"
3030
"testing"
3131

32+
"github.com/arduino/libraries-repository-engine/internal/configuration"
33+
"github.com/arduino/libraries-repository-engine/internal/libraries"
3234
"github.com/arduino/libraries-repository-engine/internal/libraries/archive"
3335
"github.com/arduino/libraries-repository-engine/internal/libraries/db"
3436
"github.com/arduino/libraries-repository-engine/internal/libraries/gitutils"
3537
"github.com/stretchr/testify/require"
3638
)
3739

3840
func TestUpdateLibraryJson(t *testing.T) {
39-
repos, err := ListRepos("./testdata/git_test_repo.txt")
41+
repos, err := libraries.ListRepos("./testdata/git_test_repo.txt")
4042

4143
require.NoError(t, err)
4244
require.NotNil(t, repos)
@@ -52,7 +54,7 @@ func TestUpdateLibraryJson(t *testing.T) {
5254
subfolder, err := repo.AsFolder()
5355
require.NoError(t, err)
5456

55-
r, err := CloneOrFetch(repo, filepath.Join("/tmp", subfolder))
57+
r, err := libraries.CloneOrFetch(repo, filepath.Join("/tmp", subfolder))
5658
require.NoError(t, err)
5759
require.NotNil(t, r)
5860

@@ -65,19 +67,21 @@ func TestUpdateLibraryJson(t *testing.T) {
6567

6668
err = gitutils.CheckoutTag(r.Repository, tag)
6769

68-
library, err := GenerateLibraryFromRepo(r)
70+
library, err := libraries.GenerateLibraryFromRepo(r)
6971
require.NoError(t, err)
7072
require.NotNil(t, library)
7173

72-
zipFolderName := archive.ZipFolderName(library)
74+
config := configuration.Config{LibrariesFolder: librariesRepo}
75+
archiveData, err := archive.New(r, library, &config)
76+
require.NoError(t, err)
7377

7478
release := db.FromLibraryToRelease(library)
7579

76-
zipFilePath, err := archive.ZipRepo(r.FolderPath, librariesRepo, zipFolderName)
80+
err = archiveData.Create()
7781
require.NoError(t, err)
78-
require.NotEmpty(t, zipFilePath)
82+
require.NotEmpty(t, archiveData.Path)
7983

80-
err = UpdateLibrary(release, r.URL, libraryDb)
84+
err = libraries.UpdateLibrary(release, r.URL, libraryDb)
8185
require.NoError(t, err)
8286

8387
}

0 commit comments

Comments
 (0)