Unverified Commit bacc2ac4 authored by Silvano Cerza's avatar Silvano Cerza Committed by GitHub

lib install --git-url and --zip-file must now be esplicitly enabled (#1075)

parent f7cdf72e
......@@ -24,6 +24,7 @@ import (
"github.com/arduino/arduino-cli/cli/instance"
"github.com/arduino/arduino-cli/cli/output"
"github.com/arduino/arduino-cli/commands/lib"
"github.com/arduino/arduino-cli/configuration"
rpc "github.com/arduino/arduino-cli/rpc/commands"
"github.com/spf13/cobra"
)
......@@ -40,8 +41,10 @@ func initInstallCommand() *cobra.Command {
Run: runInstallCommand,
}
installCommand.Flags().BoolVar(&installFlags.noDeps, "no-deps", false, "Do not install dependencies.")
installCommand.Flags().BoolVar(&installFlags.gitURL, "git-url", false, "Enter git url for libraries hosted on repositories")
installCommand.Flags().BoolVar(&installFlags.zipPath, "zip-path", false, "Enter a path to zip file")
if configuration.Settings.GetBool("library.enable_unsafe_install") {
installCommand.Flags().BoolVar(&installFlags.gitURL, "git-url", false, "Enter git url for libraries hosted on repositories")
installCommand.Flags().BoolVar(&installFlags.zipPath, "zip-path", false, "Enter a path to zip file")
}
return installCommand
}
......@@ -53,6 +56,11 @@ var installFlags struct {
func runInstallCommand(cmd *cobra.Command, args []string) {
instance := instance.CreateInstanceIgnorePlatformIndexErrors()
if installFlags.zipPath || installFlags.gitURL {
feedback.Print("--git-url and --zip-path flags are dangerous, use it at your own risk.")
}
if installFlags.zipPath {
ziplibraryInstallReq := &rpc.ZipLibraryInstallReq{
Instance: instance,
......@@ -63,7 +71,10 @@ func runInstallCommand(cmd *cobra.Command, args []string) {
feedback.Errorf("Error installing Zip Library: %v", err)
os.Exit(errorcodes.ErrGeneric)
}
} else if installFlags.gitURL {
return
}
if installFlags.gitURL {
gitlibraryInstallReq := &rpc.GitLibraryInstallReq{
Instance: instance,
Url: args[0],
......@@ -73,58 +84,59 @@ func runInstallCommand(cmd *cobra.Command, args []string) {
feedback.Errorf("Error installing Git Library: %v", err)
os.Exit(errorcodes.ErrGeneric)
}
} else {
libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
if err != nil {
feedback.Errorf("Arguments error: %v", err)
os.Exit(errorcodes.ErrBadArgument)
}
return
}
toInstall := map[string]*rpc.LibraryDependencyStatus{}
if installFlags.noDeps {
for _, libRef := range libRefs {
toInstall[libRef.Name] = &rpc.LibraryDependencyStatus{
Name: libRef.Name,
VersionRequired: libRef.Version,
}
}
} else {
for _, libRef := range libRefs {
depsResp, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesReq{
Instance: instance,
Name: libRef.Name,
Version: libRef.Version,
})
if err != nil {
feedback.Errorf("Error resolving dependencies for %s: %s", libRef, err)
os.Exit(errorcodes.ErrGeneric)
}
for _, dep := range depsResp.GetDependencies() {
feedback.Printf("%s depends on %s@%s", libRef, dep.GetName(), dep.GetVersionRequired())
if existingDep, has := toInstall[dep.GetName()]; has {
if existingDep.GetVersionRequired() != dep.GetVersionRequired() {
// TODO: make a better error
feedback.Errorf("The library %s is required in two different versions: %s and %s",
dep.GetName(), dep.GetVersionRequired(), existingDep.GetVersionRequired())
os.Exit(errorcodes.ErrGeneric)
}
}
toInstall[dep.GetName()] = dep
}
libRefs, err := ParseLibraryReferenceArgsAndAdjustCase(instance, args)
if err != nil {
feedback.Errorf("Arguments error: %v", err)
os.Exit(errorcodes.ErrBadArgument)
}
toInstall := map[string]*rpc.LibraryDependencyStatus{}
if installFlags.noDeps {
for _, libRef := range libRefs {
toInstall[libRef.Name] = &rpc.LibraryDependencyStatus{
Name: libRef.Name,
VersionRequired: libRef.Version,
}
}
for _, library := range toInstall {
libraryInstallReq := &rpc.LibraryInstallReq{
} else {
for _, libRef := range libRefs {
depsResp, err := lib.LibraryResolveDependencies(context.Background(), &rpc.LibraryResolveDependenciesReq{
Instance: instance,
Name: library.Name,
Version: library.VersionRequired,
}
err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.ProgressBar(), output.TaskProgress())
Name: libRef.Name,
Version: libRef.Version,
})
if err != nil {
feedback.Errorf("Error installing %s: %v", library, err)
feedback.Errorf("Error resolving dependencies for %s: %s", libRef, err)
os.Exit(errorcodes.ErrGeneric)
}
for _, dep := range depsResp.GetDependencies() {
feedback.Printf("%s depends on %s@%s", libRef, dep.GetName(), dep.GetVersionRequired())
if existingDep, has := toInstall[dep.GetName()]; has {
if existingDep.GetVersionRequired() != dep.GetVersionRequired() {
// TODO: make a better error
feedback.Errorf("The library %s is required in two different versions: %s and %s",
dep.GetName(), dep.GetVersionRequired(), existingDep.GetVersionRequired())
os.Exit(errorcodes.ErrGeneric)
}
}
toInstall[dep.GetName()] = dep
}
}
}
for _, library := range toInstall {
libraryInstallReq := &rpc.LibraryInstallReq{
Instance: instance,
Name: library.Name,
Version: library.VersionRequired,
}
err := lib.LibraryInstall(context.Background(), libraryInstallReq, output.ProgressBar(), output.TaskProgress())
if err != nil {
feedback.Errorf("Error installing %s: %v", library, err)
os.Exit(errorcodes.ErrGeneric)
}
}
}
......@@ -28,6 +28,9 @@ func SetDefaults(settings *viper.Viper) {
settings.SetDefault("logging.level", "info")
settings.SetDefault("logging.format", "text")
// Libraries
settings.SetDefault("library.enable_unsafe_install", false)
// Boards Manager
settings.SetDefault("board_manager.additional_urls", []string{})
......@@ -52,6 +55,7 @@ func SetDefaults(settings *viper.Viper) {
settings.AutomaticEnv()
// Bind env aliases to keep backward compatibility
settings.BindEnv("library.enable_unsafe_install", "ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL")
settings.BindEnv("directories.User", "ARDUINO_SKETCHBOOK_DIR")
settings.BindEnv("directories.Downloads", "ARDUINO_DOWNLOADS_DIR")
settings.BindEnv("directories.Data", "ARDUINO_DATA_DIR")
......
......@@ -12,8 +12,8 @@
# 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 os
import simplejson as json
from pathlib import Path
def test_list(run_command):
......@@ -145,7 +145,7 @@ def test_lib_download(run_command, downloads_dir):
# Download a specific lib version
assert run_command("lib download AudioZero@1.0.0")
assert os.path.exists(os.path.join(downloads_dir, "libraries", "AudioZero-1.0.0.zip"))
assert Path(downloads_dir, "libraries", "AudioZero-1.0.0.zip").exists()
# Wrong lib version
result = run_command("lib download AudioZero@69.42.0")
......@@ -168,23 +168,88 @@ def test_install(run_command):
assert "Error resolving dependencies for MD_Parola@3.2.0: dependency 'MD_MAX72xx' is not available" in result.stderr
def test_install_with_git_url(run_command):
def test_install_git_url_and_zip_path_flags_visibility(run_command, data_dir, downloads_dir):
# Verifies installation fail because flags are not found
git_url = "https://github.com/arduino-libraries/WiFi101.git"
res = run_command(f"lib install --git-url {git_url}")
assert res.failed
assert "Error: unknown flag: --git-url" in res.stderr
assert run_command("lib download AudioZero@1.0.0")
zip_path = Path(downloads_dir, "libraries", "AudioZero-1.0.0.zip")
res = run_command(f"lib install --zip-path {zip_path}")
assert res.failed
assert "Error: unknown flag: --zip-path" in res.stderr
env = {
"ARDUINO_DATA_DIR": data_dir,
"ARDUINO_DOWNLOADS_DIR": downloads_dir,
"ARDUINO_SKETCHBOOK_DIR": data_dir,
"ARDUINO_ENABLE_UNSAFE_LIBRARY_INSTALL": "true",
}
# Verifies installation is successful when flags are enabled with env var
res = run_command(f"lib install --git-url {git_url}", custom_env=env)
assert res.ok
assert "--git-url and --zip-path flags are dangerous, use it at your own risk." in res.stdout
res = run_command(f"lib install --zip-path {zip_path}", custom_env=env)
assert res.ok
assert "--git-url and --zip-path flags are dangerous, use it at your own risk." in res.stdout
# Uninstall libraries to install them again
assert run_command("lib uninstall WiFi101 AudioZero")
# Verifies installation is successful when flags are enabled with settings file
assert run_command("config init --dest-dir .", custom_env=env)
res = run_command(f"lib install --git-url {git_url}")
assert res.ok
assert "--git-url and --zip-path flags are dangerous, use it at your own risk." in res.stdout
res = run_command(f"lib install --zip-path {zip_path}")
assert res.ok
assert "--git-url and --zip-path flags are dangerous, use it at your own risk." in res.stdout
def test_install_with_git_url(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)
# Test git-url library install
assert run_command("lib install --git-url https://github.com/arduino-libraries/WiFi101.git")
res = run_command("lib install --git-url https://github.com/arduino-libraries/WiFi101.git")
assert res.ok
assert "--git-url and --zip-path flags are dangerous, use it at your own risk." in res.stdout
# Test failing-install as repository already exists
result = run_command("lib install --git-url https://github.com/arduino-libraries/WiFi101.git")
assert "Error installing Git Library: repository already exists" in result.stderr
res = run_command("lib install --git-url https://github.com/arduino-libraries/WiFi101.git")
assert "--git-url and --zip-path flags are dangerous, use it at your own risk." in res.stdout
assert "Error installing Git Library: repository already exists" in res.stderr
def test_install_with_zip_path(run_command, downloads_dir):
def test_install_with_zip_path(run_command, data_dir, downloads_dir):
# Initialize configs to enable --zip-path 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)
# Download a specific lib version
assert run_command("lib download AudioZero@1.0.0")
assert os.path.exists(os.path.join(downloads_dir, "libraries", "AudioZero-1.0.0.zip"))
zip_path = os.path.join(downloads_dir, "libraries", "AudioZero-1.0.0.zip")
zip_path = Path(downloads_dir, "libraries", "AudioZero-1.0.0.zip")
# Test zip-path install
assert run_command("lib install --zip-path {zip_path}".format(zip_path=zip_path))
res = run_command(f"lib install --zip-path {zip_path}")
assert res.ok
assert "--git-url and --zip-path flags are dangerous, use it at your own risk." in res.stdout
def test_update_index(run_command):
......
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