Files
platformio-core/platformio/pkgmanager.py

170 lines
5.4 KiB
Python
Raw Normal View History

# Copyright 2014-2015 Ivan Kravets <me@ikravets.com>
#
# 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.
from os import makedirs, remove
from os.path import basename, isdir, isfile, join
from shutil import rmtree
2014-11-22 23:55:17 +02:00
from time import time
2014-12-03 20:16:50 +02:00
import click
import requests
from platformio import exception, telemetry, util
2014-11-29 22:39:44 +02:00
from platformio.app import get_state_item, set_state_item
from platformio.downloader import FileDownloader
from platformio.unpacker import FileUnpacker
class PackageManager(object):
2014-11-22 23:55:17 +02:00
def __init__(self):
self._package_dir = join(util.get_home_dir(), "packages")
2014-11-22 23:55:17 +02:00
if not isdir(self._package_dir):
makedirs(self._package_dir)
assert isdir(self._package_dir)
@classmethod
@util.memoized
def get_manifest(cls):
return util.get_api_result("/packages/manifest")
@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()
@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
def is_installed(self, name):
2014-11-22 23:55:17 +02:00
return name in self.get_installed()
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)
# check system platform
systype = util.get_systype()
2014-07-31 16:20:31 +03:00
builds = ([b for b in manifest[name] if b['system'] == "all" or systype
in b['system']])
if not builds:
2014-12-03 20:16:50 +02:00
raise exception.NonSystemPackage(name, systype)
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)
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"))
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
info = self.get_info(name)
2014-11-22 23:55:17 +02:00
pkg_dir = join(self._package_dir, name)
if not isdir(pkg_dir):
makedirs(pkg_dir)
dlpath = None
try:
dlpath = self.download(info['url'], pkg_dir, info['sha1'])
2015-08-04 00:27:13 +03:00
except (requests.exceptions.ConnectionError,
exception.FDUnrecognizedStatusCode):
if info['url'].startswith("http://sourceforge.net"):
dlpath = self.download(
"http://dl.platformio.org/packages/%s" %
basename(info['url']), pkg_dir, info['sha1'])
assert isfile(dlpath)
if self.unpack(dlpath, pkg_dir):
2014-11-22 23:55:17 +02:00
self._register(name, info['version'])
# 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))
self._unregister(name)
2014-12-03 20:16:50 +02:00
click.echo("[%s]" % click.style("OK", fg="green"))
2014-11-29 22:48:15 +02:00
# report usage
telemetry.on_event(
category="PackageManager", action="Uninstall", label=name)
def update(self, name):
2014-12-03 20:16:50 +02:00
click.echo("Updating %s package:" % click.style(name, fg="yellow"))
2014-11-22 23:55:17 +02:00
installed = self.get_installed()
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)
if current_version == latest_version:
2014-12-03 20:16:50 +02:00
click.echo("[%s]" % (click.style("Up-to-date", fg="green")))
return True
else:
2014-12-03 20:16:50 +02:00
click.echo("[%s]" % (click.style("Out-of-date", fg="red")))
2014-11-22 23:55:17 +02:00
self.uninstall(name)
self.install(name)
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):
data = self.get_installed()
2014-11-22 23:55:17 +02:00
data[name] = {
"version": version,
"time": int(time())
}
set_state_item("installed_packages", data)
def _unregister(self, name):
data = self.get_installed()
2014-11-22 23:55:17 +02:00
del data[name]
set_state_item("installed_packages", data)