diff --git a/HISTORY.rst b/HISTORY.rst index 763eb9d3..a85dcbac 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -7,41 +7,65 @@ PlatformIO 3.0 3.0.0 (2016-??-??) ~~~~~~~~~~~~~~~~~~ -* Decentralized architecture for development platforms: "platform.json", - semantic versioning, package dependencies, embedded board configs, isolated - build scripts - (`issue #479 `_) -* Unit Testing for Embedded (`docs `__) +* Decentralized Development Platforms + + + Development platform manifest "platform.json" and + `open source development platforms `__ + + `Semantic Versioning `__ for platform commands, + development platforms and dependent packages + + Custom package repositories + + External embedded board configuration files, isolated build scripts + (`issue #479 `_) + + Embedded Board compatibility with more than one development platform + (`issue #456 `_) + +* `Unit Testing `__ for Embedded (`issue #408 `_) + +* Library Manager 3.0 + + + `Semantic Versioning `__ for library commands and + dependencies + (`issue #410 `_) + + Multiple library storages: project's local, PlatformIO global or custom + (`issue #475 `_) + + Install library by name + (`issue #414 `_) + + Depend on a library using VCS URL (GitHub, Git, ARM mbed code registry, Hg, SVN) + (`issue #498 `_) + + Strict search for library dependencies + (`issue #588 `_) + + Allowed ``library.json`` to specify sources other than PlatformIO's Repository + (`issue #461 `_) + * New Intelligent Library Build System - + `Library Dependency Finder `__ - that interprets C Preprocessor conditional macros with deep search behavior - + Check library compatibility with project environment before building - (`issue #415 `_) - + Control Library Dependency Finder for compatibility using - `lib_compat_mode `__ - option - + Custom library storages/directories with - `lib_extra_dirs `__ option - (`issue #537 `_) - + Handle extra build flags, source filters and build script from - `library.json `__ - (`issue #289 `_) - + Allowed to disable library archiving (``*.ar``) - (`issue #719 `_) - + Show detailed build information about dependent libraries - (`issue #617 `_) - + Support for the 3rd party manifests (Arduino IDE "library.properties" - and ARM mbed "module.json") + + `Library Dependency Finder `__ + that interprets C Preprocessor conditional macros with deep search behavior + + Check library compatibility with project environment before building + (`issue #415 `_) + + Control Library Dependency Finder for compatibility using + `lib_compat_mode `__ + option + + Custom library storages/directories with + `lib_extra_dirs `__ option + (`issue #537 `_) + + Handle extra build flags, source filters and build script from + `library.json `__ + (`issue #289 `_) + + Allowed to disable library archiving (``*.ar``) + (`issue #719 `_) + + Show detailed build information about dependent libraries + (`issue #617 `_) + + Support for the 3rd party manifests (Arduino IDE "library.properties" + and ARM mbed "module.json") * Print human-readable information when processing environments without ``-v, --verbose`` option (`issue #721 `_) * Added ``license`` field to `library.json `__ (`issue #522 `_) -* Embedded Board compatibility with more than one development platform - (`issue #456 `_) + PlatformIO 2.0 -------------- diff --git a/docs/librarymanager/ldf.rst b/docs/librarymanager/ldf.rst index c1a8d79b..e833687b 100644 --- a/docs/librarymanager/ldf.rst +++ b/docs/librarymanager/ldf.rst @@ -50,7 +50,7 @@ libraries. These folders/path have priority and LDF operates in the next order: 2. :ref:`projectconf_pio_lib_dir` - own/private library storage per project 3. :ref:`projectconf_pio_piolibdeps_dir` - project dependencies storage used by :ref:`librarymanager` -4. :ref:`projectconf_pio_home_dir`/lib - global storage per all projects. +4. ":ref:`projectconf_pio_home_dir`/lib" - global storage per all projects. .. _ldf_mode: diff --git a/docs/projectconf.rst b/docs/projectconf.rst index 748d0478..d4866ec3 100644 --- a/docs/projectconf.rst +++ b/docs/projectconf.rst @@ -253,7 +253,7 @@ General options :ref:`platforms` name. -PlatformIO allows to use specific platform versions using +PlatformIO allows to use specific version of platform using `Semantic Versioning `_ (X.Y.Z=MAJOR.MINOR.PATCH). Version specifications can take any of the following forms: diff --git a/docs/userguide/lib/cmd_install.rst b/docs/userguide/lib/cmd_install.rst index 7b6e2986..ddfef32b 100644 --- a/docs/userguide/lib/cmd_install.rst +++ b/docs/userguide/lib/cmd_install.rst @@ -1,4 +1,4 @@ -.. Copyright 2014-2016 Ivan Kravets +.. Copyright 2014-present Ivan Kravets 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 @@ -21,22 +21,67 @@ Usage .. code-block:: bash - platformio lib install [OPTIONS] [LIBRARY_ID] + platformio lib [STORAGE_OPTIONS] install [OPTIONS] [LIBRARY...] + # install project dependent library + # (run it from a project root where is located "platformio.ini") + platformio lib install [OPTIONS] [LIBRARY...] + + # install to global storage + platformio lib --global install [OPTIONS] [LIBRARY...] + platformio lib -g install [OPTIONS] [LIBRARY...] + + # install to custom storage + platformio lib --storage-dir /path/to/dir install [OPTIONS] [LIBRARY...] + platformio lib -d /path/to/dir install [OPTIONS] [LIBRARY...] + + # [LIBRARY...] forms + platformio lib [STORAGE_OPTIONS] install (with no args, project dependencies) + platformio lib [STORAGE_OPTIONS] install + platformio lib [STORAGE_OPTIONS] install @ + platformio lib [STORAGE_OPTIONS] install @ + platformio lib [STORAGE_OPTIONS] install + platformio lib [STORAGE_OPTIONS] install @ + platformio lib [STORAGE_OPTIONS] install @ + platformio lib [STORAGE_OPTIONS] install + platformio lib [STORAGE_OPTIONS] install file:// + platformio lib [STORAGE_OPTIONS] install file:// + platformio lib [STORAGE_OPTIONS] install + platformio lib [STORAGE_OPTIONS] install (name it should have locally) + platformio lib [STORAGE_OPTIONS] install ("tag" can be commit, branch or tag) Description ----------- -Install new library by specified -`PlatformIO Library Registry ID `_. +Install a library, and any libraries that it depends on using: -Installs the project library dependencies or a specific set of libraries. -[LIBRARY] can have multiple forms: , @, - or =@ +1. Library ``id`` or ``name`` from `PlatformIO Library Registry `_ +2. Custom folder, repository or archive. -Where, is a registry ID, registry name, repository URL, physical -location, is a valid semantic version/range, commit, branch, etc., and - is the name it should have locally. +The ``version`` supports `Semantic Versioning `_ ( +``..``) and 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`` + +Also, PlatformIO supports installing from local directory or archive. Need +to use ``file://`` prefix before local path. Also, directory or +archive should contain ``.library.json`` manifest (see :ref:`library_config`). + +* ``file:///local/path/to/the/platform/dir`` +* ``file:///local/path/to/the/platform.zip`` +* ``file:///local/path/to/the/platform.tar.gz`` + +Storage Options +--------------- + +See base options for :ref:`userguide_lib`. Options ------- @@ -44,50 +89,151 @@ Options .. program:: platformio lib install .. option:: - -v, --version + -q, --quiet -Install specified version of library +Suppress progress reporting + +Version control +--------------- + +PlatformIO supports installing from Git, Mercurial and Subversion, and detects +the type of VCS using url prefixes: "git+", "hg+", or "svn+". + +.. note:: + 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: + +* user/library (short version for GitHub repository) +* https://github.com/user/library.git +* git+git://git.server.org/my-library +* git+https://git.server.org/my-library +* git+ssh://git.server.org/my-library + +Passing branch names, a commit hash or a tag name is possible like so: + +* https://github.com/user/library.git#master +* git+git://git.server.org/my-library#master +* git+https://git.server.org/my-library#v1.0 +* git+ssh://git.server.org/my-library#7846d8ad52f983f2f2887bdc0f073fe9755a806d + +Mercurial +^^^^^^^^^ + +The supported schemes are: ``hg+http``, ``hg+https`` and ``hg+ssh``. Here are +the supported forms: + +* https://developer.mbed.org/users/user/code/library/ (install ARM mbed library) +* hg+hg://hg.server.org/my-library +* hg+https://hg.server.org/my-library +* hg+ssh://hg.server.org/my-library + +Passing branch names, a commit hash or a tag name is possible like so: + +* hg+hg://hg.server.org/my-library#master +* hg+https://hg.server.org/my-library#v1.0 +* hg+ssh://hg.server.org/my-library#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-library +* svn+https://svn.server.org/my-library +* svn+ssh://svn.server.org/my-library + +You can also give specific revisions to an SVN URL, like so: + +* svn+svn://svn.server.org/my-library#13 Examples -------- -1. Install the latest version of library +1. Install the latest version of library to a global storage using ID or NAME -.. code-block:: bash +.. code:: - # IRremote: http://platformio.org/lib/show/4/IRremote - $ platformio lib install 4 - # Installing library [ 4 ]: - # Downloading [####################################] 100% - # Unpacking [####################################] 100% - # The library #4 'IRremote' has been successfully installed! + > platformio lib -g install 4 + + Library Storage: /storage/dir/... + LibraryManager: Installing id=4 + Downloading [####################################] 100% + Unpacking [####################################] 100% + IRremote @ 2.2.1 has been successfully installed! + + # repeat command with name + > platformio lib -g install IRRemote + + Library Storage: /storage/dir/... + Looking for IRRemote library in registry + Found: http://platformio.org/lib/show/4/IRremote + LibraryManager: Installing id=4 + IRremote @ 2.2.1 is already installed -2. Install specified version of library +2. Install specified version of a library to a global storage -.. code-block:: bash +.. code:: - # XBee: http://platformio.org/lib/show/6/XBee - $ platformio lib install 6 --version=0.5 - # Installing library [ 6 ]: - # Downloading [####################################] 100% - # Unpacking [####################################] 100% - # The library #6 'XBee' has been successfully installed! + > platformio lib -g install Json@5.4.0 + + Library Storage: /storage/dir/... + Looking for Json library in registry + Found: http://platformio.org/lib/show/64/Json + LibraryManager: Installing id=64 @ 5.4.0 + Downloading [####################################] 100% + Unpacking [####################################] 100% + Json @ 5.4.0 has been successfully installed! -3. Install library with dependencies +3. Install library with dependencies to custom storage -.. code-block:: bash +.. code:: - # Adafruit-ST7735: http://platformio.org/lib/show/12/Adafruit-ST7735 - $ platformio lib install 12 - # Installing library [ 12 ]: - # Downloading [####################################] 100% - # Unpacking [####################################] 100% - # The library #12 'Adafruit-ST7735' has been successfully installed! - # Installing dependencies: - # Installing library [ 13 ]: - # Downloading [####################################] 100% - # Unpacking [####################################] 100% - # The library #13 'Adafruit-GFX' has been successfully installed! + > platformio lib --storage-dir /my/storage/dir install DallasTemperature + + Library Storage: /my/storage/dir + Looking for DallasTemperature library in registry + Found: http://platformio.org/lib/show/54/DallasTemperature + LibraryManager: Installing id=54 + Downloading [####################################] 100% + Unpacking [####################################] 100% + DallasTemperature @ 3.7.7 has been successfully installed! + Installing dependencies + Looking for OneWire library in registry + Found: http://platformio.org/lib/show/1/OneWire + LibraryManager: Installing id=1 + Downloading [####################################] 100% + Unpacking [####################################] 100% + OneWire @ 8fd2ebfec7 has been successfully installed! + +4. Install ARM mbed library to the global storage + +.. code:: + + > platformio lib -g install https://developer.mbed.org/users/simon/code/TextLCD/ + + Library Storage: /storage/dir/... + LibraryManager: Installing TextLCD + Mercurial Distributed SCM (version 3.8.4) + (see https://mercurial-scm.org for more information) + + Copyright (C) 2005-2016 Matt Mackall and others + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + requesting all changes + adding changesets + adding manifests + adding file changes + added 9 changesets with 18 changes to 6 files + updating to branch default + 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + TextLCD @ 308d188a2d3a has been successfully installed! diff --git a/docs/userguide/lib/cmd_list.rst b/docs/userguide/lib/cmd_list.rst index deb19b9c..fb2be037 100644 --- a/docs/userguide/lib/cmd_list.rst +++ b/docs/userguide/lib/cmd_list.rst @@ -1,4 +1,4 @@ -.. Copyright 2014-2016 Ivan Kravets +.. Copyright 2014-present Ivan Kravets 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 @@ -21,14 +21,30 @@ Usage .. code-block:: bash + platformio lib [STORAGE_OPTIONS] list [OPTIONS] + + # list project dependent libraries + # (run it from a project root where is located "platformio.ini") platformio lib list [OPTIONS] + # list libraries from global storage + platformio lib --global list [OPTIONS] + platformio lib -g list [OPTIONS] + + # list libraries from custom storage + platformio lib --storage-dir /path/to/dir list [OPTIONS] + platformio lib -d /path/to/dir list [OPTIONS] Description ----------- List installed libraries +Storage Options +--------------- + +See base options for :ref:`userguide_lib`. + Options ~~~~~~~ @@ -42,18 +58,14 @@ Return the output in `JSON `_ format Examples -------- -.. code-block:: bash +.. code:: - $ platformio lib list - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 23 ] Adafruit-L3GD20-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the L3GD20 Gyroscope - # [ 12 ] Adafruit-ST7735 arduino, atmelavr "Adafruit Industries": A library for the Adafruit 1.8" SPI display - # [ 31 ] Adafruit-Unified-Sensor arduino, atmelavr "Adafruit Industries": Adafruit Unified Sensor Driver - # [ 26 ] Adafruit-LSM303DLHC-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) - # [ 6 ] XBee arduino, atmelavr "Andrew Rapp": Arduino library for communicating with XBees in API mode - # [ 13 ] Adafruit-GFX arduino, atmelavr "Adafruit Industries": A core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.) - # [ 4 ] IRremote arduino, atmelavr "Ken Shirriff": Send and receive infrared signals with multiple protocols - # [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) - # ... + > platformio lib list + + pio lib -g list + Library Storage: /storage/dir/... + [ ID ] Name Compatibility "Authors": Description + ----------------------------------------------------------------------------------------------------------- + [ 4 ] IRremote arduino, atmelavr "Rafi Khan, Ken Shirriff": Send and receive infrared signals with multiple protocols | @2.2.1 + [ 64 ] Json arduino, atmelavr, atmelsam, timsp430, titiva, teensy, freescalekinetis, ststm32, nordicnrf51, nxplpc, espressif, siliconlabsefm32, linux_arm, native, intel_arc32 "Benoit Blanchon": An elegant and efficient JSON library for embedded systems | @5.4.0 + [ VCS ] TextLCD - "Unknown": hg+https://developer.mbed.org/users/simon/code/TextLCD/ | @308d188a2d3a diff --git a/docs/userguide/lib/cmd_register.rst b/docs/userguide/lib/cmd_register.rst index 60f00c21..54ec524d 100644 --- a/docs/userguide/lib/cmd_register.rst +++ b/docs/userguide/lib/cmd_register.rst @@ -1,4 +1,4 @@ -.. Copyright 2014-2016 Ivan Kravets +.. Copyright 2014-present Ivan Kravets 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 @@ -32,6 +32,6 @@ Register new library and allow others to install it. Examples -------- -.. code-block:: bash +.. code:: - $ platformio lib register http://my.example.com/library.json + platformio lib register http://my.example.com/raw-library.json diff --git a/docs/userguide/lib/cmd_search.rst b/docs/userguide/lib/cmd_search.rst index 4325fe7f..0502b340 100644 --- a/docs/userguide/lib/cmd_search.rst +++ b/docs/userguide/lib/cmd_search.rst @@ -1,4 +1,4 @@ -.. Copyright 2014-2016 Ivan Kravets +.. Copyright 2014-present Ivan Kravets 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 @@ -74,6 +74,11 @@ Options .. program:: platformio lib search +.. option:: + -n, --name + +Filter libraries by specified name (strict search) + .. option:: -a, --author @@ -112,126 +117,134 @@ Examples 1. List all libraries -.. code-block:: bash +.. code:: - $ platformio lib search - # Found N libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) - # [ 13 ] Adafruit-GFX arduino, atmelavr "Adafruit Industries": A core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.) - # [ 23 ] Adafruit-L3GD20-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the L3GD20 Gyroscope - # [ 26 ] Adafruit-LSM303DLHC-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) - # [ 12 ] Adafruit-ST7735 arduino, atmelavr "Adafruit Industries": A library for the Adafruit 1.8" SPI display - # [ 31 ] Adafruit-Unified-Sensor arduino, atmelavr "Adafruit Industries": Adafruit Unified Sensor Driver - # [ 4 ] IRremote arduino, atmelavr "Ken Shirriff": Send and receive infrared signals with multiple protocols - # [ 1 ] OneWire arduino, atmelavr "Paul Stoffregen": Control devices (from Dallas Semiconductor) that use the One Wire protocol (DS18S20, DS18B20, DS2408 and etc) - # [ 6 ] XBee arduino, atmelavr "Andrew Rapp": Arduino library for communicating with XBees in API mode - # [ 15 ] Adafruit-ADXL345-Unified arduino, atmelavr "Adafruit Industries": Unified driver for the ADXL345 Accelerometer - # Show next libraries? [y/N]: - # ... + > platformio lib search + + Found N libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) + [ 13 ] Adafruit-GFX arduino, atmelavr "Adafruit Industries": A core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.) + [ 23 ] Adafruit-L3GD20-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the L3GD20 Gyroscope + [ 26 ] Adafruit-LSM303DLHC-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) + [ 12 ] Adafruit-ST7735 arduino, atmelavr "Adafruit Industries": A library for the Adafruit 1.8" SPI display + [ 31 ] Adafruit-Unified-Sensor arduino, atmelavr "Adafruit Industries": Adafruit Unified Sensor Driver + [ 4 ] IRremote arduino, atmelavr "Ken Shirriff": Send and receive infrared signals with multiple protocols + [ 1 ] OneWire arduino, atmelavr "Paul Stoffregen": Control devices (from Dallas Semiconductor) that use the One Wire protocol (DS18S20, DS18B20, DS2408 and etc) + [ 6 ] XBee arduino, atmelavr "Andrew Rapp": Arduino library for communicating with XBees in API mode + [ 15 ] Adafruit-ADXL345-Unified arduino, atmelavr "Adafruit Industries": Unified driver for the ADXL345 Accelerometer + Show next libraries? [y/N]: + ... 2. Search for `1-Wire libraries `_ -.. code-block:: bash +.. code:: - $ platformio lib search "1-wire" - # Found N libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 1 ] OneWire arduino, atmelavr "Paul Stoffregen": Control devices (from Dallas Semiconductor) that use the One Wire protocol (DS18S20, DS18B20, DS2408 and etc) - # ... + > platformio lib search "1-wire" + + Found N libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 1 ] OneWire arduino, atmelavr "Paul Stoffregen": Control devices (from Dallas Semiconductor) that use the One Wire protocol (DS18S20, DS18B20, DS2408 and etc) + ... 3. Search for `Arduino-based "I2C" libraries `_ -.. code-block:: bash +.. code:: - $ platformio lib search "i2c" --framework="arduino" - # Found N libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 11 ] I2Cdevlib-Core arduino, atmelavr "Jeff Rowberg": The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices. - # [ 24 ] Adafruit-L3GD20 arduino, atmelavr "Adafruit Industries": Driver for Adafruit's L3GD20 I2C Gyroscope Breakout - # [ 10 ] I2Cdevlib-AK8975 arduino, atmelavr "Jeff Rowberg": AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology - # [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) - # ... + > platformio lib search "i2c" --framework="arduino" + + Found N libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 11 ] I2Cdevlib-Core arduino, atmelavr "Jeff Rowberg": The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices. + [ 24 ] Adafruit-L3GD20 arduino, atmelavr "Adafruit Industries": Driver for Adafruit's L3GD20 I2C Gyroscope Breakout + [ 10 ] I2Cdevlib-AK8975 arduino, atmelavr "Jeff Rowberg": AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology + [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) + ... 4. Search for `libraries by "web" and "http" keywords `_. -.. code-block:: bash +.. code:: - $ platformio lib search --keyword="web" --keyword="http" - # Found N libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 5 ] Webduino arduino, atmelavr "Ben Combee": An extensible web server library (for use with the Arduino WizNet Ethernet Shield) - # [ 17 ] Adafruit-CC3000 arduino, atmelavr "Adafruit Industries": Library code for Adafruit's CC3000 Wi-Fi/WiFi breakouts - # ... + > platformio lib search --keyword="web" --keyword="http" + + Found N libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 5 ] Webduino arduino, atmelavr "Ben Combee": An extensible web server library (for use with the Arduino WizNet Ethernet Shield) + [ 17 ] Adafruit-CC3000 arduino, atmelavr "Adafruit Industries": Library code for Adafruit's CC3000 Wi-Fi/WiFi breakouts + ... 5. Search for `libraries by "Adafruit Industries" author `_ -.. code-block:: bash +.. code:: - $ platformio lib search --author="Adafruit Industries" - # Found N libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) - # [ 13 ] Adafruit-GFX arduino, atmelavr "Adafruit Industries": A core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.) - # [ 23 ] Adafruit-L3GD20-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the L3GD20 Gyroscope - # [ 26 ] Adafruit-LSM303DLHC-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) - # ... + > platformio lib search --author="Adafruit Industries" + + Found N libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) + [ 13 ] Adafruit-GFX arduino, atmelavr "Adafruit Industries": A core graphics library for all our displays, providing a common set of graphics primitives (points, lines, circles, etc.) + [ 23 ] Adafruit-L3GD20-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the L3GD20 Gyroscope + [ 26 ] Adafruit-LSM303DLHC-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) + ... 6. Search for `libraries which are compatible with Dallas temperature sensors `_ like DS18B20, DS18S20 and etc. -.. code-block:: bash +.. code:: - $ platformio lib search "DS*" - # Found N libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 1 ] OneWire arduino, atmelavr "Paul Stoffregen": Control devices (from Dallas Semiconductor) that use the One Wire protocol (DS18S20, DS18B20, DS2408 and etc) - # ... + > platformio lib search "DS*" + + Found N libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 1 ] OneWire arduino, atmelavr "Paul Stoffregen": Control devices (from Dallas Semiconductor) that use the One Wire protocol (DS18S20, DS18B20, DS2408 and etc) + ... 7. Search for `Energia-based *nRF24* or *HttpClient* libraries `_. The search query that is described below can be interpreted like ``energia nRF24 OR energia HttpClient`` -.. code-block:: bash +.. code:: - $ platformio lib search "+(nRF24 HttpClient)" --framework="energia" - # Found 2 libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 46 ] HttpClient energia, timsp430, titiva "Zack Lalanne": HttpClient is a library to make it easier to interact with web servers - # [ 43 ] nRF24 energia, timsp430 "Eric": The nRF24L01 is a low-cost 2.4GHz ISM transceiver module. It supports a number of channel frequencies in the 2.4GHz band and a range of data rates. + > platformio lib search "+(nRF24 HttpClient)" --framework="energia" + + Found 2 libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 46 ] HttpClient energia, timsp430, titiva "Zack Lalanne": HttpClient is a library to make it easier to interact with web servers + [ 43 ] nRF24 energia, timsp430 "Eric": The nRF24L01 is a low-cost 2.4GHz ISM transceiver module. It supports a number of channel frequencies in the 2.4GHz band and a range of data rates. 8. Search for the `all sensor libraries excluding temperature `_. -.. code-block:: bash +.. code:: - $ platformio lib search "sensor -temperature" - # Found N libraries: - # - # [ ID ] Name Compatibility "Authors": Description - # ------------------------------------------------------------------------------------- - # [ 31 ] Adafruit-Unified-Sensor arduino, atmelavr "Adafruit Industries": Adafruit Unified Sensor Driver - # [ 10 ] I2Cdevlib-AK8975 arduino, atmelavr "Jeff Rowberg": AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology - # [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) - # [ 23 ] Adafruit-L3GD20-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the L3GD20 Gyroscope - # [ 26 ] Adafruit-LSM303DLHC-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) - # [ 33 ] Adafruit-TMP006 arduino, atmelavr "Adafruit Industries": A library for the Adafruit TMP006 Infrared Thermopile Sensor - # [ 34 ] Adafruit-TSL2561-Unified arduino, atmelavr "Adafruit Industries": Unified light sensor driver for Adafruit's TSL2561 breakouts - # [ 97 ] I2Cdevlib-BMA150 arduino, atmelavr "Jeff Rowberg": The BMA150 is a triaxial, low-g acceleration sensor IC with digital output for consumer market applications - # [ 106 ] I2Cdevlib-MPR121 arduino, atmelavr "Jeff Rowberg": The MPR121 is a 12-bit proximity capacitive touch sensor - # [ 111 ] I2Cdevlib-AK8975 energia, timsp430 "Jeff Rowberg": AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology - # Show next libraries? [y/N]: + > platformio lib search "sensor -temperature" + + Found N libraries: + + [ ID ] Name Compatibility "Authors": Description + ------------------------------------------------------------------------------------- + [ 31 ] Adafruit-Unified-Sensor arduino, atmelavr "Adafruit Industries": Adafruit Unified Sensor Driver + [ 10 ] I2Cdevlib-AK8975 arduino, atmelavr "Jeff Rowberg": AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology + [ 14 ] Adafruit-9DOF-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the Adafruit 9DOF Breakout (L3GD20 / LSM303) + [ 23 ] Adafruit-L3GD20-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for the L3GD20 Gyroscope + [ 26 ] Adafruit-LSM303DLHC-Unified arduino, atmelavr "Adafruit Industries": Unified sensor driver for Adafruit's LSM303 Breakout (Accelerometer + Magnetometer) + [ 33 ] Adafruit-TMP006 arduino, atmelavr "Adafruit Industries": A library for the Adafruit TMP006 Infrared Thermopile Sensor + [ 34 ] Adafruit-TSL2561-Unified arduino, atmelavr "Adafruit Industries": Unified light sensor driver for Adafruit's TSL2561 breakouts + [ 97 ] I2Cdevlib-BMA150 arduino, atmelavr "Jeff Rowberg": The BMA150 is a triaxial, low-g acceleration sensor IC with digital output for consumer market applications + [ 106 ] I2Cdevlib-MPR121 arduino, atmelavr "Jeff Rowberg": The MPR121 is a 12-bit proximity capacitive touch sensor + [ 111 ] I2Cdevlib-AK8975 energia, timsp430 "Jeff Rowberg": AK8975 is 3-axis electronic compass IC with high sensitive Hall sensor technology + Show next libraries? [y/N]: diff --git a/docs/userguide/lib/cmd_show.rst b/docs/userguide/lib/cmd_show.rst index 745685d1..9ee69da4 100644 --- a/docs/userguide/lib/cmd_show.rst +++ b/docs/userguide/lib/cmd_show.rst @@ -1,4 +1,4 @@ -.. Copyright 2014-2016 Ivan Kravets +.. Copyright 2014-present Ivan Kravets 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 @@ -21,28 +21,65 @@ Usage .. code-block:: bash - platformio lib show ID + platformio lib [STORAGE_OPTIONS] show [LIBRARY] + # show info about project dependent library + # (run it from a project root where is located "platformio.ini") + platformio lib show [LIBRARY] + + # show info about library from global storage + platformio lib --global show [LIBRARY] + platformio lib -g show [LIBRARY] + + # show info about library from custom storage + platformio lib --storage-dir /path/to/dir show [LIBRARY] + platformio lib -d /path/to/dir show [LIBRARY] + + # [LIBRARY] forms + platformio lib [STORAGE_OPTIONS] show + platformio lib [STORAGE_OPTIONS] show + platformio lib [STORAGE_OPTIONS] show @ + platformio lib [STORAGE_OPTIONS] show @ + platformio lib [STORAGE_OPTIONS] show + platformio lib [STORAGE_OPTIONS] show @ + platformio lib [STORAGE_OPTIONS] show @ Description ----------- -Show details about the installed library +Show details about the installed library. +The ``version`` supports `Semantic Versioning `_ ( +``..``) and 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`` + +Storage Options +--------------- + +See base options for :ref:`userguide_lib`. Examples -------- -.. code-block:: bash +.. code:: - # OneWire: http://platformio.org/lib/show/1/OneWire - $ platformio lib show 1 - # OneWire - # ------- - # Authors: Paul Stoffregen http://www.pjrc.com/teensy/td_libs_OneWire.html (maintainer), Jim Studt, Jason Dangel , Derek Yerger, Tom Pollard , Robin James - # Keywords: onewire, 1-wire, bus, sensor, temperature, ibutton - # Frameworks: arduino - # Platforms: atmelavr - # Version: 2.2 - # - # Control devices (from Dallas Semiconductor) that use the One Wire protocol (DS18S20, DS18B20, DS2408 and etc) + platformio lib -g show Json + + Library Storage: /storage/dir/... + Json + ==== + An elegant and efficient JSON library for embedded systems + + Authors: Benoit Blanchon http://blog.benoitblanchon.fr + Keywords: json, rest, http, web + Frameworks: arduino + Platforms: atmelavr, atmelsam, timsp430, titiva, teensy, freescalekinetis, ststm32, nordicnrf51, nxplpc, espressif, siliconlabsefm32, linux_arm, native, intel_arc32 + Version: 5.4.0 diff --git a/docs/userguide/lib/cmd_uninstall.rst b/docs/userguide/lib/cmd_uninstall.rst index df99372b..5df77eca 100644 --- a/docs/userguide/lib/cmd_uninstall.rst +++ b/docs/userguide/lib/cmd_uninstall.rst @@ -1,4 +1,4 @@ -.. Copyright 2014-2016 Ivan Kravets +.. Copyright 2014-present Ivan Kravets 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 @@ -21,20 +21,56 @@ Usage .. code-block:: bash - platformio lib uninstall ID + platformio lib [STORAGE_OPTIONS] uninstall [LIBRARY...] + # uninstall project dependent library + # (run it from a project root where is located "platformio.ini") + platformio lib uninstall [LIBRARY...] + + # uninstall library from global storage + platformio lib --global uninstall [LIBRARY...] + platformio lib -g uninstall [LIBRARY...] + + # uninstall library from custom storage + platformio lib --storage-dir /path/to/dir uninstall [LIBRARY...] + platformio lib -d /path/to/dir uninstall [LIBRARY...] + + # [LIBRARY...] forms + platformio lib [STORAGE_OPTIONS] uninstall + platformio lib [STORAGE_OPTIONS] uninstall @ + platformio lib [STORAGE_OPTIONS] uninstall @ + platformio lib [STORAGE_OPTIONS] uninstall + platformio lib [STORAGE_OPTIONS] uninstall @ + platformio lib [STORAGE_OPTIONS] uninstall @ Description ----------- Uninstall specified library +The ``version`` supports `Semantic Versioning `_ ( +``..``) and 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`` + +Storage Options +--------------- + +See base options for :ref:`userguide_lib`. Examples -------- -.. code-block:: bash +.. code:: - # XBee: http://platformio.org/lib/show/6/XBee - $ platformio lib uninstall 6 - # The library #6 'XBee' has been successfully uninstalled! + > platformio lib -g uninstall AsyncMqttClient + + Library Storage: /storage/dir/... + Uninstalling AsyncMqttClient @ 0.2.0: [OK] diff --git a/docs/userguide/lib/cmd_update.rst b/docs/userguide/lib/cmd_update.rst index 6b24f699..4e47ac9f 100644 --- a/docs/userguide/lib/cmd_update.rst +++ b/docs/userguide/lib/cmd_update.rst @@ -1,4 +1,4 @@ -.. Copyright 2014-2016 Ivan Kravets +.. Copyright 2014-present Ivan Kravets 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 @@ -21,51 +21,102 @@ Usage .. code-block:: bash - platformio lib update [LIBRARY_ID] + platformio lib [STORAGE_OPTIONS] update [OPTIONS] + + # update all project libraries + # (run it from a project root where is located "platformio.ini") + platformio lib update [OPTIONS] + + # update project dependent library + platformio lib [STORAGE_OPTIONS] update [OPTIONS] [LIBRARY...] + + # update library in global storage + platformio lib --global update [OPTIONS] [LIBRARY...] + platformio lib -g update [OPTIONS] [LIBRARY...] + + # update library in custom storage + platformio lib --storage-dir /path/to/dir update [OPTIONS] [LIBRARY...] + platformio lib -d /path/to/dir update [OPTIONS] [LIBRARY...] + + # [LIBRARY...] forms + platformio lib [STORAGE_OPTIONS] update + platformio lib [STORAGE_OPTIONS] update @ + platformio lib [STORAGE_OPTIONS] update @ + platformio lib [STORAGE_OPTIONS] update + platformio lib [STORAGE_OPTIONS] update @ + platformio lib [STORAGE_OPTIONS] update @ Description ----------- -Check or update installed libraries +Check or update installed libraries. +The ``version`` supports `Semantic Versioning `_ ( +``..``) and 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`` + +Storage Options +--------------- + +See base options for :ref:`userguide_lib`. + +Options +------- + +.. program:: platformio lib update + +.. option:: + -c, --only-check + +Do not update, only check for new version Examples -------- -1. Update all installed libraries +1. Update all installed libraries in global storage -.. code-block:: bash +.. code:: - $ platformio lib update - # Updating [ 23 ] Adafruit-L3GD20-Unified library: - # Versions: Current=63de2eb9ea, Latest=63de2eb9ea [Up-to-date] - # Updating [ 12 ] Adafruit-ST7735 library: - # Versions: Current=e880eb1687, Latest=e880eb1687 [Up-to-date] - # Updating [ 31 ] Adafruit-Unified-Sensor library: - # Versions: Current=88ae805bce, Latest=88ae805bce [Up-to-date] - # Updating [ 26 ] Adafruit-LSM303DLHC-Unified library: - # Versions: Current=59767208a8, Latest=59767208a8 [Up-to-date] - # Updating [ 13 ] Adafruit-GFX library: - # Versions: Current=a9e5bc4707, Latest=a9e5bc4707 [Up-to-date] - # Updating [ 1 ] OneWire library: - # Versions: Current=2.2, Latest=2.2 [Up-to-date] - # Updating [ 4 ] IRremote library: - # Versions: Current=f2dafe5030, Latest=f2dafe5030 [Up-to-date] - # Updating [ 14 ] Adafruit-9DOF-Unified library: - # Versions: Current=b2f07242ac, Latest=b2f07242ac [Up-to-date] + > platformio lib -g update -2. Update specified libraries + Library Storage: /storage/dir/... + Updating ESP8266_SSD1306 @ 3.2.3: [Up-to-date] + Updating EngduinoMagnetometer @ 3.1.0: [Up-to-date] + Updating IRremote @ 2.2.1: [Up-to-date] + Updating Json @ 5.4.0: [Out-of-date] + LibraryManager: Installing id=64 @ 5.6.4 + Downloading [####################################] 100% + Unpacking [####################################] 100% + Json @ 5.6.4 has been successfully installed! + Updating PJON @ 1fb26fd: [Checking] + git version 2.7.4 (Apple Git-66) + Already up-to-date. + Updating TextLCD @ 308d188a2d3a: [Checking] + Mercurial Distributed SCM (version 3.8.4) + (see https://mercurial-scm.org for more information) -.. code-block:: bash + Copyright (C) 2005-2016 Matt Mackall and others + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + pulling from https://developer.mbed.org/users/simon/code/TextLCD/ + searching for changes + no changes found - $ platformio lib update 1 59 - # Updating [ 1 ] OneWire library: - # Versions: Current=2.2, Latest=2.2 [Up-to-date] - # Updating [ 59 ] USB-Host-Shield-20 library: - # Versions: Current=fcab83dcb3, Latest=c61f9ce1c2 [Out-of-date] - # The library #59 'USB-Host-Shield-20' has been successfully uninstalled! - # Installing library [ 59 ]: - # Downloading [####################################] 100% - # Unpacking [####################################] 100% - # The library #59 'USB-Host-Shield-20' has been successfully installed! +2. Update specified libraries in global storage + +.. code:: + + > platformio lib -g update Json 4 + + Library Storage: /storage/dir/... + Updating Json @ 5.6.4: [Up-to-date] + Updating IRremote @ 2.2.1: [Up-to-date] diff --git a/docs/userguide/lib/index.rst b/docs/userguide/lib/index.rst index 55626bfb..f6aed45b 100644 --- a/docs/userguide/lib/index.rst +++ b/docs/userguide/lib/index.rst @@ -14,15 +14,48 @@ Library Manager =============== -To print all available commands and options use: +Usage +----- .. code-block:: bash - $ platformio lib --help - $ platformio lib COMMAND --help + platformio lib [OPTIONS] COMMAND + + # To print all available commands and options use + platformio lib --help + platformio lib COMMAND --help + +Options +------- + +.. program:: platformio lib + +.. option:: + -g, --global + +.. versionadded:: 3.0 + + +Manage global PlatformIO's library storage ( +":ref:`projectconf_pio_home_dir`/lib") where :ref:`ldf` will look for +dependencies by default. + +.. option:: + -d, --storage-dir + +.. versionadded:: 3.0 + +Manage custom library storage. It can be used later for the +:ref:`projectconf_extra_script` option from :ref:`projectconf`. + +Demo +---- .. image:: ../../_static/platformio-demo-lib.gif +Commands +-------- + .. toctree:: :maxdepth: 2 diff --git a/docs/userguide/platforms/cmd_install.rst b/docs/userguide/platforms/cmd_install.rst index 3ada1992..11563c3c 100644 --- a/docs/userguide/platforms/cmd_install.rst +++ b/docs/userguide/platforms/cmd_install.rst @@ -21,14 +21,18 @@ Usage .. code-block:: bash - # install platform by name platformio platform install [OPTIONS] [PLATFORM...] - # install specific platform version using Semantic Versioning - platformio platform install [OPTIONS] PLATFORM@X.Y.Z - - # install platform using URL - platformio platform install [OPTIONS] URL + # [PLATFORM...] forms + platformio platform install + platformio platform install @ + platformio platform install @ + platformio platform install + platformio platform install file:// + platformio platform install file:// + platformio platform install + platformio platform install (name it should have locally) + platformio platform install ("tag" can be commit, branch or tag) Description @@ -36,33 +40,56 @@ Description Install :ref:`platforms` and dependent packages. -There are several predefined aliases for packages, such as: +The ``version`` supports `Semantic Versioning `_ ( +``..``) and can take any of the following forms: -* ``framework`` -* ``toolchain`` -* ``uploader`` +* ``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`` -Local -~~~~~ - -PlatformIO supports installing development platform from local directory or -archive. Need to use ``file://`` prefix before local path. Also, platform -directory or archive should contain ``platform.json`` manifest. +Also, PlatformIO supports installing from local directory or archive. Need to +use ``file://`` prefix before local path. Also, directory or archive should +contain ``platform.json`` manifest. * ``file:///local/path/to/the/platform/dir`` * ``file:///local/path/to/the/platform.zip`` * ``file:///local/path/to/the/platform.tar.gz`` -Remote -~~~~~~ +Options +------- -VCS -~~~ +.. program:: platformio platform install + +.. option:: + --with-package + +Install specified package (or alias) + + +.. option:: + --without-package + +Do not install specified package (or alias) + +.. option:: + --skip-default + +Skip default packages + +Version control +--------------- 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. +.. note:: + PlatformIO requires a working VCS command on your path: ``git``, ``hg`` + or ``svn``. Git ^^^ @@ -70,6 +97,7 @@ Git The supported schemes are: ``git``, ``git+https`` and ``git+ssh``. Here are the supported forms: +* platformio/platform-NAME (short version for GitHub repository) * https://github.com/platformio/platform-NAME.git * git+git://git.server.org/my-platform * git+https://git.server.org/my-platform @@ -112,35 +140,15 @@ You can also give specific revisions to an SVN URL, like so: * svn+svn://svn.server.org/my-platform#13 -Options -------- - -.. program:: platformio platform install - -.. option:: - --with-package - -Install specified package (or alias) - - -.. option:: - --without-package - -Do not install specified package (or alias) - -.. option:: - --skip-default - -Skip default packages - Examples -------- 1. Install :ref:`platform_atmelavr` with default packages -.. code-block:: bash +.. code:: + + > platformio platform install atmelavr - $ platformio platform install atmelavr PlatformManager: Installing atmelavr Downloading... Unpacking [####################################] 100% @@ -159,7 +167,9 @@ Examples 2. Install :ref:`platform_atmelavr` with ``uploader`` utility only and skip default packages -.. code-block:: bash +.. code:: + + > platformio platform install atmelavr --skip-default-package --with-package=uploader PlatformManager: Installing atmelavr Downloading [####################################] 100% @@ -178,9 +188,9 @@ Examples 3. Install the latest development :ref:`platform_atmelavr` from Git repository -.. code-block:: bash +.. code:: - $ platformio platform install https://github.com/platformio/platform-atmelavr.git + > platformio platform install https://github.com/platformio/platform-atmelavr.git PlatformManager: Installing platform-atmelavr git version 2.7.4 (Apple Git-66) diff --git a/docs/userguide/platforms/cmd_list.rst b/docs/userguide/platforms/cmd_list.rst index aca7aec1..c4e19756 100644 --- a/docs/userguide/platforms/cmd_list.rst +++ b/docs/userguide/platforms/cmd_list.rst @@ -42,9 +42,10 @@ Return the output in `JSON `_ format Examples -------- -.. code-block:: bash +.. code:: + + > platformio platform list - $ platformio platform list atmelavr ~ Atmel AVR ==================== Atmel AVR 8- and 32-bit MCUs deliver a unique combination of performance, power efficiency and design flexibility. Optimized to speed time to market-and easily adapt to new ones-they are based on the industrys most code-efficient architecture for C and assembly programming. diff --git a/docs/userguide/platforms/cmd_search.rst b/docs/userguide/platforms/cmd_search.rst index 96f1bf5e..e377b631 100644 --- a/docs/userguide/platforms/cmd_search.rst +++ b/docs/userguide/platforms/cmd_search.rst @@ -45,9 +45,10 @@ Examples 1. Print all available development platforms -.. code-block:: bash +.. code:: + + > platformio platform search - $ platformio platform search atmelavr ~ Atmel AVR ==================== Atmel AVR 8- and 32-bit MCUs deliver a unique combination of performance, power efficiency and design flexibility. Optimized to speed time to market-and easily adapt to new ones-they are based on the industrys most code-efficient architecture for C and assembly programming. @@ -75,9 +76,10 @@ Examples 2. Search for TI development platforms -.. code-block:: bash +.. code:: + + > platformio platform search texas - $ platformio platform search texas timsp430 ~ TI MSP430 ==================== MSP430 microcontrollers (MCUs) from Texas Instruments (TI) are 16-bit, RISC-based, mixed-signal processors designed for ultra-low power. These MCUs offer the lowest power consumption and the perfect mix of integrated peripherals for thousands of applications. @@ -92,9 +94,10 @@ Examples Home: http://platformio.org/platforms/titiva Packages: ldscripts, framework-libopencm3, toolchain-gccarmnoneeabi, tool-lm4flash, framework-energiativa -.. code-block:: bash +.. code:: + + > platformio platform search framework-mbed - $ platformio platform search framework-mbed atmelsam ~ Atmel SAM ==================== Atmel | SMART offers Flash- based ARM products based on the ARM Cortex-M0+, Cortex-M3 and Cortex-M4 architectures, ranging from 8KB to 2MB of Flash including a rich peripheral and feature mix. diff --git a/docs/userguide/platforms/cmd_show.rst b/docs/userguide/platforms/cmd_show.rst index 114b4bce..9d02d1f9 100644 --- a/docs/userguide/platforms/cmd_show.rst +++ b/docs/userguide/platforms/cmd_show.rst @@ -33,9 +33,10 @@ Show details about the installed :ref:`platforms` Examples -------- -.. code-block:: bash +.. code:: + + > platformio platform show atmelavr - $ platformio platform show atmelavr atmelavr ~ Atmel AVR ==================== Atmel AVR 8- and 32-bit MCUs deliver a unique combination of performance, power efficiency and design flexibility. Optimized to speed time to market-and easily adapt to new ones-they are based on the industrys most code-efficient architecture for C and assembly programming. diff --git a/docs/userguide/platforms/cmd_uninstall.rst b/docs/userguide/platforms/cmd_uninstall.rst index 3292f147..5066a9c6 100644 --- a/docs/userguide/platforms/cmd_uninstall.rst +++ b/docs/userguide/platforms/cmd_uninstall.rst @@ -36,9 +36,9 @@ Uninstall specified :ref:`platforms` Examples -------- -.. code-block:: bash +.. code:: - $ platformio platform uninstall atmelavr + > platformio platform uninstall atmelavr Uninstalling platform atmelavr @ 0.0.0: [OK] Uninstalling package tool-scons @ 2.4.1: [OK] Uninstalling package toolchain-atmelavr @ 1.40801.0: [OK] diff --git a/docs/userguide/platforms/cmd_update.rst b/docs/userguide/platforms/cmd_update.rst index c48f802b..b225fcb3 100644 --- a/docs/userguide/platforms/cmd_update.rst +++ b/docs/userguide/platforms/cmd_update.rst @@ -51,9 +51,10 @@ Do not update, only check for new version Examples -------- -.. code-block:: bash +.. code:: + + > platformio platform update - $ platformio platform update Platform atmelavr -------- Updating atmelavr @ 0.0.0: [Up-to-date] diff --git a/docs/userguide/platforms/index.rst b/docs/userguide/platforms/index.rst index 437826f1..cc113e86 100644 --- a/docs/userguide/platforms/index.rst +++ b/docs/userguide/platforms/index.rst @@ -18,8 +18,8 @@ To print all available commands and options use: .. code-block:: bash - $ platformio platform --help - $ platformio platform COMMAND --help + platformio platform --help + platformio platform COMMAND --help .. image:: ../../_static/platformio-demo-platforms.gif diff --git a/platformio/__init__.py b/platformio/__init__.py index 6ac5d903..9fd6f088 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -14,7 +14,7 @@ import sys -VERSION = (3, 0, "0.dev15") +VERSION = (3, 0, "0.dev16") __version__ = ".".join([str(s) for s in VERSION]) __title__ = "platformio" diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index bbf8bb09..2a708d81 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -1,4 +1,4 @@ -# Copyright 2014-2016 Ivan Kravets +# Copyright 2014-present Ivan Kravets # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -13,51 +13,136 @@ # limitations under the License. import json +from os.path import join import click -from platformio import app, exception -from platformio.libmanager import LibraryManager +from platformio import app, exception, util +from platformio.managers.lib import LibraryManager from platformio.util import get_api_result + +@click.group(short_help="Library Manager") +@click.option( + "-g", + "--global", + is_flag=True, + help="Manager global PlatformIO" + " library storage `%s`" % join(util.get_home_dir(), "lib")) +@click.option( + "-d", + "--storage-dir", + default=None, + type=click.Path( + exists=True, + file_okay=False, + dir_okay=True, + writable=True, + resolve_path=True), + help="Manage custom library storage") +@click.pass_context +def cli(ctx, **options): + # skip commands that don't need storage folder + if ctx.invoked_subcommand in ("search", "register") or \ + (len(ctx.args) == 2 and ctx.args[1] in ("-h", "--help")): + return + storage_dir = options['storage_dir'] + if not storage_dir and options['global']: + storage_dir = join(util.get_home_dir(), "lib") + + if not storage_dir and not util.is_platformio_project(): + raise exception.PlatformioException( + "The `%s` is not a PlatformIO project.\nTo manage libraries " + "in the global storage `%s`, please use " + "`platformio lib --global %s` instead." % + (util.get_project_dir(), join(util.get_home_dir(), "lib"), + ctx.invoked_subcommand)) + + ctx.obj = LibraryManager(storage_dir) + click.echo("Library Storage: " + storage_dir) + + +@cli.command("install", short_help="Install library") +@click.argument("libraries", required=False, nargs=-1, metavar="[LIBRARY...]") +@click.option( + "--save", + is_flag=True, + help="Save installed libraries into the project's platformio.ini " + "library dependencies") +@click.option( + "-q", "--quiet", is_flag=True, help="Suppress progress reporting") +@click.pass_obj +def lib_install(lm, libraries, save, quiet): # pylint: disable=unused-argument + # @TODO "save" option + for library in libraries: + lm.install(library, quiet=quiet) + + +@cli.command("uninstall", short_help="Uninstall libraries") +@click.argument("libraries", nargs=-1, metavar="[LIBRARY...]") +@click.pass_obj +def lib_uninstall(lm, libraries): + for library in libraries: + lm.uninstall(library) + + +@cli.command("update", short_help="Update installed libraries") +@click.argument("libraries", required=False, nargs=-1, metavar="[LIBRARY...]") +@click.option( + "-c", + "--only-check", + is_flag=True, + help="Do not update, only check for new version") +@click.pass_obj +def lib_update(lm, libraries, only_check): + if not libraries: + libraries = [str(m.get("id", m['name'])) for m in lm.get_installed()] + for library in libraries: + lm.update(library, only_check=only_check) + +####### + LIBLIST_TPL = ("[{id:^14}] {name:<25} {compatibility:<30} " "\"{authornames}\": {description}") def echo_liblist_header(): - click.echo(LIBLIST_TPL.format( - id=click.style("ID", fg="green"), - name=click.style("Name", fg="cyan"), - compatibility=click.style("Compatibility", fg="yellow"), - authornames="Authors", - description="Description" - )) + click.echo( + LIBLIST_TPL.format( + id=click.style( + "ID", fg="green"), + name=click.style( + "Name", fg="cyan"), + compatibility=click.style( + "Compatibility", fg="yellow"), + authornames="Authors", + description="Description")) terminal_width, _ = click.get_terminal_size() click.echo("-" * terminal_width) def echo_liblist_item(item): - click.echo(LIBLIST_TPL.format( - id=click.style(str(item['id']), fg="green"), - name=click.style(item['name'], fg="cyan"), - compatibility=click.style( - ", ".join(item['frameworks'] + item['platforms']), - fg="yellow" - ), - authornames=", ".join(item['authornames']), - description=item['description'] - )) - - -@click.group(short_help="Library Manager") -def cli(): - pass + click.echo( + LIBLIST_TPL.format( + id=click.style( + str(item.get("id", "VCS")), fg="green"), + name=click.style( + item['name'], fg="cyan"), + compatibility=click.style( + ", ".join( + item.get("frameworks", ["-"]) + item.get("platforms", [])), + fg="yellow"), + authornames=", ".join(item.get("authornames", ["Unknown"])), + description=item.get("description", item.get("url", ""))) + + (" | @" + click.style( + item['version'], fg="yellow") if "version" in item else "")) @cli.command("search", short_help="Search for library") @click.option("--json-output", is_flag=True) @click.option("--page", type=click.INT, default=1) +@click.option("-n", "--name", multiple=True) @click.option("-a", "--author", multiple=True) @click.option("-k", "--keyword", multiple=True) @click.option("-f", "--framework", multiple=True) @@ -73,8 +158,9 @@ def lib_search(query, json_output, page, **filters): for value in values: query.append('%s:"%s"' % (key, value)) - result = get_api_result("/lib/search", - dict(query=" ".join(query), page=page)) + result = get_api_result( + "/lib/search", dict( + query=" ".join(query), page=page)) if json_output: click.echo(json.dumps(result)) @@ -84,17 +170,22 @@ def lib_search(query, json_output, page, **filters): click.secho( "Nothing has been found by your request\n" "Try a less-specific search or use truncation (or wildcard) " - "operator", fg="yellow", nl=False) + "operator", + fg="yellow", + nl=False) click.secho(" *", fg="green") click.secho("For example: DS*, PCA*, DHT* and etc.\n", fg="yellow") click.echo("For more examples and advanced search syntax, " "please use documentation:") - click.secho("http://docs.platformio.org" - "/en/latest/userguide/lib/cmd_search.html\n", fg="cyan") + click.secho( + "http://docs.platformio.org" + "/en/latest/userguide/lib/cmd_search.html\n", + fg="cyan") return - click.secho("Found %d libraries:\n" % result['total'], - fg="green" if result['total'] else "yellow") + click.secho( + "Found %d libraries:\n" % result['total'], + fg="green" if result['total'] else "yellow") if result['total']: echo_liblist_header() @@ -111,94 +202,17 @@ def lib_search(query, json_output, page, **filters): click.confirm("Show next libraries?")): result = get_api_result( "/lib/search", - dict(query=" ".join(query), page=int(result['page']) + 1) - ) + dict( + query=" ".join(query), page=int(result['page']) + 1)) else: break -@cli.command("install", short_help="Install library") -@click.argument("libid", type=click.INT, nargs=-1, metavar="[LIBRARY_ID]") -@click.option("-v", "--version") -@click.pass_context -def lib_install(ctx, libid, version): - lm = LibraryManager() - for id_ in libid: - click.echo( - "Installing library [ %s ]:" % click.style(str(id_), fg="green")) - try: - if not lm.install(id_, version): - continue - - info = lm.get_info(id_) - click.secho( - "The library #%s '%s' has been successfully installed!" - % (str(id_), info['name']), fg="green") - - if "dependencies" in info: - click.secho("Installing dependencies:", fg="yellow") - _dependencies = info['dependencies'] - if not isinstance(_dependencies, list): - _dependencies = [_dependencies] - for item in _dependencies: - try: - lib_install_dependency(ctx, item) - except AssertionError: - raise exception.LibInstallDependencyError(str(item)) - - except exception.LibAlreadyInstalled: - click.secho("Already installed", fg="yellow") - - -def lib_install_dependency(ctx, data): - assert isinstance(data, dict) - query = [] - for key in data: - if key in ("authors", "frameworks", "platforms", "keywords"): - values = data[key] - if not isinstance(values, list): - values = [v.strip() for v in values.split(",") if v] - for value in values: - query.append('%s:"%s"' % (key[:-1], value)) - elif isinstance(data[key], basestring): - query.append('+"%s"' % data[key]) - - result = get_api_result("/lib/search", dict(query=" ".join(query))) - assert result['total'] > 0 - - if result['total'] == 1 or not app.get_setting("enable_prompts"): - ctx.invoke(lib_install, libid=[result['items'][0]['id']]) - else: - click.secho( - "Conflict: More than one dependent libraries have been found " - "by request %s:" % json.dumps(data), fg="red") - - echo_liblist_header() - for item in result['items']: - echo_liblist_item(item) - - deplib_id = click.prompt( - "Please choose one dependent library ID", - type=click.Choice([str(i['id']) for i in result['items']])) - ctx.invoke(lib_install, libid=[int(deplib_id)]) - - -@cli.command("uninstall", short_help="Uninstall libraries") -@click.argument("libid", type=click.INT, nargs=-1) -def lib_uninstall(libid): - lm = LibraryManager() - for id_ in libid: - info = lm.get_info(id_) - if lm.uninstall(id_): - click.secho("The library #%s '%s' has been successfully " - "uninstalled!" % (str(id_), info['name']), fg="green") - - @cli.command("list", short_help="List installed libraries") @click.option("--json-output", is_flag=True) -def lib_list(json_output): - lm = LibraryManager() - items = lm.get_installed().values() +@click.pass_obj +def lib_list(lm, json_output): + items = lm.get_installed() if json_output: click.echo(json.dumps(items)) @@ -208,21 +222,34 @@ def lib_list(json_output): return echo_liblist_header() - for item in sorted(items, key=lambda i: i['id']): - item['authornames'] = [i['name'] for i in item['authors']] + for item in sorted(items, key=lambda i: i['name']): + if "authors" in item: + item['authornames'] = [i['name'] for i in item['authors']] echo_liblist_item(item) @cli.command("show", short_help="Show details about installed library") -@click.argument("libid", type=click.INT) -def lib_show(libid): - lm = LibraryManager() - info = lm.get_info(libid) - click.secho(info['name'], fg="cyan") - click.echo("-" * len(info['name'])) +@click.pass_obj +@click.argument("library", metavar="[LIBRARY]") +def lib_show(lm, library): # pylint: disable=too-many-branches + name, requirements, url = lm.parse_pkg_name(library) + installed_dir = lm.get_installed_dir(name, requirements, url) + if not installed_dir: + click.secho( + "%s @ %s is not installed" % (name, requirements or "*"), + fg="yellow") + return + + manifest = lm.load_manifest(installed_dir) + + click.secho(manifest['name'], fg="cyan") + click.echo("=" * len(manifest['name'])) + if "description" in manifest: + click.echo(manifest['description']) + click.echo() _authors = [] - for author in info['authors']: + for author in manifest.get("authors", []): _data = [] for key in ("name", "email", "url", "maintainer"): if not author[key]: @@ -234,61 +261,29 @@ def lib_show(libid): else: _data.append(author[key]) _authors.append(" ".join(_data)) - click.echo("Authors: %s" % ", ".join(_authors)) + if _authors: + click.echo("Authors: %s" % ", ".join(_authors)) - click.echo("Keywords: %s" % ", ".join(info['keywords'])) - if "frameworks" in info: - click.echo("Frameworks: %s" % ", ".join(info['frameworks'])) - if "platforms" in info: - click.echo("Platforms: %s" % ", ".join(info['platforms'])) - click.echo("Version: %s" % info['version']) - click.echo() - click.echo(info['description']) - click.echo() - - -@cli.command("update", short_help="Update installed libraries") -@click.argument("libid", type=click.INT, nargs=-1, required=False, - metavar="[LIBRARY_ID]") -@click.pass_context -def lib_update(ctx, libid): - lm = LibraryManager() - for id_, latest_version in (lm.get_latest_versions() or {}).items(): - if libid and int(id_) not in libid: - continue - - info = lm.get_info(int(id_)) - - click.echo("Updating [ %s ] %s library:" % ( - click.style(id_, fg="yellow"), - click.style(info['name'], fg="cyan"))) - - current_version = info['version'] - if latest_version is None: - click.secho("Unknown library", fg="red") - continue - - click.echo("Versions: Current=%s, Latest=%s \t " % ( - current_version, latest_version), nl=False) - - if current_version == latest_version: - click.echo("[%s]" % (click.style("Up-to-date", fg="green"))) + for key in ("keywords", "frameworks", "platforms", "license", "url", + "version"): + if key not in manifest: continue + if isinstance(manifest[key], list): + click.echo("%s: %s" % (key.title(), ", ".join(manifest[key]))) else: - click.echo("[%s]" % (click.style("Out-of-date", fg="red"))) - - ctx.invoke(lib_uninstall, libid=[int(id_)]) - ctx.invoke(lib_install, libid=[int(id_)]) + click.echo("%s: %s" % (key.title(), manifest[key])) @cli.command("register", short_help="Register new library") @click.argument("config_url") def lib_register(config_url): - if (not config_url.startswith("http://") and not - config_url.startswith("https://")): + if (not config_url.startswith("http://") and + not config_url.startswith("https://")): raise exception.InvalidLibConfURL(config_url) result = get_api_result("/lib/register", data=dict(config_url=config_url)) if "message" in result and result['message']: - click.secho(result['message'], fg="green" if "successed" in result and - result['successed'] else "red") + click.secho( + result['message'], + fg="green" + if "successed" in result and result['successed'] else "red") diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 53fc96de..56dab189 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -21,11 +21,11 @@ from time import time import click -from platformio import __version__, app, exception, telemetry, util +from platformio import __version__, exception, telemetry, util from platformio.commands.lib import lib_install as cmd_lib_install from platformio.commands.platform import \ platform_install as cmd_platform_install -from platformio.libmanager import LibraryManager +from platformio.managers.lib import LibraryManager from platformio.managers.platform import PlatformFactory @@ -188,8 +188,8 @@ class EnvironmentProcessor(object): # install dependent libraries if "lib_install" in self.options: - _autoinstall_libs(self.cmd_ctx, self.options['lib_install']) - + _autoinstall_libs(self.cmd_ctx, self.options['lib_install'], + self.verbose) try: p = PlatformFactory.newPlatform(self.options['platform']) @@ -201,22 +201,15 @@ class EnvironmentProcessor(object): return p.run(build_vars, build_targets, self.verbose) -def _autoinstall_libs(ctx, libids_list): - require_libs = [int(l.strip()) for l in libids_list.split(",")] - installed_libs = [ - l['id'] for l in LibraryManager().get_installed().values() - ] - - not_intalled_libs = set(require_libs) - set(installed_libs) - if not require_libs or not not_intalled_libs: - return - - if (not app.get_setting("enable_prompts") or - click.confirm( - "The libraries with IDs '%s' have not been installed yet. " - "Would you like to install them now?" % - ", ".join([str(i) for i in not_intalled_libs]))): - ctx.invoke(cmd_lib_install, libid=not_intalled_libs) +def _autoinstall_libs(ctx, libids_list, verbose=False): + storage_dir = util.get_projectlibdeps_dir() + ctx.obj = LibraryManager(storage_dir) + if verbose: + click.echo("Library Storage: " + storage_dir) + ctx.invoke( + cmd_lib_install, + libraries=[int(l.strip()) for l in libids_list.split(",")], + quiet=not verbose) def _clean_pioenvs_dir(pioenvs_dir): diff --git a/platformio/exception.py b/platformio/exception.py index 197ec0f9..c05d23d0 100644 --- a/platformio/exception.py +++ b/platformio/exception.py @@ -146,18 +146,9 @@ class APIRequestError(PlatformioException): MESSAGE = "[API] {0}" -class LibAlreadyInstalled(PlatformioException): - pass +class LibNotFound(PlatformioException): - -class LibNotInstalled(PlatformioException): - - MESSAGE = "Library #{0:d} has not been installed yet" - - -class LibInstallDependencyError(PlatformioException): - - MESSAGE = "Error has been occurred for library dependency '{0}'" + MESSAGE = "Library `{0}` has not been found in the registry" class InvalidLibConfURL(PlatformioException): diff --git a/platformio/libmanager.py b/platformio/libmanager.py deleted file mode 100644 index 8235d102..00000000 --- a/platformio/libmanager.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright 2014-2016 Ivan Kravets -# -# 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. - -import re -from os import listdir, makedirs, remove, rename -from os.path import isdir, isfile, join -from shutil import rmtree -from tempfile import gettempdir - -from platformio import telemetry, util -from platformio.downloader import FileDownloader -from platformio.exception import LibAlreadyInstalled, LibNotInstalled -from platformio.unpacker import FileUnpacker - - -class LibraryManager(object): - - CONFIG_NAME = ".library.json" - - def __init__(self, lib_dir=None): - self.lib_dir = lib_dir or join(util.get_home_dir(), "lib") - - @staticmethod - def download(url, dest_dir): - fd = FileDownloader(url, dest_dir) - fd.start() - return fd.get_filepath() - - @staticmethod - def unpack(pkgpath, dest_dir): - fu = FileUnpacker(pkgpath, dest_dir) - return fu.start() - - def get_installed(self): - items = {} - if not isdir(self.lib_dir): - return items - for dirname in sorted(listdir(self.lib_dir)): - conf_path = join(self.lib_dir, dirname, self.CONFIG_NAME) - if not isfile(conf_path): - continue - items[dirname] = util.load_json(conf_path) - return items - - def get_latest_versions(self): - lib_ids = [str(item['id']) for item in self.get_installed().values()] - if not lib_ids: - return None - return util.get_api_result("/lib/version/" + str(",".join(lib_ids))) - - def get_outdated(self): - outdated = [] - for id_, latest_version in (self.get_latest_versions() or {}).items(): - info = self.get_info(int(id_)) - if latest_version != info['version']: - outdated.append(info['name']) - return outdated - - def get_info(self, id_): - for item in self.get_installed().values(): - if "id" in item and item['id'] == id_: - return item - raise LibNotInstalled(id_) - - def is_installed(self, id_): - try: - return int(self.get_info(id_)['id']) == id_ - except LibNotInstalled: - return False - - def install(self, id_, version=None): - if self.is_installed(id_): - raise LibAlreadyInstalled() - - dlinfo = util.get_api_result( - "/lib/download/" + str(id_), - dict(version=version) if version else None - ) - dlpath = None - tmplib_dir = join(self.lib_dir, str(id_)) - try: - dlpath = self.download(dlinfo['url'], gettempdir()) - if not isdir(tmplib_dir): - makedirs(tmplib_dir) - self.unpack(dlpath, tmplib_dir) - finally: - if dlpath: - remove(dlpath) - - info = self.get_info(id_) - rename(tmplib_dir, join(self.lib_dir, "%s_ID%d" % ( - re.sub(r"[^\da-zA-Z]+", "_", info['name']), id_))) - - telemetry.on_event( - category="LibraryManager", action="Install", - label="#%d %s" % (id_, info['name']) - ) - - return True - - def uninstall(self, id_): - for libdir, item in self.get_installed().iteritems(): - if "id" in item and item['id'] == id_: - rmtree(join(self.lib_dir, libdir)) - telemetry.on_event( - category="LibraryManager", action="Uninstall", - label="#%d %s" % (id_, item['name']) - ) - return True - raise LibNotInstalled(id_) diff --git a/platformio/maintenance.py b/platformio/maintenance.py index ccea3cd1..2f7d66d1 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -22,12 +22,12 @@ import click import semantic_version from platformio import __version__, app, exception, telemetry, util -from platformio.commands.lib import lib_update as cmd_libraries_update +from platformio.commands.lib import lib_update as cmd_lib_update from platformio.commands.platform import \ platform_install as cmd_platform_install from platformio.commands.platform import platform_update as cmd_platform_update from platformio.commands.upgrade import get_latest_version -from platformio.libmanager import LibraryManager +from platformio.managers.lib import LibraryManager from platformio.managers.platform import PlatformManager @@ -221,16 +221,12 @@ def check_internal_updates(ctx, what): last_check[what + '_update'] = int(time()) app.set_state_item("last_check", last_check) + pm = PlatformManager() if what == "platforms" else LibraryManager() outdated_items = [] - if what == "platforms": - pm = PlatformManager() - for manifest in pm.get_installed(): - if manifest['name'] not in outdated_items and \ - pm.is_outdated(manifest['name']): - outdated_items.append(manifest['name']) - elif what == "libraries": - lm = LibraryManager() - outdated_items = lm.get_outdated() + for manifest in pm.get_installed(): + if manifest['name'] not in outdated_items and \ + pm.is_outdated(manifest['name']): + outdated_items.append(manifest['name']) if not outdated_items: return @@ -245,19 +241,26 @@ def check_internal_updates(ctx, what): if not app.get_setting("auto_update_" + what): click.secho("Please update them via ", fg="yellow", nl=False) click.secho("`platformio %s update`" % - ("lib" if what == "libraries" else "platform"), + ("lib --global" if what == "libraries" else "platform"), + fg="cyan", nl=False) + click.secho(" command.\n", fg="yellow") + click.secho("If you want to manually check for the new versions " + "without updating, please use ", fg="yellow", nl=False) + click.secho("`platformio %s update --only-check`" % + ("lib --global" if what == "libraries" else "platform"), fg="cyan", nl=False) click.secho(" command.", fg="yellow") else: click.secho("Please wait while updating %s ..." % what, fg="yellow") if what == "platforms": - ctx.invoke(cmd_platform_update) + ctx.invoke(cmd_platform_update, platforms=outdated_items) elif what == "libraries": - ctx.invoke(cmd_libraries_update) + ctx.obj = pm + ctx.invoke(cmd_lib_update, libraries=outdated_items) click.echo() - telemetry.on_event(category="Auto", action="Update", - label=what.title()) + telemetry.on_event( + category="Auto", action="Update", label=what.title()) click.echo("*" * terminal_width) click.echo("") diff --git a/platformio/managers/lib.py b/platformio/managers/lib.py new file mode 100644 index 00000000..7a1fd221 --- /dev/null +++ b/platformio/managers/lib.py @@ -0,0 +1,209 @@ +# Copyright 2014-present Ivan Kravets +# +# 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. + +import json +from os.path import join + +import click +import semantic_version + +from platformio import app, commands, exception, util +from platformio.managers.package import BasePkgManager + + +class LibraryManager(BasePkgManager): + + def __init__(self, package_dir=None): + if not package_dir: + package_dir = join(util.get_home_dir(), "lib") + BasePkgManager.__init__(self, package_dir) + + @property + def manifest_name(self): + return ".library.json" + + @staticmethod + def max_satisfying_repo_version(versions, requirements=None): + + def _cmp_dates(datestr1, datestr2): + from datetime import datetime + assert "T" in datestr1 and "T" in datestr2 + dateformat = "%Y-%m-%d %H:%M:%S" + date1 = datetime.strptime(datestr1[:-1].replace("T", " "), + dateformat) + date2 = datetime.strptime(datestr2[:-1].replace("T", " "), + dateformat) + if date1 == date2: + return 0 + return -1 if date1 < date2 else 1 + + item = None + reqspec = None + if requirements: + try: + reqspec = semantic_version.Spec(requirements) + except ValueError: + pass + for v in versions: + specver = None + try: + specver = semantic_version.Version(v['version'], partial=True) + except ValueError: + pass + + if reqspec: + if not specver or specver not in reqspec: + continue + if not item or semantic_version.Version( + item['version'], partial=True) < specver: + item = v + elif requirements: + if requirements == v['version']: + return v + else: + if not item or _cmp_dates(item['date'], v['date']) == -1: + item = v + return item + + def get_latest_repo_version(self, name, requirements): + item = self.max_satisfying_repo_version( + util.get_api_result("/lib/versions/%d" % self._get_pkg_id_by_name( + name, requirements)), requirements) + return item['version'] if item else None + + def _get_pkg_id_by_name(self, name, requirements, quiet=False): + if name.startswith("id="): + return int(name[3:]) + # try to find ID from installed packages + installed_dir = self.get_installed_dir(name, requirements) + if installed_dir: + manifest = self.load_manifest(installed_dir) + if "id" in manifest: + return int(manifest['id']) + return int(self.search_for_library({"name": name}, quiet)['id']) + + def _install_from_piorepo(self, name, requirements): + assert name.startswith("id=") + version = self.get_latest_repo_version(name, requirements) + if not version: + raise exception.UndefinedPackageVersion(requirements or "latest", + util.get_systype()) + dl_data = util.get_api_result( + "/lib/download/" + str(name[3:]), dict(version=version)) + assert dl_data + pkg_dir = None + try: + pkg_dir = self._install_from_url( + name, dl_data['url'].replace("http://", "https://"), + requirements) + except exception.APIRequestError: + pkg_dir = self._install_from_url(name, dl_data['url'], + requirements) + return pkg_dir + + def install(self, name, requirements=None, quiet=False, + trigger_event=True): + _name, _requirements, _url = self.parse_pkg_name(name, requirements) + if not _url: + _name = "id=%d" % self._get_pkg_id_by_name( + _name, _requirements, quiet=quiet) + already_installed = self.get_installed_dir(_name, _requirements, _url) + pkg_dir = BasePkgManager.install(self, _name if not _url else name, + _requirements, quiet, trigger_event) + + if already_installed: + return + + manifest = self.load_manifest(pkg_dir) + if "dependencies" not in manifest: + return pkg_dir + + if not quiet: + click.secho("Installing dependencies", fg="yellow") + + _dependencies = manifest['dependencies'] + if not isinstance(_dependencies, list): + _dependencies = [_dependencies] + for filters in _dependencies: + assert "name" in filters + if any([s in filters.get("version", "") for s in ("\\", "/")]): + self.install("{name}={version}".format(**filters)) + else: + lib_info = self.search_for_library(filters, quiet) + if filters.get("version"): + self.install( + lib_info['id'], + requirements=filters.get("version"), + quiet=quiet, + trigger_event=trigger_event) + else: + self.install( + lib_info['id'], + quiet=quiet, + trigger_event=trigger_event) + return pkg_dir + + @staticmethod + def search_for_library( # pylint: disable=too-many-branches + filters, quiet=False): + assert isinstance(filters, dict) + assert "name" in filters + if not quiet: + click.echo("Looking for %s library in registry" % click.style( + filters['name'], fg="cyan")) + query = [] + for key in filters: + if key not in ("name", "authors", "frameworks", "platforms"): + continue + values = filters[key] + if not isinstance(values, list): + values = [v.strip() for v in values.split(",") if v] + for value in values: + query.append('%s:"%s"' % (key[:-1] if key.endswith("s") else + key, value)) + + lib_info = None + result = util.get_api_result( + "/lib/search", dict(query=" ".join(query))) + if result['total'] == 1: + lib_info = result['items'][0] + elif result['total'] > 1: + click.secho( + "Conflict: More than one library has been found " + "by request %s:" % json.dumps(filters), + fg="red") + commands.lib.echo_liblist_header() + for item in result['items']: + commands.lib.echo_liblist_item(item) + + if not app.get_setting("enable_prompts"): + click.echo("Automatically chose the first available library") + lib_info = result['items'][0] + else: + deplib_id = click.prompt( + "Please choose library ID", + type=click.Choice([str(i['id']) for i in result['items']])) + for item in result['items']: + if item['id'] == int(deplib_id): + lib_info = item + break + + if not lib_info: + raise exception.LibNotFound(str(filters)) + if not quiet: + click.echo("Found: %s" % click.style( + "http://platformio.org/lib/show/{id}/{name}".format( + **lib_info), + fg="blue")) + return lib_info diff --git a/platformio/managers/package.py b/platformio/managers/package.py index 45e3e174..ac481866 100644 --- a/platformio/managers/package.py +++ b/platformio/managers/package.py @@ -312,7 +312,7 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): if "=" in text and not text.startswith("id="): name, url = text.split("=", 1) - # Handle GitHub URL (https://github.com/user/package.git) + # Handle GitHub URL (https://github.com/user/package) if url.startswith("https://github.com/") and \ not url.endswith((".zip", ".tar.gz")): url = "git+" + url @@ -394,6 +394,20 @@ class BasePkgManager(PkgRepoMixin, PkgInstallerMixin): return best.get("__pkg_dir") return None + def is_outdated(self, name, requirements=None): + installed_dir = self.get_installed_dir(name, requirements) + if not installed_dir: + click.secho( + "%s @ %s is not installed" % (name, requirements or "*"), + fg="yellow") + return + manifest_path = self.get_manifest_path(installed_dir) + if manifest_path.endswith(self.VCS_MANIFEST_NAME): + return False + manifest = self.load_manifest(installed_dir) + return manifest['version'] != self.get_latest_repo_version( + name, requirements) + def install(self, name, requirements=None, quiet=False, trigger_event=True): name, requirements, url = self.parse_pkg_name(name, requirements) diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index 2a485f07..9855746c 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -71,9 +71,10 @@ class PlatformManager(BasePkgManager): return True def is_outdated(self, name, requirements=None): + if BasePkgManager.is_outdated(self, name, requirements): + return True p = PlatformFactory.newPlatform(name, requirements) - return (p.are_outdated_packages() or - p.version != self.get_latest_repo_version(name, requirements)) + return p.are_outdated_packages() def cleanup_packages(self, names): self.reset_cache() diff --git a/platformio/vcsclient.py b/platformio/vcsclient.py index fffd6792..da0f9316 100644 --- a/platformio/vcsclient.py +++ b/platformio/vcsclient.py @@ -43,10 +43,10 @@ class VCSClientBase(object): command = None - def __init__(self, src_dir, remote_url=None, branch=None): + def __init__(self, src_dir, remote_url=None, tag=None): self.src_dir = src_dir self.remote_url = remote_url - self.branch = branch + self.tag = tag self.check_client() def check_client(self): @@ -71,7 +71,7 @@ class VCSClientBase(object): @property def can_be_updated(self): - return not self.branch + return not self.tag def get_current_revision(self): raise NotImplementedError @@ -113,19 +113,19 @@ class GitClient(VCSClientBase): @property def can_be_updated(self): - return not self.branch or not self.is_commit_id(self.branch) + return not self.tag or not self.is_commit_id(self.tag) def export(self): - is_commit = self.is_commit_id(self.branch) + is_commit = self.is_commit_id(self.tag) args = ["clone", "--recursive"] - if not self.branch or not is_commit: + if not self.tag or not is_commit: args += ["--depth", "1"] - if self.branch: - args += ["--branch", self.branch] + if self.tag: + args += ["--branch", self.tag] args += [self.remote_url, self.src_dir] assert self.run_cmd(args) if is_commit: - return self.run_cmd(["reset", "--hard", self.branch]) + return self.run_cmd(["reset", "--hard", self.tag]) return True def update(self): @@ -142,8 +142,8 @@ class HgClient(VCSClientBase): def export(self): args = ["clone"] - if self.branch: - args.extend(["--updaterev", self.branch]) + if self.tag: + args.extend(["--updaterev", self.tag]) args.extend([self.remote_url, self.src_dir]) return self.run_cmd(args) @@ -161,8 +161,8 @@ class SvnClient(VCSClientBase): def export(self): args = ["checkout"] - if self.branch: - args.extend(["--revision", self.branch]) + if self.tag: + args.extend(["--revision", self.tag]) args.extend([self.remote_url, self.src_dir]) return self.run_cmd(args) diff --git a/tests/commands/test_boards.py b/tests/commands/test_boards.py index 1a2539fd..be537c15 100644 --- a/tests/commands/test_boards.py +++ b/tests/commands/test_boards.py @@ -14,10 +14,8 @@ import json -from platformio import util from platformio.commands.boards import cli as cmd_boards -from platformio.commands.platform import \ - platform_search as cmd_platform_search +from platformio.commands.platform import platform_search as cmd_platform_search def test_board_json_output(platformio_setup, clirunner, validate_cliresult): diff --git a/tests/commands/test_init.py b/tests/commands/test_init.py index 45c23ed5..1605bba0 100644 --- a/tests/commands/test_init.py +++ b/tests/commands/test_init.py @@ -13,12 +13,12 @@ # limitations under the License. import json -from os import makedirs, getcwd +from os import getcwd, makedirs from os.path import getsize, isdir, isfile, join -from platformio.commands.init import cli -from platformio.commands.boards import cli as cmd_boards from platformio import util +from platformio.commands.boards import cli as cmd_boards +from platformio.commands.init import cli def validate_pioproject(pioproject_dir): diff --git a/tests/commands/test_lib.py b/tests/commands/test_lib.py index e749a68c..220ff632 100644 --- a/tests/commands/test_lib.py +++ b/tests/commands/test_lib.py @@ -12,25 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from os import listdir -from os.path import isdir, isfile, join - import re from platformio.commands.lib import cli -from platformio import util -def validate_libfolder(): - libs_path = util.get_lib_dir() - installed_libs = listdir(libs_path) - for lib in installed_libs: - assert isdir(join(libs_path, lib)) - assert isfile(join(libs_path, lib, ".library.json")) and isfile( - join(libs_path, lib, "library.json")) - - -def test_lib_search(clirunner, validate_cliresult): +def test_search(clirunner, validate_cliresult): result = clirunner.invoke(cli, ["search", "DHT22"]) validate_cliresult(result) match = re.search(r"Found\s+(\d+)\slibraries:", result.output) @@ -42,34 +29,70 @@ def test_lib_search(clirunner, validate_cliresult): assert int(match.group(1)) == 1 -def test_lib_install(clirunner, validate_cliresult): - result = clirunner.invoke(cli, ["install", "58", "115"]) +def test_global_install_registry(clirunner, validate_cliresult, + isolated_pio_home): + result = clirunner.invoke( + cli, ["-g", "install", "58", "OneWire", "Json@5.4.0", "Json@>5.4"]) validate_cliresult(result) - validate_libfolder() + items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] + items2 = ["DHT22_ID58", "Json_ID64", "Json_ID64@5.4.0", "OneWire_ID1"] + assert set(items1) == set(items2) -def test_lib_list(clirunner, validate_cliresult): - result = clirunner.invoke(cli, ["list"]) +def test_global_install_repository(clirunner, validate_cliresult, + isolated_pio_home): + result = clirunner.invoke( + cli, ["-g", "install", "https://github.com/gioblu/PJON.git#3.0", + "https://developer.mbed.org/users/simon/code/TextLCD/", + "http://dl.platformio.org/libraries/archives/3/3756.tar.gz", + "knolleary/pubsubclient"]) validate_cliresult(result) - assert "58" in result.output and "115" in result.output + items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] + items2 = ["PJON", "TextLCD", "ESPAsyncTCP", "PubSubClient"] + assert set(items2) & set(items1) -def test_lib_show(clirunner, validate_cliresult): - result = clirunner.invoke(cli, ["show", "115"]) +def test_global_lib_list(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli, ["-g", "list"]) validate_cliresult(result) - assert "arduino" in result.output and "atmelavr" in result.output + assert all([n in result.output for n in ("OneWire", "DHT22", "64")]) - result = clirunner.invoke(cli, ["show", "58"]) + result = clirunner.invoke(cli, ["-g", "list", "--json-output"]) validate_cliresult(result) - assert "energia" in result.output and "timsp430" in result.output + assert all( + [n in result.output + for n in ("PJON", + "https://developer.mbed.org/users/simon/code/TextLCD/")]) -def test_lib_update(clirunner, validate_cliresult): - result = clirunner.invoke(cli, ["update"]) +def test_global_lib_show(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli, ["-g", "show", "64@5.4.0"]) validate_cliresult(result) - assert "58" in result.output and "115" in result.output + assert all( + [s in result.output for s in ("Json", "arduino", "atmelavr", "5.4.0")]) - -def test_lib_uninstall(clirunner, validate_cliresult): - result = clirunner.invoke(cli, ["uninstall", "58", "115"]) + result = clirunner.invoke(cli, ["-g", "show", "Json@>5.4.0"]) validate_cliresult(result) + assert all([s in result.output for s in ("Json", "arduino", "atmelavr")]) + assert "5.4.0" not in result.output + + result = clirunner.invoke(cli, ["-g", "show", "1"]) + validate_cliresult(result) + assert "OneWire" in result.output + + +def test_global_lib_update(clirunner, validate_cliresult, isolated_pio_home): + result = clirunner.invoke(cli, ["-g", "update"]) + validate_cliresult(result) + assert all([s in result.output for s in ("Up-to-date", "Checking")]) + + +def test_global_lib_uninstall(clirunner, validate_cliresult, + isolated_pio_home): + result = clirunner.invoke( + cli, ["-g", "uninstall", "1", "Json@!=5.4.0", "TextLCD"]) + validate_cliresult(result) + items1 = [d.basename for d in isolated_pio_home.join("lib").listdir()] + items2 = ["DHT22_ID58", "Json_ID64@5.4.0", "ESPAsyncTCP_ID305", + "pubsubclient", "PJON"] + assert set(items1) == set(items2) diff --git a/tests/commands/test_platform.py b/tests/commands/test_platform.py index bd96230e..2379ec16 100644 --- a/tests/commands/test_platform.py +++ b/tests/commands/test_platform.py @@ -16,8 +16,8 @@ import json import os from os.path import join -from platformio.commands import platform as cli_platform from platformio import exception, util +from platformio.commands import platform as cli_platform def test_list_json_output(clirunner, validate_cliresult): diff --git a/tests/commands/test_settings.py b/tests/commands/test_settings.py index d74c3ad8..b1403e39 100644 --- a/tests/commands/test_settings.py +++ b/tests/commands/test_settings.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from platformio.commands.settings import cli from platformio import app +from platformio.commands.settings import cli def test_settings_check(clirunner, validate_cliresult): diff --git a/tests/conftest.py b/tests/conftest.py index f4cdc110..ca5b70f9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright 2014-2016 Ivan Kravets +# Copyright 2014-present Ivan Kravets # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,29 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -from os import environ - -from click.testing import CliRunner +import os import pytest +from click.testing import CliRunner @pytest.fixture(scope="session") def platformio_setup(request): pioenvvars = ("ENABLE_PROMPTS", "ENABLE_TELEMETRY") for v in pioenvvars: - environ["PLATFORMIO_SETTING_%s" % v] = "No" + os.environ["PLATFORMIO_SETTING_%s" % v] = "No" def platformio_teardown(): for v in pioenvvars: _name = "PLATFORMIO_SETTING_%s" % v - if _name in environ: - del environ[_name] + if _name in os.environ: + del os.environ[_name] request.addfinalizer(platformio_teardown) -@pytest.fixture(scope="session") +@pytest.fixture(scope="module") def clirunner(): return CliRunner() @@ -46,3 +45,15 @@ def validate_cliresult(): assert not result.exception assert "error" not in result.output.lower() return decorator + + +@pytest.fixture(scope="module") +def isolated_pio_home(request, tmpdir_factory): + home_dir = tmpdir_factory.mktemp(".platformio") + os.environ['PLATFORMIO_HOME_DIR'] = str(home_dir) + + def fin(): + del os.environ['PLATFORMIO_HOME_DIR'] + + request.addfinalizer(fin) + return home_dir