forked from platformio/platformio-core
		
	
		
			
				
	
	
		
			151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (C) Ivan Kravets <me@ikravets.com>
 | 
						|
# See LICENSE for details.
 | 
						|
 | 
						|
from os import makedirs, remove
 | 
						|
from os.path import isdir, join
 | 
						|
from shutil import rmtree
 | 
						|
from time import time
 | 
						|
 | 
						|
import click
 | 
						|
 | 
						|
from platformio import exception, telemetry
 | 
						|
from platformio.app import get_state_item, set_state_item
 | 
						|
from platformio.downloader import FileDownloader
 | 
						|
from platformio.unpacker import FileUnpacker
 | 
						|
from platformio.util import get_api_result, get_home_dir, get_systype
 | 
						|
 | 
						|
 | 
						|
class PackageManager(object):
 | 
						|
 | 
						|
    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)
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def get_manifest(cls):
 | 
						|
        try:
 | 
						|
            return cls._cached_manifest
 | 
						|
        except AttributeError:
 | 
						|
            cls._cached_manifest = get_api_result("/packages")
 | 
						|
        return cls._cached_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
 | 
						|
    def get_installed():
 | 
						|
        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):
 | 
						|
        return name in self.get_installed()
 | 
						|
 | 
						|
    def get_info(self, name, version=None):
 | 
						|
        manifest = self.get_manifest()
 | 
						|
        if name not in manifest:
 | 
						|
            raise exception.UnknownPackage(name)
 | 
						|
 | 
						|
        # check system platform
 | 
						|
        systype = get_systype()
 | 
						|
        builds = ([b for b in manifest[name] if b['system'] == "all" or systype
 | 
						|
                   in b['system']])
 | 
						|
        if not builds:
 | 
						|
            raise exception.NonSystemPackage(name, systype)
 | 
						|
 | 
						|
        if version:
 | 
						|
            for b in builds:
 | 
						|
                if b['version'] == version:
 | 
						|
                    return b
 | 
						|
            raise exception.InvalidPackageVersion(name, version)
 | 
						|
        else:
 | 
						|
            return sorted(builds, key=lambda s: s['version'])[-1]
 | 
						|
 | 
						|
    def install(self, name):
 | 
						|
        click.echo("Installing %s package:" % click.style(name, fg="cyan"))
 | 
						|
 | 
						|
        if self.is_installed(name):
 | 
						|
            click.secho("Already installed", fg="yellow")
 | 
						|
            return False
 | 
						|
 | 
						|
        info = self.get_info(name)
 | 
						|
        pkg_dir = join(self._package_dir, name)
 | 
						|
        if not isdir(pkg_dir):
 | 
						|
            makedirs(pkg_dir)
 | 
						|
 | 
						|
        dlpath = self.download(info['url'], pkg_dir, info['sha1'])
 | 
						|
        if self.unpack(dlpath, pkg_dir):
 | 
						|
            self._register(name, info['version'])
 | 
						|
        # remove archive
 | 
						|
        remove(dlpath)
 | 
						|
 | 
						|
        telemetry.on_event(
 | 
						|
            category="PackageManager", action="Install", label=name)
 | 
						|
 | 
						|
    def uninstall(self, name):
 | 
						|
        click.echo("Uninstalling %s package: \t" %
 | 
						|
                   click.style(name, fg="cyan"), nl=False)
 | 
						|
 | 
						|
        if not self.is_installed(name):
 | 
						|
            click.secho("Not installed", fg="yellow")
 | 
						|
            return False
 | 
						|
 | 
						|
        rmtree(join(self._package_dir, name))
 | 
						|
        self._unregister(name)
 | 
						|
        click.echo("[%s]" % click.style("OK", fg="green"))
 | 
						|
 | 
						|
        # report usage
 | 
						|
        telemetry.on_event(
 | 
						|
            category="PackageManager", action="Uninstall", label=name)
 | 
						|
 | 
						|
    def update(self, name):
 | 
						|
        click.echo("Updating %s package:" % click.style(name, fg="yellow"))
 | 
						|
 | 
						|
        installed = self.get_installed()
 | 
						|
        current_version = installed[name]['version']
 | 
						|
        latest_version = self.get_info(name)['version']
 | 
						|
 | 
						|
        click.echo("Versions: Current=%d, Latest=%d \t " %
 | 
						|
                   (current_version, latest_version), nl=False)
 | 
						|
 | 
						|
        if current_version == latest_version:
 | 
						|
            click.echo("[%s]" % (click.style("Up-to-date", fg="green")))
 | 
						|
            return True
 | 
						|
        else:
 | 
						|
            click.echo("[%s]" % (click.style("Out-of-date", fg="red")))
 | 
						|
 | 
						|
        self.uninstall(name)
 | 
						|
        self.install(name)
 | 
						|
 | 
						|
        telemetry.on_event(
 | 
						|
            category="PackageManager", action="Update", label=name)
 | 
						|
 | 
						|
    def _register(self, name, version):
 | 
						|
        data = self.get_installed()
 | 
						|
        data[name] = {
 | 
						|
            "version": version,
 | 
						|
            "time": int(time())
 | 
						|
        }
 | 
						|
        set_state_item("installed_packages", data)
 | 
						|
 | 
						|
    def _unregister(self, name):
 | 
						|
        data = self.get_installed()
 | 
						|
        del data[name]
 | 
						|
        set_state_item("installed_packages", data)
 |