diff --git a/internal/arduino/libraries/librariesmanager/install.go b/internal/arduino/libraries/librariesmanager/install.go index 1d73849f81f..9b53910d41a 100644 --- a/internal/arduino/libraries/librariesmanager/install.go +++ b/internal/arduino/libraries/librariesmanager/install.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "net/url" - "os" "strings" "github.com/arduino/arduino-cli/commands/cmderrors" @@ -215,17 +214,29 @@ func (lmi *Installer) InstallGitLib(argURL string, overwrite bool) error { defer tmp.RemoveAll() tmpInstallPath := tmp.Join(libraryName) - depth := 1 - if ref != "" { - depth = 0 - } if _, err := git.PlainClone(tmpInstallPath.String(), false, &git.CloneOptions{ URL: gitURL, - Depth: depth, - Progress: os.Stdout, - ReferenceName: ref, + ReferenceName: plumbing.ReferenceName(ref), }); err != nil { - return err + if err.Error() != "reference not found" { + return err + } + + // We did not find the requested reference, let's do a PlainClone and use + // "ResolveRevision" to find and checkout the requested revision + if repo, err := git.PlainClone(tmpInstallPath.String(), false, &git.CloneOptions{ + URL: gitURL, + }); err != nil { + return err + } else if h, err := repo.ResolveRevision(plumbing.Revision(ref)); err != nil { + return err + } else if w, err := repo.Worktree(); err != nil { + return err + } else if err := w.Checkout(&git.CheckoutOptions{ + Force: true, // workaround for: https://github.com/go-git/go-git/issues/1411 + Hash: plumbing.NewHash(h.String())}); err != nil { + return err + } } // We don't want the installed library to be a git repository thus we delete this folder @@ -241,7 +252,7 @@ func (lmi *Installer) InstallGitLib(argURL string, overwrite bool) error { // parseGitArgURL tries to recover a library name from a git URL. // Returns an error in case the URL is not a valid git URL. -func parseGitArgURL(argURL string) (string, string, plumbing.ReferenceName, error) { +func parseGitArgURL(argURL string) (string, string, string, error) { // On Windows handle paths with backslashes in the form C:\Path\to\library if path := paths.New(argURL); path != nil && path.Exist() { return path.Base(), argURL, "", nil @@ -279,7 +290,7 @@ func parseGitArgURL(argURL string) (string, string, plumbing.ReferenceName, erro return "", "", "", errors.New(i18n.Tr("invalid git url")) } // fragment == "1.0.3" - rev := plumbing.ReferenceName(parsedURL.Fragment) + rev := parsedURL.Fragment // gitURL == "https://github.com/arduino-libraries/SigFox.git" parsedURL.Fragment = "" gitURL := parsedURL.String() diff --git a/internal/integrationtest/lib/lib_test.go b/internal/integrationtest/lib/lib_test.go index 15371c80299..f900a416dad 100644 --- a/internal/integrationtest/lib/lib_test.go +++ b/internal/integrationtest/lib/lib_test.go @@ -16,6 +16,8 @@ package lib_test import ( + "crypto/sha256" + "encoding/hex" "encoding/json" "fmt" "io" @@ -687,6 +689,7 @@ func TestInstallWithGitUrlFragmentAsBranch(t *testing.T) { t.Run("RefPointingToBranch", func(t *testing.T) { libInstallDir := cli.SketchbookDir().Join("libraries", "ArduinoCloud") + t.Cleanup(func() { libInstallDir.RemoveAll() }) // Verify install with ref pointing to a branch require.NoDirExists(t, libInstallDir.String()) @@ -700,6 +703,24 @@ func TestInstallWithGitUrlFragmentAsBranch(t *testing.T) { require.NoError(t, err) require.Contains(t, string(fileToTest), `#define LENGHT_M "meters"`) // nolint:misspell }) + + t.Run("RefPointingToHash", func(t *testing.T) { + libInstallDir := cli.SketchbookDir().Join("libraries", "ArduinoCloud") + t.Cleanup(func() { libInstallDir.RemoveAll() }) + + // Verify install with ref pointing to a branch + require.NoDirExists(t, libInstallDir.String()) + _, _, err = cli.Run("lib", "install", "--git-url", "https://github.com/arduino-libraries/ArduinoCloud.git#fe1a1c5d1f8ea2cb27ece1a3b9344dc1eaed60b6", "--config-file", "arduino-cli.yaml") + require.NoError(t, err) + require.DirExists(t, libInstallDir.String()) + + // Verify that the correct branch is checked out + // https://github.com/arduino-libraries/ArduinoCloud/commit/fe1a1c5d1f8ea2cb27ece1a3b9344dc1eaed60b6 + fileToTest, err := libInstallDir.Join("examples", "ReadAndWrite", "ReadAndWrite.ino").ReadFile() + require.NoError(t, err) + chksum := sha256.Sum256(fileToTest) + require.Equal(t, hex.EncodeToString(chksum[:]), `f71889cd6da3b91755c7d1b8ec76b7ee6e2824d8a417c043d117ffdf1546f896`) + }) } func TestUpdateIndex(t *testing.T) {