diff --git a/platformio/package/commands/install.py b/platformio/package/commands/install.py index f7c85160..a060de88 100644 --- a/platformio/package/commands/install.py +++ b/platformio/package/commands/install.py @@ -23,7 +23,7 @@ from platformio.package.manager.platform import PlatformPackageManager from platformio.package.manager.tool import ToolPackageManager from platformio.package.meta import PackageSpec from platformio.project.config import ProjectConfig -from platformio.project.savedeps import save_project_dependencies +from platformio.project.savedeps import pkg_to_save_spec, save_project_dependencies @click.command( @@ -99,7 +99,7 @@ def install_project_dependencies(options): click.echo( "Resolving %s environment packages..." % click.style(env, fg="cyan") ) - already_up_to_date = install_project_env_dependencies(env, options) + already_up_to_date = not install_project_env_dependencies(env, options) if not options["silent"] and already_up_to_date: click.secho("Already up-to-date.", fg="green") @@ -184,7 +184,7 @@ def _install_project_env_custom_tools(project_env, options): skip_dependencies=options.get("skip_dependencies"), force=options.get("force"), ) - specs_to_save.append(_pkg_to_save_spec(pkg, spec)) + specs_to_save.append(pkg_to_save_spec(pkg, spec)) if not options.get("no_save") and specs_to_save: save_project_dependencies( os.getcwd(), @@ -237,7 +237,7 @@ def _install_project_env_custom_libraries(project_env, options): skip_dependencies=options.get("skip_dependencies"), force=options.get("force"), ) - specs_to_save.append(_pkg_to_save_spec(pkg, spec)) + specs_to_save.append(pkg_to_save_spec(pkg, spec)) if not options.get("no_save") and specs_to_save: save_project_dependencies( os.getcwd(), @@ -247,19 +247,3 @@ def _install_project_env_custom_libraries(project_env, options): environments=[project_env], ) return not already_up_to_date - - -def _pkg_to_save_spec(pkg, user_spec): - assert isinstance(user_spec, PackageSpec) - if user_spec.external: - return user_spec - return PackageSpec( - owner=pkg.metadata.spec.owner, - name=pkg.metadata.spec.name, - requirements=user_spec.requirements - or ( - ("^%s" % pkg.metadata.version) - if not pkg.metadata.version.build - else pkg.metadata.version - ), - ) diff --git a/platformio/project/savedeps.py b/platformio/project/savedeps.py index 2b2fe8f3..1c12bd3d 100644 --- a/platformio/project/savedeps.py +++ b/platformio/project/savedeps.py @@ -20,6 +20,22 @@ from platformio.project.config import ProjectConfig from platformio.project.exception import InvalidProjectConfError +def pkg_to_save_spec(pkg, user_spec): + assert isinstance(user_spec, PackageSpec) + if user_spec.external: + return user_spec + return PackageSpec( + owner=pkg.metadata.spec.owner, + name=pkg.metadata.spec.name, + requirements=user_spec.requirements + or ( + ("^%s" % pkg.metadata.version) + if not pkg.metadata.version.build + else pkg.metadata.version + ), + ) + + def save_project_dependencies( project_dir, specs, scope, action="add", environments=None ): @@ -31,7 +47,7 @@ def save_project_dependencies( config.expand_interpolations = False candidates = [] try: - candidates = ignore_deps_by_specs(config.get("env:" + env, scope), specs) + candidates = _ignore_deps_by_specs(config.get("env:" + env, scope), specs) except InvalidProjectConfError: pass if action == "add": @@ -48,7 +64,7 @@ def save_project_dependencies( config.save() -def ignore_deps_by_specs(deps, specs): +def _ignore_deps_by_specs(deps, specs): result = [] for dep in deps: ignore_conditions = [] diff --git a/tests/commands/pkg/test_install.py b/tests/commands/pkg/test_install.py index 64b4803e..1ceab50e 100644 --- a/tests/commands/pkg/test_install.py +++ b/tests/commands/pkg/test_install.py @@ -23,6 +23,7 @@ from platformio.package.commands.install import package_install_cmd from platformio.package.manager.library import LibraryPackageManager from platformio.package.manager.platform import PlatformPackageManager from platformio.package.manager.tool import ToolPackageManager +from platformio.package.meta import PackageSpec from platformio.project.config import ProjectConfig PROJECT_CONFIG_TPL = """ @@ -39,8 +40,84 @@ board = attiny88 """ -def pkgs_to_names(pkgs): - return [pkg.metadata.name for pkg in pkgs] +def pkgs_to_specs(pkgs): + return [ + PackageSpec(name=pkg.metadata.name, requirements=pkg.metadata.version) + for pkg in pkgs + ] + + +def test_global_packages( + clirunner, validate_cliresult, func_isolated_pio_core, tmp_path +): + # libraries + result = clirunner.invoke( + package_install_cmd, + [ + "--global", + "-l", + "milesburton/DallasTemperature@^3.9.1", + "--skip-dependencies", + ], + ) + validate_cliresult(result) + assert pkgs_to_specs(LibraryPackageManager().get_installed()) == [ + PackageSpec("DallasTemperature@3.9.1") + ] + # with dependencies + result = clirunner.invoke( + package_install_cmd, + [ + "--global", + "-l", + "milesburton/DallasTemperature@^3.9.1", + "-l", + "bblanchon/ArduinoJson@^6.19.2", + ], + ) + validate_cliresult(result) + assert pkgs_to_specs(LibraryPackageManager().get_installed()) == [ + PackageSpec("ArduinoJson@6.19.3"), + PackageSpec("DallasTemperature@3.9.1"), + PackageSpec("OneWire@2.3.6"), + ] + # custom storage + storage_dir = tmp_path / "custom_lib_storage" + storage_dir.mkdir() + result = clirunner.invoke( + package_install_cmd, + [ + "--global", + "--storage-dir", + str(storage_dir), + "-l", + "bblanchon/ArduinoJson@^6.19.2", + ], + ) + validate_cliresult(result) + assert pkgs_to_specs(LibraryPackageManager(storage_dir).get_installed()) == [ + PackageSpec("ArduinoJson@6.19.3") + ] + + # tools + result = clirunner.invoke( + package_install_cmd, + ["--global", "-t", "platformio/framework-arduino-avr-attiny@^1.5.2"], + ) + validate_cliresult(result) + assert pkgs_to_specs(ToolPackageManager().get_installed()) == [ + PackageSpec("framework-arduino-avr-attiny@1.5.2") + ] + + # platforms + result = clirunner.invoke( + package_install_cmd, + ["--global", "-p", "platformio/atmelavr@^3.4.0", "--skip-dependencies"], + ) + validate_cliresult(result) + assert pkgs_to_specs(PlatformPackageManager().get_installed()) == [ + PackageSpec("atmelavr@3.4.0") + ] def test_skip_dependencies(clirunner, validate_cliresult, isolated_pio_core, tmp_path): @@ -56,7 +133,9 @@ def test_skip_dependencies(clirunner, validate_cliresult, isolated_pio_core, tmp installed_lib_pkgs = LibraryPackageManager( os.path.join(ProjectConfig().get("platformio", "libdeps_dir"), "devkit") ).get_installed() - assert pkgs_to_names(installed_lib_pkgs) == ["DallasTemperature"] + assert pkgs_to_specs(installed_lib_pkgs) == [ + PackageSpec("DallasTemperature@3.9.1") + ] assert len(ToolPackageManager().get_installed()) == 0 @@ -73,9 +152,12 @@ def test_baremetal_project(clirunner, validate_cliresult, isolated_pio_core, tmp installed_lib_pkgs = LibraryPackageManager( os.path.join(ProjectConfig().get("platformio", "libdeps_dir"), "baremetal") ).get_installed() - assert pkgs_to_names(installed_lib_pkgs) == ["DallasTemperature", "OneWire"] - assert pkgs_to_names(ToolPackageManager().get_installed()) == [ - "toolchain-atmelavr" + assert pkgs_to_specs(installed_lib_pkgs) == [ + PackageSpec("DallasTemperature@3.9.1"), + PackageSpec("OneWire@2.3.6"), + ] + assert pkgs_to_specs(ToolPackageManager().get_installed()) == [ + PackageSpec("toolchain-atmelavr@1.70300.191015"), ] @@ -93,15 +175,26 @@ def test_project(clirunner, validate_cliresult, isolated_pio_core, tmp_path): lm = LibraryPackageManager( os.path.join(config.get("platformio", "libdeps_dir"), "devkit") ) - assert pkgs_to_names(lm.get_installed()) == ["DallasTemperature", "OneWire"] - assert pkgs_to_names(ToolPackageManager().get_installed()) == [ - "framework-arduino-avr-attiny", - "toolchain-atmelavr", + assert pkgs_to_specs(lm.get_installed()) == [ + PackageSpec("DallasTemperature@3.9.1"), + PackageSpec("OneWire@2.3.6"), + ] + assert pkgs_to_specs(ToolPackageManager().get_installed()) == [ + PackageSpec("framework-arduino-avr-attiny@1.5.2"), + PackageSpec("toolchain-atmelavr@1.70300.191015"), ] assert config.get("env:devkit", "lib_deps") == [ "milesburton/DallasTemperature@^3.9.1" ] + # test "Already up-to-date" + result = clirunner.invoke( + package_install_cmd, + ["-d", str(project_dir)], + ) + validate_cliresult(result) + assert "Already up-to-date" in result.output + def test_unknown_project_dependencies( clirunner, validate_cliresult, isolated_pio_core, tmp_path @@ -175,7 +268,7 @@ def test_custom_project_libraries( lm = LibraryPackageManager( os.path.join(config.get("platformio", "libdeps_dir"), "devkit") ) - assert pkgs_to_names(lm.get_installed()) == ["ArduinoJson"] + assert pkgs_to_specs(lm.get_installed()) == [PackageSpec("ArduinoJson@6.19.3")] # do not expect any platforms/tools assert not os.path.exists(config.get("platformio", "platforms_dir")) assert not os.path.exists(config.get("platformio", "packages_dir")) @@ -195,7 +288,10 @@ def test_custom_project_libraries( lm = LibraryPackageManager( os.path.join(config.get("platformio", "libdeps_dir"), "devkit") ) - assert pkgs_to_names(lm.get_installed()) == ["ArduinoJson", "Nanopb"] + assert pkgs_to_specs(lm.get_installed()) == [ + PackageSpec("ArduinoJson@6.19.3"), + PackageSpec("Nanopb@0.4.6+3"), + ] assert config.get("env:devkit", "lib_deps") == [ "bblanchon/ArduinoJson@^6.19.2", ] @@ -243,7 +339,9 @@ def test_custom_project_tools( assert not result.output.strip() config = ProjectConfig() - assert pkgs_to_names(ToolPackageManager().get_installed()) == ["tool-openocd"] + assert pkgs_to_specs(ToolPackageManager().get_installed()) == [ + PackageSpec("tool-openocd@2.1100.211028") + ] assert not LibraryPackageManager( os.path.join(config.get("platformio", "libdeps_dir"), "devkit") ).get_installed() @@ -262,9 +360,9 @@ def test_custom_project_tools( ) validate_cliresult(result) config = ProjectConfig() - assert pkgs_to_names(ToolPackageManager().get_installed()) == [ - "tool-esptoolpy", - "tool-openocd", + assert pkgs_to_specs(ToolPackageManager().get_installed()) == [ + PackageSpec("tool-esptoolpy@1.20310.0"), + PackageSpec("tool-openocd@2.1100.211028"), ] assert config.get("env:devkit", "platform_packages") == [ "platformio/tool-openocd@^2.1100.211028", @@ -290,7 +388,7 @@ def test_custom_project_platforms( project_dir = tmp_path / "project" project_dir.mkdir() (project_dir / "platformio.ini").write_text(PROJECT_CONFIG_TPL) - spec = "atmelavr" + spec = "atmelavr@^3.4.0" result = clirunner.invoke( package_install_cmd, ["-d", str(project_dir), "-e", "devkit", "-p", spec, "--skip-dependencies"], @@ -313,7 +411,9 @@ def test_custom_project_platforms( assert not result.output.strip() config = ProjectConfig() - assert pkgs_to_names(PlatformPackageManager().get_installed()) == ["atmelavr"] + assert pkgs_to_specs(PlatformPackageManager().get_installed()) == [ + PackageSpec("atmelavr@3.4.0") + ] assert not LibraryPackageManager( os.path.join(config.get("platformio", "libdeps_dir"), "devkit") ).get_installed() @@ -335,74 +435,3 @@ def test_custom_project_platforms( match="Unknown board ID", ): validate_cliresult(result) - - -def test_global_packages( - clirunner, validate_cliresult, func_isolated_pio_core, tmp_path -): - # libraries - result = clirunner.invoke( - package_install_cmd, - [ - "--global", - "-l", - "milesburton/DallasTemperature@^3.9.1", - "--skip-dependencies", - ], - ) - validate_cliresult(result) - assert pkgs_to_names(LibraryPackageManager().get_installed()) == [ - "DallasTemperature" - ] - # with dependencies - result = clirunner.invoke( - package_install_cmd, - [ - "--global", - "-l", - "milesburton/DallasTemperature@^3.9.1", - "-l", - "bblanchon/ArduinoJson@^6.19.2", - ], - ) - validate_cliresult(result) - assert pkgs_to_names(LibraryPackageManager().get_installed()) == [ - "ArduinoJson", - "DallasTemperature", - "OneWire", - ] - # custom storage - storage_dir = tmp_path / "custom_lib_storage" - storage_dir.mkdir() - result = clirunner.invoke( - package_install_cmd, - [ - "--global", - "--storage-dir", - str(storage_dir), - "-l", - "bblanchon/ArduinoJson@^6.19.2", - ], - ) - validate_cliresult(result) - assert pkgs_to_names(LibraryPackageManager(storage_dir).get_installed()) == [ - "ArduinoJson" - ] - - # tools - result = clirunner.invoke( - package_install_cmd, - ["--global", "-t", "platformio/framework-arduino-avr-attiny@^1.5.2"], - ) - validate_cliresult(result) - assert pkgs_to_names(ToolPackageManager().get_installed()) == [ - "framework-arduino-avr-attiny" - ] - - # platforms - result = clirunner.invoke( - package_install_cmd, - ["--global", "-p", "platformio/atmelavr@^3.4.0", "--skip-dependencies"], - ) - validate_cliresult(result) - assert pkgs_to_names(PlatformPackageManager().get_installed()) == ["atmelavr"]