Unverified Commit 78be128d authored by Joe Wreschnig's avatar Joe Wreschnig Committed by GitHub

Allow using specific revisions in `lib install --git-url` (#1113) (#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.
parent 4c539b9a
......@@ -30,6 +30,7 @@ import (
"github.com/codeclysm/extract/v3"
"github.com/sirupsen/logrus"
"gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
)
type alreadyInstalledError struct{}
......@@ -190,7 +191,7 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
return fmt.Errorf(tr("User directory not set"))
}
libraryName, err := parseGitURL(gitURL)
libraryName, ref, err := parseGitURL(gitURL)
if err != nil {
logrus.
WithError(err).
......@@ -218,9 +219,13 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
WithField("git url", gitURL).
Trace("Installing library")
_, err = git.PlainClone(installPath.String(), false, &git.CloneOptions{
depth := 1
if ref != "" {
depth = 0
}
repo, err := git.PlainClone(installPath.String(), false, &git.CloneOptions{
URL: gitURL,
Depth: 1,
Depth: depth,
Progress: os.Stdout,
})
if err != nil {
......@@ -230,6 +235,25 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
return err
}
if ref != "" {
if h, err := repo.ResolveRevision(ref); err != nil {
logrus.
WithError(err).
Warnf("Resolving revision %s", ref)
return err
} else if w, err := repo.Worktree(); err != nil {
logrus.
WithError(err).
Warn("Finding worktree")
return err
} else if err := w.Checkout(&git.CheckoutOptions{Hash: plumbing.NewHash(h.String())}); err != nil {
logrus.
WithError(err).
Warnf("Checking out %s", h)
return err
}
}
if err := validateLibrary(installPath); err != nil {
// Clean up installation directory since this is not a valid library
installPath.RemoveAll()
......@@ -243,8 +267,9 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string, overwrite bool) error {
// parseGitURL tries to recover a library name from a git URL.
// Returns an error in case the URL is not a valid git URL.
func parseGitURL(gitURL string) (string, error) {
func parseGitURL(gitURL string) (string, plumbing.Revision, error) {
var res string
var rev plumbing.Revision
if strings.HasPrefix(gitURL, "git@") {
// We can't parse these as URLs
i := strings.LastIndex(gitURL, "/")
......@@ -254,10 +279,11 @@ func parseGitURL(gitURL string) (string, error) {
} else if parsed, err := url.Parse(gitURL); parsed.String() != "" && err == nil {
i := strings.LastIndex(parsed.Path, "/")
res = strings.TrimSuffix(parsed.Path[i+1:], ".git")
rev = plumbing.Revision(parsed.Fragment)
} else {
return "", fmt.Errorf(tr("invalid git url"))
return "", "", fmt.Errorf(tr("invalid git url"))
}
return res, nil
return res, rev, nil
}
// validateLibrary verifies the dir contains a valid library, meaning it has either
......
......@@ -24,43 +24,57 @@ import (
func TestParseGitURL(t *testing.T) {
gitURL := ""
libraryName, err := parseGitURL(gitURL)
libraryName, ref, err := parseGitURL(gitURL)
require.Equal(t, "", libraryName)
require.EqualValues(t, "", ref)
require.Errorf(t, err, "invalid git url")
gitURL = "https://github.com/arduino/arduino-lib.git"
libraryName, err = parseGitURL(gitURL)
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "", ref)
require.NoError(t, err)
gitURL = "https://github.com/arduino/arduino-lib.git#0.1.2"
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "0.1.2", ref)
require.NoError(t, err)
gitURL = "git@github.com:arduino/arduino-lib.git"
libraryName, err = parseGitURL(gitURL)
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "", ref)
require.NoError(t, err)
gitURL = "file:///path/to/arduino-lib"
libraryName, err = parseGitURL(gitURL)
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "", ref)
require.NoError(t, err)
gitURL = "file:///path/to/arduino-lib.git"
libraryName, err = parseGitURL(gitURL)
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "", ref)
require.NoError(t, err)
gitURL = "/path/to/arduino-lib"
libraryName, err = parseGitURL(gitURL)
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "", ref)
require.NoError(t, err)
gitURL = "/path/to/arduino-lib.git"
libraryName, err = parseGitURL(gitURL)
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "", ref)
require.NoError(t, err)
gitURL = "file:///path/to/arduino-lib"
libraryName, err = parseGitURL(gitURL)
libraryName, ref, err = parseGitURL(gitURL)
require.Equal(t, "arduino-lib", libraryName)
require.EqualValues(t, "", ref)
require.NoError(t, err)
}
......
......@@ -52,6 +52,7 @@ func initInstallCommand() *cobra.Command {
" " + os.Args[0] + " lib install AudioZero # " + tr("for the latest version.") + "\n" +
" " + os.Args[0] + " lib install AudioZero@1.0.0 # " + tr("for the specific version.") + "\n" +
" " + os.Args[0] + " lib install --git-url https://github.com/arduino-libraries/WiFi101.git https://github.com/arduino-libraries/ArduinoBLE.git\n" +
" " + os.Args[0] + " lib install --git-url https://github.com/arduino-libraries/WiFi101.git#0.16.0 # " + tr("for the specific version.") + "\n" +
" " + os.Args[0] + " lib install --zip-path /path/to/WiFi101.zip /path/to/ArduinoBLE.zip\n",
Args: cobra.MinimumNArgs(1),
Run: runInstallCommand,
......
......@@ -360,6 +360,39 @@ def test_install_with_git_url(run_command, data_dir, downloads_dir):
assert lib_install_dir.exists()
def test_install_with_git_url_fragment_as_branch(run_command, data_dir, downloads_dir):
# Initialize configs to enable --git-url flag
env = {
"ARDUINO_DATA_DIR": data_dir,
"ARDUINO_DOWNLOADS_DIR": downloads_dir,
"ARDUINO_SKETCHBOOK_DIR": data_dir,
"ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
}
assert run_command(["config", "init", "--dest-dir", "."], custom_env=env)
lib_install_dir = Path(data_dir, "libraries", "WiFi101")
# Verifies library is not already installed
assert not lib_install_dir.exists()
git_url = "https://github.com/arduino-libraries/WiFi101.git"
# Test that a bad ref fails
res = run_command(["lib", "install", "--git-url", git_url + "#x-ref-does-not-exist"])
assert res.failed
# Verifies library is installed in expected path
res = run_command(["lib", "install", "--git-url", git_url + "#0.16.0"])
assert res.ok
assert lib_install_dir.exists()
# Reinstall library at an existing ref
assert run_command(["lib", "install", "--git-url", git_url + "#master"])
assert res.ok
# Verifies library remains installed
assert lib_install_dir.exists()
def test_install_with_zip_path(run_command, data_dir, downloads_dir):
# Initialize configs to enable --zip-path flag
env = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment