mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-29 17:47:14 +02:00
Implement pio pkg update
command // Issue #3373
This commit is contained in:
@ -8,7 +8,7 @@ PlatformIO Core 5
|
||||
|
||||
**A professional collaborative platform for embedded development**
|
||||
|
||||
5.3.0 (2022-02-??)
|
||||
5.3.0 (2022-??-??)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* **Package Management**
|
||||
@ -17,7 +17,9 @@ PlatformIO Core 5
|
||||
|
||||
* `pio pkg exec <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_exec.html>`_ - run command from package tool (`issue #4163 <https://github.com/platformio/platformio-core/issues/4163>`_)
|
||||
* `pio pkg install <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_install.html>`_ - install the project dependencies or custom packages
|
||||
* `pio pkg outdated <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_pack.html>`__ - check for project outdated packages
|
||||
* `pio pkg outdated <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_outdated.html>`__ - check for project outdated packages
|
||||
* `pio pkg update <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_update.html>`__ - update the project dependencies or custom packages
|
||||
* `pio pkg uninstall <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_uninstall.html>`_ - uninstall the project dependencies or custom packages
|
||||
|
||||
- Added support for dependencies declared in a "tool" type package
|
||||
- Ignore files according to the patterns declared in ".gitignore" when using `pio package pack <https://docs.platformio.org/en/latest/core/userguide/pkg/cmd_pack.html>`__ command (`issue #4188 <https://github.com/platformio/platformio-core/issues/4188>`_)
|
||||
|
2
docs
2
docs
Submodule docs updated: 7aa5b89963...cbf179f826
@ -237,8 +237,13 @@ def lib_uninstall(ctx, libraries, save, silent):
|
||||
def lib_update( # pylint: disable=too-many-arguments
|
||||
ctx, libraries, only_check, dry_run, silent, json_output
|
||||
):
|
||||
storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY]
|
||||
only_check = dry_run or only_check
|
||||
if only_check and not json_output:
|
||||
raise exception.UserSideException(
|
||||
"This command is deprecated, please use `pio pkg outdated` instead"
|
||||
)
|
||||
|
||||
storage_dirs = ctx.meta[CTX_META_STORAGE_DIRS_KEY]
|
||||
json_result = {}
|
||||
for storage_dir in storage_dirs:
|
||||
if not json_output:
|
||||
@ -278,7 +283,7 @@ def lib_update( # pylint: disable=too-many-arguments
|
||||
None if isinstance(library, PackageItem) else PackageSpec(library)
|
||||
)
|
||||
try:
|
||||
lm.update(library, to_spec=to_spec, only_check=only_check)
|
||||
lm.update(library, to_spec=to_spec)
|
||||
except UnknownPackageError as e:
|
||||
if library not in lib_deps:
|
||||
raise e
|
||||
@ -529,7 +534,7 @@ def lib_show(library, json_output):
|
||||
@click.argument("config_url")
|
||||
def lib_register(config_url): # pylint: disable=unused-argument
|
||||
raise exception.UserSideException(
|
||||
"This command is deprecated. Please use `pio package publish` command."
|
||||
"This command is deprecated. Please use `pio pkg publish` command."
|
||||
)
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@ from platformio.package.commands.pack import package_pack_cmd
|
||||
from platformio.package.commands.publish import package_publish_cmd
|
||||
from platformio.package.commands.uninstall import package_uninstall_cmd
|
||||
from platformio.package.commands.unpublish import package_unpublish_cmd
|
||||
from platformio.package.commands.update import package_update_cmd
|
||||
|
||||
|
||||
@click.group(
|
||||
@ -28,11 +29,12 @@ from platformio.package.commands.unpublish import package_unpublish_cmd
|
||||
commands=[
|
||||
package_exec_cmd,
|
||||
package_install_cmd,
|
||||
package_uninstall_cmd,
|
||||
package_outdated_cmd,
|
||||
package_pack_cmd,
|
||||
package_publish_cmd,
|
||||
package_uninstall_cmd,
|
||||
package_unpublish_cmd,
|
||||
package_update_cmd,
|
||||
],
|
||||
short_help="Package Manager",
|
||||
)
|
||||
|
@ -273,8 +273,13 @@ def platform_uninstall(platforms):
|
||||
@click.option("-s", "--silent", is_flag=True, help="Suppress progress reporting")
|
||||
@click.option("--json-output", is_flag=True)
|
||||
def platform_update( # pylint: disable=too-many-locals, too-many-arguments
|
||||
platforms, only_packages, only_check, dry_run, silent, json_output
|
||||
platforms, only_check, dry_run, silent, json_output, **_
|
||||
):
|
||||
if only_check and not json_output:
|
||||
raise UserSideException(
|
||||
"This command is deprecated, please use `pio pkg outdated` instead"
|
||||
)
|
||||
|
||||
pm = PlatformPackageManager()
|
||||
pm.set_log_level(logging.WARN if silent else logging.DEBUG)
|
||||
platforms = platforms or pm.get_installed()
|
||||
@ -322,7 +327,7 @@ def platform_update( # pylint: disable=too-many-locals, too-many-arguments
|
||||
)
|
||||
)
|
||||
click.echo("--------")
|
||||
pm.update(platform, only_packages=only_packages, only_check=only_check)
|
||||
pm.update(platform)
|
||||
click.echo()
|
||||
|
||||
return True
|
||||
|
@ -42,7 +42,8 @@ def cli(ctx, core_packages, only_check, dry_run):
|
||||
|
||||
only_check = dry_run or only_check
|
||||
|
||||
update_core_packages(only_check)
|
||||
if not only_check:
|
||||
update_core_packages()
|
||||
|
||||
if core_packages:
|
||||
return
|
||||
|
@ -22,6 +22,7 @@ import click
|
||||
from platformio import VERSION, __version__, app, exception
|
||||
from platformio.clients.http import fetch_remote_content
|
||||
from platformio.compat import IS_WINDOWS
|
||||
from platformio.package.manager.core import update_core_packages
|
||||
from platformio.proc import exec_command, get_pythonexe_path
|
||||
from platformio.project.helpers import get_project_cache_dir
|
||||
|
||||
@ -29,6 +30,7 @@ from platformio.project.helpers import get_project_cache_dir
|
||||
@click.command("upgrade", short_help="Upgrade PlatformIO to the latest version")
|
||||
@click.option("--dev", is_flag=True, help="Use development branch")
|
||||
def cli(dev):
|
||||
update_core_packages()
|
||||
if not dev and __version__ == get_latest_version():
|
||||
return click.secho(
|
||||
"You're up-to-date!\nPlatformIO %s is currently the "
|
||||
|
@ -150,13 +150,10 @@ def after_upgrade(ctx):
|
||||
return
|
||||
else:
|
||||
click.secho("Please wait while upgrading PlatformIO...", fg="yellow")
|
||||
try:
|
||||
cleanup_content_cache("http")
|
||||
except: # pylint: disable=bare-except
|
||||
pass
|
||||
|
||||
# Update PlatformIO's Core packages
|
||||
update_core_packages(silent=True)
|
||||
cleanup_content_cache("http")
|
||||
update_core_packages()
|
||||
|
||||
u = Upgrader(last_version, __version__)
|
||||
if u.run(ctx):
|
||||
@ -219,7 +216,7 @@ def check_platformio_upgrade():
|
||||
http.ensure_internet_on(raise_exception=True)
|
||||
|
||||
# Update PlatformIO Core packages
|
||||
update_core_packages(silent=True)
|
||||
update_core_packages()
|
||||
|
||||
latest_version = get_latest_version()
|
||||
if pepver_to_semver(latest_version) <= pepver_to_semver(__version__):
|
||||
|
252
platformio/package/commands/update.py
Normal file
252
platformio/package/commands/update.py
Normal file
@ -0,0 +1,252 @@
|
||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import click
|
||||
|
||||
from platformio import fs
|
||||
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
|
||||
from platformio.project.savedeps import pkg_to_save_spec, save_project_dependencies
|
||||
|
||||
|
||||
@click.command(
|
||||
"update", short_help="Update the project dependencies or custom packages"
|
||||
)
|
||||
@click.option(
|
||||
"-d",
|
||||
"--project-dir",
|
||||
default=os.getcwd,
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True),
|
||||
)
|
||||
@click.option("-e", "--environment", "environments", multiple=True)
|
||||
@click.option("-p", "--platform", "platforms", multiple=True)
|
||||
@click.option("-t", "--tool", "tools", multiple=True)
|
||||
@click.option("-l", "--library", "libraries", multiple=True)
|
||||
@click.option(
|
||||
"--no-save",
|
||||
is_flag=True,
|
||||
help="Prevent saving specified packages to `platformio.ini`",
|
||||
)
|
||||
@click.option("--skip-dependencies", is_flag=True, help="Skip package dependencies")
|
||||
@click.option("-g", "--global", is_flag=True, help="Update global packages")
|
||||
@click.option(
|
||||
"--storage-dir",
|
||||
default=None,
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True),
|
||||
help="Custom Package Manager storage for global packages",
|
||||
)
|
||||
@click.option("-s", "--silent", is_flag=True, help="Suppress progress reporting")
|
||||
def package_update_cmd(**options):
|
||||
if options.get("global"):
|
||||
update_global_dependencies(options)
|
||||
else:
|
||||
update_project_dependencies(options)
|
||||
|
||||
|
||||
def update_global_dependencies(options):
|
||||
pm = PlatformPackageManager(options.get("storage_dir"))
|
||||
tm = ToolPackageManager(options.get("storage_dir"))
|
||||
lm = LibraryPackageManager(options.get("storage_dir"))
|
||||
for obj in (pm, tm, lm):
|
||||
obj.set_log_level(logging.WARN if options.get("silent") else logging.DEBUG)
|
||||
for spec in options.get("platforms"):
|
||||
pm.update(
|
||||
from_spec=spec,
|
||||
to_spec=spec,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
for spec in options.get("tools"):
|
||||
tm.update(
|
||||
from_spec=spec,
|
||||
to_spec=spec,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
for spec in options.get("libraries", []):
|
||||
lm.update(
|
||||
from_spec=spec,
|
||||
to_spec=spec,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
|
||||
|
||||
def update_project_dependencies(options):
|
||||
environments = options["environments"]
|
||||
with fs.cd(options["project_dir"]):
|
||||
config = ProjectConfig.get_instance()
|
||||
config.validate(environments)
|
||||
for env in config.envs():
|
||||
if environments and env not in environments:
|
||||
continue
|
||||
if not options["silent"]:
|
||||
click.echo(
|
||||
"Resolving %s environment packages..." % click.style(env, fg="cyan")
|
||||
)
|
||||
already_up_to_date = not update_project_env_dependencies(env, options)
|
||||
if not options["silent"] and already_up_to_date:
|
||||
click.secho("Already up-to-date.", fg="green")
|
||||
|
||||
|
||||
def update_project_env_dependencies(project_env, options=None):
|
||||
options = options or {}
|
||||
updated_conds = []
|
||||
# custom platforms
|
||||
if options.get("platforms"):
|
||||
updated_conds.append(_update_project_env_custom_platforms(project_env, options))
|
||||
# custom tools
|
||||
if options.get("tools"):
|
||||
updated_conds.append(_update_project_env_custom_tools(project_env, options))
|
||||
# custom ibraries
|
||||
if options.get("libraries"):
|
||||
updated_conds.append(_update_project_env_custom_libraries(project_env, options))
|
||||
# declared dependencies
|
||||
if not updated_conds:
|
||||
updated_conds = [
|
||||
_update_project_env_platform(project_env, options),
|
||||
_update_project_env_libraries(project_env, options),
|
||||
]
|
||||
return any(updated_conds)
|
||||
|
||||
|
||||
def _update_project_env_platform(project_env, options):
|
||||
config = ProjectConfig.get_instance()
|
||||
pm = PlatformPackageManager()
|
||||
if options.get("silent"):
|
||||
pm.set_log_level(logging.WARN)
|
||||
spec = config.get(f"env:{project_env}", "platform")
|
||||
if not spec:
|
||||
return None
|
||||
cur_pkg = pm.get_package(spec)
|
||||
if not cur_pkg:
|
||||
return None
|
||||
new_pkg = PlatformPackageManager().update(
|
||||
cur_pkg,
|
||||
to_spec=spec,
|
||||
project_env=project_env,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
return cur_pkg != new_pkg
|
||||
|
||||
|
||||
def _update_project_env_custom_platforms(project_env, options):
|
||||
already_up_to_date = True
|
||||
pm = PlatformPackageManager()
|
||||
if not options.get("silent"):
|
||||
pm.set_log_level(logging.DEBUG)
|
||||
for spec in options.get("platforms"):
|
||||
cur_pkg = pm.get_package(spec)
|
||||
new_pkg = pm.update(
|
||||
cur_pkg,
|
||||
to_spec=spec,
|
||||
project_env=project_env,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
if cur_pkg != new_pkg:
|
||||
already_up_to_date = False
|
||||
return not already_up_to_date
|
||||
|
||||
|
||||
def _update_project_env_custom_tools(project_env, options):
|
||||
already_up_to_date = True
|
||||
tm = ToolPackageManager()
|
||||
if not options.get("silent"):
|
||||
tm.set_log_level(logging.DEBUG)
|
||||
|
||||
specs_to_save = []
|
||||
for tool in options.get("tools"):
|
||||
spec = PackageSpec(tool)
|
||||
cur_pkg = tm.get_package(spec)
|
||||
new_pkg = tm.update(
|
||||
cur_pkg,
|
||||
to_spec=spec,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
if cur_pkg != new_pkg:
|
||||
already_up_to_date = False
|
||||
specs_to_save.append(pkg_to_save_spec(new_pkg, spec))
|
||||
|
||||
if not options.get("no_save") and specs_to_save:
|
||||
save_project_dependencies(
|
||||
os.getcwd(),
|
||||
specs_to_save,
|
||||
scope="platform_packages",
|
||||
action="add",
|
||||
environments=[project_env],
|
||||
)
|
||||
|
||||
return not already_up_to_date
|
||||
|
||||
|
||||
def _update_project_env_libraries(project_env, options):
|
||||
already_up_to_date = True
|
||||
config = ProjectConfig.get_instance()
|
||||
lm = LibraryPackageManager(
|
||||
os.path.join(config.get("platformio", "libdeps_dir"), project_env)
|
||||
)
|
||||
if options.get("silent"):
|
||||
lm.set_log_level(logging.WARN)
|
||||
for library in config.get(f"env:{project_env}", "lib_deps"):
|
||||
spec = PackageSpec(library)
|
||||
# skip built-in dependencies
|
||||
if not spec.external and not spec.owner:
|
||||
continue
|
||||
cur_pkg = lm.get_package(spec)
|
||||
if cur_pkg:
|
||||
new_pkg = lm.update(
|
||||
cur_pkg,
|
||||
to_spec=spec,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
if cur_pkg != new_pkg:
|
||||
already_up_to_date = False
|
||||
return not already_up_to_date
|
||||
|
||||
|
||||
def _update_project_env_custom_libraries(project_env, options):
|
||||
already_up_to_date = True
|
||||
config = ProjectConfig.get_instance()
|
||||
lm = LibraryPackageManager(
|
||||
os.path.join(config.get("platformio", "libdeps_dir"), project_env)
|
||||
)
|
||||
if not options.get("silent"):
|
||||
lm.set_log_level(logging.DEBUG)
|
||||
|
||||
specs_to_save = []
|
||||
for library in options.get("libraries") or []:
|
||||
spec = PackageSpec(library)
|
||||
cur_pkg = lm.get_package(spec)
|
||||
new_pkg = lm.update(
|
||||
cur_pkg,
|
||||
to_spec=spec,
|
||||
skip_dependencies=options.get("skip_dependencies"),
|
||||
)
|
||||
if cur_pkg != new_pkg:
|
||||
already_up_to_date = False
|
||||
specs_to_save.append(pkg_to_save_spec(new_pkg, spec))
|
||||
|
||||
if not options.get("no_save") and specs_to_save:
|
||||
save_project_dependencies(
|
||||
os.getcwd(),
|
||||
specs_to_save,
|
||||
scope="lib_deps",
|
||||
action="add",
|
||||
environments=[project_env],
|
||||
)
|
||||
|
||||
return not already_up_to_date
|
@ -12,12 +12,10 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import click
|
||||
|
||||
from platformio.clients.http import ensure_internet_on
|
||||
from platformio.package.exception import UnknownPackageError
|
||||
from platformio.package.meta import PackageItem, PackageOutdatedResult, PackageSpec
|
||||
from platformio.package.vcsclient import VCSBaseException, VCSClientFactory
|
||||
@ -26,9 +24,11 @@ from platformio.package.vcsclient import VCSBaseException, VCSClientFactory
|
||||
class PackageManagerUpdateMixin(object):
|
||||
def outdated(self, pkg, spec=None):
|
||||
assert isinstance(pkg, PackageItem)
|
||||
assert not spec or isinstance(spec, PackageSpec)
|
||||
assert pkg.metadata
|
||||
|
||||
if spec and not isinstance(spec, PackageSpec):
|
||||
spec = PackageSpec(spec)
|
||||
|
||||
if not os.path.isdir(pkg.path):
|
||||
return PackageOutdatedResult(current=pkg.metadata.version)
|
||||
|
||||
@ -82,82 +82,35 @@ class PackageManagerUpdateMixin(object):
|
||||
self,
|
||||
from_spec,
|
||||
to_spec=None,
|
||||
only_check=False,
|
||||
show_incompatible=True,
|
||||
skip_dependencies=False,
|
||||
):
|
||||
pkg = self.get_package(from_spec)
|
||||
if not pkg or not pkg.metadata:
|
||||
raise UnknownPackageError(from_spec)
|
||||
|
||||
silent = not self.log.isEnabledFor(logging.INFO)
|
||||
if not silent:
|
||||
click.echo(
|
||||
"{} {:<45} {:<35}".format(
|
||||
"Checking" if only_check else "Updating",
|
||||
click.style(pkg.metadata.spec.humanize(), fg="cyan"),
|
||||
"%s @ %s" % (pkg.metadata.version, to_spec.requirements)
|
||||
if to_spec and to_spec.requirements
|
||||
else str(pkg.metadata.version),
|
||||
),
|
||||
nl=False,
|
||||
)
|
||||
if not ensure_internet_on():
|
||||
if not silent:
|
||||
click.echo("[%s]" % (click.style("Off-line", fg="yellow")))
|
||||
return pkg
|
||||
|
||||
outdated = self.outdated(pkg, to_spec)
|
||||
if not silent:
|
||||
self.print_outdated_state(outdated, only_check, show_incompatible)
|
||||
|
||||
if only_check or not outdated.is_outdated(allow_incompatible=False):
|
||||
if not outdated.is_outdated(allow_incompatible=False):
|
||||
self.log.debug(
|
||||
click.style(
|
||||
"{name} @ {version} is already up-to-date".format(
|
||||
**pkg.metadata.as_dict()
|
||||
),
|
||||
fg="yellow",
|
||||
)
|
||||
)
|
||||
return pkg
|
||||
|
||||
self.log.info(
|
||||
"Updating %s @ %s"
|
||||
% (click.style(pkg.metadata.name, fg="cyan"), pkg.metadata.version)
|
||||
)
|
||||
try:
|
||||
self.lock()
|
||||
return self._update(pkg, outdated)
|
||||
return self._update(pkg, outdated, skip_dependencies)
|
||||
finally:
|
||||
self.unlock()
|
||||
|
||||
@staticmethod
|
||||
def print_outdated_state(outdated, only_check, show_incompatible):
|
||||
if outdated.detached:
|
||||
return click.echo("[%s]" % (click.style("Detached", fg="yellow")))
|
||||
|
||||
if (
|
||||
not outdated.latest
|
||||
or outdated.current == outdated.latest
|
||||
or (not show_incompatible and outdated.current == outdated.wanted)
|
||||
):
|
||||
return click.echo("[%s]" % (click.style("Up-to-date", fg="green")))
|
||||
|
||||
if outdated.wanted and outdated.current == outdated.wanted:
|
||||
return click.echo(
|
||||
"[%s]" % (click.style("Incompatible %s" % outdated.latest, fg="yellow"))
|
||||
)
|
||||
|
||||
if only_check:
|
||||
return click.echo(
|
||||
"[%s]"
|
||||
% (
|
||||
click.style(
|
||||
"Outdated %s" % str(outdated.wanted or outdated.latest),
|
||||
fg="red",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return click.echo(
|
||||
"[%s]"
|
||||
% (
|
||||
click.style(
|
||||
"Updating to %s" % str(outdated.wanted or outdated.latest),
|
||||
fg="green",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def _update(self, pkg, outdated):
|
||||
def _update(self, pkg, outdated, skip_dependencies=False):
|
||||
if pkg.metadata.spec.external:
|
||||
vcs = VCSClientFactory.new(pkg.path, pkg.metadata.spec.url)
|
||||
assert vcs.update()
|
||||
@ -165,23 +118,15 @@ class PackageManagerUpdateMixin(object):
|
||||
pkg.dump_meta()
|
||||
return pkg
|
||||
|
||||
new_pkg = self.install(
|
||||
# uninstall existing version
|
||||
self.uninstall(pkg, skip_dependencies=True)
|
||||
|
||||
return self.install(
|
||||
PackageSpec(
|
||||
id=pkg.metadata.spec.id,
|
||||
owner=pkg.metadata.spec.owner,
|
||||
name=pkg.metadata.spec.name,
|
||||
requirements=outdated.wanted or outdated.latest,
|
||||
)
|
||||
),
|
||||
skip_dependencies=skip_dependencies,
|
||||
)
|
||||
if new_pkg:
|
||||
old_pkg = self.get_package(
|
||||
PackageSpec(
|
||||
id=pkg.metadata.spec.id,
|
||||
owner=pkg.metadata.spec.owner,
|
||||
name=pkg.metadata.name,
|
||||
requirements=pkg.metadata.version,
|
||||
)
|
||||
)
|
||||
if old_pkg:
|
||||
self.uninstall(old_pkg, skip_dependencies=True)
|
||||
return new_pkg
|
||||
|
@ -55,17 +55,15 @@ def get_core_package_dir(name, auto_install=True):
|
||||
return pm.get_package(spec).path
|
||||
|
||||
|
||||
def update_core_packages(only_check=False, silent=False):
|
||||
def update_core_packages():
|
||||
pm = ToolPackageManager()
|
||||
for name, requirements in __core_packages__.items():
|
||||
spec = PackageSpec(owner="platformio", name=name, requirements=requirements)
|
||||
pkg = pm.get_package(spec)
|
||||
if not pkg:
|
||||
continue
|
||||
if not silent or pm.outdated(pkg, spec).is_outdated():
|
||||
pm.update(pkg, spec, only_check=only_check)
|
||||
if not only_check:
|
||||
remove_unnecessary_core_packages()
|
||||
try:
|
||||
pm.update(spec, spec)
|
||||
except UnknownPackageError:
|
||||
pass
|
||||
remove_unnecessary_core_packages()
|
||||
return True
|
||||
|
||||
|
||||
|
@ -85,45 +85,28 @@ class PlatformPackageManager(BasePackageManager): # pylint: disable=too-many-an
|
||||
p.on_uninstalled()
|
||||
return pkg
|
||||
|
||||
def update( # pylint: disable=arguments-differ, too-many-arguments
|
||||
def update( # pylint: disable=arguments-differ
|
||||
self,
|
||||
from_spec,
|
||||
to_spec=None,
|
||||
only_check=False,
|
||||
show_incompatible=True,
|
||||
only_packages=False,
|
||||
skip_dependencies=False,
|
||||
project_env=None,
|
||||
):
|
||||
pkg = self.get_package(from_spec)
|
||||
if not pkg or not pkg.metadata:
|
||||
raise UnknownPackageError(from_spec)
|
||||
pkg = super(PlatformPackageManager, self).update(
|
||||
from_spec,
|
||||
to_spec,
|
||||
)
|
||||
p = PlatformFactory.new(pkg)
|
||||
# set logging level for underlying tool manager
|
||||
p.pm.set_log_level(self.log.getEffectiveLevel())
|
||||
pkgs_before = [item.metadata.name for item in p.get_installed_packages()]
|
||||
|
||||
new_pkg = None
|
||||
missed_pkgs = set()
|
||||
if not only_packages:
|
||||
new_pkg = super(PlatformPackageManager, self).update(
|
||||
from_spec,
|
||||
to_spec,
|
||||
only_check=only_check,
|
||||
show_incompatible=show_incompatible,
|
||||
)
|
||||
p = PlatformFactory.new(new_pkg)
|
||||
missed_pkgs = set(pkgs_before) & set(p.packages)
|
||||
missed_pkgs -= set(
|
||||
item.metadata.name for item in p.get_installed_packages()
|
||||
)
|
||||
|
||||
p.update_packages(only_check)
|
||||
|
||||
if missed_pkgs:
|
||||
p.install_packages(
|
||||
with_packages=list(missed_pkgs), skip_default_package=True
|
||||
)
|
||||
|
||||
return new_pkg or pkg
|
||||
if project_env:
|
||||
p.configure_project_packages(project_env)
|
||||
if not skip_dependencies:
|
||||
p.update_packages()
|
||||
return pkg
|
||||
|
||||
@util.memoized(expire="5s")
|
||||
def get_installed_boards(self):
|
||||
|
356
tests/commands/pkg/test_update.py
Normal file
356
tests/commands/pkg/test_update.py
Normal file
@ -0,0 +1,356 @@
|
||||
# Copyright (c) 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
import os
|
||||
|
||||
from platformio import fs
|
||||
from platformio.package.commands.install import package_install_cmd
|
||||
from platformio.package.commands.update import package_update_cmd
|
||||
from platformio.package.exception import UnknownPackageError
|
||||
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_OUTDATED_CONFIG_TPL = """
|
||||
[env:devkit]
|
||||
platform = platformio/atmelavr@^2
|
||||
framework = arduino
|
||||
board = attiny88
|
||||
lib_deps = milesburton/DallasTemperature@~3.8.0
|
||||
"""
|
||||
|
||||
PROJECT_UPDATED_CONFIG_TPL = """
|
||||
[env:devkit]
|
||||
platform = platformio/atmelavr@<4
|
||||
framework = arduino
|
||||
board = attiny88
|
||||
lib_deps = milesburton/DallasTemperature@^3.8.0
|
||||
"""
|
||||
|
||||
|
||||
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", "bblanchon/ArduinoJson@^5"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert pkgs_to_specs(LibraryPackageManager().get_installed()) == [
|
||||
PackageSpec("ArduinoJson@5.13.4")
|
||||
]
|
||||
# update to the latest version
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["--global", "-l", "bblanchon/ArduinoJson"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
pkgs = LibraryPackageManager().get_installed()
|
||||
assert len(pkgs) == 1
|
||||
assert pkgs[0].metadata.version.major > 5
|
||||
# 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@^5",
|
||||
],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert pkgs_to_specs(LibraryPackageManager(storage_dir).get_installed()) == [
|
||||
PackageSpec("ArduinoJson@5.13.4")
|
||||
]
|
||||
# update to the latest version
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["--global", "--storage-dir", str(storage_dir), "-l", "bblanchon/ArduinoJson"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
pkgs = LibraryPackageManager(storage_dir).get_installed()
|
||||
assert len(pkgs) == 1
|
||||
assert pkgs[0].metadata.version.major > 5
|
||||
|
||||
# tools
|
||||
result = clirunner.invoke(
|
||||
package_install_cmd,
|
||||
["--global", "-t", "platformio/framework-arduino-avr-attiny@~1.4"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert pkgs_to_specs(ToolPackageManager().get_installed()) == [
|
||||
PackageSpec("framework-arduino-avr-attiny@1.4.1")
|
||||
]
|
||||
# update to the latest version
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["--global", "-t", "platformio/framework-arduino-avr-attiny@^1"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
pkgs = ToolPackageManager().get_installed()
|
||||
assert len(pkgs) == 1
|
||||
assert pkgs[0].metadata.version.major == 1
|
||||
assert pkgs[0].metadata.version.minor > 4
|
||||
|
||||
# platforms
|
||||
result = clirunner.invoke(
|
||||
package_install_cmd,
|
||||
["--global", "-p", "platformio/atmelavr@^2", "--skip-dependencies"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert pkgs_to_specs(PlatformPackageManager().get_installed()) == [
|
||||
PackageSpec("atmelavr@2.2.0")
|
||||
]
|
||||
# update to the latest version
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["--global", "-p", "platformio/atmelavr", "--skip-dependencies"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
pkgs = PlatformPackageManager().get_installed()
|
||||
assert len(pkgs) == 1
|
||||
assert pkgs[0].metadata.version.major > 2
|
||||
|
||||
# update unknown package
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["--global", "-l", "platformio/unknown_package_for_update"],
|
||||
)
|
||||
assert isinstance(result.exception, UnknownPackageError)
|
||||
|
||||
|
||||
def test_project(clirunner, validate_cliresult, isolated_pio_core, tmp_path):
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
(project_dir / "platformio.ini").write_text(PROJECT_OUTDATED_CONFIG_TPL)
|
||||
result = clirunner.invoke(
|
||||
package_install_cmd,
|
||||
["-d", str(project_dir)],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
with fs.cd(str(project_dir)):
|
||||
config = ProjectConfig()
|
||||
lm = LibraryPackageManager(
|
||||
os.path.join(config.get("platformio", "libdeps_dir"), "devkit")
|
||||
)
|
||||
assert pkgs_to_specs(lm.get_installed()) == [
|
||||
PackageSpec("DallasTemperature@3.8.1"),
|
||||
PackageSpec("OneWire@2.3.6"),
|
||||
]
|
||||
assert pkgs_to_specs(PlatformPackageManager().get_installed()) == [
|
||||
PackageSpec("atmelavr@2.2.0")
|
||||
]
|
||||
assert pkgs_to_specs(ToolPackageManager().get_installed()) == [
|
||||
PackageSpec("framework-arduino-avr-attiny@1.3.2"),
|
||||
PackageSpec("toolchain-atmelavr@1.50400.190710"),
|
||||
]
|
||||
assert config.get("env:devkit", "lib_deps") == [
|
||||
"milesburton/DallasTemperature@~3.8.0"
|
||||
]
|
||||
|
||||
# update packages
|
||||
(project_dir / "platformio.ini").write_text(PROJECT_UPDATED_CONFIG_TPL)
|
||||
result = clirunner.invoke(package_update_cmd)
|
||||
validate_cliresult(result)
|
||||
config = ProjectConfig()
|
||||
lm = LibraryPackageManager(
|
||||
os.path.join(config.get("platformio", "libdeps_dir"), "devkit")
|
||||
)
|
||||
pkgs = PlatformPackageManager().get_installed()
|
||||
assert len(pkgs) == 1
|
||||
assert pkgs[0].metadata.name == "atmelavr"
|
||||
assert pkgs[0].metadata.version.major == 3
|
||||
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.3.2"),
|
||||
PackageSpec("toolchain-atmelavr@1.70300.191015"),
|
||||
PackageSpec("toolchain-atmelavr@1.50400.190710"),
|
||||
]
|
||||
assert config.get("env:devkit", "lib_deps") == [
|
||||
"milesburton/DallasTemperature@^3.8.0"
|
||||
]
|
||||
|
||||
# update again
|
||||
result = clirunner.invoke(package_update_cmd)
|
||||
validate_cliresult(result)
|
||||
assert "Already up-to-date." in result.output
|
||||
|
||||
# update again in the silent ,pde
|
||||
result = clirunner.invoke(package_update_cmd, ["--silent"])
|
||||
validate_cliresult(result)
|
||||
assert not result.output
|
||||
|
||||
|
||||
def test_custom_project_libraries(
|
||||
clirunner, validate_cliresult, isolated_pio_core, tmp_path
|
||||
):
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
(project_dir / "platformio.ini").write_text(PROJECT_OUTDATED_CONFIG_TPL)
|
||||
spec = "milesburton/DallasTemperature@~3.8.0"
|
||||
result = clirunner.invoke(
|
||||
package_install_cmd,
|
||||
["-d", str(project_dir), "-e", "devkit", "-l", spec],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
with fs.cd(str(project_dir)):
|
||||
config = ProjectConfig()
|
||||
assert config.get("env:devkit", "lib_deps") == [spec]
|
||||
lm = LibraryPackageManager(
|
||||
os.path.join(config.get("platformio", "libdeps_dir"), "devkit")
|
||||
)
|
||||
assert pkgs_to_specs(lm.get_installed()) == [
|
||||
PackageSpec("DallasTemperature@3.8.1"),
|
||||
PackageSpec("OneWire@2.3.6"),
|
||||
]
|
||||
# update package
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["-e", "devkit", "-l", "milesburton/DallasTemperature@^3.8.0"],
|
||||
)
|
||||
assert ProjectConfig().get("env:devkit", "lib_deps") == [
|
||||
"milesburton/DallasTemperature@^3.8.0"
|
||||
]
|
||||
# try again
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["-e", "devkit", "-l", "milesburton/DallasTemperature@^3.8.0"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "Already up-to-date." in result.output
|
||||
|
||||
# install library without saving to config
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["-e", "devkit", "-l", "milesburton/DallasTemperature@^3", "--no-save"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "Already up-to-date." in result.output
|
||||
config = ProjectConfig()
|
||||
lm = LibraryPackageManager(
|
||||
os.path.join(config.get("platformio", "libdeps_dir"), "devkit")
|
||||
)
|
||||
assert pkgs_to_specs(lm.get_installed()) == [
|
||||
PackageSpec("DallasTemperature@3.9.1"),
|
||||
PackageSpec("OneWire@2.3.6"),
|
||||
]
|
||||
assert config.get("env:devkit", "lib_deps") == [
|
||||
"milesburton/DallasTemperature@^3.8.0"
|
||||
]
|
||||
|
||||
# unknown libraries
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd, ["-l", "platformio/unknown_library"]
|
||||
)
|
||||
assert isinstance(result.exception, UnknownPackageError)
|
||||
|
||||
|
||||
def test_custom_project_tools(
|
||||
clirunner, validate_cliresult, func_isolated_pio_core, tmp_path
|
||||
):
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
(project_dir / "platformio.ini").write_text(PROJECT_OUTDATED_CONFIG_TPL)
|
||||
spec = "toolchain-atmelavr@~1.50400.0"
|
||||
result = clirunner.invoke(
|
||||
package_install_cmd,
|
||||
["-d", str(project_dir), "-e", "devkit", "-t", spec],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
with fs.cd(str(project_dir)):
|
||||
assert ProjectConfig().get("env:devkit", "platform_packages") == [
|
||||
"platformio/toolchain-atmelavr@~1.50400.0"
|
||||
]
|
||||
assert pkgs_to_specs(ToolPackageManager().get_installed()) == [
|
||||
PackageSpec("toolchain-atmelavr@1.50400.190710")
|
||||
]
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["-e", "devkit", "-t", "toolchain-atmelavr@^1"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert ProjectConfig().get("env:devkit", "platform_packages") == [
|
||||
"platformio/toolchain-atmelavr@^1"
|
||||
]
|
||||
assert pkgs_to_specs(ToolPackageManager().get_installed()) == [
|
||||
PackageSpec("toolchain-atmelavr@1.70300.191015")
|
||||
]
|
||||
|
||||
# install without saving to config
|
||||
result = clirunner.invoke(
|
||||
package_update_cmd,
|
||||
["-e", "devkit", "-t", "toolchain-atmelavr@~1.70300.191015", "--no-save"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "Already up-to-date." in result.output
|
||||
assert ProjectConfig().get("env:devkit", "platform_packages") == [
|
||||
"platformio/toolchain-atmelavr@^1"
|
||||
]
|
||||
|
||||
# unknown tool
|
||||
result = clirunner.invoke(package_update_cmd, ["-t", "platformio/unknown_tool"])
|
||||
assert isinstance(result.exception, UnknownPackageError)
|
||||
|
||||
|
||||
def test_custom_project_platforms(
|
||||
clirunner, validate_cliresult, func_isolated_pio_core, tmp_path
|
||||
):
|
||||
project_dir = tmp_path / "project"
|
||||
project_dir.mkdir()
|
||||
(project_dir / "platformio.ini").write_text(PROJECT_OUTDATED_CONFIG_TPL)
|
||||
spec = "atmelavr@^2"
|
||||
result = clirunner.invoke(
|
||||
package_install_cmd,
|
||||
["-d", str(project_dir), "-e", "devkit", "-p", spec, "--skip-dependencies"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
with fs.cd(str(project_dir)):
|
||||
assert pkgs_to_specs(PlatformPackageManager().get_installed()) == [
|
||||
PackageSpec("atmelavr@2.2.0")
|
||||
]
|
||||
assert ProjectConfig().get("env:devkit", "platform") == "platformio/atmelavr@^2"
|
||||
|
||||
# update
|
||||
result = clirunner.invoke(
|
||||
package_install_cmd,
|
||||
["-e", "devkit", "-p", "platformio/atmelavr@^3", "--skip-dependencies"],
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert pkgs_to_specs(PlatformPackageManager().get_installed()) == [
|
||||
PackageSpec("atmelavr@3.4.0"),
|
||||
PackageSpec("atmelavr@2.2.0"),
|
||||
]
|
||||
assert ProjectConfig().get("env:devkit", "platform") == "platformio/atmelavr@^2"
|
||||
|
||||
# unknown platform
|
||||
result = clirunner.invoke(package_install_cmd, ["-p", "unknown_platform"])
|
||||
assert isinstance(result.exception, UnknownPackageError)
|
@ -17,6 +17,7 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
import pytest
|
||||
import semantic_version
|
||||
|
||||
from platformio.clients.registry import RegistryClient
|
||||
@ -225,5 +226,13 @@ def test_update(clirunner, validate_cliresult, isolated_pio_core, tmpdir_factory
|
||||
result = clirunner.invoke(
|
||||
cmd_lib, ["-d", str(storage_dir), "update", "--dry-run", "ArduinoJson @ ^5"]
|
||||
)
|
||||
with pytest.raises(
|
||||
AssertionError,
|
||||
match="This command is deprecated",
|
||||
):
|
||||
validate_cliresult(result)
|
||||
result = clirunner.invoke(
|
||||
cmd_lib, ["-d", str(storage_dir), "update", "ArduinoJson @ ^5"]
|
||||
)
|
||||
validate_cliresult(result)
|
||||
assert "Incompatible" in result.stdout
|
||||
assert "ArduinoJson @ 5.13.4 is already up-to-date" in result.stdout
|
||||
|
@ -253,8 +253,8 @@ def test_global_lib_update(clirunner, validate_cliresult, strip_ansi):
|
||||
# update rest libraries
|
||||
result = clirunner.invoke(cmd_lib, ["-g", "update"])
|
||||
validate_cliresult(result)
|
||||
assert result.output.count("[Detached]") == 1
|
||||
assert result.output.count("[Up-to-date]") == 13
|
||||
assert result.output.count("+sha.") == 4
|
||||
assert result.output.count("already up-to-date") == 14
|
||||
|
||||
# update unknown library
|
||||
result = clirunner.invoke(cmd_lib, ["-g", "update", "Unknown"])
|
||||
@ -290,17 +290,18 @@ def test_global_lib_uninstall(
|
||||
|
||||
items1 = [d.basename for d in isolated_pio_core.join("lib").listdir()]
|
||||
items2 = [
|
||||
"ArduinoJson",
|
||||
"ArduinoJson@src-69ebddd821f771debe7ee734d3c7fa81",
|
||||
"AsyncMqttClient",
|
||||
"AsyncTCP",
|
||||
"ESP32WebServer",
|
||||
"ESPAsyncTCP",
|
||||
"NeoPixelBus",
|
||||
"PJON",
|
||||
"PJON@src-79de467ebe19de18287becff0a1fb42d",
|
||||
"platformio-libmirror",
|
||||
"PubSubClient",
|
||||
"ArduinoJson@src-69ebddd821f771debe7ee734d3c7fa81",
|
||||
"ESPAsyncTCP@1.2.0",
|
||||
"AsyncTCP",
|
||||
"ArduinoJson",
|
||||
"ESPAsyncTCP",
|
||||
"ESP32WebServer",
|
||||
"PJON",
|
||||
"NeoPixelBus",
|
||||
"PJON@src-79de467ebe19de18287becff0a1fb42d",
|
||||
"SomeLib",
|
||||
]
|
||||
assert set(items1) == set(items2)
|
||||
|
@ -19,7 +19,7 @@ from platformio.commands.update import cli as cmd_update
|
||||
|
||||
def test_update(clirunner, validate_cliresult, isolated_pio_core):
|
||||
matches = ("Platform Manager", "Library Manager")
|
||||
result = clirunner.invoke(cmd_update, ["--only-check"])
|
||||
result = clirunner.invoke(cmd_update)
|
||||
validate_cliresult(result)
|
||||
assert all(m in result.output for m in matches)
|
||||
result = clirunner.invoke(cmd_update)
|
||||
|
Reference in New Issue
Block a user