Files
platformio-core/platformio/maintenance.py
T
Ivan Kravets 45e75f7473 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.
2017-06-05 16:02:39 +03:00

339 lines
12 KiB
Python

# 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 json
import os
from os import getenv
from os.path import isdir, join
from time import time
import click
import semantic_version
from platformio import __version__, app, exception, telemetry, util
from platformio.commands.lib import lib_update as cmd_lib_update
from platformio.commands.platform import \
platform_install as cmd_platform_install
from platformio.commands.platform import \
platform_uninstall as cmd_platform_uninstall
from platformio.commands.platform import platform_update as cmd_platform_update
from platformio.commands.upgrade import get_latest_version
from platformio.managers.core import update_core_packages
from platformio.managers.lib import LibraryManager
from platformio.managers.platform import PlatformFactory, PlatformManager
def in_silence(ctx=None):
ctx = ctx or app.get_session_var("command_ctx")
assert ctx
ctx_args = ctx.args or []
conditions = [
ctx.args[0] == "upgrade", "--json-output" in ctx_args,
"--version" in ctx_args
]
return ctx_args and any(conditions)
def on_platformio_start(ctx, force, caller):
if not caller:
if getenv("PLATFORMIO_CALLER"):
caller = getenv("PLATFORMIO_CALLER")
elif getenv("VSCODE_PID") or getenv("VSCODE_NLS_CONFIG"):
caller = "vscode"
elif util.is_container():
if getenv("C9_UID"):
caller = "C9"
elif getenv("USER") == "cabox":
caller = "CA"
elif getenv("CHE_API", getenv("CHE_API_ENDPOINT")):
caller = "Che"
app.set_session_var("command_ctx", ctx)
app.set_session_var("force_option", force)
app.set_session_var("caller_id", caller)
telemetry.on_command()
if not in_silence(ctx):
after_upgrade(ctx)
def on_platformio_end(ctx, result): # pylint: disable=W0613
if in_silence(ctx):
return
try:
check_platformio_upgrade()
check_internal_updates(ctx, "platforms")
check_internal_updates(ctx, "libraries")
except (exception.GetLatestVersionError, exception.APIRequestError):
click.secho(
"Failed to check for PlatformIO upgrades. "
"Please check your Internet connection.",
fg="red")
def on_platformio_exception(e):
telemetry.on_exception(e)
class Upgrader(object):
def __init__(self, from_version, to_version):
self.from_version = semantic_version.Version.coerce(
util.pepver_to_semver(from_version))
self.to_version = semantic_version.Version.coerce(
util.pepver_to_semver(to_version))
self._upgraders = [
(semantic_version.Version("3.0.0-a.1"), self._upgrade_to_3_0_0),
(semantic_version.Version("3.0.0-b.11"),
self._upgrade_to_3_0_0b11),
(semantic_version.Version("3.4.0-a.9"), self._update_dev_platforms)
]
def run(self, ctx):
if self.from_version > self.to_version:
return True
result = [True]
for version, callback in self._upgraders:
if self.from_version >= version or self.to_version < version:
continue
result.append(callback(ctx))
return all(result)
@staticmethod
def _upgrade_to_3_0_0(ctx):
# convert custom board configuration
boards_dir = join(util.get_home_dir(), "boards")
if isdir(boards_dir):
for item in os.listdir(boards_dir):
if not item.endswith(".json"):
continue
data = util.load_json(join(boards_dir, item))
if set(["name", "url", "vendor"]) <= set(data.keys()):
continue
os.remove(join(boards_dir, item))
for key, value in data.items():
with open(join(boards_dir, "%s.json" % key), "w") as f:
json.dump(value, f, sort_keys=True, indent=2)
# re-install PlatformIO 2.0 development platforms
installed_platforms = app.get_state_item("installed_platforms", [])
if installed_platforms:
if "espressif" in installed_platforms:
installed_platforms[installed_platforms.index(
"espressif")] = "espressif8266"
ctx.invoke(cmd_platform_install, platforms=installed_platforms)
return True
@staticmethod
def _upgrade_to_3_0_0b11(ctx):
current_platforms = [
m['name'] for m in PlatformManager().get_installed()
]
if "espressif" not in current_platforms:
return True
ctx.invoke(cmd_platform_install, platforms=["espressif8266"])
ctx.invoke(cmd_platform_uninstall, platforms=["espressif"])
return True
@staticmethod
def _update_dev_platforms(ctx):
ctx.invoke(cmd_platform_update)
return True
def after_upgrade(ctx):
terminal_width, _ = click.get_terminal_size()
last_version = app.get_state_item("last_version", "0.0.0")
if last_version == __version__:
return
if last_version == "0.0.0":
app.set_state_item("last_version", __version__)
elif semantic_version.Version.coerce(util.pepver_to_semver(
last_version)) > semantic_version.Version.coerce(
util.pepver_to_semver(__version__)):
click.secho("*" * terminal_width, fg="yellow")
click.secho(
"Obsolete PIO Core v%s is used (previous was %s)" %
(__version__, last_version),
fg="yellow")
click.secho(
"Please remove multiple PIO Cores from a system:", fg="yellow")
click.secho(
"http://docs.platformio.org/page/faq.html"
"#multiple-pio-cores-in-a-system",
fg="cyan")
click.secho("*" * terminal_width, fg="yellow")
return
else:
click.secho("Please wait while upgrading PlatformIO...", fg="yellow")
app.clean_cache()
# Update PlatformIO's Core packages
update_core_packages(silent=True)
u = Upgrader(last_version, __version__)
if u.run(ctx):
app.set_state_item("last_version", __version__)
click.secho(
"PlatformIO has been successfully upgraded to %s!\n" %
__version__,
fg="green")
telemetry.on_event(
category="Auto",
action="Upgrade",
label="%s > %s" % (last_version, __version__))
else:
raise exception.UpgradeError("Auto upgrading...")
click.echo("")
# PlatformIO banner
click.echo("*" * terminal_width)
click.echo("If you like %s, please:" % (click.style(
"PlatformIO", fg="cyan")))
click.echo("- %s us on Twitter to stay up-to-date "
"on the latest project news > %s" % (click.style(
"follow", fg="cyan"), click.style(
"https://twitter.com/PlatformIO_Org", fg="cyan")))
click.echo("- %s it on GitHub > %s" %
(click.style("star", fg="cyan"), click.style(
"https://github.com/platformio/platformio", fg="cyan")))
if not getenv("PLATFORMIO_IDE"):
click.echo("- %s PlatformIO IDE for IoT development > %s" %
(click.style("try", fg="cyan"), click.style(
"http://platformio.org/platformio-ide", fg="cyan")))
if not util.is_ci():
click.echo("- %s us with PlatformIO Plus > %s" % (click.style(
"support", fg="cyan"), click.style(
"https://pioplus.com", fg="cyan")))
click.echo("*" * terminal_width)
click.echo("")
def check_platformio_upgrade():
last_check = app.get_state_item("last_check", {})
interval = int(app.get_setting("check_platformio_interval")) * 3600 * 24
if (time() - interval) < last_check.get("platformio_upgrade", 0):
return
last_check['platformio_upgrade'] = int(time())
app.set_state_item("last_check", last_check)
latest_version = get_latest_version()
if semantic_version.Version.coerce(util.pepver_to_semver(
latest_version)) <= semantic_version.Version.coerce(
util.pepver_to_semver(__version__)):
return
terminal_width, _ = click.get_terminal_size()
click.echo("")
click.echo("*" * terminal_width)
click.secho(
"There is a new version %s of PlatformIO available.\n"
"Please upgrade it via `" % latest_version,
fg="yellow",
nl=False)
if getenv("PLATFORMIO_IDE"):
click.secho(
"PlatformIO IDE Menu: Upgrade PlatformIO", fg="cyan", nl=False)
click.secho("`.", fg="yellow")
elif join("Cellar", "platformio") in util.get_source_dir():
click.secho("brew update && brew upgrade", fg="cyan", nl=False)
click.secho("` command.", fg="yellow")
else:
click.secho("platformio upgrade", fg="cyan", nl=False)
click.secho("` or `", fg="yellow", nl=False)
click.secho("pip install -U platformio", fg="cyan", nl=False)
click.secho("` command.", fg="yellow")
click.secho("Changes: ", fg="yellow", nl=False)
click.secho("http://docs.platformio.org/en/latest/history.html", fg="cyan")
click.echo("*" * terminal_width)
click.echo("")
def check_internal_updates(ctx, what):
last_check = app.get_state_item("last_check", {})
interval = int(app.get_setting("check_%s_interval" % what)) * 3600 * 24
if (time() - interval) < last_check.get(what + "_update", 0):
return
last_check[what + '_update'] = int(time())
app.set_state_item("last_check", last_check)
pm = PlatformManager() if what == "platforms" else LibraryManager()
outdated_items = []
for manifest in pm.get_installed():
if manifest['name'] in outdated_items:
continue
conds = [
pm.outdated(manifest['__pkg_dir']), what == "platforms" and
PlatformFactory.newPlatform(
manifest['__pkg_dir']).are_outdated_packages()
]
if any(conds):
outdated_items.append(manifest['name'])
if not outdated_items:
return
terminal_width, _ = click.get_terminal_size()
click.echo("")
click.echo("*" * terminal_width)
click.secho(
"There are the new updates for %s (%s)" %
(what, ", ".join(outdated_items)),
fg="yellow")
if not app.get_setting("auto_update_" + what):
click.secho("Please update them via ", fg="yellow", nl=False)
click.secho(
"`platformio %s update`" %
("lib --global" if what == "libraries" else "platform"),
fg="cyan",
nl=False)
click.secho(" command.\n", fg="yellow")
click.secho(
"If you want to manually check for the new versions "
"without updating, please use ",
fg="yellow",
nl=False)
click.secho(
"`platformio %s update --only-check`" %
("lib --global" if what == "libraries" else "platform"),
fg="cyan",
nl=False)
click.secho(" command.", fg="yellow")
else:
click.secho("Please wait while updating %s ..." % what, fg="yellow")
if what == "platforms":
ctx.invoke(cmd_platform_update, platforms=outdated_items)
elif what == "libraries":
ctx.obj = pm
ctx.invoke(cmd_lib_update, libraries=outdated_items)
click.echo()
telemetry.on_event(
category="Auto", action="Update", label=what.title())
click.echo("*" * terminal_width)
click.echo("")