Install development platform from local dir and VCS(git, hg, svn) // Issue #479

This commit is contained in:
Ivan Kravets
2016-05-31 00:22:25 +03:00
parent bfd66deb37
commit d6b6fa2baf
9 changed files with 374 additions and 158 deletions

View File

@ -196,6 +196,31 @@ General options
:ref:`platforms` name. :ref:`platforms` name.
PlatformIO allows to use specific platform versions using
`Semantic Versioning <http://semver.org>`_ (X.Y.Z=MAJOR.MINOR.PATCH).
Version specifications can take any of the following forms:
* ``0.1.2``: an exact version number. Use only this exact version
* ``^0.1.2``: any compatible version (exact version for ``0.x.x`` versions
* ``~0.1.2``: any version with the same major and minor versions, and an
equal or greater patch version
* ``>0.1.2``: any version greater than ``0.1.2``. ``>=``, ``<``, and ``<=``
are also possible
* ``>0.1.0,!=0.2.0,<0.3.0``: any version greater than ``0.1.0``, not equal to
``0.2.0`` and less than ``0.3.0``
Examples:
.. code-block:: ini
[env:the_latest_version]
platform = atmelavr
[env:specific_major_version]
platform = atmelavr@^0.1.2
[env:specific_major_and_minor_version]
platform = atmelavr@~0.1.2
.. _projectconf_env_framework: .. _projectconf_env_framework:

View File

@ -22,22 +22,90 @@ Usage
.. code-block:: bash .. code-block:: bash
# install platform by name # install platform by name
platformio platform install [OPTIONS] [PLATFORMS] platformio platform install [OPTIONS] PLATFORM
# install platform from local directory # install specific platform version using Semantic Versioning
platformio platform install [OPTIONS] [file:///local/path/to/platform/dir] platformio platform install [OPTIONS] PLATFORM@X.Y.Z
# install platform using URL
platformio platform install [OPTIONS] URL
Description Description
----------- -----------
Install development :ref:`platforms` and dependent packages. Install :ref:`platforms` and dependent packages.
There are several predefined aliases for packages, such as: There are several predefined aliases for packages, such as:
* ``framework``
* ``toolchain`` * ``toolchain``
* ``uploader`` * ``uploader``
Local
~~~~~
PlatformIO supports installing development platform from local directory. Here
is supported form:
* file:///local/path/to/the/platform/dir
VCS
~~~
PlatformIO supports installing from Git, Mercurial and Subversion, and detects
the type of VCS using url prefixes: "git+", "hg+", or "svn+".
PlatformIO requires a working VCS command on your path: git, hg or svn.
Git
^^^
The supported schemes are: ``git``, ``git+https`` and ``git+ssh``. Here are
the supported forms:
* https://github.com/platformio/platform-NAME.git
* git+git://git.server.org/my-platform
* git+https://git.server.org/my-platform
* git+ssh://git.server.org/my-platform
Passing branch names, a commit hash or a tag name is possible like so:
* https://github.com/platformio/platform-name.git#master
* git+git://git.server.org/my-platform#master
* git+https://git.server.org/my-platform#v1.0
* git+ssh://git.server.org/my-platform#7846d8ad52f983f2f2887bdc0f073fe9755a806d
Mercurial
^^^^^^^^^
The supported schemes are: ``hg+http``, ``hg+https`` and ``hg+ssh``. Here are
the supported forms:
* hg+hg://hg.server.org/my-platform
* hg+https://hg.server.org/my-platform
* hg+ssh://hg.server.org/my-platform
Passing branch names, a commit hash or a tag name is possible like so:
* hg+hg://hg.server.org/my-platform#master
* hg+https://hg.server.org/my-platform#v1.0
* hg+ssh://hg.server.org/my-platform#4cfe2fa00668
Subversion
^^^^^^^^^^
The supported schemes are: ``svn``, ``svn+svn``, ``svn+http``, ``svn+https``
and ``svn+ssh``. Here are the supported forms:
* svn+svn://svn.server.org/my-platform
* svn+https://svn.server.org/my-platform
* svn+ssh://svn.server.org/my-platform
You can also give specific revisions to an SVN URL, like so:
* svn+svn://svn.server.org/my-platform#13
Options Options
------- -------
@ -62,30 +130,68 @@ Skip default packages
Examples Examples
-------- --------
1. Install :ref:`platform_timsp430` with default packages 1. Install :ref:`platform_atmelavr` with default packages
.. code-block:: bash .. code-block:: bash
$ platformio platform install timsp430 $ platformio platform install atmelavr
Installing toolchain-timsp430 package: Installing platform atmelavr @ latest:
Downloading...
Unpacking [####################################] 100%
Installing package tool-scons @ >=2.3.0,<2.6.0:
Downloading [####################################] 100% Downloading [####################################] 100%
Unpacking [####################################] 100% Unpacking [####################################] 100%
Installing tool-mspdebug package: Installing package toolchain-atmelavr @ ~1.40801.0:
Downloading [####################################] 100% Downloading [####################################] 100%
Unpacking [####################################] 100% Unpacking [####################################] 100%
Installing framework-energiamsp430 package: The platform 'atmelavr' has been successfully installed!
Downloading [####################################] 100% The rest of packages will be installed automatically depending on your build environment.
Unpacking [####################################] 100%
The platform 'timsp430' has been successfully installed!
2. Install :ref:`platform_timsp430` with ``uploader`` utility only and skip 2. Install :ref:`platform_atmelavr` with ``uploader`` utility only and skip
default packages default packages
.. code-block:: bash .. code-block:: bash
$ platformio platform install timsp430 --skip-default-package --with-package=uploader $ platformio platform install atmelavr --skip-default-package --with-package=uploader
Installing tool-mspdebug package: Installing platform atmelavr @ latest:
Downloading [####################################] 100% Downloading [####################################] 100%
Unpacking [####################################] 100% Unpacking [####################################] 100%
The platform 'timsp430' has been successfully installed! Installing package tool-micronucleus @ ~1.200.0:
Downloading [####################################] 100%
Unpacking [####################################] 100%
Installing package tool-avrdude @ >=1.60001.0,<1.60101.0:
Downloading [####################################] 100%
Unpacking [####################################] 100%
The platform 'atmelavr' has been successfully installed!
The rest of packages will be installed automatically depending on your build environment.
3. Install the latest development :ref:`platform_atmelavr` from Git repository
.. code-block:: bash
$ platformio platform install https://github.com/platformio/platform-atmelavr.git
Installing platform https://github.com/platformio/platform-atmelavr.git @ latest:
git version 2.7.4 (Apple Git-66)
Cloning into '/Users/ikravets/.platformio/platforms/installing-XMIsAE-package'...
remote: Counting objects: 172, done.
remote: Compressing objects: 100% (51/51), done.
remote: Total 172 (delta 109), reused 168 (delta 109), pack-reused 0
Receiving objects: 100% (172/172), 38.18 KiB | 0 bytes/s, done.
Resolving deltas: 100% (109/109), done.
Checking connectivity... done.
Submodule 'examples/arduino-external-libs/lib/OneWire' (https://github.com/PaulStoffregen/OneWire.git) registered for path 'examples/arduino-external-libs/lib/OneWire'
Cloning into 'examples/arduino-external-libs/lib/OneWire'...
remote: Counting objects: 87, done.
remote: Total 87 (delta 0), reused 0 (delta 0), pack-reused 87
Unpacking objects: 100% (87/87), done.
Checking connectivity... done.
Submodule path 'examples/arduino-external-libs/lib/OneWire': checked out '57c18c6de80c13429275f70875c7c341f1719201'
Installing package tool-scons @ >=2.3.0,<2.6.0:
Downloading [####################################] 100%
Unpacking [####################################] 100%
Installing package toolchain-atmelavr @ ~1.40801.0:
Downloading [####################################] 100%
Unpacking [####################################] 100%
The platform 'https://github.com/platformio/platform-atmelavr.git' has been successfully installed!
The rest of packages will be installed automatically depending on your build environment.

View File

@ -23,6 +23,9 @@ Usage
platformio platform uninstall PLATFORM platformio platform uninstall PLATFORM
# uninstall specific platform version using Semantic Versioning
platformio platform uninstall PLATFORM@X.Y.Z
Description Description
----------- -----------
@ -35,8 +38,8 @@ Examples
.. code-block:: bash .. code-block:: bash
$ platformio platform uninstall timsp430 $ platformio platform uninstall atmelavr
Uninstalling toolchain-timsp430 package: [OK] Uninstalling platform atmelavr @ latest: [OK]
Uninstalling tool-mspdebug package: [OK] Uninstalling package tool-scons @ 2.5.0: [OK]
Uninstalling framework-energiamsp430 package: [OK] Uninstalling package toolchain-atmelavr @ 1.40801.0: [OK]
The platform 'timsp430' has been successfully uninstalled! The platform 'atmelavr' has been successfully uninstalled!

View File

@ -46,75 +46,53 @@ Examples
.. code-block:: bash .. code-block:: bash
$ platformio platform update $ platformio platform update
Platform atmelavr @ 0.0.0
Platform atmelavr
-------- --------
Updating toolchain-atmelavr package: Updating platform atmelavr @ latest:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=0.0.0, Latest=0.0.0 [Up-to-date]
Updating tool-avrdude package: Updating package framework-arduinoavr @ ~1.10608.0:
Versions: Current=2, Latest=2 [Up-to-date] Versions: Current=1.10608.0, Latest=1.10608.0 [Up-to-date]
Updating framework-arduinoavr package: Updating package toolchain-atmelavr @ ~1.40801.0:
Versions: Current=12, Latest=12 [Up-to-date] Versions: Current=1.40801.0, Latest=1.40801.0 [Up-to-date]
Updating tool-micronucleus package: Updating package framework-simba @ ~1.500.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=1.500.0, Latest=1.500.0 [Up-to-date]
Updating package tool-scons @ >=2.3.0,<2.6.0:
Versions: Current=2.5.0, Latest=2.5.0 [Up-to-date]
Platform atmelsam Platform atmelsam @ 0.0.0
-------- --------
Updating framework-arduinosam package: Updating platform atmelsam @ latest:
Versions: Current=3, Latest=3 [Up-to-date] Versions: Current=0.0.0, Latest=0.0.0 [Up-to-date]
Updating ldscripts package: Updating package toolchain-gccarmnoneeabi @ >=1.40803.0,<1.40805.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=1.40804.0, Latest=1.40804.0 [Up-to-date]
Updating toolchain-gccarmnoneeabi package: Updating package framework-arduinosam @ ~1.10607.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=1.10607.0, Latest=1.10607.0 [Up-to-date]
Updating tool-bossac package: Updating package framework-simba @ ~1.500.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=1.500.0, Latest=1.500.0 [Up-to-date]
Updating package framework-mbed @ ~1.117.0:
Versions: Current=1.117.0, Latest=1.117.0 [Up-to-date]
Updating package tool-scons @ >=2.3.0,<2.6.0:
Versions: Current=2.5.0, Latest=2.5.0 [Up-to-date]
Updating package tool-bossac @ ~1.10500.0:
Versions: Current=1.10500.0, Latest=1.10500.0 [Up-to-date]
Platform stm32 Platform espressif @ 0.0.0
-------- --------
Updating toolchain-gccarmnoneeabi package: Updating platform espressif @ latest:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=0.0.0, Latest=0.0.0 [Up-to-date]
Updating tool-stlink package: Updating package tool-scons @ >=2.3.0,<2.6.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=2.5.0, Latest=2.5.0 [Up-to-date]
Updating framework-spl package: Updating package toolchain-xtensa @ ~1.40802.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=1.40802.0, Latest=1.40802.0 [Up-to-date]
Updating framework-cmsis package: Updating package framework-simba @ ~1.500.0:
Versions: Current=2, Latest=2 [Up-to-date] Versions: Current=1.500.0, Latest=1.500.0 [Up-to-date]
Updating framework-opencm3 package: Updating package tool-esptool @ ~1.408.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=1.408.0, Latest=1.408.0 [Up-to-date]
Updating ldscripts package: Updating package tool-mkspiffs @ ~1.102.0:
Versions: Current=1, Latest=1 [Up-to-date] Versions: Current=1.102.0, Latest=1.102.0 [Up-to-date]
Updating package framework-arduinoespressif @ ~1.20200.0:
Versions: Current=1.20200.0, Latest=1.20200.0 [Up-to-date]
Updating package sdk-esp8266 @ ~1.10502.0:
Versions: Current=1.10502.0, Latest=1.10502.0 [Up-to-date]
Platform teensy ...
--------
Updating toolchain-atmelavr package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating ldscripts package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating framework-arduinoteensy package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating toolchain-gccarmnoneeabi package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating tool-teensy package:
Versions: Current=1, Latest=1 [Up-to-date]
Platform timsp430
--------
Updating toolchain-timsp430 package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating tool-mspdebug package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating framework-energiamsp430 package:
Versions: Current=2, Latest=2 [Up-to-date]
Platform titiva
--------
Updating ldscripts package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating toolchain-gccarmnoneeabi package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating tool-lm4flash package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating framework-opencm3 package:
Versions: Current=1, Latest=1 [Up-to-date]
Updating framework-energiativa package:
Versions: Current=4, Latest=4 [Up-to-date]

View File

@ -205,7 +205,8 @@ class EnvironmentProcessor(object):
try: try:
p = PlatformFactory.newPlatform(platform, version) p = PlatformFactory.newPlatform(platform, version)
except exception.UnknownPlatform: except exception.UnknownPlatform:
self.cmd_ctx.invoke(cmd_platform_install, platforms=[platform]) self.cmd_ctx.invoke(
cmd_platform_install, platforms=[self.options['platform']])
p = PlatformFactory.newPlatform(platform, version) p = PlatformFactory.newPlatform(platform, version)
return p.run(build_vars, build_targets, self.verbose_level) return p.run(build_vars, build_targets, self.verbose_level)

View File

@ -70,11 +70,6 @@ class UnknownPackage(PlatformioException):
MESSAGE = "Detected unknown package '{0}'" MESSAGE = "Detected unknown package '{0}'"
class InvalidLocalPackage(PlatformioException):
MESSAGE = "Invalid local package '{0}'. Can not find manifest '{1}'"
class UndefinedPackageVersion(PlatformioException): class UndefinedPackageVersion(PlatformioException):
MESSAGE = "Can not find package '{0}' with version requirements '{1}'"\ MESSAGE = "Can not find package '{0}' with version requirements '{1}'"\

View File

@ -15,6 +15,7 @@
import os import os
from os.path import dirname, isdir, isfile, islink, join from os.path import dirname, isdir, isfile, islink, join
from shutil import copyfile, copytree, rmtree from shutil import copyfile, copytree, rmtree
from tempfile import mkdtemp
import click import click
import requests import requests
@ -23,6 +24,7 @@ import semantic_version
from platformio import exception, telemetry, util from platformio import exception, telemetry, util
from platformio.downloader import FileDownloader from platformio.downloader import FileDownloader
from platformio.unpacker import FileUnpacker from platformio.unpacker import FileUnpacker
from platformio.vcsclient import VCSClientFactory
class PackageManager(object): class PackageManager(object):
@ -87,32 +89,6 @@ class PackageManager(object):
"Could not find '%s' manifest file in the package" % "Could not find '%s' manifest file in the package" %
self.manifest_name) self.manifest_name)
def make_pkg_dir(self, name, version):
pkg_dir = join(self.package_dir, name)
if isfile(join(pkg_dir, self.manifest_name)):
manifest = util.load_json(
join(pkg_dir, self.manifest_name))
cmp_result = semantic_version.compare(version, manifest['version'])
if cmp_result == 1:
# if main package version < new package, backup it
print pkg_dir, join(
self.package_dir, "%s@%s" % (name, manifest['version']))
os.rename(pkg_dir, join(
self.package_dir, "%s@%s" % (name, manifest['version'])))
elif cmp_result == -1:
pkg_dir = join(
self.package_dir, "%s@%s" % (name, version))
# remove previous/not-satisfied package
if isdir(pkg_dir):
rmtree(pkg_dir)
os.makedirs(pkg_dir)
assert isdir(pkg_dir)
self.reset_cache()
return pkg_dir
@staticmethod @staticmethod
def max_satisfying_repo_version(versions, requirements=None): def max_satisfying_repo_version(versions, requirements=None):
item = None item = None
@ -196,12 +172,11 @@ class PackageManager(object):
return self.max_satisfying_version( return self.max_satisfying_version(
name, requirements).get("_manifest_path") name, requirements).get("_manifest_path")
manifest_path = None if "://" in name:
if name.startswith("file://"): pkg_dir = self._install_from_url(name, requirements)
manifest_path = self._install_from_local_dir(name[7:])
else: else:
manifest_path = self._install_from_piorepo(name, requirements) pkg_dir = self._install_from_piorepo(name, requirements)
if not isfile(manifest_path): if not pkg_dir or not isfile(join(pkg_dir, self.manifest_name)):
raise exception.PackageInstallError( raise exception.PackageInstallError(
name, requirements or "latest", util.get_systype()) name, requirements or "latest", util.get_systype())
@ -210,32 +185,23 @@ class PackageManager(object):
telemetry.on_event( telemetry.on_event(
category="PackageManager", action="Install", label=name) category="PackageManager", action="Install", label=name)
return manifest_path return join(pkg_dir, self.manifest_name)
def _install_from_piorepo(self, name, requirements): def _install_from_piorepo(self, name, requirements):
pkg_dir = None pkg_dir = None
pkgdata = None pkgdata = None
versions = None versions = None
for versions in PackageRepoIterator(name, self.repositories): for versions in PackageRepoIterator(name, self.repositories):
dlpath = None
pkgdata = self.max_satisfying_repo_version(versions, requirements) pkgdata = self.max_satisfying_repo_version(versions, requirements)
if not pkgdata: if not pkgdata:
continue continue
pkg_dir = self.make_pkg_dir(name, pkgdata['version'])
try: try:
dlpath = self.download( pkg_dir = self._install_from_url(
pkgdata['url'], pkg_dir, pkgdata.get("sha1")) pkgdata['url'], requirements, pkgdata.get("sha1"))
assert isfile(dlpath)
self.unpack(dlpath, pkg_dir)
self.check_structure(pkg_dir)
break break
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
click.secho("Warning! Package Mirror: %s" % e, fg="yellow") click.secho("Warning! Package Mirror: %s" % e, fg="yellow")
click.secho("Looking for another mirror...", fg="yellow") click.secho("Looking for another mirror...", fg="yellow")
finally:
if dlpath and isfile(dlpath):
os.remove(dlpath)
if versions is None: if versions is None:
raise exception.UnknownPackage(name) raise exception.UnknownPackage(name)
@ -246,21 +212,64 @@ class PackageManager(object):
else: else:
raise exception.UndefinedPackageVersion( raise exception.UndefinedPackageVersion(
name, requirements or "latest", util.get_systype()) name, requirements or "latest", util.get_systype())
return pkg_dir
return join(pkg_dir, self.manifest_name) def _install_from_url(self, url, requirements=None, sha1=None):
pkg_dir = None
tmp_dir = mkdtemp("-package", "installing-", self.package_dir)
def _install_from_local_dir(self, local_dir): # Handle GitHub URL (https://github.com/user/repo.git)
if not isfile(join(local_dir, self.manifest_name)): if url.endswith(".git") and not url.startswith("git"):
raise exception.InvalidLocalPackage( url = "git+" + url
local_dir, self.manifest_name)
manifest = util.load_json(join(local_dir, self.manifest_name)) try:
assert set(["name", "version"]) <= set(manifest.keys()) if url.startswith("file://"):
pkg_dir = self.make_pkg_dir(manifest['name'], manifest['version']) rmtree(tmp_dir)
rmtree(pkg_dir) copytree(url[7:], tmp_dir)
copytree(local_dir, pkg_dir, symlinks=True) elif url.startswith(("http://", "https://", "ftp://")):
dlpath = self.download(url, tmp_dir, sha1)
assert isfile(dlpath)
self.unpack(dlpath, tmp_dir)
os.remove(dlpath)
else:
repo = VCSClientFactory.newClient(url)
repo.export(tmp_dir)
return join(pkg_dir, self.manifest_name) self.check_structure(tmp_dir)
pkg_dir = self._install_from_tmp_dir(tmp_dir, requirements)
finally:
if isdir(tmp_dir):
rmtree(tmp_dir)
return pkg_dir
def _install_from_tmp_dir(self, tmp_dir, requirements=None):
tmpmanifest = util.load_json(join(tmp_dir, self.manifest_name))
assert set(["name", "version"]) <= set(tmpmanifest.keys())
name = tmpmanifest['name']
# package should satisfy requirements
if requirements:
assert semantic_version.match(requirements, tmpmanifest['version'])
pkg_dir = join(self.package_dir, name)
if isfile(join(pkg_dir, self.manifest_name)):
manifest = util.load_json(join(pkg_dir, self.manifest_name))
cmp_result = semantic_version.compare(
tmpmanifest['version'], manifest['version'])
if cmp_result == 1:
# if main package version < new package, backup it
os.rename(pkg_dir, join(
self.package_dir, "%s@%s" % (name, manifest['version'])))
elif cmp_result == -1:
pkg_dir = join(
self.package_dir, "%s@%s" % (name, tmpmanifest['version']))
# remove previous/not-satisfied package
if isdir(pkg_dir):
rmtree(pkg_dir)
os.rename(tmp_dir, pkg_dir)
assert isdir(pkg_dir)
return pkg_dir
def uninstall(self, name, requirements=None, trigger_event=True): def uninstall(self, name, requirements=None, trigger_event=True):
click.echo("Uninstalling %s %s @ %s: \t" % ( click.echo("Uninstalling %s %s @ %s: \t" % (

View File

@ -44,25 +44,26 @@ class PlatformManager(PackageManager):
name, requirements=None, with_packages=None, name, requirements=None, with_packages=None,
without_packages=None, skip_default_packages=False): without_packages=None, skip_default_packages=False):
manifest_path = PackageManager.install(self, name, requirements) manifest_path = PackageManager.install(self, name, requirements)
PlatformFactory.newPlatform( p = PlatformFactory.newPlatform(manifest_path, requirements)
manifest_path, requirements).install_packages( p.install_packages(
with_packages, without_packages, skip_default_packages) with_packages, without_packages, skip_default_packages)
self.cleanup_packages() self.cleanup_packages(p.packages.keys())
return True return True
def uninstall(self, # pylint: disable=arguments-differ def uninstall(self, # pylint: disable=arguments-differ
name, requirements=None): name, requirements=None):
p = PlatformFactory.newPlatform(name, requirements)
PackageManager.uninstall(self, name, requirements) PackageManager.uninstall(self, name, requirements)
self.cleanup_packages() self.cleanup_packages(p.packages.keys())
return True return True
def update(self, # pylint: disable=arguments-differ def update(self, # pylint: disable=arguments-differ
name, requirements=None, only_packages=False): name, requirements=None, only_packages=False):
if not only_packages: if not only_packages:
PackageManager.update(self, name) PackageManager.update(self, name)
PlatformFactory.newPlatform( p = PlatformFactory.newPlatform(name, requirements)
name, requirements).update_packages() p.update_packages()
self.cleanup_packages() self.cleanup_packages(p.packages.keys())
return True return True
def is_outdated(self, name, requirements=None): def is_outdated(self, name, requirements=None):
@ -70,7 +71,7 @@ class PlatformManager(PackageManager):
return (p.are_outdated_packages() or return (p.are_outdated_packages() or
p.version != self.get_latest_repo_version(name, requirements)) p.version != self.get_latest_repo_version(name, requirements))
def cleanup_packages(self): def cleanup_packages(self, names):
self.reset_cache() self.reset_cache()
deppkgs = {} deppkgs = {}
for manifest in PlatformManager().get_installed(): for manifest in PlatformManager().get_installed():
@ -83,9 +84,10 @@ class PlatformManager(PackageManager):
pm = PackageManager() pm = PackageManager()
for manifest in pm.get_installed(): for manifest in pm.get_installed():
if manifest['name'] not in deppkgs: if manifest['name'] not in names:
continue continue
if manifest['version'] not in deppkgs[manifest['name']]: if (manifest['name'] not in deppkgs or
manifest['version'] not in deppkgs[manifest['name']]):
pm.uninstall( pm.uninstall(
manifest['name'], manifest['version'], trigger_event=False) manifest['name'], manifest['version'], trigger_event=False)

97
platformio/vcsclient.py Normal file
View File

@ -0,0 +1,97 @@
# Copyright 2014-present 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 platform import system
from subprocess import check_call
from sys import modules
from urlparse import urlsplit, urlunsplit
from platformio.exception import PlatformioException
class VCSClientFactory(object):
@staticmethod
def newClient(url):
scheme, netloc, path, query, fragment = urlsplit(url)
type_ = scheme
if "+" in type_:
type_, scheme = type_.split("+", 1)
url = urlunsplit((scheme, netloc, path, query, None))
clsname = "%sClient" % type_.title()
obj = getattr(modules[__name__], clsname)(url, fragment)
assert isinstance(obj, VCSClientBase)
return obj
class VCSClientBase(object):
command = None
def __init__(self, url, branch=None):
self.url = url
self.branch = branch
self.check_client()
def check_client(self):
try:
assert self.command
assert self.run_cmd(["--version"]) == 0
except (AssertionError, OSError):
raise PlatformioException(
"VCS: `%s` client is not installed in your system" %
self.command)
return True
def export(self, dst_dir):
raise NotImplementedError
def run_cmd(self, args):
return check_call([self.command] + args, shell=system() == "Windows")
class GitClient(VCSClientBase):
command = "git"
def export(self, dst_dir):
args = ["clone", "--recursive", "--depth", "1"]
if self.branch:
args.extend(["--branch", self.branch])
args.extend([self.url, dst_dir])
self.run_cmd(args)
class HgClient(VCSClientBase):
command = "hg"
def export(self, dst_dir):
args = ["clone"]
if self.branch:
args.extend(["--updaterev", self.branch])
args.extend([self.url, dst_dir])
self.run_cmd(args)
class SvnClient(VCSClientBase):
command = "svn"
def export(self, dst_dir):
args = ["export", "--force"]
if self.branch:
args.extend(["--revision", self.branch])
args.extend([self.url, dst_dir])
self.run_cmd(args)