From 4a657f4aa8b5f25781b81c715514780337fb4721 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Mon, 18 Jan 2021 18:05:31 +0100 Subject: [PATCH 1/3] Fix lib install with git url --- arduino/libraries/librariesmanager/install.go | 34 +- cli/lib/install.go | 12 +- poetry.lock | 308 ++++++++++-------- pyproject.toml | 1 + test/test_lib.py | 78 +++++ 5 files changed, 297 insertions(+), 136 deletions(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index 28f7f73f9cc..104e688a22e 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -19,6 +19,7 @@ import ( "context" "errors" "fmt" + "net/url" "os" "strings" @@ -111,17 +112,21 @@ func (lm *LibrariesManager) InstallZipLib(ctx context.Context, archivePath strin } //InstallGitLib installs a library hosted on a git repository on the specified path. -func (lm *LibrariesManager) InstallGitLib(url string) error { +func (lm *LibrariesManager) InstallGitLib(gitURL string) error { libsDir := lm.getUserLibrariesDir() if libsDir == nil { return fmt.Errorf("User directory not set") } - i := strings.LastIndex(url, "/") - folder := strings.TrimRight(url[i+1:], ".git") - path := libsDir.Join(folder) - _, err := git.PlainClone(path.String(), false, &git.CloneOptions{ - URL: url, + libraryName, err := parseGitURL(gitURL) + if err != nil { + return err + } + + installPath := libsDir.Join(libraryName) + + _, err = git.PlainClone(installPath.String(), false, &git.CloneOptions{ + URL: gitURL, Progress: os.Stdout, }) if err != nil { @@ -129,3 +134,20 @@ func (lm *LibrariesManager) InstallGitLib(url string) error { } return nil } + +func parseGitURL(gitURL string) (string, error) { + var res string + if strings.HasPrefix(gitURL, "git") || strings.HasPrefix(gitURL, "ssh") { + // We can't parse these as URLs + i := strings.LastIndex(gitURL, "/") + res = strings.TrimRight(gitURL[i+1:], ".git") + } else if path := paths.New(gitURL); path.Exist() { + res = path.Base() + } else if parsed, err := url.Parse(gitURL); err == nil { + i := strings.LastIndex(parsed.Path, "/") + res = strings.TrimRight(parsed.Path[i+1:], ".git") + } else { + return "", fmt.Errorf("invalid git url") + } + return res, nil +} diff --git a/cli/lib/install.go b/cli/lib/install.go index e672183056e..4a46300604d 100644 --- a/cli/lib/install.go +++ b/cli/lib/install.go @@ -29,6 +29,7 @@ import ( "github.com/arduino/arduino-cli/commands/lib" "github.com/arduino/arduino-cli/configuration" rpc "github.com/arduino/arduino-cli/rpc/commands" + "github.com/arduino/go-paths-helper" "github.com/spf13/cobra" ) @@ -85,9 +86,18 @@ func runInstallCommand(cmd *cobra.Command, args []string) { } if installFlags.gitURL { + url := args[0] + if url == "." { + wd, err := paths.Getwd() + if err != nil { + feedback.Errorf("Couldn't get current working directory: %v", err) + os.Exit(errorcodes.ErrGeneric) + } + url = wd.String() + } gitlibraryInstallReq := &rpc.GitLibraryInstallReq{ Instance: instance, - Url: args[0], + Url: url, } err := lib.GitLibraryInstall(context.Background(), gitlibraryInstallReq, output.TaskProgress()) if err != nil { diff --git a/poetry.lock b/poetry.lock index 196cadc40f0..386ffc5b58c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,35 +1,34 @@ [[package]] -category = "main" -description = "apipkg: namespace control and lazy-import mechanism" name = "apipkg" +version = "1.5" +description = "apipkg: namespace control and lazy-import mechanism" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.5" [[package]] -category = "main" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "main" optional = false python-versions = "*" -version = "1.4.4" [[package]] -category = "main" -description = "Atomic file writes." -marker = "sys_platform == \"win32\"" name = "atomicwrites" +version = "1.4.0" +description = "Atomic file writes." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.4.0" [[package]] -category = "main" -description = "Classes Without Boilerplate" name = "attrs" +version = "19.3.0" +description = "Classes Without Boilerplate" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "19.3.0" [package.extras] azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"] @@ -38,12 +37,12 @@ docs = ["sphinx", "zope.interface"] tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] [[package]] -category = "main" -description = "The uncompromising code formatter." name = "black" +version = "19.10b0" +description = "The uncompromising code formatter." +category = "main" optional = false python-versions = ">=3.6" -version = "19.10b0" [package.dependencies] appdirs = "*" @@ -58,45 +57,44 @@ typed-ast = ">=1.4.0" d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] [[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." name = "certifi" +version = "2020.6.20" +description = "Python package for providing Mozilla's CA Bundle." +category = "main" optional = false python-versions = "*" -version = "2020.6.20" [[package]] -category = "main" -description = "Universal encoding detector for Python 2 and 3" name = "chardet" +version = "3.0.4" +description = "Universal encoding detector for Python 2 and 3" +category = "main" optional = false python-versions = "*" -version = "3.0.4" [[package]] -category = "main" -description = "Composable command line interface toolkit" name = "click" +version = "7.1.2" +description = "Composable command line interface toolkit" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "7.1.2" [[package]] -category = "main" -description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\"" name = "colorama" +version = "0.4.3" +description = "Cross-platform colored terminal text." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.4.3" [[package]] -category = "main" -description = "execnet: rapid multi-Python deployment" name = "execnet" +version = "1.7.1" +description = "execnet: rapid multi-Python deployment" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.7.1" [package.dependencies] apipkg = ">=1.4" @@ -105,20 +103,20 @@ apipkg = ">=1.4" testing = ["pre-commit"] [[package]] -category = "main" -description = "A platform independent file lock." name = "filelock" +version = "3.0.12" +description = "A platform independent file lock." +category = "main" optional = false python-versions = "*" -version = "3.0.12" [[package]] -category = "main" -description = "the modular source code checker: pep8 pyflakes and co" name = "flake8" +version = "3.8.3" +description = "the modular source code checker: pep8 pyflakes and co" +category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "3.8.3" [package.dependencies] mccabe = ">=0.6.0,<0.7.0" @@ -126,139 +124,161 @@ pycodestyle = ">=2.6.0a1,<2.7.0" pyflakes = ">=2.2.0,<2.3.0" [[package]] +name = "gitdb" +version = "4.0.5" +description = "Git Object Database" category = "main" -description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.4" + +[package.dependencies] +smmap = ">=3.0.1,<4" + +[[package]] +name = "gitpython" +version = "3.1.12" +description = "Python Git Library" +category = "main" +optional = false +python-versions = ">=3.4" + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[[package]] name = "idna" +version = "2.8" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8" [[package]] -category = "main" -description = "iniconfig: brain-dead simple config-ini parsing" name = "iniconfig" +version = "1.0.1" +description = "iniconfig: brain-dead simple config-ini parsing" +category = "main" optional = false python-versions = "*" -version = "1.0.1" [[package]] -category = "main" -description = "Pythonic task execution" name = "invoke" +version = "1.4.1" +description = "Pythonic task execution" +category = "main" optional = false python-versions = "*" -version = "1.4.1" [[package]] -category = "main" -description = "McCabe checker, plugin for flake8" name = "mccabe" +version = "0.6.1" +description = "McCabe checker, plugin for flake8" +category = "main" optional = false python-versions = "*" -version = "0.6.1" [[package]] -category = "main" -description = "More routines for operating on iterables, beyond itertools" name = "more-itertools" +version = "8.4.0" +description = "More routines for operating on iterables, beyond itertools" +category = "main" optional = false python-versions = ">=3.5" -version = "8.4.0" [[package]] -category = "main" -description = "Core utilities for Python packages" name = "packaging" +version = "20.4" +description = "Core utilities for Python packages" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.4" [package.dependencies] pyparsing = ">=2.0.2" six = "*" [[package]] -category = "main" -description = "Utility library for gitignore style pattern matching of file paths." name = "pathspec" +version = "0.8.0" +description = "Utility library for gitignore style pattern matching of file paths." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.8.0" [[package]] -category = "main" -description = "plugin and hook calling mechanisms for python" name = "pluggy" +version = "0.13.1" +description = "plugin and hook calling mechanisms for python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.13.1" [package.extras] dev = ["pre-commit", "tox"] [[package]] -category = "main" -description = "Python client for the Prometheus monitoring system." name = "prometheus-client" +version = "0.7.1" +description = "Python client for the Prometheus monitoring system." +category = "main" optional = false python-versions = "*" -version = "0.7.1" [package.extras] twisted = ["twisted"] [[package]] -category = "main" -description = "library with cross-python path, ini-parsing, io, code, log facilities" name = "py" +version = "1.9.0" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.9.0" [[package]] -category = "main" -description = "Python style guide checker" name = "pycodestyle" +version = "2.6.0" +description = "Python style guide checker" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.6.0" [[package]] -category = "main" -description = "passive checker of Python programs" name = "pyflakes" +version = "2.2.0" +description = "passive checker of Python programs" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.2.0" [[package]] -category = "main" -description = "Python parsing module" name = "pyparsing" +version = "2.4.7" +description = "Python parsing module" +category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.7" [[package]] -category = "main" -description = "Python Serial Port Extension" name = "pyserial" +version = "3.4" +description = "Python Serial Port Extension" +category = "main" optional = false python-versions = "*" -version = "3.4" [[package]] -category = "main" -description = "pytest: simple powerful testing with Python" name = "pytest" +version = "6.0.2" +description = "pytest: simple powerful testing with Python" +category = "main" optional = false python-versions = ">=3.5" -version = "6.0.2" [package.dependencies] -atomicwrites = ">=1.0" +atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=17.4.0" -colorama = "*" +colorama = {version = "*", markers = "sys_platform == \"win32\""} iniconfig = "*" more-itertools = ">=4.0.0" packaging = "*" @@ -267,28 +287,28 @@ py = ">=1.8.2" toml = "*" [package.extras] -checkqa_mypy = ["mypy (0.780)"] +checkqa_mypy = ["mypy (==0.780)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] -category = "main" -description = "run tests in isolated forked subprocesses" name = "pytest-forked" +version = "1.3.0" +description = "run tests in isolated forked subprocesses" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "1.3.0" [package.dependencies] py = "*" pytest = ">=3.10" [[package]] -category = "main" -description = "pytest-httpserver is a httpserver for pytest" name = "pytest-httpserver" +version = "0.3.5" +description = "pytest-httpserver is a httpserver for pytest" +category = "main" optional = false python-versions = ">=3.4" -version = "0.3.5" [package.dependencies] werkzeug = "*" @@ -298,23 +318,23 @@ dev = ["autopep8", "coverage", "flake8", "ipdb", "pytest", "pytest-cov", "reno", test = ["coverage", "pytest", "pytest-cov", "requests"] [[package]] -category = "main" -description = "py.test plugin to abort hanging tests" name = "pytest-timeout" +version = "1.3.4" +description = "py.test plugin to abort hanging tests" +category = "main" optional = false python-versions = "*" -version = "1.3.4" [package.dependencies] pytest = ">=3.6.0" [[package]] -category = "main" -description = "pytest xdist plugin for distributed testing and loop-on-failing modes" name = "pytest-xdist" +version = "2.1.0" +description = "pytest xdist plugin for distributed testing and loop-on-failing modes" +category = "main" optional = false python-versions = ">=3.5" -version = "2.1.0" [package.dependencies] execnet = ">=1.1" @@ -326,28 +346,28 @@ psutil = ["psutil (>=3.0)"] testing = ["filelock"] [[package]] -category = "main" -description = "YAML parser and emitter for Python" name = "pyyaml" +version = "5.3" +description = "YAML parser and emitter for Python" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "5.3" [[package]] -category = "main" -description = "Alternative regular expression module, to replace re." name = "regex" +version = "2020.7.14" +description = "Alternative regular expression module, to replace re." +category = "main" optional = false python-versions = "*" -version = "2020.7.14" [[package]] -category = "main" -description = "Python HTTP for Humans." name = "requests" +version = "2.22.0" +description = "Python HTTP for Humans." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.22.0" [package.dependencies] certifi = ">=2017.4.17" @@ -357,76 +377,85 @@ urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" [package.extras] security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] +socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] [[package]] -category = "main" -description = "Python helper for Semantic Versioning (http://semver.org/)" name = "semver" +version = "2.9.0" +description = "Python helper for Semantic Versioning (http://semver.org/)" +category = "main" optional = false python-versions = "*" -version = "2.9.0" [[package]] -category = "main" -description = "Simple, fast, extensible JSON encoder/decoder for Python" name = "simplejson" +version = "3.17.0" +description = "Simple, fast, extensible JSON encoder/decoder for Python" +category = "main" optional = false python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*" -version = "3.17.0" [[package]] -category = "main" -description = "Python 2 and 3 compatibility utilities" name = "six" +version = "1.15.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.15.0" [[package]] +name = "smmap" +version = "3.0.4" +description = "A pure Python implementation of a sliding window memory map manager" category = "main" -description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[[package]] name = "toml" +version = "0.10.1" +description = "Python Library for Tom's Obvious, Minimal Language" +category = "main" optional = false python-versions = "*" -version = "0.10.1" [[package]] -category = "main" -description = "a fork of Python 2 and 3 ast modules with type comment support" name = "typed-ast" +version = "1.4.1" +description = "a fork of Python 2 and 3 ast modules with type comment support" +category = "main" optional = false python-versions = "*" -version = "1.4.1" [[package]] -category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." name = "urllib3" +version = "1.25.9" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.9" [package.extras] brotli = ["brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] -category = "main" -description = "The comprehensive WSGI web application library." name = "werkzeug" +version = "1.0.1" +description = "The comprehensive WSGI web application library." +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "1.0.1" [package.extras] dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"] watchdog = ["watchdog"] [metadata] -content-hash = "3500e684ec97eabc4ffd38614f8e9af23630e1650f5ff095ad031396a8b2acf2" +lock-version = "1.1" python-versions = "^3.8" +content-hash = "366ed44051d9d750af552310f355cb4fd48eee3169bd011ef5c5fb61852e82d0" [metadata.files] apipkg = [ @@ -477,6 +506,14 @@ flake8 = [ {file = "flake8-3.8.3-py2.py3-none-any.whl", hash = "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c"}, {file = "flake8-3.8.3.tar.gz", hash = "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"}, ] +gitdb = [ + {file = "gitdb-4.0.5-py3-none-any.whl", hash = "sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac"}, + {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"}, +] +gitpython = [ + {file = "GitPython-3.1.12-py3-none-any.whl", hash = "sha256:867ec3dfb126aac0f8296b19fb63b8c4a399f32b4b6fafe84c4b10af5fa9f7b5"}, + {file = "GitPython-3.1.12.tar.gz", hash = "sha256:42dbefd8d9e2576c496ed0059f3103dcef7125b9ce16f9d5f9c834aed44a1dac"}, +] idna = [ {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, @@ -631,6 +668,10 @@ six = [ {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] +smmap = [ + {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, + {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"}, +] toml = [ {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, @@ -643,19 +684,28 @@ typed-ast = [ {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, + {file = "typed_ast-1.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f"}, {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, + {file = "typed_ast-1.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298"}, {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, + {file = "typed_ast-1.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d"}, {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, + {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c"}, + {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072"}, + {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91"}, + {file = "typed_ast-1.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d"}, + {file = "typed_ast-1.4.1-cp39-cp39-win32.whl", hash = "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395"}, + {file = "typed_ast-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c"}, {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, ] urllib3 = [ diff --git a/pyproject.toml b/pyproject.toml index 0af3e431de3..d9af915d71f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ black = { version = "^19.10b0", allow-prereleases = true } filelock = "^3.0.12" pytest-xdist = "^2.1.0" pytest_httpserver = "^0.3.5" +GitPython = "^3.1.12" [tool.black] line-length = 120 diff --git a/test/test_lib.py b/test/test_lib.py index 96c8bbe308b..9285569fac6 100644 --- a/test/test_lib.py +++ b/test/test_lib.py @@ -12,7 +12,11 @@ # otherwise use the software for commercial activities involving the Arduino # software without disclosing the source code of your own applications. To purchase # a commercial license, send an email to license@arduino.cc. +import platform + import simplejson as json +import pytest +from git import Repo from pathlib import Path @@ -383,3 +387,77 @@ def test_lib_list_with_updatable_flag(run_command): assert "6.11.0" == data[0]["library"]["version"] assert "6.11.0" != data[0]["release"]["version"] assert "" != data[0]["release"]["version"] + + +def test_install_with_git_url_from_current_directory(run_command, downloads_dir, data_dir): + assert run_command("update") + + env = { + "ARDUINO_DATA_DIR": data_dir, + "ARDUINO_DOWNLOADS_DIR": downloads_dir, + "ARDUINO_SKETCHBOOK_DIR": data_dir, + "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true", + } + + lib_install_dir = Path(data_dir, "libraries", "WiFi101") + # Verifies library is not installed + assert not lib_install_dir.exists() + + # Clone repository locally + git_url = "https://github.com/arduino-libraries/WiFi101.git" + repo_dir = Path(data_dir, "WiFi101") + assert Repo.clone_from(git_url, repo_dir) + + assert run_command("lib install --git-url .", custom_working_dir=repo_dir, custom_env=env) + + # Verifies library is installed to correct folder + assert lib_install_dir.exists() + + +@pytest.mark.skipif( + platform.system() == "Windows", + reason="Using a file uri as git url doesn't work on Windows, " + + "this must be removed when this issue is fixed: https://github.com/go-git/go-git/issues/247", +) +def test_install_with_git_url_local_file_uri(run_command, downloads_dir, data_dir): + assert run_command("update") + + env = { + "ARDUINO_DATA_DIR": data_dir, + "ARDUINO_DOWNLOADS_DIR": downloads_dir, + "ARDUINO_SKETCHBOOK_DIR": data_dir, + "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true", + } + + lib_install_dir = Path(data_dir, "libraries", "WiFi101") + # Verifies library is not installed + assert not lib_install_dir.exists() + + # Clone repository locally + git_url = "https://github.com/arduino-libraries/WiFi101.git" + repo_dir = Path(data_dir, "WiFi101") + assert Repo.clone_from(git_url, repo_dir) + + assert run_command(f"lib install --git-url {repo_dir.as_uri()}", custom_working_dir=repo_dir, custom_env=env) + + +def test_install_with_git_local_url(run_command, downloads_dir, data_dir): + assert run_command("update") + + env = { + "ARDUINO_DATA_DIR": data_dir, + "ARDUINO_DOWNLOADS_DIR": downloads_dir, + "ARDUINO_SKETCHBOOK_DIR": data_dir, + "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true", + } + + lib_install_dir = Path(data_dir, "libraries", "WiFi101") + # Verifies library is not installed + assert not lib_install_dir.exists() + + # Clone repository locally + git_url = "https://github.com/arduino-libraries/WiFi101.git" + repo_dir = Path(data_dir, "WiFi101") + assert Repo.clone_from(git_url, repo_dir) + + assert run_command(f"lib install --git-url {repo_dir}", custom_working_dir=repo_dir, custom_env=env) From ae405a02f6833e7bbdbdda77dfaaaa36bc6e5fca Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Tue, 19 Jan 2021 16:29:02 +0100 Subject: [PATCH 2/3] Better git url handling --- arduino/libraries/librariesmanager/install.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arduino/libraries/librariesmanager/install.go b/arduino/libraries/librariesmanager/install.go index 104e688a22e..bcf13345050 100644 --- a/arduino/libraries/librariesmanager/install.go +++ b/arduino/libraries/librariesmanager/install.go @@ -137,7 +137,7 @@ func (lm *LibrariesManager) InstallGitLib(gitURL string) error { func parseGitURL(gitURL string) (string, error) { var res string - if strings.HasPrefix(gitURL, "git") || strings.HasPrefix(gitURL, "ssh") { + if strings.HasPrefix(gitURL, "git@") { // We can't parse these as URLs i := strings.LastIndex(gitURL, "/") res = strings.TrimRight(gitURL[i+1:], ".git") From 7df7d0d086bf7960fb99a512448f9286adebd408 Mon Sep 17 00:00:00 2001 From: Silvano Cerza Date: Wed, 20 Jan 2021 10:58:46 +0100 Subject: [PATCH 3/3] Add test --- test/test_lib.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/test/test_lib.py b/test/test_lib.py index 9285569fac6..2464df84061 100644 --- a/test/test_lib.py +++ b/test/test_lib.py @@ -438,7 +438,7 @@ def test_install_with_git_url_local_file_uri(run_command, downloads_dir, data_di repo_dir = Path(data_dir, "WiFi101") assert Repo.clone_from(git_url, repo_dir) - assert run_command(f"lib install --git-url {repo_dir.as_uri()}", custom_working_dir=repo_dir, custom_env=env) + assert run_command(f"lib install --git-url {repo_dir.as_uri()}", custom_env=env) def test_install_with_git_local_url(run_command, downloads_dir, data_dir): @@ -460,4 +460,26 @@ def test_install_with_git_local_url(run_command, downloads_dir, data_dir): repo_dir = Path(data_dir, "WiFi101") assert Repo.clone_from(git_url, repo_dir) - assert run_command(f"lib install --git-url {repo_dir}", custom_working_dir=repo_dir, custom_env=env) + assert run_command(f"lib install --git-url {repo_dir}", custom_env=env) + + +def test_install_with_git_url_relative_path(run_command, downloads_dir, data_dir): + assert run_command("update") + + env = { + "ARDUINO_DATA_DIR": data_dir, + "ARDUINO_DOWNLOADS_DIR": downloads_dir, + "ARDUINO_SKETCHBOOK_DIR": data_dir, + "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true", + } + + lib_install_dir = Path(data_dir, "libraries", "WiFi101") + # Verifies library is not installed + assert not lib_install_dir.exists() + + # Clone repository locally + git_url = "https://github.com/arduino-libraries/WiFi101.git" + repo_dir = Path(data_dir, "WiFi101") + assert Repo.clone_from(git_url, repo_dir) + + assert run_command("lib install --git-url ./WiFi101", custom_working_dir=data_dir, custom_env=env)