Refactored Package Manager

This commit is contained in:
Ivan Kravets
2014-11-22 23:55:17 +02:00
parent f8ed09c3ad
commit b103dc01c0
20 changed files with 257 additions and 171 deletions

View File

@ -4,6 +4,7 @@ Release History
0.9.0 (?) 0.9.0 (?)
--------- ---------
* Refactored *Package Manager*
* Download Manager: fixed SHA1 verification within *Cygwin Environment* * Download Manager: fixed SHA1 verification within *Cygwin Environment*
(`issue #26 <https://github.com/ivankravets/platformio/issues/26>`_) (`issue #26 <https://github.com/ivankravets/platformio/issues/26>`_)

View File

@ -16,4 +16,3 @@ __license__ = "MIT License"
__copyright__ = "Copyright (C) 2014 Ivan Kravets" __copyright__ = "Copyright (C) 2014 Ivan Kravets"
__apiurl__ = "http://api.platformio.ikravets.com" __apiurl__ = "http://api.platformio.ikravets.com"
__pkgmanifesturl__ = "http://dl.platformio.ikravets.com/packages/manifest.json"

View File

@ -11,10 +11,10 @@ except ImportError:
break break
from platformio.util import get_home_dir from platformio.util import get_home_dir
from os.path import isdir, join from os.path import join
from SCons.Script import (DefaultEnvironment, Exit, SConscript, from SCons.Script import (DefaultEnvironment, SConscript, SConscriptChdir,
SConscriptChdir, Variables) Variables)
from platformio.util import (get_lib_dir, get_pioenvs_dir, get_project_dir, from platformio.util import (get_lib_dir, get_pioenvs_dir, get_project_dir,
get_source_dir) get_source_dir)
@ -24,8 +24,16 @@ from platformio.util import (get_lib_dir, get_pioenvs_dir, get_project_dir,
# allow common variables from INI file # allow common variables from INI file
commonvars = Variables(None) commonvars = Variables(None)
commonvars.AddVariables( commonvars.AddVariables(
("BUILD_SCRIPT",),
("PIOENV",), ("PIOENV",),
("PLATFORM",), ("PLATFORM",),
# package aliases
("PIOPACKAGE_TOOLCHAIN",),
("PIOPACKAGE_UPLOADER",),
("PIOPACKAGE_FRAMEWORK",),
# options
("FRAMEWORK",), ("FRAMEWORK",),
("BUILD_FLAGS",), ("BUILD_FLAGS",),
("SRCBUILD_FLAGS",), ("SRCBUILD_FLAGS",),
@ -46,14 +54,13 @@ DefaultEnvironment(
toolpath=[join("$PIOBUILDER_DIR", "tools")], toolpath=[join("$PIOBUILDER_DIR", "tools")],
variables=commonvars, variables=commonvars,
PIOBUILDER_DIR=join(get_source_dir(), "builder"), PIOHOME_DIR=get_home_dir(),
PROJECT_DIR=get_project_dir(), PROJECT_DIR=get_project_dir(),
PIOENVS_DIR=get_pioenvs_dir(), PIOENVS_DIR=get_pioenvs_dir(),
PLATFORMIOHOME_DIR=get_home_dir(), PIOBUILDER_DIR=join(get_source_dir(), "builder"),
PLATFORM_DIR=join("$PLATFORMIOHOME_DIR", "$PLATFORM"), PIOPACKAGES_DIR=join("$PIOHOME_DIR", "packages"),
PLATFORMFW_DIR=join("$PLATFORM_DIR", "frameworks", "$FRAMEWORK"), PLATFORMFW_DIR=join("$PIOPACKAGES_DIR", "$PIOPACKAGE_FRAMEWORK"),
PLATFORMTOOLS_DIR=join("$PLATFORM_DIR", "tools"),
BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"), BUILD_DIR=join("$PIOENVS_DIR", "$PIOENV"),
LIBSOURCE_DIRS=[ LIBSOURCE_DIRS=[
@ -64,14 +71,10 @@ DefaultEnvironment(
) )
env = DefaultEnvironment() env = DefaultEnvironment()
env.PrependENVPath(
if not isdir(env['PLATFORMIOHOME_DIR']): "PATH",
Exit("You haven't installed any platforms yet. Please use " env.subst(join("$PIOPACKAGES_DIR", "$PIOPACKAGE_TOOLCHAIN", "bin"))
"`platformio install` command") )
elif not isdir(env.subst("$PLATFORM_DIR")):
Exit("An '%s' platform hasn't been installed yet. Please use "
"`platformio install %s` command" % (env['PLATFORM'],
env['PLATFORM']))
SConscriptChdir(0) SConscriptChdir(0)
SConscript(env.subst(join("$PIOBUILDER_DIR", "scripts", "${PLATFORM}.py"))) SConscript(env.subst("$BUILD_SCRIPT"))

View File

@ -53,13 +53,13 @@ env.Replace(
"-mmcu=$BOARD_MCU" "-mmcu=$BOARD_MCU"
], ],
UPLOADER=join("$PLATFORMTOOLS_DIR", "avrdude", "avrdude"), UPLOADER=join("$PIOPACKAGES_DIR", "tool-avrdude", "avrdude"),
UPLOADERFLAGS=[ UPLOADERFLAGS=[
"-V", # do not verify "-V", # do not verify
"-q", # suppress progress output "-q", # suppress progress output
"-D", # disable auto erase for flash memory "-D", # disable auto erase for flash memory
"-p", "$BOARD_MCU", "-p", "$BOARD_MCU",
"-C", join("$PLATFORMTOOLS_DIR", "avrdude", "avrdude.conf"), "-C", join("$PIOPACKAGES_DIR", "tool-avrdude", "avrdude.conf"),
"-c", "$UPLOAD_PROTOCOL", "-c", "$UPLOAD_PROTOCOL",
"-b", "$UPLOAD_SPEED", "-b", "$UPLOAD_SPEED",
"-P", "$UPLOAD_PORT" "-P", "$UPLOAD_PORT"

View File

@ -51,7 +51,7 @@ env.Replace(
"-Wl,-gc-sections,-u,main" "-Wl,-gc-sections,-u,main"
], ],
UPLOADER=join("$PLATFORMTOOLS_DIR", "mspdebug", "mspdebug"), UPLOADER=join("$PIOPACKAGES_DIR", "tool-mspdebug", "mspdebug"),
UPLOADERFLAGS=[ UPLOADERFLAGS=[
"$UPLOAD_PROTOCOL" if system() != "Windows" else "tilib", "$UPLOAD_PROTOCOL" if system() != "Windows" else "tilib",
"--force-reset" "--force-reset"

View File

@ -71,7 +71,7 @@ env.Replace(
"-fsingle-precision-constant" "-fsingle-precision-constant"
], ],
UPLOADER=join("$PLATFORMTOOLS_DIR", "lm4flash", "lm4flash"), UPLOADER=join("$PIOPACKAGES_DIR", "tool-lm4flash", "lm4flash"),
UPLOADCMD="$UPLOADER $SOURCES" UPLOADCMD="$UPLOADER $SOURCES"
) )

View File

@ -14,11 +14,6 @@ def ProcessGeneral(env):
if "BUILD_FLAGS" in env: if "BUILD_FLAGS" in env:
env.MergeFlags(env['BUILD_FLAGS']) env.MergeFlags(env['BUILD_FLAGS'])
env.PrependENVPath(
"PATH",
join(env.subst("$PLATFORMTOOLS_DIR"), "toolchain", "bin")
)
if "FRAMEWORK" in env: if "FRAMEWORK" in env:
if env['FRAMEWORK'] in ("arduino", "energia"): if env['FRAMEWORK'] in ("arduino", "energia"):
env.ConvertInotoCpp() env.ConvertInotoCpp()

View File

@ -8,7 +8,6 @@ from platformio.exception import (LibAlreadyInstalledError,
from platformio.libmanager import LibraryManager from platformio.libmanager import LibraryManager
from platformio.util import get_api_result, get_lib_dir from platformio.util import get_api_result, get_lib_dir
LIBLIST_TPL = ("[{id:^14}] {name:<25} {compatibility:<30} " LIBLIST_TPL = ("[{id:^14}] {name:<25} {compatibility:<30} "
"\"{authornames}\": {description}") "\"{authornames}\": {description}")

View File

@ -3,14 +3,19 @@
from click import command, echo, style from click import command, echo, style
from platformio.pkgmanager import PackageManager from platformio.platforms.base import PlatformFactory
@command("list", short_help="List installed platforms") @command("list", short_help="List installed platforms")
def cli(): def cli():
for name, pkgs in PackageManager.get_installed().items(): installed_platforms = PlatformFactory.get_platforms(
installed=True).keys()
sorted(installed_platforms)
for platform in installed_platforms:
p = PlatformFactory().newPlatform(platform)
echo("{name:<20} with packages: {pkgs}".format( echo("{name:<20} with packages: {pkgs}".format(
name=style(name, fg="cyan"), name=style(p.get_name(), fg="cyan"),
pkgs=", ".join(pkgs.keys()) pkgs=", ".join(p.get_installed_packages())
)) ))

View File

@ -4,19 +4,21 @@
from click import argument, command, echo, style from click import argument, command, echo, style
from platformio.platforms.base import PlatformFactory from platformio.platforms.base import PlatformFactory
from platformio.util import get_platforms
@command("search", short_help="Search for development platforms") @command("search", short_help="Search for development platforms")
@argument("query") @argument("query")
def cli(query): def cli(query):
for platform in get_platforms(): for platform in PlatformFactory.get_platforms().keys():
p = PlatformFactory().newPlatform(platform) p = PlatformFactory().newPlatform(platform)
name = p.get_name() name = p.get_name()
shinfo = p.get_short_info() shinfo = p.get_short_info()
if query == "all":
query = ""
search_data = "%s %s" % (name, shinfo) search_data = "%s %s" % (name, shinfo)
if query != "all" and query.lower() not in search_data.lower(): if query and query.lower() not in search_data.lower():
continue continue
echo("{name:<20} - {info}".format(name=style(name, fg="cyan"), echo("{name:<20} - {info}".format(name=style(name, fg="cyan"),

View File

@ -1,7 +1,7 @@
# Copyright (C) Ivan Kravets <me@ikravets.com> # Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details. # See LICENSE for details.
from os.path import join from datetime import datetime
from click import argument, command, echo, style from click import argument, command, echo, style
@ -13,20 +13,25 @@ from platformio.platforms.base import PlatformFactory
@command("show", short_help="Show details about installed platforms") @command("show", short_help="Show details about installed platforms")
@argument("platform") @argument("platform")
def cli(platform): def cli(platform):
p = PlatformFactory().newPlatform(platform)
if platform not in PackageManager.get_installed(): installed_platforms = PlatformFactory.get_platforms(
installed=True).keys()
if platform not in installed_platforms:
raise PlatformNotInstalledYet(platform) raise PlatformNotInstalledYet(platform)
# print info about platform p = PlatformFactory().newPlatform(platform)
echo("{name:<20} - {info}".format(name=style(p.get_name(), fg="cyan"), echo("{name:<20} - {info}".format(name=style(p.get_name(), fg="cyan"),
info=p.get_short_info())) info=p.get_short_info()))
pm = PackageManager(platform) installed_packages = PackageManager.get_installed()
for name, data in pm.get_installed(platform).items(): for name in p.get_installed_packages():
data = installed_packages[name]
pkgalias = p.get_pkg_alias(name) pkgalias = p.get_pkg_alias(name)
echo("----------") echo("----------")
echo("Package: %s" % style(name, fg="yellow")) echo("Package: %s" % style(name, fg="yellow"))
if pkgalias: if pkgalias:
echo("Alias: %s" % pkgalias) echo("Alias: %s" % pkgalias)
echo("Location: %s" % join(pm.get_platform_dir(), data['path']))
echo("Version: %d" % int(data['version'])) echo("Version: %d" % int(data['version']))
echo("Installed: %s" % datetime.fromtimestamp(
data['time']).strftime("%Y-%m-%d %H:%M:%S"))

View File

@ -3,8 +3,6 @@
from click import argument, command, secho from click import argument, command, secho
from platformio.exception import PlatformNotInstalledYet
from platformio.pkgmanager import PackageManager
from platformio.platforms.base import PlatformFactory from platformio.platforms.base import PlatformFactory
@ -13,10 +11,6 @@ from platformio.platforms.base import PlatformFactory
def cli(platforms): def cli(platforms):
for platform in platforms: for platform in platforms:
if platform not in PackageManager.get_installed():
raise PlatformNotInstalledYet(platform)
p = PlatformFactory().newPlatform(platform) p = PlatformFactory().newPlatform(platform)
if p.uninstall(): if p.uninstall():
secho("The platform '%s' has been successfully " secho("The platform '%s' has been successfully "

View File

@ -3,14 +3,17 @@
from click import command, echo, style from click import command, echo, style
from platformio.pkgmanager import PackageManager
from platformio.platforms.base import PlatformFactory from platformio.platforms.base import PlatformFactory
@command("update", short_help="Update installed platforms") @command("update", short_help="Update installed platforms")
def cli(): def cli():
for platform in PackageManager.get_installed().keys(): installed_platforms = PlatformFactory.get_platforms(
installed=True).keys()
sorted(installed_platforms)
for platform in installed_platforms:
echo("\nPlatform %s" % style(platform, fg="cyan")) echo("\nPlatform %s" % style(platform, fg="cyan"))
echo("--------") echo("--------")
p = PlatformFactory().newPlatform(platform) p = PlatformFactory().newPlatform(platform)

View File

@ -124,3 +124,8 @@ class LibNotInstalledError(PlatformioException):
class LibInstallDependencyError(PlatformioException): class LibInstallDependencyError(PlatformioException):
MESSAGE = "Error has been occurred for library dependency '%s'" MESSAGE = "Error has been occurred for library dependency '%s'"
class BuildScriptNotFound(PlatformioException):
MESSAGE = "Invalid path '%s' to build script"

View File

@ -1,39 +1,36 @@
# Copyright (C) Ivan Kravets <me@ikravets.com> # Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details. # See LICENSE for details.
import json
from os import makedirs, remove from os import makedirs, remove
from os.path import isdir, isfile, join from os.path import isdir, join
from shutil import rmtree from shutil import rmtree
from time import time
from click import echo, secho, style from click import echo, secho, style
from requests import get
from requests.utils import default_user_agent
from platformio import __pkgmanifesturl__, __version__
from platformio.downloader import FileDownloader from platformio.downloader import FileDownloader
from platformio.exception import (InvalidPackageVersion, NonSystemPackage, from platformio.exception import (InvalidPackageVersion, NonSystemPackage,
UnknownPackage) UnknownPackage)
from platformio.unpacker import FileUnpacker from platformio.unpacker import FileUnpacker
from platformio.util import get_home_dir, get_systype from platformio.util import AppState, get_api_result, get_home_dir, get_systype
class PackageManager(object): class PackageManager(object):
DBFILE_PATH = join(get_home_dir(), "installed.json") DBFILE_PATH = join(get_home_dir(), "installed.json")
def __init__(self, platform_name): def __init__(self):
self._platform_name = platform_name self._package_dir = join(get_home_dir(), "packages")
if not isdir(self._package_dir):
makedirs(self._package_dir)
assert isdir(self._package_dir)
@staticmethod @staticmethod
def get_manifest(): def get_manifest():
try: try:
return PackageManager._cached_manifest return PackageManager._cached_manifest
except AttributeError: except AttributeError:
headers = {"User-Agent": "PlatformIO/%s %s" % ( PackageManager._cached_manifest = get_api_result("/packages")
__version__, default_user_agent())}
PackageManager._cached_manifest = get(__pkgmanifesturl__,
headers=headers).json()
return PackageManager._cached_manifest return PackageManager._cached_manifest
@staticmethod @staticmethod
@ -49,20 +46,19 @@ class PackageManager(object):
return fu.start() return fu.start()
@staticmethod @staticmethod
def get_installed(platform=None): def get_installed():
data = {} pkgs = {}
if isfile(PackageManager.DBFILE_PATH): with AppState() as state:
with open(PackageManager.DBFILE_PATH) as fp: pkgs = state.get("installed_packages", {})
data = json.load(fp) return pkgs
return data.get(platform, None) if platform else data
def get_platform_dir(self): @staticmethod
return join(get_home_dir(), self._platform_name) def update_appstate_instpkgs(data):
with AppState() as state:
state['installed_packages'] = data
def is_installed(self, name): def is_installed(self, name):
installed = self.get_installed() return name in self.get_installed()
return (self._platform_name in installed and name in
installed[self._platform_name])
def get_info(self, name, version=None): def get_info(self, name, version=None):
manifest = self.get_manifest() manifest = self.get_manifest()
@ -84,35 +80,40 @@ class PackageManager(object):
else: else:
return sorted(builds, key=lambda s: s['version'])[-1] return sorted(builds, key=lambda s: s['version'])[-1]
def install(self, name, path): def install(self, name):
echo("Installing %s package:" % style(name, fg="cyan")) echo("Installing %s package:" % style(name, fg="cyan"))
if self.is_installed(name): if self.is_installed(name):
secho("Already installed", fg="yellow") secho("Already installed", fg="yellow")
return return False
info = self.get_info(name) info = self.get_info(name)
pkg_dir = join(self.get_platform_dir(), path) pkg_dir = join(self._package_dir, name)
if not isdir(pkg_dir): if not isdir(pkg_dir):
makedirs(pkg_dir) makedirs(pkg_dir)
dlpath = self.download(info['url'], pkg_dir, info['sha1']) dlpath = self.download(info['url'], pkg_dir, info['sha1'])
if self.unpack(dlpath, pkg_dir): if self.unpack(dlpath, pkg_dir):
self._register(name, info['version'], path) self._register(name, info['version'])
# remove archive # remove archive
remove(dlpath) remove(dlpath)
def uninstall(self, name, path): def uninstall(self, name):
echo("Uninstalling %s package: \t" % style(name, fg="cyan"), echo("Uninstalling %s package: \t" % style(name, fg="cyan"),
nl=False) nl=False)
rmtree(join(self.get_platform_dir(), path))
if not self.is_installed(name):
secho("Not installed", fg="yellow")
return False
rmtree(join(self._package_dir, name))
self._unregister(name) self._unregister(name)
echo("[%s]" % style("OK", fg="green")) echo("[%s]" % style("OK", fg="green"))
def update(self, name): def update(self, name):
echo("Updating %s package:" % style(name, fg="yellow")) echo("Updating %s package:" % style(name, fg="yellow"))
installed = self.get_installed(self._platform_name) installed = self.get_installed()
current_version = installed[name]['version'] current_version = installed[name]['version']
latest_version = self.get_info(name)['version'] latest_version = self.get_info(name)['version']
@ -125,36 +126,18 @@ class PackageManager(object):
else: else:
echo("[%s]" % (style("Out-of-date", fg="red"))) echo("[%s]" % (style("Out-of-date", fg="red")))
self.uninstall(name, installed[name]['path']) self.uninstall(name)
self.install(name, installed[name]['path']) self.install(name)
def register_platform(self, name): def _register(self, name, version):
data = self.get_installed() data = self.get_installed()
if name not in data: data[name] = {
data[name] = {}
self._update_db(data)
return data
def unregister_platform(self, name):
data = self.get_installed()
del data[name]
self._update_db(data)
def _register(self, name, version, path):
data = self.get_installed()
if self._platform_name not in data:
data = self.register_platform(self._platform_name)
data[self._platform_name][name] = {
"version": version, "version": version,
"path": path "time": time()
} }
self._update_db(data) self.update_appstate_instpkgs(data)
def _unregister(self, name): def _unregister(self, name):
data = self.get_installed() data = self.get_installed()
del data[self._platform_name][name] del data[name]
self._update_db(data) self.update_appstate_instpkgs(data)
def _update_db(self, data):
with open(self.DBFILE_PATH, "w") as fp:
json.dump(data, fp)

View File

@ -1,8 +1,6 @@
# Copyright (C) Ivan Kravets <me@ikravets.com> # Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details. # See LICENSE for details.
from os.path import join
from platformio.platforms.base import BasePlatform from platformio.platforms.base import BasePlatform
@ -15,19 +13,17 @@ class AtmelavrPlatform(BasePlatform):
PACKAGES = { PACKAGES = {
"toolchain-atmelavr": { "toolchain-atmelavr": {
"path": join("tools", "toolchain"),
"alias": "toolchain", "alias": "toolchain",
"default": True "default": True
}, },
"tool-avrdude": { "tool-avrdude": {
"path": join("tools", "avrdude"),
"alias": "uploader", "alias": "uploader",
"default": True "default": True
}, },
"framework-arduinoavr": { "framework-arduinoavr": {
"path": join("frameworks", "arduino"), "alias": "framework",
"default": True "default": True
} }
} }

View File

@ -1,23 +1,44 @@
# Copyright (C) Ivan Kravets <me@ikravets.com> # Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details. # See LICENSE for details.
from os.path import join from imp import load_source
from shutil import rmtree from os import listdir
from os.path import isfile, join
from platformio.exception import UnknownPackage, UnknownPlatform from platformio.exception import (BuildScriptNotFound, PlatformNotInstalledYet,
UnknownPackage, UnknownPlatform)
from platformio.pkgmanager import PackageManager from platformio.pkgmanager import PackageManager
from platformio.util import exec_command, get_platforms, get_source_dir from platformio.util import AppState, exec_command, get_source_dir
class PlatformFactory(object): class PlatformFactory(object):
@staticmethod
def get_platforms(installed=False):
platforms = {}
for p in listdir(join(get_source_dir(), "platforms")):
if p in ("__init__.py", "base.py") or not p.endswith(".py"):
continue
platforms[p[:-3]] = join(get_source_dir(), "platforms", p)
if not installed:
return platforms
installed_platforms = {}
with AppState() as state:
for name in state.get("installed_platforms", []):
if name in platforms:
installed_platforms[name] = platforms[name]
return installed_platforms
@staticmethod @staticmethod
def newPlatform(name): def newPlatform(name):
platforms = PlatformFactory.get_platforms()
clsname = "%sPlatform" % name.title() clsname = "%sPlatform" % name.title()
try: try:
assert name in get_platforms() assert name in platforms
mod = __import__("platformio.platforms." + name.lower(), mod = load_source(
None, None, [clsname]) "platformio.platforms.%s" % name, platforms[name])
except (AssertionError, ImportError): except (AssertionError, ImportError):
raise UnknownPlatform(name) raise UnknownPlatform(name)
@ -33,6 +54,13 @@ class BasePlatform(object):
def get_name(self): def get_name(self):
raise NotImplementedError() raise NotImplementedError()
def get_build_script(self):
builtin = join(get_source_dir(), "builder", "scripts", "%s.py" %
self.get_name())
if isfile(builtin):
return builtin
raise NotImplementedError()
def get_short_info(self): def get_short_info(self):
if self.__doc__: if self.__doc__:
doclines = [l.strip() for l in self.__doc__.splitlines()] doclines = [l.strip() for l in self.__doc__.splitlines()]
@ -40,6 +68,9 @@ class BasePlatform(object):
else: else:
raise NotImplementedError() raise NotImplementedError()
def get_packages(self):
return self.PACKAGES
def get_pkg_alias(self, pkgname): def get_pkg_alias(self, pkgname):
return self.PACKAGES[pkgname].get("alias", None) return self.PACKAGES[pkgname].get("alias", None)
@ -47,62 +78,113 @@ class BasePlatform(object):
names = [] names = []
for alias in aliases: for alias in aliases:
name = alias name = alias
# lookup by packages alias # lookup by package aliases
if name not in self.PACKAGES: for _name, _opts in self.get_packages().items():
for _name, _opts in self.PACKAGES.items(): if _opts.get("alias", None) == alias:
if _opts.get("alias", None) == alias: name = _name
name = _name break
break
names.append(name) names.append(name)
return names return names
def get_installed_packages(self):
pm = PackageManager()
return [n for n in self.get_packages().keys() if pm.is_installed(n)]
def install(self, with_packages, without_packages, skip_default_packages): def install(self, with_packages, without_packages, skip_default_packages):
with_packages = set(self.pkg_aliases_to_names(with_packages)) with_packages = set(self.pkg_aliases_to_names(with_packages))
without_packages = set(self.pkg_aliases_to_names(without_packages)) without_packages = set(self.pkg_aliases_to_names(without_packages))
upkgs = with_packages | without_packages upkgs = with_packages | without_packages
ppkgs = set(self.PACKAGES.keys()) ppkgs = set(self.get_packages().keys())
if not upkgs.issubset(ppkgs): if not upkgs.issubset(ppkgs):
raise UnknownPackage(", ".join(upkgs - ppkgs)) raise UnknownPackage(", ".join(upkgs - ppkgs))
requirements = [] requirements = []
for name, opts in self.PACKAGES.items(): for name, opts in self.get_packages().items():
if name in without_packages: if name in without_packages:
continue continue
elif (name in with_packages or (not skip_default_packages and elif (name in with_packages or (not skip_default_packages and
opts['default'])): opts['default'])):
requirements.append((name, opts['path'])) requirements.append(name)
pm = PackageManager()
for name in requirements:
pm.install(name)
# register installed platform
with AppState() as state:
data = state.get("installed_platforms", [])
if self.get_name() not in data:
data.append(self.get_name())
state['installed_platforms'] = data
pm = PackageManager(self.get_name())
for (package, path) in requirements:
pm.install(package, path)
return len(requirements) return len(requirements)
def uninstall(self): def uninstall(self):
platform = self.get_name() platform = self.get_name()
pm = PackageManager(platform) installed_platforms = PlatformFactory.get_platforms(
installed=True).keys()
for package, data in pm.get_installed(platform).items(): if platform not in installed_platforms:
pm.uninstall(package, data['path']) raise PlatformNotInstalledYet(platform)
deppkgs = set()
for item in installed_platforms:
if item == platform:
continue
p = PlatformFactory().newPlatform(item)
deppkgs = deppkgs.union(set(p.get_packages().keys()))
pm = PackageManager()
for name in self.get_packages().keys():
if not pm.is_installed(name):
continue
pm.uninstall(name)
# unregister installed platform
with AppState() as state:
installed_platforms.remove(platform)
state['installed_platforms'] = installed_platforms
pm.unregister_platform(platform)
rmtree(pm.get_platform_dir())
return True return True
def update(self): def update(self):
platform = self.get_name() pm = PackageManager()
pm = PackageManager(platform) for name in self.get_installed_packages():
for package in pm.get_installed(platform).keys(): pm.update(name)
pm.update(package)
def run(self, variables, targets): def run(self, variables, targets):
assert isinstance(variables, list) assert isinstance(variables, list)
assert isinstance(targets, list) assert isinstance(targets, list)
installed_platforms = PlatformFactory.get_platforms(
installed=True).keys()
installed_packages = PackageManager.get_installed()
if self.get_name() not in installed_platforms:
raise PlatformNotInstalledYet(self.get_name())
if "clean" in targets: if "clean" in targets:
targets.remove("clean") targets.remove("clean")
targets.append("-c") targets.append("-c")
if not any([v.startswith("BUILD_SCRIPT=") for v in variables]):
variables.append("BUILD_SCRIPT=%s" % self.get_build_script())
for v in variables:
if not v.startswith("BUILD_SCRIPT="):
continue
_, path = v.split("=", 2)
if not isfile(path):
raise BuildScriptNotFound(path)
# append aliases of installed packages
for name, options in self.get_packages().items():
if name not in installed_packages:
continue
variables.append(
"PIOPACKAGE_%s=%s" % (options['alias'].upper(), name))
result = exec_command([ result = exec_command([
"scons", "scons",
"-Q", "-Q",

View File

@ -1,8 +1,6 @@
# Copyright (C) Ivan Kravets <me@ikravets.com> # Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details. # See LICENSE for details.
from os.path import join
from platformio.platforms.base import BasePlatform from platformio.platforms.base import BasePlatform
@ -15,19 +13,17 @@ class Timsp430Platform(BasePlatform):
PACKAGES = { PACKAGES = {
"toolchain-timsp430": { "toolchain-timsp430": {
"path": join("tools", "toolchain"),
"alias": "toolchain", "alias": "toolchain",
"default": True "default": True
}, },
"tool-mspdebug": { "tool-mspdebug": {
"path": join("tools", "mspdebug"),
"alias": "uploader", "alias": "uploader",
"default": True "default": True
}, },
"framework-energiamsp430": { "framework-energiamsp430": {
"path": join("frameworks", "energia"), "alias": "framework",
"default": True "default": True
} }
} }

View File

@ -1,8 +1,6 @@
# Copyright (C) Ivan Kravets <me@ikravets.com> # Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details. # See LICENSE for details.
from os.path import join
from platformio.platforms.base import BasePlatform from platformio.platforms.base import BasePlatform
@ -15,19 +13,17 @@ class TitivaPlatform(BasePlatform):
PACKAGES = { PACKAGES = {
"toolchain-gccarmnoneeabi": { "toolchain-gccarmnoneeabi": {
"path": join("tools", "toolchain"),
"alias": "toolchain", "alias": "toolchain",
"default": True "default": True
}, },
"tool-lm4flash": { "tool-lm4flash": {
"path": join("tools", "lm4flash"),
"alias": "uploader", "alias": "uploader",
"default": True "default": True
}, },
"framework-energiativa": { "framework-energiativa": {
"path": join("frameworks", "energia"), "alias": "framework",
"default": True "default": True
} }
} }

View File

@ -1,16 +1,15 @@
# Copyright (C) Ivan Kravets <me@ikravets.com> # Copyright (C) Ivan Kravets <me@ikravets.com>
# See LICENSE for details. # See LICENSE for details.
import json
from os import name as os_name from os import name as os_name
from os import getcwd, getenv, listdir, utime from os import getcwd, getenv, makedirs, utime
from os.path import dirname, expanduser, isfile, join, realpath from os.path import dirname, expanduser, isdir, isfile, join, realpath
from platform import system, uname from platform import system, uname
from subprocess import PIPE, Popen from subprocess import PIPE, Popen
from time import sleep from time import sleep
from requests import get, post import requests
from requests.exceptions import ConnectionError, HTTPError
from requests.utils import default_user_agent
from serial import Serial from serial import Serial
from platformio import __apiurl__, __version__ from platformio import __apiurl__, __version__
@ -23,6 +22,28 @@ except ImportError:
from ConfigParser import ConfigParser from ConfigParser import ConfigParser
class AppState(object):
def __init__(self, path=None):
self.path = path
if not self.path:
self.path = join(get_home_dir(), "appstate.json")
self._state = {}
def __enter__(self):
try:
if isfile(self.path):
with open(self.path, "r") as fp:
self._state = json.load(fp)
except ValueError:
self._state = {}
return self._state
def __exit__(self, type_, value, traceback):
with open(self.path, "w") as fp:
json.dump(self._state, fp)
def get_systype(): def get_systype():
if system() == "Windows": if system() == "Windows":
return "windows" return "windows"
@ -31,14 +52,24 @@ def get_systype():
def get_home_dir(): def get_home_dir():
home_dir = None
try: try:
config = get_project_config() config = get_project_config()
if (config.has_section("platformio") and if (config.has_section("platformio") and
config.has_option("platformio", "home_dir")): config.has_option("platformio", "home_dir")):
return config.get("platformio", "home_dir") home_dir = config.get("platformio", "home_dir")
except NotPlatformProject: except NotPlatformProject:
pass pass
return expanduser("~/.platformio")
if not home_dir:
home_dir = expanduser("~/.platformio")
if not isdir(home_dir):
makedirs(home_dir)
assert isdir(home_dir)
return home_dir
def get_lib_dir(): def get_lib_dir():
@ -77,15 +108,6 @@ def get_project_config():
return cp return cp
def get_platforms():
platforms = []
for p in listdir(join(get_source_dir(), "platforms")):
if p in ("__init__.py", "base.py") or not p.endswith(".py"):
continue
platforms.append(p[:-3])
return platforms
def change_filemtime(path, time): def change_filemtime(path, time):
utime(path, (time, time)) utime(path, (time, time))
@ -123,20 +145,20 @@ def get_api_result(path, params=None, data=None):
r = None r = None
try: try:
headers = {"User-Agent": "PlatformIO/%s %s" % ( headers = {"User-Agent": "PlatformIO/%s %s" % (
__version__, default_user_agent())} __version__, requests.utils.default_user_agent())}
if data: if data:
r = post(__apiurl__ + path, params=params, data=data, r = requests.post(__apiurl__ + path, params=params, data=data,
headers=headers) headers=headers)
else: else:
r = get(__apiurl__ + path, params=params, headers=headers) r = requests.get(__apiurl__ + path, params=params, headers=headers)
result = r.json() result = r.json()
r.raise_for_status() r.raise_for_status()
except HTTPError as e: except requests.exceptions.HTTPError as e:
if result and "errors" in result: if result and "errors" in result:
raise APIRequestError(result['errors'][0]['title']) raise APIRequestError(result['errors'][0]['title'])
else: else:
raise APIRequestError(e) raise APIRequestError(e)
except ConnectionError: except requests.exceptions.ConnectionError:
raise APIRequestError( raise APIRequestError(
"Could not connect to PlatformIO Registry Service") "Could not connect to PlatformIO Registry Service")
except ValueError: except ValueError: