2014-06-07 13:34:31 +03:00
|
|
|
# Copyright (C) Ivan Kravets <me@ikravets.com>
|
|
|
|
# See LICENSE for details.
|
|
|
|
|
|
|
|
from os import makedirs, remove
|
2014-11-22 23:55:17 +02:00
|
|
|
from os.path import isdir, join
|
2014-06-13 20:47:02 +03:00
|
|
|
from shutil import rmtree
|
2014-11-22 23:55:17 +02:00
|
|
|
from time import time
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-12-03 20:16:50 +02:00
|
|
|
import click
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-12-03 20:16:50 +02:00
|
|
|
from platformio import exception, telemetry
|
2014-11-29 22:39:44 +02:00
|
|
|
from platformio.app import get_state_item, set_state_item
|
2014-06-07 13:34:31 +03:00
|
|
|
from platformio.downloader import FileDownloader
|
|
|
|
from platformio.unpacker import FileUnpacker
|
2014-11-29 22:39:44 +02:00
|
|
|
from platformio.util import get_api_result, get_home_dir, get_systype
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
|
|
|
|
class PackageManager(object):
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
def __init__(self):
|
|
|
|
self._package_dir = join(get_home_dir(), "packages")
|
|
|
|
if not isdir(self._package_dir):
|
|
|
|
makedirs(self._package_dir)
|
|
|
|
assert isdir(self._package_dir)
|
2014-06-07 13:34:31 +03:00
|
|
|
|
2014-11-29 22:55:32 +02:00
|
|
|
@classmethod
|
|
|
|
def get_manifest(cls):
|
2014-06-13 20:47:02 +03:00
|
|
|
try:
|
2014-11-29 22:55:32 +02:00
|
|
|
return cls._cached_manifest
|
2014-06-13 20:47:02 +03:00
|
|
|
except AttributeError:
|
2014-11-29 22:55:32 +02:00
|
|
|
cls._cached_manifest = get_api_result("/packages")
|
|
|
|
return cls._cached_manifest
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def download(url, dest_dir, sha1=None):
|
|
|
|
fd = FileDownloader(url, dest_dir)
|
|
|
|
fd.start()
|
|
|
|
fd.verify(sha1)
|
|
|
|
return fd.get_filepath()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def unpack(pkgpath, dest_dir):
|
|
|
|
fu = FileUnpacker(pkgpath, dest_dir)
|
|
|
|
return fu.start()
|
|
|
|
|
2014-06-13 20:47:02 +03:00
|
|
|
@staticmethod
|
2014-11-22 23:55:17 +02:00
|
|
|
def get_installed():
|
2014-11-29 22:39:44 +02:00
|
|
|
return get_state_item("installed_packages", {})
|
|
|
|
|
|
|
|
def get_outdated(self):
|
|
|
|
outdated = []
|
|
|
|
for name, data in self.get_installed().items():
|
|
|
|
if data['version'] != self.get_info(name)['version']:
|
|
|
|
outdated.append(name)
|
|
|
|
return outdated
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
def is_installed(self, name):
|
2014-11-22 23:55:17 +02:00
|
|
|
return name in self.get_installed()
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
def get_info(self, name, version=None):
|
|
|
|
manifest = self.get_manifest()
|
|
|
|
if name not in manifest:
|
2014-12-03 20:16:50 +02:00
|
|
|
raise exception.UnknownPackage(name)
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
# check system platform
|
2014-07-31 16:20:31 +03:00
|
|
|
systype = get_systype()
|
|
|
|
builds = ([b for b in manifest[name] if b['system'] == "all" or systype
|
2014-06-07 13:34:31 +03:00
|
|
|
in b['system']])
|
|
|
|
if not builds:
|
2014-12-03 20:16:50 +02:00
|
|
|
raise exception.NonSystemPackage(name, systype)
|
2014-06-07 13:34:31 +03:00
|
|
|
|
|
|
|
if version:
|
|
|
|
for b in builds:
|
|
|
|
if b['version'] == version:
|
|
|
|
return b
|
2014-12-03 20:16:50 +02:00
|
|
|
raise exception.InvalidPackageVersion(name, version)
|
2014-06-07 13:34:31 +03:00
|
|
|
else:
|
|
|
|
return sorted(builds, key=lambda s: s['version'])[-1]
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
def install(self, name):
|
2014-12-03 20:16:50 +02:00
|
|
|
click.echo("Installing %s package:" % click.style(name, fg="cyan"))
|
2014-06-13 20:47:02 +03:00
|
|
|
|
|
|
|
if self.is_installed(name):
|
2014-12-03 20:16:50 +02:00
|
|
|
click.secho("Already installed", fg="yellow")
|
2014-11-22 23:55:17 +02:00
|
|
|
return False
|
2014-06-13 20:47:02 +03:00
|
|
|
|
2014-06-07 13:34:31 +03:00
|
|
|
info = self.get_info(name)
|
2014-11-22 23:55:17 +02:00
|
|
|
pkg_dir = join(self._package_dir, name)
|
2014-06-07 13:34:31 +03:00
|
|
|
if not isdir(pkg_dir):
|
|
|
|
makedirs(pkg_dir)
|
|
|
|
|
|
|
|
dlpath = self.download(info['url'], pkg_dir, info['sha1'])
|
|
|
|
if self.unpack(dlpath, pkg_dir):
|
2014-11-22 23:55:17 +02:00
|
|
|
self._register(name, info['version'])
|
2014-06-07 13:34:31 +03:00
|
|
|
# remove archive
|
|
|
|
remove(dlpath)
|
|
|
|
|
2014-11-29 22:48:15 +02:00
|
|
|
telemetry.on_event(
|
|
|
|
category="PackageManager", action="Install", label=name)
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
def uninstall(self, name):
|
2014-12-03 20:16:50 +02:00
|
|
|
click.echo("Uninstalling %s package: \t" %
|
|
|
|
click.style(name, fg="cyan"), nl=False)
|
2014-11-22 23:55:17 +02:00
|
|
|
|
|
|
|
if not self.is_installed(name):
|
2014-12-03 20:16:50 +02:00
|
|
|
click.secho("Not installed", fg="yellow")
|
2014-11-22 23:55:17 +02:00
|
|
|
return False
|
|
|
|
|
|
|
|
rmtree(join(self._package_dir, name))
|
2014-06-13 20:47:02 +03:00
|
|
|
self._unregister(name)
|
2014-12-03 20:16:50 +02:00
|
|
|
click.echo("[%s]" % click.style("OK", fg="green"))
|
2014-06-13 20:47:02 +03:00
|
|
|
|
2014-11-29 22:48:15 +02:00
|
|
|
# report usage
|
|
|
|
telemetry.on_event(
|
|
|
|
category="PackageManager", action="Uninstall", label=name)
|
|
|
|
|
2014-06-13 20:47:02 +03:00
|
|
|
def update(self, name):
|
2014-12-03 20:16:50 +02:00
|
|
|
click.echo("Updating %s package:" % click.style(name, fg="yellow"))
|
2014-06-13 20:47:02 +03:00
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
installed = self.get_installed()
|
2014-06-13 20:47:02 +03:00
|
|
|
current_version = installed[name]['version']
|
|
|
|
latest_version = self.get_info(name)['version']
|
|
|
|
|
2014-12-04 23:17:45 +02:00
|
|
|
click.echo("Versions: Current=%d, Latest=%d \t " %
|
|
|
|
(current_version, latest_version), nl=False)
|
2014-06-13 20:47:02 +03:00
|
|
|
|
|
|
|
if current_version == latest_version:
|
2014-12-03 20:16:50 +02:00
|
|
|
click.echo("[%s]" % (click.style("Up-to-date", fg="green")))
|
2014-06-13 20:47:02 +03:00
|
|
|
return True
|
|
|
|
else:
|
2014-12-03 20:16:50 +02:00
|
|
|
click.echo("[%s]" % (click.style("Out-of-date", fg="red")))
|
2014-06-13 20:47:02 +03:00
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
self.uninstall(name)
|
|
|
|
self.install(name)
|
2014-06-13 20:47:02 +03:00
|
|
|
|
2014-11-29 22:48:15 +02:00
|
|
|
telemetry.on_event(
|
|
|
|
category="PackageManager", action="Update", label=name)
|
|
|
|
|
2014-11-22 23:55:17 +02:00
|
|
|
def _register(self, name, version):
|
2014-06-07 13:34:31 +03:00
|
|
|
data = self.get_installed()
|
2014-11-22 23:55:17 +02:00
|
|
|
data[name] = {
|
2014-06-07 13:34:31 +03:00
|
|
|
"version": version,
|
2014-11-29 22:55:32 +02:00
|
|
|
"time": int(time())
|
2014-06-07 13:34:31 +03:00
|
|
|
}
|
2014-11-29 22:55:32 +02:00
|
|
|
set_state_item("installed_packages", data)
|
2014-06-13 20:47:02 +03:00
|
|
|
|
|
|
|
def _unregister(self, name):
|
|
|
|
data = self.get_installed()
|
2014-11-22 23:55:17 +02:00
|
|
|
del data[name]
|
2014-11-29 22:55:32 +02:00
|
|
|
set_state_item("installed_packages", data)
|