Skip to content

Commit 78be128

Browse files
authored
Allow using specific revisions in lib install --git-url (arduino#1113) (arduino#1776)
This is done by providing the desired revision in the fragment, e.g. `…/Library.git#0.1.0`. When set, this disables the clone depth limit so all remote references will be available.
1 parent 4c539b9 commit 78be128

File tree

4 files changed

+88
-14
lines changed

4 files changed

+88
-14
lines changed

arduino/libraries/librariesmanager/install.go

+32-6
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/codeclysm/extract/v3"
3131
"github.com/sirupsen/logrus"
3232
"gopkg.in/src-d/go-git.v4"
33+
"gopkg.in/src-d/go-git.v4/plumbing"
3334
)
3435

3536
type alreadyInstalledError struct{}
@@ -190,7 +191,7 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
190191
return fmt.Errorf(tr("User directory not set"))
191192
}
192193

193-
libraryName, err := parseGitURL(gitURL)
194+
libraryName, ref, err := parseGitURL(gitURL)
194195
if err != nil {
195196
logrus.
196197
WithError(err).
@@ -218,9 +219,13 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
218219
WithField("git url", gitURL).
219220
Trace("Installing library")
220221

221-
_, err = git.PlainClone(installPath.String(), false, &git.CloneOptions{
222+
depth := 1
223+
if ref != "" {
224+
depth = 0
225+
}
226+
repo, err := git.PlainClone(installPath.String(), false, &git.CloneOptions{
222227
URL: gitURL,
223-
Depth: 1,
228+
Depth: depth,
224229
Progress: os.Stdout,
225230
})
226231
if err != nil {
@@ -230,6 +235,25 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
230235
return err
231236
}
232237

238+
if ref != "" {
239+
if h, err := repo.ResolveRevision(ref); err != nil {
240+
logrus.
241+
WithError(err).
242+
Warnf("Resolving revision %s", ref)
243+
return err
244+
} else if w, err := repo.Worktree(); err != nil {
245+
logrus.
246+
WithError(err).
247+
Warn("Finding worktree")
248+
return err
249+
} else if err := w.Checkout(&git.CheckoutOptions{Hash: plumbing.NewHash(h.String())}); err != nil {
250+
logrus.
251+
WithError(err).
252+
Warnf("Checking out %s", h)
253+
return err
254+
}
255+
}
256+
233257
if err := validateLibrary(installPath); err != nil {
234258
// Clean up installation directory since this is not a valid library
235259
installPath.RemoveAll()
@@ -243,8 +267,9 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
243267

244268
// parseGitURL tries to recover a library name from a git URL.
245269
// Returns an error in case the URL is not a valid git URL.
246-
func parseGitURL(gitURL string) (string, error) {
270+
func parseGitURL(gitURL string) (string, plumbing.Revision, error) {
247271
var res string
272+
var rev plumbing.Revision
248273
if strings.HasPrefix(gitURL, "git@") {
249274
// We can't parse these as URLs
250275
i := strings.LastIndex(gitURL, "/")
@@ -254,10 +279,11 @@ func parseGitURL(gitURL string) (string, error) {
254279
} else if parsed, err := url.Parse(gitURL); parsed.String() != "" && err == nil {
255280
i := strings.LastIndex(parsed.Path, "/")
256281
res = strings.TrimSuffix(parsed.Path[i+1:], ".git")
282+
rev = plumbing.Revision(parsed.Fragment)
257283
} else {
258-
return "", fmt.Errorf(tr("invalid git url"))
284+
return "", "", fmt.Errorf(tr("invalid git url"))
259285
}
260-
return res, nil
286+
return res, rev, nil
261287
}
262288

263289
// validateLibrary verifies the dir contains a valid library, meaning it has either

arduino/libraries/librariesmanager/install_test.go

+22-8
Original file line numberDiff line numberDiff line change
@@ -24,43 +24,57 @@ import (
2424

2525
func TestParseGitURL(t *testing.T) {
2626
gitURL := ""
27-
libraryName, err := parseGitURL(gitURL)
27+
libraryName, ref, err := parseGitURL(gitURL)
2828
require.Equal(t, "", libraryName)
29+
require.EqualValues(t, "", ref)
2930
require.Errorf(t, err, "invalid git url")
3031

3132
gitURL = "https://github.com/arduino/arduino-lib.git"
32-
libraryName, err = parseGitURL(gitURL)
33+
libraryName, ref, err = parseGitURL(gitURL)
3334
require.Equal(t, "arduino-lib", libraryName)
35+
require.EqualValues(t, "", ref)
36+
require.NoError(t, err)
37+
38+
gitURL = "https://github.com/arduino/arduino-lib.git#0.1.2"
39+
libraryName, ref, err = parseGitURL(gitURL)
40+
require.Equal(t, "arduino-lib", libraryName)
41+
require.EqualValues(t, "0.1.2", ref)
3442
require.NoError(t, err)
3543

3644
gitURL = "[email protected]:arduino/arduino-lib.git"
37-
libraryName, err = parseGitURL(gitURL)
45+
libraryName, ref, err = parseGitURL(gitURL)
3846
require.Equal(t, "arduino-lib", libraryName)
47+
require.EqualValues(t, "", ref)
3948
require.NoError(t, err)
4049

4150
gitURL = "file:///path/to/arduino-lib"
42-
libraryName, err = parseGitURL(gitURL)
51+
libraryName, ref, err = parseGitURL(gitURL)
4352
require.Equal(t, "arduino-lib", libraryName)
53+
require.EqualValues(t, "", ref)
4454
require.NoError(t, err)
4555

4656
gitURL = "file:///path/to/arduino-lib.git"
47-
libraryName, err = parseGitURL(gitURL)
57+
libraryName, ref, err = parseGitURL(gitURL)
4858
require.Equal(t, "arduino-lib", libraryName)
59+
require.EqualValues(t, "", ref)
4960
require.NoError(t, err)
5061

5162
gitURL = "/path/to/arduino-lib"
52-
libraryName, err = parseGitURL(gitURL)
63+
libraryName, ref, err = parseGitURL(gitURL)
5364
require.Equal(t, "arduino-lib", libraryName)
65+
require.EqualValues(t, "", ref)
5466
require.NoError(t, err)
5567

5668
gitURL = "/path/to/arduino-lib.git"
57-
libraryName, err = parseGitURL(gitURL)
69+
libraryName, ref, err = parseGitURL(gitURL)
5870
require.Equal(t, "arduino-lib", libraryName)
71+
require.EqualValues(t, "", ref)
5972
require.NoError(t, err)
6073

6174
gitURL = "file:///path/to/arduino-lib"
62-
libraryName, err = parseGitURL(gitURL)
75+
libraryName, ref, err = parseGitURL(gitURL)
6376
require.Equal(t, "arduino-lib", libraryName)
77+
require.EqualValues(t, "", ref)
6478
require.NoError(t, err)
6579
}
6680

cli/lib/install.go

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func initInstallCommand() *cobra.Command {
5252
" " + os.Args[0] + " lib install AudioZero # " + tr("for the latest version.") + "\n" +
5353
" " + os.Args[0] + " lib install [email protected] # " + tr("for the specific version.") + "\n" +
5454
" " + os.Args[0] + " lib install --git-url https://github.com/arduino-libraries/WiFi101.git https://github.com/arduino-libraries/ArduinoBLE.git\n" +
55+
" " + os.Args[0] + " lib install --git-url https://github.com/arduino-libraries/WiFi101.git#0.16.0 # " + tr("for the specific version.") + "\n" +
5556
" " + os.Args[0] + " lib install --zip-path /path/to/WiFi101.zip /path/to/ArduinoBLE.zip\n",
5657
Args: cobra.MinimumNArgs(1),
5758
Run: runInstallCommand,

test/test_lib.py

+33
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,39 @@ def test_install_with_git_url(run_command, data_dir, downloads_dir):
360360
assert lib_install_dir.exists()
361361

362362

363+
def test_install_with_git_url_fragment_as_branch(run_command, data_dir, downloads_dir):
364+
# Initialize configs to enable --git-url flag
365+
env = {
366+
"ARDUINO_DATA_DIR": data_dir,
367+
"ARDUINO_DOWNLOADS_DIR": downloads_dir,
368+
"ARDUINO_SKETCHBOOK_DIR": data_dir,
369+
"ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
370+
}
371+
assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
372+
373+
lib_install_dir = Path(data_dir, "libraries", "WiFi101")
374+
# Verifies library is not already installed
375+
assert not lib_install_dir.exists()
376+
377+
git_url = "https://github.com/arduino-libraries/WiFi101.git"
378+
379+
# Test that a bad ref fails
380+
res = run_command(["lib", "install", "--git-url", git_url + "#x-ref-does-not-exist"])
381+
assert res.failed
382+
383+
# Verifies library is installed in expected path
384+
res = run_command(["lib", "install", "--git-url", git_url + "#0.16.0"])
385+
assert res.ok
386+
assert lib_install_dir.exists()
387+
388+
# Reinstall library at an existing ref
389+
assert run_command(["lib", "install", "--git-url", git_url + "#master"])
390+
assert res.ok
391+
392+
# Verifies library remains installed
393+
assert lib_install_dir.exists()
394+
395+
363396
def test_install_with_zip_path(run_command, data_dir, downloads_dir):
364397
# Initialize configs to enable --zip-path flag
365398
env = {

0 commit comments

Comments
 (0)