You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2018/10/04 09:11:42 UTC

[GitHub] rymanluk closed pull request #106: newtmgr: Add "hci, i" option

rymanluk closed pull request #106: newtmgr: Add "hci, i" option
URL: https://github.com/apache/mynewt-newtmgr/pull/106
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/Gopkg.lock b/Gopkg.lock
index 1cc32576..a1b5ae23 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -4,8 +4,8 @@
 [[projects]]
   name = "github.com/Sirupsen/logrus"
   packages = ["."]
-  revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e"
-  version = "v1.0.3"
+  revision = "a67f783a3814b8729bd2dac5780b5f78f8dbd64d"
+  version = "v1.1.0"
 
 [[projects]]
   name = "github.com/cheggaaa/pb"
@@ -40,7 +40,7 @@
   branch = "master"
   name = "github.com/go-ble/ble"
   packages = [".","darwin","examples/lib/dev","linux","linux/adv","linux/att","linux/gatt","linux/hci","linux/hci/cmd","linux/hci/evt","linux/hci/socket"]
-  revision = "cb19fdfd5cb4f8c420bedd0c9e1bfc4717a4be2e"
+  revision = "e78417b510a348171f21754ff934fe8408b21b90"
 
 [[projects]]
   name = "github.com/inconshreveable/mousetrap"
@@ -56,9 +56,15 @@
 
 [[projects]]
   branch = "master"
+  name = "github.com/konsorten/go-windows-terminal-sequences"
+  packages = ["."]
+  revision = "b729f2633dfe35f4d1d8a32385f6685610ce1cb5"
+
+[[projects]]
   name = "github.com/kr/pretty"
   packages = ["."]
-  revision = "cfb55aafdaf3ec08f0db22699ab822c50091b1c4"
+  revision = "73f6ac0b30a98e433b289500d779f50c1a6f0712"
+  version = "v0.1.0"
 
 [[projects]]
   branch = "master"
@@ -129,8 +135,8 @@
 [[projects]]
   name = "github.com/spf13/cast"
   packages = ["."]
-  revision = "acbeb36b902d72a7a4c18e8f3241075e7ab763e4"
-  version = "v1.1.0"
+  revision = "8965335b8c7107321228e3e3702cab9832751bac"
+  version = "v1.2.0"
 
 [[projects]]
   branch = "master"
@@ -147,8 +153,8 @@
 [[projects]]
   name = "github.com/spf13/pflag"
   packages = ["."]
-  revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
-  version = "v1.0.0"
+  revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
+  version = "v1.0.3"
 
 [[projects]]
   branch = "master"
@@ -190,17 +196,18 @@
   name = "gopkg.in/fsnotify.v1"
   packages = ["."]
   revision = "629574ca2a5df945712d3079857300b5e4da0236"
+  source = "https://github.com/fsnotify/fsnotify.git"
   version = "v1.4.2"
 
 [[projects]]
   branch = "master"
   name = "mynewt.apache.org/newt"
   packages = ["util","util/unixchild","viper","yaml"]
-  revision = "773413552ff0e4e7d5a04c526da089a33c21680f"
+  revision = "757fadf0338039637436ee990f55ec12d48e9439"
 
 [solve-meta]
   analyzer-name = "dep"
   analyzer-version = 1
-  inputs-digest = "e2cc5a4fab95a5eccf8d614680b609c21280660ed87513eacbda6f9d0072b9c8"
+  inputs-digest = "214d5c29d58ea2f019ab38724d7b4211b816f30df75d00960a2ffecab6abe2f9"
   solver-name = "gps-cdcl"
   solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
index 81152be6..666ebe8d 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -27,7 +27,7 @@
 
 [[constraint]]
   branch = "master"
-  name = "github.com/currantlabs/ble"
+  name = "github.com/go-ble/ble"
 
 [[constraint]]
   name = "github.com/fatih/structs"
diff --git a/newtmgr/bll/bll_xport.go b/newtmgr/bll/bll_xport.go
index 06c9b337..ea039944 100644
--- a/newtmgr/bll/bll_xport.go
+++ b/newtmgr/bll/bll_xport.go
@@ -23,10 +23,8 @@ package bll
 
 import (
 	"fmt"
-
 	"github.com/go-ble/ble"
 	"github.com/go-ble/ble/examples/lib/dev"
-
 	"mynewt.apache.org/newtmgr/nmxact/bledefs"
 	"mynewt.apache.org/newtmgr/nmxact/sesn"
 )
@@ -44,11 +42,13 @@ func NewXportCfg() XportCfg {
 
 type BllXport struct {
 	cfg XportCfg
+	hciIdx	int
 }
 
-func NewBllXport(cfg XportCfg) *BllXport {
+func NewBllXport(cfg XportCfg, hciIdx int) *BllXport {
 	return &BllXport{
 		cfg: cfg,
+		hciIdx: hciIdx,
 	}
 }
 
@@ -62,9 +62,9 @@ func (bx *BllXport) BuildBllSesn(cfg BllSesnCfg) (sesn.Sesn, error) {
 }
 
 func (bx *BllXport) Start() error {
-	d, err := dev.NewDevice(bx.cfg.CtlrName)
+	d, err := dev.NewDevice(bx.cfg.CtlrName, ble.OptDeviceID(bx.hciIdx))
 	if err != nil {
-		return err
+		return fmt.Errorf("[hci%d]: %s", bx.hciIdx, err)
 	}
 
 	// Set the connection parameters to use for all initiated connections.
diff --git a/newtmgr/bll/bll_xport_linux.go b/newtmgr/bll/bll_xport_linux.go
index a4174ec8..e9162fd1 100644
--- a/newtmgr/bll/bll_xport_linux.go
+++ b/newtmgr/bll/bll_xport_linux.go
@@ -24,7 +24,6 @@ package bll
 import (
 	"github.com/go-ble/ble"
 	"github.com/go-ble/ble/linux"
-	"github.com/go-ble/ble/linux/hci"
 	"github.com/go-ble/ble/linux/hci/cmd"
 
 	"mynewt.apache.org/newt/util"
@@ -51,7 +50,7 @@ func BllXportSetConnParams(dev ble.Device, ownAddrType bledefs.BleAddrType) erro
 		PeerAddress:     [6]byte{}, //
 	}
 
-	opt := hci.OptConnParams(cc)
+	opt := ble.OptConnParams(cc)
 	if err := ldev.HCI.Option(opt); err != nil {
 		return util.FmtNewtError("error setting connection parameters: %s",
 			err.Error())
diff --git a/newtmgr/cli/commands.go b/newtmgr/cli/commands.go
index 0c30c5bd..5bfebbe6 100644
--- a/newtmgr/cli/commands.go
+++ b/newtmgr/cli/commands.go
@@ -95,6 +95,9 @@ func Commands() *cobra.Command {
 	}
 	nmCmd.AddCommand(versCmd)
 
+	nmCmd.PersistentFlags().IntVarP(&nmutil.HciIdx, "hci", "i",
+		0, "HCI index for the controller on Linux machine")
+
 	nmCmd.AddCommand(crashCmd())
 	nmCmd.AddCommand(dateTimeCmd())
 	nmCmd.AddCommand(fsCmd())
diff --git a/newtmgr/cli/common.go b/newtmgr/cli/common.go
index 6e6ad49c..30512188 100644
--- a/newtmgr/cli/common.go
+++ b/newtmgr/cli/common.go
@@ -131,7 +131,7 @@ func GetXport() (xport.Xport, error) {
 			cfg.CtlrName = bc.CtlrName
 		}
 		cfg.OwnAddrType = bc.OwnAddrType
-		globalXport = bll.NewBllXport(cfg)
+		globalXport = bll.NewBllXport(cfg, bc.HciIdx)
 
 	case config.CONN_TYPE_BLE_PLAIN, config.CONN_TYPE_BLE_OIC:
 		bc, err := config.ParseBleConnString(cp.ConnString)
@@ -261,16 +261,16 @@ func buildBllSesn(cp *config.ConnProfile) (sesn.Sesn, error) {
 		return nil, err
 	}
 
-	x, err := GetXport()
+	sc, err := config.BuildBllSesnCfg(bc)
 	if err != nil {
 		return nil, err
 	}
-	bx := x.(*bll.BllXport)
 
-	sc, err := config.BuildBllSesnCfg(bc)
+	x, err := GetXport()
 	if err != nil {
 		return nil, err
 	}
+	bx := x.(*bll.BllXport)
 
 	switch cp.Type {
 	case config.CONN_TYPE_BLL_PLAIN:
diff --git a/newtmgr/config/ble_config.go b/newtmgr/config/ble_config.go
index 82e7d163..142b1775 100644
--- a/newtmgr/config/ble_config.go
+++ b/newtmgr/config/ble_config.go
@@ -45,6 +45,8 @@ type BleConfig struct {
 
 	BlehostdPath   string
 	ControllerPath string
+
+	HciIdx int
 }
 
 func NewBleConfig() *BleConfig {
@@ -109,6 +111,8 @@ func ParseBleConnString(cs string) (*BleConfig, error) {
 		}
 	}
 
+	bc.HciIdx = nmutil.HciIdx
+
 	return bc, nil
 }
 
diff --git a/newtmgr/config/bll_config.go b/newtmgr/config/bll_config.go
index 070d9ffd..a507761c 100644
--- a/newtmgr/config/bll_config.go
+++ b/newtmgr/config/bll_config.go
@@ -43,6 +43,8 @@ type BllConfig struct {
 
 	// Connection timeout, in seconds.
 	ConnTimeout float64
+
+	HciIdx int
 }
 
 func NewBllConfig() *BllConfig {
@@ -99,6 +101,8 @@ func ParseBllConnString(cs string) (*BllConfig, error) {
 		}
 	}
 
+	bc.HciIdx = nmutil.HciIdx
+
 	return bc, nil
 }
 
diff --git a/newtmgr/nmutil/nmutil.go b/newtmgr/nmutil/nmutil.go
index 910dd77b..908d7b05 100644
--- a/newtmgr/nmutil/nmutil.go
+++ b/newtmgr/nmutil/nmutil.go
@@ -44,6 +44,7 @@ var ConnType string
 var ConnString string
 var ConnExtra string
 var ToolInfo ToolInfoType
+var HciIdx int
 
 func TxOptions() sesn.TxOptions {
 	return sesn.TxOptions{
diff --git a/vendor/github.com/Sirupsen/logrus/.travis.yml b/vendor/github.com/Sirupsen/logrus/.travis.yml
index a23296a5..1f953beb 100644
--- a/vendor/github.com/Sirupsen/logrus/.travis.yml
+++ b/vendor/github.com/Sirupsen/logrus/.travis.yml
@@ -1,15 +1,51 @@
 language: go
-go:
-  - 1.6.x
-  - 1.7.x
-  - 1.8.x
-  - tip
 env:
   - GOMAXPROCS=4 GORACE=halt_on_error=1
-install:
-  - go get github.com/stretchr/testify/assert
-  - go get gopkg.in/gemnasium/logrus-airbrake-hook.v2
-  - go get golang.org/x/sys/unix
-  - go get golang.org/x/sys/windows
-script:
-  - go test -race -v ./...
+matrix:
+  include:
+    - go: 1.10.x
+      install:
+        - go get github.com/stretchr/testify/assert
+        - go get golang.org/x/crypto/ssh/terminal
+        - go get golang.org/x/sys/unix
+        - go get golang.org/x/sys/windows
+      script:
+        - go test -race -v ./...
+    - go: 1.11.x
+      env: GO111MODULE=on
+      install:
+        - go mod download
+      script:
+        - go test -race -v ./...
+    - go: 1.11.x
+      env: GO111MODULE=off
+      install:
+        - go get github.com/stretchr/testify/assert
+        - go get golang.org/x/crypto/ssh/terminal
+        - go get golang.org/x/sys/unix
+        - go get golang.org/x/sys/windows
+      script:
+        - go test -race -v ./...
+    - go: 1.10.x
+      install:
+        - go get github.com/stretchr/testify/assert
+        - go get golang.org/x/crypto/ssh/terminal
+        - go get golang.org/x/sys/unix
+        - go get golang.org/x/sys/windows
+      script:
+        - go test -race -v -tags appengine ./...
+    - go: 1.11.x
+      env: GO111MODULE=on
+      install:
+        - go mod download
+      script:
+        - go test -race -v -tags appengine ./...
+    - go: 1.11.x
+      env: GO111MODULE=off
+      install:
+        - go get github.com/stretchr/testify/assert
+        - go get golang.org/x/crypto/ssh/terminal
+        - go get golang.org/x/sys/unix
+        - go get golang.org/x/sys/windows
+      script:
+        - go test -race -v -tags appengine ./...
diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
index 8236d8b6..17026960 100644
--- a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
+++ b/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
@@ -1,3 +1,43 @@
+# 1.1.0
+This new release introduces:
+  * several fixes:
+    * a fix for a race condition on entry formatting
+    * proper cleanup of previously used entries before putting them back in the pool
+    * the extra new line at the end of message in text formatter has been removed
+  * a new global public API to check if a level is activated: IsLevelEnabled
+  * the following methods have been added to the Logger object
+    * IsLevelEnabled
+    * SetFormatter
+    * SetOutput
+    * ReplaceHooks
+  * introduction of go module
+  * an indent configuration for the json formatter
+  * output colour support for windows
+  * the field sort function is now configurable for text formatter
+  * the CLICOLOR and CLICOLOR\_FORCE environment variable support in text formater
+
+# 1.0.6
+
+This new release introduces:
+  * a new api WithTime which allows to easily force the time of the log entry
+    which is mostly useful for logger wrapper
+  * a fix reverting the immutability of the entry given as parameter to the hooks
+    a new configuration field of the json formatter in order to put all the fields
+    in a nested dictionnary
+  * a new SetOutput method in the Logger
+  * a new configuration of the textformatter to configure the name of the default keys
+  * a new configuration of the text formatter to disable the level truncation
+
+# 1.0.5
+
+* Fix hooks race (#707)
+* Fix panic deadlock (#695)
+
+# 1.0.4
+
+* Fix race when adding hooks (#612)
+* Fix terminal check in AppEngine (#635)
+
 # 1.0.3
 
 * Replace example files with testable examples
diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/Sirupsen/logrus/README.md
index 4f5ce576..072e99be 100644
--- a/vendor/github.com/Sirupsen/logrus/README.md
+++ b/vendor/github.com/Sirupsen/logrus/README.md
@@ -220,7 +220,7 @@ Logrus comes with [built-in hooks](hooks/). Add those, or your custom hook, in
 ```go
 import (
   log "github.com/sirupsen/logrus"
-  "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
+  "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
   logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
   "log/syslog"
 )
@@ -241,54 +241,8 @@ func init() {
 ```
 Note: Syslog hook also support connecting to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). For the detail, please check the [syslog hook README](hooks/syslog/README.md).
 
-| Hook  | Description |
-| ----- | ----------- |
-| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
-| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
-| [Amazon Kinesis](https://github.com/evalphobia/logrus_kinesis) | Hook for logging to [Amazon Kinesis](https://aws.amazon.com/kinesis/) |
-| [Amqp-Hook](https://github.com/vladoatanasov/logrus_amqp) | Hook for logging to Amqp broker (Like RabbitMQ) |
-| [Bugsnag](https://github.com/Shopify/logrus-bugsnag/blob/master/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
-| [DeferPanic](https://github.com/deferpanic/dp-logrus) | Hook for logging to DeferPanic |
-| [Discordrus](https://github.com/kz/discordrus) | Hook for logging to [Discord](https://discordapp.com/) |
-| [ElasticSearch](https://github.com/sohlich/elogrus) | Hook for logging to ElasticSearch|
-| [Firehose](https://github.com/beaubrewer/logrus_firehose) | Hook for logging to [Amazon Firehose](https://aws.amazon.com/kinesis/firehose/)
-| [Fluentd](https://github.com/evalphobia/logrus_fluent) | Hook for logging to fluentd |
-| [Go-Slack](https://github.com/multiplay/go-slack) | Hook for logging to [Slack](https://slack.com) |
-| [Graylog](https://github.com/gemnasium/logrus-graylog-hook) | Hook for logging to [Graylog](http://graylog2.org/) |
-| [Hiprus](https://github.com/nubo/hiprus) | Send errors to a channel in hipchat. |
-| [Honeybadger](https://github.com/agonzalezro/logrus_honeybadger) | Hook for sending exceptions to Honeybadger |
-| [InfluxDB](https://github.com/Abramovic/logrus_influxdb) | Hook for logging to influxdb |
-| [Influxus](http://github.com/vlad-doru/influxus) | Hook for concurrently logging to [InfluxDB](http://influxdata.com/) |
-| [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` |
-| [KafkaLogrus](https://github.com/goibibo/KafkaLogrus) | Hook for logging to kafka |
-| [LFShook](https://github.com/rifflock/lfshook) | Hook for logging to the local filesystem |
-| [Logentries](https://github.com/jcftang/logentriesrus) | Hook for logging to [Logentries](https://logentries.com/) |
-| [Logentrus](https://github.com/puddingfactory/logentrus) | Hook for logging to [Logentries](https://logentries.com/) |
-| [Logmatic.io](https://github.com/logmatic/logmatic-go) | Hook for logging to [Logmatic.io](http://logmatic.io/) |
-| [Logrusly](https://github.com/sebest/logrusly) | Send logs to [Loggly](https://www.loggly.com/) |
-| [Logstash](https://github.com/bshuster-repo/logrus-logstash-hook) | Hook for logging to [Logstash](https://www.elastic.co/products/logstash) |
-| [Mail](https://github.com/zbindenren/logrus_mail) | Hook for sending exceptions via mail |
-| [Mattermost](https://github.com/shuLhan/mattermost-integration/tree/master/hooks/logrus) | Hook for logging to [Mattermost](https://mattermost.com/) |
-| [Mongodb](https://github.com/weekface/mgorus) | Hook for logging to mongodb |
-| [NATS-Hook](https://github.com/rybit/nats_logrus_hook) | Hook for logging to [NATS](https://nats.io) |
-| [Octokit](https://github.com/dorajistyle/logrus-octokit-hook) | Hook for logging to github via octokit |
-| [Papertrail](https://github.com/polds/logrus-papertrail-hook) | Send errors to the [Papertrail](https://papertrailapp.com) hosted logging service via UDP. |
-| [PostgreSQL](https://github.com/gemnasium/logrus-postgresql-hook) | Send logs to [PostgreSQL](http://postgresql.org) |
-| [Pushover](https://github.com/toorop/logrus_pushover) | Send error via [Pushover](https://pushover.net) |
-| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) |
-| [Redis-Hook](https://github.com/rogierlommers/logrus-redis-hook) | Hook for logging to a ELK stack (through Redis) |
-| [Rollrus](https://github.com/heroku/rollrus) | Hook for sending errors to rollbar |
-| [Scribe](https://github.com/sagar8192/logrus-scribe-hook) | Hook for logging to [Scribe](https://github.com/facebookarchive/scribe)|
-| [Sentry](https://github.com/evalphobia/logrus_sentry) | Send errors to the Sentry error logging and aggregation service. |
-| [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. |
-| [Stackdriver](https://github.com/knq/sdhook) | Hook for logging to [Google Stackdriver](https://cloud.google.com/logging/) |
-| [Sumorus](https://github.com/doublefree/sumorus) | Hook for logging to [SumoLogic](https://www.sumologic.com/)|
-| [Syslog](https://github.com/sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
-| [Syslog TLS](https://github.com/shinji62/logrus-syslog-ng) | Send errors to remote syslog server with TLS support. |
-| [TraceView](https://github.com/evalphobia/logrus_appneta) | Hook for logging to [AppNeta TraceView](https://www.appneta.com/products/traceview/) |
-| [Typetalk](https://github.com/dragon3/logrus-typetalk-hook) | Hook for logging to [Typetalk](https://www.typetalk.in/) |
-| [logz.io](https://github.com/ripcurld00d/logrus-logzio-hook) | Hook for logging to [logz.io](https://logz.io), a Log as a Service using Logstash |
-| [SQS-Hook](https://github.com/tsarpaul/logrus_sqs) | Hook for logging to [Amazon Simple Queue Service (SQS)](https://aws.amazon.com/sqs/) |
+A list of currently known of service hook can be found in this wiki [page](https://github.com/sirupsen/logrus/wiki/Hooks)
+
 
 #### Level logging
 
@@ -366,13 +320,15 @@ The built-in logging formatters are:
     field to `true`.  To force no colored output even if there is a TTY  set the
     `DisableColors` field to `true`. For Windows, see
     [github.com/mattn/go-colorable](https://github.com/mattn/go-colorable).
+  * When colors are enabled, levels are truncated to 4 characters by default. To disable
+    truncation set the `DisableLevelTruncation` field to `true`.
   * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#TextFormatter).
 * `logrus.JSONFormatter`. Logs fields as JSON.
   * All options are listed in the [generated docs](https://godoc.org/github.com/sirupsen/logrus#JSONFormatter).
 
 Third party logging formatters:
 
-* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can by parsed by Kubernetes and Google Container Engine.
+* [`FluentdFormatter`](https://github.com/joonix/log). Formats entries that can be parsed by Kubernetes and Google Container Engine.
 * [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
 * [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
 * [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
@@ -489,7 +445,7 @@ logrus.RegisterExitHandler(handler)
 
 #### Thread safety
 
-By default Logger is protected by mutex for concurrent writes, this mutex is invoked when calling hooks and writing logs.
+By default, Logger is protected by a mutex for concurrent writes. The mutex is held when calling hooks and writing logs.
 If you are sure such locking is not needed, you can call logger.SetNoLock() to disable the locking.
 
 Situation when locking is not needed includes:
diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/Sirupsen/logrus/entry.go
index 5bf582ef..4efedddf 100644
--- a/vendor/github.com/Sirupsen/logrus/entry.go
+++ b/vendor/github.com/Sirupsen/logrus/entry.go
@@ -41,14 +41,14 @@ type Entry struct {
 	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
 	Message string
 
-	// When formatter is called in entry.log(), an Buffer may be set to entry
+	// When formatter is called in entry.log(), a Buffer may be set to entry
 	Buffer *bytes.Buffer
 }
 
 func NewEntry(logger *Logger) *Entry {
 	return &Entry{
 		Logger: logger,
-		// Default is three fields, give a little extra room
+		// Default is five fields, give a little extra room
 		Data: make(Fields, 5),
 	}
 }
@@ -83,51 +83,75 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
 	for k, v := range fields {
 		data[k] = v
 	}
-	return &Entry{Logger: entry.Logger, Data: data}
+	return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time}
+}
+
+// Overrides the time of the Entry.
+func (entry *Entry) WithTime(t time.Time) *Entry {
+	return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t}
 }
 
 // This function is not declared with a pointer value because otherwise
 // race conditions will occur when using multiple goroutines
 func (entry Entry) log(level Level, msg string) {
 	var buffer *bytes.Buffer
-	entry.Time = time.Now()
+
+	// Default to now, but allow users to override if they want.
+	//
+	// We don't have to worry about polluting future calls to Entry#log()
+	// with this assignment because this function is declared with a
+	// non-pointer receiver.
+	if entry.Time.IsZero() {
+		entry.Time = time.Now()
+	}
+
 	entry.Level = level
 	entry.Message = msg
 
-	if err := entry.Logger.Hooks.Fire(level, &entry); err != nil {
-		entry.Logger.mu.Lock()
-		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
-		entry.Logger.mu.Unlock()
-	}
+	entry.fireHooks()
+
 	buffer = bufferPool.Get().(*bytes.Buffer)
 	buffer.Reset()
 	defer bufferPool.Put(buffer)
 	entry.Buffer = buffer
-	serialized, err := entry.Logger.Formatter.Format(&entry)
+
+	entry.write()
+
 	entry.Buffer = nil
+
+	// To avoid Entry#log() returning a value that only would make sense for
+	// panic() to use in Entry#Panic(), we avoid the allocation by checking
+	// directly here.
+	if level <= PanicLevel {
+		panic(&entry)
+	}
+}
+
+func (entry *Entry) fireHooks() {
+	entry.Logger.mu.Lock()
+	defer entry.Logger.mu.Unlock()
+	err := entry.Logger.Hooks.Fire(entry.Level, entry)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
+	}
+}
+
+func (entry *Entry) write() {
+	entry.Logger.mu.Lock()
+	defer entry.Logger.mu.Unlock()
+	serialized, err := entry.Logger.Formatter.Format(entry)
 	if err != nil {
-		entry.Logger.mu.Lock()
 		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
-		entry.Logger.mu.Unlock()
 	} else {
-		entry.Logger.mu.Lock()
 		_, err = entry.Logger.Out.Write(serialized)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
 		}
-		entry.Logger.mu.Unlock()
-	}
-
-	// To avoid Entry#log() returning a value that only would make sense for
-	// panic() to use in Entry#Panic(), we avoid the allocation by checking
-	// directly here.
-	if level <= PanicLevel {
-		panic(&entry)
 	}
 }
 
 func (entry *Entry) Debug(args ...interface{}) {
-	if entry.Logger.level() >= DebugLevel {
+	if entry.Logger.IsLevelEnabled(DebugLevel) {
 		entry.log(DebugLevel, fmt.Sprint(args...))
 	}
 }
@@ -137,13 +161,13 @@ func (entry *Entry) Print(args ...interface{}) {
 }
 
 func (entry *Entry) Info(args ...interface{}) {
-	if entry.Logger.level() >= InfoLevel {
+	if entry.Logger.IsLevelEnabled(InfoLevel) {
 		entry.log(InfoLevel, fmt.Sprint(args...))
 	}
 }
 
 func (entry *Entry) Warn(args ...interface{}) {
-	if entry.Logger.level() >= WarnLevel {
+	if entry.Logger.IsLevelEnabled(WarnLevel) {
 		entry.log(WarnLevel, fmt.Sprint(args...))
 	}
 }
@@ -153,20 +177,20 @@ func (entry *Entry) Warning(args ...interface{}) {
 }
 
 func (entry *Entry) Error(args ...interface{}) {
-	if entry.Logger.level() >= ErrorLevel {
+	if entry.Logger.IsLevelEnabled(ErrorLevel) {
 		entry.log(ErrorLevel, fmt.Sprint(args...))
 	}
 }
 
 func (entry *Entry) Fatal(args ...interface{}) {
-	if entry.Logger.level() >= FatalLevel {
+	if entry.Logger.IsLevelEnabled(FatalLevel) {
 		entry.log(FatalLevel, fmt.Sprint(args...))
 	}
 	Exit(1)
 }
 
 func (entry *Entry) Panic(args ...interface{}) {
-	if entry.Logger.level() >= PanicLevel {
+	if entry.Logger.IsLevelEnabled(PanicLevel) {
 		entry.log(PanicLevel, fmt.Sprint(args...))
 	}
 	panic(fmt.Sprint(args...))
@@ -175,13 +199,13 @@ func (entry *Entry) Panic(args ...interface{}) {
 // Entry Printf family functions
 
 func (entry *Entry) Debugf(format string, args ...interface{}) {
-	if entry.Logger.level() >= DebugLevel {
+	if entry.Logger.IsLevelEnabled(DebugLevel) {
 		entry.Debug(fmt.Sprintf(format, args...))
 	}
 }
 
 func (entry *Entry) Infof(format string, args ...interface{}) {
-	if entry.Logger.level() >= InfoLevel {
+	if entry.Logger.IsLevelEnabled(InfoLevel) {
 		entry.Info(fmt.Sprintf(format, args...))
 	}
 }
@@ -191,7 +215,7 @@ func (entry *Entry) Printf(format string, args ...interface{}) {
 }
 
 func (entry *Entry) Warnf(format string, args ...interface{}) {
-	if entry.Logger.level() >= WarnLevel {
+	if entry.Logger.IsLevelEnabled(WarnLevel) {
 		entry.Warn(fmt.Sprintf(format, args...))
 	}
 }
@@ -201,20 +225,20 @@ func (entry *Entry) Warningf(format string, args ...interface{}) {
 }
 
 func (entry *Entry) Errorf(format string, args ...interface{}) {
-	if entry.Logger.level() >= ErrorLevel {
+	if entry.Logger.IsLevelEnabled(ErrorLevel) {
 		entry.Error(fmt.Sprintf(format, args...))
 	}
 }
 
 func (entry *Entry) Fatalf(format string, args ...interface{}) {
-	if entry.Logger.level() >= FatalLevel {
+	if entry.Logger.IsLevelEnabled(FatalLevel) {
 		entry.Fatal(fmt.Sprintf(format, args...))
 	}
 	Exit(1)
 }
 
 func (entry *Entry) Panicf(format string, args ...interface{}) {
-	if entry.Logger.level() >= PanicLevel {
+	if entry.Logger.IsLevelEnabled(PanicLevel) {
 		entry.Panic(fmt.Sprintf(format, args...))
 	}
 }
@@ -222,13 +246,13 @@ func (entry *Entry) Panicf(format string, args ...interface{}) {
 // Entry Println family functions
 
 func (entry *Entry) Debugln(args ...interface{}) {
-	if entry.Logger.level() >= DebugLevel {
+	if entry.Logger.IsLevelEnabled(DebugLevel) {
 		entry.Debug(entry.sprintlnn(args...))
 	}
 }
 
 func (entry *Entry) Infoln(args ...interface{}) {
-	if entry.Logger.level() >= InfoLevel {
+	if entry.Logger.IsLevelEnabled(InfoLevel) {
 		entry.Info(entry.sprintlnn(args...))
 	}
 }
@@ -238,7 +262,7 @@ func (entry *Entry) Println(args ...interface{}) {
 }
 
 func (entry *Entry) Warnln(args ...interface{}) {
-	if entry.Logger.level() >= WarnLevel {
+	if entry.Logger.IsLevelEnabled(WarnLevel) {
 		entry.Warn(entry.sprintlnn(args...))
 	}
 }
@@ -248,20 +272,20 @@ func (entry *Entry) Warningln(args ...interface{}) {
 }
 
 func (entry *Entry) Errorln(args ...interface{}) {
-	if entry.Logger.level() >= ErrorLevel {
+	if entry.Logger.IsLevelEnabled(ErrorLevel) {
 		entry.Error(entry.sprintlnn(args...))
 	}
 }
 
 func (entry *Entry) Fatalln(args ...interface{}) {
-	if entry.Logger.level() >= FatalLevel {
+	if entry.Logger.IsLevelEnabled(FatalLevel) {
 		entry.Fatal(entry.sprintlnn(args...))
 	}
 	Exit(1)
 }
 
 func (entry *Entry) Panicln(args ...interface{}) {
-	if entry.Logger.level() >= PanicLevel {
+	if entry.Logger.IsLevelEnabled(PanicLevel) {
 		entry.Panic(entry.sprintlnn(args...))
 	}
 }
diff --git a/vendor/github.com/Sirupsen/logrus/entry_test.go b/vendor/github.com/Sirupsen/logrus/entry_test.go
index 99c3b41d..a81e2b38 100644
--- a/vendor/github.com/Sirupsen/logrus/entry_test.go
+++ b/vendor/github.com/Sirupsen/logrus/entry_test.go
@@ -75,3 +75,41 @@ func TestEntryPanicf(t *testing.T) {
 	entry := NewEntry(logger)
 	entry.WithField("err", errBoom).Panicf("kaboom %v", true)
 }
+
+const (
+	badMessage   = "this is going to panic"
+	panicMessage = "this is broken"
+)
+
+type panickyHook struct{}
+
+func (p *panickyHook) Levels() []Level {
+	return []Level{InfoLevel}
+}
+
+func (p *panickyHook) Fire(entry *Entry) error {
+	if entry.Message == badMessage {
+		panic(panicMessage)
+	}
+
+	return nil
+}
+
+func TestEntryHooksPanic(t *testing.T) {
+	logger := New()
+	logger.Out = &bytes.Buffer{}
+	logger.Level = InfoLevel
+	logger.Hooks.Add(&panickyHook{})
+
+	defer func() {
+		p := recover()
+		assert.NotNil(t, p)
+		assert.Equal(t, panicMessage, p)
+
+		entry := NewEntry(logger)
+		entry.Info("another message")
+	}()
+
+	entry := NewEntry(logger)
+	entry.Info(badMessage)
+}
diff --git a/vendor/github.com/Sirupsen/logrus/example_basic_test.go b/vendor/github.com/Sirupsen/logrus/example_basic_test.go
index a2acf550..5f3849bf 100644
--- a/vendor/github.com/Sirupsen/logrus/example_basic_test.go
+++ b/vendor/github.com/Sirupsen/logrus/example_basic_test.go
@@ -1,14 +1,16 @@
 package logrus_test
 
 import (
-	"github.com/sirupsen/logrus"
 	"os"
+
+	"github.com/sirupsen/logrus"
 )
 
 func Example_basic() {
 	var log = logrus.New()
 	log.Formatter = new(logrus.JSONFormatter)
 	log.Formatter = new(logrus.TextFormatter)                     //default
+	log.Formatter.(*logrus.TextFormatter).DisableColors = true    // remove colors
 	log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output
 	log.Level = logrus.DebugLevel
 	log.Out = os.Stdout
diff --git a/vendor/github.com/Sirupsen/logrus/example_hook_test.go b/vendor/github.com/Sirupsen/logrus/example_hook_test.go
index d4ddffca..15118d26 100644
--- a/vendor/github.com/Sirupsen/logrus/example_hook_test.go
+++ b/vendor/github.com/Sirupsen/logrus/example_hook_test.go
@@ -1,16 +1,24 @@
+// +build !windows
+
 package logrus_test
 
 import (
-	"github.com/sirupsen/logrus"
-	"gopkg.in/gemnasium/logrus-airbrake-hook.v2"
+	"log/syslog"
 	"os"
+
+	"github.com/sirupsen/logrus"
+	slhooks "github.com/sirupsen/logrus/hooks/syslog"
 )
 
+// An example on how to use a hook
 func Example_hook() {
 	var log = logrus.New()
 	log.Formatter = new(logrus.TextFormatter)                     // default
+	log.Formatter.(*logrus.TextFormatter).DisableColors = true    // remove colors
 	log.Formatter.(*logrus.TextFormatter).DisableTimestamp = true // remove timestamp from test output
-	log.Hooks.Add(airbrake.NewHook(123, "xyz", "development"))
+	if sl, err := slhooks.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, ""); err != nil {
+		log.Hooks.Add(sl)
+	}
 	log.Out = os.Stdout
 
 	log.WithFields(logrus.Fields{
diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/Sirupsen/logrus/exported.go
index 013183ed..fb2a7a1f 100644
--- a/vendor/github.com/Sirupsen/logrus/exported.go
+++ b/vendor/github.com/Sirupsen/logrus/exported.go
@@ -2,6 +2,7 @@ package logrus
 
 import (
 	"io"
+	"time"
 )
 
 var (
@@ -15,37 +16,32 @@ func StandardLogger() *Logger {
 
 // SetOutput sets the standard logger output.
 func SetOutput(out io.Writer) {
-	std.mu.Lock()
-	defer std.mu.Unlock()
-	std.Out = out
+	std.SetOutput(out)
 }
 
 // SetFormatter sets the standard logger formatter.
 func SetFormatter(formatter Formatter) {
-	std.mu.Lock()
-	defer std.mu.Unlock()
-	std.Formatter = formatter
+	std.SetFormatter(formatter)
 }
 
 // SetLevel sets the standard logger level.
 func SetLevel(level Level) {
-	std.mu.Lock()
-	defer std.mu.Unlock()
 	std.SetLevel(level)
 }
 
 // GetLevel returns the standard logger level.
 func GetLevel() Level {
-	std.mu.Lock()
-	defer std.mu.Unlock()
-	return std.level()
+	return std.GetLevel()
+}
+
+// IsLevelEnabled checks if the log level of the standard logger is greater than the level param
+func IsLevelEnabled(level Level) bool {
+	return std.IsLevelEnabled(level)
 }
 
 // AddHook adds a hook to the standard logger hooks.
 func AddHook(hook Hook) {
-	std.mu.Lock()
-	defer std.mu.Unlock()
-	std.Hooks.Add(hook)
+	std.AddHook(hook)
 }
 
 // WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
@@ -72,6 +68,15 @@ func WithFields(fields Fields) *Entry {
 	return std.WithFields(fields)
 }
 
+// WithTime creats an entry from the standard logger and overrides the time of
+// logs generated with it.
+//
+// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
+// or Panic on the Entry it returns.
+func WithTime(t time.Time) *Entry {
+	return std.WithTime(t)
+}
+
 // Debug logs a message at level Debug on the standard logger.
 func Debug(args ...interface{}) {
 	std.Debug(args...)
@@ -107,7 +112,7 @@ func Panic(args ...interface{}) {
 	std.Panic(args...)
 }
 
-// Fatal logs a message at level Fatal on the standard logger.
+// Fatal logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
 func Fatal(args ...interface{}) {
 	std.Fatal(args...)
 }
@@ -147,7 +152,7 @@ func Panicf(format string, args ...interface{}) {
 	std.Panicf(format, args...)
 }
 
-// Fatalf logs a message at level Fatal on the standard logger.
+// Fatalf logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
 func Fatalf(format string, args ...interface{}) {
 	std.Fatalf(format, args...)
 }
@@ -187,7 +192,7 @@ func Panicln(args ...interface{}) {
 	std.Panicln(args...)
 }
 
-// Fatalln logs a message at level Fatal on the standard logger.
+// Fatalln logs a message at level Fatal on the standard logger then the process will exit with status set to 1.
 func Fatalln(args ...interface{}) {
 	std.Fatalln(args...)
 }
diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/Sirupsen/logrus/formatter.go
index b183ff5b..83c74947 100644
--- a/vendor/github.com/Sirupsen/logrus/formatter.go
+++ b/vendor/github.com/Sirupsen/logrus/formatter.go
@@ -30,16 +30,22 @@ type Formatter interface {
 //
 // It's not exported because it's still using Data in an opinionated way. It's to
 // avoid code duplication between the two default formatters.
-func prefixFieldClashes(data Fields) {
-	if t, ok := data["time"]; ok {
-		data["fields.time"] = t
+func prefixFieldClashes(data Fields, fieldMap FieldMap) {
+	timeKey := fieldMap.resolve(FieldKeyTime)
+	if t, ok := data[timeKey]; ok {
+		data["fields."+timeKey] = t
+		delete(data, timeKey)
 	}
 
-	if m, ok := data["msg"]; ok {
-		data["fields.msg"] = m
+	msgKey := fieldMap.resolve(FieldKeyMsg)
+	if m, ok := data[msgKey]; ok {
+		data["fields."+msgKey] = m
+		delete(data, msgKey)
 	}
 
-	if l, ok := data["level"]; ok {
-		data["fields.level"] = l
+	levelKey := fieldMap.resolve(FieldKeyLevel)
+	if l, ok := data[levelKey]; ok {
+		data["fields."+levelKey] = l
+		delete(data, levelKey)
 	}
 }
diff --git a/vendor/github.com/Sirupsen/logrus/go.mod b/vendor/github.com/Sirupsen/logrus/go.mod
new file mode 100644
index 00000000..f4fed02f
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/go.mod
@@ -0,0 +1,10 @@
+module github.com/sirupsen/logrus
+
+require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/stretchr/testify v1.2.2
+	golang.org/x/crypto v0.0.0-20180904163835-0709b304e793
+	golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33
+)
diff --git a/vendor/github.com/Sirupsen/logrus/go.sum b/vendor/github.com/Sirupsen/logrus/go.sum
new file mode 100644
index 00000000..1f0d7196
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/go.sum
@@ -0,0 +1,12 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe h1:CHRGQ8V7OlCYtwaKPJi3iA7J+YdNKdo8j7nG5IgDhjs=
+github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/vendor/github.com/Sirupsen/logrus/hook_test.go b/vendor/github.com/Sirupsen/logrus/hook_test.go
index 13f34cb6..80b93b8c 100644
--- a/vendor/github.com/Sirupsen/logrus/hook_test.go
+++ b/vendor/github.com/Sirupsen/logrus/hook_test.go
@@ -1,9 +1,13 @@
 package logrus
 
 import (
+	"bytes"
+	"encoding/json"
+	"sync"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 type TestHook struct {
@@ -84,6 +88,46 @@ func TestCanFireMultipleHooks(t *testing.T) {
 	})
 }
 
+type SingleLevelModifyHook struct {
+	ModifyHook
+}
+
+func (h *SingleLevelModifyHook) Levels() []Level {
+	return []Level{InfoLevel}
+}
+
+func TestHookEntryIsPristine(t *testing.T) {
+	l := New()
+	b := &bytes.Buffer{}
+	l.Formatter = &JSONFormatter{}
+	l.Out = b
+	l.AddHook(&SingleLevelModifyHook{})
+
+	l.Error("error message")
+	data := map[string]string{}
+	err := json.Unmarshal(b.Bytes(), &data)
+	require.NoError(t, err)
+	_, ok := data["wow"]
+	require.False(t, ok)
+	b.Reset()
+
+	l.Info("error message")
+	data = map[string]string{}
+	err = json.Unmarshal(b.Bytes(), &data)
+	require.NoError(t, err)
+	_, ok = data["wow"]
+	require.True(t, ok)
+	b.Reset()
+
+	l.Error("error message")
+	data = map[string]string{}
+	err = json.Unmarshal(b.Bytes(), &data)
+	require.NoError(t, err)
+	_, ok = data["wow"]
+	require.False(t, ok)
+	b.Reset()
+}
+
 type ErrorHook struct {
 	Fired bool
 }
@@ -120,3 +164,24 @@ func TestErrorHookShouldFireOnError(t *testing.T) {
 		assert.Equal(t, hook.Fired, true)
 	})
 }
+
+func TestAddHookRace(t *testing.T) {
+	var wg sync.WaitGroup
+	wg.Add(2)
+	hook := new(ErrorHook)
+	LogAndAssertJSON(t, func(log *Logger) {
+		go func() {
+			defer wg.Done()
+			log.AddHook(hook)
+		}()
+		go func() {
+			defer wg.Done()
+			log.Error("test")
+		}()
+		wg.Wait()
+	}, func(fields Fields) {
+		// the line may have been logged
+		// before the hook was added, so we can't
+		// actually assert on the hook
+	})
+}
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
index 5ec3a444..bec6efd5 100644
--- a/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
+++ b/vendor/github.com/Sirupsen/logrus/hooks/syslog/syslog_test.go
@@ -1,3 +1,5 @@
+// +build !windows,!nacl,!plan9
+
 package syslog
 
 import (
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/test/test.go b/vendor/github.com/Sirupsen/logrus/hooks/test/test.go
index 62c4845d..234a17df 100644
--- a/vendor/github.com/Sirupsen/logrus/hooks/test/test.go
+++ b/vendor/github.com/Sirupsen/logrus/hooks/test/test.go
@@ -15,7 +15,7 @@ type Hook struct {
 	// Entries is an array of all entries that have been received by this hook.
 	// For safe access, use the AllEntries() method, rather than reading this
 	// value directly.
-	Entries []*logrus.Entry
+	Entries []logrus.Entry
 	mu      sync.RWMutex
 }
 
@@ -52,7 +52,7 @@ func NewNullLogger() (*logrus.Logger, *Hook) {
 func (t *Hook) Fire(e *logrus.Entry) error {
 	t.mu.Lock()
 	defer t.mu.Unlock()
-	t.Entries = append(t.Entries, e)
+	t.Entries = append(t.Entries, *e)
 	return nil
 }
 
@@ -68,9 +68,7 @@ func (t *Hook) LastEntry() *logrus.Entry {
 	if i < 0 {
 		return nil
 	}
-	// Make a copy, for safety
-	e := *t.Entries[i]
-	return &e
+	return &t.Entries[i]
 }
 
 // AllEntries returns all entries that were logged.
@@ -79,10 +77,9 @@ func (t *Hook) AllEntries() []*logrus.Entry {
 	defer t.mu.RUnlock()
 	// Make a copy so the returned value won't race with future log requests
 	entries := make([]*logrus.Entry, len(t.Entries))
-	for i, entry := range t.Entries {
+	for i := 0; i < len(t.Entries); i++ {
 		// Make a copy, for safety
-		e := *entry
-		entries[i] = &e
+		entries[i] = &t.Entries[i]
 	}
 	return entries
 }
@@ -91,5 +88,5 @@ func (t *Hook) AllEntries() []*logrus.Entry {
 func (t *Hook) Reset() {
 	t.mu.Lock()
 	defer t.mu.Unlock()
-	t.Entries = make([]*logrus.Entry, 0)
+	t.Entries = make([]logrus.Entry, 0)
 }
diff --git a/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go b/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go
index 3f55cfe3..d6f6d306 100644
--- a/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go
+++ b/vendor/github.com/Sirupsen/logrus/hooks/test/test_test.go
@@ -1,14 +1,16 @@
 package test
 
 import (
+	"math/rand"
+	"sync"
 	"testing"
+	"time"
 
 	"github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/assert"
 )
 
 func TestAllHooks(t *testing.T) {
-
 	assert := assert.New(t)
 
 	logger, hook := NewNullLogger()
@@ -35,5 +37,37 @@ func TestAllHooks(t *testing.T) {
 	assert.Equal(logrus.ErrorLevel, hook.LastEntry().Level)
 	assert.Equal("Hello error", hook.LastEntry().Message)
 	assert.Equal(1, len(hook.Entries))
+}
+
+func TestLoggingWithHooksRace(t *testing.T) {
+
+	rand.Seed(time.Now().Unix())
+	unlocker := rand.Int() % 100
+
+	assert := assert.New(t)
+	logger, hook := NewNullLogger()
+
+	var wgOne, wgAll sync.WaitGroup
+	wgOne.Add(1)
+	wgAll.Add(100)
+
+	for i := 0; i < 100; i++ {
+		go func(i int) {
+			logger.Info("info")
+			wgAll.Done()
+			if i == unlocker {
+				wgOne.Done()
+			}
+		}(i)
+	}
+
+	wgOne.Wait()
+
+	assert.Equal(logrus.InfoLevel, hook.LastEntry().Level)
+	assert.Equal("info", hook.LastEntry().Message)
+
+	wgAll.Wait()
 
+	entries := hook.AllEntries()
+	assert.Equal(100, len(entries))
 }
diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/Sirupsen/logrus/json_formatter.go
index fb01c1b1..d3dadefe 100644
--- a/vendor/github.com/Sirupsen/logrus/json_formatter.go
+++ b/vendor/github.com/Sirupsen/logrus/json_formatter.go
@@ -1,6 +1,7 @@
 package logrus
 
 import (
+	"bytes"
 	"encoding/json"
 	"fmt"
 )
@@ -33,6 +34,9 @@ type JSONFormatter struct {
 	// DisableTimestamp allows disabling automatic timestamps in output
 	DisableTimestamp bool
 
+	// DataKey allows users to put all the log entry parameters into a nested dictionary at a given key.
+	DataKey string
+
 	// FieldMap allows users to customize the names of keys for default fields.
 	// As an example:
 	// formatter := &JSONFormatter{
@@ -43,6 +47,9 @@ type JSONFormatter struct {
 	//    },
 	// }
 	FieldMap FieldMap
+
+	// PrettyPrint will indent all json logs
+	PrettyPrint bool
 }
 
 // Format renders a single log entry
@@ -58,7 +65,14 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 			data[k] = v
 		}
 	}
-	prefixFieldClashes(data)
+
+	if f.DataKey != "" {
+		newData := make(Fields, 4)
+		newData[f.DataKey] = data
+		data = newData
+	}
+
+	prefixFieldClashes(data, f.FieldMap)
 
 	timestampFormat := f.TimestampFormat
 	if timestampFormat == "" {
@@ -71,9 +85,20 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
 	data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
 	data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
 
-	serialized, err := json.Marshal(data)
-	if err != nil {
+	var b *bytes.Buffer
+	if entry.Buffer != nil {
+		b = entry.Buffer
+	} else {
+		b = &bytes.Buffer{}
+	}
+
+	encoder := json.NewEncoder(b)
+	if f.PrettyPrint {
+		encoder.SetIndent("", "  ")
+	}
+	if err := encoder.Encode(data); err != nil {
 		return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
 	}
-	return append(serialized, '\n'), nil
+
+	return b.Bytes(), nil
 }
diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter_test.go b/vendor/github.com/Sirupsen/logrus/json_formatter_test.go
index 51093a79..0dde3004 100644
--- a/vendor/github.com/Sirupsen/logrus/json_formatter_test.go
+++ b/vendor/github.com/Sirupsen/logrus/json_formatter_test.go
@@ -3,6 +3,7 @@ package logrus
 import (
 	"encoding/json"
 	"errors"
+	"fmt"
 	"strings"
 	"testing"
 )
@@ -106,6 +107,102 @@ func TestFieldClashWithLevel(t *testing.T) {
 	}
 }
 
+func TestFieldClashWithRemappedFields(t *testing.T) {
+	formatter := &JSONFormatter{
+		FieldMap: FieldMap{
+			FieldKeyTime:  "@timestamp",
+			FieldKeyLevel: "@level",
+			FieldKeyMsg:   "@message",
+		},
+	}
+
+	b, err := formatter.Format(WithFields(Fields{
+		"@timestamp": "@timestamp",
+		"@level":     "@level",
+		"@message":   "@message",
+		"timestamp":  "timestamp",
+		"level":      "level",
+		"msg":        "msg",
+	}))
+	if err != nil {
+		t.Fatal("Unable to format entry: ", err)
+	}
+
+	entry := make(map[string]interface{})
+	err = json.Unmarshal(b, &entry)
+	if err != nil {
+		t.Fatal("Unable to unmarshal formatted entry: ", err)
+	}
+
+	for _, field := range []string{"timestamp", "level", "msg"} {
+		if entry[field] != field {
+			t.Errorf("Expected field %v to be untouched; got %v", field, entry[field])
+		}
+
+		remappedKey := fmt.Sprintf("fields.%s", field)
+		if remapped, ok := entry[remappedKey]; ok {
+			t.Errorf("Expected %s to be empty; got %v", remappedKey, remapped)
+		}
+	}
+
+	for _, field := range []string{"@timestamp", "@level", "@message"} {
+		if entry[field] == field {
+			t.Errorf("Expected field %v to be mapped to an Entry value", field)
+		}
+
+		remappedKey := fmt.Sprintf("fields.%s", field)
+		if remapped, ok := entry[remappedKey]; ok {
+			if remapped != field {
+				t.Errorf("Expected field %v to be copied to %s; got %v", field, remappedKey, remapped)
+			}
+		} else {
+			t.Errorf("Expected field %v to be copied to %s; was absent", field, remappedKey)
+		}
+	}
+}
+
+func TestFieldsInNestedDictionary(t *testing.T) {
+	formatter := &JSONFormatter{
+		DataKey: "args",
+	}
+
+	logEntry := WithFields(Fields{
+		"level":      "level",
+		"test":		  "test",
+	})
+	logEntry.Level = InfoLevel
+
+	b, err := formatter.Format(logEntry)
+	if err != nil {
+		t.Fatal("Unable to format entry: ", err)
+	}
+
+	entry := make(map[string]interface{})
+	err = json.Unmarshal(b, &entry)
+	if err != nil {
+		t.Fatal("Unable to unmarshal formatted entry: ", err)
+	}
+
+	args := entry["args"].(map[string]interface{})
+
+	for _, field := range []string{"test", "level"} {
+		if value, present := args[field]; !present || value != field {
+			t.Errorf("Expected field %v to be present under 'args'; untouched", field)
+		}
+	}
+
+	for _, field := range []string{"test", "fields.level"} {
+		if _, present := entry[field]; present {
+			t.Errorf("Expected field %v not to be present at top level", field)
+		}
+	}
+
+	// with nested object, "level" shouldn't clash
+	if entry["level"] != "info" {
+		t.Errorf("Expected 'level' field to contain 'info'")
+	}
+}
+
 func TestJSONEntryEndsWithNewline(t *testing.T) {
 	formatter := &JSONFormatter{}
 
diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/Sirupsen/logrus/logger.go
index 2acab050..b67bfcbd 100644
--- a/vendor/github.com/Sirupsen/logrus/logger.go
+++ b/vendor/github.com/Sirupsen/logrus/logger.go
@@ -5,12 +5,13 @@ import (
 	"os"
 	"sync"
 	"sync/atomic"
+	"time"
 )
 
 type Logger struct {
 	// The logs are `io.Copy`'d to this in a mutex. It's common to set this to a
 	// file, or leave it default which is `os.Stderr`. You can also set this to
-	// something more adventorous, such as logging to Kafka.
+	// something more adventurous, such as logging to Kafka.
 	Out io.Writer
 	// Hooks for the logger instance. These allow firing events based on logging
 	// levels and log entries. For example, to send errors to an error tracking
@@ -84,11 +85,12 @@ func (logger *Logger) newEntry() *Entry {
 }
 
 func (logger *Logger) releaseEntry(entry *Entry) {
+	entry.Data = map[string]interface{}{}
 	logger.entryPool.Put(entry)
 }
 
 // Adds a field to the log entry, note that it doesn't log until you call
-// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
+// Debug, Print, Info, Warn, Error, Fatal or Panic. It only creates a log entry.
 // If you want multiple fields, use `WithFields`.
 func (logger *Logger) WithField(key string, value interface{}) *Entry {
 	entry := logger.newEntry()
@@ -112,8 +114,15 @@ func (logger *Logger) WithError(err error) *Entry {
 	return entry.WithError(err)
 }
 
+// Overrides the time of the log entry.
+func (logger *Logger) WithTime(t time.Time) *Entry {
+	entry := logger.newEntry()
+	defer logger.releaseEntry(entry)
+	return entry.WithTime(t)
+}
+
 func (logger *Logger) Debugf(format string, args ...interface{}) {
-	if logger.level() >= DebugLevel {
+	if logger.IsLevelEnabled(DebugLevel) {
 		entry := logger.newEntry()
 		entry.Debugf(format, args...)
 		logger.releaseEntry(entry)
@@ -121,7 +130,7 @@ func (logger *Logger) Debugf(format string, args ...interface{}) {
 }
 
 func (logger *Logger) Infof(format string, args ...interface{}) {
-	if logger.level() >= InfoLevel {
+	if logger.IsLevelEnabled(InfoLevel) {
 		entry := logger.newEntry()
 		entry.Infof(format, args...)
 		logger.releaseEntry(entry)
@@ -135,7 +144,7 @@ func (logger *Logger) Printf(format string, args ...interface{}) {
 }
 
 func (logger *Logger) Warnf(format string, args ...interface{}) {
-	if logger.level() >= WarnLevel {
+	if logger.IsLevelEnabled(WarnLevel) {
 		entry := logger.newEntry()
 		entry.Warnf(format, args...)
 		logger.releaseEntry(entry)
@@ -143,7 +152,7 @@ func (logger *Logger) Warnf(format string, args ...interface{}) {
 }
 
 func (logger *Logger) Warningf(format string, args ...interface{}) {
-	if logger.level() >= WarnLevel {
+	if logger.IsLevelEnabled(WarnLevel) {
 		entry := logger.newEntry()
 		entry.Warnf(format, args...)
 		logger.releaseEntry(entry)
@@ -151,7 +160,7 @@ func (logger *Logger) Warningf(format string, args ...interface{}) {
 }
 
 func (logger *Logger) Errorf(format string, args ...interface{}) {
-	if logger.level() >= ErrorLevel {
+	if logger.IsLevelEnabled(ErrorLevel) {
 		entry := logger.newEntry()
 		entry.Errorf(format, args...)
 		logger.releaseEntry(entry)
@@ -159,7 +168,7 @@ func (logger *Logger) Errorf(format string, args ...interface{}) {
 }
 
 func (logger *Logger) Fatalf(format string, args ...interface{}) {
-	if logger.level() >= FatalLevel {
+	if logger.IsLevelEnabled(FatalLevel) {
 		entry := logger.newEntry()
 		entry.Fatalf(format, args...)
 		logger.releaseEntry(entry)
@@ -168,7 +177,7 @@ func (logger *Logger) Fatalf(format string, args ...interface{}) {
 }
 
 func (logger *Logger) Panicf(format string, args ...interface{}) {
-	if logger.level() >= PanicLevel {
+	if logger.IsLevelEnabled(PanicLevel) {
 		entry := logger.newEntry()
 		entry.Panicf(format, args...)
 		logger.releaseEntry(entry)
@@ -176,7 +185,7 @@ func (logger *Logger) Panicf(format string, args ...interface{}) {
 }
 
 func (logger *Logger) Debug(args ...interface{}) {
-	if logger.level() >= DebugLevel {
+	if logger.IsLevelEnabled(DebugLevel) {
 		entry := logger.newEntry()
 		entry.Debug(args...)
 		logger.releaseEntry(entry)
@@ -184,7 +193,7 @@ func (logger *Logger) Debug(args ...interface{}) {
 }
 
 func (logger *Logger) Info(args ...interface{}) {
-	if logger.level() >= InfoLevel {
+	if logger.IsLevelEnabled(InfoLevel) {
 		entry := logger.newEntry()
 		entry.Info(args...)
 		logger.releaseEntry(entry)
@@ -198,7 +207,7 @@ func (logger *Logger) Print(args ...interface{}) {
 }
 
 func (logger *Logger) Warn(args ...interface{}) {
-	if logger.level() >= WarnLevel {
+	if logger.IsLevelEnabled(WarnLevel) {
 		entry := logger.newEntry()
 		entry.Warn(args...)
 		logger.releaseEntry(entry)
@@ -206,7 +215,7 @@ func (logger *Logger) Warn(args ...interface{}) {
 }
 
 func (logger *Logger) Warning(args ...interface{}) {
-	if logger.level() >= WarnLevel {
+	if logger.IsLevelEnabled(WarnLevel) {
 		entry := logger.newEntry()
 		entry.Warn(args...)
 		logger.releaseEntry(entry)
@@ -214,7 +223,7 @@ func (logger *Logger) Warning(args ...interface{}) {
 }
 
 func (logger *Logger) Error(args ...interface{}) {
-	if logger.level() >= ErrorLevel {
+	if logger.IsLevelEnabled(ErrorLevel) {
 		entry := logger.newEntry()
 		entry.Error(args...)
 		logger.releaseEntry(entry)
@@ -222,7 +231,7 @@ func (logger *Logger) Error(args ...interface{}) {
 }
 
 func (logger *Logger) Fatal(args ...interface{}) {
-	if logger.level() >= FatalLevel {
+	if logger.IsLevelEnabled(FatalLevel) {
 		entry := logger.newEntry()
 		entry.Fatal(args...)
 		logger.releaseEntry(entry)
@@ -231,7 +240,7 @@ func (logger *Logger) Fatal(args ...interface{}) {
 }
 
 func (logger *Logger) Panic(args ...interface{}) {
-	if logger.level() >= PanicLevel {
+	if logger.IsLevelEnabled(PanicLevel) {
 		entry := logger.newEntry()
 		entry.Panic(args...)
 		logger.releaseEntry(entry)
@@ -239,7 +248,7 @@ func (logger *Logger) Panic(args ...interface{}) {
 }
 
 func (logger *Logger) Debugln(args ...interface{}) {
-	if logger.level() >= DebugLevel {
+	if logger.IsLevelEnabled(DebugLevel) {
 		entry := logger.newEntry()
 		entry.Debugln(args...)
 		logger.releaseEntry(entry)
@@ -247,7 +256,7 @@ func (logger *Logger) Debugln(args ...interface{}) {
 }
 
 func (logger *Logger) Infoln(args ...interface{}) {
-	if logger.level() >= InfoLevel {
+	if logger.IsLevelEnabled(InfoLevel) {
 		entry := logger.newEntry()
 		entry.Infoln(args...)
 		logger.releaseEntry(entry)
@@ -261,7 +270,7 @@ func (logger *Logger) Println(args ...interface{}) {
 }
 
 func (logger *Logger) Warnln(args ...interface{}) {
-	if logger.level() >= WarnLevel {
+	if logger.IsLevelEnabled(WarnLevel) {
 		entry := logger.newEntry()
 		entry.Warnln(args...)
 		logger.releaseEntry(entry)
@@ -269,7 +278,7 @@ func (logger *Logger) Warnln(args ...interface{}) {
 }
 
 func (logger *Logger) Warningln(args ...interface{}) {
-	if logger.level() >= WarnLevel {
+	if logger.IsLevelEnabled(WarnLevel) {
 		entry := logger.newEntry()
 		entry.Warnln(args...)
 		logger.releaseEntry(entry)
@@ -277,7 +286,7 @@ func (logger *Logger) Warningln(args ...interface{}) {
 }
 
 func (logger *Logger) Errorln(args ...interface{}) {
-	if logger.level() >= ErrorLevel {
+	if logger.IsLevelEnabled(ErrorLevel) {
 		entry := logger.newEntry()
 		entry.Errorln(args...)
 		logger.releaseEntry(entry)
@@ -285,7 +294,7 @@ func (logger *Logger) Errorln(args ...interface{}) {
 }
 
 func (logger *Logger) Fatalln(args ...interface{}) {
-	if logger.level() >= FatalLevel {
+	if logger.IsLevelEnabled(FatalLevel) {
 		entry := logger.newEntry()
 		entry.Fatalln(args...)
 		logger.releaseEntry(entry)
@@ -294,7 +303,7 @@ func (logger *Logger) Fatalln(args ...interface{}) {
 }
 
 func (logger *Logger) Panicln(args ...interface{}) {
-	if logger.level() >= PanicLevel {
+	if logger.IsLevelEnabled(PanicLevel) {
 		entry := logger.newEntry()
 		entry.Panicln(args...)
 		logger.releaseEntry(entry)
@@ -312,6 +321,47 @@ func (logger *Logger) level() Level {
 	return Level(atomic.LoadUint32((*uint32)(&logger.Level)))
 }
 
+// SetLevel sets the logger level.
 func (logger *Logger) SetLevel(level Level) {
 	atomic.StoreUint32((*uint32)(&logger.Level), uint32(level))
 }
+
+// GetLevel returns the logger level.
+func (logger *Logger) GetLevel() Level {
+	return logger.level()
+}
+
+// AddHook adds a hook to the logger hooks.
+func (logger *Logger) AddHook(hook Hook) {
+	logger.mu.Lock()
+	defer logger.mu.Unlock()
+	logger.Hooks.Add(hook)
+}
+
+// IsLevelEnabled checks if the log level of the logger is greater than the level param
+func (logger *Logger) IsLevelEnabled(level Level) bool {
+	return logger.level() >= level
+}
+
+// SetFormatter sets the logger formatter.
+func (logger *Logger) SetFormatter(formatter Formatter) {
+	logger.mu.Lock()
+	defer logger.mu.Unlock()
+	logger.Formatter = formatter
+}
+
+// SetOutput sets the logger output.
+func (logger *Logger) SetOutput(output io.Writer) {
+	logger.mu.Lock()
+	defer logger.mu.Unlock()
+	logger.Out = output
+}
+
+// ReplaceHooks replaces the logger hooks and returns the old ones
+func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks {
+	logger.mu.Lock()
+	oldHooks := logger.Hooks
+	logger.Hooks = hooks
+	logger.mu.Unlock()
+	return oldHooks
+}
diff --git a/vendor/github.com/Sirupsen/logrus/logger_bench_test.go b/vendor/github.com/Sirupsen/logrus/logger_bench_test.go
index dd23a353..f0a76843 100644
--- a/vendor/github.com/Sirupsen/logrus/logger_bench_test.go
+++ b/vendor/github.com/Sirupsen/logrus/logger_bench_test.go
@@ -1,6 +1,7 @@
 package logrus
 
 import (
+	"io/ioutil"
 	"os"
 	"testing"
 )
@@ -59,3 +60,26 @@ func doLoggerBenchmarkNoLock(b *testing.B, out *os.File, formatter Formatter, fi
 		}
 	})
 }
+
+func BenchmarkLoggerJSONFormatter(b *testing.B) {
+	doLoggerBenchmarkWithFormatter(b, &JSONFormatter{})
+}
+
+func BenchmarkLoggerTextFormatter(b *testing.B) {
+	doLoggerBenchmarkWithFormatter(b, &TextFormatter{})
+}
+
+func doLoggerBenchmarkWithFormatter(b *testing.B, f Formatter) {
+	b.SetParallelism(100)
+	log := New()
+	log.Formatter = f
+	log.Out = ioutil.Discard
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			log.
+				WithField("foo1", "bar1").
+				WithField("foo2", "bar2").
+				Info("this is a dummy log")
+		}
+	})
+}
diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/Sirupsen/logrus/logrus.go
index dd389997..fa0b9dea 100644
--- a/vendor/github.com/Sirupsen/logrus/logrus.go
+++ b/vendor/github.com/Sirupsen/logrus/logrus.go
@@ -140,4 +140,11 @@ type FieldLogger interface {
 	Errorln(args ...interface{})
 	Fatalln(args ...interface{})
 	Panicln(args ...interface{})
+
+	// IsDebugEnabled() bool
+	// IsInfoEnabled() bool
+	// IsWarnEnabled() bool
+	// IsErrorEnabled() bool
+	// IsFatalEnabled() bool
+	// IsPanicEnabled() bool
 }
diff --git a/vendor/github.com/Sirupsen/logrus/logrus_test.go b/vendor/github.com/Sirupsen/logrus/logrus_test.go
index 78cbc282..97d15d7f 100644
--- a/vendor/github.com/Sirupsen/logrus/logrus_test.go
+++ b/vendor/github.com/Sirupsen/logrus/logrus_test.go
@@ -3,10 +3,12 @@ package logrus
 import (
 	"bytes"
 	"encoding/json"
+	"io/ioutil"
 	"strconv"
 	"strings"
 	"sync"
 	"testing"
+	"time"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -209,6 +211,65 @@ func TestDefaultFieldsAreNotPrefixed(t *testing.T) {
 	})
 }
 
+func TestWithTimeShouldOverrideTime(t *testing.T) {
+	now := time.Now().Add(24 * time.Hour)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithTime(now).Info("foobar")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat))
+	})
+}
+
+func TestWithTimeShouldNotOverrideFields(t *testing.T) {
+	now := time.Now().Add(24 * time.Hour)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithField("herp", "derp").WithTime(now).Info("blah")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat))
+		assert.Equal(t, fields["herp"], "derp")
+	})
+}
+
+func TestWithFieldShouldNotOverrideTime(t *testing.T) {
+	now := time.Now().Add(24 * time.Hour)
+
+	LogAndAssertJSON(t, func(log *Logger) {
+		log.WithTime(now).WithField("herp", "derp").Info("blah")
+	}, func(fields Fields) {
+		assert.Equal(t, fields["time"], now.Format(defaultTimestampFormat))
+		assert.Equal(t, fields["herp"], "derp")
+	})
+}
+
+func TestTimeOverrideMultipleLogs(t *testing.T) {
+	var buffer bytes.Buffer
+	var firstFields, secondFields Fields
+
+	logger := New()
+	logger.Out = &buffer
+	formatter := new(JSONFormatter)
+	formatter.TimestampFormat = time.StampMilli
+	logger.Formatter = formatter
+
+	llog := logger.WithField("herp", "derp")
+	llog.Info("foo")
+
+	err := json.Unmarshal(buffer.Bytes(), &firstFields)
+	assert.NoError(t, err, "should have decoded first message")
+
+	buffer.Reset()
+
+	time.Sleep(10 * time.Millisecond)
+	llog.Info("bar")
+
+	err = json.Unmarshal(buffer.Bytes(), &secondFields)
+	assert.NoError(t, err, "should have decoded second message")
+
+	assert.NotEqual(t, firstFields["time"], secondFields["time"], "timestamps should not be equal")
+}
+
 func TestDoubleLoggingDoesntPrefixPreviousFields(t *testing.T) {
 
 	var buffer bytes.Buffer
@@ -343,6 +404,45 @@ func TestLoggingRace(t *testing.T) {
 	wg.Wait()
 }
 
+func TestLoggingRaceWithHooksOnEntry(t *testing.T) {
+	logger := New()
+	hook := new(ModifyHook)
+	logger.AddHook(hook)
+	entry := logger.WithField("context", "clue")
+
+	var wg sync.WaitGroup
+	wg.Add(100)
+
+	for i := 0; i < 100; i++ {
+		go func() {
+			entry.Info("info")
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func TestReplaceHooks(t *testing.T) {
+	old, cur := &TestHook{}, &TestHook{}
+
+	logger := New()
+	logger.SetOutput(ioutil.Discard)
+	logger.AddHook(old)
+
+	hooks := make(LevelHooks)
+	hooks.Add(cur)
+	replaced := logger.ReplaceHooks(hooks)
+
+	logger.Info("test")
+
+	assert.Equal(t, old.Fired, false)
+	assert.Equal(t, cur.Fired, true)
+
+	logger.ReplaceHooks(replaced)
+	logger.Info("test")
+	assert.Equal(t, old.Fired, true)
+}
+
 // Compile test
 func TestLogrusInterface(t *testing.T) {
 	var buffer bytes.Buffer
@@ -384,3 +484,54 @@ func TestEntryWriter(t *testing.T) {
 	assert.Equal(t, fields["foo"], "bar")
 	assert.Equal(t, fields["level"], "warning")
 }
+
+func TestLogLevelEnabled(t *testing.T) {
+	log := New()
+	log.SetLevel(PanicLevel)
+	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(FatalLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(ErrorLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
+
+	log.SetLevel(FatalLevel)
+	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(ErrorLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
+
+	log.SetLevel(ErrorLevel)
+	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(WarnLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
+
+	log.SetLevel(WarnLevel)
+	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(InfoLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
+
+	log.SetLevel(InfoLevel)
+	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(InfoLevel))
+	assert.Equal(t, false, log.IsLevelEnabled(DebugLevel))
+
+	log.SetLevel(DebugLevel)
+	assert.Equal(t, true, log.IsLevelEnabled(PanicLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(FatalLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(ErrorLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(WarnLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(InfoLevel))
+	assert.Equal(t, true, log.IsLevelEnabled(DebugLevel))
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_appengine.go b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go
new file mode 100644
index 00000000..72f679cd
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_appengine.go
@@ -0,0 +1,13 @@
+// Based on ssh/terminal:
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package logrus
+
+import "io"
+
+func initTerminal(w io.Writer) {
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
index d7b3893f..62ca252d 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
+++ b/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
@@ -1,10 +1,17 @@
 // +build darwin freebsd openbsd netbsd dragonfly
-// +build !appengine
+// +build !appengine,!js
 
 package logrus
 
-import "golang.org/x/sys/unix"
+import (
+	"io"
+
+	"golang.org/x/sys/unix"
+)
 
 const ioctlReadTermios = unix.TIOCGETA
 
 type Termios unix.Termios
+
+func initTerminal(w io.Writer) {
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go b/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go
new file mode 100644
index 00000000..2403de98
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_check_appengine.go
@@ -0,0 +1,11 @@
+// +build appengine
+
+package logrus
+
+import (
+	"io"
+)
+
+func checkIfTerminal(w io.Writer) bool {
+	return true
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_js.go b/vendor/github.com/Sirupsen/logrus/terminal_check_js.go
new file mode 100644
index 00000000..0c209750
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_check_js.go
@@ -0,0 +1,11 @@
+// +build js
+
+package logrus
+
+import (
+	"io"
+)
+
+func checkIfTerminal(w io.Writer) bool {
+	return false
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go
new file mode 100644
index 00000000..cf309d6f
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_check_notappengine.go
@@ -0,0 +1,19 @@
+// +build !appengine,!js,!windows
+
+package logrus
+
+import (
+	"io"
+	"os"
+
+	"golang.org/x/crypto/ssh/terminal"
+)
+
+func checkIfTerminal(w io.Writer) bool {
+	switch v := w.(type) {
+	case *os.File:
+		return terminal.IsTerminal(int(v.Fd()))
+	default:
+		return false
+	}
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_check_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_check_windows.go
new file mode 100644
index 00000000..3b9d2864
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_check_windows.go
@@ -0,0 +1,20 @@
+// +build !appengine,!js,windows
+
+package logrus
+
+import (
+	"io"
+	"os"
+	"syscall"
+)
+
+func checkIfTerminal(w io.Writer) bool {
+	switch v := w.(type) {
+	case *os.File:
+		var mode uint32
+		err := syscall.GetConsoleMode(syscall.Handle(v.Fd()), &mode)
+		return err == nil
+	default:
+		return false
+	}
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/Sirupsen/logrus/terminal_linux.go
index 88d7298e..18066f08 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_linux.go
+++ b/vendor/github.com/Sirupsen/logrus/terminal_linux.go
@@ -3,12 +3,19 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !appengine
+// +build !appengine,!js
 
 package logrus
 
-import "golang.org/x/sys/unix"
+import (
+	"io"
+
+	"golang.org/x/sys/unix"
+)
 
 const ioctlReadTermios = unix.TCGETS
 
 type Termios unix.Termios
+
+func initTerminal(w io.Writer) {
+}
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/Sirupsen/logrus/terminal_windows.go
new file mode 100644
index 00000000..b4ef5286
--- /dev/null
+++ b/vendor/github.com/Sirupsen/logrus/terminal_windows.go
@@ -0,0 +1,18 @@
+// +build !appengine,!js,windows
+
+package logrus
+
+import (
+	"io"
+	"os"
+	"syscall"
+
+	sequences "github.com/konsorten/go-windows-terminal-sequences"
+)
+
+func initTerminal(w io.Writer) {
+	switch v := w.(type) {
+	case *os.File:
+		sequences.EnableVirtualTerminalProcessing(syscall.Handle(v.Fd()), true)
+	}
+}
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/Sirupsen/logrus/text_formatter.go
index be412aa9..67fb686c 100644
--- a/vendor/github.com/Sirupsen/logrus/text_formatter.go
+++ b/vendor/github.com/Sirupsen/logrus/text_formatter.go
@@ -3,14 +3,11 @@ package logrus
 import (
 	"bytes"
 	"fmt"
-	"io"
 	"os"
 	"sort"
 	"strings"
 	"sync"
 	"time"
-
-	"golang.org/x/crypto/ssh/terminal"
 )
 
 const (
@@ -24,6 +21,7 @@ const (
 
 var (
 	baseTimestamp time.Time
+	emptyFieldMap FieldMap
 )
 
 func init() {
@@ -38,6 +36,9 @@ type TextFormatter struct {
 	// Force disabling colors.
 	DisableColors bool
 
+	// Override coloring based on CLICOLOR and CLICOLOR_FORCE. - https://bixense.com/clicolors/
+	EnvironmentOverrideColors bool
+
 	// Disable timestamp logging. useful when output is redirected to logging
 	// system that already adds timestamps.
 	DisableTimestamp bool
@@ -54,69 +55,119 @@ type TextFormatter struct {
 	// be desired.
 	DisableSorting bool
 
+	// The keys sorting function, when uninitialized it uses sort.Strings.
+	SortingFunc func([]string)
+
+	// Disables the truncation of the level text to 4 characters.
+	DisableLevelTruncation bool
+
 	// QuoteEmptyFields will wrap empty fields in quotes if true
 	QuoteEmptyFields bool
 
 	// Whether the logger's out is to a terminal
 	isTerminal bool
 
-	sync.Once
+	// FieldMap allows users to customize the names of keys for default fields.
+	// As an example:
+	// formatter := &TextFormatter{
+	//     FieldMap: FieldMap{
+	//         FieldKeyTime:  "@timestamp",
+	//         FieldKeyLevel: "@level",
+	//         FieldKeyMsg:   "@message"}}
+	FieldMap FieldMap
+
+	terminalInitOnce sync.Once
 }
 
 func (f *TextFormatter) init(entry *Entry) {
 	if entry.Logger != nil {
-		f.isTerminal = f.checkIfTerminal(entry.Logger.Out)
+		f.isTerminal = checkIfTerminal(entry.Logger.Out)
+
+		if f.isTerminal {
+			initTerminal(entry.Logger.Out)
+		}
 	}
 }
 
-func (f *TextFormatter) checkIfTerminal(w io.Writer) bool {
-	switch v := w.(type) {
-	case *os.File:
-		return terminal.IsTerminal(int(v.Fd()))
-	default:
-		return false
+func (f *TextFormatter) isColored() bool {
+	isColored := f.ForceColors || f.isTerminal
+
+	if f.EnvironmentOverrideColors {
+		if force, ok := os.LookupEnv("CLICOLOR_FORCE"); ok && force != "0" {
+			isColored = true
+		} else if ok && force == "0" {
+			isColored = false
+		} else if os.Getenv("CLICOLOR") == "0" {
+			isColored = false
+		}
 	}
+
+	return isColored && !f.DisableColors
 }
 
 // Format renders a single log entry
 func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
-	var b *bytes.Buffer
+	prefixFieldClashes(entry.Data, f.FieldMap)
+
 	keys := make([]string, 0, len(entry.Data))
 	for k := range entry.Data {
 		keys = append(keys, k)
 	}
 
+	fixedKeys := make([]string, 0, 3+len(entry.Data))
+	if !f.DisableTimestamp {
+		fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
+	}
+	fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLevel))
+	if entry.Message != "" {
+		fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyMsg))
+	}
+
 	if !f.DisableSorting {
-		sort.Strings(keys)
+		if f.SortingFunc == nil {
+			sort.Strings(keys)
+			fixedKeys = append(fixedKeys, keys...)
+		} else {
+			if !f.isColored() {
+				fixedKeys = append(fixedKeys, keys...)
+				f.SortingFunc(fixedKeys)
+			} else {
+				f.SortingFunc(keys)
+			}
+		}
+	} else {
+		fixedKeys = append(fixedKeys, keys...)
 	}
+
+	var b *bytes.Buffer
 	if entry.Buffer != nil {
 		b = entry.Buffer
 	} else {
 		b = &bytes.Buffer{}
 	}
 
-	prefixFieldClashes(entry.Data)
-
-	f.Do(func() { f.init(entry) })
-
-	isColored := (f.ForceColors || f.isTerminal) && !f.DisableColors
+	f.terminalInitOnce.Do(func() { f.init(entry) })
 
 	timestampFormat := f.TimestampFormat
 	if timestampFormat == "" {
 		timestampFormat = defaultTimestampFormat
 	}
-	if isColored {
+	if f.isColored() {
 		f.printColored(b, entry, keys, timestampFormat)
 	} else {
-		if !f.DisableTimestamp {
-			f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat))
-		}
-		f.appendKeyValue(b, "level", entry.Level.String())
-		if entry.Message != "" {
-			f.appendKeyValue(b, "msg", entry.Message)
-		}
-		for _, key := range keys {
-			f.appendKeyValue(b, key, entry.Data[key])
+		for _, key := range fixedKeys {
+			var value interface{}
+			switch key {
+			case f.FieldMap.resolve(FieldKeyTime):
+				value = entry.Time.Format(timestampFormat)
+			case f.FieldMap.resolve(FieldKeyLevel):
+				value = entry.Level.String()
+			case f.FieldMap.resolve(FieldKeyMsg):
+				value = entry.Message
+			default:
+				value = entry.Data[key]
+			}
+			f.appendKeyValue(b, key, value)
 		}
 	}
 
@@ -137,7 +188,14 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
 		levelColor = blue
 	}
 
-	levelText := strings.ToUpper(entry.Level.String())[0:4]
+	levelText := strings.ToUpper(entry.Level.String())
+	if !f.DisableLevelTruncation {
+		levelText = levelText[0:4]
+	}
+
+	// Remove a single newline if it already exists in the message to keep
+	// the behavior of logrus text_formatter the same as the stdlib log package
+	entry.Message = strings.TrimSuffix(entry.Message, "\n")
 
 	if f.DisableTimestamp {
 		fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter_test.go b/vendor/github.com/Sirupsen/logrus/text_formatter_test.go
index d93b931e..b0d3a916 100644
--- a/vendor/github.com/Sirupsen/logrus/text_formatter_test.go
+++ b/vendor/github.com/Sirupsen/logrus/text_formatter_test.go
@@ -4,9 +4,14 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
+	"os"
+	"sort"
 	"strings"
 	"testing"
 	"time"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestFormatting(t *testing.T) {
@@ -128,6 +133,44 @@ func TestTimestampFormat(t *testing.T) {
 	checkTimeStr("")
 }
 
+func TestDisableLevelTruncation(t *testing.T) {
+	entry := &Entry{
+		Time:    time.Now(),
+		Message: "testing",
+	}
+	keys := []string{}
+	timestampFormat := "Mon Jan 2 15:04:05 -0700 MST 2006"
+	checkDisableTruncation := func(disabled bool, level Level) {
+		tf := &TextFormatter{DisableLevelTruncation: disabled}
+		var b bytes.Buffer
+		entry.Level = level
+		tf.printColored(&b, entry, keys, timestampFormat)
+		logLine := (&b).String()
+		if disabled {
+			expected := strings.ToUpper(level.String())
+			if !strings.Contains(logLine, expected) {
+				t.Errorf("level string expected to be %s when truncation disabled", expected)
+			}
+		} else {
+			expected := strings.ToUpper(level.String())
+			if len(level.String()) > 4 {
+				if strings.Contains(logLine, expected) {
+					t.Errorf("level string %s expected to be truncated to %s when truncation is enabled", expected, expected[0:4])
+				}
+			} else {
+				if !strings.Contains(logLine, expected) {
+					t.Errorf("level string expected to be %s when truncation is enabled and level string is below truncation threshold", expected)
+				}
+			}
+		}
+	}
+
+	checkDisableTruncation(true, DebugLevel)
+	checkDisableTruncation(true, InfoLevel)
+	checkDisableTruncation(false, ErrorLevel)
+	checkDisableTruncation(false, InfoLevel)
+}
+
 func TestDisableTimestampWithColoredOutput(t *testing.T) {
 	tf := &TextFormatter{DisableTimestamp: true, ForceColors: true}
 
@@ -137,5 +180,301 @@ func TestDisableTimestampWithColoredOutput(t *testing.T) {
 	}
 }
 
-// TODO add tests for sorting etc., this requires a parser for the text
-// formatter output.
+func TestNewlineBehavior(t *testing.T) {
+	tf := &TextFormatter{ForceColors: true}
+
+	// Ensure a single new line is removed as per stdlib log
+	e := NewEntry(StandardLogger())
+	e.Message = "test message\n"
+	b, _ := tf.Format(e)
+	if bytes.Contains(b, []byte("test message\n")) {
+		t.Error("first newline at end of Entry.Message resulted in unexpected 2 newlines in output. Expected newline to be removed.")
+	}
+
+	// Ensure a double new line is reduced to a single new line
+	e = NewEntry(StandardLogger())
+	e.Message = "test message\n\n"
+	b, _ = tf.Format(e)
+	if bytes.Contains(b, []byte("test message\n\n")) {
+		t.Error("Double newline at end of Entry.Message resulted in unexpected 2 newlines in output. Expected single newline")
+	}
+	if !bytes.Contains(b, []byte("test message\n")) {
+		t.Error("Double newline at end of Entry.Message did not result in a single newline after formatting")
+	}
+}
+
+func TestTextFormatterFieldMap(t *testing.T) {
+	formatter := &TextFormatter{
+		DisableColors: true,
+		FieldMap: FieldMap{
+			FieldKeyMsg:   "message",
+			FieldKeyLevel: "somelevel",
+			FieldKeyTime:  "timeywimey",
+		},
+	}
+
+	entry := &Entry{
+		Message: "oh hi",
+		Level:   WarnLevel,
+		Time:    time.Date(1981, time.February, 24, 4, 28, 3, 100, time.UTC),
+		Data: Fields{
+			"field1":     "f1",
+			"message":    "messagefield",
+			"somelevel":  "levelfield",
+			"timeywimey": "timeywimeyfield",
+		},
+	}
+
+	b, err := formatter.Format(entry)
+	if err != nil {
+		t.Fatal("Unable to format entry: ", err)
+	}
+
+	assert.Equal(t,
+		`timeywimey="1981-02-24T04:28:03Z" `+
+			`somelevel=warning `+
+			`message="oh hi" `+
+			`field1=f1 `+
+			`fields.message=messagefield `+
+			`fields.somelevel=levelfield `+
+			`fields.timeywimey=timeywimeyfield`+"\n",
+		string(b),
+		"Formatted output doesn't respect FieldMap")
+}
+
+func TestTextFormatterIsColored(t *testing.T) {
+	params := []struct {
+		name               string
+		expectedResult     bool
+		isTerminal         bool
+		disableColor       bool
+		forceColor         bool
+		envColor           bool
+		clicolorIsSet      bool
+		clicolorForceIsSet bool
+		clicolorVal        string
+		clicolorForceVal   string
+	}{
+		// Default values
+		{
+			name:               "testcase1",
+			expectedResult:     false,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           false,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: false,
+		},
+		// Output on terminal
+		{
+			name:               "testcase2",
+			expectedResult:     true,
+			isTerminal:         true,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           false,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: false,
+		},
+		// Output on terminal with color disabled
+		{
+			name:               "testcase3",
+			expectedResult:     false,
+			isTerminal:         true,
+			disableColor:       true,
+			forceColor:         false,
+			envColor:           false,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: false,
+		},
+		// Output not on terminal with color disabled
+		{
+			name:               "testcase4",
+			expectedResult:     false,
+			isTerminal:         false,
+			disableColor:       true,
+			forceColor:         false,
+			envColor:           false,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: false,
+		},
+		// Output not on terminal with color forced
+		{
+			name:               "testcase5",
+			expectedResult:     true,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         true,
+			envColor:           false,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: false,
+		},
+		// Output on terminal with clicolor set to "0"
+		{
+			name:               "testcase6",
+			expectedResult:     false,
+			isTerminal:         true,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           true,
+			clicolorIsSet:      true,
+			clicolorForceIsSet: false,
+			clicolorVal:        "0",
+		},
+		// Output on terminal with clicolor set to "1"
+		{
+			name:               "testcase7",
+			expectedResult:     true,
+			isTerminal:         true,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           true,
+			clicolorIsSet:      true,
+			clicolorForceIsSet: false,
+			clicolorVal:        "1",
+		},
+		// Output not on terminal with clicolor set to "0"
+		{
+			name:               "testcase8",
+			expectedResult:     false,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           true,
+			clicolorIsSet:      true,
+			clicolorForceIsSet: false,
+			clicolorVal:        "0",
+		},
+		// Output not on terminal with clicolor set to "1"
+		{
+			name:               "testcase9",
+			expectedResult:     false,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           true,
+			clicolorIsSet:      true,
+			clicolorForceIsSet: false,
+			clicolorVal:        "1",
+		},
+		// Output not on terminal with clicolor set to "1" and force color
+		{
+			name:               "testcase10",
+			expectedResult:     true,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         true,
+			envColor:           true,
+			clicolorIsSet:      true,
+			clicolorForceIsSet: false,
+			clicolorVal:        "1",
+		},
+		// Output not on terminal with clicolor set to "0" and force color
+		{
+			name:               "testcase11",
+			expectedResult:     false,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         true,
+			envColor:           true,
+			clicolorIsSet:      true,
+			clicolorForceIsSet: false,
+			clicolorVal:        "0",
+		},
+		// Output not on terminal with clicolor_force set to "1"
+		{
+			name:               "testcase12",
+			expectedResult:     true,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           true,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: true,
+			clicolorForceVal:   "1",
+		},
+		// Output not on terminal with clicolor_force set to "0"
+		{
+			name:               "testcase13",
+			expectedResult:     false,
+			isTerminal:         false,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           true,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: true,
+			clicolorForceVal:   "0",
+		},
+		// Output on terminal with clicolor_force set to "0"
+		{
+			name:               "testcase14",
+			expectedResult:     false,
+			isTerminal:         true,
+			disableColor:       false,
+			forceColor:         false,
+			envColor:           true,
+			clicolorIsSet:      false,
+			clicolorForceIsSet: true,
+			clicolorForceVal:   "0",
+		},
+	}
+
+	cleanenv := func() {
+		os.Unsetenv("CLICOLOR")
+		os.Unsetenv("CLICOLOR_FORCE")
+	}
+
+	defer cleanenv()
+
+	for _, val := range params {
+		t.Run("textformatter_"+val.name, func(subT *testing.T) {
+			tf := TextFormatter{
+				isTerminal:                val.isTerminal,
+				DisableColors:             val.disableColor,
+				ForceColors:               val.forceColor,
+				EnvironmentOverrideColors: val.envColor,
+			}
+			cleanenv()
+			if val.clicolorIsSet {
+				os.Setenv("CLICOLOR", val.clicolorVal)
+			}
+			if val.clicolorForceIsSet {
+				os.Setenv("CLICOLOR_FORCE", val.clicolorForceVal)
+			}
+			res := tf.isColored()
+			assert.Equal(subT, val.expectedResult, res)
+		})
+	}
+}
+
+func TestCustomSorting(t *testing.T) {
+	formatter := &TextFormatter{
+		DisableColors: true,
+		SortingFunc: func(keys []string) {
+			sort.Slice(keys, func(i, j int) bool {
+				if keys[j] == "prefix" {
+					return false
+				}
+				if keys[i] == "prefix" {
+					return true
+				}
+				return strings.Compare(keys[i], keys[j]) == -1
+			})
+		},
+	}
+
+	entry := &Entry{
+		Message: "Testing custom sort function",
+		Time:    time.Now(),
+		Level:   InfoLevel,
+		Data: Fields{
+			"test":      "testvalue",
+			"prefix":    "the application prefix",
+			"blablabla": "blablabla",
+		},
+	}
+	b, err := formatter.Format(entry)
+	require.NoError(t, err)
+	require.True(t, strings.HasPrefix(string(b), "prefix="), "format output is %q", string(b))
+}
diff --git a/vendor/github.com/go-ble/ble/.travis.yml b/vendor/github.com/go-ble/ble/.travis.yml
index 37dfd94c..d9b98257 100644
--- a/vendor/github.com/go-ble/ble/.travis.yml
+++ b/vendor/github.com/go-ble/ble/.travis.yml
@@ -4,7 +4,6 @@ os:
         - linux
 
 go:
-        - 1.7
         - 1.8
         - 1.9
         - tip
diff --git a/vendor/github.com/go-ble/ble/client.go b/vendor/github.com/go-ble/ble/client.go
index b8e4f316..8b2214c8 100644
--- a/vendor/github.com/go-ble/ble/client.go
+++ b/vendor/github.com/go-ble/ble/client.go
@@ -66,4 +66,7 @@ type Client interface {
 
 	// Disconnected returns a receiving channel, which is closed when the client disconnects.
 	Disconnected() <-chan struct{}
+
+	// Conn returns the client's current connection.
+	Conn() Conn
 }
diff --git a/vendor/github.com/go-ble/ble/darwin/client.go b/vendor/github.com/go-ble/ble/darwin/client.go
index 4934a600..43097894 100644
--- a/vendor/github.com/go-ble/ble/darwin/client.go
+++ b/vendor/github.com/go-ble/ble/darwin/client.go
@@ -176,6 +176,7 @@ func (cln *Client) ReadCharacteristic(c *ble.Characteristic) ([]byte, error) {
 	if rsp.err() != nil {
 		return nil, rsp.err()
 	}
+	c.Value = rsp.data()
 	return rsp.data(), nil
 }
 
@@ -215,6 +216,7 @@ func (cln *Client) ReadDescriptor(d *ble.Descriptor) ([]byte, error) {
 	if err := rsp.err(); err != nil {
 		return nil, err
 	}
+	d.Value = rsp.data()
 	return rsp.data(), nil
 }
 
@@ -318,6 +320,11 @@ func (cln *Client) Disconnected() <-chan struct{} {
 	return cln.conn.Disconnected()
 }
 
+// Conn returns the client's current connection.
+func (cln *Client) Conn() ble.Conn {
+	return cln.conn
+}
+
 type sub struct {
 	fn   ble.NotificationHandler
 	char *ble.Characteristic
diff --git a/vendor/github.com/go-ble/ble/darwin/conn.go b/vendor/github.com/go-ble/ble/darwin/conn.go
index 96079818..597f186e 100644
--- a/vendor/github.com/go-ble/ble/darwin/conn.go
+++ b/vendor/github.com/go-ble/ble/darwin/conn.go
@@ -9,10 +9,10 @@ import (
 	"github.com/raff/goble/xpc"
 )
 
-func newConn(d *Device, a ble.Addr) *conn {
+func newConn(d *Device, a ble.Addr, rxMTU int) *conn {
 	return &conn{
 		dev:   d,
-		rxMTU: 23,
+		rxMTU: rxMTU,
 		txMTU: 23,
 		addr:  a,
 		done:  make(chan struct{}),
@@ -43,6 +43,8 @@ type conn struct {
 	notifiers map[uint16]ble.Notifier // central connection only
 
 	subs map[uint16]*sub
+
+	isConnected bool
 }
 
 func (c *conn) Context() context.Context {
@@ -75,7 +77,9 @@ func (c *conn) TxMTU() int {
 }
 
 func (c *conn) SetTxMTU(mtu int) {
+	c.Lock()
 	c.txMTU = mtu
+	c.Unlock()
 }
 
 func (c *conn) Read(b []byte) (int, error) {
diff --git a/vendor/github.com/go-ble/ble/darwin/device.go b/vendor/github.com/go-ble/ble/darwin/device.go
index c94abc61..f6e941a3 100644
--- a/vendor/github.com/go-ble/ble/darwin/device.go
+++ b/vendor/github.com/go-ble/ble/darwin/device.go
@@ -37,7 +37,7 @@ type Device struct {
 }
 
 // NewDevice returns a BLE device.
-func NewDevice(opts ...Option) (*Device, error) {
+func NewDevice(opts ...ble.Option) (*Device, error) {
 	err := initXpcIDs()
 	if err != nil {
 		return nil, err
@@ -61,7 +61,7 @@ func NewDevice(opts ...Option) (*Device, error) {
 }
 
 // Option sets the options specified.
-func (d *Device) Option(opts ...Option) error {
+func (d *Device) Option(opts ...ble.Option) error {
 	var err error
 	for _, opt := range opts {
 		err = opt(d)
@@ -489,10 +489,15 @@ func (d *Device) HandleXpcEvent(event xpc.Dict, err error) {
 		d.conn(args).unsubscribed(d.chars[args.attributeID()])
 
 	case evtPeripheralConnected:
-		d.chConn <- d.conn(args)
+		c := d.conn(args)
+		if !c.isConnected {
+			c.isConnected = true
+			d.chConn <- c
+		}
 
 	case evtPeripheralDisconnected:
 		c := d.conn(args)
+		c.isConnected = false
 		select {
 		case c.rspc <- m:
 			// Canceled by local central synchronously
@@ -541,7 +546,7 @@ func (d *Device) conn(m msg) *conn {
 	d.connLock.Lock()
 	c, ok := d.conns[a.String()]
 	if !ok {
-		c = newConn(d, a)
+		c = newConn(d, a, m.attMTU())
 		d.conns[a.String()] = c
 	}
 	d.connLock.Unlock()
diff --git a/vendor/github.com/go-ble/ble/darwin/msg.go b/vendor/github.com/go-ble/ble/darwin/msg.go
index 9360b511..87b3c5a1 100644
--- a/vendor/github.com/go-ble/ble/darwin/msg.go
+++ b/vendor/github.com/go-ble/ble/darwin/msg.go
@@ -12,7 +12,12 @@ func (m msg) args() xpc.Dict { return xpc.Dict(m).MustGetDict("kCBMsgArgs") }
 func (m msg) advertisementData() xpc.Dict {
 	return xpc.Dict(m).MustGetDict("kCBMsgArgAdvertisementData")
 }
-func (m msg) attMTU() int          { return xpc.Dict(m).MustGetInt("kCBMsgArgATTMTU") }
+
+const macOSXDefaultMTU = 23
+
+// Uses GetInt as oppose to MustGetInt due to OSX not supporting 'kCBMsgArgATTMTU'.
+// Issue #29
+func (m msg) attMTU() int          { return xpc.Dict(m).GetInt("kCBMsgArgATTMTU", macOSXDefaultMTU) }
 func (m msg) attWrites() xpc.Array { return xpc.Dict(m).MustGetArray("kCBMsgArgATTWrites") }
 func (m msg) attributeID() int     { return xpc.Dict(m).MustGetInt("kCBMsgArgAttributeID") }
 func (m msg) characteristicHandle() int {
diff --git a/vendor/github.com/go-ble/ble/darwin/option.go b/vendor/github.com/go-ble/ble/darwin/option.go
index 924d1d5e..cdbdde31 100644
--- a/vendor/github.com/go-ble/ble/darwin/option.go
+++ b/vendor/github.com/go-ble/ble/darwin/option.go
@@ -1,20 +1,40 @@
 package darwin
 
-// An Option is a configuration function, which configures the device.
-type Option func(*Device) error
-
-// OptPeripheralRole configures the device to perform Peripheral tasks.
-func OptPeripheralRole() Option {
-	return func(d *Device) error {
-		d.role = 1
-		return nil
-	}
+import (
+	"errors"
+	"time"
+
+	"github.com/go-ble/ble/linux/hci/cmd"
+)
+
+// SetPeripheralRole configures the device to perform Peripheral tasks.
+func (d *Device) SetPeripheralRole() error {
+	d.role = 1
+	return nil
+}
+
+// SetCentralRole configures the device to perform Central tasks.
+func (d *Device) SetCentralRole() error {
+	d.role = 0
+	return nil
+}
+
+// SetDeviceID sets HCI device ID.
+func (d *Device) SetDeviceID(id int) error {
+	return errors.New("Not supported")
+}
+
+// SetDialerTimeout sets dialing timeout for Dialer.
+func (d *Device) SetDialerTimeout(dur time.Duration) error {
+	return errors.New("Not supported")
+}
+
+// SetListenerTimeout sets dialing timeout for Listener.
+func (d *Device) SetListenerTimeout(dur time.Duration) error {
+	return errors.New("Not supported")
 }
 
-// OptCentralRole configures the device to perform Central tasks.
-func OptCentralRole() Option {
-	return func(d *Device) error {
-		d.role = 0
-		return nil
-	}
+// SetConnParams overrides default connection parameters.
+func (d *Device) SetConnParams(param cmd.LECreateConnection) error {
+	return errors.New("Not supported")
 }
diff --git a/vendor/github.com/go-ble/ble/examples/blesh/lnx.go b/vendor/github.com/go-ble/ble/examples/blesh/lnx.go
index 9752ea12..e1d2cb0f 100644
--- a/vendor/github.com/go-ble/ble/examples/blesh/lnx.go
+++ b/vendor/github.com/go-ble/ble/examples/blesh/lnx.go
@@ -1,8 +1,8 @@
 package main
 
 import (
+	"github.com/go-ble/ble"
 	"github.com/go-ble/ble/linux"
-	"github.com/go-ble/ble/linux/hci"
 	"github.com/go-ble/ble/linux/hci/cmd"
 	"github.com/pkg/errors"
 )
@@ -31,7 +31,7 @@ func updateLinuxParam(d *linux.Device) error {
 		return errors.Wrap(err, "can't set scan param")
 	}
 
-	if err := d.HCI.Option(hci.OptConnParams(
+	if err := d.HCI.Option(ble.OptConnParams(
 		cmd.LECreateConnection{
 			LEScanInterval:        0x0004,    // 0x0004 - 0x4000; N * 0.625 msec
 			LEScanWindow:          0x0004,    // 0x0004 - 0x4000; N * 0.625 msec
diff --git a/vendor/github.com/go-ble/ble/examples/lib/dev/default_darwin.go b/vendor/github.com/go-ble/ble/examples/lib/dev/default_darwin.go
index 3ca967f9..dd46f76f 100644
--- a/vendor/github.com/go-ble/ble/examples/lib/dev/default_darwin.go
+++ b/vendor/github.com/go-ble/ble/examples/lib/dev/default_darwin.go
@@ -6,6 +6,6 @@ import (
 )
 
 // DefaultDevice ...
-func DefaultDevice() (d ble.Device, err error) {
-	return darwin.NewDevice()
+func DefaultDevice(opts ...ble.Option) (d ble.Device, err error) {
+	return darwin.NewDevice(opts...)
 }
diff --git a/vendor/github.com/go-ble/ble/examples/lib/dev/default_linux.go b/vendor/github.com/go-ble/ble/examples/lib/dev/default_linux.go
index c01e9bd9..eca7bf60 100644
--- a/vendor/github.com/go-ble/ble/examples/lib/dev/default_linux.go
+++ b/vendor/github.com/go-ble/ble/examples/lib/dev/default_linux.go
@@ -6,6 +6,6 @@ import (
 )
 
 // DefaultDevice ...
-func DefaultDevice() (d ble.Device, err error) {
-	return linux.NewDevice()
+func DefaultDevice(opts ...ble.Option) (d ble.Device, err error) {
+	return linux.NewDevice(opts...)
 }
diff --git a/vendor/github.com/go-ble/ble/examples/lib/dev/dev.go b/vendor/github.com/go-ble/ble/examples/lib/dev/dev.go
index e449a6a6..cd197e19 100644
--- a/vendor/github.com/go-ble/ble/examples/lib/dev/dev.go
+++ b/vendor/github.com/go-ble/ble/examples/lib/dev/dev.go
@@ -1,8 +1,10 @@
 package dev
 
-import "github.com/go-ble/ble"
+import (
+	"github.com/go-ble/ble"
+)
 
 // NewDevice ...
-func NewDevice(impl string) (d ble.Device, err error) {
-	return DefaultDevice()
+func NewDevice(impl string, opts ...ble.Option) (d ble.Device, err error) {
+	return DefaultDevice(opts...)
 }
diff --git a/vendor/github.com/go-ble/ble/linux/adv/packet.go b/vendor/github.com/go-ble/ble/linux/adv/packet.go
index 6ffc7535..f15e6159 100644
--- a/vendor/github.com/go-ble/ble/linux/adv/packet.go
+++ b/vendor/github.com/go-ble/ble/linux/adv/packet.go
@@ -185,6 +185,47 @@ func (p *Packet) Field(typ byte) []byte {
 	return nil
 }
 
+func (p *Packet) getUUIDsByType(typ byte, u []ble.UUID, w int) []ble.UUID {
+	pos := 0
+	var b []byte
+	for pos < len(p.b) {
+		if b, pos = p.fieldPos(typ, pos); b != nil {
+			u = uuidList(u, b, w)
+		}
+	}
+	return u
+}
+
+func (p *Packet) fieldPos(typ byte, offset int) ([]byte, int) {
+	if offset >= len(p.b) {
+		return nil, len(p.b)
+	}
+
+	b := p.b[offset:]
+	pos := offset
+
+	if len(b) < 2 {
+		return nil, pos + len(b)
+	}
+
+	for len(b) > 0 {
+		l, t := b[0], b[1]
+		if int(l) < 1 || len(b) < int(1+l) {
+			return nil, pos
+		}
+		if t == typ {
+			r := b[2 : 2+l-1]
+			return r, pos + 1 + int(l)
+		}
+		b = b[1+l:]
+		pos += 1 + int(l)
+		if len(b) < 2 {
+			break
+		}
+	}
+	return nil, pos
+}
+
 // Flags returns the flags of the packet.
 func (p *Packet) Flags() (flags byte, present bool) {
 	b := p.Field(flags)
@@ -214,24 +255,12 @@ func (p *Packet) TxPower() (power int, present bool) {
 // UUIDs returns a list of service UUIDs.
 func (p *Packet) UUIDs() []ble.UUID {
 	var u []ble.UUID
-	if b := p.Field(someUUID16); b != nil {
-		u = uuidList(u, b, 2)
-	}
-	if b := p.Field(allUUID16); b != nil {
-		u = uuidList(u, b, 2)
-	}
-	if b := p.Field(someUUID32); b != nil {
-		u = uuidList(u, b, 4)
-	}
-	if b := p.Field(allUUID32); b != nil {
-		u = uuidList(u, b, 4)
-	}
-	if b := p.Field(someUUID128); b != nil {
-		u = uuidList(u, b, 16)
-	}
-	if b := p.Field(allUUID128); b != nil {
-		u = uuidList(u, b, 16)
-	}
+	u = p.getUUIDsByType(someUUID16, u, 2)
+	u = p.getUUIDsByType(allUUID16, u, 2)
+	u = p.getUUIDsByType(someUUID32, u, 4)
+	u = p.getUUIDsByType(allUUID32, u, 4)
+	u = p.getUUIDsByType(someUUID128, u, 16)
+	u = p.getUUIDsByType(allUUID128, u, 16)
 	return u
 }
 
diff --git a/vendor/github.com/go-ble/ble/linux/att/db.go b/vendor/github.com/go-ble/ble/linux/att/db.go
index 93585a2f..bee9750a 100644
--- a/vendor/github.com/go-ble/ble/linux/att/db.go
+++ b/vendor/github.com/go-ble/ble/linux/att/db.go
@@ -25,7 +25,7 @@ func (r *DB) idx(h int) int {
 	if h < int(r.base) {
 		return tooSmall
 	}
-	if int(h) >= int(r.base)+len(r.attrs) {
+	if h >= int(r.base)+len(r.attrs) {
 		return tooLarge
 	}
 	return h - int(r.base)
diff --git a/vendor/github.com/go-ble/ble/linux/att/server.go b/vendor/github.com/go-ble/ble/linux/att/server.go
index 5056ebca..0ff0703d 100644
--- a/vendor/github.com/go-ble/ble/linux/att/server.go
+++ b/vendor/github.com/go-ble/ble/linux/att/server.go
@@ -302,7 +302,7 @@ func (s *Server) handleFindByTypeValueRequest(r FindByTypeValueRequest) []byte {
 
 	for _, a := range s.db.subrange(r.StartingHandle(), r.EndingHandle()) {
 		v, starth, endh := a.v, a.h, a.endh
-		if !(ble.UUID(a.typ).Equal(ble.UUID16(r.AttributeType()))) {
+		if !a.typ.Equal(ble.UUID16(r.AttributeType())) {
 			continue
 		}
 		if v == nil {
diff --git a/vendor/github.com/go-ble/ble/linux/device.go b/vendor/github.com/go-ble/ble/linux/device.go
index 521eb9f6..86fe565f 100644
--- a/vendor/github.com/go-ble/ble/linux/device.go
+++ b/vendor/github.com/go-ble/ble/linux/device.go
@@ -13,17 +13,17 @@ import (
 )
 
 // NewDevice returns the default HCI device.
-func NewDevice() (*Device, error) {
-	return NewDeviceWithName("Gopher")
+func NewDevice(opts ...ble.Option) (*Device, error) {
+	return NewDeviceWithName("Gopher", opts...)
 }
 
 // NewDeviceWithName returns the default HCI device.
-func NewDeviceWithName(name string) (*Device, error) {
-	return NewDeviceWithNameAndHandler(name, nil)
+func NewDeviceWithName(name string, opts ...ble.Option) (*Device, error) {
+	return NewDeviceWithNameAndHandler(name, nil, opts...)
 }
 
-func NewDeviceWithNameAndHandler(name string, handler ble.NotifyHandler) (*Device, error) {
-	dev, err := hci.NewHCI()
+func NewDeviceWithNameAndHandler(name string, handler ble.NotifyHandler, opts ...ble.Option) (*Device, error) {
+	dev, err := hci.NewHCI(opts...)
 	if err != nil {
 		return nil, errors.Wrap(err, "can't create hci")
 	}
diff --git a/vendor/github.com/go-ble/ble/linux/gatt/client.go b/vendor/github.com/go-ble/ble/linux/gatt/client.go
index 3ad108e1..e138d9e0 100644
--- a/vendor/github.com/go-ble/ble/linux/gatt/client.go
+++ b/vendor/github.com/go-ble/ble/linux/gatt/client.go
@@ -208,7 +208,13 @@ func (p *Client) DiscoverDescriptors(filter []ble.UUID, c *ble.Characteristic) (
 func (p *Client) ReadCharacteristic(c *ble.Characteristic) ([]byte, error) {
 	p.Lock()
 	defer p.Unlock()
-	return p.ac.Read(c.ValueHandle)
+	val, err := p.ac.Read(c.ValueHandle)
+	if err != nil {
+		return nil, err
+	}
+
+	c.Value = val
+	return val, nil
 }
 
 // ReadLongCharacteristic reads a characteristic value which is longer than the MTU. [Vol 3, Part G, 4.8.3]
@@ -231,6 +237,8 @@ func (p *Client) ReadLongCharacteristic(c *ble.Characteristic) ([]byte, error) {
 		}
 		buffer = append(buffer, read...)
 	}
+
+	c.Value = buffer
 	return buffer, nil
 }
 
@@ -248,7 +256,13 @@ func (p *Client) WriteCharacteristic(c *ble.Characteristic, v []byte, noRsp bool
 func (p *Client) ReadDescriptor(d *ble.Descriptor) ([]byte, error) {
 	p.Lock()
 	defer p.Unlock()
-	return p.ac.Read(d.Handle)
+	val, err := p.ac.Read(d.Handle)
+	if err != nil {
+		return nil, err
+	}
+
+	d.Value = val
+	return val, nil
 }
 
 // WriteDescriptor writes a characteristic descriptor to a server. [Vol 3, Part G, 4.12.3]
@@ -357,6 +371,11 @@ func (p *Client) Disconnected() <-chan struct{} {
 	return p.conn.Disconnected()
 }
 
+// Conn returns the client's current connection.
+func (p *Client) Conn() ble.Conn {
+	return p.conn
+}
+
 // HandleNotification ...
 func (p *Client) HandleNotification(req []byte) {
 	p.Lock()
diff --git a/vendor/github.com/go-ble/ble/linux/hci/conn.go b/vendor/github.com/go-ble/ble/linux/hci/conn.go
index 46a46f83..d6c39fc1 100644
--- a/vendor/github.com/go-ble/ble/linux/hci/conn.go
+++ b/vendor/github.com/go-ble/ble/linux/hci/conn.go
@@ -33,9 +33,6 @@ type Conn struct {
 	txMTU int
 	rxMPS int
 
-	// leFrame is set to be true when the LE Credit based flow control is used.
-	leFrame bool
-
 	// Signaling MTUs are The maximum size of command information that the
 	// L2CAP layer entity is capable of accepting.
 	// A L2CAP implementations supporting LE-U should support at least 23 bytes.
@@ -47,23 +44,25 @@ type Conn struct {
 	sigRxMTU int
 	sigTxMTU int
 
-	// sigID is used to match responses with signaling requests.
-	// The requesting device sets this field and the responding device uses the
-	// same value in its response. Within each signalling channel a different
-	// Identifier shall be used for each successive command. [Vol 3, Part A, 4]
-	sigID uint8
-
 	sigSent chan []byte
-	smpSent chan []byte
+	// smpSent chan []byte
 
 	chInPkt chan packet
 	chInPDU chan pdu
 
+	chDone chan struct{}
 	// Host to Controller Data Flow Control pkt-based Data flow control for LE-U [Vol 2, Part E, 4.1.1]
 	// chSentBufs tracks the HCI buffer occupied by this connection.
 	txBuffer *Client
 
-	chDone chan struct{}
+	// sigID is used to match responses with signaling requests.
+	// The requesting device sets this field and the responding device uses the
+	// same value in its response. Within each signalling channel a different
+	// Identifier shall be used for each successive command. [Vol 3, Part A, 4]
+	sigID uint8
+
+	// leFrame is set to be true when the LE Credit based flow control is used.
+	leFrame bool
 }
 
 func newConn(h *HCI, param evt.LEConnectionComplete) *Conn {
@@ -94,7 +93,7 @@ func newConn(h *HCI, param evt.LEConnectionComplete) *Conn {
 				if err != io.EOF {
 					// TODO: wrap and pass the error up.
 					// err := errors.Wrap(err, "recombine failed")
-					logger.Error("recombine failed: ", "err", err)
+					_ = logger.Error("recombine failed: ", "err", err)
 				}
 				close(c.chInPDU)
 				return
@@ -140,7 +139,7 @@ func (c *Conn) Read(sdu []byte) (n int, err error) {
 	buf.Write(data)
 	for buf.Len() < slen {
 		p := <-c.chInPDU
-		buf.Write(pdu(p).payload())
+		buf.Write(p.payload())
 	}
 	return slen, nil
 }
@@ -205,10 +204,23 @@ func (c *Conn) writePDU(pdu []byte) (int, error) {
 		}
 
 		// Prepare the Headers
-		binary.Write(pkt, binary.LittleEndian, uint8(pktTypeACLData))                         // HCI Header: pkt Type
-		binary.Write(pkt, binary.LittleEndian, uint16(c.param.ConnectionHandle()|(flags<<8))) // ACL Header: handle and flags
-		binary.Write(pkt, binary.LittleEndian, uint16(flen))                                  // ACL Header: data len
-		binary.Write(pkt, binary.LittleEndian, pdu[:flen])                                    // Append payload
+
+		// HCI Header: pkt Type
+		if err := binary.Write(pkt, binary.LittleEndian, pktTypeACLData); err != nil {
+			return 0, err
+		}
+		// ACL Header: handle and flags
+		if err := binary.Write(pkt, binary.LittleEndian, c.param.ConnectionHandle()|(flags<<8)); err != nil {
+			return 0, err
+		}
+		// ACL Header: data len
+		if err := binary.Write(pkt, binary.LittleEndian, uint16(flen)); err != nil {
+			return 0, err
+		}
+		// Append payload
+		if err := binary.Write(pkt, binary.LittleEndian, pdu[:flen]); err != nil {
+			return 0, err
+		}
 
 		// Flush the pkt to HCI
 		select {
diff --git a/vendor/github.com/go-ble/ble/linux/hci/gap.go b/vendor/github.com/go-ble/ble/linux/hci/gap.go
index d114a0a0..6bb1f1ea 100644
--- a/vendor/github.com/go-ble/ble/linux/hci/gap.go
+++ b/vendor/github.com/go-ble/ble/linux/hci/gap.go
@@ -209,28 +209,35 @@ func (h *HCI) Dial(ctx context.Context, a ble.Addr) (ble.Client, error) {
 	if h.dialerTmo != time.Duration(0) {
 		tmo = time.After(h.dialerTmo)
 	}
+
 	select {
 	case <-ctx.Done():
-		return nil, ctx.Err()
+		return h.cancelDial()
+	case <-tmo:
+		return h.cancelDial()
 	case <-h.done:
 		return nil, h.err
 	case c := <-h.chMasterConn:
 		return gatt.NewClient(c)
-	case <-tmo:
-		err := h.Send(&h.params.connCancel, nil)
-		if err == nil {
-			// The pending connection was canceled successfully.
-			return nil, fmt.Errorf("connection timed out")
-		}
-		// The connection has been established, the cancel command
-		// failed with ErrDisallowed.
-		if err == ErrDisallowed {
-			return gatt.NewClient(<-h.chMasterConn)
-		}
-		return nil, errors.Wrap(err, "cancel connection failed")
+
 	}
 }
 
+// cancelDial cancels the Dialing
+func (h *HCI) cancelDial() (ble.Client, error) {
+	err := h.Send(&h.params.connCancel, nil)
+	if err == nil {
+		// The pending connection was canceled successfully.
+		return nil, fmt.Errorf("connection canceled")
+	}
+	// The connection has been established, the cancel command
+	// failed with ErrDisallowed.
+	if err == ErrDisallowed {
+		return gatt.NewClient(<-h.chMasterConn)
+	}
+	return nil, errors.Wrap(err, "cancel connection failed")
+}
+
 // Advertise starts advertising.
 func (h *HCI) Advertise() error {
 	h.params.advEnable.AdvertisingEnable = 1
diff --git a/vendor/github.com/go-ble/ble/linux/hci/hci.go b/vendor/github.com/go-ble/ble/linux/hci/hci.go
index 3e5b9fdb..4abd8491 100644
--- a/vendor/github.com/go-ble/ble/linux/hci/hci.go
+++ b/vendor/github.com/go-ble/ble/linux/hci/hci.go
@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"io"
 	"net"
+	"strings"
 	"sync"
 	"time"
 
@@ -34,13 +35,14 @@ type pkt struct {
 }
 
 // NewHCI returns a hci device.
-func NewHCI(opts ...Option) (*HCI, error) {
+func NewHCI(opts ...ble.Option) (*HCI, error) {
 	h := &HCI{
 		id: -1,
 
 		chCmdPkt:  make(chan *pkt),
-		chCmdBufs: make(chan []byte, 8),
+		chCmdBufs: make(chan []byte, 16),
 		sent:      make(map[int]*pkt),
+		muSent:    &sync.Mutex{},
 
 		evth: map[int]handlerFn{},
 		subh: map[int]handlerFn{},
@@ -72,6 +74,7 @@ type HCI struct {
 	// Host to Controller command flow control [Vol 2, Part E, 4.4]
 	chCmdPkt  chan *pkt
 	chCmdBufs chan []byte
+	muSent    *sync.Mutex
 	sent      map[int]*pkt
 
 	// evtHub
@@ -168,7 +171,7 @@ func (h *HCI) Error() error {
 }
 
 // Option sets the options specified.
-func (h *HCI) Option(opts ...Option) error {
+func (h *HCI) Option(opts ...ble.Option) error {
 	var err error
 	for _, opt := range opts {
 		err = opt(h)
@@ -247,7 +250,9 @@ func (h *HCI) send(c Command) ([]byte, error) {
 		h.close(fmt.Errorf("hci: failed to marshal cmd"))
 	}
 
-	h.sent[c.OpCode()] = p // TODO: lock
+	h.muSent.Lock()
+	h.sent[c.OpCode()] = p
+	h.muSent.Unlock()
 	if n, err := h.skt.Write(b[:4+c.Len()]); err != nil {
 		h.close(fmt.Errorf("hci: failed to send cmd"))
 	} else if n != 4+c.Len() {
@@ -274,8 +279,14 @@ func (h *HCI) sktLoop() {
 		p := make([]byte, n)
 		copy(p, b)
 		if err := h.handlePkt(p); err != nil {
-			h.err = fmt.Errorf("skt: %s", err)
-			return
+			// Some bluetooth devices may append vendor specific packets at the last,
+			// in this case, simply ignore them.
+			if strings.HasPrefix(err.Error(), "unsupported vendor packet:") {
+				_ = logger.Error("skt: %v", err)
+			} else {
+				h.err = fmt.Errorf("skt: %v", err)
+				return
+			}
 		}
 	}
 }
@@ -310,7 +321,7 @@ func (h *HCI) handleACL(b []byte) error {
 	c, ok := h.conns[handle]
 	h.muConns.Unlock()
 	if !ok {
-		logger.Warn("invalid connection handle on ACL packet", "handle", handle)
+		_ = logger.Warn("invalid connection handle on ACL packet", "handle", handle)
 		return nil
 	}
 	c.chInPkt <- b
@@ -402,10 +413,12 @@ func (h *HCI) handleCommandComplete(b []byte) error {
 
 	// NOP command, used for flow control purpose [Vol 2, Part E, 4.4]
 	if e.CommandOpcode() == 0x0000 {
-		h.chCmdBufs = make(chan []byte, 8)
+		h.chCmdBufs = make(chan []byte, 16)
 		return nil
 	}
+	h.muSent.Lock()
 	p, found := h.sent[int(e.CommandOpcode())]
+	h.muSent.Unlock()
 	if !found {
 		return fmt.Errorf("can't find the cmd for CommandCompleteEP: % X", e)
 	}
@@ -419,7 +432,9 @@ func (h *HCI) handleCommandStatus(b []byte) error {
 		h.chCmdBufs <- make([]byte, 64)
 	}
 
+	h.muSent.Lock()
 	p, found := h.sent[int(e.CommandOpcode())]
+	h.muSent.Unlock()
 	if !found {
 		return fmt.Errorf("can't find the cmd for CommandStatusEP: % X", e)
 	}
@@ -435,7 +450,11 @@ func (h *HCI) handleLEConnectionComplete(b []byte) error {
 	h.muConns.Unlock()
 	if e.Role() == roleMaster {
 		if e.Status() == 0x00 {
-			h.chMasterConn <- c
+			select {
+			case h.chMasterConn <- c:
+			default:
+				go c.Close()
+			}
 			return nil
 		}
 		if ErrCommand(e.Status()) == ErrConnID {
@@ -479,7 +498,7 @@ func (h *HCI) handleDisconnectionComplete(b []byte) error {
 	}
 	close(c.chInPkt)
 
-	if c.param.Role() == roleMaster {
+	if c.param.Role() == roleSlave {
 		// Re-enable advertising, if it was advertising. Refer to the
 		// handleLEConnectionComplete() for details.
 		// This may failed with ErrCommandDisallowed, if the controller
diff --git a/vendor/github.com/go-ble/ble/linux/hci/option.go b/vendor/github.com/go-ble/ble/linux/hci/option.go
index b0f4832b..d765d803 100644
--- a/vendor/github.com/go-ble/ble/linux/hci/option.go
+++ b/vendor/github.com/go-ble/ble/linux/hci/option.go
@@ -1,42 +1,42 @@
 package hci
 
 import (
+	"errors"
 	"time"
 
 	"github.com/go-ble/ble/linux/hci/cmd"
 )
 
-// An Option is a configuration function, which configures the device.
-type Option func(*HCI) error
+// SetDeviceID sets HCI device ID.
+func (h *HCI) SetDeviceID(id int) error {
+	h.id = id
+	return nil
+}
+
+// SetDialerTimeout sets dialing timeout for Dialer.
+func (h *HCI) SetDialerTimeout(d time.Duration) error {
+	h.dialerTmo = d
+	return nil
+}
 
-// OptDeviceID sets HCI device ID.
-func OptDeviceID(id int) Option {
-	return func(h *HCI) error {
-		h.id = id
-		return nil
-	}
+// SetListenerTimeout sets dialing timeout for Listener.
+func (h *HCI) SetListenerTimeout(d time.Duration) error {
+	h.listenerTmo = d
+	return nil
 }
 
-// OptDialerTimeout sets dialing timeout for Dialer.
-func OptDialerTimeout(d time.Duration) Option {
-	return func(h *HCI) error {
-		h.dialerTmo = d
-		return nil
-	}
+// SetConnParams overrides default connection parameters.
+func (h *HCI) SetConnParams(param cmd.LECreateConnection) error {
+	h.params.connParams = param
+	return nil
 }
 
-// OptListenerTimeout sets dialing timeout for Listener.
-func OptListenerTimeout(d time.Duration) Option {
-	return func(h *HCI) error {
-		h.listenerTmo = d
-		return nil
-	}
+// SetPeripheralRole is not supported
+func (h *HCI) SetPeripheralRole() error {
+	return errors.New("Not supported")
 }
 
-// OptConnParams overrides default connection parameters.
-func OptConnParams(param cmd.LECreateConnection) Option {
-	return func(h *HCI) error {
-		h.params.connParams = param
-		return nil
-	}
+// SetCentralRole is not supported
+func (h *HCI) SetCentralRole() error {
+	return errors.New("Not supported")
 }
diff --git a/vendor/github.com/go-ble/ble/linux/hci/signal.go b/vendor/github.com/go-ble/ble/linux/hci/signal.go
index 0badb585..9a18745c 100644
--- a/vendor/github.com/go-ble/ble/linux/hci/signal.go
+++ b/vendor/github.com/go-ble/ble/linux/hci/signal.go
@@ -13,7 +13,7 @@ import (
 // Signal ...
 type Signal interface {
 	Code() int
-	Marshal() []byte
+	Marshal() ([]byte, error)
 	Unmarshal([]byte) error
 }
 
@@ -26,15 +26,30 @@ func (s sigCmd) data() []byte { return s[4 : 4+s.len()] }
 
 // Signal ...
 func (c *Conn) Signal(req Signal, rsp Signal) error {
-	data := req.Marshal()
+	data, err := req.Marshal()
+	if err != nil {
+		return err
+	}
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, uint16(4+len(data)))
-	binary.Write(buf, binary.LittleEndian, uint16(cidLESignal))
+	if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(data))); err != nil {
+		return err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, cidLESignal); err != nil {
+		return err
+	}
 
-	binary.Write(buf, binary.LittleEndian, uint8(req.Code()))
-	binary.Write(buf, binary.LittleEndian, uint8(c.sigID))
-	binary.Write(buf, binary.LittleEndian, uint16(len(data)))
-	binary.Write(buf, binary.LittleEndian, data)
+	if err := binary.Write(buf, binary.LittleEndian, uint8(req.Code())); err != nil {
+		return err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, uint8(c.sigID)); err != nil {
+		return err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, uint16(len(data))); err != nil {
+		return err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, data); err != nil {
+		return err
+	}
 
 	c.sigSent = make(chan []byte)
 	defer close(c.sigSent)
@@ -63,13 +78,26 @@ func (c *Conn) Signal(req Signal, rsp Signal) error {
 }
 
 func (c *Conn) sendResponse(code uint8, id uint8, r Signal) (int, error) {
-	data := r.Marshal()
+	data, err := r.Marshal()
+	if err != nil {
+		return 0, err
+	}
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, uint16(4+len(data)))
-	binary.Write(buf, binary.LittleEndian, uint16(cidLESignal))
-	binary.Write(buf, binary.LittleEndian, uint8(code))
-	binary.Write(buf, binary.LittleEndian, uint8(id))
-	binary.Write(buf, binary.LittleEndian, uint16(len(data)))
+	if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(data))); err != nil {
+		return 0, err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, cidLESignal); err != nil {
+		return 0, err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, code); err != nil {
+		return 0, err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, id); err != nil {
+		return 0, err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, uint16(len(data))); err != nil {
+		return 0, err
+	}
 	if err := binary.Write(buf, binary.LittleEndian, data); err != nil {
 		return 0, err
 	}
@@ -85,13 +113,16 @@ func (c *Conn) handleSignal(p pdu) error {
 	// command in the L2CAP packet. If only Responses are recognized, the packet
 	// shall be silently discarded. [Vol3, Part A, 4.1]
 	if p.dlen() > c.sigRxMTU {
-		c.sendResponse(
+		_, err := c.sendResponse(
 			SignalCommandReject,
 			sigCmd(p.payload()).id(),
 			&CommandReject{
 				Reason: 0x0001,                                            // Signaling MTU exceeded.
 				Data:   []byte{uint8(c.sigRxMTU), uint8(c.sigRxMTU >> 8)}, // Actual MTUsig.
 			})
+		if err != nil {
+			_ = logger.Error("send repsonse", fmt.Sprintf("%v", err))
+		}
 		return nil
 	}
 
diff --git a/vendor/github.com/go-ble/ble/linux/hci/signal_gen.go b/vendor/github.com/go-ble/ble/linux/hci/signal_gen.go
index 6f2d988c..ed1d828a 100644
--- a/vendor/github.com/go-ble/ble/linux/hci/signal_gen.go
+++ b/vendor/github.com/go-ble/ble/linux/hci/signal_gen.go
@@ -18,10 +18,12 @@ type CommandReject struct {
 func (s CommandReject) Code() int { return 0x01 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *CommandReject) Marshal() []byte {
+func (s *CommandReject) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
@@ -42,10 +44,12 @@ type DisconnectRequest struct {
 func (s DisconnectRequest) Code() int { return 0x06 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *DisconnectRequest) Marshal() []byte {
+func (s *DisconnectRequest) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
@@ -66,10 +70,12 @@ type DisconnectResponse struct {
 func (s DisconnectResponse) Code() int { return 0x07 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *DisconnectResponse) Marshal() []byte {
+func (s *DisconnectResponse) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
@@ -92,10 +98,12 @@ type ConnectionParameterUpdateRequest struct {
 func (s ConnectionParameterUpdateRequest) Code() int { return 0x12 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *ConnectionParameterUpdateRequest) Marshal() []byte {
+func (s *ConnectionParameterUpdateRequest) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
@@ -115,10 +123,12 @@ type ConnectionParameterUpdateResponse struct {
 func (s ConnectionParameterUpdateResponse) Code() int { return 0x13 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *ConnectionParameterUpdateResponse) Marshal() []byte {
+func (s *ConnectionParameterUpdateResponse) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
@@ -142,10 +152,12 @@ type LECreditBasedConnectionRequest struct {
 func (s LECreditBasedConnectionRequest) Code() int { return 0x14 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *LECreditBasedConnectionRequest) Marshal() []byte {
+func (s *LECreditBasedConnectionRequest) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
@@ -169,10 +181,12 @@ type LECreditBasedConnectionResponse struct {
 func (s LECreditBasedConnectionResponse) Code() int { return 0x15 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *LECreditBasedConnectionResponse) Marshal() []byte {
+func (s *LECreditBasedConnectionResponse) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
@@ -193,10 +207,12 @@ type LEFlowControlCredit struct {
 func (s LEFlowControlCredit) Code() int { return 0x16 }
 
 // Marshal serializes the command parameters into binary form.
-func (s *LEFlowControlCredit) Marshal() []byte {
+func (s *LEFlowControlCredit) Marshal() ([]byte, error) {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, s)
-	return buf.Bytes()
+	if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
+		return nil, err
+	}
+	return buf.Bytes(), nil
 }
 
 // Unmarshal de-serializes the binary data and stores the result in the receiver.
diff --git a/vendor/github.com/go-ble/ble/linux/hci/smp.go b/vendor/github.com/go-ble/ble/linux/hci/smp.go
index 87a43f8e..8e3950e0 100644
--- a/vendor/github.com/go-ble/ble/linux/hci/smp.go
+++ b/vendor/github.com/go-ble/ble/linux/hci/smp.go
@@ -25,9 +25,15 @@ const (
 
 func (c *Conn) sendSMP(p pdu) error {
 	buf := bytes.NewBuffer(make([]byte, 0))
-	binary.Write(buf, binary.LittleEndian, uint16(4+len(p)))
-	binary.Write(buf, binary.LittleEndian, cidSMP)
-	binary.Write(buf, binary.LittleEndian, p)
+	if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(p))); err != nil {
+		return err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, cidSMP); err != nil {
+		return err
+	}
+	if err := binary.Write(buf, binary.LittleEndian, p); err != nil {
+		return err
+	}
 	_, err := c.writePDU(buf.Bytes())
 	logger.Debug("smp", "send", fmt.Sprintf("[%X]", buf.Bytes()))
 	return err
diff --git a/vendor/github.com/go-ble/ble/option.go b/vendor/github.com/go-ble/ble/option.go
new file mode 100644
index 00000000..f301c7f6
--- /dev/null
+++ b/vendor/github.com/go-ble/ble/option.go
@@ -0,0 +1,68 @@
+package ble
+
+import (
+	"time"
+
+	"github.com/go-ble/ble/linux/hci/cmd"
+)
+
+// DeviceOption is an interface which the device should implement to allow using configuration options
+type DeviceOption interface {
+	SetDeviceID(int) error
+	SetDialerTimeout(time.Duration) error
+	SetListenerTimeout(time.Duration) error
+	SetConnParams(cmd.LECreateConnection) error
+	SetPeripheralRole() error
+	SetCentralRole() error
+}
+
+// An Option is a configuration function, which configures the device.
+type Option func(DeviceOption) error
+
+// OptDeviceID sets HCI device ID.
+func OptDeviceID(id int) Option {
+	return func(opt DeviceOption) error {
+		opt.SetDeviceID(id)
+		return nil
+	}
+}
+
+// OptDialerTimeout sets dialing timeout for Dialer.
+func OptDialerTimeout(d time.Duration) Option {
+	return func(opt DeviceOption) error {
+		opt.SetDialerTimeout(d)
+		return nil
+	}
+}
+
+// OptListenerTimeout sets dialing timeout for Listener.
+func OptListenerTimeout(d time.Duration) Option {
+	return func(opt DeviceOption) error {
+		opt.SetListenerTimeout(d)
+		return nil
+	}
+}
+
+// OptConnParams overrides default connection parameters.
+func OptConnParams(param cmd.LECreateConnection) Option {
+	return func(opt DeviceOption) error {
+		opt.SetConnParams(param)
+		return nil
+	}
+}
+
+// OptPeripheralRole configures the device to perform Peripheral tasks.
+func OptPeripheralRole() Option {
+	return func(opt DeviceOption) error {
+		opt.SetPeripheralRole()
+		return nil
+	}
+}
+
+// OptCentralRole configures the device to perform Central tasks.
+func OptCentralRole() Option {
+	return func(opt DeviceOption) error {
+		opt.SetCentralRole()
+		return nil
+	}
+}
diff --git a/vendor/github.com/go-ble/ble/uuid.go b/vendor/github.com/go-ble/ble/uuid.go
index 79ebf33b..999c2623 100644
--- a/vendor/github.com/go-ble/ble/uuid.go
+++ b/vendor/github.com/go-ble/ble/uuid.go
@@ -84,15 +84,13 @@ func Contains(s []UUID, u UUID) bool {
 
 // Reverse returns a reversed copy of u.
 func Reverse(u []byte) []byte {
-	// Special-case 16 bit UUIDS for speed.
 	l := len(u)
-	if l == 2 {
-		return []byte{u[1], u[0]}
-	}
 	b := make([]byte, l)
-	for i := 0; i < l/2+1; i++ {
-		b[i], b[l-i-1] = u[l-i-1], u[i]
+
+	for i := 0; i < l; i++ {
+		b[l-i-1] = u[i]
 	}
+
 	return b
 }
 
diff --git a/vendor/github.com/go-ble/ble/uuid_test.go b/vendor/github.com/go-ble/ble/uuid_test.go
new file mode 100644
index 00000000..bb823d62
--- /dev/null
+++ b/vendor/github.com/go-ble/ble/uuid_test.go
@@ -0,0 +1,28 @@
+package ble
+
+import (
+	"bytes"
+	"testing"
+)
+
+var forward = [][]byte{
+	[]byte{1, 2, 3, 4, 5, 6},
+	[]byte{12, 143, 231, 123, 87, 124, 209},
+	[]byte{3, 43, 223, 12, 54},
+}
+
+var reverse = [][]byte{
+	[]byte{6, 5, 4, 3, 2, 1},
+	[]byte{209, 124, 87, 123, 231, 143, 12},
+	[]byte{54, 12, 223, 43, 3},
+}
+
+func TestReverse(t *testing.T) {
+
+	for i := 0; i < len(forward); i++ {
+		r := Reverse(forward[i])
+		if !bytes.Equal(r, reverse[i]) {
+			t.Errorf("Error: %v in reverse should be %v, but is: %v", forward[i], reverse[i], r)
+		}
+	}
+}
diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
new file mode 100644
index 00000000..949b77e3
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md
@@ -0,0 +1,40 @@
+# Windows Terminal Sequences
+
+This library allow for enabling Windows terminal color support for Go.
+
+See [Console Virtual Terminal Sequences](https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences) for details.
+
+## Usage
+
+```go
+import (
+	"syscall"
+	
+	sequences "github.com/konsorten/go-windows-terminal-sequences"
+)
+
+func main() {
+	sequences.EnableVirtualTerminalProcessing(syscall.Stdout, true)
+}
+
+```
+
+## Authors
+
+The tool is sponsored by the [marvin + konsorten GmbH](http://www.konsorten.de).
+
+We thank all the authors who provided code to this library:
+
+* Felix Kollmann
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2018 marvin + konsorten GmbH (open-source@konsorten.de)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/license b/vendor/github.com/konsorten/go-windows-terminal-sequences/license
new file mode 100644
index 00000000..14127cd8
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/license
@@ -0,0 +1,9 @@
+(The MIT License)
+
+Copyright (c) 2017 marvin + konsorten GmbH (open-source@konsorten.de)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
new file mode 100644
index 00000000..ef18d8f9
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences.go
@@ -0,0 +1,36 @@
+// +build windows
+
+package sequences
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+var (
+	kernel32Dll    *syscall.LazyDLL  = syscall.NewLazyDLL("Kernel32.dll")
+	setConsoleMode *syscall.LazyProc = kernel32Dll.NewProc("SetConsoleMode")
+)
+
+func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error {
+	const ENABLE_VIRTUAL_TERMINAL_PROCESSING uint32 = 0x4
+
+	var mode uint32
+	err := syscall.GetConsoleMode(syscall.Stdout, &mode)
+	if err != nil {
+		return err
+	}
+
+	if enable {
+		mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING
+	} else {
+		mode &^= ENABLE_VIRTUAL_TERMINAL_PROCESSING
+	}
+
+	ret, _, err := setConsoleMode.Call(uintptr(unsafe.Pointer(stream)), uintptr(mode))
+	if ret == 0 {
+		return err
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_test.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_test.go
new file mode 100644
index 00000000..aad41c5c
--- /dev/null
+++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_test.go
@@ -0,0 +1,48 @@
+// +build windows
+
+package sequences
+
+import (
+	"fmt"
+	"os"
+	"syscall"
+	"testing"
+)
+
+func TestStdoutSequencesOn(t *testing.T) {
+	err := EnableVirtualTerminalProcessing(syscall.Stdout, true)
+	if err != nil {
+		t.Fatalf("Failed to enable VTP: %v", err)
+	}
+	defer EnableVirtualTerminalProcessing(syscall.Stdout, false)
+
+	fmt.Fprintf(os.Stdout, "\x1b[34mHello \x1b[35mWorld\x1b[0m!\n")
+}
+
+func TestStdoutSequencesOff(t *testing.T) {
+	err := EnableVirtualTerminalProcessing(syscall.Stdout, false)
+	if err != nil {
+		t.Fatalf("Failed to enable VTP: %v", err)
+	}
+
+	fmt.Fprintf(os.Stdout, "\x1b[34mHello \x1b[35mWorld\x1b[0m!\n")
+}
+
+func TestStderrSequencesOn(t *testing.T) {
+	err := EnableVirtualTerminalProcessing(syscall.Stderr, true)
+	if err != nil {
+		t.Fatalf("Failed to enable VTP: %v", err)
+	}
+	defer EnableVirtualTerminalProcessing(syscall.Stderr, false)
+
+	fmt.Fprintf(os.Stderr, "\x1b[34mHello \x1b[35mWorld\x1b[0m!\n")
+}
+
+func TestStderrSequencesOff(t *testing.T) {
+	err := EnableVirtualTerminalProcessing(syscall.Stderr, false)
+	if err != nil {
+		t.Fatalf("Failed to enable VTP: %v", err)
+	}
+
+	fmt.Fprintf(os.Stderr, "\x1b[34mHello \x1b[35mWorld\x1b[0m!\n")
+}
diff --git a/vendor/github.com/kr/pretty/go.mod b/vendor/github.com/kr/pretty/go.mod
new file mode 100644
index 00000000..1e295331
--- /dev/null
+++ b/vendor/github.com/kr/pretty/go.mod
@@ -0,0 +1,3 @@
+module "github.com/kr/pretty"
+
+require "github.com/kr/text" v0.1.0
diff --git a/vendor/github.com/spf13/cast/cast_test.go b/vendor/github.com/spf13/cast/cast_test.go
index 404fe768..d9b0b013 100644
--- a/vendor/github.com/spf13/cast/cast_test.go
+++ b/vendor/github.com/spf13/cast/cast_test.go
@@ -697,6 +697,10 @@ func TestStringMapStringSliceE(t *testing.T) {
 	var stringMapInterface1 = map[string]interface{}{"key 1": []string{"value 1"}, "key 2": []string{"value 2"}}
 	var stringMapInterfaceResult1 = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2"}}
 
+	var jsonStringMapString = `{"key 1": "value 1", "key 2": "value 2"}`
+	var jsonStringMapStringArray = `{"key 1": ["value 1"], "key 2": ["value 2", "value 3"]}`
+	var jsonStringMapStringArrayResult = map[string][]string{"key 1": {"value 1"}, "key 2": {"value 2", "value 3"}}
+
 	type Key struct {
 		k string
 	}
@@ -718,11 +722,15 @@ func TestStringMapStringSliceE(t *testing.T) {
 		{interfaceMapInterfaceSlice, stringMapStringSlice, false},
 		{interfaceMapString, stringMapStringSingleSliceFieldsResult, false},
 		{interfaceMapInterface, stringMapStringSingleSliceFieldsResult, false},
+		{jsonStringMapStringArray, jsonStringMapStringArrayResult, false},
+
 		// errors
 		{nil, nil, true},
 		{testing.T{}, nil, true},
 		{map[interface{}]interface{}{"foo": testing.T{}}, nil, true},
 		{map[interface{}]interface{}{Key{"foo"}: "bar"}, nil, true}, // ToStringE(Key{"foo"}) should fail
+		{jsonStringMapString, nil, true},
+		{"", nil, true},
 	}
 
 	for i, test := range tests {
@@ -751,9 +759,13 @@ func TestToStringMapE(t *testing.T) {
 	}{
 		{map[interface{}]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
 		{map[string]interface{}{"tag": "tags", "group": "groups"}, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
+		{`{"tag": "tags", "group": "groups"}`, map[string]interface{}{"tag": "tags", "group": "groups"}, false},
+		{`{"tag": "tags", "group": true}`, map[string]interface{}{"tag": "tags", "group": true}, false},
+
 		// errors
 		{nil, nil, true},
 		{testing.T{}, nil, true},
+		{"", nil, true},
 	}
 
 	for i, test := range tests {
@@ -783,9 +795,12 @@ func TestToStringMapBoolE(t *testing.T) {
 		{map[interface{}]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
 		{map[string]interface{}{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
 		{map[string]bool{"v1": true, "v2": false}, map[string]bool{"v1": true, "v2": false}, false},
+		{`{"v1": true, "v2": false}`, map[string]bool{"v1": true, "v2": false}, false},
+
 		// errors
 		{nil, nil, true},
 		{testing.T{}, nil, true},
+		{"", nil, true},
 	}
 
 	for i, test := range tests {
@@ -811,6 +826,9 @@ func TestToStringMapStringE(t *testing.T) {
 	var stringMapInterface = map[string]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
 	var interfaceMapString = map[interface{}]string{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
 	var interfaceMapInterface = map[interface{}]interface{}{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}
+	var jsonString = `{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"}`
+	var invalidJsonString = `{"key 1": "value 1", "key 2": "value 2", "key 3": "value 3"`
+	var emptyString = ""
 
 	tests := []struct {
 		input  interface{}
@@ -821,9 +839,13 @@ func TestToStringMapStringE(t *testing.T) {
 		{stringMapInterface, stringMapString, false},
 		{interfaceMapString, stringMapString, false},
 		{interfaceMapInterface, stringMapString, false},
+		{jsonString, stringMapString, false},
+
 		// errors
 		{nil, nil, true},
 		{testing.T{}, nil, true},
+		{invalidJsonString, nil, true},
+		{emptyString, nil, true},
 	}
 
 	for i, test := range tests {
@@ -984,9 +1006,12 @@ func TestToDurationSliceE(t *testing.T) {
 		{[]string{"1s", "1m"}, []time.Duration{time.Second, time.Minute}, false},
 		{[]int{1, 2}, []time.Duration{1, 2}, false},
 		{[]interface{}{1, 3}, []time.Duration{1, 3}, false},
+		{[]time.Duration{1, 3}, []time.Duration{1, 3}, false},
+
 		// errors
 		{nil, nil, true},
 		{testing.T{}, nil, true},
+		{[]string{"invalid"}, nil, true},
 	}
 
 	for i, test := range tests {
diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go
index 81511fe5..4fe19289 100644
--- a/vendor/github.com/spf13/cast/caste.go
+++ b/vendor/github.com/spf13/cast/caste.go
@@ -6,6 +6,7 @@
 package cast
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
 	"html/template"
@@ -872,6 +873,9 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
 			m[ToString(k)] = ToString(val)
 		}
 		return m, nil
+	case string:
+		err := jsonStringToObject(v, &m)
+		return m, err
 	default:
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i)
 	}
@@ -932,6 +936,9 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
 			}
 			m[key] = value
 		}
+	case string:
+		err := jsonStringToObject(v, &m)
+		return m, err
 	default:
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i)
 	}
@@ -955,6 +962,9 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
 		return m, nil
 	case map[string]bool:
 		return v, nil
+	case string:
+		err := jsonStringToObject(v, &m)
+		return m, err
 	default:
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i)
 	}
@@ -972,6 +982,9 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
 		return m, nil
 	case map[string]interface{}:
 		return v, nil
+	case string:
+		err := jsonStringToObject(v, &m)
+		return m, err
 	default:
 		return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i)
 	}
@@ -1144,3 +1157,10 @@ func parseDateWith(s string, dates []string) (d time.Time, e error) {
 	}
 	return d, fmt.Errorf("unable to parse date: %s", s)
 }
+
+// jsonStringToObject attempts to unmarshall a string as JSON into
+// the object passed as pointer.
+func jsonStringToObject(s string, v interface{}) error {
+	data := []byte(s)
+	return json.Unmarshal(data, v)
+}
diff --git a/vendor/github.com/spf13/pflag/bytes.go b/vendor/github.com/spf13/pflag/bytes.go
new file mode 100644
index 00000000..67d53045
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/bytes.go
@@ -0,0 +1,209 @@
+package pflag
+
+import (
+	"encoding/base64"
+	"encoding/hex"
+	"fmt"
+	"strings"
+)
+
+// BytesHex adapts []byte for use as a flag. Value of flag is HEX encoded
+type bytesHexValue []byte
+
+// String implements pflag.Value.String.
+func (bytesHex bytesHexValue) String() string {
+	return fmt.Sprintf("%X", []byte(bytesHex))
+}
+
+// Set implements pflag.Value.Set.
+func (bytesHex *bytesHexValue) Set(value string) error {
+	bin, err := hex.DecodeString(strings.TrimSpace(value))
+
+	if err != nil {
+		return err
+	}
+
+	*bytesHex = bin
+
+	return nil
+}
+
+// Type implements pflag.Value.Type.
+func (*bytesHexValue) Type() string {
+	return "bytesHex"
+}
+
+func newBytesHexValue(val []byte, p *[]byte) *bytesHexValue {
+	*p = val
+	return (*bytesHexValue)(p)
+}
+
+func bytesHexConv(sval string) (interface{}, error) {
+
+	bin, err := hex.DecodeString(sval)
+
+	if err == nil {
+		return bin, nil
+	}
+
+	return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
+}
+
+// GetBytesHex return the []byte value of a flag with the given name
+func (f *FlagSet) GetBytesHex(name string) ([]byte, error) {
+	val, err := f.getFlagType(name, "bytesHex", bytesHexConv)
+
+	if err != nil {
+		return []byte{}, err
+	}
+
+	return val.([]byte), nil
+}
+
+// BytesHexVar defines an []byte flag with specified name, default value, and usage string.
+// The argument p points to an []byte variable in which to store the value of the flag.
+func (f *FlagSet) BytesHexVar(p *[]byte, name string, value []byte, usage string) {
+	f.VarP(newBytesHexValue(value, p), name, "", usage)
+}
+
+// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) {
+	f.VarP(newBytesHexValue(value, p), name, shorthand, usage)
+}
+
+// BytesHexVar defines an []byte flag with specified name, default value, and usage string.
+// The argument p points to an []byte variable in which to store the value of the flag.
+func BytesHexVar(p *[]byte, name string, value []byte, usage string) {
+	CommandLine.VarP(newBytesHexValue(value, p), name, "", usage)
+}
+
+// BytesHexVarP is like BytesHexVar, but accepts a shorthand letter that can be used after a single dash.
+func BytesHexVarP(p *[]byte, name, shorthand string, value []byte, usage string) {
+	CommandLine.VarP(newBytesHexValue(value, p), name, shorthand, usage)
+}
+
+// BytesHex defines an []byte flag with specified name, default value, and usage string.
+// The return value is the address of an []byte variable that stores the value of the flag.
+func (f *FlagSet) BytesHex(name string, value []byte, usage string) *[]byte {
+	p := new([]byte)
+	f.BytesHexVarP(p, name, "", value, usage)
+	return p
+}
+
+// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
+	p := new([]byte)
+	f.BytesHexVarP(p, name, shorthand, value, usage)
+	return p
+}
+
+// BytesHex defines an []byte flag with specified name, default value, and usage string.
+// The return value is the address of an []byte variable that stores the value of the flag.
+func BytesHex(name string, value []byte, usage string) *[]byte {
+	return CommandLine.BytesHexP(name, "", value, usage)
+}
+
+// BytesHexP is like BytesHex, but accepts a shorthand letter that can be used after a single dash.
+func BytesHexP(name, shorthand string, value []byte, usage string) *[]byte {
+	return CommandLine.BytesHexP(name, shorthand, value, usage)
+}
+
+// BytesBase64 adapts []byte for use as a flag. Value of flag is Base64 encoded
+type bytesBase64Value []byte
+
+// String implements pflag.Value.String.
+func (bytesBase64 bytesBase64Value) String() string {
+	return base64.StdEncoding.EncodeToString([]byte(bytesBase64))
+}
+
+// Set implements pflag.Value.Set.
+func (bytesBase64 *bytesBase64Value) Set(value string) error {
+	bin, err := base64.StdEncoding.DecodeString(strings.TrimSpace(value))
+
+	if err != nil {
+		return err
+	}
+
+	*bytesBase64 = bin
+
+	return nil
+}
+
+// Type implements pflag.Value.Type.
+func (*bytesBase64Value) Type() string {
+	return "bytesBase64"
+}
+
+func newBytesBase64Value(val []byte, p *[]byte) *bytesBase64Value {
+	*p = val
+	return (*bytesBase64Value)(p)
+}
+
+func bytesBase64ValueConv(sval string) (interface{}, error) {
+
+	bin, err := base64.StdEncoding.DecodeString(sval)
+	if err == nil {
+		return bin, nil
+	}
+
+	return nil, fmt.Errorf("invalid string being converted to Bytes: %s %s", sval, err)
+}
+
+// GetBytesBase64 return the []byte value of a flag with the given name
+func (f *FlagSet) GetBytesBase64(name string) ([]byte, error) {
+	val, err := f.getFlagType(name, "bytesBase64", bytesBase64ValueConv)
+
+	if err != nil {
+		return []byte{}, err
+	}
+
+	return val.([]byte), nil
+}
+
+// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
+// The argument p points to an []byte variable in which to store the value of the flag.
+func (f *FlagSet) BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
+	f.VarP(newBytesBase64Value(value, p), name, "", usage)
+}
+
+// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
+	f.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
+}
+
+// BytesBase64Var defines an []byte flag with specified name, default value, and usage string.
+// The argument p points to an []byte variable in which to store the value of the flag.
+func BytesBase64Var(p *[]byte, name string, value []byte, usage string) {
+	CommandLine.VarP(newBytesBase64Value(value, p), name, "", usage)
+}
+
+// BytesBase64VarP is like BytesBase64Var, but accepts a shorthand letter that can be used after a single dash.
+func BytesBase64VarP(p *[]byte, name, shorthand string, value []byte, usage string) {
+	CommandLine.VarP(newBytesBase64Value(value, p), name, shorthand, usage)
+}
+
+// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
+// The return value is the address of an []byte variable that stores the value of the flag.
+func (f *FlagSet) BytesBase64(name string, value []byte, usage string) *[]byte {
+	p := new([]byte)
+	f.BytesBase64VarP(p, name, "", value, usage)
+	return p
+}
+
+// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
+	p := new([]byte)
+	f.BytesBase64VarP(p, name, shorthand, value, usage)
+	return p
+}
+
+// BytesBase64 defines an []byte flag with specified name, default value, and usage string.
+// The return value is the address of an []byte variable that stores the value of the flag.
+func BytesBase64(name string, value []byte, usage string) *[]byte {
+	return CommandLine.BytesBase64P(name, "", value, usage)
+}
+
+// BytesBase64P is like BytesBase64, but accepts a shorthand letter that can be used after a single dash.
+func BytesBase64P(name, shorthand string, value []byte, usage string) *[]byte {
+	return CommandLine.BytesBase64P(name, shorthand, value, usage)
+}
diff --git a/vendor/github.com/spf13/pflag/bytes_test.go b/vendor/github.com/spf13/pflag/bytes_test.go
new file mode 100644
index 00000000..5251f347
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/bytes_test.go
@@ -0,0 +1,134 @@
+package pflag
+
+import (
+	"encoding/base64"
+	"fmt"
+	"os"
+	"testing"
+)
+
+func setUpBytesHex(bytesHex *[]byte) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.BytesHexVar(bytesHex, "bytes", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in HEX")
+	f.BytesHexVarP(bytesHex, "bytes2", "B", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in HEX")
+	return f
+}
+
+func TestBytesHex(t *testing.T) {
+	testCases := []struct {
+		input    string
+		success  bool
+		expected string
+	}{
+		/// Positive cases
+		{"", true, ""}, // Is empty string OK ?
+		{"01", true, "01"},
+		{"0101", true, "0101"},
+		{"1234567890abcdef", true, "1234567890ABCDEF"},
+		{"1234567890ABCDEF", true, "1234567890ABCDEF"},
+
+		// Negative cases
+		{"0", false, ""},   // Short string
+		{"000", false, ""}, /// Odd-length string
+		{"qq", false, ""},  /// non-hex character
+	}
+
+	devnull, _ := os.Open(os.DevNull)
+	os.Stderr = devnull
+
+	for i := range testCases {
+		var bytesHex []byte
+		f := setUpBytesHex(&bytesHex)
+
+		tc := &testCases[i]
+
+		// --bytes
+		args := []string{
+			fmt.Sprintf("--bytes=%s", tc.input),
+			fmt.Sprintf("-B  %s", tc.input),
+			fmt.Sprintf("--bytes2=%s", tc.input),
+		}
+
+		for _, arg := range args {
+			err := f.Parse([]string{arg})
+
+			if err != nil && tc.success == true {
+				t.Errorf("expected success, got %q", err)
+				continue
+			} else if err == nil && tc.success == false {
+				// bytesHex, err := f.GetBytesHex("bytes")
+				t.Errorf("expected failure while processing %q", tc.input)
+				continue
+			} else if tc.success {
+				bytesHex, err := f.GetBytesHex("bytes")
+				if err != nil {
+					t.Errorf("Got error trying to fetch the 'bytes' flag: %v", err)
+				}
+				if fmt.Sprintf("%X", bytesHex) != tc.expected {
+					t.Errorf("expected %q, got '%X'", tc.expected, bytesHex)
+				}
+			}
+		}
+	}
+}
+
+func setUpBytesBase64(bytesBase64 *[]byte) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.BytesBase64Var(bytesBase64, "bytes", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in Base64")
+	f.BytesBase64VarP(bytesBase64, "bytes2", "B", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, "Some bytes in Base64")
+	return f
+}
+
+func TestBytesBase64(t *testing.T) {
+	testCases := []struct {
+		input    string
+		success  bool
+		expected string
+	}{
+		/// Positive cases
+		{"", true, ""}, // Is empty string OK ?
+		{"AQ==", true, "AQ=="},
+
+		// Negative cases
+		{"AQ", false, ""}, // Padding removed
+		{"ï", false, ""},  // non-base64 characters
+	}
+
+	devnull, _ := os.Open(os.DevNull)
+	os.Stderr = devnull
+
+	for i := range testCases {
+		var bytesBase64 []byte
+		f := setUpBytesBase64(&bytesBase64)
+
+		tc := &testCases[i]
+
+		// --bytes
+		args := []string{
+			fmt.Sprintf("--bytes=%s", tc.input),
+			fmt.Sprintf("-B  %s", tc.input),
+			fmt.Sprintf("--bytes2=%s", tc.input),
+		}
+
+		for _, arg := range args {
+			err := f.Parse([]string{arg})
+
+			if err != nil && tc.success == true {
+				t.Errorf("expected success, got %q", err)
+				continue
+			} else if err == nil && tc.success == false {
+				// bytesBase64, err := f.GetBytesBase64("bytes")
+				t.Errorf("expected failure while processing %q", tc.input)
+				continue
+			} else if tc.success {
+				bytesBase64, err := f.GetBytesBase64("bytes")
+				if err != nil {
+					t.Errorf("Got error trying to fetch the 'bytes' flag: %v", err)
+				}
+				if base64.StdEncoding.EncodeToString(bytesBase64) != tc.expected {
+					t.Errorf("expected %q, got '%X'", tc.expected, bytesBase64)
+				}
+			}
+		}
+	}
+}
diff --git a/vendor/github.com/spf13/pflag/count.go b/vendor/github.com/spf13/pflag/count.go
index 250a4381..aa126e44 100644
--- a/vendor/github.com/spf13/pflag/count.go
+++ b/vendor/github.com/spf13/pflag/count.go
@@ -11,13 +11,13 @@ func newCountValue(val int, p *int) *countValue {
 }
 
 func (i *countValue) Set(s string) error {
-	v, err := strconv.ParseInt(s, 0, 64)
-	// -1 means that no specific value was passed, so increment
-	if v == -1 {
+	// "+1" means that no specific value was passed, so increment
+	if s == "+1" {
 		*i = countValue(*i + 1)
-	} else {
-		*i = countValue(v)
+		return nil
 	}
+	v, err := strconv.ParseInt(s, 0, 0)
+	*i = countValue(v)
 	return err
 }
 
@@ -54,7 +54,7 @@ func (f *FlagSet) CountVar(p *int, name string, usage string) {
 // CountVarP is like CountVar only take a shorthand for the flag name.
 func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
 	flag := f.VarPF(newCountValue(0, p), name, shorthand, usage)
-	flag.NoOptDefVal = "-1"
+	flag.NoOptDefVal = "+1"
 }
 
 // CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set
diff --git a/vendor/github.com/spf13/pflag/count_test.go b/vendor/github.com/spf13/pflag/count_test.go
index 460d96a6..3785d375 100644
--- a/vendor/github.com/spf13/pflag/count_test.go
+++ b/vendor/github.com/spf13/pflag/count_test.go
@@ -17,10 +17,14 @@ func TestCount(t *testing.T) {
 		success  bool
 		expected int
 	}{
+		{[]string{}, true, 0},
+		{[]string{"-v"}, true, 1},
 		{[]string{"-vvv"}, true, 3},
 		{[]string{"-v", "-v", "-v"}, true, 3},
 		{[]string{"-v", "--verbose", "-v"}, true, 3},
 		{[]string{"-v=3", "-v"}, true, 4},
+		{[]string{"--verbose=0"}, true, 0},
+		{[]string{"-v=0"}, true, 0},
 		{[]string{"-v=a"}, false, 0},
 	}
 
@@ -45,7 +49,7 @@ func TestCount(t *testing.T) {
 				t.Errorf("Got error trying to fetch the counter flag")
 			}
 			if c != tc.expected {
-				t.Errorf("expected %q, got %q", tc.expected, c)
+				t.Errorf("expected %d, got %d", tc.expected, c)
 			}
 		}
 	}
diff --git a/vendor/github.com/spf13/pflag/duration_slice.go b/vendor/github.com/spf13/pflag/duration_slice.go
new file mode 100644
index 00000000..52c6b6dc
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/duration_slice.go
@@ -0,0 +1,128 @@
+package pflag
+
+import (
+	"fmt"
+	"strings"
+	"time"
+)
+
+// -- durationSlice Value
+type durationSliceValue struct {
+	value   *[]time.Duration
+	changed bool
+}
+
+func newDurationSliceValue(val []time.Duration, p *[]time.Duration) *durationSliceValue {
+	dsv := new(durationSliceValue)
+	dsv.value = p
+	*dsv.value = val
+	return dsv
+}
+
+func (s *durationSliceValue) Set(val string) error {
+	ss := strings.Split(val, ",")
+	out := make([]time.Duration, len(ss))
+	for i, d := range ss {
+		var err error
+		out[i], err = time.ParseDuration(d)
+		if err != nil {
+			return err
+		}
+
+	}
+	if !s.changed {
+		*s.value = out
+	} else {
+		*s.value = append(*s.value, out...)
+	}
+	s.changed = true
+	return nil
+}
+
+func (s *durationSliceValue) Type() string {
+	return "durationSlice"
+}
+
+func (s *durationSliceValue) String() string {
+	out := make([]string, len(*s.value))
+	for i, d := range *s.value {
+		out[i] = fmt.Sprintf("%s", d)
+	}
+	return "[" + strings.Join(out, ",") + "]"
+}
+
+func durationSliceConv(val string) (interface{}, error) {
+	val = strings.Trim(val, "[]")
+	// Empty string would cause a slice with one (empty) entry
+	if len(val) == 0 {
+		return []time.Duration{}, nil
+	}
+	ss := strings.Split(val, ",")
+	out := make([]time.Duration, len(ss))
+	for i, d := range ss {
+		var err error
+		out[i], err = time.ParseDuration(d)
+		if err != nil {
+			return nil, err
+		}
+
+	}
+	return out, nil
+}
+
+// GetDurationSlice returns the []time.Duration value of a flag with the given name
+func (f *FlagSet) GetDurationSlice(name string) ([]time.Duration, error) {
+	val, err := f.getFlagType(name, "durationSlice", durationSliceConv)
+	if err != nil {
+		return []time.Duration{}, err
+	}
+	return val.([]time.Duration), nil
+}
+
+// DurationSliceVar defines a durationSlice flag with specified name, default value, and usage string.
+// The argument p points to a []time.Duration variable in which to store the value of the flag.
+func (f *FlagSet) DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) {
+	f.VarP(newDurationSliceValue(value, p), name, "", usage)
+}
+
+// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) {
+	f.VarP(newDurationSliceValue(value, p), name, shorthand, usage)
+}
+
+// DurationSliceVar defines a duration[] flag with specified name, default value, and usage string.
+// The argument p points to a duration[] variable in which to store the value of the flag.
+func DurationSliceVar(p *[]time.Duration, name string, value []time.Duration, usage string) {
+	CommandLine.VarP(newDurationSliceValue(value, p), name, "", usage)
+}
+
+// DurationSliceVarP is like DurationSliceVar, but accepts a shorthand letter that can be used after a single dash.
+func DurationSliceVarP(p *[]time.Duration, name, shorthand string, value []time.Duration, usage string) {
+	CommandLine.VarP(newDurationSliceValue(value, p), name, shorthand, usage)
+}
+
+// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a []time.Duration variable that stores the value of the flag.
+func (f *FlagSet) DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration {
+	p := []time.Duration{}
+	f.DurationSliceVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration {
+	p := []time.Duration{}
+	f.DurationSliceVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string.
+// The return value is the address of a []time.Duration variable that stores the value of the flag.
+func DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration {
+	return CommandLine.DurationSliceP(name, "", value, usage)
+}
+
+// DurationSliceP is like DurationSlice, but accepts a shorthand letter that can be used after a single dash.
+func DurationSliceP(name, shorthand string, value []time.Duration, usage string) *[]time.Duration {
+	return CommandLine.DurationSliceP(name, shorthand, value, usage)
+}
diff --git a/vendor/github.com/spf13/pflag/duration_slice_test.go b/vendor/github.com/spf13/pflag/duration_slice_test.go
new file mode 100644
index 00000000..489b012f
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/duration_slice_test.go
@@ -0,0 +1,165 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code ds governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pflag
+
+import (
+	"fmt"
+	"strings"
+	"testing"
+	"time"
+)
+
+func setUpDSFlagSet(dsp *[]time.Duration) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.DurationSliceVar(dsp, "ds", []time.Duration{}, "Command separated list!")
+	return f
+}
+
+func setUpDSFlagSetWithDefault(dsp *[]time.Duration) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.DurationSliceVar(dsp, "ds", []time.Duration{0, 1}, "Command separated list!")
+	return f
+}
+
+func TestEmptyDS(t *testing.T) {
+	var ds []time.Duration
+	f := setUpDSFlagSet(&ds)
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getDS, err := f.GetDurationSlice("ds")
+	if err != nil {
+		t.Fatal("got an error from GetDurationSlice():", err)
+	}
+	if len(getDS) != 0 {
+		t.Fatalf("got ds %v with len=%d but expected length=0", getDS, len(getDS))
+	}
+}
+
+func TestDS(t *testing.T) {
+	var ds []time.Duration
+	f := setUpDSFlagSet(&ds)
+
+	vals := []string{"1ns", "2ms", "3m", "4h"}
+	arg := fmt.Sprintf("--ds=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ds {
+		d, err := time.ParseDuration(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if d != v {
+			t.Fatalf("expected ds[%d] to be %s but got: %d", i, vals[i], v)
+		}
+	}
+	getDS, err := f.GetDurationSlice("ds")
+	if err != nil {
+		t.Fatalf("got error: %v", err)
+	}
+	for i, v := range getDS {
+		d, err := time.ParseDuration(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if d != v {
+			t.Fatalf("expected ds[%d] to be %s but got: %d from GetDurationSlice", i, vals[i], v)
+		}
+	}
+}
+
+func TestDSDefault(t *testing.T) {
+	var ds []time.Duration
+	f := setUpDSFlagSetWithDefault(&ds)
+
+	vals := []string{"0s", "1ns"}
+
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ds {
+		d, err := time.ParseDuration(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if d != v {
+			t.Fatalf("expected ds[%d] to be %d but got: %d", i, d, v)
+		}
+	}
+
+	getDS, err := f.GetDurationSlice("ds")
+	if err != nil {
+		t.Fatal("got an error from GetDurationSlice():", err)
+	}
+	for i, v := range getDS {
+		d, err := time.ParseDuration(vals[i])
+		if err != nil {
+			t.Fatal("got an error from GetDurationSlice():", err)
+		}
+		if d != v {
+			t.Fatalf("expected ds[%d] to be %d from GetDurationSlice but got: %d", i, d, v)
+		}
+	}
+}
+
+func TestDSWithDefault(t *testing.T) {
+	var ds []time.Duration
+	f := setUpDSFlagSetWithDefault(&ds)
+
+	vals := []string{"1ns", "2ns"}
+	arg := fmt.Sprintf("--ds=%s", strings.Join(vals, ","))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ds {
+		d, err := time.ParseDuration(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if d != v {
+			t.Fatalf("expected ds[%d] to be %d but got: %d", i, d, v)
+		}
+	}
+
+	getDS, err := f.GetDurationSlice("ds")
+	if err != nil {
+		t.Fatal("got an error from GetDurationSlice():", err)
+	}
+	for i, v := range getDS {
+		d, err := time.ParseDuration(vals[i])
+		if err != nil {
+			t.Fatalf("got error: %v", err)
+		}
+		if d != v {
+			t.Fatalf("expected ds[%d] to be %d from GetDurationSlice but got: %d", i, d, v)
+		}
+	}
+}
+
+func TestDSCalledTwice(t *testing.T) {
+	var ds []time.Duration
+	f := setUpDSFlagSet(&ds)
+
+	in := []string{"1ns,2ns", "3ns"}
+	expected := []time.Duration{1, 2, 3}
+	argfmt := "--ds=%s"
+	arg1 := fmt.Sprintf(argfmt, in[0])
+	arg2 := fmt.Sprintf(argfmt, in[1])
+	err := f.Parse([]string{arg1, arg2})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range ds {
+		if expected[i] != v {
+			t.Fatalf("expected ds[%d] to be %d but got: %d", i, expected[i], v)
+		}
+	}
+}
diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go
index 6f1fc300..9beeda8e 100644
--- a/vendor/github.com/spf13/pflag/flag.go
+++ b/vendor/github.com/spf13/pflag/flag.go
@@ -101,6 +101,7 @@ package pflag
 import (
 	"bytes"
 	"errors"
+	goflag "flag"
 	"fmt"
 	"io"
 	"os"
@@ -123,6 +124,12 @@ const (
 	PanicOnError
 )
 
+// ParseErrorsWhitelist defines the parsing errors that can be ignored
+type ParseErrorsWhitelist struct {
+	// UnknownFlags will ignore unknown flags errors and continue parsing rest of the flags
+	UnknownFlags bool
+}
+
 // NormalizedName is a flag name that has been normalized according to rules
 // for the FlagSet (e.g. making '-' and '_' equivalent).
 type NormalizedName string
@@ -138,6 +145,9 @@ type FlagSet struct {
 	// help/usage messages.
 	SortFlags bool
 
+	// ParseErrorsWhitelist is used to configure a whitelist of errors
+	ParseErrorsWhitelist ParseErrorsWhitelist
+
 	name              string
 	parsed            bool
 	actual            map[NormalizedName]*Flag
@@ -153,6 +163,8 @@ type FlagSet struct {
 	output            io.Writer // nil means stderr; use out() accessor
 	interspersed      bool      // allow interspersed option/non-option args
 	normalizeNameFunc func(f *FlagSet, name string) NormalizedName
+
+	addedGoFlagSets []*goflag.FlagSet
 }
 
 // A Flag represents the state of a flag.
@@ -202,12 +214,18 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
 func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
 	f.normalizeNameFunc = n
 	f.sortedFormal = f.sortedFormal[:0]
-	for k, v := range f.orderedFormal {
-		delete(f.formal, NormalizedName(v.Name))
-		nname := f.normalizeFlagName(v.Name)
-		v.Name = string(nname)
-		f.formal[nname] = v
-		f.orderedFormal[k] = v
+	for fname, flag := range f.formal {
+		nname := f.normalizeFlagName(flag.Name)
+		if fname == nname {
+			continue
+		}
+		flag.Name = string(nname)
+		delete(f.formal, fname)
+		f.formal[nname] = flag
+		if _, set := f.actual[fname]; set {
+			delete(f.actual, fname)
+			f.actual[nname] = flag
+		}
 	}
 }
 
@@ -261,16 +279,16 @@ func (f *FlagSet) VisitAll(fn func(*Flag)) {
 	}
 }
 
-// HasFlags returns a bool to indicate if the FlagSet has any flags definied.
+// HasFlags returns a bool to indicate if the FlagSet has any flags defined.
 func (f *FlagSet) HasFlags() bool {
 	return len(f.formal) > 0
 }
 
 // HasAvailableFlags returns a bool to indicate if the FlagSet has any flags
-// definied that are not hidden or deprecated.
+// that are not hidden.
 func (f *FlagSet) HasAvailableFlags() bool {
 	for _, flag := range f.formal {
-		if !flag.Hidden && len(flag.Deprecated) == 0 {
+		if !flag.Hidden {
 			return true
 		}
 	}
@@ -380,6 +398,7 @@ func (f *FlagSet) MarkDeprecated(name string, usageMessage string) error {
 		return fmt.Errorf("deprecated message for flag %q must be set", name)
 	}
 	flag.Deprecated = usageMessage
+	flag.Hidden = true
 	return nil
 }
 
@@ -440,13 +459,15 @@ func (f *FlagSet) Set(name, value string) error {
 		return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
 	}
 
-	if f.actual == nil {
-		f.actual = make(map[NormalizedName]*Flag)
-	}
-	f.actual[normalName] = flag
-	f.orderedActual = append(f.orderedActual, flag)
+	if !flag.Changed {
+		if f.actual == nil {
+			f.actual = make(map[NormalizedName]*Flag)
+		}
+		f.actual[normalName] = flag
+		f.orderedActual = append(f.orderedActual, flag)
 
-	flag.Changed = true
+		flag.Changed = true
+	}
 
 	if flag.Deprecated != "" {
 		fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
@@ -556,6 +577,14 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
 		name = "int"
 	case "uint64":
 		name = "uint"
+	case "stringSlice":
+		name = "strings"
+	case "intSlice":
+		name = "ints"
+	case "uintSlice":
+		name = "uints"
+	case "boolSlice":
+		name = "bools"
 	}
 
 	return
@@ -570,11 +599,14 @@ func wrapN(i, slop int, s string) (string, string) {
 		return s, ""
 	}
 
-	w := strings.LastIndexAny(s[:i], " \t")
+	w := strings.LastIndexAny(s[:i], " \t\n")
 	if w <= 0 {
 		return s, ""
 	}
-
+	nlPos := strings.LastIndex(s[:i], "\n")
+	if nlPos > 0 && nlPos < w {
+		return s[:nlPos], s[nlPos+1:]
+	}
 	return s[:w], s[w+1:]
 }
 
@@ -583,7 +615,7 @@ func wrapN(i, slop int, s string) (string, string) {
 // caller). Pass `w` == 0 to do no wrapping
 func wrap(i, w int, s string) string {
 	if w == 0 {
-		return s
+		return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
 	}
 
 	// space between indent i and end of line width w into which
@@ -601,7 +633,7 @@ func wrap(i, w int, s string) string {
 	}
 	// If still not enough space then don't even try to wrap.
 	if wrap < 24 {
-		return s
+		return strings.Replace(s, "\n", r, -1)
 	}
 
 	// Try to avoid short orphan words on the final line, by
@@ -613,14 +645,14 @@ func wrap(i, w int, s string) string {
 	// Handle first line, which is indented by the caller (or the
 	// special case above)
 	l, s = wrapN(wrap, slop, s)
-	r = r + l
+	r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
 
 	// Now wrap the rest
 	for s != "" {
 		var t string
 
 		t, s = wrapN(wrap, slop, s)
-		r = r + "\n" + strings.Repeat(" ", i) + t
+		r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
 	}
 
 	return r
@@ -637,7 +669,7 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
 
 	maxlen := 0
 	f.VisitAll(func(flag *Flag) {
-		if flag.Deprecated != "" || flag.Hidden {
+		if flag.Hidden {
 			return
 		}
 
@@ -660,6 +692,10 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
 				if flag.NoOptDefVal != "true" {
 					line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
 				}
+			case "count":
+				if flag.NoOptDefVal != "+1" {
+					line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
+				}
 			default:
 				line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
 			}
@@ -680,6 +716,9 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
 				line += fmt.Sprintf(" (default %s)", flag.DefValue)
 			}
 		}
+		if len(flag.Deprecated) != 0 {
+			line += fmt.Sprintf(" (DEPRECATED: %s)", flag.Deprecated)
+		}
 
 		lines = append(lines, line)
 	})
@@ -857,8 +896,10 @@ func VarP(value Value, name, shorthand, usage string) {
 // returns the error.
 func (f *FlagSet) failf(format string, a ...interface{}) error {
 	err := fmt.Errorf(format, a...)
-	fmt.Fprintln(f.out(), err)
-	f.usage()
+	if f.errorHandling != ContinueOnError {
+		fmt.Fprintln(f.out(), err)
+		f.usage()
+	}
 	return err
 }
 
@@ -874,6 +915,28 @@ func (f *FlagSet) usage() {
 	}
 }
 
+//--unknown (args will be empty)
+//--unknown --next-flag ... (args will be --next-flag ...)
+//--unknown arg ... (args will be arg ...)
+func stripUnknownFlagValue(args []string) []string {
+	if len(args) == 0 {
+		//--unknown
+		return args
+	}
+
+	first := args[0]
+	if len(first) > 0 && first[0] == '-' {
+		//--unknown --next-flag ...
+		return args
+	}
+
+	//--unknown arg ... (args will be arg ...)
+	if len(args) > 1 {
+		return args[1:]
+	}
+	return nil
+}
+
 func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) {
 	a = args
 	name := s[2:]
@@ -885,13 +948,24 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 	split := strings.SplitN(name, "=", 2)
 	name = split[0]
 	flag, exists := f.formal[f.normalizeFlagName(name)]
+
 	if !exists {
-		if name == "help" { // special case for nice help message.
+		switch {
+		case name == "help":
 			f.usage()
 			return a, ErrHelp
+		case f.ParseErrorsWhitelist.UnknownFlags:
+			// --unknown=unknownval arg ...
+			// we do not want to lose arg in this case
+			if len(split) >= 2 {
+				return a, nil
+			}
+
+			return stripUnknownFlagValue(a), nil
+		default:
+			err = f.failf("unknown flag: --%s", name)
+			return
 		}
-		err = f.failf("unknown flag: --%s", name)
-		return
 	}
 
 	var value string
@@ -912,27 +986,43 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
 	}
 
 	err = fn(flag, value)
+	if err != nil {
+		f.failf(err.Error())
+	}
 	return
 }
 
 func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) {
+	outArgs = args
+
 	if strings.HasPrefix(shorthands, "test.") {
 		return
 	}
 
-	outArgs = args
 	outShorts = shorthands[1:]
 	c := shorthands[0]
 
 	flag, exists := f.shorthands[c]
 	if !exists {
-		if c == 'h' { // special case for nice help message.
+		switch {
+		case c == 'h':
 			f.usage()
 			err = ErrHelp
 			return
+		case f.ParseErrorsWhitelist.UnknownFlags:
+			// '-f=arg arg ...'
+			// we do not want to lose arg in this case
+			if len(shorthands) > 2 && shorthands[1] == '=' {
+				outShorts = ""
+				return
+			}
+
+			outArgs = stripUnknownFlagValue(outArgs)
+			return
+		default:
+			err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
+			return
 		}
-		err = f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
-		return
 	}
 
 	var value string
@@ -962,6 +1052,9 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
 	}
 
 	err = fn(flag, value)
+	if err != nil {
+		f.failf(err.Error())
+	}
 	return
 }
 
@@ -1016,6 +1109,11 @@ func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) {
 // are defined and before flags are accessed by the program.
 // The return value will be ErrHelp if -help was set but not defined.
 func (f *FlagSet) Parse(arguments []string) error {
+	if f.addedGoFlagSets != nil {
+		for _, goFlagSet := range f.addedGoFlagSets {
+			goFlagSet.Parse(nil)
+		}
+	}
 	f.parsed = true
 
 	if len(arguments) < 0 {
@@ -1034,6 +1132,7 @@ func (f *FlagSet) Parse(arguments []string) error {
 		case ContinueOnError:
 			return err
 		case ExitOnError:
+			fmt.Println(err)
 			os.Exit(2)
 		case PanicOnError:
 			panic(err)
diff --git a/vendor/github.com/spf13/pflag/flag_test.go b/vendor/github.com/spf13/pflag/flag_test.go
index c3def0fd..7d02dbc8 100644
--- a/vendor/github.com/spf13/pflag/flag_test.go
+++ b/vendor/github.com/spf13/pflag/flag_test.go
@@ -106,8 +106,8 @@ func TestUsage(t *testing.T) {
 	if GetCommandLine().Parse([]string{"--x"}) == nil {
 		t.Error("parse did not fail for unknown flag")
 	}
-	if !called {
-		t.Error("did not call Usage for unknown flag")
+	if called {
+		t.Error("did call Usage while using ContinueOnError")
 	}
 }
 
@@ -168,6 +168,7 @@ func testParse(f *FlagSet, t *testing.T) {
 	bool3Flag := f.Bool("bool3", false, "bool3 value")
 	intFlag := f.Int("int", 0, "int value")
 	int8Flag := f.Int8("int8", 0, "int value")
+	int16Flag := f.Int16("int16", 0, "int value")
 	int32Flag := f.Int32("int32", 0, "int value")
 	int64Flag := f.Int64("int64", 0, "int64 value")
 	uintFlag := f.Uint("uint", 0, "uint value")
@@ -192,6 +193,7 @@ func testParse(f *FlagSet, t *testing.T) {
 		"--bool3=false",
 		"--int=22",
 		"--int8=-8",
+		"--int16=-16",
 		"--int32=-32",
 		"--int64=0x23",
 		"--uint", "24",
@@ -236,9 +238,15 @@ func testParse(f *FlagSet, t *testing.T) {
 	if *int8Flag != -8 {
 		t.Error("int8 flag should be 0x23, is ", *int8Flag)
 	}
+	if *int16Flag != -16 {
+		t.Error("int16 flag should be -16, is ", *int16Flag)
+	}
 	if v, err := f.GetInt8("int8"); err != nil || v != *int8Flag {
 		t.Error("GetInt8 does not work.")
 	}
+	if v, err := f.GetInt16("int16"); err != nil || v != *int16Flag {
+		t.Error("GetInt16 does not work.")
+	}
 	if *int32Flag != -32 {
 		t.Error("int32 flag should be 0x23, is ", *int32Flag)
 	}
@@ -381,7 +389,83 @@ func testParseAll(f *FlagSet, t *testing.T) {
 	}
 	if !reflect.DeepEqual(got, want) {
 		t.Errorf("f.ParseAll() fail to restore the args")
-		t.Errorf("Got: %v", got)
+		t.Errorf("Got:  %v", got)
+		t.Errorf("Want: %v", want)
+	}
+}
+
+func testParseWithUnknownFlags(f *FlagSet, t *testing.T) {
+	if f.Parsed() {
+		t.Error("f.Parse() = true before Parse")
+	}
+	f.ParseErrorsWhitelist.UnknownFlags = true
+
+	f.BoolP("boola", "a", false, "bool value")
+	f.BoolP("boolb", "b", false, "bool2 value")
+	f.BoolP("boolc", "c", false, "bool3 value")
+	f.BoolP("boold", "d", false, "bool4 value")
+	f.BoolP("boole", "e", false, "bool4 value")
+	f.StringP("stringa", "s", "0", "string value")
+	f.StringP("stringz", "z", "0", "string value")
+	f.StringP("stringx", "x", "0", "string value")
+	f.StringP("stringy", "y", "0", "string value")
+	f.StringP("stringo", "o", "0", "string value")
+	f.Lookup("stringx").NoOptDefVal = "1"
+	args := []string{
+		"-ab",
+		"-cs=xx",
+		"--stringz=something",
+		"--unknown1",
+		"unknown1Value",
+		"-d=true",
+		"-x",
+		"--unknown2=unknown2Value",
+		"-u=unknown3Value",
+		"-p",
+		"unknown4Value",
+		"-q", //another unknown with bool value
+		"-y",
+		"ee",
+		"--unknown7=unknown7value",
+		"--stringo=ovalue",
+		"--unknown8=unknown8value",
+		"--boole",
+		"--unknown6",
+		"",
+		"-uuuuu",
+		"",
+		"--unknown10",
+		"--unknown11",
+	}
+	want := []string{
+		"boola", "true",
+		"boolb", "true",
+		"boolc", "true",
+		"stringa", "xx",
+		"stringz", "something",
+		"boold", "true",
+		"stringx", "1",
+		"stringy", "ee",
+		"stringo", "ovalue",
+		"boole", "true",
+	}
+	got := []string{}
+	store := func(flag *Flag, value string) error {
+		got = append(got, flag.Name)
+		if len(value) > 0 {
+			got = append(got, value)
+		}
+		return nil
+	}
+	if err := f.ParseAll(args, store); err != nil {
+		t.Errorf("expected no error, got %s", err)
+	}
+	if !f.Parsed() {
+		t.Errorf("f.Parse() = false after Parse")
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("f.ParseAll() fail to restore the args")
+		t.Errorf("Got:  %v", got)
 		t.Errorf("Want: %v", want)
 	}
 }
@@ -492,6 +576,11 @@ func TestParseAll(t *testing.T) {
 	testParseAll(GetCommandLine(), t)
 }
 
+func TestIgnoreUnknownFlags(t *testing.T) {
+	ResetForTesting(func() { t.Error("bad parse") })
+	testParseWithUnknownFlags(GetCommandLine(), t)
+}
+
 func TestFlagSetParse(t *testing.T) {
 	testParse(NewFlagSet("test", ContinueOnError), t)
 }
@@ -604,7 +693,6 @@ func aliasAndWordSepFlagNames(f *FlagSet, name string) NormalizedName {
 	switch name {
 	case oldName:
 		name = newName
-		break
 	}
 
 	return NormalizedName(name)
@@ -658,6 +746,70 @@ func TestNormalizationFuncShouldChangeFlagName(t *testing.T) {
 	}
 }
 
+// Related to https://github.com/spf13/cobra/issues/521.
+func TestNormalizationSharedFlags(t *testing.T) {
+	f := NewFlagSet("set f", ContinueOnError)
+	g := NewFlagSet("set g", ContinueOnError)
+	nfunc := wordSepNormalizeFunc
+	testName := "valid_flag"
+	normName := nfunc(nil, testName)
+	if testName == string(normName) {
+		t.Error("TestNormalizationSharedFlags meaningless: the original and normalized flag names are identical:", testName)
+	}
+
+	f.Bool(testName, false, "bool value")
+	g.AddFlagSet(f)
+
+	f.SetNormalizeFunc(nfunc)
+	g.SetNormalizeFunc(nfunc)
+
+	if len(f.formal) != 1 {
+		t.Error("Normalizing flags should not result in duplications in the flag set:", f.formal)
+	}
+	if f.orderedFormal[0].Name != string(normName) {
+		t.Error("Flag name not normalized")
+	}
+	for k := range f.formal {
+		if k != "valid.flag" {
+			t.Errorf("The key in the flag map should have been normalized: wanted \"%s\", got \"%s\" instead", normName, k)
+		}
+	}
+
+	if !reflect.DeepEqual(f.formal, g.formal) || !reflect.DeepEqual(f.orderedFormal, g.orderedFormal) {
+		t.Error("Two flag sets sharing the same flags should stay consistent after being normalized. Original set:", f.formal, "Duplicate set:", g.formal)
+	}
+}
+
+func TestNormalizationSetFlags(t *testing.T) {
+	f := NewFlagSet("normalized", ContinueOnError)
+	nfunc := wordSepNormalizeFunc
+	testName := "valid_flag"
+	normName := nfunc(nil, testName)
+	if testName == string(normName) {
+		t.Error("TestNormalizationSetFlags meaningless: the original and normalized flag names are identical:", testName)
+	}
+
+	f.Bool(testName, false, "bool value")
+	f.Set(testName, "true")
+	f.SetNormalizeFunc(nfunc)
+
+	if len(f.formal) != 1 {
+		t.Error("Normalizing flags should not result in duplications in the flag set:", f.formal)
+	}
+	if f.orderedFormal[0].Name != string(normName) {
+		t.Error("Flag name not normalized")
+	}
+	for k := range f.formal {
+		if k != "valid.flag" {
+			t.Errorf("The key in the flag map should have been normalized: wanted \"%s\", got \"%s\" instead", normName, k)
+		}
+	}
+
+	if !reflect.DeepEqual(f.formal, f.actual) {
+		t.Error("The map of set flags should get normalized. Formal:", f.formal, "Actual:", f.actual)
+	}
+}
+
 // Declare a user-defined flag type.
 type flagVar []string
 
@@ -819,10 +971,14 @@ func TestTermination(t *testing.T) {
 	}
 }
 
-func TestDeprecatedFlagInDocs(t *testing.T) {
+func getDeprecatedFlagSet() *FlagSet {
 	f := NewFlagSet("bob", ContinueOnError)
 	f.Bool("badflag", true, "always true")
 	f.MarkDeprecated("badflag", "use --good-flag instead")
+	return f
+}
+func TestDeprecatedFlagInDocs(t *testing.T) {
+	f := getDeprecatedFlagSet()
 
 	out := new(bytes.Buffer)
 	f.SetOutput(out)
@@ -833,6 +989,27 @@ func TestDeprecatedFlagInDocs(t *testing.T) {
 	}
 }
 
+func TestUnHiddenDeprecatedFlagInDocs(t *testing.T) {
+	f := getDeprecatedFlagSet()
+	flg := f.Lookup("badflag")
+	if flg == nil {
+		t.Fatalf("Unable to lookup 'bob' in TestUnHiddenDeprecatedFlagInDocs")
+	}
+	flg.Hidden = false
+
+	out := new(bytes.Buffer)
+	f.SetOutput(out)
+	f.PrintDefaults()
+
+	defaults := out.String()
+	if !strings.Contains(defaults, "badflag") {
+		t.Errorf("Did not find deprecated flag in usage!")
+	}
+	if !strings.Contains(defaults, "use --good-flag instead") {
+		t.Errorf("Did not find 'use --good-flag instead' in defaults")
+	}
+}
+
 func TestDeprecatedFlagShorthandInDocs(t *testing.T) {
 	f := NewFlagSet("bob", ContinueOnError)
 	name := "noshorthandflag"
@@ -978,16 +1155,17 @@ const defaultOutput = `      --A                         for bootstrapping, allo
       --IP ip                     IP address with no default
       --IPMask ipMask             Netmask address with no default
       --IPNet ipNet               IP network with no default
-      --Ints intSlice             int slice with zero default
+      --Ints ints                 int slice with zero default
       --N int                     a non-zero int (default 27)
       --ND1 string[="bar"]        a string with NoOptDefVal (default "foo")
       --ND2 num[=4321]            a num with NoOptDefVal (default 1234)
       --StringArray stringArray   string array with zero default
-      --StringSlice stringSlice   string slice with zero default
+      --StringSlice strings       string slice with zero default
       --Z int                     an int that defaults to zero
       --custom custom             custom Value implementation
       --customP custom            a VarP with default (default 10)
       --maxT timeout              set timeout for dial
+  -v, --verbose count             verbosity
 `
 
 // Custom value that satisfies the Value interface.
@@ -1028,6 +1206,7 @@ func TestPrintDefaults(t *testing.T) {
 	fs.ShorthandLookup("E").NoOptDefVal = "1234"
 	fs.StringSlice("StringSlice", []string{}, "string slice with zero default")
 	fs.StringArray("StringArray", []string{}, "string array with zero default")
+	fs.CountP("verbose", "v", "verbosity")
 
 	var cv customValue
 	fs.Var(&cv, "custom", "custom Value implementation")
diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go
index c4f47ebe..d3dd72b7 100644
--- a/vendor/github.com/spf13/pflag/golangflag.go
+++ b/vendor/github.com/spf13/pflag/golangflag.go
@@ -98,4 +98,8 @@ func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
 	newSet.VisitAll(func(goflag *goflag.Flag) {
 		f.AddGoFlag(goflag)
 	})
+	if f.addedGoFlagSets == nil {
+		f.addedGoFlagSets = make([]*goflag.FlagSet, 0)
+	}
+	f.addedGoFlagSets = append(f.addedGoFlagSets, newSet)
 }
diff --git a/vendor/github.com/spf13/pflag/golangflag_test.go b/vendor/github.com/spf13/pflag/golangflag_test.go
index 77e2d7d8..5bd831bf 100644
--- a/vendor/github.com/spf13/pflag/golangflag_test.go
+++ b/vendor/github.com/spf13/pflag/golangflag_test.go
@@ -36,4 +36,12 @@ func TestGoflags(t *testing.T) {
 	if getBool != true {
 		t.Fatalf("expected getBool=true but got getBool=%v", getBool)
 	}
+	if !f.Parsed() {
+		t.Fatal("f.Parsed() return false after f.Parse() called")
+	}
+
+	// in fact it is useless. because `go test` called flag.Parse()
+	if !goflag.CommandLine.Parsed() {
+		t.Fatal("goflag.CommandLine.Parsed() return false after f.Parse() called")
+	}
 }
diff --git a/vendor/github.com/spf13/pflag/int16.go b/vendor/github.com/spf13/pflag/int16.go
new file mode 100644
index 00000000..f1a01d05
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/int16.go
@@ -0,0 +1,88 @@
+package pflag
+
+import "strconv"
+
+// -- int16 Value
+type int16Value int16
+
+func newInt16Value(val int16, p *int16) *int16Value {
+	*p = val
+	return (*int16Value)(p)
+}
+
+func (i *int16Value) Set(s string) error {
+	v, err := strconv.ParseInt(s, 0, 16)
+	*i = int16Value(v)
+	return err
+}
+
+func (i *int16Value) Type() string {
+	return "int16"
+}
+
+func (i *int16Value) String() string { return strconv.FormatInt(int64(*i), 10) }
+
+func int16Conv(sval string) (interface{}, error) {
+	v, err := strconv.ParseInt(sval, 0, 16)
+	if err != nil {
+		return 0, err
+	}
+	return int16(v), nil
+}
+
+// GetInt16 returns the int16 value of a flag with the given name
+func (f *FlagSet) GetInt16(name string) (int16, error) {
+	val, err := f.getFlagType(name, "int16", int16Conv)
+	if err != nil {
+		return 0, err
+	}
+	return val.(int16), nil
+}
+
+// Int16Var defines an int16 flag with specified name, default value, and usage string.
+// The argument p points to an int16 variable in which to store the value of the flag.
+func (f *FlagSet) Int16Var(p *int16, name string, value int16, usage string) {
+	f.VarP(newInt16Value(value, p), name, "", usage)
+}
+
+// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) Int16VarP(p *int16, name, shorthand string, value int16, usage string) {
+	f.VarP(newInt16Value(value, p), name, shorthand, usage)
+}
+
+// Int16Var defines an int16 flag with specified name, default value, and usage string.
+// The argument p points to an int16 variable in which to store the value of the flag.
+func Int16Var(p *int16, name string, value int16, usage string) {
+	CommandLine.VarP(newInt16Value(value, p), name, "", usage)
+}
+
+// Int16VarP is like Int16Var, but accepts a shorthand letter that can be used after a single dash.
+func Int16VarP(p *int16, name, shorthand string, value int16, usage string) {
+	CommandLine.VarP(newInt16Value(value, p), name, shorthand, usage)
+}
+
+// Int16 defines an int16 flag with specified name, default value, and usage string.
+// The return value is the address of an int16 variable that stores the value of the flag.
+func (f *FlagSet) Int16(name string, value int16, usage string) *int16 {
+	p := new(int16)
+	f.Int16VarP(p, name, "", value, usage)
+	return p
+}
+
+// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) Int16P(name, shorthand string, value int16, usage string) *int16 {
+	p := new(int16)
+	f.Int16VarP(p, name, shorthand, value, usage)
+	return p
+}
+
+// Int16 defines an int16 flag with specified name, default value, and usage string.
+// The return value is the address of an int16 variable that stores the value of the flag.
+func Int16(name string, value int16, usage string) *int16 {
+	return CommandLine.Int16P(name, "", value, usage)
+}
+
+// Int16P is like Int16, but accepts a shorthand letter that can be used after a single dash.
+func Int16P(name, shorthand string, value int16, usage string) *int16 {
+	return CommandLine.Int16P(name, shorthand, value, usage)
+}
diff --git a/vendor/github.com/spf13/pflag/printusage_test.go b/vendor/github.com/spf13/pflag/printusage_test.go
new file mode 100644
index 00000000..df982aab
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/printusage_test.go
@@ -0,0 +1,74 @@
+package pflag
+
+import (
+	"bytes"
+	"io"
+	"testing"
+)
+
+const expectedOutput = `      --long-form    Some description
+      --long-form2   Some description
+                       with multiline
+  -s, --long-name    Some description
+  -t, --long-name2   Some description with
+                       multiline
+`
+
+func setUpPFlagSet(buf io.Writer) *FlagSet {
+	f := NewFlagSet("test", ExitOnError)
+	f.Bool("long-form", false, "Some description")
+	f.Bool("long-form2", false, "Some description\n  with multiline")
+	f.BoolP("long-name", "s", false, "Some description")
+	f.BoolP("long-name2", "t", false, "Some description with\n  multiline")
+	f.SetOutput(buf)
+	return f
+}
+
+func TestPrintUsage(t *testing.T) {
+	buf := bytes.Buffer{}
+	f := setUpPFlagSet(&buf)
+	f.PrintDefaults()
+	res := buf.String()
+	if res != expectedOutput {
+		t.Errorf("Expected \n%s \nActual \n%s", expectedOutput, res)
+	}
+}
+
+func setUpPFlagSet2(buf io.Writer) *FlagSet {
+	f := NewFlagSet("test", ExitOnError)
+	f.Bool("long-form", false, "Some description")
+	f.Bool("long-form2", false, "Some description\n  with multiline")
+	f.BoolP("long-name", "s", false, "Some description")
+	f.BoolP("long-name2", "t", false, "Some description with\n  multiline")
+	f.StringP("some-very-long-arg", "l", "test", "Some very long description having break the limit")
+	f.StringP("other-very-long-arg", "o", "long-default-value", "Some very long description having break the limit")
+	f.String("some-very-long-arg2", "very long default value", "Some very long description\nwith line break\nmultiple")
+	f.SetOutput(buf)
+	return f
+}
+
+const expectedOutput2 = `      --long-form                    Some description
+      --long-form2                   Some description
+                                       with multiline
+  -s, --long-name                    Some description
+  -t, --long-name2                   Some description with
+                                       multiline
+  -o, --other-very-long-arg string   Some very long description having
+                                     break the limit (default
+                                     "long-default-value")
+  -l, --some-very-long-arg string    Some very long description having
+                                     break the limit (default "test")
+      --some-very-long-arg2 string   Some very long description
+                                     with line break
+                                     multiple (default "very long default
+                                     value")
+`
+
+func TestPrintUsage_2(t *testing.T) {
+	buf := bytes.Buffer{}
+	f := setUpPFlagSet2(&buf)
+	res := f.FlagUsagesWrapped(80)
+	if res != expectedOutput2 {
+		t.Errorf("Expected \n%q \nActual \n%q", expectedOutput2, res)
+	}
+}
diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go
index 276b7ed4..fa7bc601 100644
--- a/vendor/github.com/spf13/pflag/string_array.go
+++ b/vendor/github.com/spf13/pflag/string_array.go
@@ -52,7 +52,7 @@ func (f *FlagSet) GetStringArray(name string) ([]string, error) {
 
 // StringArrayVar defines a string flag with specified name, default value, and usage string.
 // The argument p points to a []string variable in which to store the values of the multiple flags.
-// The value of each argument will not try to be separated by comma
+// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
 func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {
 	f.VarP(newStringArrayValue(value, p), name, "", usage)
 }
@@ -64,7 +64,7 @@ func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []s
 
 // StringArrayVar defines a string flag with specified name, default value, and usage string.
 // The argument p points to a []string variable in which to store the value of the flag.
-// The value of each argument will not try to be separated by comma
+// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
 func StringArrayVar(p *[]string, name string, value []string, usage string) {
 	CommandLine.VarP(newStringArrayValue(value, p), name, "", usage)
 }
@@ -76,7 +76,7 @@ func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage
 
 // StringArray defines a string flag with specified name, default value, and usage string.
 // The return value is the address of a []string variable that stores the value of the flag.
-// The value of each argument will not try to be separated by comma
+// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
 func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {
 	p := []string{}
 	f.StringArrayVarP(&p, name, "", value, usage)
@@ -92,7 +92,7 @@ func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage str
 
 // StringArray defines a string flag with specified name, default value, and usage string.
 // The return value is the address of a []string variable that stores the value of the flag.
-// The value of each argument will not try to be separated by comma
+// The value of each argument will not try to be separated by comma. Use a StringSlice for that.
 func StringArray(name string, value []string, usage string) *[]string {
 	return CommandLine.StringArrayP(name, "", value, usage)
 }
diff --git a/vendor/github.com/spf13/pflag/string_slice.go b/vendor/github.com/spf13/pflag/string_slice.go
index 05eee754..0cd3ccc0 100644
--- a/vendor/github.com/spf13/pflag/string_slice.go
+++ b/vendor/github.com/spf13/pflag/string_slice.go
@@ -82,6 +82,11 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
 
 // StringSliceVar defines a string flag with specified name, default value, and usage string.
 // The argument p points to a []string variable in which to store the value of the flag.
+// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
+// For example:
+//   --ss="v1,v2" -ss="v3"
+// will result in
+//   []string{"v1", "v2", "v3"}
 func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
 	f.VarP(newStringSliceValue(value, p), name, "", usage)
 }
@@ -93,6 +98,11 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
 
 // StringSliceVar defines a string flag with specified name, default value, and usage string.
 // The argument p points to a []string variable in which to store the value of the flag.
+// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
+// For example:
+//   --ss="v1,v2" -ss="v3"
+// will result in
+//   []string{"v1", "v2", "v3"}
 func StringSliceVar(p *[]string, name string, value []string, usage string) {
 	CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
 }
@@ -104,6 +114,11 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
 
 // StringSlice defines a string flag with specified name, default value, and usage string.
 // The return value is the address of a []string variable that stores the value of the flag.
+// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
+// For example:
+//   --ss="v1,v2" -ss="v3"
+// will result in
+//   []string{"v1", "v2", "v3"}
 func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
 	p := []string{}
 	f.StringSliceVarP(&p, name, "", value, usage)
@@ -119,6 +134,11 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
 
 // StringSlice defines a string flag with specified name, default value, and usage string.
 // The return value is the address of a []string variable that stores the value of the flag.
+// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
+// For example:
+//   --ss="v1,v2" -ss="v3"
+// will result in
+//   []string{"v1", "v2", "v3"}
 func StringSlice(name string, value []string, usage string) *[]string {
 	return CommandLine.StringSliceP(name, "", value, usage)
 }
diff --git a/vendor/github.com/spf13/pflag/string_to_int.go b/vendor/github.com/spf13/pflag/string_to_int.go
new file mode 100644
index 00000000..5ceda396
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/string_to_int.go
@@ -0,0 +1,149 @@
+package pflag
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// -- stringToInt Value
+type stringToIntValue struct {
+	value   *map[string]int
+	changed bool
+}
+
+func newStringToIntValue(val map[string]int, p *map[string]int) *stringToIntValue {
+	ssv := new(stringToIntValue)
+	ssv.value = p
+	*ssv.value = val
+	return ssv
+}
+
+// Format: a=1,b=2
+func (s *stringToIntValue) Set(val string) error {
+	ss := strings.Split(val, ",")
+	out := make(map[string]int, len(ss))
+	for _, pair := range ss {
+		kv := strings.SplitN(pair, "=", 2)
+		if len(kv) != 2 {
+			return fmt.Errorf("%s must be formatted as key=value", pair)
+		}
+		var err error
+		out[kv[0]], err = strconv.Atoi(kv[1])
+		if err != nil {
+			return err
+		}
+	}
+	if !s.changed {
+		*s.value = out
+	} else {
+		for k, v := range out {
+			(*s.value)[k] = v
+		}
+	}
+	s.changed = true
+	return nil
+}
+
+func (s *stringToIntValue) Type() string {
+	return "stringToInt"
+}
+
+func (s *stringToIntValue) String() string {
+	var buf bytes.Buffer
+	i := 0
+	for k, v := range *s.value {
+		if i > 0 {
+			buf.WriteRune(',')
+		}
+		buf.WriteString(k)
+		buf.WriteRune('=')
+		buf.WriteString(strconv.Itoa(v))
+		i++
+	}
+	return "[" + buf.String() + "]"
+}
+
+func stringToIntConv(val string) (interface{}, error) {
+	val = strings.Trim(val, "[]")
+	// An empty string would cause an empty map
+	if len(val) == 0 {
+		return map[string]int{}, nil
+	}
+	ss := strings.Split(val, ",")
+	out := make(map[string]int, len(ss))
+	for _, pair := range ss {
+		kv := strings.SplitN(pair, "=", 2)
+		if len(kv) != 2 {
+			return nil, fmt.Errorf("%s must be formatted as key=value", pair)
+		}
+		var err error
+		out[kv[0]], err = strconv.Atoi(kv[1])
+		if err != nil {
+			return nil, err
+		}
+	}
+	return out, nil
+}
+
+// GetStringToInt return the map[string]int value of a flag with the given name
+func (f *FlagSet) GetStringToInt(name string) (map[string]int, error) {
+	val, err := f.getFlagType(name, "stringToInt", stringToIntConv)
+	if err != nil {
+		return map[string]int{}, err
+	}
+	return val.(map[string]int), nil
+}
+
+// StringToIntVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a map[string]int variable in which to store the values of the multiple flags.
+// The value of each argument will not try to be separated by comma
+func (f *FlagSet) StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
+	f.VarP(newStringToIntValue(value, p), name, "", usage)
+}
+
+// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
+	f.VarP(newStringToIntValue(value, p), name, shorthand, usage)
+}
+
+// StringToIntVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a map[string]int variable in which to store the value of the flag.
+// The value of each argument will not try to be separated by comma
+func StringToIntVar(p *map[string]int, name string, value map[string]int, usage string) {
+	CommandLine.VarP(newStringToIntValue(value, p), name, "", usage)
+}
+
+// StringToIntVarP is like StringToIntVar, but accepts a shorthand letter that can be used after a single dash.
+func StringToIntVarP(p *map[string]int, name, shorthand string, value map[string]int, usage string) {
+	CommandLine.VarP(newStringToIntValue(value, p), name, shorthand, usage)
+}
+
+// StringToInt defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a map[string]int variable that stores the value of the flag.
+// The value of each argument will not try to be separated by comma
+func (f *FlagSet) StringToInt(name string, value map[string]int, usage string) *map[string]int {
+	p := map[string]int{}
+	f.StringToIntVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
+	p := map[string]int{}
+	f.StringToIntVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// StringToInt defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a map[string]int variable that stores the value of the flag.
+// The value of each argument will not try to be separated by comma
+func StringToInt(name string, value map[string]int, usage string) *map[string]int {
+	return CommandLine.StringToIntP(name, "", value, usage)
+}
+
+// StringToIntP is like StringToInt, but accepts a shorthand letter that can be used after a single dash.
+func StringToIntP(name, shorthand string, value map[string]int, usage string) *map[string]int {
+	return CommandLine.StringToIntP(name, shorthand, value, usage)
+}
diff --git a/vendor/github.com/spf13/pflag/string_to_int_test.go b/vendor/github.com/spf13/pflag/string_to_int_test.go
new file mode 100644
index 00000000..b60bbafb
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/string_to_int_test.go
@@ -0,0 +1,156 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of ths2i source code s2i governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pflag
+
+import (
+	"bytes"
+	"fmt"
+	"strconv"
+	"testing"
+)
+
+func setUpS2IFlagSet(s2ip *map[string]int) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.StringToIntVar(s2ip, "s2i", map[string]int{}, "Command separated ls2it!")
+	return f
+}
+
+func setUpS2IFlagSetWithDefault(s2ip *map[string]int) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.StringToIntVar(s2ip, "s2i", map[string]int{"a": 1, "b": 2}, "Command separated ls2it!")
+	return f
+}
+
+func createS2IFlag(vals map[string]int) string {
+	var buf bytes.Buffer
+	i := 0
+	for k, v := range vals {
+		if i > 0 {
+			buf.WriteRune(',')
+		}
+		buf.WriteString(k)
+		buf.WriteRune('=')
+		buf.WriteString(strconv.Itoa(v))
+		i++
+	}
+	return buf.String()
+}
+
+func TestEmptyS2I(t *testing.T) {
+	var s2i map[string]int
+	f := setUpS2IFlagSet(&s2i)
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getS2I, err := f.GetStringToInt("s2i")
+	if err != nil {
+		t.Fatal("got an error from GetStringToInt():", err)
+	}
+	if len(getS2I) != 0 {
+		t.Fatalf("got s2i %v with len=%d but expected length=0", getS2I, len(getS2I))
+	}
+}
+
+func TestS2I(t *testing.T) {
+	var s2i map[string]int
+	f := setUpS2IFlagSet(&s2i)
+
+	vals := map[string]int{"a": 1, "b": 2, "d": 4, "c": 3}
+	arg := fmt.Sprintf("--s2i=%s", createS2IFlag(vals))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for k, v := range s2i {
+		if vals[k] != v {
+			t.Fatalf("expected s2i[%s] to be %d but got: %d", k, vals[k], v)
+		}
+	}
+	getS2I, err := f.GetStringToInt("s2i")
+	if err != nil {
+		t.Fatalf("got error: %v", err)
+	}
+	for k, v := range getS2I {
+		if vals[k] != v {
+			t.Fatalf("expected s2i[%s] to be %d but got: %d from GetStringToInt", k, vals[k], v)
+		}
+	}
+}
+
+func TestS2IDefault(t *testing.T) {
+	var s2i map[string]int
+	f := setUpS2IFlagSetWithDefault(&s2i)
+
+	vals := map[string]int{"a": 1, "b": 2}
+
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for k, v := range s2i {
+		if vals[k] != v {
+			t.Fatalf("expected s2i[%s] to be %d but got: %d", k, vals[k], v)
+		}
+	}
+
+	getS2I, err := f.GetStringToInt("s2i")
+	if err != nil {
+		t.Fatal("got an error from GetStringToInt():", err)
+	}
+	for k, v := range getS2I {
+		if vals[k] != v {
+			t.Fatalf("expected s2i[%s] to be %d from GetStringToInt but got: %d", k, vals[k], v)
+		}
+	}
+}
+
+func TestS2IWithDefault(t *testing.T) {
+	var s2i map[string]int
+	f := setUpS2IFlagSetWithDefault(&s2i)
+
+	vals := map[string]int{"a": 1, "b": 2}
+	arg := fmt.Sprintf("--s2i=%s", createS2IFlag(vals))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for k, v := range s2i {
+		if vals[k] != v {
+			t.Fatalf("expected s2i[%s] to be %d but got: %d", k, vals[k], v)
+		}
+	}
+
+	getS2I, err := f.GetStringToInt("s2i")
+	if err != nil {
+		t.Fatal("got an error from GetStringToInt():", err)
+	}
+	for k, v := range getS2I {
+		if vals[k] != v {
+			t.Fatalf("expected s2i[%s] to be %d from GetStringToInt but got: %d", k, vals[k], v)
+		}
+	}
+}
+
+func TestS2ICalledTwice(t *testing.T) {
+	var s2i map[string]int
+	f := setUpS2IFlagSet(&s2i)
+
+	in := []string{"a=1,b=2", "b=3"}
+	expected := map[string]int{"a": 1, "b": 3}
+	argfmt := "--s2i=%s"
+	arg1 := fmt.Sprintf(argfmt, in[0])
+	arg2 := fmt.Sprintf(argfmt, in[1])
+	err := f.Parse([]string{arg1, arg2})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range s2i {
+		if expected[i] != v {
+			t.Fatalf("expected s2i[%s] to be %d but got: %d", i, expected[i], v)
+		}
+	}
+}
diff --git a/vendor/github.com/spf13/pflag/string_to_string.go b/vendor/github.com/spf13/pflag/string_to_string.go
new file mode 100644
index 00000000..890a01af
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/string_to_string.go
@@ -0,0 +1,160 @@
+package pflag
+
+import (
+	"bytes"
+	"encoding/csv"
+	"fmt"
+	"strings"
+)
+
+// -- stringToString Value
+type stringToStringValue struct {
+	value   *map[string]string
+	changed bool
+}
+
+func newStringToStringValue(val map[string]string, p *map[string]string) *stringToStringValue {
+	ssv := new(stringToStringValue)
+	ssv.value = p
+	*ssv.value = val
+	return ssv
+}
+
+// Format: a=1,b=2
+func (s *stringToStringValue) Set(val string) error {
+	var ss []string
+	n := strings.Count(val, "=")
+	switch n {
+	case 0:
+		return fmt.Errorf("%s must be formatted as key=value", val)
+	case 1:
+		ss = append(ss, strings.Trim(val, `"`))
+	default:
+		r := csv.NewReader(strings.NewReader(val))
+		var err error
+		ss, err = r.Read()
+		if err != nil {
+			return err
+		}
+	}
+
+	out := make(map[string]string, len(ss))
+	for _, pair := range ss {
+		kv := strings.SplitN(pair, "=", 2)
+		if len(kv) != 2 {
+			return fmt.Errorf("%s must be formatted as key=value", pair)
+		}
+		out[kv[0]] = kv[1]
+	}
+	if !s.changed {
+		*s.value = out
+	} else {
+		for k, v := range out {
+			(*s.value)[k] = v
+		}
+	}
+	s.changed = true
+	return nil
+}
+
+func (s *stringToStringValue) Type() string {
+	return "stringToString"
+}
+
+func (s *stringToStringValue) String() string {
+	records := make([]string, 0, len(*s.value)>>1)
+	for k, v := range *s.value {
+		records = append(records, k+"="+v)
+	}
+
+	var buf bytes.Buffer
+	w := csv.NewWriter(&buf)
+	if err := w.Write(records); err != nil {
+		panic(err)
+	}
+	w.Flush()
+	return "[" + strings.TrimSpace(buf.String()) + "]"
+}
+
+func stringToStringConv(val string) (interface{}, error) {
+	val = strings.Trim(val, "[]")
+	// An empty string would cause an empty map
+	if len(val) == 0 {
+		return map[string]string{}, nil
+	}
+	r := csv.NewReader(strings.NewReader(val))
+	ss, err := r.Read()
+	if err != nil {
+		return nil, err
+	}
+	out := make(map[string]string, len(ss))
+	for _, pair := range ss {
+		kv := strings.SplitN(pair, "=", 2)
+		if len(kv) != 2 {
+			return nil, fmt.Errorf("%s must be formatted as key=value", pair)
+		}
+		out[kv[0]] = kv[1]
+	}
+	return out, nil
+}
+
+// GetStringToString return the map[string]string value of a flag with the given name
+func (f *FlagSet) GetStringToString(name string) (map[string]string, error) {
+	val, err := f.getFlagType(name, "stringToString", stringToStringConv)
+	if err != nil {
+		return map[string]string{}, err
+	}
+	return val.(map[string]string), nil
+}
+
+// StringToStringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a map[string]string variable in which to store the values of the multiple flags.
+// The value of each argument will not try to be separated by comma
+func (f *FlagSet) StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
+	f.VarP(newStringToStringValue(value, p), name, "", usage)
+}
+
+// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
+	f.VarP(newStringToStringValue(value, p), name, shorthand, usage)
+}
+
+// StringToStringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a map[string]string variable in which to store the value of the flag.
+// The value of each argument will not try to be separated by comma
+func StringToStringVar(p *map[string]string, name string, value map[string]string, usage string) {
+	CommandLine.VarP(newStringToStringValue(value, p), name, "", usage)
+}
+
+// StringToStringVarP is like StringToStringVar, but accepts a shorthand letter that can be used after a single dash.
+func StringToStringVarP(p *map[string]string, name, shorthand string, value map[string]string, usage string) {
+	CommandLine.VarP(newStringToStringValue(value, p), name, shorthand, usage)
+}
+
+// StringToString defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a map[string]string variable that stores the value of the flag.
+// The value of each argument will not try to be separated by comma
+func (f *FlagSet) StringToString(name string, value map[string]string, usage string) *map[string]string {
+	p := map[string]string{}
+	f.StringToStringVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
+	p := map[string]string{}
+	f.StringToStringVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// StringToString defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a map[string]string variable that stores the value of the flag.
+// The value of each argument will not try to be separated by comma
+func StringToString(name string, value map[string]string, usage string) *map[string]string {
+	return CommandLine.StringToStringP(name, "", value, usage)
+}
+
+// StringToStringP is like StringToString, but accepts a shorthand letter that can be used after a single dash.
+func StringToStringP(name, shorthand string, value map[string]string, usage string) *map[string]string {
+	return CommandLine.StringToStringP(name, shorthand, value, usage)
+}
diff --git a/vendor/github.com/spf13/pflag/string_to_string_test.go b/vendor/github.com/spf13/pflag/string_to_string_test.go
new file mode 100644
index 00000000..0777f03f
--- /dev/null
+++ b/vendor/github.com/spf13/pflag/string_to_string_test.go
@@ -0,0 +1,162 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of ths2s source code s2s governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pflag
+
+import (
+	"bytes"
+	"encoding/csv"
+	"fmt"
+	"strings"
+	"testing"
+)
+
+func setUpS2SFlagSet(s2sp *map[string]string) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.StringToStringVar(s2sp, "s2s", map[string]string{}, "Command separated ls2st!")
+	return f
+}
+
+func setUpS2SFlagSetWithDefault(s2sp *map[string]string) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.StringToStringVar(s2sp, "s2s", map[string]string{"da": "1", "db": "2", "de": "5,6"}, "Command separated ls2st!")
+	return f
+}
+
+func createS2SFlag(vals map[string]string) string {
+	records := make([]string, 0, len(vals)>>1)
+	for k, v := range vals {
+		records = append(records, k+"="+v)
+	}
+
+	var buf bytes.Buffer
+	w := csv.NewWriter(&buf)
+	if err := w.Write(records); err != nil {
+		panic(err)
+	}
+	w.Flush()
+	return strings.TrimSpace(buf.String())
+}
+
+func TestEmptyS2S(t *testing.T) {
+	var s2s map[string]string
+	f := setUpS2SFlagSet(&s2s)
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getS2S, err := f.GetStringToString("s2s")
+	if err != nil {
+		t.Fatal("got an error from GetStringToString():", err)
+	}
+	if len(getS2S) != 0 {
+		t.Fatalf("got s2s %v with len=%d but expected length=0", getS2S, len(getS2S))
+	}
+}
+
+func TestS2S(t *testing.T) {
+	var s2s map[string]string
+	f := setUpS2SFlagSet(&s2s)
+
+	vals := map[string]string{"a": "1", "b": "2", "d": "4", "c": "3", "e": "5,6"}
+	arg := fmt.Sprintf("--s2s=%s", createS2SFlag(vals))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for k, v := range s2s {
+		if vals[k] != v {
+			t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v)
+		}
+	}
+	getS2S, err := f.GetStringToString("s2s")
+	if err != nil {
+		t.Fatalf("got error: %v", err)
+	}
+	for k, v := range getS2S {
+		if vals[k] != v {
+			t.Fatalf("expected s2s[%s] to be %s but got: %s from GetStringToString", k, vals[k], v)
+		}
+	}
+}
+
+func TestS2SDefault(t *testing.T) {
+	var s2s map[string]string
+	f := setUpS2SFlagSetWithDefault(&s2s)
+
+	vals := map[string]string{"da": "1", "db": "2", "de": "5,6"}
+
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for k, v := range s2s {
+		if vals[k] != v {
+			t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v)
+		}
+	}
+
+	getS2S, err := f.GetStringToString("s2s")
+	if err != nil {
+		t.Fatal("got an error from GetStringToString():", err)
+	}
+	for k, v := range getS2S {
+		if vals[k] != v {
+			t.Fatalf("expected s2s[%s] to be %s from GetStringToString but got: %s", k, vals[k], v)
+		}
+	}
+}
+
+func TestS2SWithDefault(t *testing.T) {
+	var s2s map[string]string
+	f := setUpS2SFlagSetWithDefault(&s2s)
+
+	vals := map[string]string{"a": "1", "b": "2", "e": "5,6"}
+	arg := fmt.Sprintf("--s2s=%s", createS2SFlag(vals))
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for k, v := range s2s {
+		if vals[k] != v {
+			t.Fatalf("expected s2s[%s] to be %s but got: %s", k, vals[k], v)
+		}
+	}
+
+	getS2S, err := f.GetStringToString("s2s")
+	if err != nil {
+		t.Fatal("got an error from GetStringToString():", err)
+	}
+	for k, v := range getS2S {
+		if vals[k] != v {
+			t.Fatalf("expected s2s[%s] to be %s from GetStringToString but got: %s", k, vals[k], v)
+		}
+	}
+}
+
+func TestS2SCalledTwice(t *testing.T) {
+	var s2s map[string]string
+	f := setUpS2SFlagSet(&s2s)
+
+	in := []string{"a=1,b=2", "b=3", `"e=5,6"`, `f=7,8`}
+	expected := map[string]string{"a": "1", "b": "3", "e": "5,6", "f": "7,8"}
+	argfmt := "--s2s=%s"
+	arg0 := fmt.Sprintf(argfmt, in[0])
+	arg1 := fmt.Sprintf(argfmt, in[1])
+	arg2 := fmt.Sprintf(argfmt, in[2])
+	arg3 := fmt.Sprintf(argfmt, in[3])
+	err := f.Parse([]string{arg0, arg1, arg2, arg3})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	if len(s2s) != len(expected) {
+		t.Fatalf("expected %d flags; got %d flags", len(expected), len(s2s))
+	}
+	for i, v := range s2s {
+		if expected[i] != v {
+			t.Fatalf("expected s2s[%s] to be %s but got: %s", i, expected[i], v)
+		}
+	}
+}
diff --git a/vendor/mynewt.apache.org/newt/.rat-excludes b/vendor/mynewt.apache.org/newt/.rat-excludes
index 0256fff8..e305895d 100644
--- a/vendor/mynewt.apache.org/newt/.rat-excludes
+++ b/vendor/mynewt.apache.org/newt/.rat-excludes
@@ -6,6 +6,9 @@
 .gdb_out
 tags
 
+# Ignore documentation folder
+docs
+
 # Non-source files
 COMPATIBLE
 COPYING
@@ -13,7 +16,7 @@ INSTALLING.md
 RELEASE_NOTES.md
 Godeps.json
 .gitignore
-
+Makefile
 
 # Viper - MIT license.
 viper
diff --git a/vendor/mynewt.apache.org/newt/Gopkg.lock b/vendor/mynewt.apache.org/newt/Gopkg.lock
new file mode 100644
index 00000000..3d72fc57
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/Gopkg.lock
@@ -0,0 +1,155 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+  name = "github.com/Sirupsen/logrus"
+  packages = ["."]
+  revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
+  version = "v1.0.5"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/armon/consul-api"
+  packages = ["."]
+  revision = "eb2c6b5be1b66bab83016e0b05f01b8d5496ffbd"
+
+[[projects]]
+  name = "github.com/coreos/etcd"
+  packages = [
+    "client",
+    "pkg/pathutil",
+    "pkg/srv",
+    "pkg/types",
+    "version"
+  ]
+  revision = "33245c6b5b49130ca99280408fadfab01aac0e48"
+  version = "v3.3.8"
+
+[[projects]]
+  name = "github.com/coreos/go-semver"
+  packages = ["semver"]
+  revision = "8ab6407b697782a06568d4b7f1db25550ec2e4c6"
+  version = "v0.2.0"
+
+[[projects]]
+  name = "github.com/davecgh/go-spew"
+  packages = ["spew"]
+  revision = "346938d642f2ec3594ed81d874461961cd0faa76"
+  version = "v1.1.0"
+
+[[projects]]
+  name = "github.com/inconshreveable/mousetrap"
+  packages = ["."]
+  revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
+  version = "v1.0"
+
+[[projects]]
+  name = "github.com/kr/pretty"
+  packages = ["."]
+  revision = "73f6ac0b30a98e433b289500d779f50c1a6f0712"
+  version = "v0.1.0"
+
+[[projects]]
+  name = "github.com/kr/text"
+  packages = ["."]
+  revision = "e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f"
+  version = "v0.1.0"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/mitchellh/mapstructure"
+  packages = ["."]
+  revision = "bb74f1db0675b241733089d5a1faa5dd8b0ef57b"
+
+[[projects]]
+  name = "github.com/pmezard/go-difflib"
+  packages = ["difflib"]
+  revision = "792786c7400a136282c1664665ae0a8db921c6c2"
+  version = "v1.0.0"
+
+[[projects]]
+  name = "github.com/spf13/cast"
+  packages = ["."]
+  revision = "8965335b8c7107321228e3e3702cab9832751bac"
+  version = "v1.2.0"
+
+[[projects]]
+  name = "github.com/spf13/cobra"
+  packages = ["."]
+  revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
+  version = "v0.0.3"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/spf13/jwalterweatherman"
+  packages = ["."]
+  revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
+
+[[projects]]
+  name = "github.com/spf13/pflag"
+  packages = ["."]
+  revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
+  version = "v1.0.1"
+
+[[projects]]
+  name = "github.com/stretchr/testify"
+  packages = ["assert"]
+  revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
+  version = "v1.2.2"
+
+[[projects]]
+  name = "github.com/ugorji/go"
+  packages = ["codec"]
+  revision = "b4c50a2b199d93b13dc15e78929cfb23bfdf21ab"
+  version = "v1.1.1"
+
+[[projects]]
+  branch = "master"
+  name = "github.com/xordataexchange/crypt"
+  packages = [
+    "backend",
+    "backend/consul",
+    "backend/etcd",
+    "config",
+    "encoding/secconf"
+  ]
+  revision = "b2862e3d0a775f18c7cfe02273500ae307b61218"
+
+[[projects]]
+  branch = "master"
+  name = "golang.org/x/crypto"
+  packages = [
+    "cast5",
+    "openpgp",
+    "openpgp/armor",
+    "openpgp/elgamal",
+    "openpgp/errors",
+    "openpgp/packet",
+    "openpgp/s2k",
+    "pbkdf2",
+    "ssh/terminal"
+  ]
+  revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602"
+
+[[projects]]
+  branch = "master"
+  name = "golang.org/x/sys"
+  packages = [
+    "unix",
+    "windows"
+  ]
+  revision = "3c6ecd8f22c6f40fbeec94c000a069d7d87c7624"
+
+[[projects]]
+  name = "gopkg.in/fsnotify.v1"
+  packages = ["."]
+  revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
+  source = "https://github.com/fsnotify/fsnotify.git"
+  version = "v1.4.7"
+
+[solve-meta]
+  analyzer-name = "dep"
+  analyzer-version = 1
+  inputs-digest = "39e73b3e764602883e242e51a9e3a17ebe4f7196716a4da457093e8527c86502"
+  solver-name = "gps-cdcl"
+  solver-version = 1
diff --git a/vendor/mynewt.apache.org/newt/Gopkg.toml b/vendor/mynewt.apache.org/newt/Gopkg.toml
new file mode 100644
index 00000000..4ac43189
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/Gopkg.toml
@@ -0,0 +1,76 @@
+# Gopkg.toml example
+#
+# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+#   name = "github.com/user/project"
+#   version = "1.0.0"
+#
+# [[constraint]]
+#   name = "github.com/user/project2"
+#   branch = "dev"
+#   source = "github.com/myfork/project2"
+#
+# [[override]]
+#   name = "github.com/x/y"
+#   version = "2.4.0"
+#
+# [prune]
+#   non-go = false
+#   go-tests = true
+#   unused-packages = true
+
+
+[[constraint]]
+  name = "github.com/Sirupsen/logrus"
+  version = "1.0.5"
+
+[[constraint]]
+  name = "github.com/kr/pretty"
+  version = "0.1.0"
+
+[[constraint]]
+  branch = "master"
+  name = "github.com/mitchellh/mapstructure"
+
+[[constraint]]
+  name = "github.com/spf13/cast"
+  version = "1.2.0"
+
+[[constraint]]
+  name = "github.com/spf13/cobra"
+  version = "0.0.3"
+
+[[constraint]]
+  branch = "master"
+  name = "github.com/spf13/jwalterweatherman"
+
+[[constraint]]
+  name = "github.com/spf13/pflag"
+  version = "1.0.1"
+
+[[constraint]]
+  name = "github.com/stretchr/testify"
+  version = "1.2.2"
+
+[[constraint]]
+  branch = "master"
+  name = "github.com/xordataexchange/crypt"
+
+[[constraint]]
+  branch = "master"
+  name = "golang.org/x/crypto"
+
+# This constraint added by hand (see
+# https://github.com/golang/dep/issues/1799).
+[[constraint]]
+  name = "gopkg.in/fsnotify.v1"
+  source = "https://github.com/fsnotify/fsnotify.git"
+
+[prune]
+  go-tests = true
+  unused-packages = true
diff --git a/vendor/mynewt.apache.org/newt/LICENSE b/vendor/mynewt.apache.org/newt/LICENSE
index f084df37..1db24bf0 100644
--- a/vendor/mynewt.apache.org/newt/LICENSE
+++ b/vendor/mynewt.apache.org/newt/LICENSE
@@ -305,3 +305,7 @@ For details, see:
 This product bundles go-coap which is available under the MIT license.
 For details, see:
     * newtmgr/vendor/github.com/dustin/go-coap/LICENSE
+
+This product bundles go-homedir which is available under the MIT license.
+For details, see:
+    * newtmgr/vendor/github.com/mitchellh/go-homedir/LICENSE
diff --git a/vendor/mynewt.apache.org/newt/Makefile b/vendor/mynewt.apache.org/newt/Makefile
new file mode 100644
index 00000000..b3663f23
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/Makefile
@@ -0,0 +1,10 @@
+# Use for building deb package. Needed by dpkg-buildpackage. 
+BIN=$(DESTDIR)/usr/bin
+TARGET=newt
+build:
+	./build.sh
+
+install:
+	install -d $(BIN)
+	install $(TARGET)/$(TARGET) $(BIN)
+	rm -f  $(TARGET)/$(TARGET)
diff --git a/vendor/mynewt.apache.org/newt/README.md b/vendor/mynewt.apache.org/newt/README.md
index e462a817..e7d4a6bd 100644
--- a/vendor/mynewt.apache.org/newt/README.md
+++ b/vendor/mynewt.apache.org/newt/README.md
@@ -108,12 +108,8 @@ code coverage is a win for every Apache Mynewt user.
 ## Writing Documentation
 
 Contributing to documentation (in addition to writing tests), is a great way
-to get involved with the Apache Mynewt project.
-
-Pull requests to the apache-mynewt-site repository on Github are the best
-way to submit documentation.  For more information on contributing to the
-documentation, the [FAQ](https://mynewt.apache.org/faq/answers/) has some
-more information.
+to get involved with the Apache Mynewt project. The Newt documentation is found 
+in [/docs](/docs).
 
 ## Getting Help
 
diff --git a/vendor/mynewt.apache.org/newt/RELEASE_NOTES.md b/vendor/mynewt.apache.org/newt/RELEASE_NOTES.md
index 9d5b64a0..d2b9dcf1 100644
--- a/vendor/mynewt.apache.org/newt/RELEASE_NOTES.md
+++ b/vendor/mynewt.apache.org/newt/RELEASE_NOTES.md
@@ -1,6 +1,6 @@
 # RELEASE NOTES
 
-7 March 2017 - Apache Newt v1.0.0
+04 June 2018 - Apache Newt v1.4.0
 
 For full release notes, please visit the
 [Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes).
@@ -17,9 +17,6 @@ Future versions will add:
 
   * More robust package management and versioning
 
-  * Plenty of helper commands for seeing what's installed, what's changed,
-    and why things failed.
-
 If working on next-generation build and source package management systems
 sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt
 Developer's list, dev@mynewt.apache.org.
diff --git a/vendor/mynewt.apache.org/newt/build.sh b/vendor/mynewt.apache.org/newt/build.sh
index 9405e6bb..b56f0e43 100755
--- a/vendor/mynewt.apache.org/newt/build.sh
+++ b/vendor/mynewt.apache.org/newt/build.sh
@@ -26,7 +26,7 @@ expandpath() {
     )
 }
 
-### Ensure >= go1.7 is installed.
+### Ensure >= go1.10 is installed.
 go_ver_str="$(go version | cut -d ' ' -f 3)"
 go_ver="${go_ver_str#go}"
 
@@ -49,9 +49,9 @@ then
     go_min=0
 fi
 
-if [ ! "$go_maj" -gt 1 ] && [ ! "$go_min" -ge 7 ]
+if [ ! "$go_maj" -gt 1 ] && [ ! "$go_min" -ge 10 ]
 then
-    printf "* Error: go 1.7 or later is required (detected version: %s)\n" \
+    printf "* Error: go 1.10 or later is required (detected version: %s)\n" \
         "$go_maj"."$go_min".X
     exit 1
 fi
@@ -80,4 +80,4 @@ ln -s "$installdir" "$repodir"
 )
 
 ### Delete the temporary directory.
-rm -r "$godir"
+rm -rf "$godir"
diff --git a/vendor/mynewt.apache.org/newt/docs/.gitignore b/vendor/mynewt.apache.org/newt/docs/.gitignore
new file mode 100644
index 00000000..2abe8a03
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/.gitignore
@@ -0,0 +1,5 @@
+xml
+node_modules
+_build
+doxygen_*
+*.pyc
diff --git a/vendor/mynewt.apache.org/newt/docs/Makefile b/vendor/mynewt.apache.org/newt/docs/Makefile
new file mode 100644
index 00000000..da8a7b36
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/Makefile
@@ -0,0 +1,16 @@
+# Make a preview site for Sphinx output
+
+BUILDDIR      = _build/html
+
+.PHONY: Makefile clean preview
+
+clean:
+	rm -rf _build
+
+preview: _build sphinx
+
+_build:
+	mkdir -p _build
+
+sphinx:
+	sphinx-build . ${BUILDDIR}
diff --git a/vendor/mynewt.apache.org/newt/docs/README.rst b/vendor/mynewt.apache.org/newt/docs/README.rst
new file mode 100644
index 00000000..032ff328
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/README.rst
@@ -0,0 +1,29 @@
+Mynewt Newt Tool Documentation
+#################################
+
+This folder holds the documentation for the newt tool for the
+`Apache Mynewt`_ project. It is  built using `Sphinx`_.
+
+The complete project documentation can be found at `mynewt documentation`_
+
+.. contents::
+
+Writing Documentation
+=======================
+
+See: https://github.com/apache/mynewt-documentation#writing-documentation
+
+Previewing Changes
+==========================
+
+In order to preview any changes you make you must first install a Sphinx toolchain as
+described at https://github.com/apache/mynewt-documentation#id3. Then:
+
+.. code-block:: bash
+
+  $ cd docs
+  $ make clean && make preview && (cd _build/html && python -m SimpleHTTPServer 8080)
+
+.. _Apache Mynewt: https://mynewt.apache.org/
+.. _mynewt documentation: https://github.com/apache/mynewt-documentation
+.. _Sphinx: http://www.sphinx-doc.org/
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_build.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_build.rst
new file mode 100644
index 00000000..af8bef25
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_build.rst
@@ -0,0 +1,42 @@
+newt build
+-----------
+
+Build one or more targets.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt build  <target-name> [target_name ...] [flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Compiles, links, and builds an ELF binary for the target named <target-name>. It builds an ELF file for the application specified by the ``app`` variable for the ``target-name`` target. The image can be loaded and run on the hardware specified by the ``bsp`` variable for the target. The command creates the 'bin/' directory under the project's base directory (that the ``newt new`` command created) and stores the executable in the 'bin/targets/<target-name>/app/apps/<app-name>' directory. A ``manifest.json`` build manifest file is also generated in the same directory. This build manifest contains information such as build time, version, image name, a hash to identify the image, packages actually used to create the build, and the target for which the image is built.
+
+You can specify a list of target names, separated by a space, to build multiple targets.
+
+Examples
+^^^^^^^^
+
++------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Usage                              | Explanation                                                                                                                                                                                                                                                    |
++====================================+================================================================================================================================================================================================================================================================+
+| ``newt build my_blinky_sim``       | Builds an executable for the ``my_blinky_sim`` target. For example, if the ``my_blinky_sim`` target has ``app`` set to ``apps/blinky``, you will find the generated .elf, .a, and .lst files in the 'bin/targets/my\_blinky\_sim/app/apps/blinky' directory.   |
++------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| ``newt build my_blinky_sim myble`` | Builds the images for the applications defined by the ``my_blinky_sim`` and ``myble`` targets.                                                                                                                                                                 |
++------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_clean.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_clean.rst
new file mode 100644
index 00000000..7c2d1f61
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_clean.rst
@@ -0,0 +1,42 @@
+newt clean
+-----------
+
+Delete build artifacts for one or more targets.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt clean <target-name> [target-name...] | all [flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Deletes all the build artifacts generated for the ``target-name`` target. It does not delete the target definition. You can specify a list of targets, separated by a space, to delete the artifacts for multiple targets, or specify ``all`` to delete the artifacts for all targets.
+
+Examples
+^^^^^^^^
+
++------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Usage                              | Explanation                                                                                                                                                                              |
++====================================+==========================================================================================================================================================================================+
+| ``newt clean myble``               | Deletes the 'bin/targets/myble' directory where all the build artifacts generated from the ``myble`` target build are stored.                                                            |
++------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| ``newt clean my_blinky_sim myble`` | Deletes the 'bin/targets/my\_blinky\_sim' and the 'bin/targets/myble' directories where all the artifacts generated from the ``my_blinky_sim`` and ``myble`` target builds are stored.   |
++------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| ``newt clean all``                 | Removes the artifacts for all target builds. Deletes the top level 'bin' directory.                                                                                                      |
++------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_complete.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_complete.rst
new file mode 100644
index 00000000..205710d4
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_complete.rst
@@ -0,0 +1,35 @@
+newt complete 
+--------------
+
+Performs bash autocompletion using tab. It is not intended to be called directly from the command line.
+
+Install bash autocompletion
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        $ brew install bash-completion
+        Updating Homebrew...
+        <snip>
+        Bash completion has been installed to:
+          /usr/local/etc/bash_completion.d
+        ==> Summary
+        🍺  /usr/local/Cellar/bash-completion/1.3_1: 189 files, 607.8K
+
+Enable autocompletion for newt
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        $ complete -C "newt complete" newt
+
+Usage
+^^^^^
+
+Hit tab and see possible completion options or completed command.
+
+.. code-block:: console
+
+        $ newt target s
+        set   show  
+        $ newt target show
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_create_image.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_create_image.rst
new file mode 100644
index 00000000..9c4c544d
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_create_image.rst
@@ -0,0 +1,57 @@
+newt create-image
+------------------
+
+Create and sign an image by adding an image header to the binary file created for a target. Version number in the header is set to <version>. To sign an image provide a .pem file for the signing-key and an optional key-id.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt create-image <target-name> <version> [signing-key [key-id]][flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Adds an image header to the created binary file for the ``target-name`` target. The image version is set to ``version``. It creates a ``<app-name>.img`` file the image, where ``app-name`` is the value specified in the target ``app`` variable, and stores the file in the '/bin/targets/<target-name>/app/apps/<app-name>/' directory. It also creates a ``<app-name>.hex`` file for the image in the same directory, and adds the version, build id, image file name, and image hash to the ``manifest.json`` file that the ``newt build`` command created.
+
+To sign an image, provide a .pem file for the ``signing-key`` and an optional ``key-id``. ``key-id`` must be a value between 0-255.
+
+Examples
+^^^^^^^^
+
+================================================== =================================================================================
+Usage                                              Explanation
+================================================== =================================================================================
+``newt create-image myble2 1.0.1.0``               Creates an image for target ``myble2`` and assigns it version
+                                                   ``1.0.1.0``.
+
+                                                   For the following target definition:
+
+                                                   | targets/myble2
+                                                   | app=\@apache-mynewt-core/apps/btshell
+                                                   | bsp=\@apache-mynewt-core/hw/bsp/nrf52dk
+                                                   | build\_profile=optimized
+                                                   | syscfg=STATS\_NAMES=1
+
+                                                   the 'bin/targets/myble2/app/apps/btshell/btshell.img' and
+                                                   'bin/targets/myble2/app/apps/btshell/btshell.hex' files are created,
+                                                   and the manifest in 'bin/targets/myble2/app/apps/btshell/manifest.json'
+                                                   is updated with the image information.
+
+``newt create-image myble2 1.0.1.0 private.pem``   Creates an image for target ``myble2`` and assigns it the version
+                                                   ``1.0.1.0``. Signs the image using private key specified by the private.pem file.
+================================================== =================================================================================
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_debug.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_debug.rst
new file mode 100644
index 00000000..8bb9af82
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_debug.rst
@@ -0,0 +1,48 @@
+newt debug
+-----------
+
+Open a debugger session to a target.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt debug <target-name> [flag]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+          --extrajtagcmd string   Extra commands to send to JTAG software
+      -n, --noGDB                 Do not start GDB from command line
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Opens a debugger session to the image built for the <target-name> target.
+
+Examples
+^^^^^^^^
+
++--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Usage                    | Explanation                                                                                                                                                                                                                                                                                |
++==========================+============================================================================================================================================================================================================================================================================================+
+| ``newt debug myble2``    | Opens a J-Link connection and starts a GNU gdb session to debug bin/targets/myble2/app/apps/btshell/btshell.elf when the target is as follows: targets/myble2 app=\@apache-mynewt-core/apps/btshell bsp=\@apache-mynewt-core/hw/bsp/nrf52dk build_profile=optimized syscfg=STATS_NAMES=1   |
++--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| ``newt debug myble2 -n`` | Opens a J-Link connection bin/targets/myble2/app/apps/btshell/btshell.elf but do not start GDB on the command line.                                                                                                                                                                        |
++--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_help.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_help.rst
new file mode 100644
index 00000000..6a722eb7
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_help.rst
@@ -0,0 +1,68 @@
+newt help
+----------
+
+Display the help text for the newt command line tool:
+
+.. code-block:: console
+
+    Newt allows you to create your own embedded application based on the Mynewt
+    operating system. Newt provides both build and package management in a single
+    tool, which allows you to compose an embedded application, and set of
+    projects, and then build the necessary artifacts from those projects. For more
+    information on the Mynewt operating system, please visit
+    https://mynewt.apache.org/.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt help [command]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Available Commands:
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        build        Build one or more targets
+        clean        Delete build artifacts for one or more targets
+        create-image Add image header to target binary
+        debug        Open debugger session to target
+        info         Show project info
+        install      Install project dependencies
+        load         Load built target to board
+        mfg          Manufacturing flash image commands
+        new          Create a new project
+        pkg          Create and manage packages in the current workspace
+        run          build/create-image/download/debug <target>
+        size         Size of target components
+        sync         Synchronize project dependencies
+        target       Command for manipulating targets
+        test         Executes unit tests for one or more packages
+        upgrade      Upgrade project dependencies
+        vals         Display valid values for the specified element type(s)
+        version      Display the Newt version number
+
+Examples
+^^^^^^^^
+
++------------------------+----------------------------------------------------------+
+| Usage                  | Explanation                                              |
++========================+==========================================================+
+| ``newt help target``   | Displays the help text for the newt ``target`` command   |
++------------------------+----------------------------------------------------------+
+| ``newt help``          | Displays the help text for newt tool                     |
++------------------------+----------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_info.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_info.rst
new file mode 100644
index 00000000..5bc5ab83
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_info.rst
@@ -0,0 +1,29 @@
+newt info 
+----------
+
+Show information about the current project.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt info [flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Displays the repositories in the current project (the local as well as all the external repositories fetched). It also displays the packages in the local repository.
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_install.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_install.rst
new file mode 100644
index 00000000..149258fc
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_install.rst
@@ -0,0 +1,38 @@
+newt install 
+-------------
+
+Install project dependencies.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt install [flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+        -f, --force  Force install of the repositories in project, regardless of what exists in repos directory
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+This command downloads the description for all the repositories specified in the ``project.yml`` file for the current project, and installs the correct versions of all the packages specified by the project dependencies.
+
+You must run this command from within the current project directory. (Remember to ``cd`` into this project directory after you use ``newt new`` to create this project before you run ``newt install``.)
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_load.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_load.rst
new file mode 100644
index 00000000..f2fd4125
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_load.rst
@@ -0,0 +1,36 @@
+newt load 
+----------
+
+Load application image onto the board for a target.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt load <target-name> [flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+        --extrajtagcmd string   Extra commands to send to JTAG software
+
+Global Flags:
+~~~~~~~~~~~~~
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Uses download scripts to automatically load, onto the connected board, the image built for the app defined by the ``target-name`` target If the wrong board is connected or the target definition is incorrect (i.e. the wrong values are given for bsp or app), the command will fail with error messages such as ``Can not connect to J-Link via USB`` or ``Unspecified error -1``.
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_mfg.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_mfg.rst
new file mode 100644
index 00000000..e6147883
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_mfg.rst
@@ -0,0 +1,109 @@
+newt mfg
+---------
+
+Commands to create, build, and upload manufacturing image.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt mfg [flags]
+        newt mfg [command]
+
+Available Commands:
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        create      Create a manufacturing flash image
+        deploy      Build and upload a manufacturing image (build + load)
+        load        Load a manufacturing flash image onto a device
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Sub-command   | Explanation                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
++===============+================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================+
+| create        | A manufacturing image specifies 1) a boot loader target, and 2) one or more image targets. Assuming the manufacturing entity has been created and defined in the ``mfgs/<mfg image name>/`` package (see Examples below), this command collects the manufacturing related files in the newly created ``bin/mfgs/<mfg image name>`` directory. The collection includes the image file, the hex file, and the manifests with the image build time, version, manufacturing package build time, image ID (or hash) etc. It is essentially a snapshot of the image data and metadata uploaded to the device flash at manufacturing time. Note that the command expects the targets and images to have already been built using ``newt build`` and ``newt create-image`` commands.   |
++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| deploy        | A combination of build and load commands to put together and upload manufacturing image on to the device.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| load          | Loads the manufacturing package onto to the flash of the connected device.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
++---------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+Examples
+^^^^^^^^
+
+Suppose you have created two targets (one for the bootloader and one for the ``blinky`` app).
+
+.. code-block:: console
+
+    $ newt target show
+    targets/my_blinky_sim
+        app=apps/blinky
+        bsp=@apache-mynewt-core/hw/bsp/native
+        build_profile=debug
+    targets/rb_blinky
+        app=apps/blinky
+        bsp=@apache-mynewt-core/hw/bsp/rb-nano2
+        build_profile=debug
+    targets/rb_boot
+        app=@apache-mynewt-core/apps/boot
+        bsp=@apache-mynewt-core/hw/bsp/rb-nano2
+        build_profile=optimized
+
+Create the directory to hold the mfg packages.
+
+.. code-block:: console
+
+    $ mkdir -p mfgs/rb_blinky_rsa
+
+The ``rb_blinky_rsa`` package needs a pkg.yml file. In addition it is needs a mfg.yml file to specify the two constituent targets. An example of each file is shown below.
+
+.. code-block:: console
+
+    $  more mfgs/rb_blinky_rsa/pkg.yml
+    pkg.name: "mfgs/rb_blinky_rsa"
+    pkg.type: "mfg"
+    pkg.description:
+    pkg.author:
+    pkg.homepage:
+
+.. code-block:: console
+
+    $  more mfgs/rb_blinky_rsa/mfg.yml
+    mfg.bootloader: 'targets/rb_boot'
+    mfg.images:
+        - 'targets/rb_blinky'
+
+Build the bootloader and app images.
+
+.. code-block:: console
+
+    $ newt build rb_boot
+    $ newt create-image rb_blinky 0.0.1
+
+Run the ``newt mfg create`` command to collect all the manufacturing snapshot files.
+
+.. code-block:: console
+
+    $ newt mfg create rb_blinky_rsa 0.0.1
+    Creating a manufacturing image from the following files:
+    <snip>
+    Generated the following files:
+    <snip>
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_new.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_new.rst
new file mode 100644
index 00000000..ab094ad1
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_new.rst
@@ -0,0 +1,38 @@
+newt new
+---------
+
+Create a new project from a skeleton. Currently, the default skeleton is the `blinky repository <https://github.com/apache/mynewt-blinky>`__.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt new <project-name> [flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+~~~~~~~~~~~
+
+Creates a new project named ``project-name`` from the default skeleton `blinky repository <https://github.com/apache/mynewt-blinky>`__.
+
+Examples
+^^^^^^^^
+
++---------------------------+-------------------------------------------------------------------------------------------------------------------------+
+| Usage                     | Explanation                                                                                                             |
++===========================+=========================================================================================================================+
+| ``newt new test_project`` | Creates a new project named ``test_project`` using the default skeleton from the ``apache/mynewt-blinky`` repository.   |
++---------------------------+-------------------------------------------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_pkg.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_pkg.rst
new file mode 100644
index 00000000..999947ed
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_pkg.rst
@@ -0,0 +1,65 @@
+newt pkg
+---------
+
+Commands for creating and manipulating packages.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt pkg [command] [flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+     -t, --type string   Type of package to create: app, bsp, lib, sdk, unittest. (default "lib")
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+The pkg command provides subcommands to create and manage packages. The subcommands take one or two ``package-name`` arguments.
+
++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Sub-command   | Explanation                                                                                                                                                                                                                                                                                         |
++===============+=====================================================================================================================================================================================================================================================================================================+
+| copy          | The copy <src-pkg> <dst-pkg> command creates the new ``dst-pkg`` package by cloning the ``src-pkg`` package.                                                                                                                                                                                        |
++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| move          | The move <old-pkg> <new-pkg> command moves the ``old-pkg`` package to the ``new-pkg`` package.                                                                                                                                                                                                      |
++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| new           | The new <new-pkg> command creates a new package named ``new-pkg``, from a template, in the current directory. You can create a package of type ``app``, ``bsp``, ``lib``, ``sdk``, or ``unittest``. The default package type is ``lib``. You use the -t flag to specify a different package type.   |
++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| remove        | The remove <my-pkg> command deletes the ``my-pkg`` package.                                                                                                                                                                                                                                         |
++---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+Examples
+^^^^^^^^
+
++---------------+--------------------------------------------------+-----------------------------------------------------------------------------------------+
+| Sub-command   | Usage                                            | Explanation                                                                             |
++===============+==================================================+=========================================================================================+
+| copy          | ``newt pkg copy apps/btshell apps/new_btshell``  | Copies the ``apps/btshell`` package to the ``apps/new_btshell``.                        |
++---------------+--------------------------------------------------+-----------------------------------------------------------------------------------------+
+| move          | ``newt pkg move apps/slinky apps/new_slinky``    | Moves the ``apps/slinky`` package to the ``apps/new_slinky`` package.                   |
++---------------+--------------------------------------------------+-----------------------------------------------------------------------------------------+
+| new           | ``newt pkg new apps/new_slinky``                 | Creates a package named ``apps/new_slinky`` of type ``pkg`` in the current directory.   |
++---------------+--------------------------------------------------+-----------------------------------------------------------------------------------------+
+| new           | ``newt pkg new hw/bsp/myboard -t bsp``           | Creates a package named ``hw/bsp/myboard`` of type ``bsp`` in the current directory.    |
++---------------+--------------------------------------------------+-----------------------------------------------------------------------------------------+
+| remove        | ``newt pkg remove hw/bsp/myboard``               | Removes the ``hw/bsp/myboard`` package.                                                 |
++---------------+--------------------------------------------------+-----------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_resign_image.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_resign_image.rst
new file mode 100644
index 00000000..7a942399
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_resign_image.rst
@@ -0,0 +1,46 @@
+newt resign-image
+------------------
+
+Sign or re-sign an existing image file.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt resign-image <image-file> [signing-key [key-id]][flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Changes the signature of an existing image file. To sign an image, specify a .pem file for the ``signing-key`` and an
+optional ``key-id``. ``key-id`` must be a value between 0-255. If a signing key is not specified, the command strips the
+current signature from the image file.
+
+A new image header is created. The rest of the image is byte-for-byte equivalent to the original image.
+
+Warning: The image hash will change if you change the key-id or the type of key used for signing.
+
+Examples
+^^^^^^^^
+
++------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+
+| Usage                                                                              | Explanation                                                                                   |
++====================================================================================+===============================================================================================+
+| ``newt resign-image bin/targets/myble/app/apps/btshell/btshell.img private.pem``   | Signs the ``bin/targets/myble/app/apps/btshell/btshell.img`` file with the private.pem key.   |
++------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+
+| ``newt resign-image bin/targets/myble/app/apps/btshell/btshell.img``               | Strips the current signature from ``bin/targets/myble/app/apps/btshell/btshell.img`` file.    |
++------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_run.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_run.rst
new file mode 100644
index 00000000..3457e144
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_run.rst
@@ -0,0 +1,53 @@
+newt run
+---------
+
+A single command to do four steps - build a target, create-image, load image on a board, and start a debug session with the image on the board.
+
+**Note**: If the version number is omitted:
+
+-  The create-image step is skipped for a bootloader target.
+-  You will be prompted to enter a version number for an application target.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt run <target-name> [<version>][flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+          --extrajtagcmd string   Extra commands to send to JTAG software
+      -n, --noGDB                 Do not start GDB from the command line
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Same as running ``build <target-name>``, ``create-image <target-name> <version>``, ``load <target-name>``, and ``debug <target-name>``.
+
+Examples
+^^^^^^^^
+
++------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Usage                              | Explanation                                                                                                                                                                                                                                                                                                                                                                          |
++====================================+======================================================================================================================================================================================================================================================================================================================================================================================+
+| ``newt run blink_rigado``          | Compiles and builds the image for the ``app`` and the ``bsp`` defined for target ``blink_rigado``, loads the image onto the board, and opens an active GNU gdb debugging session to run the image.                                                                                                                                                                                   |
++------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| ``newt run ble_rigado 0.1.0.0``    | Compiles and builds the image for the ``app`` and the ``bsp`` defined for target ``ble_rigado``, signs and creates the image with version number 0.1.0.0, loads the image onto the board, and opens an active GNU gdb debugging session to run the image. Note that if there is no bootloader available for a particular board/kit, a signed image creation step is not necessary.   |
++------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_size.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_size.rst
new file mode 100644
index 00000000..79f00162
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_size.rst
@@ -0,0 +1,73 @@
+newt size
+----------
+
+Calculates the size of target components for a target.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt size <target-name> [flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+        -F, --flash   Print FLASH statistics
+        -R, --ram     Print RAM statistics
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+      -h, --help              Help for newt commands
+      -j, --jobs int          Number of concurrent build jobs (default 8)
+      -l, --loglevel string   Log level (default "WARN")
+      -o, --outfile string    Filename to tee output to
+      -q, --quiet             Be quiet; only display error output
+      -s, --silent            Be silent; don't output anything
+      -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Displays the RAM and FLASH size of each component for the ``target-name`` target.
+
+Examples
+^^^^^^^^
+
++-------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+| Usage                         | Explanation                                                                                                                     |
++===============================+=================================================================================================================================+
+| ``newt size blink_rigado``    | Inspects and lists the RAM and Flash memory that each component (object files and libraries) for the ``blink_rigado`` target.   |
++-------------------------------+---------------------------------------------------------------------------------------------------------------------------------+
+
+Example output for ``newt size blink_rigado``:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+
+    $ newt size blink_rigado
+      FLASH     RAM
+          9     223 *fill*
+       1052       0 baselibc.a
+        195    1116 blinky.a
+        616     452 bmd300eval.a
+         64       0 cmsis-core.a
+        124       0 crt0.o
+          8       0 crti.o
+         16       0 crtn.o
+        277     196 full.a
+         20       8 hal.a
+         96    1068 libg.a
+       1452       0 libgcc.a
+        332      28 nrf52xxx.a
+       3143     677 os.a
+
+    objsize
+       text    data     bss     dec     hex filename
+       7404    1172    2212   10788    2a24 /Users/<username>/dev/rigado/bin/blink_rigado/apps/blinky/blinky.elf
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_sync.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_sync.rst
new file mode 100644
index 00000000..685e05fd
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_sync.rst
@@ -0,0 +1,39 @@
+newt sync
+----------
+
+Synchronize and refresh the contents of the local copy of all the repositories used in the project with the latest
+updates maintained in the remote repositories.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt sync [flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+        -f, --force             Force overwrite of existing remote repository
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Synchronize project dependencies and repositories. Prior to 1.0.0 release, the command deletes and resynchronizes each
+repository. Post 1.0.0, it will abort the synchronization if there are any local changes to any repository. Using the -f
+to force overwrite of existing repository will stash and save the changes while pulling in all the latest changes from the remote repository.
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_target.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_target.rst
new file mode 100644
index 00000000..2beece15
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_target.rst
@@ -0,0 +1,185 @@
+newt target
+------------
+
+Commands to create, delete, configure and query targets.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt target [command] [flags]
+
+Available Commands:
+^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        amend       Add, change, or delete values for multi-value target variables
+        config      View or populate a target's system configuration settings
+        copy        Copy target
+        create      Create a target
+        delete      Delete target
+        dep         View target's dependency graph
+        revdep      View target's reverse-dependency graph
+        set         Set target configuration variable
+        show        View target configuration variables
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+      -h, --help              Help for newt commands
+      -j, --jobs int          Number of concurrent build jobs (default 8)
+      -l, --loglevel string   Log level (default "WARN")
+      -o, --outfile string    Filename to tee output to
+      -q, --quiet             Be quiet; only display error output
+      -s, --silent            Be silent; don't output anything
+      -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+The target command provides subcommands to create, build, delete, and query targets. The subcommands take one or two ``target-name`` arguments.
+
+=============   =========================================================================================================================
+Sub-command     Explanation
+=============   =========================================================================================================================
+amend           The amend command allows you to add, change, or delete values for multi-value target variables that you
+                have set with the ``newt target set`` command. The format of the amend command is:
+
+                ``newt target amend <target-name> <var-name=var-value> [var-name=var-value...]``
+
+                Specify the ``-d`` flag to delete values.
+
+                The following multi-value variables can be amended: ``aflags``, ``cflags``, ``lflags``, ``syscfg``.
+
+                The ``var-value`` format depends on the ``var-name`` as follows:
+
+                ``aflags``, ``cflags``, ``lflags``:
+                  A string of flags, with each flag separated by a space. These variables are saved in the target's ``pkg.yml`` file.
+
+                ``syscfg``:
+                  The ``syscfg`` variable allows you to assign values to configuration settings in your target's ``syscfg.yml`` file.
+
+                  The format is ``syscfg=setting-name1=setting-value1[:setting-name2=setting-value2...]``, where ``setting-name1`` is a
+                  configuration setting name and ``setting-value1`` is the value to assign to ``setting-name1``. If ``setting-value1``
+                  is not specified, the setting is set to value ``1``. You use a ``:`` to delimit each setting when you amend multiple
+                  settings.
+
+                  To delete a system configuration setting, you only need to specify the setting name. 
+                  For example, ``syscfg=setting-name1:setting-name2``
+                  deletes configuration settings named ``setting-name1`` and ``setting-name2``.
+
+config          The config command allows you to view or populate a target's system configuration settings.
+                A target's system configuration settings include the settings of all the packages it includes.
+                The settings for a package are listed in the package's ``syscfg.yml`` file. The ``config`` command has
+                two subcommands: ``show`` and ``init``. The config show <target-name> command displays the system
+                configuration setting definitions and values for all the packages that the ``target-name`` target includes.
+                The config init <target-name> command populates the target's ``syscfg.yml`` file with the system configuration
+                values for all the packages that the ``target-name`` target includes.
+
+copy            The copy <src-target> <dst-target> command creates a new target named ``dst-target`` by cloning the
+                ``src-target`` target.
+
+create          The create <target-name> command creates an empty target named ``target-name``. It creates the
+                ``targets/target-name`` directory and the skeleton ``pkg.yml`` and ``target.yml`` files in the directory.
+
+delete          The delete <target-name> command deletes the description for the ``target-name`` target. It deletes
+                the 'targets/target-name' directory. It does not delete the 'bin/targets/target-name' directory where
+                the build artifacts are stored. If you want to delete the build artifacts, run the ``newt clean <target-name>``
+                command **before** deleting the target.
+
+dep             The dep <target-name> command displays a dependency tree for the packages that the ``target-name``
+                target includes. It shows each package followed by the list of libraries or packages that it
+                depends on.
+
+revdep          The revdep <target-name> command displays the reverse dependency tree for the packages that the
+                ``target-name`` target includes. It shows each package followed by the list of libraries or packages
+                that depend on it.
+
+set             The set <target-name> <var-name=var-value> [var-name=var-value...] command sets variables (attributes)
+                for the <target-name> target. The set command overwrites your current variable values.
+
+                The valid ``var-name`` values are: ``app``, ``bsp``, ``loader``, ``build_profile``, ``cflags``,
+                ``lflags``, ``aflags``, ``syscfg``.
+
+                The ``var-value`` format depends on the ``var-name`` as follows:
+
+                ``app``, ``bsp``, ``loader``:
+                  \@<source-path>, where ``source-path`` is the directory containing the application or bsp source.
+                  These variables are stored in the target's target.yml file. For a simulated target, e.g. for software
+                  testing purposes, set ``bsp`` to ``@apache-mynewt-core/hw/bsp/native``.
+
+                ``build_profile``:
+                  ``optimized`` or ``debug``
+
+                ``aflags``, ``cflags``, ``lflags``:
+                  A string of flags, with each flag separated by a space. These variables are saved in the target's ``pkg.yml`` file.
+
+                ``syscfg``:
+                  The ``syscfg`` variable allows you to assign values to configuration settings in your target's ``syscfg.yml`` file.
+
+                  The format is ``syscfg=setting-name1=setting-value1[:setting-name2=setting-value2...]``, where ``setting-name1``
+                  is a configuration setting name and ``setting-value1`` is the value to assign to ``setting-name1``.
+                  If ``setting-value1`` is not specified, the setting is set to value ``1``. You use a ``:`` to delimit
+                  each setting when you set multiple settings.
+
+                You can specify ``var-name=`` or ``var-name=""`` to unset a variable value.
+
+                **Warning**: For multi-value variables, the command overrides all existing values. Use
+                the ``newt target amend`` command to change or add new values for a multi-value variable after you have
+                set the variable value. The multi-value variables are: ``aflags``, ``cflags``, ``lflags``, and ``syscfg``
+
+                To display all the existing values for a target variable (attribute), you can run the ``newt vals <variable-name>``
+                command. For example, ``newt vals app`` displays the valid values available for the variable ``app`` for any target.
+
+show            The show [target-name] command shows the values of the variables (attributes) for the ``target-name``
+                target. When ``target-name`` is not specified, the command shows the variables for
+                all the targets that are defined for your project.
+
+=============   =========================================================================================================================
+
+
+Examples
+^^^^^^^^
+
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Sub-command   | Usage                                                   | Explanation                                                                                                                                                                                                                                           |
++===============+=========================================================+=======================================================================================================================================================================================================================================================+
+| amend         | ``newt target amend myble``                             | Changes (or adds) the ``CONFIG_NEWTMGR`` variable to value 0 in the ``syscfg.yml`` file and adds the -DTEST flag to ``pkg.cflags`` in the ``pkg.yml`` file for the ``myble`` target. Other syscfg setting values and cflags values are not changed.   |
+|               | ``syscfg=CONFIG_NEWTMGR=0 cflags="-DTEST"``             |                                                                                                                                                                                                                                                       |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| amend         | ``newt target amend myble``                             | Deletes the ``LOG_LEVEL`` and ``CONFIG_NEWTMGR`` settings from the ``syscfg.yml`` file and the -DTEST flag from ``pkg.cflags`` for the ``myble`` target. Other syscfg setting values and cflags values are not changed.                               |
+|               | ``-d syscfg=LOG_LEVEL:CONFIG_NEWTMGR cflags="-DTEST"``  |                                                                                                                                                                                                                                                       |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| config show   | ``newt target config show rb_blinky``                   | Shows the system configuration settings for all the packages that the ``rb_blinky`` target includes.                                                                                                                                                  |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| config init   | ``newt target config init my_blinky``                   | Creates and populates the ``my_blinky`` target's ``syscfg.yml`` file with the system configuration setting values from all the packages that the ``my_blinky`` target includes.                                                                       |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| copy          | ``newt target copy rb_blinky rb_btshell``               | Creates the ``rb_btshell`` target by cloning the ``rb_blinky`` target.                                                                                                                                                                                |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| create        | ``newt target create my_new_target``                    | Creates the ``my_newt_target`` target. It creates the ``targets/my_new_target`` directory and creates the skeleton ``pkg.yml`` and ``target.yml`` files in the directory.                                                                             |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| delete        | ``newt target delete rb_btshell``                       | Deletes the ``rb_btshell`` target. It deletes the ``targets/rb_btshell`` directory.                                                                                                                                                                   |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| dep           | ``newt target dep myble``                               | Displays the dependency tree of all the package dependencies for the ``myble`` target. It lists each package followed by a list of packages it depends on.                                                                                            |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| revdep        | ``newt target revdep myble``                            | Displays the reverse dependency tree of all the package dependencies for the ``myble`` target. It lists each package followed by a list of packages that depend on it.                                                                                |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| set           | ``newt target set myble``                               | Use ``btshell`` as the application to build for the ``myble`` target.                                                                                                                                                                                 |
+|               | ``app=@apache-mynewt-core/apps/btshell``                |                                                                                                                                                                                                                                                       |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| set           | ``newt target set myble``                               | Set ``pkg.cflags`` variable with ``-DNDEBUG -Werror`` in the ``myble`` target's ``pkg.yml`` file..                                                                                                                                                    |
+|               | ``cflags="-DNDEBUG -Werror"``                           |                                                                                                                                                                                                                                                       |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| set           | ``newt target set myble``                               | Sets the ``syscfg.vals`` variable in the ``myble`` target's ``syscfg.yml`` file with the setting values: LOG_NEWTMGR: 0 and CONFIG_NEWTMGR: 1. CONFIG_NEWTMGR is set to 1 because a value is not specified.                                           |
+|               | ``syscfg=LOG_NEWTMGR=0:CONFIG_NEWTMGR``                 |                                                                                                                                                                                                                                                       |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| set           | ``newt target set myble cflags=``                       | Unsets the ``pkg.cflags`` variable in the ``myble`` target's ``pkg.yml`` file.                                                                                                                                                                        |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| show          | ``newt target show myble``                              | Shows all variable settings for the ``myble`` target, i.e. the values that app, bsp, build_profile, cflags, aflags, ldflags, syscfg variables are set to. Note that not all variables have to be set for a target.                                    |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| show          | ``newt target show``                                    | Shows all the variable settings for all the targets defined for the project.                                                                                                                                                                          |
++---------------+---------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_test.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_test.rst
new file mode 100644
index 00000000..a971cdaf
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_test.rst
@@ -0,0 +1,51 @@
+newt test
+----------
+
+Execute unit tests for one or more packages.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt test <package-name> [package-names...]  | all [flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+       -e, --exclude string   Comma separated list of packages to exclude
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Executes unit tests for one or more packages. You specify a list of packages, separated by space, to test multiple packages in the same command, or specify ``all`` to test all packages. When you use the ``all`` option, you may use the ``-e`` flag followed by a comma separated list of packages to exclude from the test.
+
+Examples
+^^^^^^^^
+
++---------------------------------------------+-------------------------------------------------------------------------------------+
+| Usage                                       | Explanation                                                                         |
++=============================================+=====================================================================================+
+| ``newt test @apache-mynewt-core/kernel/os`` | Tests the ``kernel/os`` package in the ``apache-mynewt-core`` repository.           |
++---------------------------------------------+-------------------------------------------------------------------------------------+
+| ``newt test kernel/os encoding/json``       | Tests the ``kernel/os`` and ``encoding/json`` packages in the current repository.   |
++---------------------------------------------+-------------------------------------------------------------------------------------+
+| ``newt test all``                           | Tests all packages.                                                                 |
++---------------------------------------------+-------------------------------------------------------------------------------------+
+| ``newt test all -e net/oic,encoding/json``  | Tests all packages except for the ``net/oic`` and the ``encoding/json`` packages.   |
++---------------------------------------------+-------------------------------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_upgrade.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_upgrade.rst
new file mode 100644
index 00000000..05fda7e5
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_upgrade.rst
@@ -0,0 +1,36 @@
+newt upgrade
+-------------
+
+Upgrade project dependencies.
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt upgrade [flags]
+
+Flags:
+^^^^^^
+
+.. code-block:: console
+
+        -f, --force   Force upgrade of the repositories to latest state in project.yml
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Upgrades your project and package dependencies. If you have changed the project.yml description for the project, you need to run this command to update all the package dependencies.
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_vals.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_vals.rst
new file mode 100644
index 00000000..88dff11f
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_vals.rst
@@ -0,0 +1,74 @@
+newt vals
+----------
+
+Display valid values for the specified element type(s).
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+      newt vals <element-type> [element-types...] [flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Description
+^^^^^^^^^^^
+
+Displays valid values for the specified element type(s). You must set valid values for one or more elements when you define a package or a target. Valid element types are:
+
+-  api
+-  app
+-  bsp
+-  build\_profile
+-  compiler
+-  lib
+-  sdk
+-  target
+
+Examples
+^^^^^^^^
+
++-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| Usage             | Explanation                                                                                                                                                                                                         |
++===================+=====================================================================================================================================================================================================================+
+| ``newt vals api`` | Shows the possible values for APIs a package may specify as required. For example, the ``pkg.yml`` for ``adc`` specifies that it requires the api named ``ADC_HW_IMPL``, one of the values listed by the command.   |
++-------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+Example output for ``newt vals bsp``:
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This lists all possible values that may be assigned to a target's bsp attribute.
+
+.. code-block:: console
+
+    $ newt vals bsp
+    bsp names:
+        @apache-mynewt-core/hw/bsp/arduino_primo_nrf52
+        @apache-mynewt-core/hw/bsp/bmd300eval
+        @apache-mynewt-core/hw/bsp/ci40
+        @apache-mynewt-core/hw/bsp/frdm-k64f
+        @apache-mynewt-core/hw/bsp/native
+        @apache-mynewt-core/hw/bsp/nrf51-arduino_101
+        @apache-mynewt-core/hw/bsp/nrf51-blenano
+        @apache-mynewt-core/hw/bsp/nrf51dk
+        @apache-mynewt-core/hw/bsp/nrf51dk-16kbram
+        @apache-mynewt-core/hw/bsp/nrf52dk
+        @apache-mynewt-core/hw/bsp/nucleo-f401re
+        @apache-mynewt-core/hw/bsp/olimex_stm32-e407_devboard
+        @apache-mynewt-core/hw/bsp/rb-nano2
+        @apache-mynewt-core/hw/bsp/stm32f4discovery
+    $ newt target set sample_target bsp=@apache-mynewt-core/hw/bsp/rb-nano2
+
+Obviously, this output will grow as more board support packages are added for new boards and MCUs.
diff --git a/vendor/mynewt.apache.org/newt/docs/command_list/newt_version.rst b/vendor/mynewt.apache.org/newt/docs/command_list/newt_version.rst
new file mode 100644
index 00000000..b6ef0e4c
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/command_list/newt_version.rst
@@ -0,0 +1,33 @@
+newt version
+-------------
+
+Display the version of the newt tool you have installed
+
+Usage:
+^^^^^^
+
+.. code-block:: console
+
+        newt version [flags]
+
+Global Flags:
+^^^^^^^^^^^^^
+
+.. code-block:: console
+
+        -h, --help              Help for newt commands
+        -j, --jobs int          Number of concurrent build jobs (default 8)
+        -l, --loglevel string   Log level (default "WARN")
+        -o, --outfile string    Filename to tee output to
+        -q, --quiet             Be quiet; only display error output
+        -s, --silent            Be silent; don't output anything
+        -v, --verbose           Enable verbose output when executing commands
+
+Examples
+^^^^^^^^
+
++------------------+------------------------------------------------------------+
+| Usage            | Explanation                                                |
++==================+============================================================+
+| ``newt version`` | Displays the version of the newt tool you have installed   |
++------------------+------------------------------------------------------------+
diff --git a/vendor/mynewt.apache.org/newt/docs/conf.py b/vendor/mynewt.apache.org/newt/docs/conf.py
new file mode 100644
index 00000000..42d6e8bf
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/conf.py
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+#
+# Mynewt documentation build configuration file, created by
+# sphinx-quickstart on Tue Jan 10 11:33:44 2017.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+import os
+import sys
+sys.path.insert(0, os.path.abspath('_ext'))
+
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autodoc', 'breathe', 'sphinx.ext.todo',
+    'sphinx.ext.extlinks'
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = []
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Mynewt Newt Tool'
+copyright = u'Copyright © 2017 The Apache Software Foundation, Licensed under the Apache License, Version 2.0 Apache and the Apache feather logo are trademarks of The Apache Software Foundation.'
+author = u'The Apache Software Foundation'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = u'1.0'
+# The full version, including alpha/beta/rc tags.
+release = u'1.0.0-b1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ['_build', 'README.rst', 'Thumbs.db', '.DS_Store']
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+highlight_language = 'none'
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+
+html_theme = 'alabaster'
+html_theme_path = []
+html_sidebars = {
+    '**': [
+        'about.html',
+        'navigation.html',
+        'relations.html',
+        'searchbox.html',
+        'donate.html',
+    ]
+}
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+html_theme_options = {
+}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+
+# -- Options for HTMLHelp output ------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Mynewtdoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+    # The paper size ('letterpaper' or 'a4paper').
+    #
+    # 'papersize': 'letterpaper',
+
+    # The font size ('10pt', '11pt' or '12pt').
+    #
+    # 'pointsize': '10pt',
+
+    # Additional stuff for the LaTeX preamble.
+    #
+    # 'preamble': '',
+
+    # Latex figure (float) alignment
+    #
+    # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+#  author, documentclass [howto, manual, or own class]).
+latex_documents = [
+    (master_doc, 'Mynewt.tex', u'Mynewt Newt Tool',
+     u'The Apache Software Foundation', 'manual'),
+]
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    (master_doc, 'mynewt', u'Mynewt Documentation',
+     [author], 1)
+]
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+    (master_doc, 'Mynewt', u'Mynewt Newt Tool',
+     author, 'Mynewt', 'One line description of project.',
+     'Miscellaneous'),
+]
+
+breathe_projects = {
+    "mynewt": "_build/xml"
+}
+breathe_default_project = "mynewt"
+# breathe_domain_by_extension = {
+#     "h" : "c",
+# }
diff --git a/vendor/mynewt.apache.org/newt/docs/index.rst b/vendor/mynewt.apache.org/newt/docs/index.rst
new file mode 100644
index 00000000..a979b123
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/index.rst
@@ -0,0 +1,223 @@
+Newt Tool Guide
+---------------
+
+.. toctree::
+   :hidden:
+   :titlesonly:
+
+   newt_operation
+   newt_ops
+   install/index
+
+Introduction
+~~~~~~~~~~~~
+
+Newt is a smart build and package management system for embedded
+contexts. It is a single tool that accomplishes both the following
+goals:
+
+-  source package management
+-  build, debug and install.
+
+Rationale
+~~~~~~~~~
+
+In order for the Mynewt operating system to work well for constrained
+environments across the many different types of micro-controller
+applications (from doorbells to medical devices to power grids), a
+system is needed that lets you select which packages to install and
+which packages to build.
+
+The build systems for embedded devices are often fairly complicated and
+not well served for this purpose. For example, autoconf is designed for
+detecting system compatibility issues but not well suited when it comes
+to tasks like:
+
+-  Building for multiple targets
+-  Deciding what to build in and what not to build in
+-  Managing dependencies between components
+
+Fortunately, solutions addressing these very issues can be found in
+source package management systems in higher level languages such as
+Javascript (Node), Go, PHP and Ruby. We decided to fuse their source
+management systems with a make system built for embedded systems and
+create Newt.
+
+Build System
+~~~~~~~~~~~~
+
+A good build system must allow the user to take a few common steps while
+developing embedded applications:
+
+-  Generate full flash images
+-  Download debug images to a target board using a debugger
+-  Conditionally compile libraries & code based upon build settings
+
+Newt can read a directory tree, build a dependency tree, and emit the
+right build artifacts. An example newt source tree is in
+mynewt-blinky/develop:
+
+.. code-block:: console
+
+  $ tree -L 3 .
+  ├── DISCLAIMER
+  ├── LICENSE
+  ├── NOTICE
+  ├── README.md
+  ├── apps
+  │ └── blinky
+  │ ├── pkg.yml
+  │ └── src
+  ├── project.yml
+  └── targets
+      ├── my_blinky_sim
+      │ ├── pkg.yml
+      │ └── target.yml
+      └── unittest
+          ├── pkg.yml
+          └── target.yml
+
+  6 directories, 10 files
+
+When Newt sees a directory tree that contains a "project.yml" file, it is smart enough to recognize it as the base directory of a project, and
+automatically builds a package tree. It also recognizes two important package directories in the package tree - "apps" and "targets".
+More on these directories in :doc:`newt_operation`.
+
+When Newt builds a target, it recursively resolves all package dependencies, and generates artifacts that are placed in the
+bin/targets/<target-name>/app/apps/<app-name> directory, where the bin directory is under the project base directory,
+``target-name`` is the name of the target, and ``app-name`` is the name of the application. For our example ``my_blinky_sim`` is the
+name of the target and ``blinky`` is the name of the application. The ``blinky.elf`` executable is stored in the
+bin/targets/my_blinky_sim/app/apps/blinky directory as shown in the source tree:
+
+.. code-block:: console
+
+  $ tree -L 6 bin/
+  bin/
+  └── targets
+      ├── my_blinky_sim
+      │   ├── app
+      │   │   ├── apps
+      │   │   │   └── blinky
+      │   │   │       ├── apps
+      │   │   │       ├── apps_blinky.a
+      │   │   │       ├── apps_blinky.a.cmd
+      │   │   │       ├── blinky.elf
+      │   │   │       ├── blinky.elf.cmd
+      │   │   │       ├── blinky.elf.dSYM
+      │   │   │       ├── blinky.elf.lst
+      │   │   │       └── manifest.json
+      │   │   ├── hw
+      │   │   │   ├── bsp
+      │   │   │   │   └── native
+      │   │   │   ├── drivers
+      │   │   │   │   └── uart
+      │   │   │   ├── hal
+      │   │   │   │   ├── hw_hal.a
+      │   │   │   │   ├── hw_hal.a.cmd
+      │   │   │   │   └── repos
+
+  <snip>
+
+More operations using Newt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once a target has been built, Newt allows additional operations on the target.
+
+* **load**: Download built target to board
+* **debug**: Open debugger session to target
+* **size**: Get size of target components
+* **create-image**: Add image header to the binary image
+* **run**: Build, create image, load, and finally open a debug session with the target
+* **target**: Create, delete, configure, and query a target
+
+For more details on how Newt works, go to :doc:`newt_operation`.
+
+Source Management and Repositories
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The other major element of the Newt tool is the ability to create reusable source distributions from a collection of code.
+**A project can be a reusable container of source code.** In other words, projects can be versioned and redistributed, not packages.
+A project bundles together packages that are typically needed to work together in a product e.g. RTOS core, filesystem APIs, and networking stack.
+
+A project that has been made redistributable is known as a **repository**.
+Repositories can be added to your local project by adding them into your project.yml file.  Here is an example of the blinky
+project's yml file which relies on apache-mynewt-core:
+
+.. code-block:: console
+
+  $ more project.yml
+  <snip>
+  project.repositories:
+        - apache-mynewt-core
+
+  repository.apache-mynewt-core:
+        type: github
+        vers: 1-latest
+        user: apache
+        repo: incubator-mynewt-core
+
+When you specify this repository in the blinky's project file, you can then use the Newt tool to install dependencies:
+
+.. code-block:: console
+
+  $ newt install
+  Downloading repository description for apache-mynewt-core... success!
+  Downloading repository incubator-mynewt-core (branch: develop) at https://github.com/apache/incubator-mynewt-core.git
+  Cloning into '/var/folders/7l/7b3w9m4n2mg3sqmgw2q1b9p80000gn/T/newt-repo814721459'...
+  remote: Counting objects: 17601, done.
+  remote: Compressing objects: 100% (300/300), done.
+  remote: Total 17601 (delta 142), reused 0 (delta 0), pack-reused 17284
+  Receiving objects: 100% (17601/17601), 6.09 MiB \| 3.17 MiB/s, done.
+  Resolving deltas: 100% (10347/10347), done.
+  Checking connectivity... done.
+  Repos successfully installed
+
+Newt will install this repository in the <project>/repos directory.  In the case of blinky, the directory structure ends up looking like:
+
+.. code-block:: console
+
+  $ tree -L 2
+  .
+  ├── DISCLAIMER
+  ├── LICENSE
+  ├── NOTICE
+  ├── README.md
+  ├── apps
+  │   └── blinky
+  ├── project.state
+  ├── project.yml
+  ├── repos
+  │   └── apache-mynewt-core
+  └── targets
+       ├── my_blinky_sim
+       └── unittest
+
+In order to reference the installed repositories in packages, the "@" notation should be specified in the repository
+specifier.  As an example, the apps/blinky application has the following dependencies in its pkg.yml file. This tells
+the build system to look in the base directory of repos/apache-mynewt-core for the ``kernel/os``, ``hw/hal``, and ``sys/console/full`` packages.
+
+.. code-block:: console
+
+  $ more apps/blinky/pkg.yml
+  pkg.deps:
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/sys/console/full"
+
+Newt has the ability to autocomplete within ``bash``. The following
+instructions allow MAC users to enable autocomplete within ``bash``.
+
+1. Install the autocomplete tools for bash via
+   ``brew install bash-completion``
+2. Tell your shell to use newt for autocompletion of newt via
+   ``complete -C "newt complete" newt``. You can add this to your
+   .bashrc or other init file to have it automatically set for all bash
+   shells.
+
+Notes:
+~~~~~~
+
+1. Autocomplete will give you flag hints, but only if you type a '-'.
+2. Autocomplete will not give you completion hints for the flag
+   arguments (those optional things after the flag like ``-l DEBUG``)
+3. Autocomplete uses newt to parse the project to find targets and libs.
diff --git a/vendor/mynewt.apache.org/newt/docs/install/index.rst b/vendor/mynewt.apache.org/newt/docs/install/index.rst
new file mode 100644
index 00000000..76163487
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/install/index.rst
@@ -0,0 +1,10 @@
+Install
+-----------------
+
+.. toctree::
+   :maxdepth: 2
+
+   newt_mac
+   newt_linux
+   newt_windows
+   prev_releases
diff --git a/vendor/mynewt.apache.org/newt/docs/install/newt_linux.rst b/vendor/mynewt.apache.org/newt/docs/install/newt_linux.rst
new file mode 100644
index 00000000..8ace7974
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/install/newt_linux.rst
@@ -0,0 +1,207 @@
+Installing Newt on Linux
+------------------------
+
+You can install the latest release (1.3.0) of the newt tool from a Debian binary package (amd64). You can also download
+and build the latest release version of newt from source.
+
+This page shows you how to:
+
+1. Set up your computer to download Debian binary packages from the runtimeco APT repository.
+
+   **Note:** The key for signing the repository has changed. If you set up your computer before release 1.1.0, you will
+   need to download and import the public key again.
+
+2. Install the latest release version of newt from a Debian binary package. You can use apt-get to install the package
+   or manually download and install the Debian binary package.
+
+3. Download, build, and install the latest release version of newt from source.
+
+If you are installing on an amd64 platform, we recommend that you install from the binary package.
+
+See :doc:`prev_releases` to install an earlier version of newt.
+
+**Note:** We have tested the newt tool binary and apt-get install from the runtimeco APT repository for Ubuntu version
+1704. Earlier Ubuntu versions (for example: Ubuntu 14) may have incompatibility with the repository. You can manually
+download and install the Debian binary package.
+
+**Note:** See :doc:`../../misc/go_env` if you want to:
+
+- Use the newt tool with the latest updates from the master branch. The master branch may be unstable and we recommend
+  that you use the latest stable release version.
+- Contribute to the newt tool.
+
+Setting Up Your Computer to use apt-get to Install the Package
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The newt Debian packages are stored in a private APT repository on **https://github/runtimeco/debian-mynewt**. To use
+apt-get, you must set up the following on your computer to retrieve packages from the repository:
+
+**Note**: You only need to perform this setup once on your computer. However, if you previously downloaded and imported
+the public key for the runtimeco APT repository, you will need to perform step 2 again as the key has changed.
+
+1. Download the public key for the runtimeco APT repository and import the key into the apt keychain.
+2. Add the repository for the binary and source packages to the apt source list.
+
+Download the public key for the runtimeco apt repo (**Note:** There is a ``-`` after ``apt-key add``):
+
+.. code-block:: console
+
+    $ wget -qO - https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/mynewt.gpg.key | sudo apt-key add -
+
+Add the repository for the binary and source packages to the ``mynewt.list`` apt source list file:
+
+.. code-block:: console
+
+    $ sudo tee /etc/apt/sources.list.d/mynewt.list <<EOF
+    deb https://raw.githubusercontent.com/runtimeco/debian-mynewt/master latest main
+    EOF
+
+Update the available packages:
+
+.. code-block:: console
+
+    $ sudo apt-get update
+
+**Note:** If you are not using Ubuntu version 1704, you may see the following errors. We have provided instructions on
+how to manually download and install the binary package.
+
+.. code-block:: console
+
+    W: Failed to fetch https://raw.githubusercontent.com/runtimeco/debian-mynewt/master/dists/latest/main/source/Sources  HttpError404
+
+Installing the Latest Release of Newt from a Binary Package
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can use either apt-get to install the package, or manually download and install the Debian binary package.
+
+Method 1: Using apt-get to Upgrade or to Install
+==============================================================================================
+
+Run the following commands to upgrade or install the latest version of newt:
+
+.. code-block:: console
+
+    $ sudo apt-get update
+    $ sudo apt-get install newt
+
+**Note:** If you encounter build errors (such as missing ``sys/mman.h``), please make sure you have a 32-bit glibc:
+
+.. code-block:: console
+
+    $ sudo apt-get install gcc-multilib
+
+Method 2: Downloading and Installing the Debian Package Manually
+==============================================================================================
+
+Download and install the package manually.
+
+.. code-block:: console
+
+    $ wget https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.4.1/newt_1.4.1-1_amd64.deb
+    $ sudo dpkg -i newt_1.4.1-1_amd64.deb
+
+See `Checking the Installed Version of Newt`_ to verify that you are using the installed version of newt.
+
+Installing the Latest Release of Newt from a Source Package
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you are running Linux on a different architecture, you can build and install the latest release version of newt from
+source.
+
+#. Download and unpack the newt source:
+
+   .. code-block:: console
+
+    $ wget -P /tmp https://github.com/apache/mynewt-newt/archive/mynewt_1_4_1_tag.tar.gz
+    $ tar -xzf /tmp/mynewt_1_4_1_tag.tar.gz
+
+#. Run the build.sh to build the newt tool.
+
+   .. code-block:: console
+
+    $ cd mynewt-newt-mynewt_1_4_1_tag
+    $ ./build.sh
+    $ rm /tmp/mynewt_1_4_1_tag.tar.gz
+
+#. You should see the ``newt/newt`` executable. Move the executable to a bin directory in your PATH:
+
+   -  If you previously built newt from the master branch, you can move the binary to your $GOPATH/bin directory.
+
+      .. code-block:: console
+
+       $ mv newt/newt $GOPATH/bin
+
+   -  If you are installing newt for the first time and do not have a Go workspace set up, you can move the binary to
+      /usr/bin or a directory in your PATH:
+
+      .. code-block:: console
+
+       $ mv newt/newt /usr/bin
+
+Checking the Installed Version of Newt
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+1. Check which newt you are using and that the version is the latest release version.
+
+   .. code-block:: console
+
+    $ which newt
+    /usr/bin/newt
+    $ newt version
+    Apache Newt version: 1.4.1
+
+2. Get information about newt:
+
+   .. code-block:: console
+
+    $ newt
+    Newt allows you to create your own embedded application based on the Mynewt
+    operating system. Newt provides both build and package management in a single
+    tool, which allows you to compose an embedded application, and set of
+    projects, and then build the necessary artifacts from those projects. For more
+    information on the Mynewt operating system, please visit
+    https://mynewt.apache.org/.
+
+    Please use the newt help command, and specify the name of the command you want
+    help for, for help on how to use a specific command
+
+    Usage:
+      newt [flags]
+      newt [command]
+
+    Examples:
+      newt
+      newt help [<command-name>]
+        For help on <command-name>.  If not specified, print this message.
+
+    Available Commands:
+      build        Build one or more targets
+      clean        Delete build artifacts for one or more targets
+      create-image Add image header to target binary
+      debug        Open debugger session to target
+      info         Show project info
+      install      Install project dependencies
+      load         Load built target to board
+      mfg          Manufacturing flash image commands
+      new          Create a new project
+      pkg          Create and manage packages in the current workspace
+      resign-image Re-sign an image.
+      run          build/create-image/download/debug <target>
+      size         Size of target components
+      sync         Synchronize project dependencies
+      target       Commands to create, delete, configure, and query targets
+      test         Executes unit tests for one or more packages
+      upgrade      Upgrade project dependencies
+      vals         Display valid values for the specified element type(s)
+      version      Display the Newt version number
+
+    Flags:
+      -h, --help              Help for newt commands
+      -j, --jobs int          Number of concurrent build jobs (default 8)
+      -l, --loglevel string   Log level (default "WARN")
+      -o, --outfile string    Filename to tee output to
+      -q, --quiet             Be quiet; only display error output
+      -s, --silent            Be silent; don't output anything
+      -v, --verbose           Enable verbose output when executing commands
+
+    Use "newt [command] --help" for more information about a command.
diff --git a/vendor/mynewt.apache.org/newt/docs/install/newt_mac.rst b/vendor/mynewt.apache.org/newt/docs/install/newt_mac.rst
new file mode 100644
index 00000000..a2f5c29f
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/install/newt_mac.rst
@@ -0,0 +1,189 @@
+Installing Newt on Mac OS
+-------------------------
+
+Newt is supported on Mac OS X 64 bit platforms and has been tested on
+Mac OS 10.10 and higher.
+
+This page shows you how to:
+
+-  Upgrade to or install the latest release version of newt.
+-  Install the latest newt from the master branch (unstable).
+
+See :doc:`prev_releases` to install an earlier version of newt.
+
+**Note:** If you would like to contribute to the newt tool, see :doc:`Setting Up Go Environment to Contribute
+to Newt and Newtmgr Tools <../../misc/go_env>`.
+
+Installing Homebrew
+~~~~~~~~~~~~~~~~~~~
+
+If you do not have Homebrew installed, run the following command. You
+will be prompted for your sudo password.
+
+.. code-block:: console
+
+    $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+
+You can also extract (or ``git clone``) Homebrew and install it to
+/usr/local.
+
+Adding the Mynewt Homebrew Tap
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If this is your first time installing newt, add the
+**runtimeco/homebrew-mynewt** tap:
+
+.. code-block:: console
+
+    $ brew tap runtimeco/homebrew-mynewt
+    $ brew update
+
+Upgrading to or Installing the Latest Release Version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Perform the following to upgrade or install the latest release version
+of newt.
+
+Upgrading to the Latest Release Version of Newt
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you previously installed newt using brew, run the following
+commands to upgrade to newt latest:
+
+.. code-block:: console
+
+    $ brew update
+    $ brew upgrade mynewt-newt
+    ==> Upgrading 1 outdated package, with result:
+    runtimeco/mynewt/mynewt-newt 1.4.1
+    ==> Upgrading runtimeco/mynewt/mynewt-newt
+    ==> Downloading https://github.com/runtimeco/binary-releases/raw/master/mynewt-newt-tools_1.4.1/mynewt-newt-1.4.1.sierra.bottle.tar.gz
+    ==> Downloading from https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.4.1/mynewt-newt-1.4.1.sierra.bottle.tar.gz
+    ######################################################################## 100.0%
+    ==> Pouring mynewt-newt-1.4.1.sierra.bottle.tar.gz
+    🍺  /usr/local/Cellar/mynewt-newt/1.4.1: 3 files, 7.9MB
+
+Installing the Latest Release Version of Newt
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Run the following command to install the latest release version of newt:
+
+.. code-block:: console
+
+    $ brew update
+    $ brew install mynewt-newt
+    ==> Installing mynewt-newt from runtimeco/mynewt
+    ==> Downloading https://github.com/runtimeco/binary-releases/raw/master/mynewt-newt-tools_1.4.1/mynewt-newt-1.4.1.sierra.bottle.tar.gz
+    Already downloaded: /Users/gavin/Library/Caches/Homebrew/mynewt-newt-1.4.1.sierra.bottle.tar.gz
+    ==> Pouring mynewt-newt-1.4.1.sierra.bottle.tar.gz
+    🍺  /usr/local/Cellar/mynewt-newt/1.4.1: 3 files, 7.9MB
+
+**Notes:** Homebrew bottles for newt are available for Mac OS Sierra. If you are running an earlier version of Mac OS,
+the installation will install the latest version of Go and compile newt locally.
+
+Checking the Installed Version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Check that you are using the installed version of newt:
+
+.. code-block:: console
+
+    $ which newt
+    /usr/local/bin/newt
+    $ newt version
+    Apache Newt version: 1.4.1
+
+**Note:** If you previously built newt from source and the output of
+``which newt`` shows
+"$GOPATH/bin/newt", you will need to move "$GOPATH/bin" after
+"/usr/local/bin" for your PATH in ~/.bash_profile, and source
+~/.bash_profile.
+
+Get information about newt:
+
+.. code-block:: console
+
+    $ newt help
+    Newt allows you to create your own embedded application based on the Mynewt
+    operating system. Newt provides both build and package management in a single
+    tool, which allows you to compose an embedded application, and set of
+    projects, and then build the necessary artifacts from those projects. For more
+    information on the Mynewt operating system, please visit
+    https://mynewt.apache.org/.
+
+    Please use the newt help command, and specify the name of the command you want
+    help for, for help on how to use a specific command
+
+    Usage:
+      newt [flags]
+      newt [command]
+
+    Examples:
+      newt
+      newt help [<command-name>]
+        For help on <command-name>.  If not specified, print this message.
+
+    Available Commands:
+      build        Build one or more targets
+      clean        Delete build artifacts for one or more targets
+      create-image Add image header to target binary
+      debug        Open debugger session to target
+      info         Show project info
+      install      Install project dependencies
+      load         Load built target to board
+      mfg          Manufacturing flash image commands
+      new          Create a new project
+      pkg          Create and manage packages in the current workspace
+      resign-image Re-sign an image.
+      run          build/create-image/download/debug <target>
+      size         Size of target components
+      sync         Synchronize project dependencies
+      target       Commands to create, delete, configure, and query targets
+      test         Executes unit tests for one or more packages
+      upgrade      Upgrade project dependencies
+      vals         Display valid values for the specified element type(s)
+      version      Display the Newt version number
+
+    Flags:
+      -h, --help              Help for newt commands
+      -j, --jobs int          Number of concurrent build jobs (default 8)
+      -l, --loglevel string   Log level (default "WARN")
+      -o, --outfile string    Filename to tee output to
+      -q, --quiet             Be quiet; only display error output
+      -s, --silent            Be silent; don't output anything
+      -v, --verbose           Enable verbose output when executing commands
+
+    Use "newt [command] --help" for more information about a command.
+
+Installing Newt from the Master Branch
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+We recommend that you use the latest release version of newt. If
+you would like to use the master branch with the latest updates, you can
+install newt from the HEAD of the master branch.
+
+**Notes:**
+
+-  The master branch may be unstable.
+-  This installation will install the latest version of Go on your
+   computer, if it is not installed, and compile newt locally.
+
+If you previously installed newt using brew, unlink the current
+version:
+
+.. code-block:: console
+
+    $ brew unlink mynewt-newt
+
+Install the latest unstable version of newt from the master branch:
+
+.. code-block:: console
+
+    $ brew install mynewt-newt --HEAD
+
+To switch back to the latest stable release version of newt,
+you can run:
+
+.. code-block:: console
+
+    $ brew switch mynewt-newt 1.4.1
diff --git a/vendor/mynewt.apache.org/newt/docs/install/newt_windows.rst b/vendor/mynewt.apache.org/newt/docs/install/newt_windows.rst
new file mode 100644
index 00000000..f494c212
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/install/newt_windows.rst
@@ -0,0 +1,215 @@
+Installing Newt on Windows
+--------------------------
+
+You can develop and build Mynewt OS applications for your target boards on the Windows platform. This guide shows you how to
+install the latest release version of newt from binary or from source. The tool is written in Go (golang).
+
+In Windows, we use MinGW as the development environment to build and run Mynewt OS applications for target boards. MinGW runs the
+bash shell and provides a Unix-like environment. This provides a uniform way to build Mynewt OS applications. The Mynewt
+documentation and tutorials use Unix commands and you can use the same Unix commands on MinGW to follow the tutorials. The
+documentation will note any commands or behaviors that are specific to Windows.
+
+This guide shows you how to perform the following:
+
+1. Install MSYS2/MinGW.
+2. Install Git.
+3. Install latest release (1.4.1) of newt from binary.
+4. Install latest release of newt from source.
+
+See :doc:`prev_releases` to install an earlier version of newt. You still need
+to set up your MinGW development environment.
+
+**Note:** If you would like to contribute to the newt tool, see :doc:`../../misc/go_env`.
+
+Installing MSYS2/MinGW
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+MSYS2/MinGW provides a bash shell and tools to build applications that run on Windows. It includes
+three subsystems:
+
+-  MSYS2 toolchain to build POSIX applications that run on Windows.
+-  MinGW32 toolchains to build 32 bit native Windows applications.
+-  MinGW64 toolchains to build 64 bit native Windows applications.
+
+The subsystems run the bash shell and provide a Unix-like environment. You can also run Windows applications from the shell. We
+will use the MinGW subsystem.
+
+**Note:** You can skip this installation step if you already have MinGW installed (from an earlier MSYS2/MinGW or Git Bash
+installation), but you must list the **bin** path for your installation in your Windows Path. For example: if you installed
+MSYS2/MinGW in the **C:\\msys64** directory, add **C:\\msys64\\usr\\bin**
+to your Windows Path. If you are using Windows 10 WSL, ensure that you use the
+**C:\\msys64\\usr\\bin\\base.exe** and not the Windows 10 WSL bash.
+
+To install and setup MSYS2 and MinGW:
+
+1. Download and run the `MSYS2 installer <http://www.msys2.org>`__. Select the 64 bit version if you are running on a 64 bit
+   platform. Follow the prompts and check the ``Run MSYS2 now`` checkbox on the ``Installation Complete`` dialog.
+2. In the MSYS2 terminal, run the ``pacman -Syuu`` command. If you get a message to run the update again, close the terminal and
+   run the ``pacman -Syuu`` command in a new terminal.
+
+   To start a new MSYS2 terminal, select the "MSYS2 MSYS" application from the Windows start menu.
+
+3. Add a new user variable named **MSYS2_PATH_TYPE** and set the value to **inherit** in your Windows environment. This enables
+   the MSYS2 and MinGW bash to inherit your Windows user **Path** values.
+
+   To add the variable, select properties for your computer > Advanced system settings > Environment Variables > New
+
+4. Add the MinGW **bin** path to your Windows Path. For example: if you install MSYS2/MinGW in the **C:\\msys64**
+   directory, add **C:\\msys64\\usr\\bin** to your Windows Path.
+
+   **Note:** If you are using Windows 10 WSL, ensure that you use the
+   **C:\\msys64\\usr\\bin\\base.exe** and not the Windows 10 WSL bash.
+
+5. Run the ``pacman -Su vim`` command to install the vim editor.
+
+   **Note:**\ You can also use a Windows editor. You can access your files from the
+   **C:<msys-install-folder>\\home\\<username>** folder, where **msys-install-folder** is the folder you installed
+   MSYS2 in. For example, if you installed MSYS2 in the **msys64** folder, your files are stored in
+   **C:\\msys64\\home\\<username>**
+
+6. Run the ``pacman -Su tar`` command to install the tar tool.
+
+You will need to start a MinGW terminal to run the commands specified in the Mynewt documentation and tutorials. To start a MinGW
+terminal, select the "MSYS2 Mingw" application from the start Menu (you can use either MinGW32 or MinGW64). In Windows, we use the
+MinGW subsystem to build Mynewt tools and applications.
+
+Installing Git for Windows
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Download and install `Git for Windows <https://git-for-windows.github.io>`__ if it is not already installed.
+
+Installing the Latest Release of the Newt Tool from Binary
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can install the latest release of newt from binary. It has been tested on Windows 10 64 bit platform.
+
+1. Start a MinGW terminal.
+
+2. Download the newt binary tar file. The link suggested below should direct you to the nearest mirror automatically. If it does not, go to http://www.apache.org/dyn/closer.lua/mynewt/apache-mynewt-1.4.1/ and manually choose the specific mirror site suggested for you.
+
+   .. code-block:: console
+
+    $ wget -P /tmp http://www.apache.org/dyn/closer.lua/mynewt/apache-mynewt-1.4.1/apache-mynewt-newt-bin-windows-1.4.1.tgz
+
+3. Extract the file:
+
+   -  If you previously built newt from the master branch, you can extract the file into your $GOPATH/bin directory. Note: This
+      overwrites the current newt.exe in the directory and assumes that you are using $GOPATH/bin for your Go applications.
+
+      .. code-block:: console
+
+        tar -xzf /tmp/apache-mynewt-newt-bin-windows-1.4.1.tgz -C $GOPATH/bin
+
+   -  If you are installing newt for the first time and do not have a Go workspace setup, you can extract into /usr/bin directory:
+
+      .. code-block:: console
+
+        tar -xzf /tmp/apache-mynewt-newt-bin-windows-1.4.1.tgz -C /usr/bin
+
+4. Verify the installed version of newt. See `Checking the Installed Version`_.
+
+Installing the Latest Release of Newt From Source
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you have an older version of Windows or a 32 bit platform, you can build and install the latest release version of newt from
+source.
+
+1. If you do not have Go installed, download and install the latest version of `Go <https://golang.org/dl/>`__. Newt requires Go
+   version 1.7.6 or higher.
+
+2. Start a MinGw terminal.
+
+3. Download and unpack the newt source:
+
+   .. code-block:: console
+
+    $ wget -P /tmp https://github.com/apache/mynewt-newt/archive/mynewt_1_4_1_tag.tar.gz
+    $ tar -xzf /tmp/mynewt_1_4_1_tag.tar.gz
+
+4. Run the build.sh to build the newt tool.
+
+   .. code-block:: console
+
+    $ cd mynewt-newt-mynewt_1_4_1_tag
+    $ ./build.sh
+    $ rm /tmp/mynewt_1_4_1_tag.tar.gz
+
+5. You should see the ``newt/newt.exe`` executable. Move the executable to a bin directory in your PATH:
+
+   -  If you previously built newt from the master branch, you can move the executable to the $GOPATH/bin directory.
+
+      .. code-block:: console
+
+       $ mv newt/newt.exe $GOPATH/bin
+
+   -  If you are installing newt for the first time and do not have a Go workspace set up, you can move the executable to /usr/bin or
+      a directory in your PATH:
+
+      .. code-block:: console
+
+       $ mv newt/newt.exe /usr/bin
+
+Checking the Installed Version
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+1. Check the version of newt:
+
+   .. code-block:: console
+
+    $ newt version
+    Apache Newt version: 1.4.1
+
+2. Get information about newt:
+
+   .. code-block:: console
+
+    Newt allows you to create your own embedded application based on the Mynewt
+    operating system. Newt provides both build and package management in a single
+    tool, which allows you to compose an embedded application, and set of
+    projects, and then build the necessary artifacts from those projects. For more
+    information on the Mynewt operating system, please visit
+    https://mynewt.apache.org/.
+
+    Please use the newt help command, and specify the name of the command you want
+    help for, for help on how to use a specific command
+
+    Usage:
+      newt [flags]
+      newt [command]
+
+    Examples:
+      newt
+      newt help [<command-name>]
+        For help on <command-name>.  If not specified, print this message.
+
+    Available Commands:
+      build        Build one or more targets
+      clean        Delete build artifacts for one or more targets
+      create-image Add image header to target binary
+      debug        Open debugger session to target
+      info         Show project info
+      install      Install project dependencies
+      load         Load built target to board
+      mfg          Manufacturing flash image commands
+      new          Create a new project
+      pkg          Create and manage packages in the current workspace
+      resign-image Re-sign an image.
+      run          build/create-image/download/debug <target>
+      size         Size of target components
+      sync         Synchronize project dependencies
+      target       Commands to create, delete, configure, and query targets
+      test         Executes unit tests for one or more packages
+      upgrade      Upgrade project dependencies
+      vals         Display valid values for the specified element type(s)
+      version      Display the Newt version number
+
+    Flags:
+      -h, --help              Help for newt commands
+      -j, --jobs int          Number of concurrent build jobs (default 8)
+      -l, --loglevel string   Log level (default "WARN")
+      -o, --outfile string    Filename to tee output to
+      -q, --quiet             Be quiet; only display error output
+      -s, --silent            Be silent; don't output anything
+      -v, --verbose           Enable verbose output when executing commands
+
+    Use "newt [command] --help" for more information about a command.
diff --git a/vendor/mynewt.apache.org/newt/docs/install/prev_releases.rst b/vendor/mynewt.apache.org/newt/docs/install/prev_releases.rst
new file mode 100644
index 00000000..6fb1614f
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/install/prev_releases.rst
@@ -0,0 +1,88 @@
+Installing Previous Releases of Newt
+------------------------------------
+
+This page shows you how to install previous releases of newt for Mac OS, Linux, and Windows.
+
+Mac OS
+~~~~~~
+
+You can install previous releases of newt using ``mynewt-newt@X.Y`` Homebrew formulas, where X.Y is a version number.
+
+For example, if you want to install newt 1.0, run the following commands:
+
+.. code-block:: console
+
+    $ brew update
+    $ brew install mynewt-newt@1.0
+
+**Note:** This is a keg-only installation. newt 1.0 is installed in /usr/local/Cellar/mynewt-newt@1.0/1.0.0/bin but not symlinked
+into /usr/local/bin.
+
+If you need this version of newt first in your PATH, run the following commands:
+
+.. code-block:: console
+
+
+    $ echo 'export PATH=/usr/local/Cellar/mynewt-newt@1.0/1.0.0/bin:$PATH' >> ~/.bash_profile
+    $ source ~/.bash_profile
+
+You can also manually symlink into /usr/local/bin as follows:
+
+1. Unlink newt if you have the latest version of newt installed:
+
+   .. code-block:: console
+
+    $ brew unlink mynewt-newt
+
+2. Link mynewt-newt@1.0 into /usr/local/bin:
+
+   .. code-block:: console
+
+    $ brew link -f mynewt-newt@1.0
+
+Linux
+~~~~~~
+
+1. Download the binary:
+
+   +-----------+----------------------------------------------------------------------------------------------------------------------------------------------------+
+   | Version   | Download                                                                                                                                           |
+   +===========+====================================================================================================================================================+
+   | 1.0.0     | `newt\_1.0.0-1\_amd64.deb <https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.0.0/newt_1.0.0-1_amd64.deb>`__   |
+   +-----------+----------------------------------------------------------------------------------------------------------------------------------------------------+
+   | 1.1.0     | `newt\_1.1.0-1\_amd64.deb <https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.1.0/newt_1.1.0-1_amd64.deb>`__   |
+   +-----------+----------------------------------------------------------------------------------------------------------------------------------------------------+
+   | 1.3.0     | `newt\_1.3.0-1\_amd64.deb <https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.3.0/newt_1.3.0-1_amd64.deb>`__   |
+   +-----------+----------------------------------------------------------------------------------------------------------------------------------------------------+
+
+2. Run the ``sudo apt-get remove newt`` command to remove the the current installation.
+
+3. Install the package. For example, run ``sudo dpkg -i newt_1.0.0-1_amd64.deb`` to install newt 1.0.0
+
+Windows
+~~~~~~~~
+
+1. Download the binary:
+
+   +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+   | Version   | Download                                                                                                                                                                |
+   +===========+=========================================================================================================================================================================+
+   | 1.1.0     | `newt\_1\_1\_0\_windows\_amd64.tar.gz <https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.1.0/newt_1_1_0_windows_amd64.tar.gz>`__   |
+   +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+   | 1.3.0     | `newt\_3\_1\_0\_windows\_amd64.tar.gz <https://raw.githubusercontent.com/runtimeco/binary-releases/master/mynewt-newt-tools_1.3.0/newt_1_3_0_windows_amd64.tar.gz>`__   |
+   +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+
+2. Extract the file:
+
+   -  If you previously built newt from the master branch, you can extract the file into your $GOPATH/bin directory. Note: This
+      overwrites the current newt.exe in the directory and assumes that you are using $GOPATH/bin for your Go applications.
+
+      .. code-block:: console
+
+          tar -xzf newt_1_1_0_windows_amd64.tar.gz -C $GOPATH/bin
+
+   -  If you are installing newt for the first time and do not have a Go workspace setup, you can extract into /usr/bin directory:
+
+      .. code-block:: console
+
+       tar -xzf newt_1_1_0_windows_amd64.tar.gz -C /usr/bin
diff --git a/vendor/mynewt.apache.org/newt/docs/newt_operation.rst b/vendor/mynewt.apache.org/newt/docs/newt_operation.rst
new file mode 100644
index 00000000..c57b20af
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/newt_operation.rst
@@ -0,0 +1,312 @@
+Theory of Operations
+--------------------
+
+Newt has a fairly smart package manager that can read a directory tree,
+build a dependency tree, and emit the right build artifacts.
+
+Building dependencies
+~~~~~~~~~~~~~~~~~~~~~
+
+Newt can read a directory tree, build a dependency tree, and emit the
+right build artifacts. An example newt source tree is in
+mynewt-blinky/develop:
+
+.. code-block:: console
+
+  $ tree -L 3
+  .
+  ├── LICENSE
+  ├── NOTICE
+  ├── README.md
+  ├── apps
+  │   └── blinky
+  │       ├── pkg.yml
+  │       └── src
+  ├── project.yml
+  └── targets
+      ├── my_blinky_sim
+      │   ├── pkg.yml
+      │   └── target.yml
+      └── unittest
+          ├── pkg.yml
+          └── target.yml
+
+  6 directories, 9 files
+
+When newt sees a directory tree that contains a "project.yml" file it knows that it is in the base directory of a project,
+and automatically builds a package tree. You can see that there are two essential package directories, "apps" and "targets."
+
+"apps" Package Directory
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+``apps`` is where applications are stored, and applications are where the main() function is contained.  The base project
+directory comes with one simple app called ``blinky`` in the ``apps`` directory. The core repository ``@apache-mynewt-core``
+comes with many additional sample apps in its ``apps`` directory. At the time of this writing, there are several example BLE
+apps, the boot app, slinky app for using newt manager protocol, and more in that directory.
+
+.. code-block:: console
+
+  $ ls repos/apache-mynewt-core/apps
+  blecent  blehr          blemesh_shell  blesplit  boot     btshell     lora_app_shell  ocf_sample    slinky      splitty    trng_test
+  blecsc   blemesh        bleprph        bletest   bsncent  ffs2native  loraping        pwm_test      slinky_oic  testbench
+  blehci   blemesh_light  bleprph_oic    bleuart   bsnprph  iptest      lorashell       sensors_test  spitest     timtest
+
+Along with the ``targets`` directory, ``apps`` represents the top-level of the build tree for the particular project, and
+define the dependencies for the rest of the system. Mynewt users and developers can add their own apps to the project's ``apps`` directory.
+
+The app definition is contained in a ``pkg.yml`` file. For example, blinky's ``pkg.yml`` file is:
+
+.. code-block:: console
+
+  $ more apps/blinky/pkg.yml
+  pkg.name: apps/blinky
+  pkg.type: app
+  pkg.description: Basic example application which blinks an LED.
+  pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+  pkg.homepage: "http://mynewt.apache.org/"
+  pkg.keywords:
+
+  pkg.deps:
+      - "@apache-mynewt-core/kernel/os"
+      - "@apache-mynewt-core/hw/hal"
+      - "@apache-mynewt-core/sys/console/stub"
+
+This file says that the name of the package is apps/blinky, and it depends on the ``kernel/os``, ``hw/hal`` and ``sys/console/stub`` packages.
+
+**NOTE:** @apache-mynewt-core is a repository descriptor, and this will be
+covered in the "repository" section.
+
+"targets" Package Directory
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``targets`` is where targets are stored, and each target is a collection of parameters that must be passed to newt in
+order to generate a reproducible build. Along with the ``apps`` directory, ``targets`` represents the top of the build
+tree. Any packages or parameters specified at the target level cascades down to all dependencies.
+
+Most targets consist of:
+
+* app: The application to build
+* bsp: The board support package to combine with that application
+* build_profile: Either debug or optimized.
+
+The ``my_blinky_sim`` target that is included by default has the following settings:
+
+.. code-block:: console
+
+  $ newt target show
+  targets/my_blinky_sim
+      app=apps/blinky
+      bsp=@apache-mynewt-core/hw/bsp/native
+      build_profile=debug
+  $ ls targets/my_blinky_sim/
+  pkg.yml		target.yml
+
+There are helper functions to aid the developer specify parameters for a target.
+
+* **vals**: Displays all valid values for the specified parameter type (e.g. bsp for a target)
+* **target show**: Displays the variable values for either a specific target or all targets defined for the project
+* **target set**: Sets values for target variables
+
+In general, the three basic parameters of a target (``app``, ``bsp``, and ``build_profile``) are stored in the
+target's ``target.yml`` file in the targets/<target-name> directory, where ``target-name`` is the name of the target. You
+will also see a ``pkg.yml`` file in the same directory. Since targets are packages, a ``pkg.yml`` is expected. It contains
+typical package descriptors, dependencies, and additional parameters such as the following:
+
+* Cflags: Any additional compiler flags you might want to specify to the build
+* Aflags: Any additional assembler flags you might want to specify to the build
+* Lflags: Any additional linker flags you might want to specify to the build
+
+You can also override the values of the system configuration settings that are defined by the packages that your target
+includes. You override the values in your target's ``syscfg.yml`` file (stored in the targets/<target-name> directory).
+You can use the ``newt target config show`` command to see the configuration settings and values for your target, and use
+the ``newt target set`` command to set the ``syscfg`` variable and override the configuration setting values.  You can
+also use an editor to create your target's ``syscfg.yml`` file and add the setting values to the file.
+See :doc:`../os/modules/sysinitconfig/sysinitconfig` for more information on system configuration settings.
+
+Resolving dependencies
+~~~~~~~~~~~~~~~~~~~~~~
+
+When newt builds a project, it will:
+
+* find the top-level project.yml file
+* recurse the packages in the package tree, and build a list of all source packages
+
+Newt then looks at the target that the user set, for example, blinky_sim:
+
+.. code-block:: console
+
+  $ more targets/my_blinky_sim/target.yml
+  ### Target: targets/my_blinky_sim
+  target.app: "apps/blinky"
+  target.bsp: "@apache-mynewt-core/hw/bsp/native"
+  target.build_profile: "debug"
+
+The target specifies two major things:
+
+* Application (target.app): The application to build
+* Board Support Package (target.bsp): The board support package to build along with that application.
+
+Newt builds the dependency tree specified by all the packages. While building this tree, it does a few other things:
+
+* Sets up the include paths for each package. Any package that depends on another package, automatically gets the include
+  directories from the package it includes.  Include directories in the
+  newt structure must always be prefixed by the package name. For example, kernel/os has the following include tree and its
+  include directory files contains the package name "os" before any header files.  This is so in order to avoid any header file conflicts.
+
+.. code-block:: console
+
+  $ tree repos/apache-mynewt-core/kernel/os/include/
+  repos/apache-mynewt-core/kernel/os/include/
+  └── os
+      ├── arch
+      │   ├── cortex_m0
+      │   │   └── os
+      │   │       └── os_arch.h
+      │   ├── cortex_m4
+      │   │   └── os
+      │   │       └── os_arch.h
+      │   ├── mips
+      │   │   └── os
+      │   │       └── os_arch.h
+      │   ├── sim
+      │   │   └── os
+      │   │       └── os_arch.h
+      │   └── sim-mips
+      │       └── os
+      │           └── os_arch.h
+      ├── endian.h
+      ├── os.h
+      ├── os_callout.h
+      ├── os_cfg.h
+      ├── os_cputime.h
+      ├── os_dev.h
+      ├── os_eventq.h
+      ├── os_fault.h
+      ├── os_heap.h
+      ├── os_malloc.h
+      ├── os_mbuf.h
+      ├── os_mempool.h
+      ├── os_mutex.h
+      ├── os_sanity.h
+      ├── os_sched.h
+      ├── os_sem.h
+      ├── os_task.h
+      ├── os_test.h
+      ├── os_time.h
+      └── queue.h
+
+  12 directories, 25 files
+
+* Validates API requirements.  Packages can export APIs they
+  implement, (i.e. pkg.api: hw-hal-impl), and other packages can require
+  those APIs (i.e. pkg.req_api: hw-hal-impl).
+
+* Reads and validates the configuration setting definitions and values from the package ``syscfg.yml`` files.
+  It generates a ``syscfg.h`` header file that packages include in the source files in order to access the settings.
+  It also generates a system initialization function to initialize the packages.
+  See :doc:`../os/modules/sysinitconfig/sysinitconfig` for more information.
+
+In order to properly resolve all dependencies in the build system, newt recursively processes the package dependencies
+until there are no new dependencies.  And it builds a big list of all the packages that need to be build.
+
+Newt then goes through this package list, and builds every package into
+an archive file.
+
+**NOTE:** The newt tool generates compiler dependencies for all of these packages, and only rebuilds the packages whose
+dependencies have changed. Changes in package & project dependencies are also taken into account. It is smart, after all!
+
+Producing artifacts
+~~~~~~~~~~~~~~~~~~~
+
+Once newt has built all the archive files, it then links the archive files together.  The linkerscript to use is specified
+by the board support package (BSP.)
+
+The newt tool creates a bin directory under the base project directory, and places a target's build artifacts into the
+bin/targets/<target-name>/app/apps/<app-name> directory, where ``target-name`` is the name of the target and ``app-name``
+is the name of the application. As an example, the ``blinky.elf`` executable for the ``blinky`` application defined by
+the ``my_blinky_sim`` target is stored in the bin/targets/my_blinky_sim/app/apps/blinky directory as shown in the following source tree:
+
+.. code-block:: console
+
+  $tree -L 9 bin/
+  bin/
+  └── targets
+      ├── my_blinky_sim
+      │   ├── app
+      │   │   ├── apps
+      │   │   │   └── blinky
+      │   │   │       ├── apps
+      │   │   │       │   └── blinky
+      │   │   │       │       └── src
+      │   │   │       │           ├── main.d
+      │   │   │       │           ├── main.o
+      │   │   │       │           └── main.o.cmd
+      │   │   │       ├── apps_blinky.a
+      │   │   │       ├── apps_blinky.a.cmd
+      │   │   │       ├── blinky.elf
+      │   │   │       ├── blinky.elf.cmd
+      │   │   │       ├── blinky.elf.dSYM
+      │   │   │       │   └── Contents
+      │   │   │       │       ├── Info.plist
+      │   │   │       │       └── Resources
+      │   │   │       │           └── DWARF
+      │   │   │       ├── blinky.elf.lst
+      │   │   │       └── manifest.json
+      │   │   ├── hw
+      │   │   │   ├── bsp
+      │   │   │   │   └── native
+      │   │   │   │       ├── hw_bsp_native.a
+      │   │   │   │       ├── hw_bsp_native.a.cmd
+      │   │   │   │       └── repos
+      │   │   │   │           └── apache-mynewt-core
+      │   │   │   │               └── hw
+
+  <snip>
+
+As you can see, a number of files are generated:
+
+- Archive File
+- \*.cmd: The command use to generate the object or archive file
+- \*.lst: The list file where symbols are located
+
+Note: The \*.o object files that get put into the archive file are stored in the bin/targets/my_blinky_sim/app/apps/blinky/apps/blinky/src directory.
+
+Download/Debug Support
+~~~~~~~~~~~~~~~~~~~~~~
+
+Once a target has been built, there are a number of helper functions
+that work on the target.  These are:
+
+* **load**     Download built target to board
+* **debug**        Open debugger session to target
+* **size**         Size of target components
+* **create-image**  Add image header to target binary
+* **run**  The equivalent of build, create-image, load, and debug on specified target
+* **target** Create, delete, configure, and query a target
+
+``load`` and ``debug`` handles driving GDB and the system debugger.  These
+commands call out to scripts that are defined by the BSP.
+
+.. code-block:: console
+
+  $ more repos/apache-mynewt-core/hw/bsp/nrf52dk/nrf52dk_debug.sh
+  <snip>
+  . $CORE_PATH/hw/scripts/jlink.sh
+
+  FILE_NAME=$BIN_BASENAME.elf
+
+  if [ $# -gt 2 ]; then
+      SPLIT_ELF_NAME=$3.elf
+      # TODO -- this magic number 0x42000 is the location of the second image
+      # slot. we should either get this from a flash map file or somehow learn
+      # this from the image itself
+      EXTRA_GDB_CMDS="add-symbol-file $SPLIT_ELF_NAME 0x8000 -readnow"
+  fi
+
+  JLINK_DEV="nRF52"
+
+  jlink_debug
+
+The idea is that every BSP will add support for the debugger environment
+for that board. That way common tools can be used across various
+development boards and kits.
diff --git a/vendor/mynewt.apache.org/newt/docs/newt_ops.rst b/vendor/mynewt.apache.org/newt/docs/newt_ops.rst
new file mode 100644
index 00000000..5d723204
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/docs/newt_ops.rst
@@ -0,0 +1,69 @@
+Command Structure
+-----------------
+
+.. toctree::
+   :hidden:
+   :titlesonly:
+   :glob:
+
+   command_list/*
+
+Just like verbs are actions in a sentence and adverbs modify verbs, so
+in the *newt* tool, commands are actions and flags modify actions. A
+command can have subcommands. Arguments to commands and subcommands,
+with appropriate flags, dictate the execution and result of a command.
+
+For instance, in the example below, the *newt* command has the
+subcommand ``target set`` in which the argument 'my_target1' is the
+target whose attribute, *app*, is set to ``@apache-mynewt-core/hw/bsp/nrf52dk``
+
+.. code-block:: console
+
+        newt target set my_target1 app=@apache-mynewt-core/hw/bsp/nrf52dk
+
+Global flags work uniformly across *newt* commands. Consider the flag
+``-v, --verbose,`` It works both for command and subcommands, to
+generate verbose output. Likewise, the help flag ``-h`` or ``--help,``
+to print helpful messsages.
+
+A command may additionally take flags specific to it. For example, the
+``-n`` flag instructs ``newt debug`` not to start GDB from command line.
+
+.. code-block:: console
+
+        newt debug <target-name> -n
+
+In addition to the documentation in :doc:`index`,
+command-line help is available for each command (and subcommand),
+through the ``-h`` or ``--help`` options.
+
+.. code-block:: console
+
+        newt target  --help
+        Commands to create, delete, configure, and query targets
+
+        Usage:
+          newt target [flags]
+          newt target [command]
+
+        Available Commands:
+          amend       Add, change, or delete values for multi-value target variables
+          config      View or populate a target's system configuration
+          copy        Copy target
+          create      Create a target
+          delete      Delete target
+          dep         View target's dependency graph
+          revdep      View target's reverse-dependency graph
+          set         Set target configuration variable
+          show        View target configuration variables
+
+        Global Flags:
+          -h, --help              Help for newt commands
+          -j, --jobs int          Number of concurrent build jobs (default 8)
+          -l, --loglevel string   Log level (default "WARN")
+          -o, --outfile string    Filename to tee output to
+          -q, --quiet             Be quiet; only display error output
+          -s, --silent            Be silent; don't output anything
+          -v, --verbose           Enable verbose output when executing commands
+
+        Use "newt target [command] --help" for more information about a command.
diff --git a/vendor/mynewt.apache.org/newt/newt/Godeps/Godeps.json b/vendor/mynewt.apache.org/newt/newt/Godeps/Godeps.json
deleted file mode 100644
index 32f885b3..00000000
--- a/vendor/mynewt.apache.org/newt/newt/Godeps/Godeps.json
+++ /dev/null
@@ -1,69 +0,0 @@
-{
-	"ImportPath": "mynewt.apache.org/newt/newt",
-	"GoVersion": "go1.6",
-	"GodepVersion": "v74",
-	"Deps": [
-		{
-			"ImportPath": "github.com/Sirupsen/logrus",
-			"Comment": "v0.11.0-10-ga437dfd",
-			"Rev": "a437dfd2463eaedbec3dfe443e477d3b0a810b3f"
-		},
-		{
-			"ImportPath": "github.com/inconshreveable/mousetrap",
-			"Rev": "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
-		},
-		{
-			"ImportPath": "github.com/kr/pretty",
-			"Comment": "go.weekly.2011-12-22-36-gcfb55aa",
-			"Rev": "cfb55aafdaf3ec08f0db22699ab822c50091b1c4"
-		},
-		{
-			"ImportPath": "github.com/kr/text",
-			"Rev": "7cafcd837844e784b526369c9bce262804aebc60"
-		},
-		{
-			"ImportPath": "github.com/mitchellh/mapstructure",
-			"Rev": "f3009df150dadf309fdee4a54ed65c124afad715"
-		},
-		{
-			"ImportPath": "github.com/spf13/cast",
-			"Rev": "24b6558033ffe202bf42f0f3b870dcc798dd2ba8"
-		},
-		{
-			"ImportPath": "github.com/spf13/cobra",
-			"Rev": "9495bc009a56819bdb0ddbc1a373e29c140bc674"
-		},
-		{
-			"ImportPath": "github.com/spf13/jwalterweatherman",
-			"Rev": "33c24e77fb80341fe7130ee7c594256ff08ccc46"
-		},
-		{
-			"ImportPath": "github.com/spf13/pflag",
-			"Rev": "5ccb023bc27df288a957c5e994cd44fd19619465"
-		},
-		{
-			"ImportPath": "golang.org/x/sys/unix",
-			"Rev": "b699b7032584f0953262cb2788a0ca19bb494703"
-		},
-		{
-			"ImportPath": "gopkg.in/fsnotify.v1",
-			"Comment": "v1.4.2",
-			"Rev": "629574ca2a5df945712d3079857300b5e4da0236"
-		},
-		{
-			"ImportPath": "mynewt.apache.org/newt/util",
-			"Comment": "pre_sterly_refactor-136-gb93ff7f",
-			"Rev": "b93ff7f6f8715f92d37ce68c66978f2b9bf20692"
-		},
-		{
-			"ImportPath": "mynewt.apache.org/newt/viper",
-			"Comment": "pre_sterly_refactor-136-gb93ff7f",
-			"Rev": "b93ff7f6f8715f92d37ce68c66978f2b9bf20692"
-		},
-		{
-			"ImportPath": "mynewt.apache.org/newt/yaml",
-			"Comment": "pre_sterly_refactor-136-gb93ff7f",
-			"Rev": "b93ff7f6f8715f92d37ce68c66978f2b9bf20692"
-		}
-	]
-}
diff --git a/vendor/mynewt.apache.org/newt/newt/Godeps/Readme b/vendor/mynewt.apache.org/newt/newt/Godeps/Readme
deleted file mode 100644
index 4cdaa53d..00000000
--- a/vendor/mynewt.apache.org/newt/newt/Godeps/Readme
+++ /dev/null
@@ -1,5 +0,0 @@
-This directory tree is generated automatically by godep.
-
-Please do not edit.
-
-See https://github.com/tools/godep for more information.
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/build.go b/vendor/mynewt.apache.org/newt/newt/builder/build.go
index 6e4ab348..9ffee8e7 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/build.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/build.go
@@ -245,10 +245,38 @@ func collectCompileEntriesDir(srcDir string, c *toolchain.Compiler,
 	return entries, nil
 }
 
+// Determines which build profile to use when building the specified package.
+// 1. If the package specifies a "pkg.build_profile" value, that is returned:
+//
+//      pkg.build_profile: debug
+//
+// 2. Else if the target specifies this package in its
+//    "target.package_profiles" map, that value is returned:
+//
+//      target.package_profiles:
+//          'apps/blinky': debug
+//          '@apache-mynewt-core/sys/log/full': debug
+//
+// 3. Else, "" is returned (falls back to the target's general build profile).
+func (b *Builder) buildProfileFor(bpkg *BuildPackage) string {
+	bp := bpkg.BuildProfile(b)
+	if bp != "" {
+		return bp
+	}
+
+	tgt := b.targetBuilder.GetTarget()
+	return tgt.PkgProfiles[bpkg.rpkg.Lpkg.FullName()]
+}
+
 func (b *Builder) newCompiler(bpkg *BuildPackage,
 	dstDir string) (*toolchain.Compiler, error) {
 
-	c, err := b.targetBuilder.NewCompiler(dstDir)
+	var buildProfile string
+	if bpkg != nil {
+		buildProfile = b.buildProfileFor(bpkg)
+	}
+
+	c, err := b.targetBuilder.NewCompiler(dstDir, buildProfile)
 	if err != nil {
 		return nil, err
 	}
@@ -312,6 +340,11 @@ func (b *Builder) collectCompileEntriesBpkg(bpkg *BuildPackage) (
 	return entries, nil
 }
 
+func (b *Builder) CollectCompileEntriesBpkg(bpkg *BuildPackage) (
+	[]toolchain.CompilerJob, error) {
+	return b.collectCompileEntriesBpkg(bpkg)
+}
+
 func (b *Builder) createArchive(c *toolchain.Compiler,
 	bpkg *BuildPackage) error {
 
@@ -361,12 +394,21 @@ func (b *Builder) link(elfName string, linkerScripts []string,
 	/* Always used the trimmed archive files. */
 	pkgNames := []string{}
 
-	for _, bpkg := range b.PkgMap {
+	for _, bpkg := range b.sortedBuildPackages() {
 		archiveNames, _ := filepath.Glob(b.PkgBinDir(bpkg) + "/*.a")
 		for i, archiveName := range archiveNames {
 			archiveNames[i] = filepath.ToSlash(archiveName)
 		}
 		pkgNames = append(pkgNames, archiveNames...)
+
+		// Collect lflags from all constituent packages.  Discard everything
+		// from the compiler info except lflags; that is all that is relevant
+		// to the link command.
+		ci, err := bpkg.CompilerInfo(b)
+		if err != nil {
+			return err
+		}
+		c.AddInfo(&toolchain.CompilerInfo{Lflags: ci.Lflags})
 	}
 
 	c.LinkerScripts = linkerScripts
@@ -448,11 +490,14 @@ func (b *Builder) PrepBuild() error {
 	baseCi.AddCompilerInfo(bspCi)
 
 	// All packages have access to the generated code header directory.
-	baseCi.Cflags = append(baseCi.Cflags,
-		"-I"+GeneratedIncludeDir(b.targetPkg.rpkg.Lpkg.Name()))
+	baseCi.Includes = append(baseCi.Includes,
+		GeneratedIncludeDir(b.targetPkg.rpkg.Lpkg.Name()))
+
+	// Let multiplatform libraries know that a Mynewt binary is being build.
+	baseCi.Cflags = append(baseCi.Cflags, "-DMYNEWT=1")
 
-	// Note: Compiler flags get added at the end, after the flags for library
-	// package being built are calculated.
+	// Note: The compiler package's flags get added at the end, after the flags
+	// for library package being built are calculated.
 	b.compilerInfo = baseCi
 
 	return nil
@@ -670,7 +715,7 @@ func (b *Builder) buildRomElf(common *symbol.SymbolMap) error {
 	// check dependencies on the ROM ELF.  This is really dependent on
 	// all of the .a files, but since we already depend on the loader
 	// .as to build the initial elf, we only need to check the app .a
-	c, err := b.targetBuilder.NewCompiler(b.AppElfPath())
+	c, err := b.targetBuilder.NewCompiler(b.AppElfPath(), "")
 	d := toolchain.NewDepTracker(c)
 	if err != nil {
 		return err
@@ -754,6 +799,7 @@ func (b *Builder) CreateImage(version string,
 		}
 	}
 
+	img.HeaderSize = uint(b.targetBuilder.target.HeaderSize)
 	err = img.Generate(loaderImg)
 	if err != nil {
 		return nil, err
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/buildpackage.go b/vendor/mynewt.apache.org/newt/newt/builder/buildpackage.go
index e82566fb..c89e6fde 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/buildpackage.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/buildpackage.go
@@ -61,7 +61,7 @@ func (bpkg *BuildPackage) collectDepsAux(b *Builder,
 		dbpkg := b.PkgMap[dep.Rpkg]
 		if dbpkg == nil {
 			return util.FmtNewtError("Package not found %s; required by %s",
-				dbpkg.rpkg.Lpkg.Name(), bpkg.rpkg.Lpkg.Name())
+				dep.Rpkg.Lpkg.Name(), bpkg.rpkg.Lpkg.Name())
 		}
 
 		if err := dbpkg.collectDepsAux(b, set); err != nil {
@@ -118,30 +118,38 @@ func expandFlags(flags []string) {
 	}
 }
 
+// Retrieves the build package's build profile override, as specified in its
+// `pkg.yml` file.  If the package does not override the build profile, "" is
+// returned.
+func (bpkg *BuildPackage) BuildProfile(b *Builder) string {
+	settings := b.cfg.AllSettingsForLpkg(bpkg.rpkg.Lpkg)
+	return bpkg.rpkg.Lpkg.PkgY.GetValString("pkg.build_profile", settings)
+}
+
 func (bpkg *BuildPackage) CompilerInfo(
 	b *Builder) (*toolchain.CompilerInfo, error) {
 
-	// If this package's compiler info has already been generated, returned the
+	// If this package's compiler info has already been generated, return the
 	// cached copy.
 	if bpkg.ci != nil {
 		return bpkg.ci, nil
 	}
 
 	ci := toolchain.NewCompilerInfo()
-	features := b.cfg.FeaturesForLpkg(bpkg.rpkg.Lpkg)
+	settings := b.cfg.AllSettingsForLpkg(bpkg.rpkg.Lpkg)
 
-	// Read each set of flags and expand repo designators ("@<repo-nme>") into
+	// Read each set of flags and expand repo designators ("@<repo-name>") into
 	// paths.
-	ci.Cflags = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features,
-		"pkg.cflags")
+	ci.Cflags = bpkg.rpkg.Lpkg.PkgY.GetValStringSlice("pkg.cflags", settings)
 	expandFlags(ci.Cflags)
 
-	ci.Lflags = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features,
-		"pkg.lflags")
+	ci.CXXflags = bpkg.rpkg.Lpkg.PkgY.GetValStringSlice("pkg.cxxflags", settings)
+	expandFlags(ci.CXXflags)
+
+	ci.Lflags = bpkg.rpkg.Lpkg.PkgY.GetValStringSlice("pkg.lflags", settings)
 	expandFlags(ci.Lflags)
 
-	ci.Aflags = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV, features,
-		"pkg.aflags")
+	ci.Aflags = bpkg.rpkg.Lpkg.PkgY.GetValStringSlice("pkg.aflags", settings)
 	expandFlags(ci.Aflags)
 
 	// Package-specific injected settings get specified as C flags on the
@@ -151,8 +159,7 @@ func (bpkg *BuildPackage) CompilerInfo(
 	}
 
 	ci.IgnoreFiles = []*regexp.Regexp{}
-	ignPats := newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV,
-		features, "pkg.ign_files")
+	ignPats := bpkg.rpkg.Lpkg.PkgY.GetValStringSlice("pkg.ign_files", settings)
 	for _, str := range ignPats {
 		re, err := regexp.Compile(str)
 		if err != nil {
@@ -163,8 +170,7 @@ func (bpkg *BuildPackage) CompilerInfo(
 	}
 
 	ci.IgnoreDirs = []*regexp.Regexp{}
-	ignPats = newtutil.GetStringSliceFeatures(bpkg.rpkg.Lpkg.PkgV,
-		features, "pkg.ign_dirs")
+	ignPats = bpkg.rpkg.Lpkg.PkgY.GetValStringSlice("pkg.ign_dirs", settings)
 	for _, str := range ignPats {
 		re, err := regexp.Compile(str)
 		if err != nil {
@@ -174,9 +180,8 @@ func (bpkg *BuildPackage) CompilerInfo(
 		ci.IgnoreDirs = append(ci.IgnoreDirs, re)
 	}
 
-	bpkg.SourceDirectories = newtutil.GetStringSliceFeatures(
-		bpkg.rpkg.Lpkg.PkgV,
-		features, "pkg.src_dirs")
+	bpkg.SourceDirectories = bpkg.rpkg.Lpkg.PkgY.GetValStringSlice(
+		"pkg.src_dirs", settings)
 
 	includePaths, err := bpkg.recursiveIncludePaths(b)
 	if err != nil {
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/buildutil.go b/vendor/mynewt.apache.org/newt/newt/builder/buildutil.go
index 61e5b653..113cbfde 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/buildutil.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/buildutil.go
@@ -26,6 +26,7 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 
+	"mynewt.apache.org/newt/newt/parse"
 	"mynewt.apache.org/newt/newt/resolve"
 )
 
@@ -36,10 +37,12 @@ func TestTargetName(testPkgName string) string {
 func (b *Builder) FeatureString() string {
 	var buffer bytes.Buffer
 
-	featureMap := b.cfg.Features()
-	featureSlice := make([]string, 0, len(featureMap))
-	for k, _ := range featureMap {
-		featureSlice = append(featureSlice, k)
+	settingMap := b.cfg.SettingValues()
+	featureSlice := make([]string, 0, len(settingMap))
+	for k, v := range settingMap {
+		if parse.ValueIsTrue(v) {
+			featureSlice = append(featureSlice, k)
+		}
 	}
 	sort.Strings(featureSlice)
 
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/cmake.go b/vendor/mynewt.apache.org/newt/newt/builder/cmake.go
new file mode 100644
index 00000000..b1f6da79
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/builder/cmake.go
@@ -0,0 +1,352 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package builder
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"os"
+	"path/filepath"
+	"strings"
+
+	log "github.com/Sirupsen/logrus"
+
+	"mynewt.apache.org/newt/newt/interfaces"
+	"mynewt.apache.org/newt/newt/project"
+	"mynewt.apache.org/newt/newt/target"
+	"mynewt.apache.org/newt/newt/toolchain"
+	"mynewt.apache.org/newt/util"
+)
+
+const CMAKELISTS_FILENAME string = "CMakeLists.txt"
+
+func CmakeListsPath() string {
+	return project.GetProject().BasePath + "/" + CMAKELISTS_FILENAME
+}
+
+func EscapeName(name string) string {
+	return strings.Replace(name, "/", "_", -1)
+}
+
+func trimProjectPath(path string) string {
+	proj := interfaces.GetProject()
+	path = strings.TrimPrefix(path, proj.Path()+"/")
+	return path
+}
+
+func trimProjectPathSlice(elements []string) {
+	for e := range elements {
+		elements[e] = trimProjectPath(elements[e])
+	}
+}
+
+func extractIncludes(flags *[]string, includes *[]string, other *[]string) {
+	for _, f := range *flags {
+		if strings.HasPrefix(f, "-I") {
+			*includes = append(*includes, strings.TrimPrefix(f, "-I"))
+		} else {
+			*other = append(*other, f)
+		}
+	}
+}
+
+func CmakeSourceObjectWrite(w io.Writer, cj toolchain.CompilerJob, includeDirs *[]string) {
+	c := cj.Compiler
+
+	compileFlags := []string{}
+	otherFlags := []string{}
+
+	switch cj.CompilerType {
+	case toolchain.COMPILER_TYPE_C:
+		compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
+		compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
+	case toolchain.COMPILER_TYPE_ASM:
+		compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
+		compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
+		compileFlags = append(compileFlags, c.GetCompilerInfo().Aflags...)
+		compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Aflags...)
+	case toolchain.COMPILER_TYPE_CPP:
+		compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
+		compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
+		compileFlags = append(compileFlags, c.GetCompilerInfo().CXXflags...)
+		compileFlags = append(compileFlags, c.GetLocalCompilerInfo().CXXflags...)
+	}
+
+	extractIncludes(&compileFlags, includeDirs, &otherFlags)
+	cj.Filename = trimProjectPath(cj.Filename)
+
+	// Sort and remove duplicate flags
+	otherFlags = util.SortFields(otherFlags...)
+
+	fmt.Fprintf(w, `set_property(SOURCE %s APPEND_STRING
+														PROPERTY
+														COMPILE_FLAGS
+														"%s")`,
+		cj.Filename,
+		strings.Replace(strings.Join(otherFlags, " "), "\"", "\\\\\\\"", -1))
+	fmt.Fprintln(w)
+}
+
+func (b *Builder) CMakeBuildPackageWrite(w io.Writer, bpkg *BuildPackage) (*BuildPackage, error) {
+	entries, err := b.collectCompileEntriesBpkg(bpkg)
+	if err != nil {
+		return nil, err
+	}
+
+	if len(entries) <= 0 {
+		return nil, nil
+	}
+
+	otherIncludes := []string{}
+	files := []string{}
+
+	for _, s := range entries {
+		filename := filepath.ToSlash(s.Filename)
+		if s.Compiler.ShouldIgnoreFile(filename) {
+			log.Infof("Ignoring %s because package dictates it.\n", filename)
+			continue
+		}
+
+		CmakeSourceObjectWrite(w, s, &otherIncludes)
+		s.Filename = trimProjectPath(s.Filename)
+		files = append(files, s.Filename)
+	}
+
+	if len(files) <= 0 {
+		return nil, nil
+	}
+
+	pkgName := bpkg.rpkg.Lpkg.Name()
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Generating CMakeLists.txt for %s\n", pkgName)
+	fmt.Fprintf(w, "# Generating CMakeLists.txt for %s\n\n", pkgName)
+	fmt.Fprintf(w, "add_library(%s %s)\n\n",
+		EscapeName(pkgName),
+		strings.Join(files, " "))
+
+	archivePath := filepath.Dir(b.ArchivePath(bpkg))
+	archivePath = trimProjectPath(archivePath)
+	CmakeCompilerInfoWrite(w, archivePath, bpkg, entries[0], otherIncludes)
+
+	return bpkg, nil
+}
+
+func (b *Builder) CMakeTargetWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
+	bpkgs := b.sortedBuildPackages()
+
+	c := targetCompiler
+
+	builtPackages := []*BuildPackage{}
+	for _, bpkg := range bpkgs {
+		builtPackage, err := b.CMakeBuildPackageWrite(w, bpkg)
+		if err != nil {
+			return err
+		}
+
+		if builtPackage != nil {
+			builtPackages = append(builtPackages, builtPackage)
+		}
+	}
+
+	elfName := "cmake_" + filepath.Base(b.AppElfPath())
+	fmt.Fprintf(w, "# Generating code for %s\n\n", elfName)
+
+	var targetObjectsBuffer bytes.Buffer
+
+	for _, bpkg := range builtPackages {
+		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
+			EscapeName(bpkg.rpkg.Lpkg.Name())))
+	}
+
+	elfOutputDir := trimProjectPath(filepath.Dir(b.AppElfPath()))
+	fmt.Fprintf(w, "file(WRITE %s \"\")\n", filepath.Join(elfOutputDir, "null.c"))
+	fmt.Fprintf(w, "add_executable(%s %s)\n\n", elfName, filepath.Join(elfOutputDir, "null.c"))
+
+	if c.GetLdResolveCircularDeps() {
+		fmt.Fprintf(w, "target_link_libraries(%s -Wl,--start-group %s -Wl,--end-group)\n",
+			elfName, targetObjectsBuffer.String())
+	} else {
+		fmt.Fprintf(w, "target_link_libraries(%s %s)\n",
+			elfName, targetObjectsBuffer.String())
+	}
+
+	var flags []string
+	flags = append(flags, c.GetCompilerInfo().Cflags...)
+	flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
+	flags = append(flags, c.GetCompilerInfo().CXXflags...)
+	flags = append(flags, c.GetLocalCompilerInfo().CXXflags...)
+
+	fmt.Fprintf(w, `set_property(TARGET %s APPEND_STRING
+														PROPERTY
+														COMPILE_FLAGS
+														"%s")`,
+		elfName,
+		strings.Replace(strings.Join(flags, " "), "\"", "\\\\\\\"", -1))
+	fmt.Fprintln(w)
+
+	lFlags := append(c.GetCompilerInfo().Lflags, c.GetLocalCompilerInfo().Lflags...)
+	for _, ld := range c.LinkerScripts {
+		lFlags = append(lFlags, "-T"+ld)
+	}
+
+	lFlags = append(lFlags, c.GetLocalCompilerInfo().Cflags...)
+	lFlags = append(lFlags, c.GetLocalCompilerInfo().CXXflags...)
+	fmt.Fprintf(w, `set_target_properties(%s
+							PROPERTIES
+							ARCHIVE_OUTPUT_DIRECTORY %s
+							LIBRARY_OUTPUT_DIRECTORY %s
+							RUNTIME_OUTPUT_DIRECTORY %s
+							LINK_FLAGS "%s"
+							LINKER_LANGUAGE C)`,
+		elfName,
+		elfOutputDir,
+		elfOutputDir,
+		elfOutputDir,
+		strings.Replace(strings.Join(lFlags, " "), "\"", "\\\\\\\"", -1))
+
+	fmt.Fprintln(w)
+
+	libs := strings.Join(getLibsFromLinkerFlags(lFlags), " ")
+	fmt.Fprintf(w, "# Workaround for gcc linker woes\n")
+	fmt.Fprintf(w, "set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} %s\")\n", libs)
+	fmt.Fprintln(w)
+
+	return nil
+}
+
+func getLibsFromLinkerFlags(lflags []string) []string {
+	libs := []string{}
+
+	for _, flag := range lflags {
+		if strings.HasPrefix(flag, "-l") {
+			libs = append(libs, flag)
+		}
+	}
+
+	return libs
+}
+
+func CmakeCompilerInfoWrite(w io.Writer, archiveFile string, bpkg *BuildPackage,
+	cj toolchain.CompilerJob, otherIncludes []string) {
+	c := cj.Compiler
+
+	var includes []string
+
+	includes = append(includes, c.GetCompilerInfo().Includes...)
+	includes = append(includes, c.GetLocalCompilerInfo().Includes...)
+	includes = append(includes, otherIncludes...)
+
+	// Sort and remove duplicate flags
+	includes = util.SortFields(includes...)
+	trimProjectPathSlice(includes)
+
+	fmt.Fprintf(w, `set_target_properties(%s
+							PROPERTIES
+							ARCHIVE_OUTPUT_DIRECTORY %s
+							LIBRARY_OUTPUT_DIRECTORY %s
+							RUNTIME_OUTPUT_DIRECTORY %s)`,
+		EscapeName(bpkg.rpkg.Lpkg.Name()),
+		archiveFile,
+		archiveFile,
+		archiveFile,
+	)
+	fmt.Fprintln(w)
+	fmt.Fprintf(w, "target_include_directories(%s PUBLIC %s)\n\n",
+		EscapeName(bpkg.rpkg.Lpkg.Name()),
+		strings.Join(includes, " "))
+}
+
+func (t *TargetBuilder) CMakeTargetBuilderWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
+	if err := t.PrepBuild(); err != nil {
+		return err
+	}
+
+	/* Build the Apps */
+	project.ResetDeps(t.AppList)
+
+	targetCompiler.LinkerScripts = t.bspPkg.LinkerScripts
+
+	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
+		return err
+	}
+
+	if err := t.AppBuilder.CMakeTargetWrite(w, targetCompiler); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func CmakeCompilerWrite(w io.Writer, c *toolchain.Compiler) {
+	/* Since CMake 3 it is required to set a full path to the compiler */
+	/* TODO: get rid of the prefix to /usr/bin */
+	fmt.Fprintln(w, "set(CMAKE_SYSTEM_NAME Generic)")
+	fmt.Fprintln(w, "set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)")
+	fmt.Fprintf(w, "set(CMAKE_C_COMPILER %s)\n", c.GetCcPath())
+	fmt.Fprintf(w, "set(CMAKE_CXX_COMPILER %s)\n", c.GetCppPath())
+	fmt.Fprintf(w, "set(CMAKE_ASM_COMPILER %s)\n", c.GetAsPath())
+	/* TODO: cmake returns error on link */
+	//fmt.Fprintf(w, "set(CMAKE_AR %s)\n", c.GetArPath())
+	fmt.Fprintln(w)
+}
+
+func CmakeHeaderWrite(w io.Writer, c *toolchain.Compiler, targetName string) {
+	fmt.Fprintln(w, "cmake_minimum_required(VERSION 3.7)\n")
+	CmakeCompilerWrite(w, c)
+	fmt.Fprintf(w, "project(%s VERSION 0.0.0 LANGUAGES C CXX ASM)\n\n", targetName)
+	fmt.Fprintln(w, "SET(CMAKE_C_FLAGS_BACKUP  \"${CMAKE_C_FLAGS}\")")
+	fmt.Fprintln(w, "SET(CMAKE_CXX_FLAGS_BACKUP  \"${CMAKE_CXX_FLAGS}\")")
+	fmt.Fprintln(w, "SET(CMAKE_ASM_FLAGS_BACKUP  \"${CMAKE_ASM_FLAGS}\")")
+	fmt.Fprintln(w)
+}
+
+func CMakeTargetGenerate(target *target.Target) error {
+	CmakeFileHandle, err := os.Create(CmakeListsPath())
+	if err != nil {
+		return util.ChildNewtError(err)
+	}
+
+	var b = bytes.Buffer{}
+	w := bufio.NewWriter(&b)
+	defer CmakeFileHandle.Close()
+
+	targetBuilder, err := NewTargetBuilder(target)
+	if err != nil {
+		return err
+	}
+
+	targetCompiler, err := targetBuilder.NewCompiler("", "")
+	if err != nil {
+		return err
+	}
+
+	CmakeHeaderWrite(w, targetCompiler, target.ShortName())
+
+	if err := targetBuilder.CMakeTargetBuilderWrite(w, targetCompiler); err != nil {
+		return err
+	}
+
+	w.Flush()
+
+	CmakeFileHandle.Write(b.Bytes())
+	return nil
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/depgraph.go b/vendor/mynewt.apache.org/newt/newt/builder/depgraph.go
index 5dba2579..ba12d3ce 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/depgraph.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/depgraph.go
@@ -22,6 +22,7 @@ package builder
 import (
 	"bytes"
 	"fmt"
+	"strings"
 
 	"mynewt.apache.org/newt/newt/resolve"
 )
@@ -111,8 +112,18 @@ func revdepGraph(rs *resolve.ResolveSet) (DepGraph, error) {
 
 func depString(dep *resolve.ResolveDep) string {
 	s := fmt.Sprintf("%s", dep.Rpkg.Lpkg.FullName())
+
+	var reasons []string
 	if dep.Api != "" {
-		s += fmt.Sprintf("(api:%s)", dep.Api)
+		reasons = append(reasons, fmt.Sprintf("api:%s", dep.Api))
+	}
+
+	if dep.Expr != "" {
+		reasons = append(reasons, fmt.Sprintf("syscfg:%s", dep.Expr))
+	}
+
+	if len(reasons) > 0 {
+		s += fmt.Sprintf("(%s)", strings.Join(reasons, " "))
 	}
 
 	return s
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/library.go b/vendor/mynewt.apache.org/newt/newt/builder/library.go
index af3c5b8d..b2551293 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/library.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/library.go
@@ -127,7 +127,7 @@ func (b *Builder) ParseObjectElf(elf_file string) (error, *symbol.SymbolMap) {
 func (b *Builder) ParseObjectLibraryFile(bp *BuildPackage,
 	file string, textDataOnly bool) (error, *symbol.SymbolMap) {
 
-	c, err := b.targetBuilder.NewCompiler(b.AppElfPath())
+	c, err := b.targetBuilder.NewCompiler(b.AppElfPath(), "")
 
 	ext := filepath.Ext(file)
 
@@ -206,7 +206,7 @@ func (b *Builder) ParseObjectLibraryFile(bp *BuildPackage,
 }
 
 func (b *Builder) CopySymbols(sm *symbol.SymbolMap) error {
-	c, err := b.targetBuilder.NewCompiler(b.AppElfPath())
+	c, err := b.targetBuilder.NewCompiler(b.AppElfPath(), "")
 
 	if err != nil {
 		return err
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/load.go b/vendor/mynewt.apache.org/newt/newt/builder/load.go
index fafd4b80..bb2738c9 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/load.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/load.go
@@ -26,6 +26,7 @@ import (
 	"strconv"
 	"strings"
 
+	"mynewt.apache.org/newt/newt/parse"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/util"
@@ -116,10 +117,10 @@ func (b *Builder) Load(imageSlot int, extraJtagCmd string) error {
 	if extraJtagCmd != "" {
 		envSettings["EXTRA_JTAG_CMD"] = extraJtagCmd
 	}
-	features := b.cfg.Features()
+	settings := b.cfg.SettingValues()
 
 	var flashTargetArea string
-	if _, ok := features["BOOT_LOADER"]; ok {
+	if parse.ValueIsTrue(settings["BOOT_LOADER"]) {
 		envSettings["BOOT_LOADER"] = "1"
 
 		flashTargetArea = "FLASH_AREA_BOOTLOADER"
@@ -143,9 +144,10 @@ func (b *Builder) Load(imageSlot int, extraJtagCmd string) error {
 	}
 	envSettings["FLASH_OFFSET"] = "0x" + strconv.FormatInt(int64(tgtArea.Offset), 16)
 
-	if err := Load(b.AppBinBasePath(), b.targetBuilder.bspPkg,
-		envSettings); err != nil {
-
+	// Convert the binary path from absolute to relative.  This is required for
+	// compatibility with unix-in-windows environemnts (e.g., cygwin).
+	binPath := util.TryRelPath(b.AppBinBasePath())
+	if err := Load(binPath, b.targetBuilder.bspPkg, envSettings); err != nil {
 		return err
 	}
 
@@ -212,5 +214,8 @@ func (b *Builder) Debug(extraJtagCmd string, reset bool, noGDB bool) error {
 		return util.NewNewtError("app package not specified")
 	}
 
-	return b.debugBin(b.AppBinBasePath(), extraJtagCmd, reset, noGDB)
+	// Convert the binary path from absolute to relative.  This is required for
+	// Windows compatibility.
+	binPath := util.TryRelPath(b.AppBinBasePath())
+	return b.debugBin(binPath, extraJtagCmd, reset, noGDB)
 }
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/size.go b/vendor/mynewt.apache.org/newt/newt/builder/size.go
index 7cdcc451..c0a19bf0 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/size.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/size.go
@@ -30,6 +30,7 @@ import (
 
 	"mynewt.apache.org/newt/newt/image"
 	"mynewt.apache.org/newt/util"
+	"mynewt.apache.org/newt/newt/interfaces"
 )
 
 /*
@@ -224,6 +225,7 @@ func ParseMapFileSizes(fileName string) (map[string]*PkgSize, error) {
 			}
 
 			array := strings.Fields(scanner.Text())
+
 			switch len(array) {
 			case 1:
 				/*
@@ -308,12 +310,18 @@ func ParseMapFileSizes(fileName string) (map[string]*PkgSize, error) {
 			if size == 0 {
 				continue
 			}
+
+			// srcFile might be : mylib.a(object_file.o) or object_file.o
 			tmpStrArr := strings.Split(srcFile, "(")
 			srcLib := tmpStrArr[0]
 			objName := ""
 			if srcLib != "*fill*" {
-				tmpStrArr = strings.Split(tmpStrArr[1], ")")
-				objName = tmpStrArr[0]
+				if len(tmpStrArr) > 1 {
+					tmpStrArr = strings.Split(tmpStrArr[1], ")")
+					objName = tmpStrArr[0]
+				} else {
+					objName = filepath.Base(tmpStrArr[0])
+				}
 			}
 			tmpStrArr = strings.Split(symName, ".")
 			if len(tmpStrArr) > 2 {
@@ -503,7 +511,7 @@ func (b *Builder) Size() error {
 	return nil
 }
 
-func (t *TargetBuilder) SizeReport(ram, flash bool) error {
+func (t *TargetBuilder) SizeReport(sectionName string) error {
 
 	err := t.PrepBuild()
 
@@ -512,21 +520,22 @@ func (t *TargetBuilder) SizeReport(ram, flash bool) error {
 	}
 
 	fmt.Printf("Size of Application Image: %s\n", t.AppBuilder.buildName)
-	err = t.AppBuilder.SizeReport(ram, flash)
+	err = t.AppBuilder.SizeReport(sectionName)
 
 	if err == nil {
 		if t.LoaderBuilder != nil {
 			fmt.Printf("Size of Loader Image: %s\n", t.LoaderBuilder.buildName)
-			err = t.LoaderBuilder.SizeReport(ram, flash)
+			err = t.LoaderBuilder.SizeReport(sectionName)
 		}
 	}
 
 	return err
 }
 
-func (b *Builder) SizeReport(ram, flash bool) error {
-	srcBase := b.targetBuilder.GetTarget().App().Repo().Path() + "/"
-	err := SizeReport(b.AppElfPath(), srcBase, ram, flash)
+func (b *Builder) SizeReport(sectionName string) error {
+	srcBase := interfaces.GetProject().Path() + "/"
+
+	err := SizeReport(b.AppElfPath(), srcBase, sectionName)
 	if err != nil {
 		return util.NewNewtError(err.Error())
 	}
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/size_report.go b/vendor/mynewt.apache.org/newt/newt/builder/size_report.go
index 5c9fa02e..bfb4ad7c 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/size_report.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/size_report.go
@@ -35,7 +35,7 @@ func runNmCommand(elfFilePath string) ([]byte, error) {
 		err    error
 	)
 	cmdName := "arm-none-eabi-nm"
-	cmdArgs := []string{elfFilePath, "-S", "-l", "--size-sort", "--radix=d"}
+	cmdArgs := []string{elfFilePath, "-S", "-l", "--size-sort"}
 
 	if cmdOut, err = exec.Command(cmdName, cmdArgs...).Output(); err != nil {
 		fmt.Fprintln(os.Stderr, "There was an error running nm command: ", err)
@@ -61,6 +61,22 @@ func runObjdumpCommand(elfFilePath string, params string) ([]byte, error) {
 	return cmdOut, err
 }
 
+func runAddr2lineCommand(elfFilePath string, address string) ([]byte, error) {
+	var (
+		cmdOut []byte
+		err    error
+	)
+	cmdName := "arm-none-eabi-addr2line"
+	cmdArgs := []string{"-e", elfFilePath, address}
+
+	cmdOut, err = exec.Command(cmdName, cmdArgs...).Output()
+
+	/* This can fail and it's not a critical error */
+
+	return cmdOut, err
+}
+
+
 func loadSymbolsAndPaths(elfFilePath, pathToStrip string) (map[string]string,
 	error) {
 	symbolsPath := make(map[string]string)
@@ -80,7 +96,13 @@ func loadSymbolsAndPaths(elfFilePath, pathToStrip string) (map[string]string,
 		var path string
 
 		if len(fields) < 5 {
-			path = "(other)"
+			addr2lineOut, err := runAddr2lineCommand(elfFilePath, fields[0])
+			if err != nil {
+				path = "(other)"
+			} else {
+				aline := strings.Split(string(addr2lineOut), "\n")[0]
+				path = strings.Split(aline, ":")[0]
+			}
 		} else {
 			path = strings.Split(fields[4], ":")[0]
 		}
@@ -157,18 +179,18 @@ func loadSymbolsAndSections(elfFilePath string) (map[string]*Symbol, error) {
 	return symbols, nil
 }
 
-func generateMemoryRegions(elfFilePath string) (*MemoryRegion, *MemoryRegion,
+func getMemoryRegion(elfFilePath string, sectionName string) (*MemoryRegion,
 	error) {
 
 	mapFile := elfFilePath + ".map"
-	flashRegion, ramRegion, err := parseMapFileRegions(mapFile)
+	sectionRegion, err := parseMapFileRegions(mapFile, sectionName)
 	if err != nil {
-		return nil, nil, err
+		return nil, err
 	}
 
 	objdumpOut, err := runObjdumpCommand(elfFilePath, "-hw")
 	if err != nil {
-		return nil, nil, err
+		return nil, err
 	}
 
 	lines := strings.Split(string(objdumpOut), "\n")
@@ -186,38 +208,30 @@ func generateMemoryRegions(elfFilePath string) (*MemoryRegion, *MemoryRegion,
 			continue
 		}
 
-		if flashRegion.PartOf(address) {
-			flashRegion.TotalSize += size
-			flashRegion.SectionNames[fields[1]] = struct{}{}
-			flashRegion.NamesSizes[fields[1]] = size
-			continue
-		}
-
-		if ramRegion.PartOf(address) {
-			ramRegion.TotalSize += size
-			ramRegion.SectionNames[fields[1]] = struct{}{}
-			ramRegion.NamesSizes[fields[1]] = size
+		if sectionRegion.PartOf(address) {
+			sectionRegion.TotalSize += size
+			sectionRegion.SectionNames[fields[1]] = struct{}{}
+			sectionRegion.NamesSizes[fields[1]] = size
 			continue
 		}
 	}
 
-	return flashRegion, ramRegion, nil
+	return sectionRegion, nil
 }
 
 /*
  * Go through GCC generated mapfile, and collect info about symbol sizes
  */
-func parseMapFileRegions(fileName string) (*MemoryRegion, *MemoryRegion,
+func parseMapFileRegions(fileName string, sectionName string) (*MemoryRegion,
 	error) {
 	var state int = 0
 
 	file, err := os.Open(fileName)
 	if err != nil {
-		return nil, nil, err
+		return nil, err
 	}
 
-	flashRegion := MakeMemoryRegion()
-	ramRegion := MakeMemoryRegion()
+	sectionRegion := MakeMemoryRegion()
 
 	scanner := bufio.NewScanner(file)
 	for scanner.Scan() {
@@ -244,52 +258,39 @@ func parseMapFileRegions(fileName string) (*MemoryRegion, *MemoryRegion,
 			if err != nil {
 				continue
 			}
-			if strings.EqualFold(array[0], "flash") {
-				flashRegion.Name = array[0]
-				flashRegion.Offset = offset
-				flashRegion.EndOff = offset + size
-			} else if strings.EqualFold(array[0], "ram") {
-				ramRegion.Name = array[0]
-				ramRegion.Offset = offset
-				ramRegion.EndOff = offset + size
+
+			if strings.EqualFold(array[0], sectionName) {
+				sectionRegion.Name = array[0]
+				sectionRegion.Offset = offset
+				sectionRegion.EndOff = offset + size
 			}
 		case 3:
 			fallthrough
 		default:
-			return flashRegion, ramRegion, nil
+			return sectionRegion, nil
 		}
 
 	}
-	return flashRegion, flashRegion, nil
+	return sectionRegion, nil
 }
 
-func logMemoryRegionStats(flashRegion, ramRegion *MemoryRegion) {
+func logMemoryRegionStats(memRegion *MemoryRegion, sectionName string) {
+	memName := fmt.Sprintf("Mem %s:", sectionName)
 	util.StatusMessage(util.VERBOSITY_VERBOSE, "%-10s 0x%08x-0x%08x\n",
-		"Mem FLASH:", flashRegion.Offset, flashRegion.EndOff)
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "%-10s 0x%08x-0x%08x\n",
-		"Mem RAM:", ramRegion.Offset, ramRegion.EndOff)
+		memName, memRegion.Offset, memRegion.EndOff)
 	util.StatusMessage(util.VERBOSITY_VERBOSE, "\n")
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "Mem: FLASH\n")
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "Mem: %s\n", sectionName)
 	util.StatusMessage(util.VERBOSITY_VERBOSE, "%-20s %10s\n", "Name", "Size")
-	for sectionName, size := range flashRegion.NamesSizes {
+	for sectionName, size := range memRegion.NamesSizes {
 		util.StatusMessage(util.VERBOSITY_VERBOSE, "%-20s %10d\n",
 			sectionName, size)
 	}
 	util.StatusMessage(util.VERBOSITY_VERBOSE, "%-20s %10d\n", "Total",
-		flashRegion.TotalSize)
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "\n")
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "Mem: RAM\n")
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "%-20s %10s\n", "Name", "Size")
-	for sectionName, size := range ramRegion.NamesSizes {
-		util.StatusMessage(util.VERBOSITY_VERBOSE, "%-20s %10d\n",
-			sectionName, size)
-	}
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "%-20s %10d\n", "Total",
-		ramRegion.TotalSize)
+		memRegion.TotalSize)
 	util.StatusMessage(util.VERBOSITY_VERBOSE, "\n")
 }
 
-func SizeReport(elfFilePath, srcBase string, ram bool, flash bool) error {
+func SizeReport(elfFilePath, srcBase string, sectionName string) error {
 	symbolsPath, err := loadSymbolsAndPaths(elfFilePath, srcBase)
 	if err != nil {
 		return err
@@ -298,35 +299,22 @@ func SizeReport(elfFilePath, srcBase string, ram bool, flash bool) error {
 	if err != nil {
 		return err
 	}
-	flashRegion, ramRegion, err := generateMemoryRegions(elfFilePath)
+	sectionRegion, err := getMemoryRegion(elfFilePath, sectionName)
 	if err != nil {
 		return err
 	}
 
-	logMemoryRegionStats(flashRegion, ramRegion)
+	logMemoryRegionStats(sectionRegion, sectionName)
 
 	startPath := "."
 
-	if flash {
-		flashNodes := newFolder(startPath)
-		for _, symbol := range loadedSectionSizes {
-			if _, ok := flashRegion.SectionNames[symbol.Section]; ok {
-				flashNodes.addSymbol(symbol, symbolsPath[symbol.Name])
-			}
-		}
-		fmt.Println("FLASH report:")
-		fmt.Printf("%v", flashNodes.ToString(flashRegion.TotalSize))
-	}
-
-	if ram {
-		ramNodes := newFolder(startPath)
-		for _, symbol := range loadedSectionSizes {
-			if _, ok := ramRegion.SectionNames[symbol.Section]; ok {
-				ramNodes.addSymbol(symbol, symbolsPath[symbol.Name])
-			}
+	sectionNodes := newFolder(startPath)
+	for _, symbol := range loadedSectionSizes {
+		if _, ok := sectionRegion.SectionNames[symbol.Section]; ok {
+			sectionNodes.addSymbol(symbol, symbolsPath[symbol.Name])
 		}
-		fmt.Println("RAM report:")
-		fmt.Printf("%v", ramNodes.ToString(ramRegion.TotalSize))
 	}
+	fmt.Printf("%s report:\n", sectionName)
+	fmt.Printf("%v", sectionNodes.ToString(sectionRegion.TotalSize))
 	return nil
 }
diff --git a/vendor/mynewt.apache.org/newt/newt/builder/targetbuild.go b/vendor/mynewt.apache.org/newt/newt/builder/targetbuild.go
index 8acb276f..1c2f8ba7 100644
--- a/vendor/mynewt.apache.org/newt/newt/builder/targetbuild.go
+++ b/vendor/mynewt.apache.org/newt/newt/builder/targetbuild.go
@@ -20,7 +20,12 @@
 package builder
 
 import (
+	"bufio"
+	"crypto/ecdsa"
+	"crypto/rsa"
+	"crypto/x509"
 	"encoding/json"
+	"encoding/pem"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -60,6 +65,7 @@ type TargetBuilder struct {
 	LoaderBuilder *Builder
 	LoaderList    interfaces.PackageList
 
+	keyFile          string
 	injectedSettings map[string]string
 
 	res *resolve.Resolution
@@ -89,6 +95,7 @@ func NewTargetTester(target *target.Target,
 		compilerPkg:      compilerPkg,
 		appPkg:           target.App(),
 		loaderPkg:        target.Loader(),
+		keyFile:          target.KeyFile,
 		testPkg:          testPkg,
 		injectedSettings: map[string]string{},
 	}
@@ -100,13 +107,15 @@ func NewTargetBuilder(target *target.Target) (*TargetBuilder, error) {
 	return NewTargetTester(target, nil)
 }
 
-func (t *TargetBuilder) NewCompiler(dstDir string) (
+func (t *TargetBuilder) NewCompiler(dstDir string, buildProfile string) (
 	*toolchain.Compiler, error) {
 
+	if buildProfile == "" {
+		buildProfile = t.target.BuildProfile
+	}
+
 	c, err := toolchain.NewCompiler(
-		t.compilerPkg.BasePath(),
-		dstDir,
-		t.target.BuildProfile)
+		t.compilerPkg.BasePath(), dstDir, buildProfile)
 
 	return c, err
 }
@@ -119,8 +128,8 @@ func (t *TargetBuilder) ensureResolved() error {
 	var loaderSeeds []*pkg.LocalPackage
 	if t.loaderPkg != nil {
 		loaderSeeds = []*pkg.LocalPackage{
-			t.loaderPkg,
-			t.bspPkg.LocalPackage,
+			t.target.LoaderYml(),
+			t.target.BspYml(),
 			t.compilerPkg,
 			t.target.Package(),
 		}
@@ -142,13 +151,13 @@ func (t *TargetBuilder) ensureResolved() error {
 	}
 
 	appSeeds := []*pkg.LocalPackage{
-		t.bspPkg.LocalPackage,
+		t.target.BspYml(),
 		t.compilerPkg,
 		t.target.Package(),
 	}
 
 	if t.appPkg != nil {
-		appSeeds = append(appSeeds, t.appPkg)
+		appSeeds = append(appSeeds, t.target.AppYml())
 	}
 
 	if t.testPkg != nil {
@@ -192,9 +201,11 @@ func (t *TargetBuilder) validateAndWriteCfg() error {
 
 	warningText := strings.TrimSpace(t.res.WarningText())
 	if warningText != "" {
-		for _, line := range strings.Split(warningText, "\n") {
-			log.Debugf(line)
-		}
+		log.Debug(warningText)
+	}
+
+	for _, line := range t.res.DeprecatedWarning() {
+		log.Warn(line)
 	}
 
 	if err := syscfg.EnsureWritten(t.res.Cfg,
@@ -312,7 +323,7 @@ func (t *TargetBuilder) buildLoader() error {
 	/* rebuild the loader */
 	project.ResetDeps(t.LoaderList)
 
-	if err := t.bspPkg.Reload(t.LoaderBuilder.cfg.Features()); err != nil {
+	if err := t.bspPkg.Reload(t.LoaderBuilder.cfg.SettingValues()); err != nil {
 		return err
 	}
 
@@ -349,6 +360,75 @@ func (t *TargetBuilder) buildLoader() error {
 
 }
 
+/// Generates a .c source file with public key information required by the
+/// bootloader.
+///
+/// The input filename should be supplied by the user in the target.yml file,
+/// using the `target.key_file` option. This file can be either a private key
+/// in PEM format, an extracted public key in PEM format or a DER file.
+///
+/// To extract a PEM public key from the private key:
+///   `openssl ec -in ec_pk.pem -pubout -out pubkey.pub`
+///   `openssl rsa -in rsa_pk.pem -RSAPublicKey_out -out pubkey.pub`
+func (t *TargetBuilder) autogenKeys() error {
+	keyBytes, err := ioutil.ReadFile(t.keyFile)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Error reading key file: %s", err))
+	}
+
+	// Initially try parsing a private key in PEM format, if it fails try
+	// parsing as PEM public key, otherwise accepted as raw key data (DER)
+
+	privKey, err := image.ParsePrivateKey(keyBytes)
+	if err == nil {
+		switch pk := privKey.(type) {
+		case *rsa.PrivateKey:
+			keyBytes = x509.MarshalPKCS1PublicKey(&pk.PublicKey)
+		case *ecdsa.PrivateKey:
+			keyBytes, err = x509.MarshalPKIXPublicKey(&pk.PublicKey)
+			if err != nil {
+				return util.NewNewtError("Failed parsing EC public key")
+			}
+		default:
+			return util.NewNewtError("Unknown private key format")
+		}
+	} else {
+		b, _ := pem.Decode(keyBytes)
+		if b != nil && (b.Type == "PUBLIC KEY" || b.Type == "RSA PUBLIC KEY") {
+			keyBytes = b.Bytes
+		}
+	}
+
+	srcDir := GeneratedSrcDir(t.target.Name())
+
+	f, _ := os.Create(srcDir + "/pubkey-autogen.c")
+	w := bufio.NewWriter(f)
+
+	fmt.Fprintln(w, "/* Autogenerated, do not edit. */")
+	fmt.Fprintln(w, "#include <bootutil/sign_key.h>")
+	fmt.Fprintf(w, "const unsigned char key[] = {")
+	for count, b := range keyBytes {
+		if count%8 == 0 {
+			fmt.Fprintf(w, "\n    ")
+		} else {
+			fmt.Fprintf(w, " ")
+		}
+		fmt.Fprintf(w, "0x%02x,", b)
+	}
+	fmt.Fprintf(w, "\n};\n")
+	fmt.Fprintf(w, "const unsigned int key_len = %v;\n", len(keyBytes))
+	fmt.Fprintln(w, "const struct bootutil_key bootutil_keys[] = {")
+	fmt.Fprintln(w, "    [0] = {")
+	fmt.Fprintln(w, "        .key = key,")
+	fmt.Fprintln(w, "        .len = &key_len,")
+	fmt.Fprintln(w, "    },")
+	fmt.Fprintln(w, "};")
+	fmt.Fprintln(w, "const int bootutil_key_cnt = 1;")
+	w.Flush()
+
+	return nil
+}
+
 func (t *TargetBuilder) Build() error {
 	if err := t.PrepBuild(); err != nil {
 		return err
@@ -357,10 +437,17 @@ func (t *TargetBuilder) Build() error {
 	/* Build the Apps */
 	project.ResetDeps(t.AppList)
 
-	if err := t.bspPkg.Reload(t.AppBuilder.cfg.Features()); err != nil {
+	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
 		return err
 	}
 
+	if t.keyFile != "" {
+		err := t.autogenKeys()
+		if err != nil {
+			return err
+		}
+	}
+
 	if err := t.AppBuilder.Build(); err != nil {
 		return err
 	}
@@ -563,7 +650,7 @@ func (t *TargetBuilder) createManifest() error {
 
 	manifest.Repos = rm.AllRepos()
 
-	vars := t.GetTarget().Vars
+	vars := t.GetTarget().TargetY.AllSettingsAsStrings()
 	keys := make([]string, 0, len(vars))
 	for k := range vars {
 		keys = append(keys, k)
@@ -572,7 +659,8 @@ func (t *TargetBuilder) createManifest() error {
 	for _, k := range keys {
 		manifest.TgtVars = append(manifest.TgtVars, k+"="+vars[k])
 	}
-	syscfgKV := t.GetTarget().Package().SyscfgV.GetStringMapString("syscfg.vals")
+	syscfgKV := t.GetTarget().Package().SyscfgY.GetValStringMapString(
+		"syscfg.vals", nil)
 	if len(syscfgKV) > 0 {
 		tgtSyscfg := fmt.Sprintf("target.syscfg=%s",
 			syscfg.KeyValueToStr(syscfgKV))
@@ -776,7 +864,7 @@ func (t *TargetBuilder) CreateImages(version string,
 	var appImg *image.Image
 	var loaderImg *image.Image
 
-	c, err := t.NewCompiler("")
+	c, err := t.NewCompiler("", "")
 	if err != nil {
 		return nil, nil, err
 	}
@@ -793,7 +881,7 @@ func (t *TargetBuilder) CreateImages(version string,
 			t.LoaderBuilder.AppHexPath(),
 			tgtArea.Offset)
 		err = c.ConvertBinToHex(t.LoaderBuilder.AppImgPath(),
-				t.LoaderBuilder.AppHexPath(), tgtArea.Offset)
+			t.LoaderBuilder.AppHexPath(), tgtArea.Offset)
 		if err != nil {
 			log.Errorf("Can't convert to hexfile %s\n", err.Error())
 		}
@@ -807,7 +895,7 @@ func (t *TargetBuilder) CreateImages(version string,
 	flashTargetArea := ""
 	if t.LoaderBuilder == nil {
 		flashTargetArea = flash.FLASH_AREA_NAME_IMAGE_0
-	} else  {
+	} else {
 		flashTargetArea = flash.FLASH_AREA_NAME_IMAGE_1
 	}
 	tgtArea := t.bspPkg.FlashMap.Areas[flashTargetArea]
@@ -817,7 +905,7 @@ func (t *TargetBuilder) CreateImages(version string,
 			t.AppBuilder.AppHexPath(),
 			tgtArea.Offset)
 		err = c.ConvertBinToHex(t.AppBuilder.AppImgPath(),
-				t.AppBuilder.AppHexPath(), tgtArea.Offset)
+			t.AppBuilder.AppHexPath(), tgtArea.Offset)
 		if err != nil {
 			log.Errorf("Can't convert to hexfile %s\n", err.Error())
 		}
diff --git a/vendor/mynewt.apache.org/newt/newt/cli/build_cmds.go b/vendor/mynewt.apache.org/newt/newt/cli/build_cmds.go
index 9df1a9de..5865b0ab 100644
--- a/vendor/mynewt.apache.org/newt/newt/cli/build_cmds.go
+++ b/vendor/mynewt.apache.org/newt/newt/cli/build_cmds.go
@@ -88,11 +88,9 @@ func pkgToUnitTests(pack *pkg.LocalPackage) []*pkg.LocalPackage {
 	// Otherwise, return all the package's direct descendants that are unit
 	// test packages.
 	result := []*pkg.LocalPackage{}
-	srcPath := pack.BasePath()
 	for p, _ := range testablePkgs() {
-		dirPath := filepath.ToSlash(filepath.Dir(p.BasePath()))
 		if p.Type() == pkg.PACKAGE_TYPE_UNITTEST &&
-			dirPath == srcPath {
+			strings.HasPrefix(p.FullName(), pack.FullName()) {
 
 			result = append(result, p)
 		}
@@ -265,7 +263,10 @@ func testRunCmd(cmd *cobra.Command, args []string, exclude string, executeShell
 	packLoop:
 		for _, pack := range orig {
 			for _, excl := range excls {
-				if pack.Name() == excl || strings.HasPrefix(pack.Name(), excl+"/") {
+				if pack.Name() == excl ||
+					strings.HasPrefix(pack.Name(), excl+"/") ||
+					pack.NameWithRepo() == excl ||
+					strings.HasPrefix(pack.NameWithRepo(), excl+"/") {
 					continue packLoop
 				}
 			}
@@ -364,7 +365,7 @@ func debugRunCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
-func sizeRunCmd(cmd *cobra.Command, args []string, ram bool, flash bool) {
+func sizeRunCmd(cmd *cobra.Command, args []string, ram bool, flash bool, section string) {
 	if len(args) < 1 {
 		NewtUsage(cmd, util.NewNewtError("Must specify target"))
 	}
@@ -381,10 +382,27 @@ func sizeRunCmd(cmd *cobra.Command, args []string, ram bool, flash bool) {
 		NewtUsage(nil, err)
 	}
 
-	if ram || flash {
-		if err := b.SizeReport(ram, flash); err != nil {
-			NewtUsage(cmd, err)
+	var sections []string
+
+	if ram {
+		sections = append(sections, "RAM")
+	}
+
+	if flash {
+		sections = append(sections, "FLASH")
+	}
+
+	if section != "" {
+		sections = append(sections, section)
+	}
+
+	if len(sections) > 0 {
+		for _, sectionName := range sections {
+			if err := b.SizeReport(sectionName); err != nil {
+				NewtUsage(cmd, err)
+			}
 		}
+
 		return
 	}
 
@@ -479,18 +497,20 @@ func AddBuildCommands(cmd *cobra.Command) {
 		"<target-name>."
 
 	var ram, flash bool
+	var section string
 	sizeCmd := &cobra.Command{
 		Use:   "size <target-name>",
 		Short: "Size of target components",
 		Long:  sizeHelpText,
 		Run: func(cmd *cobra.Command, args []string) {
-			sizeRunCmd(cmd, args, ram, flash)
+			sizeRunCmd(cmd, args, ram, flash, section)
 		},
 	}
 
 	sizeCmd.Flags().BoolVarP(&ram, "ram", "R", false, "Print RAM statistics")
 	sizeCmd.Flags().BoolVarP(&flash, "flash", "F", false,
 		"Print FLASH statistics")
+	sizeCmd.Flags().StringVarP(&section, "section", "S", "", "Print section statistics")
 
 	cmd.AddCommand(sizeCmd)
 	AddTabCompleteFn(sizeCmd, targetList)
diff --git a/vendor/mynewt.apache.org/newt/newt/cli/image_cmds.go b/vendor/mynewt.apache.org/newt/newt/cli/image_cmds.go
index a9ae3f39..5c4e63d8 100644
--- a/vendor/mynewt.apache.org/newt/newt/cli/image_cmds.go
+++ b/vendor/mynewt.apache.org/newt/newt/cli/image_cmds.go
@@ -29,6 +29,9 @@ import (
 	"mynewt.apache.org/newt/util"
 )
 
+var useV1 bool
+var useV2 bool
+
 func createImageRunCmd(cmd *cobra.Command, args []string) {
 	var keyId uint8
 	var keystr string
@@ -37,6 +40,15 @@ func createImageRunCmd(cmd *cobra.Command, args []string) {
 		NewtUsage(cmd, util.NewNewtError("Must specify target and version"))
 	}
 
+	if useV1 && useV2 {
+		NewtUsage(cmd, util.NewNewtError("Either -1, or -2, but not both"))
+	}
+	if useV2 {
+		image.UseV1 = false
+	} else {
+		image.UseV1 = true
+	}
+
 	TryGetProject()
 
 	targetName := args[0]
@@ -78,6 +90,15 @@ func resignImageRunCmd(cmd *cobra.Command, args []string) {
 		NewtUsage(cmd, util.NewNewtError("Must specify image to re-sign."))
 	}
 
+	if useV1 && useV2 {
+		NewtUsage(cmd, util.NewNewtError("Either -1, or -2, but not both"))
+	}
+	if useV2 {
+		image.UseV1 = false
+	} else {
+		image.UseV1 = true
+	}
+
 	imgName := args[0]
 	img, err := image.OldImage(imgName)
 	if err != nil {
@@ -110,12 +131,24 @@ func resignImageRunCmd(cmd *cobra.Command, args []string) {
 
 func AddImageCommands(cmd *cobra.Command) {
 	createImageHelpText := "Create an image by adding an image header to the " +
-		"binary file created for <target-name>. Version number in the header is set " +
-		"to be <version>.\n\nTo sign the image give private key as <signing-key> and an optional key-id."
-	createImageHelpEx := "  newt create-image my_target1 1.2.0\n"
-	createImageHelpEx += "  newt create-image my_target1 1.2.0.3\n"
-	createImageHelpEx += "  newt create-image my_target1 1.2.0.3 private.pem\n"
-	createImageHelpEx += "  newt create-image my_target1 1.2.0.3 private.pem 5\n"
+		"binary file created for <target-name>. Version number in the header " +
+		"is set to be <version>.\n\n"
+
+	createImageHelpText += "To use version 1 of image format, specify -1 on " +
+		"command line.\n"
+	createImageHelpText += "To sign version 1 of the image format give private " +
+		"key as <signing-key> and an optional key-id.\n\n"
+	createImageHelpText += "To use version 2 of image format, specify -2 on " +
+		"command line.\n"
+	createImageHelpText += "To sign version 2 of the image format give private " +
+		"key as <signing-key> (no key-id needed).\n\n"
+
+	createImageHelpText += "Default image format is version 1.\n"
+
+	createImageHelpEx := "  newt create-image my_target1 1.3.0\n"
+	createImageHelpEx += "  newt create-image my_target1 1.3.0.3\n"
+	createImageHelpEx += "  newt create-image my_target1 1.3.0.3 private.pem\n"
+	createImageHelpEx += "  newt create-image my_target1 1.3.0.3 private.pem 5\n"
 
 	createImageCmd := &cobra.Command{
 		Use:     "create-image <target-name> <version> [signing-key [key-id]]",
@@ -130,7 +163,12 @@ func AddImageCommands(cmd *cobra.Command) {
 		"Ignore flash overflow errors during image creation")
 	createImageCmd.PersistentFlags().BoolVar(&image.UseRsaPss,
 		"rsa-pss", false,
-		"Use RSA-PSS instead of PKCS#1 v1.5 for RSA sigs")
+		"Use RSA-PSS instead of PKCS#1 v1.5 for RSA sig. "+
+			"Meaningful for version 1 image format.")
+	createImageCmd.PersistentFlags().BoolVarP(&useV1,
+		"1", "1", false, "Use old image header format")
+	createImageCmd.PersistentFlags().BoolVarP(&useV2,
+		"2", "2", false, "Use new image header format")
 
 	cmd.AddCommand(createImageCmd)
 	AddTabCompleteFn(createImageCmd, targetList)
@@ -138,7 +176,10 @@ func AddImageCommands(cmd *cobra.Command) {
 	resignImageHelpText := "Sign/Re-sign an existing image file with the specified signing key.\nIf a signing key is not specified, the signing key in the current image\nis stripped.  "
 	resignImageHelpText += "A image header will be recreated!\n"
 	resignImageHelpText += "\nWarning: The image hash will change if you change key-id "
-	resignImageHelpText += "or the type of key used for signing."
+	resignImageHelpText += "or the type of key used for signing.\n"
+	resignImageHelpText += "Default image format is version 1.\n"
+	resignImageHelpText += "RSA signature format by default for ver 1 image is PKCSv1.5\n"
+	resignImageHelpText += "RSA signature format for ver 2 image is RSA-PSS\n"
 
 	resignImageHelpEx := "  newt resign-image my_target1.img private.pem\n"
 	resignImageHelpEx += "  newt resign-image my_target1.img private.pem 5\n"
@@ -154,6 +195,14 @@ func AddImageCommands(cmd *cobra.Command) {
 	resignImageCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
 		"force", "f", false,
 		"Ignore flash overflow errors during image creation")
+	resignImageCmd.PersistentFlags().BoolVar(&image.UseRsaPss,
+		"rsa-pss", false,
+		"Use RSA-PSS instead of PKCS#1 v1.5 for RSA sig. "+
+			"Meaningful for version 1 image format.")
+	resignImageCmd.PersistentFlags().BoolVarP(&useV1,
+		"1", "1", false, "Use old image header format")
+	resignImageCmd.PersistentFlags().BoolVarP(&useV2,
+		"2", "2", false, "Use new image header format")
 
 	cmd.AddCommand(resignImageCmd)
 }
diff --git a/vendor/mynewt.apache.org/newt/newt/cli/project_cmds.go b/vendor/mynewt.apache.org/newt/newt/cli/project_cmds.go
index 5cac6af5..42045249 100644
--- a/vendor/mynewt.apache.org/newt/newt/cli/project_cmds.go
+++ b/vendor/mynewt.apache.org/newt/newt/cli/project_cmds.go
@@ -20,7 +20,6 @@
 package cli
 
 import (
-	"fmt"
 	"os"
 	"sort"
 	"strings"
@@ -30,9 +29,12 @@ import (
 	"mynewt.apache.org/newt/newt/interfaces"
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/project"
+	"mynewt.apache.org/newt/newt/repo"
 	"mynewt.apache.org/newt/util"
 )
 
+var infoRemote bool
+
 func newRunCmd(cmd *cobra.Command, args []string) {
 	if len(args) < 1 {
 		NewtUsage(cmd, util.NewNewtError("Must specify "+
@@ -52,15 +54,20 @@ func newRunCmd(cmd *cobra.Command, args []string) {
 	dl.User = "apache"
 	dl.Repo = "mynewt-blinky"
 
-	dir, err := dl.DownloadRepo(newtutil.NewtBlinkyTag)
+	tmpdir, err := newtutil.MakeTempRepoDir()
 	if err != nil {
-		NewtUsage(cmd, err)
+		NewtUsage(nil, err)
+	}
+	defer os.RemoveAll(tmpdir)
+
+	if err := dl.Clone(newtutil.NewtBlinkyTag, tmpdir); err != nil {
+		NewtUsage(nil, err)
 	}
 
 	util.StatusMessage(util.VERBOSITY_DEFAULT, "Installing "+
 		"skeleton in %s...\n", newDir)
 
-	if err := util.CopyDir(dir, newDir); err != nil {
+	if err := util.CopyDir(tmpdir, newDir); err != nil {
 		NewtUsage(cmd, err)
 	}
 
@@ -72,12 +79,38 @@ func newRunCmd(cmd *cobra.Command, args []string) {
 		"Project %s successfully created.\n", newDir)
 }
 
+// Builds a repo selection predicate based on the specified names.  If no names
+// are specified, the resulting function selects all non-local repos.
+// Otherwise, the function selects each non-local repo whose name is specified.
+func makeRepoPredicate(repoNames []string) func(r *repo.Repo) bool {
+	// If the user didn't specify any repo names, apply the operation to all
+	// repos in `project.yml`.
+	if len(repoNames) == 0 {
+		proj := project.GetProject()
+		return func(r *repo.Repo) bool { return proj.RepoIsRoot(r.Name()) }
+	}
+
+	return func(r *repo.Repo) bool {
+		if !r.IsLocal() {
+			for _, arg := range repoNames {
+				if strings.TrimPrefix(r.Name(), "@") == arg {
+					return true
+				}
+			}
+		}
+		return false
+	}
+}
+
 func installRunCmd(cmd *cobra.Command, args []string) {
 	proj := TryGetProject()
 	interfaces.SetProject(proj)
 
-	if err := proj.Install(false, newtutil.NewtForce); err != nil {
-		NewtUsage(cmd, err)
+	pred := makeRepoPredicate(args)
+	if err := proj.InstallIf(
+		false, newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {
+
+		NewtUsage(nil, err)
 	}
 }
 
@@ -85,18 +118,29 @@ func upgradeRunCmd(cmd *cobra.Command, args []string) {
 	proj := TryGetProject()
 	interfaces.SetProject(proj)
 
-	if err := proj.Upgrade(newtutil.NewtForce); err != nil {
-		NewtUsage(cmd, err)
+	pred := makeRepoPredicate(args)
+	if err := proj.InstallIf(
+		true, newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {
+
+		NewtUsage(nil, err)
 	}
 }
 
 func infoRunCmd(cmd *cobra.Command, args []string) {
-	reqRepoName := ""
-	if len(args) >= 1 {
-		reqRepoName = strings.TrimPrefix(args[0], "@")
+	proj := TryGetProject()
+
+	// If no arguments specified, print status of all installed repos.
+	if len(args) == 0 {
+		pred := func(r *repo.Repo) bool { return !r.IsLocal() }
+
+		if err := proj.InfoIf(pred, infoRemote); err != nil {
+			NewtUsage(nil, err)
+		}
+		return
 	}
 
-	proj := TryGetProject()
+	// Otherwise, list packages specified repo contains.
+	reqRepoName := strings.TrimPrefix(args[0], "@")
 
 	repoNames := []string{}
 	for repoName, _ := range proj.PackageList() {
@@ -104,19 +148,6 @@ func infoRunCmd(cmd *cobra.Command, args []string) {
 	}
 	sort.Strings(repoNames)
 
-	if reqRepoName == "" {
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "Repositories in %s:\n",
-			proj.Name())
-
-		for _, repoName := range repoNames {
-			util.StatusMessage(util.VERBOSITY_DEFAULT, "    * @%s\n", repoName)
-		}
-
-		// Now display the packages in the local repository.
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
-		reqRepoName = "local"
-	}
-
 	firstRepo := true
 	for _, repoName := range repoNames {
 		if reqRepoName == "all" || reqRepoName == repoName {
@@ -150,47 +181,23 @@ func infoRunCmd(cmd *cobra.Command, args []string) {
 
 func syncRunCmd(cmd *cobra.Command, args []string) {
 	proj := TryGetProject()
-	repos := proj.Repos()
+	pred := makeRepoPredicate(args)
 
-	ps, err := project.LoadProjectState()
-	if err != nil {
-		NewtUsage(nil, err)
-	}
+	if err := proj.SyncIf(
+		newtutil.NewtForce, newtutil.NewtAsk, pred); err != nil {
 
-	var failedRepos []string
-	for _, repo := range repos {
-		var exists bool
-		var updated bool
-		if repo.IsLocal() {
-			continue
-		}
-		vers := ps.GetInstalledVersion(repo.Name())
-		if vers == nil {
-			util.StatusMessage(util.VERBOSITY_DEFAULT,
-				"No installed version of %s found, skipping\n\n",
-				repo.Name())
-		}
-		exists, updated, err = repo.Sync(vers, newtutil.NewtForce)
-		if exists && !updated {
-			failedRepos = append(failedRepos, repo.Name())
-		}
-	}
-	if len(failedRepos) > 0 {
-		var forceMsg string
-		if !newtutil.NewtForce {
-			forceMsg = " To force resync, add the -f (force) option."
-		}
-		err = util.NewNewtError(fmt.Sprintf("Failed for repos: %v."+
-			forceMsg, failedRepos))
 		NewtUsage(nil, err)
 	}
 }
 
 func AddProjectCommands(cmd *cobra.Command) {
 	installHelpText := ""
-	installHelpEx := ""
+	installHelpEx := "  newt install\n"
+	installHelpEx += "    Installs all repositories specified in project.yml.\n\n"
+	installHelpEx += "  newt install apache-mynewt-core\n"
+	installHelpEx += "    Installs the apache-mynewt-core repository."
 	installCmd := &cobra.Command{
-		Use:     "install",
+		Use:     "install [repo-1] [repo-2] [...]",
 		Short:   "Install project dependencies",
 		Long:    installHelpText,
 		Example: installHelpEx,
@@ -200,13 +207,18 @@ func AddProjectCommands(cmd *cobra.Command) {
 		"force", "f", false,
 		"Force install of the repositories in project, regardless of what "+
 			"exists in repos directory")
+	installCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
+		"ask", "a", false, "Prompt user before installing any repos")
 
 	cmd.AddCommand(installCmd)
 
 	upgradeHelpText := ""
-	upgradeHelpEx := ""
+	upgradeHelpEx := "  newt upgrade\n"
+	upgradeHelpEx += "    Upgrades all repositories specified in project.yml.\n\n"
+	upgradeHelpEx += "  newt upgrade apache-mynewt-core\n"
+	upgradeHelpEx += "    Upgrades the apache-mynewt-core repository."
 	upgradeCmd := &cobra.Command{
-		Use:     "upgrade",
+		Use:     "upgrade [repo-1] [repo-2] [...]",
 		Short:   "Upgrade project dependencies",
 		Long:    upgradeHelpText,
 		Example: upgradeHelpEx,
@@ -215,13 +227,18 @@ func AddProjectCommands(cmd *cobra.Command) {
 	upgradeCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
 		"force", "f", false,
 		"Force upgrade of the repositories to latest state in project.yml")
+	upgradeCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
+		"ask", "a", false, "Prompt user before upgrading any repos")
 
 	cmd.AddCommand(upgradeCmd)
 
 	syncHelpText := ""
-	syncHelpEx := ""
+	syncHelpEx := "  newt sync\n"
+	syncHelpEx += "    Syncs all repositories specified in project.yml.\n\n"
+	syncHelpEx += "  newt sync apache-mynewt-core\n"
+	syncHelpEx += "    Syncs the apache-mynewt-core repository."
 	syncCmd := &cobra.Command{
-		Use:     "sync",
+		Use:     "sync [repo-1] [repo-2] [...]",
 		Short:   "Synchronize project dependencies",
 		Long:    syncHelpText,
 		Example: syncHelpEx,
@@ -230,6 +247,8 @@ func AddProjectCommands(cmd *cobra.Command) {
 	syncCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
 		"force", "f", false,
 		"Force overwrite of existing remote repositories.")
+	syncCmd.PersistentFlags().BoolVarP(&newtutil.NewtAsk,
+		"ask", "a", false, "Prompt user before syncing any repos")
 	cmd.AddCommand(syncCmd)
 
 	newHelpText := ""
@@ -254,6 +273,9 @@ func AddProjectCommands(cmd *cobra.Command) {
 		Example: infoHelpEx,
 		Run:     infoRunCmd,
 	}
+	infoCmd.PersistentFlags().BoolVarP(&infoRemote,
+		"remote", "r", false,
+		"Fetch latest repos to determine if upgrades are required")
 
 	cmd.AddCommand(infoCmd)
 }
diff --git a/vendor/mynewt.apache.org/newt/newt/cli/run_cmds.go b/vendor/mynewt.apache.org/newt/newt/cli/run_cmds.go
index 9c36f676..49a2e4d3 100644
--- a/vendor/mynewt.apache.org/newt/newt/cli/run_cmds.go
+++ b/vendor/mynewt.apache.org/newt/newt/cli/run_cmds.go
@@ -23,7 +23,9 @@ import (
 	"fmt"
 	"github.com/spf13/cobra"
 
+	"mynewt.apache.org/newt/newt/image"
 	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/parse"
 	"mynewt.apache.org/newt/util"
 )
 
@@ -32,6 +34,15 @@ func runRunCmd(cmd *cobra.Command, args []string) {
 		NewtUsage(cmd, util.NewNewtError("Must specify target"))
 	}
 
+	if useV1 && useV2 {
+		NewtUsage(cmd, util.NewNewtError("Either -1, or -2, but not both"))
+	}
+	if useV2 {
+		image.UseV1 = false
+	} else {
+		image.UseV1 = true
+	}
+
 	TryGetProject()
 
 	b, err := TargetBuilderForTargetOrUnittest(args[0])
@@ -62,9 +73,11 @@ func runRunCmd(cmd *cobra.Command, args []string) {
 			if err != nil {
 				NewtUsage(nil, err)
 			}
-			features := res.Cfg.Features()
+			settings := res.Cfg.SettingValues()
+
+			if !parse.ValueIsTrue(settings["BOOT_LOADER"]) &&
+				!parse.ValueIsTrue(settings["BSP_SIMULATED"]) {
 
-			if !features["BOOT_LOADER"] && !features["BSP_SIMULATED"] {
 				version = "0"
 				fmt.Println("Enter image version(default 0):")
 				fmt.Scanf("%s\n", &version)
@@ -116,6 +129,10 @@ func AddRunCommands(cmd *cobra.Command) {
 	runCmd.PersistentFlags().BoolVarP(&newtutil.NewtForce,
 		"force", "f", false,
 		"Ignore flash overflow errors during image creation")
+	runCmd.PersistentFlags().BoolVarP(&useV1,
+		"1", "1", false, "Use old image header format")
+	runCmd.PersistentFlags().BoolVarP(&useV2,
+		"2", "2", false, "Use new image header format")
 
 	cmd.AddCommand(runCmd)
 	AddTabCompleteFn(runCmd, func() []string {
diff --git a/vendor/mynewt.apache.org/newt/newt/cli/target_cmds.go b/vendor/mynewt.apache.org/newt/newt/cli/target_cmds.go
index 5632a78e..bf7d6ddf 100644
--- a/vendor/mynewt.apache.org/newt/newt/cli/target_cmds.go
+++ b/vendor/mynewt.apache.org/newt/newt/cli/target_cmds.go
@@ -36,18 +36,17 @@ import (
 	"mynewt.apache.org/newt/newt/resolve"
 	"mynewt.apache.org/newt/newt/syscfg"
 	"mynewt.apache.org/newt/newt/target"
+	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
-	"mynewt.apache.org/newt/viper"
 )
 
-var targetForce bool = false
 var amendDelete bool = false
 
 // target variables that can have values amended with the amend command.
-var amendVars = []string{"aflags", "cflags", "lflags", "syscfg"}
+var amendVars = []string{"aflags", "cflags", "cxxflags", "lflags", "syscfg"}
 
 var setVars = []string{"aflags", "app", "build_profile", "bsp", "cflags",
-	"lflags", "loader", "syscfg"}
+	"cxxflags", "lflags", "loader", "syscfg"}
 
 func resolveExistingTargetArg(arg string) (*target.Target, error) {
 	t := ResolveTarget(arg)
@@ -81,11 +80,11 @@ func targetContainsUserFiles(t *target.Target) (bool, error) {
 }
 
 func pkgVarSliceString(pack *pkg.LocalPackage, key string) string {
-	features := pack.PkgV.GetStringSlice(key)
-	sort.Strings(features)
+	vals := pack.PkgY.GetValStringSlice(key, nil)
+	sort.Strings(vals)
 	var buffer bytes.Buffer
-	for _, f := range features {
-		buffer.WriteString(f)
+	for _, v := range vals {
+		buffer.WriteString(v)
 		buffer.WriteString(" ")
 	}
 	return buffer.String()
@@ -93,9 +92,8 @@ func pkgVarSliceString(pack *pkg.LocalPackage, key string) string {
 
 //Process amend command for syscfg target variable
 func amendSysCfg(value string, t *target.Target) error {
-
 	// Get the current syscfg.vals name-value pairs
-	sysVals := t.Package().SyscfgV.GetStringMapString("syscfg.vals")
+	sysVals := t.Package().SyscfgY.GetValStringMapString("syscfg.vals", nil)
 
 	// Convert the input syscfg into name-value pairs
 	amendSysVals, err := syscfg.KeyValueFromStr(value)
@@ -119,14 +117,16 @@ func amendSysCfg(value string, t *target.Target) error {
 			sysVals = amendSysVals
 		}
 	}
-	t.Package().SyscfgV.Set("syscfg.vals", sysVals)
+
+	itfMap := util.StringMapStringToItfMapItf(sysVals)
+	t.Package().SyscfgY.Replace("syscfg.vals", itfMap)
 	return nil
 }
 
-//Process amend command for aflags, cflags, and lflags target variables.
+//Process amend command for aflags, cflags, cxxflags, and lflags target variables.
 func amendBuildFlags(kv []string, t *target.Target) error {
-	pkg_var := "pkg." + kv[0]
-	curFlags := t.Package().PkgV.GetStringSlice(pkg_var)
+	pkgVar := "pkg." + kv[0]
+	curFlags := t.Package().PkgY.GetValStringSlice(pkgVar, nil)
 	amendFlags := strings.Fields(kv[1])
 
 	newFlags := []string{}
@@ -164,7 +164,7 @@ func amendBuildFlags(kv []string, t *target.Target) error {
 			}
 		}
 	}
-	t.Package().PkgV.Set(pkg_var, newFlags)
+	t.Package().PkgY.Replace(pkgVar, newFlags)
 	return nil
 }
 
@@ -200,14 +200,16 @@ func targetShowCmd(cmd *cobra.Command, args []string) {
 		util.StatusMessage(util.VERBOSITY_DEFAULT, name+"\n")
 
 		target := target.GetTargets()[name]
-		for k, v := range target.Vars {
+		settings := target.TargetY.AllSettingsAsStrings()
+		for k, v := range settings {
 			kvPairs[strings.TrimPrefix(k, "target.")] = v
 		}
 
 		// A few variables come from the base package rather than the target.
 		kvPairs["syscfg"] = syscfg.KeyValueToStr(
-			target.Package().SyscfgV.GetStringMapString("syscfg.vals"))
+			target.Package().SyscfgY.GetValStringMapString("syscfg.vals", nil))
 		kvPairs["cflags"] = pkgVarSliceString(target.Package(), "pkg.cflags")
+		kvPairs["cxxflags"] = pkgVarSliceString(target.Package(), "pkg.cxxflags")
 		kvPairs["lflags"] = pkgVarSliceString(target.Package(), "pkg.lflags")
 		kvPairs["aflags"] = pkgVarSliceString(target.Package(), "pkg.aflags")
 
@@ -226,6 +228,27 @@ func targetShowCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
+func targetCmakeCmd(cmd *cobra.Command, args []string) {
+	TryGetProject()
+
+	// Verify and resolve each specified package.
+	targets, err := ResolveTargets(args...)
+	if err != nil {
+		NewtUsage(cmd, err)
+		return
+	}
+
+	if len(targets) != 1 {
+		NewtUsage(cmd, err)
+		return
+	}
+
+	err = builder.CMakeTargetGenerate(targets[0])
+	if err != nil {
+		NewtUsage(nil, err)
+	}
+}
+
 func targetSetCmd(cmd *cobra.Command, args []string) {
 	if len(args) < 2 {
 		NewtUsage(cmd,
@@ -282,31 +305,33 @@ func targetSetCmd(cmd *cobra.Command, args []string) {
 		// A few variables are special cases; they get set in the base package
 		// instead of the target.
 		if kv[0] == "target.syscfg" {
-			t.Package().SyscfgV = viper.New()
+			t.Package().SyscfgY = ycfg.YCfg{}
 			kv, err := syscfg.KeyValueFromStr(kv[1])
 			if err != nil {
 				NewtUsage(cmd, err)
 			}
 
-			t.Package().SyscfgV.Set("syscfg.vals", kv)
+			itfMap := util.StringMapStringToItfMapItf(kv)
+			t.Package().SyscfgY.Replace("syscfg.vals", itfMap)
 		} else if kv[0] == "target.cflags" ||
+			kv[0] == "target.cxxflags" ||
 			kv[0] == "target.lflags" ||
 			kv[0] == "target.aflags" {
 
 			kv[0] = "pkg." + strings.TrimPrefix(kv[0], "target.")
 			if kv[1] == "" {
 				// User specified empty value; delete variable.
-				t.Package().PkgV.Set(kv[0], nil)
+				t.Package().PkgY.Replace(kv[0], nil)
 			} else {
-				t.Package().PkgV.Set(kv[0], strings.Fields(kv[1]))
+				t.Package().PkgY.Replace(kv[0], strings.Fields(kv[1]))
 			}
 		} else {
 			if kv[1] == "" {
 				// User specified empty value; delete variable.
-				delete(t.Vars, kv[0])
+				t.TargetY.Delete(kv[0])
 			} else {
 				// Assign value to specified variable.
-				t.Vars[kv[0]] = kv[1]
+				t.TargetY.Replace(kv[0], kv[1])
 			}
 		}
 	}
@@ -383,6 +408,7 @@ func targetAmendCmd(cmd *cobra.Command, args []string) {
 				NewtUsage(cmd, err)
 			}
 		} else if kv[0] == "cflags" ||
+			kv[0] == "cxxflags" ||
 			kv[0] == "lflags" ||
 			kv[0] == "aflags" {
 			err = amendBuildFlags(kv, t)
@@ -430,7 +456,7 @@ func targetCreateCmd(cmd *cobra.Command, args []string) {
 }
 
 func targetDelOne(t *target.Target) error {
-	if !targetForce {
+	if !newtutil.NewtForce {
 		// Determine if the target directory contains extra user files.  If it
 		// does, a prompt (or force) is required to delete it.
 		userFiles, err := targetContainsUserFiles(t)
@@ -543,11 +569,40 @@ func printSetting(entry syscfg.CfgEntry) {
 			"    * Overridden: ")
 		for i := 1; i < len(entry.History); i++ {
 			util.StatusMessage(util.VERBOSITY_DEFAULT, "%s, ",
-				entry.History[i].Source.Name())
+				entry.History[i].Source.FullName())
 		}
 		util.StatusMessage(util.VERBOSITY_DEFAULT,
 			"default=%s\n", entry.History[0].Value)
 	}
+	if len(entry.ValueRefName) > 0 {
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"    * Copied from: %s\n",
+			entry.ValueRefName)
+	}
+}
+
+func printBriefSetting(entry syscfg.CfgEntry) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "  %s: %s",
+		entry.Name, entry.Value)
+
+	var extras []string
+
+	if len(entry.History) > 1 {
+		s := fmt.Sprintf("overridden by %s",
+			entry.History[len(entry.History)-1].Source.FullName())
+		extras = append(extras, s)
+	}
+	if len(entry.ValueRefName) > 0 {
+		s := fmt.Sprintf("copied from %s", entry.ValueRefName)
+		extras = append(extras, s)
+	}
+
+	if len(extras) > 0 {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, " (%s)",
+			strings.Join(extras, ", "))
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
 }
 
 func printPkgCfg(pkgName string, cfg syscfg.Cfg, entries []syscfg.CfgEntry) {
@@ -586,6 +641,42 @@ func printCfg(targetName string, cfg syscfg.Cfg) {
 	}
 }
 
+func printPkgBriefCfg(pkgName string, cfg syscfg.Cfg, entries []syscfg.CfgEntry) {
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "[%s]\n", pkgName)
+
+	settingNames := make([]string, len(entries))
+	for i, entry := range entries {
+		settingNames[i] = entry.Name
+	}
+	sort.Strings(settingNames)
+
+	for _, name := range settingNames {
+		printBriefSetting(cfg.Settings[name])
+	}
+}
+
+func printBriefCfg(targetName string, cfg syscfg.Cfg) {
+	if errText := cfg.ErrorText(); errText != "" {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "!!! %s\n\n", errText)
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Brief syscfg for %s:\n", targetName)
+	pkgNameEntryMap := syscfg.EntriesByPkg(cfg)
+
+	pkgNames := make([]string, 0, len(pkgNameEntryMap))
+	for pkgName, _ := range pkgNameEntryMap {
+		pkgNames = append(pkgNames, pkgName)
+	}
+	sort.Strings(pkgNames)
+
+	for i, pkgName := range pkgNames {
+		if i > 0 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+		printPkgBriefCfg(pkgName, cfg, pkgNameEntryMap[pkgName])
+	}
+}
+
 func yamlPkgCfg(w io.Writer, pkgName string, cfg syscfg.Cfg,
 	entries []syscfg.CfgEntry) {
 
@@ -635,9 +726,7 @@ func targetBuilderConfigResolve(b *builder.TargetBuilder) *resolve.Resolution {
 
 	warningText := strings.TrimSpace(res.WarningText())
 	if warningText != "" {
-		for _, line := range strings.Split(warningText, "\n") {
-			log.Warn(line)
-		}
+		log.Warn(warningText + "\n")
 	}
 
 	return res
@@ -649,7 +738,9 @@ func targetConfigShowCmd(cmd *cobra.Command, args []string) {
 			util.NewNewtError("Must specify target or unittest name"))
 	}
 
-	for _, arg := range args {
+	TryGetProject()
+
+	for i, arg := range args {
 		b, err := TargetBuilderForTargetOrUnittest(arg)
 		if err != nil {
 			NewtUsage(cmd, err)
@@ -657,6 +748,33 @@ func targetConfigShowCmd(cmd *cobra.Command, args []string) {
 
 		res := targetBuilderConfigResolve(b)
 		printCfg(b.GetTarget().Name(), res.Cfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
+	}
+}
+
+func targetConfigBriefCmd(cmd *cobra.Command, args []string) {
+	if len(args) < 1 {
+		NewtUsage(cmd,
+			util.NewNewtError("Must specify target or unittest name"))
+	}
+
+	TryGetProject()
+
+	for i, arg := range args {
+		b, err := TargetBuilderForTargetOrUnittest(arg)
+		if err != nil {
+			NewtUsage(cmd, err)
+		}
+
+		res := targetBuilderConfigResolve(b)
+		printBriefCfg(b.GetTarget().Name(), res.Cfg)
+
+		if i < len(args)-1 {
+			util.StatusMessage(util.VERBOSITY_DEFAULT, "\n")
+		}
 	}
 }
 
@@ -673,6 +791,8 @@ func targetConfigInitCmd(cmd *cobra.Command, args []string) {
 		exists bool
 	}
 
+	TryGetProject()
+
 	anyExist := false
 	entries := make([]entry, len(args))
 	for i, pkgName := range args {
@@ -697,7 +817,7 @@ func targetConfigInitCmd(cmd *cobra.Command, args []string) {
 		}
 	}
 
-	if anyExist && !targetForce {
+	if anyExist && !newtutil.NewtForce {
 		util.StatusMessage(util.VERBOSITY_DEFAULT,
 			"Configuration files already exist:\n")
 		for _, e := range entries {
@@ -845,6 +965,21 @@ func AddTargetCommands(cmd *cobra.Command) {
 	targetCmd.AddCommand(showCmd)
 	AddTabCompleteFn(showCmd, targetList)
 
+	cmakeHelpText := "Generate CMakeLists.txt for target specified " +
+		"by <target-name>."
+	cmakeHelpEx := "  newt target cmake <target-name>\n"
+	cmakeHelpEx += "  newt target cmake my_target1"
+
+	cmakeCmd := &cobra.Command{
+		Use:     "cmake",
+		Short:   "",
+		Long:    cmakeHelpText,
+		Example: cmakeHelpEx,
+		Run:     targetCmakeCmd,
+	}
+	targetCmd.AddCommand(cmakeCmd)
+	AddTabCompleteFn(cmakeCmd, targetList)
+
 	setHelpText := "Set a target variable (<var-name>) on target "
 	setHelpText += "<target-name> to value <value>.\n"
 	setHelpText += "Variables that can be set are:\n"
@@ -956,7 +1091,7 @@ func AddTargetCommands(cmd *cobra.Command) {
 	targetCmd.AddCommand(configCmd)
 
 	configShowCmd := &cobra.Command{
-		Use:   "show <target>",
+		Use:   "show <target> [target...]",
 		Short: "View a target's system configuration",
 		Long:  "View a target's system configuration",
 		Run:   targetConfigShowCmd,
@@ -967,6 +1102,18 @@ func AddTargetCommands(cmd *cobra.Command) {
 		return append(targetList(), unittestList()...)
 	})
 
+	configBriefCmd := &cobra.Command{
+		Use:   "brief <target> [target...]",
+		Short: "View a summary of target's system configuration",
+		Long:  "View a summary of target's system configuration",
+		Run:   targetConfigBriefCmd,
+	}
+
+	configCmd.AddCommand(configBriefCmd)
+	AddTabCompleteFn(configBriefCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
+
 	configInitCmd := &cobra.Command{
 		Use:   "init",
 		Short: "Populate a target's system configuration file",
diff --git a/vendor/mynewt.apache.org/newt/newt/cli/vars.go b/vendor/mynewt.apache.org/newt/newt/cli/vars.go
index 7ed25de5..cba62703 100644
--- a/vendor/mynewt.apache.org/newt/newt/cli/vars.go
+++ b/vendor/mynewt.apache.org/newt/newt/cli/vars.go
@@ -26,6 +26,7 @@ import (
 	"strings"
 
 	"mynewt.apache.org/newt/newt/interfaces"
+	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/util"
@@ -57,7 +58,7 @@ func settingValues(settingName string) ([]string, error) {
 	packs := project.GetProject().PackagesOfType(-1)
 	for _, pack := range packs {
 		settings :=
-			pack.(*pkg.LocalPackage).PkgV.GetStringSlice(settingName)
+			pack.(*pkg.LocalPackage).PkgY.GetValStringSlice(settingName, nil)
 
 		for _, setting := range settings {
 			settingMap[setting] = struct{}{}
@@ -78,7 +79,7 @@ func buildProfileValues() ([]string, error) {
 
 	packs := project.GetProject().PackagesOfType(pkg.PACKAGE_TYPE_COMPILER)
 	for _, pack := range packs {
-		v, err := util.ReadConfig(pack.(*pkg.LocalPackage).BasePath(),
+		v, err := newtutil.ReadConfig(pack.(*pkg.LocalPackage).BasePath(),
 			"compiler")
 		if err != nil {
 			return nil, err
diff --git a/vendor/mynewt.apache.org/newt/newt/compat/compat.go b/vendor/mynewt.apache.org/newt/newt/compat/compat.go
index 2e4355fe..1e3c363c 100644
--- a/vendor/mynewt.apache.org/newt/newt/compat/compat.go
+++ b/vendor/mynewt.apache.org/newt/newt/compat/compat.go
@@ -27,8 +27,8 @@ import (
 	"github.com/spf13/cast"
 
 	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
-	"mynewt.apache.org/newt/viper"
 )
 
 type NewtCompatCode int
@@ -104,9 +104,9 @@ func ParseNcTable(strMap map[string]string) (NewtCompatTable, error) {
 	return tbl, nil
 }
 
-func ReadNcMap(v *viper.Viper) (NewtCompatMap, error) {
+func ReadNcMap(yc ycfg.YCfg) (NewtCompatMap, error) {
 	mp := NewtCompatMap{}
-	ncMap := v.GetStringMap("repo.newt_compatibility")
+	ncMap := yc.GetValStringMap("repo.newt_compatibility", nil)
 
 	for k, v := range ncMap {
 		repoVer, err := newtutil.ParseVersion(k)
diff --git a/vendor/mynewt.apache.org/newt/newt/deprepo/deprepo.go b/vendor/mynewt.apache.org/newt/newt/deprepo/deprepo.go
new file mode 100644
index 00000000..75168d8d
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/deprepo/deprepo.go
@@ -0,0 +1,354 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+// deprepo: Package for resolving repo dependencies.
+package deprepo
+
+import (
+	"fmt"
+	"sort"
+	"strings"
+
+	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/repo"
+	"mynewt.apache.org/newt/util"
+)
+
+// [repo-name] => repo
+type RepoMap map[string]*repo.Repo
+
+// [repo-name] => repo-version
+type VersionMap map[string]newtutil.RepoVersion
+
+// [repo-name] => requirements-for-key-repo
+type RequirementMap map[string][]newtutil.RepoVersionReq
+
+// Indicates an inability to find an acceptable version of a particular repo.
+type Conflict struct {
+	RepoName string
+	Filters  []Filter
+}
+
+// Returns a sorted slice of all constituent repo names.
+func (vm VersionMap) SortedNames() []string {
+	names := make([]string, 0, len(vm))
+	for name, _ := range vm {
+		names = append(names, name)
+	}
+
+	sort.Strings(names)
+	return names
+}
+
+// Returns a slice of all constituent repos, sorted by name.
+func (rm RepoMap) Sorted() []*repo.Repo {
+	names := make([]string, 0, len(rm))
+	for n, _ := range rm {
+		names = append(names, n)
+	}
+	sort.Strings(names)
+
+	repos := make([]*repo.Repo, len(names))
+	for i, n := range names {
+		repos[i] = rm[n]
+	}
+
+	return repos
+}
+
+func (vm VersionMap) String() string {
+	s := ""
+
+	for repoName, ver := range vm {
+		if len(s) > 0 {
+			s += "\n"
+		}
+		s += fmt.Sprintf("%s:%s", repoName, ver.String())
+	}
+	return s
+}
+
+// Constructs a version matrix from the specified repos.  Each row in the
+// resulting matrix corresponds to a repo in the supplied slice.  Each row node
+// represents a single version of the repo.
+func BuildMatrix(repos []*repo.Repo, vm VersionMap) (Matrix, error) {
+	m := Matrix{}
+
+	for _, r := range repos {
+		if !r.IsLocal() {
+			vers, err := r.NormalizedVersions()
+			if err != nil {
+				return m, err
+			}
+			if err := m.AddRow(r.Name(), vers); err != nil {
+				return m, err
+			}
+		}
+	}
+
+	return m, nil
+}
+
+// Builds a repo dependency graph from the repo requirements expressed in the
+// `project.yml` file.
+func BuildDepGraph(repos RepoMap, rootReqs RequirementMap) (DepGraph, error) {
+	dg := DepGraph{}
+
+	// First, add the hard dependencies expressed in `project.yml`.
+	for repoName, verReqs := range rootReqs {
+		repo := repos[repoName]
+		normalizedReqs, err := repo.NormalizeVerReqs(verReqs)
+		if err != nil {
+			return nil, err
+		}
+
+		if err := dg.AddRootDep(repoName, normalizedReqs); err != nil {
+			return nil, err
+		}
+	}
+
+	// Add inter-repo dependencies to the graph.
+	for _, r := range repos.Sorted() {
+		nvers, err := r.NormalizedVersions()
+		if err != nil {
+			return nil, err
+		}
+		for _, v := range nvers {
+			deps := r.DepsForVersion(v)
+			reqMap := RequirementMap{}
+			for _, d := range deps {
+				depRepo := repos[d.Name]
+				verReqs, err := depRepo.NormalizeVerReqs(d.VerReqs)
+				if err != nil {
+					return nil, err
+				}
+				reqMap[d.Name] = verReqs
+			}
+			if err := dg.AddRepoVer(r.Name(), v, reqMap); err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return dg, nil
+}
+
+// Prunes unusable repo versions from the specified matrix.
+func PruneMatrix(m *Matrix, repos RepoMap, rootReqs RequirementMap) error {
+	pruned := map[*repo.RepoDependency]struct{}{}
+
+	// Removes versions of the depended-on package that fail to satisfy the
+	// dependent's requirements.  Each of the depended-on package's
+	// dependencies are then recursively visited.
+	var recurse func(dependentName string, dep *repo.RepoDependency) error
+	recurse = func(dependentName string, dep *repo.RepoDependency) error {
+		// Don't prune the same dependency twice; prevents infinite
+		// recursion.
+		if _, ok := pruned[dep]; ok {
+			return nil
+		}
+		pruned[dep] = struct{}{}
+
+		// Remove versions of this depended-on package that don't satisfy the
+		// dependency's version requirements.
+		r := repos[dep.Name]
+		normalizedReqs, err := r.NormalizeVerReqs(dep.VerReqs)
+		if err != nil {
+			return err
+		}
+		filter := Filter{
+			Name: dependentName,
+			Reqs: normalizedReqs,
+		}
+		m.ApplyFilter(dep.Name, filter)
+
+		// If there is only one version of the depended-on package left in the
+		// matrix, we can recursively call this function on all its
+		// dependencies.
+		//
+		// We don't do it, but it is possible to prune when there is more than
+		// one version remaining.  To accomplish this, we would collect the
+		// requirements from all versions, find their union, and remove
+		// depended-on packages that satisfy none of the requirements in the
+		// union.  The actual implementation (only prune when one version
+		// remains) is a simplified implementation of this general procedure.
+		// In exchange for simplicity, some unusable versions remain in the
+		// matrix that could have been pruned.  These unsuable versions must be
+		// evaluated unnecessarily when the matrix is being searched for an
+		// acceptable version set.
+		row := m.FindRow(r.Name())
+		if row != nil && len(row.Vers) == 1 {
+			ver := row.Vers[0]
+			commit, err := r.CommitFromVer(ver)
+			if err != nil {
+				return err
+			}
+			depRepo := repos[dep.Name]
+			for _, ddep := range depRepo.CommitDepMap()[commit] {
+				name := fmt.Sprintf("%s,%s", depRepo.Name(), ver.String())
+				if err := recurse(name, ddep); err != nil {
+					return err
+				}
+			}
+		}
+
+		return nil
+	}
+
+	// Prune versions that are guaranteed to be unusable.  Any repo version
+	// which doesn't satisfy a requirement in `project.yml` is a
+	// known-bad-version and can be removed.  These repos' dependencies can
+	// then be pruned in turn.
+	for repoName, reqs := range rootReqs {
+		if len(reqs) > 0 {
+			dep := &repo.RepoDependency{
+				Name:    repoName,
+				VerReqs: reqs,
+			}
+
+			if err := recurse("project.yml", dep); err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+// Produces an error describing the specified set of repo conflicts.
+func ConflictError(conflicts []Conflict) error {
+	s := ""
+
+	for _, c := range conflicts {
+		if s != "" {
+			s += "\n\n"
+		}
+
+		s += fmt.Sprintf("    Installation of repo \"%s\" is blocked:",
+			c.RepoName)
+
+		lines := []string{}
+		for _, f := range c.Filters {
+			lines = append(lines, fmt.Sprintf("\n    %30s requires %s %s",
+				f.Name, c.RepoName, newtutil.RepoVerReqsString(f.Reqs)))
+		}
+		sort.Strings(lines)
+		s += strings.Join(lines, "")
+	}
+
+	return util.NewNewtError("Repository conflicts:\n" + s)
+}
+
+// Searches a version matrix for a set of acceptable repo versions.  If there
+// isn't an acceptable set of versions, the set with the fewest conflicts is
+// returned.
+//
+// @param m                     Matrix containing all unpruned repo versions.
+// @param dg                    The repo dependency graph.
+//
+// @return VersionMap           The first perfect set of repo versions, or the
+//                                  closest match if there is no perfect set.
+// @return []string             nil if a perfect set was found, else the names
+//                                  of the repos that lack a suitable version
+//                                  in the returned version map.
+func findClosestMatch(m Matrix, dg DepGraph) (VersionMap, []string) {
+	// Tracks the best match seen so far.
+	type Best struct {
+		vm       VersionMap
+		failures []string
+	}
+	var best Best
+
+	for {
+		vm := m.CurVersions()
+		badRepos := dg.conflictingRepos(vm)
+		if len(badRepos) == 0 {
+			// Found a perfect match.  Return it.
+			return vm, nil
+		}
+
+		if best.failures == nil || len(badRepos) < len(best.failures) {
+			best.vm = vm
+			best.failures = badRepos
+		}
+
+		// Evaluate the next set of versions on the following iteration.
+		if !m.Increment() {
+			// All version sets evaluated.  Return the best match.
+			return best.vm, best.failures
+		}
+	}
+}
+
+// Finds the first set of repo versions which satisfies the dependency graph.
+// If there is no acceptable set, a slice of conflicts is returned instead.
+//
+// @param m                     Matrix containing all unpruned repo versions.
+// @param dg                    The repo dependency graph.
+// @return VersionMap           The first perfect set of repo versions, or nil
+//                                  if there is no perfect set.
+// @return []Conflict           nil if a perfect set was found, else the set of
+//                                  conflicts preventing a perfect match from
+//                                  being returned.
+func FindAcceptableVersions(m Matrix, dg DepGraph) (VersionMap, []Conflict) {
+	vm, failures := findClosestMatch(m, dg)
+	if len(failures) == 0 {
+		// No failures implies a perfect match was found.  Return it.
+		return vm, nil
+	}
+
+	// A perfect version set doesn't exist.  Generate the set of relevant
+	// conflicts and return it.
+	conflicts := make([]Conflict, len(failures))
+
+	// Build a reverse dependency graph.  This will make it easy to determine
+	// which version requirements are relevant to the failure.
+	rg := dg.Reverse()
+	for i, f := range failures {
+		conflict := Conflict{
+			RepoName: f,
+		}
+		for _, node := range rg[f] {
+			// Determine if this filter is responsible for any conflicts.
+			// Record the name of the filter if it applies.
+			var filterName string
+			if node.Name == rootDependencyName {
+				filterName = "project.yml"
+			} else {
+				// If the version of the repo in the closest-match version map
+				// is the same one that imposes this version requirement,
+				// include it in the conflict object.
+				if newtutil.CompareRepoVersions(vm[node.Name], node.Ver) == 0 {
+					filterName = fmt.Sprintf(
+						"%s,%s", node.Name, node.Ver.String())
+				}
+			}
+
+			if filterName != "" {
+				conflict.Filters = append(conflict.Filters, Filter{
+					Name: filterName,
+					Reqs: node.VerReqs,
+				})
+			}
+		}
+		conflicts[i] = conflict
+	}
+
+	return nil, conflicts
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/deprepo/graph.go b/vendor/mynewt.apache.org/newt/newt/deprepo/graph.go
new file mode 100644
index 00000000..cf720116
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/deprepo/graph.go
@@ -0,0 +1,229 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+// deprepo: Package for resolving repo dependencies.
+package deprepo
+
+import (
+	"fmt"
+	"sort"
+	"strings"
+
+	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/util"
+)
+
+// Describes a repo that depends on other repos.
+type Dependent struct {
+	Name string
+	Ver  newtutil.RepoVersion
+}
+
+const rootDependencyName = ""
+
+// Represents a top-level repo dependency (i.e., a repo specified in
+// `project.yml`).
+var rootDependent = Dependent{Name: rootDependencyName}
+
+// A single node in a repo dependency graph.
+type DepGraphNode struct {
+	// Name of depended-on repo.
+	Name string
+	// Expresses the versions of the repo that satisfy this dependency.
+	VerReqs []newtutil.RepoVersionReq
+}
+
+// A repo dependency graph.
+// Key: A repo with dependencies.
+// Value: The corresponding list of dependencies.
+type DepGraph map[Dependent][]DepGraphNode
+
+// A single node in a repo reverse dependency graph.
+type RevdepGraphNode struct {
+	// The name of the dependent repo.
+	Name string
+	// The version of the dependent repo.
+	Ver newtutil.RepoVersion
+	// The dependent's version requirements that apply to the graph key.
+	VerReqs []newtutil.RepoVersionReq
+}
+
+// A repo reverse dependency graph.
+// Key: A depended-on repo.
+// Value: The corresponding list of dependencies.
+type RevdepGraph map[string][]RevdepGraphNode
+
+func repoNameVerString(repoName string, ver newtutil.RepoVersion) string {
+	if repoName == rootDependencyName {
+		return "project.yml"
+	} else {
+		return fmt.Sprintf("%s-%s", repoName, ver.String())
+	}
+}
+
+func (dep *Dependent) String() string {
+	return repoNameVerString(dep.Name, dep.Ver)
+}
+
+func (dgn *DepGraphNode) String() string {
+	return fmt.Sprintf("%s,%s", dgn.Name,
+		newtutil.RepoVerReqsString(dgn.VerReqs))
+}
+
+func (dg DepGraph) String() string {
+	lines := make([]string, 0, len(dg))
+
+	for dependent, nodes := range dg {
+		line := fmt.Sprintf("%s:", dependent.String())
+		for _, node := range nodes {
+			line += fmt.Sprintf(" (%s)", node.String())
+		}
+
+		lines = append(lines, line)
+	}
+
+	sort.Strings(lines)
+	return strings.Join(lines, "\n")
+}
+
+func (rgn *RevdepGraphNode) String() string {
+	return fmt.Sprintf("%s,%s", repoNameVerString(rgn.Name, rgn.Ver),
+		newtutil.RepoVerReqsString(rgn.VerReqs))
+}
+
+func (rg RevdepGraph) String() string {
+	lines := make([]string, 0, len(rg))
+
+	for repoName, nodes := range rg {
+		line := fmt.Sprintf("%s:", repoName)
+		for _, node := range nodes {
+			line += fmt.Sprintf(" (%s)", node.String())
+		}
+
+		lines = append(lines, line)
+	}
+
+	sort.Strings(lines)
+	return strings.Join(lines, "\n")
+}
+
+// Adds all dependencies expressed by a single version of a repo.
+//
+// @param repoName              The name of the dependent repo.
+// @param repoVer               The version of the dependent repo.
+// @param reqMap                The dependency requirements of the specified
+//                                  repo version.
+func (dg DepGraph) AddRepoVer(repoName string, repoVer newtutil.RepoVersion,
+	reqMap RequirementMap) error {
+
+	dep := Dependent{
+		Name: repoName,
+		Ver:  repoVer,
+	}
+
+	if _, ok := dg[dep]; ok {
+		return util.FmtNewtError(
+			"Duplicate repo-version-pair in repo dependency graph: %s,%s",
+			repoName, repoVer.String())
+	}
+
+	for depName, depReqs := range reqMap {
+		dg[dep] = append(dg[dep], DepGraphNode{
+			Name:    depName,
+			VerReqs: depReqs,
+		})
+	}
+
+	return nil
+}
+
+// Adds a root dependency (i.e., required repo specified in `project.yml`).
+func (dg DepGraph) AddRootDep(repoName string,
+	verReqs []newtutil.RepoVersionReq) error {
+
+	rootDeps := dg[rootDependent]
+	for _, d := range rootDeps {
+		if d.Name == repoName {
+			return util.FmtNewtError(
+				"Duplicate root dependency repo dependency graph: %s",
+				repoName)
+		}
+	}
+
+	dg[rootDependent] = append(dg[rootDependent], DepGraphNode{
+		Name:    repoName,
+		VerReqs: verReqs,
+	})
+
+	return nil
+}
+
+// Reverses a dependency graph, forming a reverse dependency graph.
+//
+// A normal dependency graph expresses the following relationship:
+//     [dependent] => depended-on
+//
+// A reverse dependency graph expresses the following relationship:
+//     [depended-on] => dependent
+func (dg DepGraph) Reverse() RevdepGraph {
+	rg := RevdepGraph{}
+
+	for dependent, nodes := range dg {
+		for _, node := range nodes {
+			rg[node.Name] = append(rg[node.Name], RevdepGraphNode{
+				Name:    dependent.Name,
+				Ver:     dependent.Ver,
+				VerReqs: node.VerReqs,
+			})
+		}
+	}
+
+	return rg
+}
+
+// Identifies repos which cannot satisfy all their dependents.  For example, if
+// `project.yml` requires X1 and Y2, but Y2 requires X2, then X is a
+// conflicting repo (no overlap in requirement sets).
+func (dg DepGraph) conflictingRepos(vm VersionMap) []string {
+	repoNames := make([]string, 0, len(vm))
+	for name, _ := range vm {
+		repoNames = append(repoNames, name)
+	}
+	sort.Strings(repoNames)
+
+	badRepoMap := map[string]struct{}{}
+	for _, repoName := range repoNames {
+		dependentVer := vm[repoName]
+		dependent := Dependent{repoName, dependentVer}
+		for _, node := range dg[dependent] {
+			dependeeVer := vm[node.Name]
+			if !dependeeVer.SatisfiesAll(node.VerReqs) {
+				badRepoMap[node.Name] = struct{}{}
+			}
+		}
+	}
+
+	badRepoSlice := make([]string, 0, len(badRepoMap))
+	for repoName, _ := range badRepoMap {
+		badRepoSlice = append(badRepoSlice, repoName)
+	}
+	sort.Strings(badRepoSlice)
+
+	return badRepoSlice
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/deprepo/matrix.go b/vendor/mynewt.apache.org/newt/newt/deprepo/matrix.go
new file mode 100644
index 00000000..97dc9826
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/deprepo/matrix.go
@@ -0,0 +1,172 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+// deprepo: Package for resolving repo dependencies.
+package deprepo
+
+import (
+	"fmt"
+	"strings"
+
+	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/util"
+)
+
+// Eliminates non-matching version numbers when applied to a matrix row.
+type Filter struct {
+	Name string
+	Reqs []newtutil.RepoVersionReq
+}
+
+// Contains all versions of a single repo.  These version numbers are read from
+// the repo's `repository.yml` file.  Only normalized versions are included.
+type MatrixRow struct {
+	// The name of the repo that the row corresponds to.
+	RepoName string
+
+	// All normalized versions of the repo.
+	Vers []newtutil.RepoVersion
+
+	// Indicates the version of this repo currently being evaluated for
+	// conflicts.
+	VerIdx int
+
+	// All filters that have been applied to this row.  This is only used
+	// during reporting.
+	Filters []Filter
+}
+
+// Contains all versions of a set of repos.  Each row correponds to a single
+// repo.  Each element within a row represents a single version of the repo.
+//
+// The Matrix type serves two purposes:
+//
+// 1. Simple lookup: Provides a convenient means of determining whether a
+// specific version of a repo exists.
+//
+// 2. Requirements matching: The client can cycle through all combinations of
+// repo versions via the `Increment()` function.  Each combination can be
+// exported as a version map via the `CurVersions()` function.  By evaluating
+// each version map against a set of requirements, the client can find the set
+// of repo versions to upgrade to.
+type Matrix struct {
+	rows []MatrixRow
+}
+
+func (m *Matrix) String() string {
+	lines := make([]string, len(m.rows))
+
+	for i, row := range m.rows {
+		line := fmt.Sprintf("%s:", row.RepoName)
+		for _, v := range row.Vers {
+			line += fmt.Sprintf(" %s", v.String())
+		}
+
+		lines[i] = line
+	}
+
+	return strings.Join(lines, "\n")
+}
+
+// Adjusts the matrix to point to the next possible set of repo versions.
+//
+// @return bool                 true if the matrix points to a new set;
+//                              false if the matrix wrapped around to the first
+//                                  set.
+func (m *Matrix) Increment() bool {
+	for i := range m.rows {
+		row := &m.rows[i]
+
+		row.VerIdx++
+		if row.VerIdx < len(row.Vers) {
+			return true
+		}
+
+		// No more versions left for this repo; proceed to next.
+		row.VerIdx = 0
+	}
+
+	// All version combinations evaluated.
+	return false
+}
+
+func (m *Matrix) findRowIdx(repoName string) int {
+	for i, row := range m.rows {
+		if row.RepoName == repoName {
+			return i
+		}
+	}
+
+	return -1
+}
+
+func (m *Matrix) FindRow(repoName string) *MatrixRow {
+	idx := m.findRowIdx(repoName)
+	if idx == -1 {
+		return nil
+	}
+	return &m.rows[idx]
+}
+
+func (m *Matrix) AddRow(repoName string,
+	vers []newtutil.RepoVersion) error {
+
+	if m.findRowIdx(repoName) != -1 {
+		return util.FmtNewtError("Duplicate repo \"%s\" in repo matrix",
+			repoName)
+	}
+
+	m.rows = append(m.rows, MatrixRow{
+		RepoName: repoName,
+		Vers:     newtutil.SortedVersionsDesc(vers),
+	})
+
+	return nil
+}
+
+// Removes all non-matching versions of the specified repo from the matrix.
+func (m *Matrix) ApplyFilter(repoName string, filter Filter) {
+	rowIdx := m.findRowIdx(repoName)
+	if rowIdx == -1 {
+		return
+	}
+	row := &m.rows[rowIdx]
+
+	goodVers := []newtutil.RepoVersion{}
+	for _, v := range row.Vers {
+		if v.SatisfiesAll(filter.Reqs) {
+			goodVers = append(goodVers, v)
+		}
+	}
+
+	row.Vers = goodVers
+	row.Filters = append(row.Filters, filter)
+}
+
+// Constructs a version map from the matrix's current state.
+func (m *Matrix) CurVersions() VersionMap {
+	vm := make(VersionMap, len(m.rows))
+	for _, row := range m.rows {
+		if len(row.Vers) > 0 {
+			vm[row.RepoName] = row.Vers[row.VerIdx]
+		}
+	}
+
+	return vm
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/downloader/downloader.go b/vendor/mynewt.apache.org/newt/newt/downloader/downloader.go
index b6968a63..58d8cda9 100644
--- a/vendor/mynewt.apache.org/newt/newt/downloader/downloader.go
+++ b/vendor/mynewt.apache.org/newt/newt/downloader/downloader.go
@@ -21,33 +21,66 @@ package downloader
 
 import (
 	"fmt"
-	"io"
 	"io/ioutil"
-	"net/http"
 	"os"
 	"os/exec"
 	"path/filepath"
+	"sort"
 	"strings"
 
 	log "github.com/Sirupsen/logrus"
 
-	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/settings"
 	"mynewt.apache.org/newt/util"
 )
 
+type DownloaderCommitType int
+
+const (
+	COMMIT_TYPE_BRANCH DownloaderCommitType = iota
+	COMMIT_TYPE_TAG
+	COMMIT_TYPE_HASH
+)
+
 type Downloader interface {
-	FetchFile(name string, dest string) error
-	Branch() string
-	SetBranch(branch string)
-	DownloadRepo(branch string) (string, error)
+	// Fetches all remotes and downloads the specified file.
+	FetchFile(commit string, path string, filename string, dstDir string) error
+
+	// Clones the repo and checks out the specified commit.
+	Clone(commit string, dstPath string) error
+
+	// Determines the equivalent commit hash for the specified commit string.
+	HashFor(path string, commit string) (string, error)
+
+	// Collects all commits that are equivalent to the specified commit string
+	// (i.e., 1 hash, n tags, and n branches).
+	CommitsFor(path string, commit string) ([]string, error)
+
+	// Fetches all remotes and merges the specified branch into the local repo.
+	Pull(path string, branchName string) error
+
+	// Indicates whether the repo is in a clean or dirty state.
+	DirtyState(path string) (string, error)
+
+	// Determines the type of the specified commit.
+	CommitType(path string, commit string) (DownloaderCommitType, error)
+
+	// Configures the `origin` remote with the correct URL, according the the
+	// user's `project.yml` file and / or the repo dependency lists.
+	FixupOrigin(path string) error
+
+	// Retrieves the name of the currently checked out branch, or "" if no
+	// branch is checked out.
 	CurrentBranch(path string) (string, error)
-	UpdateRepo(path string, branchName string) error
-	CleanupRepo(path string, branchName string) error
-	LocalDiff(path string) ([]byte, error)
+
+	// Retrieves the name of the remote branch being tracked by the specified
+	// local branch, or "" if there is no tracked remote branch.
+	UpstreamFor(repoDir string, branch string) (string, error)
 }
 
 type GenericDownloader struct {
-	branch string
+	// Whether 'origin' has been fetched during this run.
+	fetched bool
 }
 
 type GithubDownloader struct {
@@ -67,6 +100,11 @@ type GithubDownloader struct {
 	PasswordEnv string
 }
 
+type GitDownloader struct {
+	GenericDownloader
+	Url string
+}
+
 type LocalDownloader struct {
 	GenericDownloader
 
@@ -74,28 +112,36 @@ type LocalDownloader struct {
 	Path string
 }
 
-func executeGitCommand(dir string, cmd []string) ([]byte, error) {
+func gitPath() (string, error) {
+	gitPath, err := exec.LookPath("git")
+	if err != nil {
+		return "", util.NewNewtError(fmt.Sprintf("Can't find git binary: %s\n",
+			err.Error()))
+	}
+
+	return filepath.ToSlash(gitPath), nil
+}
+
+func executeGitCommand(dir string, cmd []string, logCmd bool) ([]byte, error) {
 	wd, err := os.Getwd()
 	if err != nil {
 		return nil, util.NewNewtError(err.Error())
 	}
 
-	gitPath, err := exec.LookPath("git")
+	gp, err := gitPath()
 	if err != nil {
-		return nil, util.NewNewtError(fmt.Sprintf("Can't find git binary: %s\n",
-			err.Error()))
+		return nil, err
 	}
-	gitPath = filepath.ToSlash(gitPath)
 
 	if err := os.Chdir(dir); err != nil {
-		return nil, util.NewNewtError(err.Error())
+		return nil, util.ChildNewtError(err)
 	}
 
 	defer os.Chdir(wd)
 
-	gitCmd := []string{gitPath}
+	gitCmd := []string{gp}
 	gitCmd = append(gitCmd, cmd...)
-	output, err := util.ShellCommand(gitCmd, nil)
+	output, err := util.ShellCommandLimitDbgOutput(gitCmd, nil, logCmd, -1)
 	if err != nil {
 		return nil, err
 	}
@@ -103,16 +149,43 @@ func executeGitCommand(dir string, cmd []string) ([]byte, error) {
 	return output, nil
 }
 
-func isTag(repoDir string, branchName string) bool {
-	cmd := []string{"tag", "--list"}
-	output, _ := executeGitCommand(repoDir, cmd)
-	return strings.Contains(string(output), branchName)
+func commitExists(repoDir string, commit string) bool {
+	cmd := []string{
+		"show-ref",
+		"--verify",
+		"--quiet",
+		"refs/heads/" + commit,
+	}
+	_, err := executeGitCommand(repoDir, cmd, true)
+	return err == nil
 }
 
-func branchExists(repoDir string, branchName string) bool {
-	cmd := []string{"show-ref", "--verify", "--quiet", "refs/heads/" + branchName}
-	_, err := executeGitCommand(repoDir, cmd)
-	return err == nil
+func initSubmodules(path string) error {
+	cmd := []string{
+		"submodule",
+		"init",
+	}
+
+	_, err := executeGitCommand(path, cmd, true)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func updateSubmodules(path string) error {
+	cmd := []string{
+		"submodule",
+		"update",
+	}
+
+	_, err := executeGitCommand(path, cmd, true)
+	if err != nil {
+		return err
+	}
+
+	return nil
 }
 
 // checkout does checkout a branch, or create a new branch from a tag name
@@ -120,212 +193,457 @@ func branchExists(repoDir string, branchName string) bool {
 // handling and result in dettached from HEAD state.
 func checkout(repoDir string, commit string) error {
 	var cmd []string
-	if isTag(repoDir, commit) && !branchExists(repoDir, commit) {
+	ct, err := commitType(repoDir, commit)
+	if err != nil {
+		return err
+	}
+
+	full, err := remoteCommitName(repoDir, commit)
+	if err != nil {
+		return err
+	}
+
+	if ct == COMMIT_TYPE_TAG {
 		util.StatusMessage(util.VERBOSITY_VERBOSE, "Will create new branch %s"+
-			" from tag %s\n", commit, "tags/"+commit)
+			" from %s\n", commit, full)
 		cmd = []string{
 			"checkout",
-			"tags/" + commit,
+			full,
 			"-b",
 			commit,
 		}
 	} else {
-		util.StatusMessage(util.VERBOSITY_VERBOSE, "Will checkout branch %s\n",
-			commit)
+		util.StatusMessage(util.VERBOSITY_VERBOSE, "Will checkout %s\n", full)
 		cmd = []string{
 			"checkout",
 			commit,
 		}
 	}
-	_, err := executeGitCommand(repoDir, cmd)
-	return err
+	if _, err := executeGitCommand(repoDir, cmd, true); err != nil {
+		return err
+	}
+
+	// Always initialize and update submodules on checkout.  This prevents the
+	// repo from being in a modified "(new commits)" state immediately after
+	// switching commits.  If the submodules have already been updated, this
+	// does not generate any network activity.
+	if err := initSubmodules(repoDir); err != nil {
+		return err
+	}
+	if err := updateSubmodules(repoDir); err != nil {
+		return err
+	}
+
+	return nil
 }
 
-// mergeBranches applies upstream changes to the local copy and must be
+// rebase applies upstream changes to the local copy and must be
 // preceeded by a "fetch" to achieve any meaningful result.
-func mergeBranches(repoDir string) {
-	branches := []string{"master", "develop"}
-	for _, branch := range branches {
-		err := checkout(repoDir, branch)
-		if err != nil {
-			continue
+func rebase(repoDir string, commit string) error {
+	if err := checkout(repoDir, commit); err != nil {
+		return err
+	}
+
+	// We want to rebase the remote version of this branch.
+	full, err := remoteCommitName(repoDir, commit)
+	if err != nil {
+		return err
+	}
+
+	cmd := []string{
+		"rebase",
+		full}
+	if _, err := executeGitCommand(repoDir, cmd, true); err != nil {
+		util.StatusMessage(util.VERBOSITY_VERBOSE,
+			"Merging changes from %s: %s\n", full, err)
+		return err
+	}
+
+	util.StatusMessage(util.VERBOSITY_VERBOSE,
+		"Merging changes from %s\n", full)
+	return nil
+}
+
+func mergeBase(repoDir string, commit string) (string, error) {
+	cmd := []string{
+		"merge-base",
+		commit,
+		commit,
+	}
+	o, err := executeGitCommand(repoDir, cmd, true)
+	if err != nil {
+		return "", err
+	}
+
+	return strings.TrimSpace(string(o)), nil
+}
+
+func branchExists(repoDir string, branchName string) bool {
+	cmd := []string{
+		"show-ref",
+		"--verify",
+		"--quiet",
+		"refs/heads/" + branchName,
+	}
+	_, err := executeGitCommand(repoDir, cmd, true)
+	return err == nil
+}
+
+func commitType(repoDir string, commit string) (DownloaderCommitType, error) {
+	if commit == "HEAD" {
+		return COMMIT_TYPE_HASH, nil
+	}
+
+	if _, err := mergeBase(repoDir, commit); err == nil {
+		// Distinguish local branch from hash.
+		if branchExists(repoDir, commit) {
+			return COMMIT_TYPE_BRANCH, nil
+		} else {
+			return COMMIT_TYPE_HASH, nil
 		}
-		_, err = executeGitCommand(repoDir, []string{"merge", "origin/" + branch})
-		if err != nil {
-			util.StatusMessage(util.VERBOSITY_VERBOSE, "Merging changes from origin/%s: %s\n",
-				branch, err)
+	}
+
+	if _, err := mergeBase(repoDir, "tags/"+commit); err == nil {
+		return COMMIT_TYPE_TAG, nil
+	}
+
+	return DownloaderCommitType(-1), util.FmtNewtError(
+		"Cannot determine commit type of \"%s\"", commit)
+}
+
+func upstreamFor(path string, commit string) (string, error) {
+	cmd := []string{
+		"rev-parse",
+		"--abbrev-ref",
+		"--symbolic-full-name",
+		commit + "@{u}",
+	}
+
+	up, err := executeGitCommand(path, cmd, true)
+	if err != nil {
+		if !util.IsExit(err) {
+			return "", err
 		} else {
-			util.StatusMessage(util.VERBOSITY_VERBOSE, "Merging changes from origin/%s\n",
-				branch)
+			return "", nil
 		}
-		// XXX: ignore error, probably resulting from a branch not available at
-		//      origin anymore.
 	}
+
+	return strings.TrimSpace(string(up)), nil
 }
 
-func fetch(repoDir string) error {
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "Fetching new remote branches/tags\n")
-	_, err := executeGitCommand(repoDir, []string{"fetch", "--tags"})
-	return err
+func remoteCommitName(path string, commit string) (string, error) {
+	ct, err := commitType(path, commit)
+	if err != nil {
+		return "", err
+	}
+
+	switch ct {
+	case COMMIT_TYPE_BRANCH:
+		rmt, err := upstreamFor(path, commit)
+		if err != nil {
+			return "", err
+		}
+		if rmt == "" {
+			return "",
+				util.FmtNewtError("No remote upstream for branch \"%s\"",
+					commit)
+		}
+		return rmt, nil
+	case COMMIT_TYPE_TAG:
+		return "tags/" + commit, nil
+	case COMMIT_TYPE_HASH:
+		return commit, nil
+	default:
+		return "", util.FmtNewtError("unknown commit type: %d", int(ct))
+	}
 }
 
-// stash saves current changes locally and returns if a new stash was
-// created (if there where no changes, there's no need to stash)
-func stash(repoDir string) (bool, error) {
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "Stashing local changes\n")
-	output, err := executeGitCommand(repoDir, []string{"stash"})
+func showFile(
+	path string, branch string, filename string, dstDir string) error {
+
+	if err := os.MkdirAll(dstDir, os.ModePerm); err != nil {
+		return util.ChildNewtError(err)
+	}
+
+	full, err := remoteCommitName(path, branch)
 	if err != nil {
-		return false, err
+		return err
 	}
-	return strings.Contains(string(output), "Saved"), nil
+
+	cmd := []string{
+		"show",
+		fmt.Sprintf("%s:%s", full, filename),
+	}
+
+	dstPath := fmt.Sprintf("%s/%s", dstDir, filename)
+	log.Debugf("Fetching file %s to %s", filename, dstPath)
+	data, err := executeGitCommand(path, cmd, true)
+	if err != nil {
+		return err
+	}
+
+	if err := ioutil.WriteFile(dstPath, data, os.ModePerm); err != nil {
+		return util.ChildNewtError(err)
+	}
+
+	return nil
 }
 
-func stashPop(repoDir string) error {
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "Un-stashing local changes\n")
-	_, err := executeGitCommand(repoDir, []string{"stash", "pop"})
-	return err
+func getRemoteUrl(path string, remote string) (string, error) {
+	cmd := []string{
+		"remote",
+		"get-url",
+		remote,
+	}
+
+	o, err := executeGitCommand(path, cmd, true)
+	if err != nil {
+		return "", err
+	}
+
+	return strings.TrimSpace(string(o)), nil
 }
 
-func clean(repoDir string) error {
-	_, err := executeGitCommand(repoDir, []string{"clean", "-f"})
-	return err
+func setRemoteUrlCmd(remote string, url string) []string {
+	return []string{
+		"remote",
+		"set-url",
+		remote,
+		url,
+	}
 }
 
-func (gd *GenericDownloader) Branch() string {
-	return gd.branch
+func setRemoteUrl(path string, remote string, url string, logCmd bool) error {
+	cmd := setRemoteUrlCmd(remote, url)
+	_, err := executeGitCommand(path, cmd, logCmd)
+	return err
 }
 
-func (gd *GenericDownloader) SetBranch(branch string) {
-	gd.branch = branch
+func warnWrongOriginUrl(path string, curUrl string, goodUrl string) {
+	util.StatusMessage(util.VERBOSITY_QUIET,
+		"WARNING: Repo's \"origin\" remote points to unexpected URL: "+
+			"%s; correcting it to %s.  Repo contents may be incorrect.\n",
+		curUrl, goodUrl)
 }
 
-func (gd *GenericDownloader) TempDir() (string, error) {
-	dir, err := ioutil.TempDir("", "newt-tmp")
-	return dir, err
+func (gd *GenericDownloader) CommitType(
+	path string, commit string) (DownloaderCommitType, error) {
+
+	return commitType(path, commit)
 }
 
-func (gd *GithubDownloader) password() string {
-	if gd.Password != "" {
-		return gd.Password
-	} else if gd.PasswordEnv != "" {
-		return os.Getenv(gd.PasswordEnv)
-	} else {
-		return ""
+func (gd *GenericDownloader) HashFor(path string, commit string) (string, error) {
+	full, err := remoteCommitName(path, commit)
+	if err != nil {
+		return "", err
+	}
+	cmd := []string{"rev-parse", full}
+	o, err := executeGitCommand(path, cmd, true)
+	if err != nil {
+		return "", err
 	}
+
+	return strings.TrimSpace(string(o)), nil
 }
 
-func (gd *GithubDownloader) FetchFile(name string, dest string) error {
-	var url string
-	if gd.Server != "" {
-		// Use the github API
-		url = fmt.Sprintf("https://%s/api/v3/repos/%s/%s/%s?ref=%s", gd.Server, gd.User, gd.Repo, name, gd.Branch())
-	} else {
-		// The public github API is ratelimited. Avoid rate limit issues with the raw endpoint.
-		url = fmt.Sprintf("https://raw.githubusercontent.com/%s/%s/%s/%s", gd.User, gd.Repo, gd.Branch(), name)
+func (gd *GenericDownloader) CommitsFor(
+	path string, commit string) ([]string, error) {
+
+	// Hash.
+	hash, err := gd.HashFor(path, commit)
+	if err != nil {
+		return nil, err
 	}
 
-	req, err := http.NewRequest("GET", url, nil)
-	req.Header.Add("Accept", "application/vnd.github.v3.raw")
+	// Branches and tags.
+	cmd := []string{
+		"for-each-ref",
+		"--format=%(refname:short)",
+		"--points-at",
+		hash,
+	}
+	o, err := executeGitCommand(path, cmd, true)
+	if err != nil {
+		return nil, err
+	}
 
-	pw := gd.password()
-	if pw != "" {
-		// XXX: Add command line option to include password in log.
-		log.Debugf("Using basic auth; login=%s", gd.Login)
-		req.SetBasicAuth(gd.Login, pw)
+	lines := []string{hash}
+	text := strings.TrimSpace(string(o))
+	if text != "" {
+		lines = append(lines, strings.Split(text, "\n")...)
 	}
 
-	log.Debugf("Fetching file %s (url: %s) to %s", name, url, dest)
-	client := &http.Client{}
-	rsp, err := client.Do(req)
+	sort.Strings(lines)
+	return lines, nil
+}
+
+func (gd *GenericDownloader) CurrentBranch(path string) (string, error) {
+	cmd := []string{
+		"rev-parse",
+		"--abbrev-ref",
+		"HEAD",
+	}
+	o, err := executeGitCommand(path, cmd, true)
 	if err != nil {
-		return util.NewNewtError(err.Error())
-	}
-	defer rsp.Body.Close()
-
-	if rsp.StatusCode != http.StatusOK {
-		errMsg := fmt.Sprintf("Failed to download '%s'; status=%s",
-			url, rsp.Status)
-		switch rsp.StatusCode {
-		case http.StatusNotFound:
-			errMsg += "; URL incorrect or repository private?"
-		case http.StatusUnauthorized:
-			errMsg += "; credentials incorrect?"
-		}
+		return "", err
+	}
 
-		return util.NewNewtError(errMsg)
+	s := strings.TrimSpace(string(o))
+	if s == "HEAD" {
+		return "", nil
+	} else {
+		return s, nil
 	}
+}
 
-	handle, err := os.Create(dest)
-	if err != nil {
-		return util.NewNewtError(err.Error())
+func (gd *GenericDownloader) UpstreamFor(repoDir string,
+	branch string) (string, error) {
+
+	return upstreamFor(repoDir, branch)
+}
+
+// Fetches the downloader's origin remote if it hasn't been fetched yet during
+// this run.
+func (gd *GenericDownloader) cachedFetch(fn func() error) error {
+	if gd.fetched {
+		return nil
 	}
-	defer handle.Close()
 
-	_, err = io.Copy(handle, rsp.Body)
+	if err := fn(); err != nil {
+		return err
+	}
 
+	gd.fetched = true
 	return nil
 }
 
-func (gd *GithubDownloader) CurrentBranch(path string) (string, error) {
-	cmd := []string{"rev-parse", "--abbrev-ref", "HEAD"}
-	branch, err := executeGitCommand(path, cmd)
-	return strings.Trim(string(branch), "\r\n"), err
-}
+// Indicates whether the specified git repo is in a clean or dirty state.
+//
+// @param path                  The path of the git repo to check.
+//
+// @return string               Text describing repo's dirty state, or "" if
+//                                  clean.
+// @return error                Error.
+func (gd *GenericDownloader) DirtyState(path string) (string, error) {
+	// Check for local changes.
+	cmd := []string{
+		"diff",
+		"--name-only",
+	}
 
-func (gd *GithubDownloader) UpdateRepo(path string, branchName string) error {
-	err := fetch(path)
+	o, err := executeGitCommand(path, cmd, true)
 	if err != nil {
-		return err
+		return "", err
+	}
+
+	if len(o) > 0 {
+		return "local changes", nil
+	}
+
+	// Check for staged changes.
+	cmd = []string{
+		"diff",
+		"--name-only",
+		"--staged",
 	}
 
-	stashed, err := stash(path)
+	o, err = executeGitCommand(path, cmd, true)
 	if err != nil {
-		return err
+		return "", err
 	}
 
-	mergeBranches(path)
+	if len(o) > 0 {
+		return "staged changes", nil
+	}
 
-	err = checkout(path, branchName)
+	// If on a branch, check for unpushed commits.
+	branch, err := gd.CurrentBranch(path)
 	if err != nil {
-		return err
+		return "", err
 	}
 
-	if stashed {
-		return stashPop(path)
+	if branch != "" {
+		cmd = []string{
+			"rev-list",
+			"@{u}..",
+		}
+
+		o, err = executeGitCommand(path, cmd, true)
+		if err != nil {
+			return "", err
+		}
+
+		if len(o) > 0 {
+			return "unpushed commits", nil
+		}
 	}
 
-	return nil
+	return "", nil
 }
 
-func (gd *GithubDownloader) CleanupRepo(path string, branchName string) error {
-	_, err := stash(path)
-	if err != nil {
-		return err
-	}
+func (gd *GithubDownloader) fetch(repoDir string) error {
+	return gd.cachedFetch(func() error {
+		util.StatusMessage(util.VERBOSITY_VERBOSE, "Fetching repo %s\n",
+			gd.Repo)
 
-	err = clean(path)
-	if err != nil {
+		_, err := gd.authenticatedCommand(repoDir, []string{"fetch", "--tags"})
 		return err
+	})
+}
+
+func (gd *GithubDownloader) password() string {
+	if gd.Password != "" {
+		return gd.Password
+	} else if gd.PasswordEnv != "" {
+		return os.Getenv(gd.PasswordEnv)
+	} else {
+		return ""
 	}
+}
 
-	// TODO: needs handling of non-tracked files
+func (gd *GithubDownloader) authenticatedCommand(path string,
+	args []string) ([]byte, error) {
 
-	return gd.UpdateRepo(path, branchName)
+	if err := gd.setRemoteAuth(path); err != nil {
+		return nil, err
+	}
+	defer gd.clearRemoteAuth(path)
+
+	return executeGitCommand(path, args, true)
 }
 
-func (gd *GithubDownloader) LocalDiff(path string) ([]byte, error) {
-	return executeGitCommand(path, []string{"diff"})
+func (gd *GithubDownloader) FetchFile(
+	commit string, path string, filename string, dstDir string) error {
+
+	if err := gd.fetch(path); err != nil {
+		return err
+	}
+
+	if err := showFile(path, commit, filename, dstDir); err != nil {
+		return err
+	}
+
+	return nil
 }
 
-func (gd *GithubDownloader) DownloadRepo(commit string) (string, error) {
-	// Get a temporary directory, and copy the repository into that directory.
-	tmpdir, err := ioutil.TempDir("", "newt-repo")
+func (gd *GithubDownloader) Pull(path string, branchName string) error {
+	err := gd.fetch(path)
 	if err != nil {
-		return "", err
+		return err
 	}
 
-	// Currently only the master branch is supported.
-	branch := "master"
+	// Ignore error, probably resulting from a branch not available at origin
+	// anymore.
+	rebase(path, branchName)
+
+	if err := checkout(path, branchName); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (gd *GithubDownloader) remoteUrls() (string, string) {
 	server := "github.com"
 
 	if gd.Server != "" {
@@ -333,121 +651,257 @@ func (gd *GithubDownloader) DownloadRepo(commit string) (string, error) {
 	}
 
 	var auth string
-	var publicAuth string
 	if gd.Login != "" {
 		pw := gd.password()
 		auth = fmt.Sprintf("%s:%s@", gd.Login, pw)
-		if pw == "" {
-			publicAuth = auth
-		} else {
-			publicAuth = fmt.Sprintf("%s:<password-hidden>@", gd.Login)
-		}
 	}
-	url := fmt.Sprintf("https://%s%s/%s/%s.git", auth, server, gd.User, gd.Repo)
-	publicUrl := fmt.Sprintf("https://%s%s/%s/%s.git", publicAuth, server, gd.User, gd.Repo)
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "Downloading "+
-		"repository %s (branch: %s; commit: %s) at %s\n", gd.Repo, branch,
-		commit, publicUrl)
 
-	gitPath, err := exec.LookPath("git")
+	url := fmt.Sprintf("https://%s%s/%s/%s.git", auth, server, gd.User,
+		gd.Repo)
+	publicUrl := fmt.Sprintf("https://%s/%s/%s.git", server, gd.User, gd.Repo)
+
+	return url, publicUrl
+}
+
+func (gd *GithubDownloader) setOriginUrl(path string, url string) error {
+	// Hide password in logged command.
+	safeUrl := url
+	pw := gd.password()
+	if pw != "" {
+		safeUrl = strings.Replace(safeUrl, pw, "<password-hidden>", -1)
+	}
+	util.LogShellCmd(setRemoteUrlCmd("origin", safeUrl), nil)
+
+	return setRemoteUrl(path, "origin", url, false)
+}
+
+func (gd *GithubDownloader) clearRemoteAuth(path string) error {
+	url, publicUrl := gd.remoteUrls()
+	if url == publicUrl {
+		return nil
+	}
+
+	return gd.setOriginUrl(path, publicUrl)
+}
+
+func (gd *GithubDownloader) setRemoteAuth(path string) error {
+	url, publicUrl := gd.remoteUrls()
+	if url == publicUrl {
+		return nil
+	}
+
+	return gd.setOriginUrl(path, url)
+}
+
+func (gd *GithubDownloader) Clone(commit string, dstPath string) error {
+	// Currently only the master branch is supported.
+	branch := "master"
+
+	url, publicUrl := gd.remoteUrls()
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"Downloading repository %s (commit: %s) from %s\n",
+		gd.Repo, commit, publicUrl)
+
+	gp, err := gitPath()
 	if err != nil {
-		os.RemoveAll(tmpdir)
-		return "", util.NewNewtError(fmt.Sprintf("Can't find git binary: %s\n",
-			err.Error()))
+		return err
 	}
-	gitPath = filepath.ToSlash(gitPath)
 
 	// Clone the repository.
 	cmd := []string{
-		gitPath,
+		gp,
 		"clone",
 		"-b",
 		branch,
 		url,
-		tmpdir,
+		dstPath,
 	}
 
 	if util.Verbosity >= util.VERBOSITY_VERBOSE {
-		if err := util.ShellInteractiveCommand(cmd, nil); err != nil {
-			os.RemoveAll(tmpdir)
-			return "", err
-		}
+		err = util.ShellInteractiveCommand(cmd, nil)
 	} else {
-		if _, err := util.ShellCommand(cmd, nil); err != nil {
-			return "", err
-		}
+		_, err = util.ShellCommand(cmd, nil)
+	}
+	if err != nil {
+		return err
 	}
 
+	defer gd.clearRemoteAuth(dstPath)
+
 	// Checkout the specified commit.
-	if err := checkout(tmpdir, commit); err != nil {
-		return "", err
+	if err := checkout(dstPath, commit); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (gd *GithubDownloader) FixupOrigin(path string) error {
+	curUrl, err := getRemoteUrl(path, "origin")
+	if err != nil {
+		return err
+	}
+
+	// Use the public URL, i.e., hide the login and password.
+	_, publicUrl := gd.remoteUrls()
+	if curUrl == publicUrl {
+		return nil
 	}
 
-	return tmpdir, nil
+	warnWrongOriginUrl(path, curUrl, publicUrl)
+	return gd.setOriginUrl(path, publicUrl)
 }
 
 func NewGithubDownloader() *GithubDownloader {
 	return &GithubDownloader{}
 }
 
-func (ld *LocalDownloader) FetchFile(name string, dest string) error {
-	srcPath := ld.Path + "/" + name
+func (gd *GitDownloader) fetch(repoDir string) error {
+	return gd.cachedFetch(func() error {
+		util.StatusMessage(util.VERBOSITY_VERBOSE, "Fetching repo %s\n",
+			gd.Url)
+		_, err := executeGitCommand(repoDir, []string{"fetch", "--tags"}, true)
+		return err
+	})
+}
+
+func (gd *GitDownloader) FetchFile(
+	commit string, path string, filename string, dstDir string) error {
+
+	if err := gd.fetch(path); err != nil {
+		return err
+	}
 
-	log.Debugf("Fetching file %s to %s", srcPath, dest)
-	if err := util.CopyFile(srcPath, dest); err != nil {
+	if err := showFile(path, commit, filename, dstDir); err != nil {
 		return err
 	}
 
 	return nil
 }
 
-func (ld *LocalDownloader) CurrentBranch(path string) (string, error) {
-	cmd := []string{"rev-parse", "--abbrev-ref", "HEAD"}
-	branch, err := executeGitCommand(path, cmd)
-	return strings.Trim(string(branch), "\r\n"), err
+func (gd *GitDownloader) Pull(path string, branchName string) error {
+	err := gd.fetch(path)
+	if err != nil {
+		return err
+	}
+
+	// Ignore error, probably resulting from a branch not available at origin
+	// anymore.
+	rebase(path, branchName)
+
+	if err := checkout(path, branchName); err != nil {
+		return err
+	}
+
+	return nil
 }
 
-// NOTE: intentionally always error...
-func (ld *LocalDownloader) UpdateRepo(path string, branchName string) error {
-	return util.NewNewtError(fmt.Sprintf("Can't pull from a local repo\n"))
+func (gd *GitDownloader) Clone(commit string, dstPath string) error {
+	// Currently only the master branch is supported.
+	branch := "master"
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"Downloading repository %s (commit: %s)\n", gd.Url, commit)
+
+	gp, err := gitPath()
+	if err != nil {
+		return err
+	}
+
+	// Clone the repository.
+	cmd := []string{
+		gp,
+		"clone",
+		"-b",
+		branch,
+		gd.Url,
+		dstPath,
+	}
+
+	if util.Verbosity >= util.VERBOSITY_VERBOSE {
+		err = util.ShellInteractiveCommand(cmd, nil)
+	} else {
+		_, err = util.ShellCommand(cmd, nil)
+	}
+	if err != nil {
+		return err
+	}
+
+	// Checkout the specified commit.
+	if err := checkout(dstPath, commit); err != nil {
+		return err
+	}
+
+	return nil
 }
 
-func (ld *LocalDownloader) CleanupRepo(path string, branchName string) error {
-	os.RemoveAll(path)
-	_, err := ld.DownloadRepo(branchName)
-	return err
+func (gd *GitDownloader) FixupOrigin(path string) error {
+	curUrl, err := getRemoteUrl(path, "origin")
+	if err != nil {
+		return err
+	}
+
+	if curUrl == gd.Url {
+		return nil
+	}
+
+	warnWrongOriginUrl(path, curUrl, gd.Url)
+	return setRemoteUrl(path, "origin", gd.Url, true)
 }
 
-func (ld *LocalDownloader) LocalDiff(path string) ([]byte, error) {
-	return executeGitCommand(path, []string{"diff"})
+func NewGitDownloader() *GitDownloader {
+	return &GitDownloader{}
 }
 
-func (ld *LocalDownloader) DownloadRepo(commit string) (string, error) {
-	// Get a temporary directory, and copy the repository into that directory.
-	tmpdir, err := ioutil.TempDir("", "newt-repo")
-	if err != nil {
-		return "", err
+func (ld *LocalDownloader) FetchFile(
+	commit string, path string, filename string, dstDir string) error {
+
+	srcPath := ld.Path + "/" + filename
+	dstPath := dstDir + "/" + filename
+
+	log.Debugf("Fetching file %s to %s", srcPath, dstPath)
+	if err := util.CopyFile(srcPath, dstPath); err != nil {
+		return err
 	}
 
-	util.StatusMessage(util.VERBOSITY_VERBOSE,
+	return nil
+}
+
+func (ld *LocalDownloader) Pull(path string, branchName string) error {
+	os.RemoveAll(path)
+	return ld.Clone(branchName, path)
+}
+
+func (ld *LocalDownloader) Clone(commit string, dstPath string) error {
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
 		"Downloading local repository %s\n", ld.Path)
 
-	if err := util.CopyDir(ld.Path, tmpdir); err != nil {
-		return "", err
+	if err := util.CopyDir(ld.Path, dstPath); err != nil {
+		return err
 	}
 
 	// Checkout the specified commit.
-	if err := checkout(tmpdir, commit); err != nil {
-		return "", err
+	if err := checkout(dstPath, commit); err != nil {
+		return err
 	}
 
-	return tmpdir, nil
+	return nil
+}
+
+func (ld *LocalDownloader) FixupOrigin(path string) error {
+	return nil
 }
 
 func NewLocalDownloader() *LocalDownloader {
 	return &LocalDownloader{}
 }
 
+func loadError(format string, args ...interface{}) error {
+	return util.NewNewtError(
+		"error loading project.yml: " + fmt.Sprintf(format, args...))
+}
+
 func LoadDownloader(repoName string, repoVars map[string]string) (
 	Downloader, error) {
 
@@ -468,8 +922,8 @@ func LoadDownloader(repoName string, repoVars map[string]string) (
 
 		// Alternatively, the user can put security material in
 		// $HOME/.newt/repos.yml.
-		newtrc := newtutil.Newtrc()
-		privRepo := newtrc.GetStringMapString("repository." + repoName)
+		newtrc := settings.Newtrc()
+		privRepo := newtrc.GetValStringMapString("repository."+repoName, nil)
 		if privRepo != nil {
 			if gd.Login == "" {
 				gd.Login = privRepo["login"]
@@ -483,13 +937,21 @@ func LoadDownloader(repoName string, repoVars map[string]string) (
 		}
 		return gd, nil
 
+	case "git":
+		gd := NewGitDownloader()
+		gd.Url = repoVars["url"]
+		if gd.Url == "" {
+			return nil, loadError("repo \"%s\" missing required field \"url\"",
+				repoName)
+		}
+		return gd, nil
+
 	case "local":
 		ld := NewLocalDownloader()
 		ld.Path = repoVars["path"]
 		return ld, nil
 
 	default:
-		return nil, util.FmtNewtError("Invalid repository type: %s",
-			repoVars["type"])
+		return nil, loadError("invalid repository type: %s", repoVars["type"])
 	}
 }
diff --git a/vendor/mynewt.apache.org/newt/newt/image/encrypted.go b/vendor/mynewt.apache.org/newt/newt/image/encrypted.go
new file mode 100644
index 00000000..0547e2fc
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/image/encrypted.go
@@ -0,0 +1,196 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+// Decoder for PKCS#5 encrypted PKCS#8 private keys.
+package image
+
+import (
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/sha1"
+	"crypto/sha256"
+	"crypto/x509"
+	"crypto/x509/pkix"
+	"encoding/asn1"
+	"fmt"
+	"hash"
+
+	"golang.org/x/crypto/pbkdf2"
+	"golang.org/x/crypto/ssh/terminal"
+)
+
+var (
+	oidPbes2          = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13}
+	oidPbkdf2         = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12}
+	oidHmacWithSha1   = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 7}
+	oidHmacWithSha224 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 8}
+	oidHmacWithSha256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9}
+	oidAes128CBC      = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
+	oidAes256CBC      = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
+)
+
+// We only support a narrow set of possible key types, namely the type
+// generated by either MCUboot's `imgtool.py` command, or using an
+// OpenSSL command such as:
+//
+//     openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 \
+//         -aes-256-cbc > keyfile.pem
+//
+// or similar for ECDSA.  Specifically, the encryption must be done
+// with PBES2, and PBKDF2, and aes-256-cbc used as the cipher.
+type pkcs5 struct {
+	Algo      pkix.AlgorithmIdentifier
+	Encrypted []byte
+}
+
+// The parameters when the algorithm in pkcs5 is oidPbes2
+type pbes2 struct {
+	KeyDerivationFunc pkix.AlgorithmIdentifier
+	EncryptionScheme  pkix.AlgorithmIdentifier
+}
+
+// Salt is given as a choice, but we will only support the inlined
+// octet string.
+type pbkdf2Param struct {
+	Salt      []byte
+	IterCount int
+	HashFunc  pkix.AlgorithmIdentifier
+	// Optional and default values omitted, and unsupported.
+}
+
+type hashFunc func() hash.Hash
+
+func parseEncryptedPrivateKey(der []byte) (key interface{}, err error) {
+	var wrapper pkcs5
+	if _, err = asn1.Unmarshal(der, &wrapper); err != nil {
+		return nil, err
+	}
+	if !wrapper.Algo.Algorithm.Equal(oidPbes2) {
+		return nil, fmt.Errorf("pkcs5: Unknown PKCS#5 wrapper algorithm: %v", wrapper.Algo.Algorithm)
+	}
+
+	var pbparm pbes2
+	if _, err = asn1.Unmarshal(wrapper.Algo.Parameters.FullBytes, &pbparm); err != nil {
+		return nil, err
+	}
+	if !pbparm.KeyDerivationFunc.Algorithm.Equal(oidPbkdf2) {
+		return nil, fmt.Errorf("pkcs5: Unknown KDF: %v", pbparm.KeyDerivationFunc.Algorithm)
+	}
+
+	var kdfParam pbkdf2Param
+	if _, err = asn1.Unmarshal(pbparm.KeyDerivationFunc.Parameters.FullBytes, &kdfParam); err != nil {
+		return nil, err
+	}
+
+	var hashNew hashFunc
+	switch {
+	case kdfParam.HashFunc.Algorithm.Equal(oidHmacWithSha1):
+		hashNew = sha1.New
+	case kdfParam.HashFunc.Algorithm.Equal(oidHmacWithSha224):
+		hashNew = sha256.New224
+	case kdfParam.HashFunc.Algorithm.Equal(oidHmacWithSha256):
+		hashNew = sha256.New
+	default:
+		return nil, fmt.Errorf("pkcs5: Unsupported hash: %v", pbparm.EncryptionScheme.Algorithm)
+	}
+
+	// Get the encryption used.
+	size := 0
+	var iv []byte
+	switch {
+	case pbparm.EncryptionScheme.Algorithm.Equal(oidAes256CBC):
+		size = 32
+		if _, err = asn1.Unmarshal(pbparm.EncryptionScheme.Parameters.FullBytes, &iv); err != nil {
+			return nil, err
+		}
+	case pbparm.EncryptionScheme.Algorithm.Equal(oidAes128CBC):
+		size = 16
+		if _, err = asn1.Unmarshal(pbparm.EncryptionScheme.Parameters.FullBytes, &iv); err != nil {
+			return nil, err
+		}
+	default:
+		return nil, fmt.Errorf("pkcs5: Unsupported cipher: %v", pbparm.EncryptionScheme.Algorithm)
+	}
+
+	return unwrapPbes2Pbkdf2(&kdfParam, size, iv, hashNew, wrapper.Encrypted)
+}
+
+func unwrapPbes2Pbkdf2(param *pbkdf2Param, size int, iv []byte, hashNew hashFunc, encrypted []byte) (key interface{}, err error) {
+	pass, err := getPassword()
+	if err != nil {
+		return nil, err
+	}
+	cryptoKey := pbkdf2.Key(pass, param.Salt, param.IterCount, size, hashNew)
+
+	block, err := aes.NewCipher(cryptoKey)
+	if err != nil {
+		return nil, err
+	}
+	enc := cipher.NewCBCDecrypter(block, iv)
+
+	plain := make([]byte, len(encrypted))
+	enc.CryptBlocks(plain, encrypted)
+
+	plain, err = checkPkcs7Padding(plain)
+	if err != nil {
+		return nil, err
+	}
+
+	return x509.ParsePKCS8PrivateKey(plain)
+}
+
+// Verify that PKCS#7 padding is correct on this plaintext message.
+// Returns a new slice with the padding removed.
+func checkPkcs7Padding(buf []byte) ([]byte, error) {
+	if len(buf) < 16 {
+		return nil, fmt.Errorf("Invalid padded buffer")
+	}
+
+	padLen := int(buf[len(buf)-1])
+	if padLen < 1 || padLen > 16 {
+		return nil, fmt.Errorf("Invalid padded buffer")
+	}
+
+	if padLen > len(buf) {
+		return nil, fmt.Errorf("Invalid padded buffer")
+	}
+
+	for pos := len(buf) - padLen; pos < len(buf); pos++ {
+		if int(buf[pos]) != padLen {
+			return nil, fmt.Errorf("Invalid padded buffer")
+		}
+	}
+
+	return buf[:len(buf)-padLen], nil
+}
+
+// For testing, a key can be set here.  If this is empty, the key will
+// be queried via prompt.
+var KeyPassword = []byte{}
+
+// Prompt the user for a password, unless we have stored one for
+// testing.
+func getPassword() ([]byte, error) {
+	if len(KeyPassword) != 0 {
+		return KeyPassword, nil
+	}
+
+	fmt.Printf("key password: ")
+	return terminal.ReadPassword(0)
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/image/image.go b/vendor/mynewt.apache.org/newt/newt/image/image.go
index 78fbc474..f43d5b91 100644
--- a/vendor/mynewt.apache.org/newt/newt/image/image.go
+++ b/vendor/mynewt.apache.org/newt/newt/image/image.go
@@ -50,6 +50,9 @@ import (
 // v1.5.  Eventually, this should be the default.
 var UseRsaPss = false
 
+// Use old image format
+var UseV1 = false
+
 type ImageVersion struct {
 	Major    uint8
 	Minor    uint8
@@ -71,7 +74,7 @@ type Image struct {
 	TotalSize  uint // Total size, in bytes, of the generated .img file.
 }
 
-type ImageHdr struct {
+type ImageHdrV1 struct {
 	Magic uint32
 	TlvSz uint16
 	KeyId uint8
@@ -84,6 +87,22 @@ type ImageHdr struct {
 	Pad3  uint32
 }
 
+type ImageHdr struct {
+	Magic uint32
+	Pad1  uint32
+	HdrSz uint16
+	Pad2  uint16
+	ImgSz uint32
+	Flags uint32
+	Vers  ImageVersion
+	Pad3  uint32
+}
+
+type ImageTlvInfo struct {
+	Magic     uint16
+	TlvTotLen uint16
+}
+
 type ImageTrailerTlv struct {
 	Type uint8
 	Pad  uint8
@@ -91,7 +110,9 @@ type ImageTrailerTlv struct {
 }
 
 const (
-	IMAGE_MAGIC = 0x96f3b83c /* Image header magic */
+	IMAGEv1_MAGIC       = 0x96f3b83c /* Image header magic */
+	IMAGE_MAGIC         = 0x96f3b83d /* Image header magic */
+	IMAGE_TRAILER_MAGIC = 0x6907     /* Image tlv info magic */
 )
 
 const (
@@ -102,23 +123,32 @@ const (
  * Image header flags.
  */
 const (
-	IMAGE_F_PIC                      = 0x00000001
-	IMAGE_F_SHA256                   = 0x00000002 /* Image contains hash TLV */
-	IMAGE_F_PKCS15_RSA2048_SHA256    = 0x00000004 /* PKCS15 w/RSA2048 and SHA256 */
-	IMAGE_F_ECDSA224_SHA256          = 0x00000008 /* ECDSA224 over SHA256 */
-	IMAGE_F_NON_BOOTABLE             = 0x00000010 /* non bootable image */
-	IMAGE_F_ECDSA256_SHA256          = 0x00000020 /* ECDSA256 over SHA256 */
-	IMAGE_F_PKCS1_PSS_RSA2048_SHA256 = 0x00000040 /* RSA-PSS w/RSA2048 and SHA256 */
+	IMAGEv1_F_PIC                      = 0x00000001
+	IMAGEv1_F_SHA256                   = 0x00000002 /* Image contains hash TLV */
+	IMAGEv1_F_PKCS15_RSA2048_SHA256    = 0x00000004 /* PKCS15 w/RSA2048 and SHA256 */
+	IMAGEv1_F_ECDSA224_SHA256          = 0x00000008 /* ECDSA224 over SHA256 */
+	IMAGEv1_F_NON_BOOTABLE             = 0x00000010 /* non bootable image */
+	IMAGEv1_F_ECDSA256_SHA256          = 0x00000020 /* ECDSA256 over SHA256 */
+	IMAGEv1_F_PKCS1_PSS_RSA2048_SHA256 = 0x00000040 /* RSA-PSS w/RSA2048 and SHA256 */
+
+	IMAGE_F_PIC          = 0x00000001
+	IMAGE_F_NON_BOOTABLE = 0x00000002 /* non bootable image */
 )
 
 /*
  * Image trailer TLV types.
  */
 const (
-	IMAGE_TLV_SHA256   = 1
-	IMAGE_TLV_RSA2048  = 2
-	IMAGE_TLV_ECDSA224 = 3
-	IMAGE_TLV_ECDSA256 = 4
+	IMAGEv1_TLV_SHA256   = 1
+	IMAGEv1_TLV_RSA2048  = 2
+	IMAGEv1_TLV_ECDSA224 = 3
+	IMAGEv1_TLV_ECDSA256 = 4
+
+	IMAGE_TLV_KEYHASH  = 0x01
+	IMAGE_TLV_SHA256   = 0x10
+	IMAGE_TLV_RSA2048  = 0x20
+	IMAGE_TLV_ECDSA224 = 0x21
+	IMAGE_TLV_ECDSA256 = 0x22
 )
 
 /*
@@ -267,13 +297,11 @@ func (image *Image) SetVersion(versStr string) error {
 	return nil
 }
 
-func (image *Image) SetSigningKey(fileName string, keyId uint8) error {
-	data, err := ioutil.ReadFile(fileName)
-	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Error reading key file: %s", err))
-	}
+func ParsePrivateKey(keyBytes []byte) (interface{}, error) {
+	var privKey interface{}
+	var err error
 
-	block, data := pem.Decode(data)
+	block, data := pem.Decode(keyBytes)
 	if block != nil && block.Type == "EC PARAMETERS" {
 		/*
 		 * Openssl prepends an EC PARAMETERS block before the
@@ -287,46 +315,85 @@ func (image *Image) SetSigningKey(fileName string, keyId uint8) error {
 		 * ParsePKCS1PrivateKey returns an RSA private key from its ASN.1
 		 * PKCS#1 DER encoded form.
 		 */
-		privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+		privKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Private key parsing "+
+			return nil, util.NewNewtError(fmt.Sprintf("Private key parsing "+
 				"failed: %s", err))
 		}
-		image.SigningRSA = privateKey
 	}
 	if block != nil && block.Type == "EC PRIVATE KEY" {
 		/*
 		 * ParseECPrivateKey returns a EC private key
 		 */
-		privateKey, err := x509.ParseECPrivateKey(block.Bytes)
+		privKey, err = x509.ParseECPrivateKey(block.Bytes)
+		if err != nil {
+			return nil, util.NewNewtError(fmt.Sprintf("Private key parsing "+
+				"failed: %s", err))
+		}
+	}
+	if block != nil && block.Type == "PRIVATE KEY" {
+		// This indicates a PKCS#8 unencrypted private key.
+		// The particular type of key will be indicated within
+		// the key itself.
+		privKey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
 		if err != nil {
-			return util.NewNewtError(fmt.Sprintf("Private key parsing "+
+			return nil, util.NewNewtError(fmt.Sprintf("Private key parsing "+
 				"failed: %s", err))
 		}
-		image.SigningEC = privateKey
 	}
-	if image.SigningEC == nil && image.SigningRSA == nil {
-		return util.NewNewtError("Unknown private key format, EC/RSA private " +
+	if block != nil && block.Type == "ENCRYPTED PRIVATE KEY" {
+		// This indicates a PKCS#8 key wrapped with PKCS#5
+		// encryption.
+		privKey, err = parseEncryptedPrivateKey(block.Bytes)
+		if err != nil {
+			return nil, util.FmtNewtError("Unable to decode encrypted private key: %s", err)
+		}
+	}
+	if privKey == nil {
+		return nil, util.NewNewtError("Unknown private key format, EC/RSA private " +
 			"key in PEM format only.")
 	}
+
+	return privKey, nil
+}
+
+func (image *Image) SetSigningKey(fileName string, keyId uint8) error {
+	keyBytes, err := ioutil.ReadFile(fileName)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Error reading key file: %s", err))
+	}
+
 	image.KeyId = keyId
+	privKey, err := ParsePrivateKey(keyBytes)
+	if err != nil {
+		return err
+	}
+
+	switch priv := privKey.(type) {
+	case *rsa.PrivateKey:
+		image.SigningRSA = priv
+	case *ecdsa.PrivateKey:
+		image.SigningEC = priv
+	default:
+		return util.NewNewtError("Unknown private key format")
+	}
 
 	return nil
 }
 
-func (image *Image) sigHdrType() (uint32, error) {
+func (image *Image) sigHdrTypeV1() (uint32, error) {
 	if image.SigningRSA != nil {
 		if UseRsaPss {
-			return IMAGE_F_PKCS1_PSS_RSA2048_SHA256, nil
+			return IMAGEv1_F_PKCS1_PSS_RSA2048_SHA256, nil
 		} else {
-			return IMAGE_F_PKCS15_RSA2048_SHA256, nil
+			return IMAGEv1_F_PKCS15_RSA2048_SHA256, nil
 		}
 	} else if image.SigningEC != nil {
 		switch image.SigningEC.Curve.Params().Name {
 		case "P-224":
-			return IMAGE_F_ECDSA224_SHA256, nil
+			return IMAGEv1_F_ECDSA224_SHA256, nil
 		case "P-256":
-			return IMAGE_F_ECDSA256_SHA256, nil
+			return IMAGEv1_F_ECDSA256_SHA256, nil
 		default:
 			return 0, util.NewNewtError("Unsupported ECC curve")
 		}
@@ -335,6 +402,27 @@ func (image *Image) sigHdrType() (uint32, error) {
 	}
 }
 
+func (image *Image) sigKeyHash() ([]uint8, error) {
+	if image.SigningRSA != nil {
+		pubkey, _ := asn1.Marshal(image.SigningRSA.PublicKey)
+		sum := sha256.Sum256(pubkey)
+		return sum[:4], nil
+	} else if image.SigningEC != nil {
+		switch image.SigningEC.Curve.Params().Name {
+		case "P-224":
+			fallthrough
+		case "P-256":
+			pubkey, _ := x509.MarshalPKIXPublicKey(&image.SigningEC.PublicKey)
+			sum := sha256.Sum256(pubkey)
+			return sum[:4], nil
+		default:
+			return []uint8{}, util.NewNewtError("Unsupported ECC curve")
+		}
+	} else {
+		return []uint8{}, util.NewNewtError("No public key to hash")
+	}
+}
+
 func (image *Image) sigLen() uint16 {
 	if image.SigningRSA != nil {
 		return 256
@@ -352,6 +440,23 @@ func (image *Image) sigLen() uint16 {
 	}
 }
 
+func (image *Image) sigTlvTypeV1() uint8 {
+	if image.SigningRSA != nil {
+		return IMAGEv1_TLV_RSA2048
+	} else if image.SigningEC != nil {
+		switch image.SigningEC.Curve.Params().Name {
+		case "P-224":
+			return IMAGEv1_TLV_ECDSA224
+		case "P-256":
+			return IMAGEv1_TLV_ECDSA256
+		default:
+			return 0
+		}
+	} else {
+		return 0
+	}
+}
+
 func (image *Image) sigTlvType() uint8 {
 	if image.SigningRSA != nil {
 		return IMAGE_TLV_RSA2048
@@ -382,24 +487,51 @@ func (image *Image) ReSign() error {
 			image.SourceImg, err.Error()))
 	}
 
-	var hdr ImageHdr
+	var hdr1 ImageHdrV1
+	var hdr2 ImageHdr
+	var hdrSz uint16
+	var imgSz uint32
 
-	err = binary.Read(srcImg, binary.LittleEndian, &hdr)
+	err = binary.Read(srcImg, binary.LittleEndian, &hdr1)
+	if err == nil {
+		srcImg.Seek(0, 0)
+		err = binary.Read(srcImg, binary.LittleEndian, &hdr2)
+	}
 	if err != nil {
 		return util.NewNewtError(fmt.Sprintf("Failing to access image %s: %s",
 			image.SourceImg, err.Error()))
 	}
+	if hdr1.Magic == IMAGEv1_MAGIC {
+		if uint32(srcInfo.Size()) !=
+			uint32(hdr1.HdrSz)+hdr1.ImgSz+uint32(hdr1.TlvSz) {
 
-	if uint32(srcInfo.Size()) != uint32(hdr.HdrSz)+hdr.ImgSz+uint32(hdr.TlvSz) ||
-		hdr.Magic != IMAGE_MAGIC {
+			return util.NewNewtError(fmt.Sprintf("File %s is not an image\n",
+				image.SourceImg))
+		}
+		imgSz = hdr1.ImgSz
+		hdrSz = hdr1.HdrSz
+		image.Version = hdr1.Vers
+
+		log.Debugf("Resigning %s (ver %d.%d.%d.%d)", image.SourceImg,
+			hdr1.Vers.Major, hdr1.Vers.Minor, hdr1.Vers.Rev,
+			hdr1.Vers.BuildNum)
+	} else if hdr2.Magic == IMAGE_MAGIC {
+		if uint32(srcInfo.Size()) < uint32(hdr2.HdrSz)+hdr2.ImgSz {
+			return util.NewNewtError(fmt.Sprintf("File %s is not an image\n",
+				image.SourceImg))
+		}
+		imgSz = hdr2.ImgSz
+		hdrSz = hdr2.HdrSz
+		image.Version = hdr2.Vers
 
+		log.Debugf("Resigning %s (ver %d.%d.%d.%d)", image.SourceImg,
+			hdr2.Vers.Major, hdr2.Vers.Minor, hdr2.Vers.Rev,
+			hdr2.Vers.BuildNum)
+	} else {
 		return util.NewNewtError(fmt.Sprintf("File %s is not an image\n",
 			image.SourceImg))
 	}
-	srcImg.Seek(int64(hdr.HdrSz), 0)
-
-	log.Debugf("Resigning %s (ver %d.%d.%d.%d)", image.SourceImg,
-		hdr.Vers.Major, hdr.Vers.Minor, hdr.Vers.Rev, hdr.Vers.BuildNum)
+	srcImg.Seek(int64(hdrSz), 0)
 
 	tmpBin, err := ioutil.TempFile("", "")
 	if err != nil {
@@ -410,9 +542,8 @@ func (image *Image) ReSign() error {
 	defer os.Remove(tmpBinName)
 
 	log.Debugf("Extracting data from %s:%d-%d to %s\n",
-		image.SourceImg, int64(hdr.HdrSz), int64(hdr.HdrSz)+int64(hdr.ImgSz),
-		tmpBinName)
-	_, err = io.CopyN(tmpBin, srcImg, int64(hdr.ImgSz))
+		image.SourceImg, int64(hdrSz), int64(hdrSz)+int64(imgSz), tmpBinName)
+	_, err = io.CopyN(tmpBin, srcImg, int64(imgSz))
 	srcImg.Close()
 	tmpBin.Close()
 	if err != nil {
@@ -422,13 +553,12 @@ func (image *Image) ReSign() error {
 
 	image.SourceBin = tmpBinName
 	image.TargetImg = image.SourceImg
-	image.Version = hdr.Vers
-	image.HeaderSize = uint(hdr.HdrSz)
+	image.HeaderSize = uint(hdrSz)
 
 	return image.Generate(nil)
 }
 
-func (image *Image) Generate(loader *Image) error {
+func (image *Image) generateV1(loader *Image) error {
 	binFile, err := os.Open(image.SourceBin)
 	if err != nil {
 		return util.NewNewtError(fmt.Sprintf("Can't open app binary: %s",
@@ -443,7 +573,7 @@ func (image *Image) Generate(loader *Image) error {
 	}
 
 	imgFile, err := os.OpenFile(image.TargetImg,
-		os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
+		os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
 	if err != nil {
 		return util.NewNewtError(fmt.Sprintf("Can't open target image %s: %s",
 			image.TargetImg, err.Error()))
@@ -466,8 +596,8 @@ func (image *Image) Generate(loader *Image) error {
 	/*
 	 * First the header
 	 */
-	hdr := &ImageHdr{
-		Magic: IMAGE_MAGIC,
+	hdr := &ImageHdrV1{
+		Magic: IMAGEv1_MAGIC,
 		TlvSz: 0,
 		KeyId: 0,
 		Pad1:  0,
@@ -479,7 +609,7 @@ func (image *Image) Generate(loader *Image) error {
 		Pad3:  0,
 	}
 
-	hdr.Flags, err = image.sigHdrType()
+	hdr.Flags, err = image.sigHdrTypeV1()
 	if err != nil {
 		return err
 	}
@@ -492,10 +622,10 @@ func (image *Image) Generate(loader *Image) error {
 	}
 
 	hdr.TlvSz += 4 + 32
-	hdr.Flags |= IMAGE_F_SHA256
+	hdr.Flags |= IMAGEv1_F_SHA256
 
 	if loader != nil {
-		hdr.Flags |= IMAGE_F_NON_BOOTABLE
+		hdr.Flags |= IMAGEv1_F_NON_BOOTABLE
 	}
 
 	if image.HeaderSize != 0 {
@@ -561,7 +691,8 @@ func (image *Image) Generate(loader *Image) error {
 			}
 		}
 		if nonZero {
-			log.Warnf("Skip requested of iamge %s, but image not preceeded by %d bytes of all zeros",
+			log.Warnf("Skip requested of image %s, but image not preceeded "+
+				"by %d bytes of all zeros",
 				image.SourceBin, image.SrcSkip)
 		}
 	}
@@ -597,7 +728,7 @@ func (image *Image) Generate(loader *Image) error {
 	 * Trailer with hash of the data
 	 */
 	tlv := &ImageTrailerTlv{
-		Type: IMAGE_TLV_SHA256,
+		Type: IMAGEv1_TLV_SHA256,
 		Pad:  0,
 		Len:  uint16(len(image.Hash)),
 	}
@@ -617,7 +748,7 @@ func (image *Image) Generate(loader *Image) error {
 		 * If signing key was set, generate TLV for that.
 		 */
 		tlv := &ImageTrailerTlv{
-			Type: IMAGE_TLV_RSA2048,
+			Type: IMAGEv1_TLV_RSA2048,
 			Pad:  0,
 			Len:  256, /* 2048 bits */
 		}
@@ -657,6 +788,305 @@ func (image *Image) Generate(loader *Image) error {
 
 		sigLen := image.sigLen()
 
+		var ECDSA ECDSASig
+		ECDSA.R = r
+		ECDSA.S = s
+		signature, err := asn1.Marshal(ECDSA)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf(
+				"Failed to construct signature: %s", err))
+		}
+		if len(signature) > int(sigLen) {
+			return util.NewNewtError(fmt.Sprintf(
+				"Something is really wrong\n"))
+		}
+		tlv := &ImageTrailerTlv{
+			Type: image.sigTlvTypeV1(),
+			Pad:  0,
+			Len:  sigLen,
+		}
+		err = binary.Write(imgFile, binary.LittleEndian, tlv)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
+				"trailer: %s", err.Error()))
+		}
+		_, err = imgFile.Write(signature)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s",
+				err.Error()))
+		}
+		pad := make([]byte, int(sigLen)-len(signature))
+		_, err = imgFile.Write(pad)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
+				"trailer: %s", err.Error()))
+		}
+	}
+
+	util.StatusMessage(util.VERBOSITY_VERBOSE,
+		"Computed Hash for image %s as %s \n",
+		image.TargetImg, hex.EncodeToString(image.Hash))
+
+	// XXX: Replace "1" with io.SeekCurrent when go 1.7 becomes mainstream.
+	sz, err := imgFile.Seek(0, 1)
+	if err != nil {
+		return util.FmtNewtError("Failed to calculate file size of generated "+
+			"image %s: %s", image.TargetImg, err.Error())
+	}
+	image.TotalSize = uint(sz)
+
+	return nil
+}
+
+func (image *Image) generateV2(loader *Image) error {
+	binFile, err := os.Open(image.SourceBin)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Can't open app binary: %s",
+			err.Error()))
+	}
+	defer binFile.Close()
+
+	binInfo, err := binFile.Stat()
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Can't stat app binary %s: %s",
+			image.SourceBin, err.Error()))
+	}
+
+	imgFile, err := os.OpenFile(image.TargetImg,
+		os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Can't open target image %s: %s",
+			image.TargetImg, err.Error()))
+	}
+	defer imgFile.Close()
+
+	/*
+	 * Compute hash while updating the file.
+	 */
+	hash := sha256.New()
+
+	if loader != nil {
+		err = binary.Write(hash, binary.LittleEndian, loader.Hash)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to seed hash: %s",
+				err.Error()))
+		}
+	}
+
+	/*
+	 * First the header
+	 */
+	hdr := &ImageHdr{
+		Magic: IMAGE_MAGIC,
+		Pad1:  0,
+		HdrSz: IMAGE_HEADER_SIZE,
+		Pad2:  0,
+		ImgSz: uint32(binInfo.Size()) - uint32(image.SrcSkip),
+		Flags: 0,
+		Vers:  image.Version,
+		Pad3:  0,
+	}
+
+	if loader != nil {
+		hdr.Flags |= IMAGE_F_NON_BOOTABLE
+	}
+
+	if image.HeaderSize != 0 {
+		/*
+		 * Pad the header out to the given size.  There will
+		 * just be zeros between the header and the start of
+		 * the image when it is padded.
+		 */
+		if image.HeaderSize < IMAGE_HEADER_SIZE {
+			return util.NewNewtError(fmt.Sprintf("Image header must be at "+
+				"least %d bytes", IMAGE_HEADER_SIZE))
+		}
+
+		hdr.HdrSz = uint16(image.HeaderSize)
+	}
+
+	err = binary.Write(imgFile, binary.LittleEndian, hdr)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s",
+			err.Error()))
+	}
+	err = binary.Write(hash, binary.LittleEndian, hdr)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s",
+			err.Error()))
+	}
+
+	if image.HeaderSize > IMAGE_HEADER_SIZE {
+		/*
+		 * Pad the image (and hash) with zero bytes to fill
+		 * out the buffer.
+		 */
+		buf := make([]byte, image.HeaderSize-IMAGE_HEADER_SIZE)
+
+		_, err = imgFile.Write(buf)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to write padding: %s",
+				err.Error()))
+		}
+
+		_, err = hash.Write(buf)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to hash padding: %s",
+				err.Error()))
+		}
+	}
+
+	/*
+	 * Skip requested initial part of image.
+	 */
+	if image.SrcSkip > 0 {
+		buf := make([]byte, image.SrcSkip)
+		_, err = binFile.Read(buf)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s",
+				image.SourceBin, err.Error()))
+		}
+
+		nonZero := false
+		for _, b := range buf {
+			if b != 0 {
+				nonZero = true
+				break
+			}
+		}
+		if nonZero {
+			log.Warnf("Skip requested of image %s, but image not preceeded by %d bytes of all zeros",
+				image.SourceBin, image.SrcSkip)
+		}
+	}
+
+	/*
+	 * Followed by data.
+	 */
+	dataBuf := make([]byte, 1024)
+	for {
+		cnt, err := binFile.Read(dataBuf)
+		if err != nil && err != io.EOF {
+			return util.NewNewtError(fmt.Sprintf("Failed to read from %s: %s",
+				image.SourceBin, err.Error()))
+		}
+		if cnt == 0 {
+			break
+		}
+		_, err = imgFile.Write(dataBuf[0:cnt])
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to write to %s: %s",
+				image.TargetImg, err.Error()))
+		}
+		_, err = hash.Write(dataBuf[0:cnt])
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to hash data: %s",
+				err.Error()))
+		}
+	}
+
+	image.Hash = hash.Sum(nil)
+
+	/*
+	 * Write TLV info.
+	 */
+	tlvInfo := &ImageTlvInfo{
+		Magic:     IMAGE_TRAILER_MAGIC,
+		TlvTotLen: 0,
+	}
+	tlvInfoOff, err := imgFile.Seek(0, 1)
+	if err != nil {
+		return util.FmtNewtError("Failed to calculate file size of generated "+
+			"image %s: %s", image.TargetImg, err.Error())
+	}
+	err = binary.Write(imgFile, binary.LittleEndian, tlvInfo)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s",
+			err.Error()))
+	}
+
+	/*
+	 * Trailer with hash of the data
+	 */
+	tlv := &ImageTrailerTlv{
+		Type: IMAGE_TLV_SHA256,
+		Pad:  0,
+		Len:  uint16(len(image.Hash)),
+	}
+	err = binary.Write(imgFile, binary.LittleEndian, tlv)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
+			"trailer: %s", err.Error()))
+	}
+	_, err = imgFile.Write(image.Hash)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Failed to append hash: %s",
+			err.Error()))
+	}
+
+	if image.SigningRSA != nil || image.SigningEC != nil {
+		keyHash, err := image.sigKeyHash()
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to compute hash " +
+				"of the public key"))
+		}
+
+		tlv = &ImageTrailerTlv{
+			Type: IMAGE_TLV_KEYHASH,
+			Pad:  0,
+			Len:  uint16(len(keyHash)),
+		}
+		err = binary.Write(imgFile, binary.LittleEndian, tlv)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to serial image "+
+				"trailer: %s", err.Error()))
+		}
+		_, err = imgFile.Write(keyHash)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to append "+
+				"key hash: %s", err.Error()))
+		}
+	}
+	if image.SigningRSA != nil {
+		/*
+		 * If signing key was set, generate TLV for that.
+		 */
+		tlv := &ImageTrailerTlv{
+			Type: IMAGE_TLV_RSA2048,
+			Pad:  0,
+			Len:  256, /* 2048 bits */
+		}
+		var signature []byte
+		opts := rsa.PSSOptions{
+			SaltLength: rsa.PSSSaltLengthEqualsHash,
+		}
+		signature, err = rsa.SignPSS(rand.Reader, image.SigningRSA,
+			crypto.SHA256, image.Hash, &opts)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf(
+				"Failed to compute signature: %s", err))
+		}
+
+		err = binary.Write(imgFile, binary.LittleEndian, tlv)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to serialize image "+
+				"trailer: %s", err.Error()))
+		}
+		_, err = imgFile.Write(signature)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf("Failed to append sig: %s",
+				err.Error()))
+		}
+	}
+	if image.SigningEC != nil {
+		r, s, err := ecdsa.Sign(rand.Reader, image.SigningEC, image.Hash)
+		if err != nil {
+			return util.NewNewtError(fmt.Sprintf(
+				"Failed to compute signature: %s", err))
+		}
+
+		sigLen := image.sigLen()
+
 		var ECDSA ECDSASig
 		ECDSA.R = r
 		ECDSA.S = s
@@ -704,9 +1134,33 @@ func (image *Image) Generate(loader *Image) error {
 	}
 	image.TotalSize = uint(sz)
 
+	tlvInfo.TlvTotLen = uint16(sz - tlvInfoOff)
+
+	/*
+	 * Go back and write tlv info total length
+	 */
+	_, err = imgFile.Seek(tlvInfoOff, 0)
+	if err != nil {
+		return util.FmtNewtError("Failed to move to tlvInfo offset %d "+
+			"image: %s", int(tlvInfoOff), err.Error())
+	}
+	err = binary.Write(imgFile, binary.LittleEndian, tlvInfo)
+	if err != nil {
+		return util.NewNewtError(fmt.Sprintf("Failed to serialize image hdr: %s",
+			err.Error()))
+	}
+
 	return nil
 }
 
+func (image *Image) Generate(loader *Image) error {
+	if UseV1 {
+		return image.generateV1(loader)
+	} else {
+		return image.generateV2(loader)
+	}
+}
+
 func CreateBuildId(app *Image, loader *Image) []byte {
 	return app.Hash
 }
diff --git a/vendor/mynewt.apache.org/newt/newt/image/keys_test.go b/vendor/mynewt.apache.org/newt/newt/image/keys_test.go
new file mode 100644
index 00000000..86124031
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/image/keys_test.go
@@ -0,0 +1,246 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package image_test
+
+import (
+	"io/ioutil"
+	"os"
+	"path"
+	"testing"
+
+	"mynewt.apache.org/newt/newt/image"
+)
+
+func TestRSA(t *testing.T) {
+	signatureTest(t, rsaPkcs1Private)
+}
+
+func TestPlainRSAPKCS8(t *testing.T) {
+	signatureTest(t, rsaPkcs8Private)
+}
+
+func TestEcdsa(t *testing.T) {
+	signatureTest(t, ecdsaPrivate)
+}
+
+func TestPlainEcdsaPkcs8(t *testing.T) {
+	signatureTest(t, ecdsaPkcs8Private)
+}
+
+func TestEncryptedRSA(t *testing.T) {
+	image.KeyPassword = []byte("sample")
+	signatureTest(t, rsaEncryptedPrivate)
+	image.KeyPassword = []byte{}
+}
+
+func TestEncryptedEcdsa(t *testing.T) {
+	image.KeyPassword = []byte("sample")
+	signatureTest(t, ecdsaEncryptedPrivate)
+	image.KeyPassword = []byte{}
+}
+
+func signatureTest(t *testing.T, privateKey []byte) {
+	tmpdir, err := ioutil.TempDir("", "newttest")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tmpdir)
+
+	// Create a source image.  Format doesn't really matter that
+	// much, since the header will be placed on it by the image
+	// tool.
+
+	simpleName := path.Join(tmpdir, "simple.bin")
+	hashedName := path.Join(tmpdir, "simple-hashed.bin")
+	signedName := path.Join(tmpdir, "simple-signed.bin")
+	keyName := path.Join(tmpdir, "private.pem")
+
+	tmp := make([]byte, 256)
+	for i := 0; i < len(tmp); i++ {
+		tmp[i] = byte(i & 0xFF)
+	}
+	err = ioutil.WriteFile(simpleName, tmp, 0644)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	img, err := image.NewImage(simpleName, hashedName)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	img.SetVersion("1.5")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	img.Generate(nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Now try with a signature.
+	err = ioutil.WriteFile(keyName, privateKey, 0644)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	img, err = image.NewImage(simpleName, signedName)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = img.SetSigningKey(keyName, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = img.SetVersion("1.6")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = img.Generate(nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
+
+// An RSA private key in the old PKCS1 format.
+var rsaPkcs1Private = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA6q2Q/VoFf6U5xm35ynls+HDbHKwfIbBr27PtFJxlS9YT0xKJ
+bcZScPTVizTlft0wfp2TctX/vGd/Y/X3qo5ckRmz+lKUeHm46i4k6rtOBbhBz2id
+hwrO7/ylzwaf8lxn2dj/9ikoYQKFtBb/cKu8wyuvW3gs/ou51AVEF8aKTrl5Expy
+PrhSlh97er2zUmm8NAoo259I5yHK1SvR9kCw2gNXSDQLpFlK2WikdmEbIu0N+cvN
+WM4ONAhffkasznrEOoLPSI66RDrzYhi/Ks9t+N2buEOXao19fDRcSHgZLKT8e6W6
+uK7WxRiEzNbajzgDddbZFqWlcpE7sqPNHFBijwIDAQABAoIBAQDdXx7fLpTzROvM
+F5/C9GnrraGzWVYAlIgZ9o8Umzceo3GN8PV8fND1xq7Novc9he8h8QjPEbksg0Dz
+DWo0FBiTs3hIELAHOWNKXH7sggVmddp2iUvXwEVWsq/CK5CjsbExGXbSQR7a6+Mt
+72fEY+wq+0Fuel2PPETuEI2cE+gRuyspIcO7asmMvLRkxLi2EXU0s4JlqV9UfxKQ
+aqn0PHlRXa5SIzys3mVhXuoe45T50+VKX0DIfu/RuV8njNkkMx74DeEVvf5W4MJW
+vHrRBHoK6KoMrqiwafyPLW/Rh6fMYAdPrffMVuuThtG7Hp83VBVX1HxFhI4Jrf3S
+Hf63hmSZAoGBAO2R/vYBl57qgWEKiMQaU8rzctRbP0TtTsqNdISPMnHV1Tn/rNAU
+m0N7/6IBDb+IlndXDQwIsW/DTXhF2XJSu7n6GXua8B1LF+zuVWUsFfmE3+eLz7B8
+x8G/OkSnOTfRZCYWEoEvzhynn1dlADQ+x49I/XmKqccvAhY71glk6WULAoGBAPzi
+IYo9G+ktlNj9/3OciX7aTCiIIMDyPYtYS6wi59gwH9IswaicHYK4w2fDpTWKlzEE
+18dKF4puuI5GxnKCwHBiWxGhij063cZKKMqA64X41csK+mumux/PAb2gKbGSzzoF
+mSgkKXJ+sZ4ytlgsijEAHV85Sw7j+xy8A0qnCWMNAoGAeCDR7q1hcM8duucrvxWc
+90vg7bZyKLVimROsLneGR3+cAWbiiJlS5W3nFpE31XkItLHE/CfNKTl1i/KuAJwL
+JwBrMFBpSDa3k2v0rGL9fZ2N5rSQwapnC/ZZTWvNiAcOgB+7Ha4BqAWuke+VidWQ
+7Ug4O+Q882Y2xO1ezoNDbX8CgYBq228KyAm8PXuRObsw8iuTg9D8q5ETlwj0kcng
+IhvP2X4IxMrMYbOCompHtX9hIYADwaUgXCmYYHLyA+wlRSTmGFmdGKKefvppqLqV
+32YmhWBp3Oi2hoy5wzJcG4qis4OHZAg00xsEe464Z3tvxNpcHE1NCJuz3hglKzlE
+2VJ5HQKBgQDRisWDbdnOEp7LTXp3Aa33PF1Rx/pkFk4Wb+2Hk977O1OxsAin2cKM
+S5HCltHvON2sCmSQUIxMXXKaNPJiGL3UZJxWZDj38zSg0vO+msmemS1Yjt0xCpbO
+pkl0kvKb/NVlsY4w9kquvql+t9e1rUu9Ug28TKEsSjc9SFrcnVPoNA==
+-----END RSA PRIVATE KEY-----
+`)
+
+// An RSA private key in PKCS8 format, with no encryption.
+var rsaPkcs8Private = []byte(`-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC+FjuXqPSPucsQ
+adxY4nw+9kTgAdsXRIPxq4Q//wkfjEjYhDczN+/rafi0hApuRh7PN7VMGOsDGGR1
+edyertiLt3SfUHAZROIqZ0VAoKGtxgXmnC+s+mMujAv9Ssntbmbi5tNxDcltdWjA
+SdBn7tbIMVVofKaMMugyuXCglxebMm8yxtkSgUvE1E6zZERnteDJTPo8dBCiqkvU
+hf+vG9s1j9lNDMjrZ+d5CHIFmBxJ/WFa6m49lNBFb1Ba43bKdj6mkK05rZ4VWMXU
+evy3Z/UUgU4VPJpoB+GIKy82iOrtjiU7s/6aDkvZ2e+fgxKksN0pzFE9azeA73QS
+bamp28E/AgMBAAECggEBAJ78+4UDFOKt1JF66YkSjjcfRkZSZwyUCwP0oF3ik5/m
+dvtZws29KJevgAyEMDFBxv0srB/k65QgL84uSgATYB2kKRAjeE86VSyASeUfNXui
+GEdlNV8p4hEJo/GMP06uu7FmvU1e6a36uM20L3LuyoiQ8s29DJRQ8/ORNQmstlrg
+J32FZSjTF1mElGPSc1koxhWvl1hE7UGE9pxsSfdsvPNhCIWwAOnVnIv49xG8EWaK
+CkHhEVVdZW8IvO9GYR5U0BJcgzNmdNkS8HVQBIxZtboGAAuPI32EC7siDomKmCF6
+rEcs40f/J/RlK6lrTyKKfqWb4DPtRrOSh9cmjrFFZlECgYEA6mZIANLXJd7CINZ9
+fjotI+FxH8BDOZF7l8xTnOk1e3Me1ia7t2GMcIL+frfG/zMBiDFq0IQuUYScRK1v
+pAILjJKFiU6yY8vH6FZ3mXqiiag6RPa+q89DaUsO0uXRUjQvhtTd5Yy6r8Eac1ya
+y6XC5T5sCJ6HgaF3qlheap+5FkkCgYEAz5qSLShV5oekuj1R0fs+h/Yn7VW9Q0sj
+px8jOD4MWc8gPZ9gZe0UPTvofOLrM3eAetP4egSif99AE9iD8EbiBzAt16OX7EN8
+d7xNiIN922Ep3pubcD6f1vglaI7Thrca/p52g6kWPip6+PWFd1acU6u31Uj0Xvgz
+VFiafstF+0cCgYEAw2sOcJFXCZ2Tnyjzav85jwZu95ek9CPUNJQGyXSsQAWUGdok
++hf7q/mqDx9Maoqtpkv8z2bD7vZuCdvGjaee1U16wyS3GPhV69/ayjwxsi5slf5Y
+rIiZnPkUnMM5Jh2X2gMyFCSlp82ILdFwxIOn3tOR4gW411w0lfIilSYgevECgYA3
+JAgVZHREcdzH9seHrWLze+co+6/0cr26guO46YogRIp8s5tIF0tb5FCg8yijl+cR
+OMHzrs12h1aertCEfl9Ep4BVmUcd4uLpbqNtUfeY0FrtnIkRrCCKWYieF+mJC5No
+86/o0n1s752QCK51fxSwiJigVutJWkVP7uTCLr2cuwKBgQCJPWMcWmSuRlLOVWnO
+jPFoa02Bb83n8GrRpQkpkZZofHextwfo2dd1sZF72zghRsbdC6e0Zj1GrekJOYXO
+8AXmCpyKlXJU7iH5tPGSo68uFN05R6mINbTNmEIQBNTKv8UoKT+nHcTycFrVtarX
+A8EPW2xB86m+Bjq/GNyRgfbPMg==
+-----END PRIVATE KEY-----
+`)
+
+// An ECDSA key in the X.509 internal private key format.
+var ecdsaPrivate = []byte(`-----BEGIN EC PRIVATE KEY-----
+MGgCAQEEHF64kDx3pZyVvezbqYMIxlLbtuPQmI85k4GRy1mgBwYFK4EEACGhPAM6
+AASRtolOCTLQYkDefkIF02tUXR92MKHrbtH4WK/8bfTSFVkaygTPdJbpNthK2wae
+oX9ZeFHS1pcOfQ==
+-----END EC PRIVATE KEY-----
+`)
+
+// An ECDSA key in PKCS#8 format, no encryption.
+var ecdsaPkcs8Private = []byte(`-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHKeDq4UU6M+c+pMm
+j0AQZlBs7f4r67668eDCUB8aDR2hRANCAATyZPzsx+xn9JtlxdspevTrYisiMTjl
+YuBJCrV1FZj2HkplEgO+ZIMuD7eRvyTEBS2bw6F1aCeKOMUmYVImAbpc
+-----END PRIVATE KEY-----
+`)
+
+// A password-protected RSA private key in PKCS#5/8 format.  The
+// password for this key is "sample".
+var rsaEncryptedPrivate = []byte(`-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIRMifqJThk8kCAggA
+MB0GCWCGSAFlAwQBKgQQTMUBoFpzjJ5UNRnCIeqf4QSCBNDkQvXnUNmss8erKiDo
+Uqs2tf9ZD8MjDThLBmF/gV1dg1q6aDY+3fI2E4yLXJb2PmKcUq82YZ0FDeoCvJRJ
+BCurzM9slur5akpNBTFoFwtFsdHz7nKNS4MHUul22rGBnVFUUNTySmpjl/m+dxWO
+fa6tWpGTAr7tsCy9gF5PxpSw7NR/NpIL0PmpydHWhTs1tl2csqBqK6Tp014Kefi/
+pmmeb2eRl5cmprxW32rW2QBMtv4z91SsbnlVdz4r8txTG+3S4td9v9jD5kqcIiC2
+KQHrbH9y7okUk/ISsp9ANKPJt10fbYDxORiMK57XssXy1enGjpkIIrUGz1TMydkD
+USfwqkmPuIrrzOXnbxU4ef2wC/pA/h9Smby3WWYo8725/1kZyIediNDcgi/Qgrs4
+1VQAYzsD6duwyUNSo+tgmYVFGvZhsottus3fMWe/Ay1biJ6z6Vk8gqKWI1VV/REJ
+zK/I9hgKGxj2N2Ff6E/YkcwQenHWj/iDWLjvokyOBnPFNqzzM2Qqo1XFpzj4EO5D
+0WD4EzZYvUhk3lZZNydvXiuy8RrCVLLJMS08XgOqQaiFqqxj2hjRwv3nBesk7iA8
+5Tv8GMa5QkNrISCnp4/uGBh+v/CjwVRqPTcK3/mctPN2nLhI6H4pF4Y6apXkz1TN
+NMQqxaxmVVg8fyLaS4/xfUr8LAmiEtOwvs0XOhcqCTvvlsO4N+yec4VD4gmsTDY9
+/2b/+YwSlGMpA+GQQbg0FraaF8NyJRG1mSER6WiUGGM1cuKK44nzBbykQbZwzDSA
+kkhjDaadkhv/NPKAUR3sNy2GXVaNL/ItCpQUHRKKcIPp0HhdXsl0YebuwRlHjw/6
+UOdzNYe23e40X/Xl3vmOKRbzhLP/qO2DV21o0wI4ujF8Xu5h1h8s49HPp58G1ldy
+/hJ6durYKX8T5khiR2iXYewoy0YObuccV//Ov1/ySOp/x0/QuCl/swvs8Jf7awnu
+rpRrHPArpCvMmXmt5Y+TFYXFjkJGwsxTew5TcwBebBlIET2XNbo2pbz4WqJ3eVlK
+CNZVDEZ8mMrGT00FBi759Vfw9rhrnqXnLlNtJZ5VCXFUw8Tos302sLaQWXzHYyf8
+4awM8G9PSu5Q9lFcN9od4H95YrAAv/l8F+pcGgEKD8ZuzsgFIalqgx5wzmUMDcPM
+NKV5u9mtHjI92ru6NB8rGesM6sy6kBGvpotsDWawpV2SoCrkbyEkk+kXaGS+fsG7
+D2H37GfktN8R5Ktc0Uf/JJiNfDzq8lk1J4r7LBQlWUbhKbfGMYxt+7Xo0GsqAsLp
+PKSUwx+hTZb3BmW6s4Q6vivI1MdQbWVT1zh41StvfRSNlo70iOFxOM0lU1jjY989
+UKo+gcolddvZbMNwip0ILPO3dsa+he1jJ/gbo9qBHLy7plfsBLLakZP1Nu6xdlqQ
+TSSobaE8uxUMZk+wMWClA9AOZ1TcUr2yRV5GVj/bxG9ab+H37vF9F8vFE+jjJ7yN
+6pjdohm4gXeSVx7ON4SeZLsVwNYkCVYS89E81qLx1jP9F57+6IUGDZN5EMC0aJLT
+ny75MCCLT00KD7BFsb0KDLXxp++eu/L2hinorT3p6dXp/9mUoxmy6wJqEyqCFniZ
+N2GZN7+LDTIbHUxCijVWamU2DQ==
+-----END ENCRYPTED PRIVATE KEY-----
+`)
+
+// A password-protected ECDSA private key in PKCS#5/8 format.  The
+// password for this key is "sample"
+var ecdsaEncryptedPrivate = []byte(`-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIHeMEkGCSqGSIb3DQEFDTA8MBsGCSqGSIb3DQEFDDAOBAjlKrDSKNg9QQICCAAw
+HQYJYIZIAWUDBAEqBBDliPNzQTNpdlppTcYpmuhWBIGQVhfWaVSzUvi/qIZLiZVn
+Nulfw5jDOlbn3UBX9kp/Z9Pro582Q0kjzLfm5UahvDINEJWxL4pc/28UnGQTBr0Q
+nSEg+RbqpuD099C38H0Gq/YkIM+RDG4aiQrkmzHXyVsHshIbG+z2LsLTIwmU69/Z
+v0nX6/hGErVR8YWcrOne086rCvfJVrxyO5+EUqrkLhEr
+-----END ENCRYPTED PRIVATE KEY-----
+`)
diff --git a/vendor/mynewt.apache.org/newt/newt/install/install.go b/vendor/mynewt.apache.org/newt/newt/install/install.go
new file mode 100644
index 00000000..c5fa0e8d
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/install/install.go
@@ -0,0 +1,989 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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.
+
+// ----------------------------------------------------------------------------
+// install: Handles project installs, upgrades, and syncs.
+// ----------------------------------------------------------------------------
+//
+// This file implements three newt operations:
+// * Install - Downloads repos that aren't installed yet.  The downloaded
+//             version matches what `project.yml` specifies.
+//
+// * Upgrade - Ensures the installed version of each repo matches what
+//             `project.yml` specifies.  This is similar to Install, but it
+//             also operates on already-installed repos.
+//
+// * Sync    - Fetches and pulls the latest for each repo, but does not change
+//             the branch (version).
+//
+// All three operations operate on the repos specified in the `project.yml`
+// file and the set of each repo's dependencies.
+//
+// Within the `project.yml` file, repo requirements are expressed with one of
+// the following forms:
+//     * [Normalized version]: #.#.#
+//           (e.g., "1.3.0")
+//     * [Floating version]:   #[.#]-<stability
+//           (e.g., "0-dev")
+//     * [Git commit]:         <git-commit-ish>-commit
+//           (e.g., "0aae710654b48d9a84d54de771cc18427709df7d-commit")
+//
+// The first two types (normalized version and floating version) are called
+// "version specifiers".  Version specifiers map to "official releases", while
+// git commits typically map to "custom versions".
+//
+// Before newt can do anything with a repo requirement, it needs to extrapolate
+// two pieces of information:
+// 1. The normalized version number.
+// 2. The git commit.
+//
+// Newt needs the normalized version to determine the repo's dependencies, and
+// to ensure the version of the repo is compatible with the version of newt
+// being used.  Newt needs the git commit so that it knows how to checkout the
+// desired repo version.
+//
+// ### VERSION SPECIFIERS
+//
+// A repo's `repository.yml` file maps version specifiers to git commits in its
+// `repo.versions` field.  For example:
+//    repo.versions:
+//        "0.0.0": "master"
+//        "1.0.0": "mynewt_1_0_0_tag"
+//        "1.1.0": "mynewt_1_1_0_tag"
+//        "0-dev": "0.0.0"
+//
+// By performing a series of recursive lookups, newt converts a version
+// specifier to a normalized-version,git-commit pair.
+//
+// ### GIT COMMITS
+//
+// When newt encounters a git commit in the `project.yml` file, it already has
+// one piece of information that it needs: the git commit.  Newt uses the
+// following procedure to extrapolate its corresponding repo version:
+//
+// 1. If the repo at the commit contains a `version.yml` file, read the version
+//    from this file.
+// 2. Else, if the repo's `repository.yml` file maps the commit to a version
+//    number, use that version number.
+// 3. Else, warn the user and assume 0.0.0.
+//
+// The `version.yml` file is expected to be present in every commit in a repo.
+// It has the following form:
+//    repo.version: <normalized-version-number>
+//
+// For example, if commit 10 of repo X contains the following `version.yml`
+// file:
+//    repo.version: 1.10.0
+//
+// and commit 20 of repo X changes `version.yml` to:
+//    repo.version: 2.0.0
+//
+// then newt extrapolates 1.10.0 from commits 10 through 19 (inclusive).
+// Commit 20 and beyond correspond to 2.0.0.
+//
+// ### VERSION STRINGS
+//
+// Newt uses the following procedure when displaying a repo version to the
+// user:
+//
+// Official releases are expressed as a normalized version.
+//     e.g., 1.10.0
+//
+// Custom versions are expressed with the following form:
+//     <extrapolated-version>/<git-commit>
+//
+// E.g.,:
+//     0.0.0/0aae710654b48d9a84d54de771cc18427709df7d
+// ----------------------------------------------------------------------------
+
+package install
+
+import (
+	"bufio"
+	"fmt"
+	"os"
+	"sort"
+	"strings"
+
+	log "github.com/Sirupsen/logrus"
+
+	"mynewt.apache.org/newt/newt/deprepo"
+	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/repo"
+	"mynewt.apache.org/newt/util"
+)
+
+type installOp int
+
+const (
+	INSTALL_OP_INSTALL installOp = iota
+	INSTALL_OP_UPGRADE
+	INSTALL_OP_SYNC
+)
+
+// Determines the currently installed version of the specified repo.  If the
+// repo doesn't have a valid `version.yml` file, and it isn't using a commit
+// that maps to a version, 0.0.0 is returned.
+func detectVersion(r *repo.Repo) (newtutil.RepoVersion, error) {
+	ver, err := r.InstalledVersion()
+	if err != nil {
+		return newtutil.RepoVersion{}, err
+	}
+
+	// Fallback to 0.0.0 if version detection failed.
+	if ver == nil {
+		commit, err := r.CurrentHash()
+		if err != nil {
+			return newtutil.RepoVersion{}, err
+		}
+
+		// Create a 0.0.0 version specifier with the indicated commit string.
+		ver = &newtutil.RepoVersion{
+			Commit: commit,
+		}
+
+		util.StatusMessage(util.VERBOSITY_QUIET,
+			"WARNING: Could not detect version of installed repo \"%s\"; "+
+				"assuming %s\n", r.Name(), ver.String())
+	}
+
+	log.Debugf("currently installed version of repo \"%s\": %s",
+		r.Name(), ver.String())
+
+	return *ver, nil
+}
+
+type Installer struct {
+	// Map of all repos in the project.
+	repos deprepo.RepoMap
+
+	// Version of each installed repo.
+	vers deprepo.VersionMap
+
+	// Required versions of installed repos, as read from `project.yml`.
+	reqs deprepo.RequirementMap
+}
+
+func NewInstaller(repos deprepo.RepoMap,
+	reqs deprepo.RequirementMap) (Installer, error) {
+
+	inst := Installer{
+		repos: repos,
+		vers:  deprepo.VersionMap{},
+		reqs:  reqs,
+	}
+
+	// Detect the installed versions of all repos.
+	var firstErr error
+	for n, r := range inst.repos {
+		if !r.IsLocal() && !r.IsNewlyCloned() {
+			ver, err := detectVersion(r)
+			if err != nil {
+				if firstErr == nil {
+					firstErr = err
+				}
+			} else {
+				inst.vers[n] = ver
+			}
+		}
+	}
+
+	return inst, firstErr
+}
+
+// Retrieves the installed version of the specified repo.  Versions get
+// detected and cached when the installer is constructed.  This function just
+// retrieves the corresponding entry from the cache.
+func (inst *Installer) installedVer(repoName string) *newtutil.RepoVersion {
+	ver, ok := inst.vers[repoName]
+	if !ok {
+		return nil
+	} else {
+		return &ver
+	}
+}
+
+// Given a slice of repos, recursively appends all depended-on repos, ensuring
+// each element is unique.
+//
+// @param repos                 The list of dependent repos to process.
+// @param vm                    Indicates the version of each repo to consider.
+//                                  Pass nil to consider all versions of all
+//                                  repos.
+//
+// @return []*repo.Repo         The original list, augmented with all
+//                                  depended-on repos.
+func (inst *Installer) ensureDepsInList(repos []*repo.Repo,
+	vm deprepo.VersionMap) []*repo.Repo {
+
+	seen := map[string]struct{}{}
+
+	var recurse func(r *repo.Repo) []*repo.Repo
+	recurse = func(r *repo.Repo) []*repo.Repo {
+		// Don't process this repo a second time.
+		if _, ok := seen[r.Name()]; ok {
+			return nil
+		}
+		seen[r.Name()] = struct{}{}
+
+		result := []*repo.Repo{r}
+
+		var deps []*repo.RepoDependency
+		if vm == nil {
+			deps = r.AllDeps()
+		} else {
+			deps = r.DepsForVersion(vm[r.Name()])
+		}
+		for _, d := range deps {
+			depRepo := inst.repos[d.Name]
+			result = append(result, recurse(depRepo)...)
+		}
+
+		return result
+	}
+
+	deps := []*repo.Repo{}
+	for _, r := range repos {
+		deps = append(deps, recurse(r)...)
+	}
+
+	return deps
+}
+
+// Normalizes the installer's set of repo requirements.  Only the repos in the
+// specified slice are considered.
+//
+// A repo requirement takes one of two forms:
+//  * Version specifier (e.g., 1.3.0. or 0-dev).
+//  * Git commit (e.g., 1f48a3c or master).
+//
+// This function converts requirements from the second form to the first.  A
+// git commit is converted to a version number with this procedure:
+//
+// 1. If the specified commit contains a `version.yml` file, read the version
+//    from this file.
+// 2. Else, if the repo's `repository.yml` file maps the commit to a version
+//    number, use that version number.
+// 3. Else, assume 0.0.0.
+func (inst *Installer) inferReqVers(repos []*repo.Repo) error {
+	for _, r := range repos {
+		reqs, ok := inst.reqs[r.Name()]
+		if ok {
+			for i, req := range reqs {
+				if req.Ver.Commit != "" {
+					ver, err := r.NonInstalledVersion(req.Ver.Commit)
+					if err != nil {
+						return err
+					}
+
+					if ver == nil {
+						util.StatusMessage(util.VERBOSITY_QUIET,
+							"WARNING: Could not detect version of "+
+								"requested repo %s:%s; assuming 0.0.0\n",
+							r.Name(), req.Ver.Commit)
+
+						ver = &req.Ver
+					}
+					reqs[i].Ver = *ver
+					reqs[i].Ver.Commit, err = r.HashFromVer(reqs[i].Ver)
+					if err != nil {
+						return err
+					}
+				}
+			}
+		}
+	}
+
+	return nil
+}
+
+// Determines if the `project.yml` file specifies a nonexistent repo version.
+// Only the repos in the specified slice are considered.
+//
+// @param repos                 The list of repos to consider during the check.
+// @param m                     A matrix containing all versions of the
+//                                  specified repos.
+//
+// @return error                Error if any repo requirement is invalid.
+func (inst *Installer) detectIllegalRepoReqs(
+	repos []*repo.Repo, m deprepo.Matrix) error {
+
+	var lines []string
+	for _, r := range repos {
+		reqs, ok := inst.reqs[r.Name()]
+		if ok {
+			row := m.FindRow(r.Name())
+			if row == nil {
+				return util.FmtNewtError(
+					"internal error; repo \"%s\" missing from matrix", r.Name())
+			}
+
+			r := inst.repos[r.Name()]
+			nreqs, err := r.NormalizeVerReqs(reqs)
+			if err != nil {
+				return err
+			}
+
+			anySatisfied := false
+			for _, ver := range row.Vers {
+				if ver.SatisfiesAll(nreqs) {
+					anySatisfied = true
+					break
+				}
+			}
+			if !anySatisfied {
+				line := fmt.Sprintf("    %s,%s", r.Name(),
+					newtutil.RepoVerReqsString(nreqs))
+				lines = append(lines, line)
+			}
+		}
+	}
+
+	if len(lines) > 0 {
+		sort.Strings(lines)
+		return util.NewNewtError(
+			"project.yml file specifies nonexistent repo versions:\n" +
+				strings.Join(lines, "\n"))
+	}
+
+	return nil
+}
+
+// Removes repos that shouldn't be installed from the specified list.  A repo
+// should not be installed if it is already installed (any version).
+//
+// @param repos                 The list of repos to filter.
+//
+// @return []*Repo              The filtered list of repos.
+func (inst *Installer) filterInstallList(
+	vm deprepo.VersionMap) (deprepo.VersionMap, error) {
+
+	filtered := deprepo.VersionMap{}
+
+	for name, ver := range vm {
+		curVer := inst.installedVer(name)
+		if curVer == nil {
+			filtered[name] = ver
+		} else {
+			util.StatusMessage(util.VERBOSITY_DEFAULT,
+				"Skipping \"%s\": already installed (%s)\n",
+				name, curVer.String())
+		}
+	}
+
+	return filtered, nil
+}
+
+// Indicates whether a repo should be upgraded to the specified version.  A
+// repo should be upgraded if it is not currently installed, or if a version
+// other than the desired one is installed.
+func (inst *Installer) shouldUpgradeRepo(
+	repoName string, destVer newtutil.RepoVersion) (bool, error) {
+
+	curVer := inst.installedVer(repoName)
+
+	// If the repo isn't installed, it needs to be upgraded.
+	if curVer == nil {
+		return true, nil
+	}
+
+	r := inst.repos[repoName]
+	if r == nil {
+		return false, util.FmtNewtError(
+			"internal error: nonexistent repo has version: %s", repoName)
+	}
+
+	if !r.VersionsEqual(*curVer, destVer) {
+		return true, nil
+	}
+
+	equiv, err := r.CommitsEquivalent(curVer.Commit, destVer.Commit)
+	if err != nil {
+		return false, err
+	}
+
+	return !equiv, nil
+}
+
+// Removes repos that shouldn't be upgraded from the specified list.  A repo
+// should not be upgraded if the desired version is already installed.
+//
+// @param repos                 The list of repos to filter.
+// @param vm                    Specifies the desired version of each repo.
+//
+// @return []*Repo              The filtered list of repos.
+func (inst *Installer) filterUpgradeList(
+	vm deprepo.VersionMap) (deprepo.VersionMap, error) {
+
+	filtered := deprepo.VersionMap{}
+
+	for name, ver := range vm {
+		doUpgrade, err := inst.shouldUpgradeRepo(name, ver)
+		if err != nil {
+			return nil, err
+		}
+		if doUpgrade {
+			filtered[name] = ver
+		} else {
+			curVer := inst.installedVer(name)
+			if curVer == nil {
+				return nil, util.FmtNewtError(
+					"internal error: should upgrade repo %s, "+
+						"but no version installed",
+					name)
+			}
+			curVer.Commit = ver.Commit
+			util.StatusMessage(util.VERBOSITY_DEFAULT,
+				"Skipping \"%s\": already upgraded (%s)\n",
+				name, curVer.String())
+		}
+	}
+
+	return filtered, nil
+}
+
+// Describes an imminent install or upgrade operation to the user.  The
+// displayed message applies to the specified repo.
+func (inst *Installer) installMessageOneRepo(
+	repoName string, op installOp, force bool, curVer *newtutil.RepoVersion,
+	destVer newtutil.RepoVersion) (string, error) {
+
+	// If the repo isn't installed yet, this is an install, not an upgrade.
+	if op == INSTALL_OP_UPGRADE && curVer == nil {
+		op = INSTALL_OP_INSTALL
+	}
+
+	var verb string
+	switch op {
+	case INSTALL_OP_INSTALL:
+		if !force {
+			verb = "install"
+		} else {
+			verb = "reinstall"
+		}
+
+	case INSTALL_OP_UPGRADE:
+		verb = "upgrade"
+
+	case INSTALL_OP_SYNC:
+		verb = "sync"
+
+	default:
+		return "", util.FmtNewtError(
+			"internal error: invalid install op: %v", op)
+	}
+
+	msg := fmt.Sprintf("    %s %s ", verb, repoName)
+	if op == INSTALL_OP_UPGRADE {
+		msg += fmt.Sprintf("(%s --> %s)", curVer.String(), destVer.String())
+	} else if op != INSTALL_OP_SYNC {
+		msg += fmt.Sprintf("(%s)", destVer.String())
+	} else {
+		// Sync operation.  Don't print the project version.  Instead, print
+		// the actual branch name later during the sync.
+	}
+
+	return msg, nil
+}
+
+// Describes an imminent repo operation to the user.  In addition, prompts the
+// user for confirmation if the `-a` (ask) option was specified.
+func (inst *Installer) installPrompt(vm deprepo.VersionMap, op installOp,
+	force bool, ask bool) (bool, error) {
+
+	if len(vm) == 0 {
+		return true, nil
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"Making the following changes to the project:\n")
+
+	names := vm.SortedNames()
+	for _, name := range names {
+		r := inst.repos[name]
+		curVer := inst.installedVer(name)
+		if curVer != nil && curVer.Commit != "" {
+			c, err := r.CurrentHash()
+			if err == nil {
+				curVer.Commit = c
+			}
+		}
+		destVer := vm[name]
+
+		msg, err := inst.installMessageOneRepo(
+			name, op, force, curVer, destVer)
+		if err != nil {
+			return false, err
+		}
+
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "%s\n", msg)
+	}
+
+	if !ask {
+		return true, nil
+	}
+
+	for {
+		fmt.Printf("Proceed? [Y/n] ")
+		line, more, err := bufio.NewReader(os.Stdin).ReadLine()
+		if more || err != nil {
+			return false, util.ChildNewtError(err)
+		}
+
+		trimmed := strings.ToLower(strings.TrimSpace(string(line)))
+		if len(trimmed) == 0 || strings.HasPrefix(trimmed, "y") {
+			// User wants to proceed.
+			return true, nil
+		}
+
+		if strings.HasPrefix(trimmed, "n") {
+			// User wants to cancel.
+			return false, nil
+		}
+
+		// Invalid response.
+		fmt.Printf("Invalid response.\n")
+	}
+}
+
+// Determines whether a repo version's `Commit` field should be maintained.  If
+// the commit corresponds exactly to a repo version in `repository.yml` (as
+// opposed to simply indicating its version in a `version.yml` file), then the
+// commit string should be discarded.  If the commit string is kept, newt
+// interprets the version as being different from the official release version,
+// triggering an upgrade.
+func (inst *Installer) shouldKeepCommit(
+	repoName string, commit string) (bool, error) {
+
+	if commit == "" {
+		return false, nil
+	}
+
+	r := inst.repos[repoName]
+	if r == nil {
+		return false, nil
+	}
+
+	vers, err := r.VersFromEquivCommit(commit)
+	if err != nil {
+		return false, err
+	}
+	if len(vers) > 0 {
+		return false, nil
+	}
+
+	return true, nil
+}
+
+// Filters out repos from a version map, keeping only those which are present
+// in the supplied slice.
+func filterVersionMap(
+	vm deprepo.VersionMap, keep []*repo.Repo) deprepo.VersionMap {
+
+	filtered := deprepo.VersionMap{}
+	for _, r := range keep {
+		name := r.Name()
+		if ver, ok := vm[name]; ok {
+			filtered[name] = ver
+		}
+	}
+
+	return filtered
+}
+
+// Creates a slice of repos, each corresponding to an element in the provided
+// version map.  The returned slice is sorted by repo name.
+func (inst *Installer) versionMapRepos(
+	vm deprepo.VersionMap) ([]*repo.Repo, error) {
+
+	repos := make([]*repo.Repo, 0, len(vm))
+
+	names := vm.SortedNames()
+	for _, name := range names {
+		r := inst.repos[name]
+		if r == nil {
+			return nil, util.FmtNewtError(
+				"internal error: repo \"%s\" missing from Installer#repos",
+				name)
+		}
+
+		repos = append(repos, r)
+	}
+
+	return repos, nil
+}
+
+// Calculates a map of repos and version numbers that should be included in an
+// install or upgrade operation.
+func (inst *Installer) calcVersionMap(candidates []*repo.Repo) (
+	deprepo.VersionMap, error) {
+
+	// Repos that depend on any specified repos must also be considered during
+	// the install / upgrade operation.
+	repoList := inst.ensureDepsInList(candidates, nil)
+
+	m, err := deprepo.BuildMatrix(repoList, inst.vers)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := inst.inferReqVers(repoList); err != nil {
+		return nil, err
+	}
+
+	// If the `project.yml` file specifies an invalid repo version, abort now.
+	if err := inst.detectIllegalRepoReqs(repoList, m); err != nil {
+		return nil, err
+	}
+
+	// Remove blocked repo versions from the table.
+	if err := deprepo.PruneMatrix(
+		&m, inst.repos, inst.reqs); err != nil {
+
+		return nil, err
+	}
+
+	// Construct a repo dependency graph from the `project.yml` version
+	// requirements and from each repo's dependency list.
+	dg, err := deprepo.BuildDepGraph(inst.repos, inst.reqs)
+	if err != nil {
+		return nil, err
+	}
+
+	log.Debugf("Repo dependency graph:\n%s\n", dg.String())
+	log.Debugf("Repo reverse dependency graph:\n%s\n", dg.Reverse().String())
+
+	// Try to find a version set that satisfies the dependency graph.  If no
+	// such set exists, report the conflicts and abort.
+	vm, conflicts := deprepo.FindAcceptableVersions(m, dg)
+	if vm == nil {
+		return nil, deprepo.ConflictError(conflicts)
+	}
+
+	log.Debugf("Repo version map:\n%s\n", vm.String())
+
+	// If project.yml specified any specific git commits, ensure we get them.
+	for name, ver := range vm {
+		reqs := inst.reqs[name]
+		if len(reqs) > 0 {
+			keep, err := inst.shouldKeepCommit(name, reqs[0].Ver.Commit)
+			if err != nil {
+				return nil, err
+			}
+			if keep {
+				ver.Commit = reqs[0].Ver.Commit
+			}
+			vm[name] = ver
+		}
+	}
+
+	// Now that we know which repo versions we want, we can eliminate some
+	// false-positives from the repo list.
+	repoList = inst.ensureDepsInList(candidates, vm)
+	vm = filterVersionMap(vm, repoList)
+
+	return vm, nil
+}
+
+// Checks if any repos in the specified slice are in a dirty state.  If any
+// repos are dirty and `force` is *not* enabled, an error is returned.  If any
+// repos are dirty and `force` is enabled, a warning is displayed.
+func verifyRepoDirtyState(repos []*repo.Repo, force bool) error {
+	// [repo] => dirty-state.
+	var m map[*repo.Repo]string
+
+	// Collect all dirty repos and insert them into m.
+	for _, r := range repos {
+		dirtyState, err := r.DirtyState()
+		if err != nil {
+			return err
+		}
+
+		if dirtyState != "" {
+			if m == nil {
+				m = make(map[*repo.Repo]string)
+				m[r] = dirtyState
+			}
+		}
+	}
+
+	if len(m) > 0 {
+		s := "some repos are in a dirty state:\n"
+		for r, d := range m {
+			s += fmt.Sprintf("    %s: contains %s\n", r.Name(), d)
+		}
+
+		if !force {
+			s += "Specify the `-f` (force) switch to attempt anyway"
+			return util.NewNewtError(s)
+		} else {
+			util.StatusMessage(util.VERBOSITY_QUIET, "WARNING: %s\n", s)
+		}
+	}
+
+	return nil
+}
+
+// Installs the specified set of repos.
+func (inst *Installer) Install(
+	candidates []*repo.Repo, force bool, ask bool) error {
+
+	vm, err := inst.calcVersionMap(candidates)
+	if err != nil {
+		return err
+	}
+
+	// Perform some additional filtering on the list of repos to process.
+	if !force {
+		// Don't install a repo if it is already installed (any version).  We
+		// skip this filter for forced reinstalls.
+		vm, err = inst.filterInstallList(vm)
+		if err != nil {
+			return err
+		}
+	}
+
+	// Notify the user of what install operations are about to happen, and
+	// prompt if the `-a` (ask) option was specified.
+	proceed, err := inst.installPrompt(vm, INSTALL_OP_INSTALL, force, ask)
+	if err != nil {
+		return err
+	}
+	if !proceed {
+		return nil
+	}
+
+	repos, err := inst.versionMapRepos(vm)
+	if err != nil {
+		return err
+	}
+
+	// For a forced install, delete all existing repos.
+	if force {
+		for _, r := range repos {
+			// Don't delete the local project directory!  And don't delete a
+			// repo that was just cloned during this invocation of newt.
+			if !r.IsLocal() && !r.IsNewlyCloned() {
+				util.StatusMessage(util.VERBOSITY_DEFAULT,
+					"Removing old copy of \"%s\" (%s)\n", r.Name(), r.Path())
+				os.RemoveAll(r.Path())
+				delete(inst.vers, r.Name())
+			}
+		}
+	}
+
+	// Install each repo in the version map.
+	for _, r := range repos {
+		destVer := vm[r.Name()]
+		if err := r.Install(destVer); err != nil {
+			return err
+		}
+
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"%s successfully installed version %s\n",
+			r.Name(), destVer.String())
+	}
+
+	return nil
+}
+
+// Installs or upgrades the specified set of repos.
+func (inst *Installer) Upgrade(candidates []*repo.Repo, force bool,
+	ask bool) error {
+
+	if err := verifyRepoDirtyState(candidates, force); err != nil {
+		return err
+	}
+
+	vm, err := inst.calcVersionMap(candidates)
+	if err != nil {
+		return err
+	}
+
+	// Don't upgrade a repo if we already have the desired version.
+	vm, err = inst.filterUpgradeList(vm)
+	if err != nil {
+		return err
+	}
+
+	// Notify the user of what install operations are about to happen, and
+	// prompt if the `-a` (ask) option was specified.
+	proceed, err := inst.installPrompt(vm, INSTALL_OP_UPGRADE, false, ask)
+	if err != nil {
+		return err
+	}
+	if !proceed {
+		return nil
+	}
+
+	repos, err := inst.versionMapRepos(vm)
+	if err != nil {
+		return err
+	}
+
+	// Upgrade each repo in the version map.
+	for _, r := range repos {
+		destVer := vm[r.Name()]
+		if err := r.Upgrade(destVer); err != nil {
+			return err
+		}
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"%s successfully upgraded to version %s\n",
+			r.Name(), destVer.String())
+	}
+
+	return nil
+}
+
+// Syncs the specified set of repos.
+func (inst *Installer) Sync(candidates []*repo.Repo,
+	force bool, ask bool) error {
+
+	if err := verifyRepoDirtyState(candidates, force); err != nil {
+		return err
+	}
+
+	vm, err := inst.calcVersionMap(candidates)
+	if err != nil {
+		return err
+	}
+
+	// Notify the user of what install operations are about to happen, and
+	// prompt if the `-a` (ask) option was specified.
+	proceed, err := inst.installPrompt(vm, INSTALL_OP_SYNC, false, ask)
+	if err != nil {
+		return err
+	}
+	if !proceed {
+		return nil
+	}
+
+	repos, err := inst.versionMapRepos(vm)
+	if err != nil {
+		return err
+	}
+
+	// Sync each repo in the list.
+	var anyFails bool
+	for _, r := range repos {
+		ver := inst.installedVer(r.Name())
+		if ver == nil {
+			util.StatusMessage(util.VERBOSITY_DEFAULT,
+				"No installed version of %s found, skipping\n",
+				r.Name())
+		} else {
+			if _, err := r.Sync(*ver); err != nil {
+				util.StatusMessage(util.VERBOSITY_QUIET,
+					"Failed to sync repo \"%s\": %s\n",
+					r.Name(), err.Error())
+				anyFails = true
+			}
+		}
+	}
+
+	if anyFails {
+		return util.FmtNewtError("Failed to sync")
+	}
+
+	return nil
+}
+
+type repoInfo struct {
+	installedVer *newtutil.RepoVersion
+	errorText    string
+	dirtyState   string
+	needsUpgrade bool
+}
+
+// Collects information about the specified repo.  If a version map is provided
+// (i.e., vm is not nil), this function also queries the repo's remote to
+// determine if the repo can be upgraded.
+func (inst *Installer) gatherInfo(r *repo.Repo,
+	vm *deprepo.VersionMap) repoInfo {
+
+	ri := repoInfo{}
+
+	if !r.CheckExists() {
+		return ri
+	}
+
+	ver, err := r.InstalledVersion()
+	if err != nil {
+		ri.errorText = strings.TrimSpace(err.Error())
+		return ri
+	}
+	ri.installedVer = ver
+
+	dirty, err := r.DirtyState()
+	if err != nil {
+		ri.errorText = strings.TrimSpace(err.Error())
+		return ri
+	}
+	ri.dirtyState = dirty
+
+	if vm != nil {
+		if ver == nil || *ver != (*vm)[r.Name()] {
+			ri.needsUpgrade = true
+		}
+	}
+
+	return ri
+}
+
+// Prints out information about the specified repos:
+//     * Currently installed version.
+//     * Whether upgrade is possible.
+//     * Whether repo is in a dirty state.
+//
+// @param repos                 The set of repositories to inspect.
+// @param remote                Whether to perform any remote queries to
+//                                  determine if upgrades are needed.
+func (inst *Installer) Info(repos []*repo.Repo, remote bool) error {
+	var vmp *deprepo.VersionMap
+
+	if remote {
+		vm, err := inst.calcVersionMap(repos)
+		if err != nil {
+			return err
+		}
+
+		vmp = &vm
+	}
+
+	util.StatusMessage(util.VERBOSITY_DEFAULT, "Repository info:\n")
+	for _, r := range repos {
+		ri := inst.gatherInfo(r, vmp)
+		s := fmt.Sprintf("    * %s:", r.Name())
+
+		if ri.installedVer == nil {
+			s += " (not installed)"
+		} else if ri.errorText != "" {
+			s += fmt.Sprintf(" (unknown: %s)", ri.errorText)
+		} else {
+			s += fmt.Sprintf(" %s", ri.installedVer.String())
+			if ri.dirtyState != "" {
+				s += fmt.Sprintf(" (dirty: %s)", ri.dirtyState)
+			}
+			if ri.needsUpgrade {
+				s += " (needs upgrade)"
+			}
+		}
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "%s\n", s)
+	}
+
+	return nil
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/interfaces/interfaces.go b/vendor/mynewt.apache.org/newt/newt/interfaces/interfaces.go
index 12826d02..e84d7a2c 100644
--- a/vendor/mynewt.apache.org/newt/newt/interfaces/interfaces.go
+++ b/vendor/mynewt.apache.org/newt/newt/interfaces/interfaces.go
@@ -35,23 +35,6 @@ type RepoInterface interface {
 	Path() string
 }
 
-type VersionReqInterface interface {
-	CompareType() string
-	Version() VersionInterface
-	String() string
-}
-
-type VersionInterface interface {
-	SatisfiesVersion(versReq []VersionReqInterface) bool
-	CompareVersions(vers1 VersionInterface, vers2 VersionInterface) int64
-	Major() int64
-	Minor() int64
-	Revision() int64
-	Stability() string
-	Tag() string
-	String() string
-}
-
 type PackageList map[string]*map[string]PackageInterface
 
 type DependencyInterface interface {
@@ -66,6 +49,7 @@ type ProjectInterface interface {
 	ResolvePath(basePath string, name string) (string, error)
 	PackageList() PackageList
 	FindRepoPath(rname string) string
+	RepoIsInstalled(rname string) bool
 }
 
 var globalProject ProjectInterface
diff --git a/vendor/mynewt.apache.org/newt/newt/mfg/load.go b/vendor/mynewt.apache.org/newt/newt/mfg/load.go
index b2250ed4..e17635b1 100644
--- a/vendor/mynewt.apache.org/newt/newt/mfg/load.go
+++ b/vendor/mynewt.apache.org/newt/newt/mfg/load.go
@@ -28,6 +28,7 @@ import (
 
 	"github.com/spf13/cast"
 
+	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/project"
 	"mynewt.apache.org/newt/newt/target"
@@ -220,7 +221,7 @@ func (mi *MfgImage) detectOverlaps() error {
 }
 
 func Load(basePkg *pkg.LocalPackage) (*MfgImage, error) {
-	v, err := util.ReadConfig(basePkg.BasePath(),
+	v, err := newtutil.ReadConfig(basePkg.BasePath(),
 		strings.TrimSuffix(MFG_YAML_FILENAME, ".yml"))
 	if err != nil {
 		return nil, err
@@ -230,7 +231,7 @@ func Load(basePkg *pkg.LocalPackage) (*MfgImage, error) {
 		basePkg: basePkg,
 	}
 
-	bootName := v.GetString("mfg.bootloader")
+	bootName := v.GetValString("mfg.bootloader", nil)
 	if bootName == "" {
 		return nil, mi.loadError("mfg.bootloader field required")
 	}
@@ -239,7 +240,7 @@ func Load(basePkg *pkg.LocalPackage) (*MfgImage, error) {
 		return nil, err
 	}
 
-	imgNames := v.GetStringSlice("mfg.images")
+	imgNames := v.GetValStringSlice("mfg.images", nil)
 	if imgNames != nil {
 		for _, imgName := range imgNames {
 			imgTarget, err := mi.loadTarget(imgName)
@@ -256,7 +257,7 @@ func Load(basePkg *pkg.LocalPackage) (*MfgImage, error) {
 			len(mi.images))
 	}
 
-	itf := v.Get("mfg.raw")
+	itf := v.GetFirstVal("mfg.raw", nil)
 	slice := cast.ToSlice(itf)
 	if slice != nil {
 		for i, entryItf := range slice {
@@ -289,7 +290,7 @@ func Load(basePkg *pkg.LocalPackage) (*MfgImage, error) {
 		return nil, mi.loadError(err.Error())
 	}
 	mi.compiler, err = toolchain.NewCompiler(compilerPkg.BasePath(), "",
-							target.DEFAULT_BUILD_PROFILE)
+		target.DEFAULT_BUILD_PROFILE)
 	if err != nil {
 		return nil, mi.loadError(err.Error())
 	}
diff --git a/vendor/mynewt.apache.org/newt/newt/newtutil/newtutil.go b/vendor/mynewt.apache.org/newt/newt/newtutil/newtutil.go
index a5e70509..5b83bc8e 100644
--- a/vendor/mynewt.apache.org/newt/newt/newtutil/newtutil.go
+++ b/vendor/mynewt.apache.org/newt/newt/newtutil/newtutil.go
@@ -21,27 +21,22 @@ package newtutil
 
 import (
 	"fmt"
-	"os/user"
-	"sort"
+	"io/ioutil"
 	"strconv"
 	"strings"
 
-	log "github.com/Sirupsen/logrus"
-	"github.com/spf13/cast"
-
 	"mynewt.apache.org/newt/newt/interfaces"
+	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
-	"mynewt.apache.org/newt/viper"
+	"mynewt.apache.org/newt/yaml"
 )
 
-var NewtVersion Version = Version{1, 1, 0}
-var NewtVersionStr string = "Apache Newt version: 1.1.0-dev"
-var NewtBlinkyTag string = "develop"
+var NewtVersion Version = Version{1, 4, 9999}
+var NewtVersionStr string = "Apache Newt version: 1.5.0-dev"
+var NewtBlinkyTag string = "master"
 var NewtNumJobs int
 var NewtForce bool
-
-const NEWTRC_DIR string = ".newt"
-const REPOS_FILENAME string = "repos.yml"
+var NewtAsk bool
 
 const CORE_REPO_NAME string = "apache-mynewt-core"
 const ARDUINO_ZERO_REPO_NAME string = "mynewt_arduino_zero"
@@ -101,144 +96,6 @@ func VerCmp(v1 Version, v2 Version) int64 {
 	return 0
 }
 
-// Contains general newt settings read from $HOME/.newt
-var newtrc *viper.Viper
-
-func readNewtrc() *viper.Viper {
-	usr, err := user.Current()
-	if err != nil {
-		log.Warn("Failed to obtain user name")
-		return viper.New()
-	}
-
-	dir := usr.HomeDir + "/" + NEWTRC_DIR
-	v, err := util.ReadConfig(dir, strings.TrimSuffix(REPOS_FILENAME, ".yml"))
-	if err != nil {
-		log.Debugf("Failed to read %s/%s file", dir, REPOS_FILENAME)
-		return viper.New()
-	}
-
-	return v
-}
-
-func Newtrc() *viper.Viper {
-	if newtrc != nil {
-		return newtrc
-	}
-
-	newtrc = readNewtrc()
-	return newtrc
-}
-
-func GetSliceFeatures(v *viper.Viper, features map[string]bool,
-	key string) []interface{} {
-
-	val := v.Get(key)
-	vals := []interface{}{val}
-
-	// Process the features in alphabetical order to ensure consistent
-	// results across repeated runs.
-	featureKeys := make([]string, 0, len(features))
-	for feature, _ := range features {
-		featureKeys = append(featureKeys, feature)
-	}
-	sort.Strings(featureKeys)
-
-	for _, feature := range featureKeys {
-		overwriteVal := v.Get(key + "." + feature + ".OVERWRITE")
-		if overwriteVal != nil {
-			return []interface{}{overwriteVal}
-		}
-
-		appendVal := v.Get(key + "." + feature)
-		if appendVal != nil {
-			vals = append(vals, appendVal)
-		}
-	}
-
-	return vals
-}
-
-func GetStringMapFeatures(v *viper.Viper, features map[string]bool,
-	key string) map[string]interface{} {
-
-	result := map[string]interface{}{}
-
-	slice := GetSliceFeatures(v, features, key)
-	for _, itf := range slice {
-		sub := cast.ToStringMap(itf)
-		for k, v := range sub {
-			result[k] = v
-		}
-	}
-
-	return result
-}
-
-func GetStringFeatures(v *viper.Viper, features map[string]bool,
-	key string) string {
-	val := v.GetString(key)
-
-	// Process the features in alphabetical order to ensure consistent
-	// results across repeated runs.
-	var featureKeys []string
-	for feature, _ := range features {
-		featureKeys = append(featureKeys, feature)
-	}
-	sort.Strings(featureKeys)
-
-	for _, feature := range featureKeys {
-		overwriteVal := v.GetString(key + "." + feature + ".OVERWRITE")
-		if overwriteVal != "" {
-			val = strings.Trim(overwriteVal, "\n")
-			break
-		}
-
-		appendVal := v.GetString(key + "." + feature)
-		if appendVal != "" {
-			val += " " + strings.Trim(appendVal, "\n")
-		}
-	}
-	return strings.TrimSpace(val)
-}
-
-func GetBoolFeaturesDflt(v *viper.Viper, features map[string]bool,
-	key string, dflt bool) (bool, error) {
-
-	s := GetStringFeatures(v, features, key)
-	if s == "" {
-		return dflt, nil
-	}
-
-	b, err := strconv.ParseBool(s)
-	if err != nil {
-		return dflt, util.FmtNewtError("invalid bool value for %s: %s",
-			key, s)
-	}
-
-	return b, nil
-}
-
-func GetBoolFeatures(v *viper.Viper, features map[string]bool,
-	key string) (bool, error) {
-
-	return GetBoolFeaturesDflt(v, features, key, false)
-}
-
-func GetStringSliceFeatures(v *viper.Viper, features map[string]bool,
-	key string) []string {
-
-	vals := GetSliceFeatures(v, features, key)
-
-	strVals := []string{}
-	for _, v := range vals {
-		subVals := cast.ToStringSlice(v)
-		strVals = append(strVals, subVals...)
-	}
-
-	return strVals
-}
-
 // Parses a string of the following form:
 //     [@repo]<path/to/package>
 //
@@ -307,3 +164,40 @@ func GeneratedPreamble() string {
 	return fmt.Sprintf("/**\n * This file was generated by %s\n */\n\n",
 		NewtVersionStr)
 }
+
+// Creates a temporary directory for downloading a repo.
+func MakeTempRepoDir() (string, error) {
+	tmpdir, err := ioutil.TempDir("", "newt-repo")
+	if err != nil {
+		return "", util.ChildNewtError(err)
+	}
+
+	return tmpdir, nil
+}
+
+func ReadConfigPath(path string) (ycfg.YCfg, error) {
+	file, err := ioutil.ReadFile(path)
+	if err != nil {
+		return nil, util.NewNewtError(fmt.Sprintf("Error reading %s: %s",
+			path, err.Error()))
+	}
+
+	settings := map[string]interface{}{}
+	if err := yaml.Unmarshal(file, &settings); err != nil {
+		return nil, util.FmtNewtError("Failure parsing \"%s\": %s",
+			path, err.Error())
+	}
+
+	return ycfg.NewYCfg(settings)
+}
+
+// Read in the configuration file specified by name, in path
+// return a new viper config object if successful, and error if not
+func ReadConfig(dir string, filename string) (ycfg.YCfg, error) {
+	return ReadConfigPath(dir + "/" + filename + ".yml")
+}
+
+// Converts the provided YAML-configuration map to a YAML-encoded string.
+func YCfgToYaml(yc ycfg.YCfg) string {
+	return yaml.MapToYaml(yc.AllSettings())
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/newtutil/repo_version.go b/vendor/mynewt.apache.org/newt/newt/newtutil/repo_version.go
new file mode 100644
index 00000000..ea6bac67
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/newtutil/repo_version.go
@@ -0,0 +1,323 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package newtutil
+
+import (
+	"fmt"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+
+	"mynewt.apache.org/newt/util"
+
+	log "github.com/Sirupsen/logrus"
+)
+
+const (
+	VERSION_STABILITY_NONE   = ""
+	VERSION_STABILITY_STABLE = "stable"
+	VERSION_STABILITY_DEV    = "dev"
+	VERSION_STABILITY_LATEST = "latest"
+
+	// "commit" is not actually a stability, but it takes the place of one in
+	// the repo version notation.  The "commit" string indicates a commit hash,
+	// tag, or branch, rather than a version specifier.
+	VERSION_STABILITY_COMMIT = "commit"
+)
+
+// Represents an unspecified part in a version.  For example, in "1-latest",
+// the minor and revision parts are floating.
+const VERSION_FLOATING = -1
+
+type RepoVersionReq struct {
+	CompareType string
+	Ver         RepoVersion
+}
+
+type RepoVersion struct {
+	Major     int64
+	Minor     int64
+	Revision  int64
+	Stability string
+	Commit    string
+}
+
+func (v *RepoVersion) IsNormalized() bool {
+	return v.Stability == VERSION_STABILITY_NONE
+}
+
+func (vm *RepoVersionReq) String() string {
+	return vm.CompareType + vm.Ver.String()
+}
+
+func CompareRepoVersions(v1 RepoVersion, v2 RepoVersion) int64 {
+	if r := v1.Major - v2.Major; r != 0 {
+		return r
+	}
+
+	if r := v1.Minor - v2.Minor; r != 0 {
+		return r
+	}
+
+	if r := v1.Revision - v2.Revision; r != 0 {
+		return r
+	}
+
+	return 0
+}
+
+func (v *RepoVersion) Satisfies(verReq RepoVersionReq) bool {
+	if verReq.Ver.Commit != "" && verReq.CompareType != "==" {
+		log.Warningf("RepoVersion comparison with a tag %s %s %s",
+			verReq.Ver, verReq.CompareType, v)
+	}
+	r := CompareRepoVersions(verReq.Ver, *v)
+	switch verReq.CompareType {
+	case "<":
+		if r <= 0 {
+			return false
+		}
+	case "<=":
+		if r < 0 {
+			return false
+		}
+	case ">":
+		if r >= 0 {
+			return false
+		}
+	case ">=":
+		if r > 0 {
+			return false
+		}
+	case "==":
+		if r != 0 {
+			return false
+		}
+	}
+
+	if verReq.Ver.Stability != v.Stability {
+		return false
+	}
+
+	return true
+}
+
+func (v *RepoVersion) SatisfiesAll(verReqs []RepoVersionReq) bool {
+	for _, r := range verReqs {
+		if !v.Satisfies(r) {
+			return false
+		}
+	}
+
+	return true
+}
+
+func (ver *RepoVersion) String() string {
+	s := fmt.Sprintf("%d", ver.Major)
+	if ver.Minor != VERSION_FLOATING {
+		s += fmt.Sprintf(".%d", ver.Minor)
+	}
+	if ver.Revision != VERSION_FLOATING {
+		s += fmt.Sprintf(".%d", ver.Revision)
+	}
+
+	if ver.Stability != VERSION_STABILITY_NONE {
+		s += fmt.Sprintf("-%s", ver.Stability)
+	}
+
+	if ver.Commit != "" {
+		s += fmt.Sprintf("/%s", ver.Commit)
+	}
+
+	return s
+}
+
+func (ver *RepoVersion) ToNuVersion() Version {
+	return Version{
+		Major:    ver.Major,
+		Minor:    ver.Minor,
+		Revision: ver.Revision,
+	}
+}
+
+func ParseRepoVersion(verStr string) (RepoVersion, error) {
+	var err error
+
+	stability := VERSION_STABILITY_NONE
+	base := verStr
+
+	dashIdx := strings.LastIndex(verStr, "-")
+	if dashIdx != -1 {
+		stability = strings.TrimSpace(verStr[dashIdx+1:])
+		base = strings.TrimSpace(verStr[:dashIdx])
+
+		switch stability {
+		case VERSION_STABILITY_COMMIT:
+			return RepoVersion{Commit: strings.TrimSpace(base)}, nil
+
+		case VERSION_STABILITY_STABLE:
+		case VERSION_STABILITY_DEV:
+		case VERSION_STABILITY_LATEST:
+
+		default:
+			return RepoVersion{}, util.FmtNewtError(
+				"Unknown stability (%s) in version %s", stability, verStr)
+		}
+	}
+
+	parts := strings.Split(base, ".")
+	if len(parts) > 3 {
+		return RepoVersion{},
+			util.FmtNewtError("Invalid version string: %s", verStr)
+	}
+
+	if len(parts) != 3 && stability == VERSION_STABILITY_NONE {
+		return RepoVersion{},
+			util.FmtNewtError("Invalid version string: %s", verStr)
+	}
+
+	// Assume no parts of the version are specified.
+	ver := RepoVersion{
+		Major:     VERSION_FLOATING,
+		Minor:     VERSION_FLOATING,
+		Revision:  VERSION_FLOATING,
+		Stability: stability,
+	}
+
+	// Convert each dot-delimited part to an integer.
+	if ver.Major, err = strconv.ParseInt(parts[0], 10, 64); err != nil {
+		return RepoVersion{}, util.NewNewtError(err.Error())
+	}
+	if len(parts) >= 2 {
+		if ver.Minor, err = strconv.ParseInt(parts[1], 10, 64); err != nil {
+			return RepoVersion{}, util.NewNewtError(err.Error())
+		}
+	}
+	if len(parts) == 3 {
+		if ver.Revision, err = strconv.ParseInt(parts[2], 10, 64); err != nil {
+			return RepoVersion{}, util.NewNewtError(err.Error())
+		}
+	}
+
+	return ver, nil
+}
+
+// Parse a set of version string constraints on a dependency.
+// This function
+// The version string contains a list of version constraints in the following format:
+//    - <comparison><version>
+// Where <comparison> can be any one of the following comparison
+//   operators: <=, <, >, >=, ==
+// And <version> is specified in the form: X.Y.Z where X, Y and Z are all
+// int64 types in decimal form
+func ParseRepoVersionReqs(versStr string) ([]RepoVersionReq, error) {
+	var err error
+
+	verReqs := []RepoVersionReq{}
+
+	re, err := regexp.Compile(`(<=|>=|==|>|<)([\d\.]+)`)
+	if err != nil {
+		return nil, err
+	}
+
+	matches := re.FindAllStringSubmatch(versStr, -1)
+	if matches != nil {
+		for _, match := range matches {
+			vm := RepoVersionReq{}
+			vm.CompareType = match[1]
+			if vm.Ver, err = ParseRepoVersion(match[2]); err != nil {
+				return nil, err
+			}
+
+			verReqs = append(verReqs, vm)
+		}
+	} else {
+		vm := RepoVersionReq{}
+		vm.CompareType = "=="
+		if vm.Ver, err = ParseRepoVersion(versStr); err != nil {
+			return nil, err
+		}
+
+		verReqs = append(verReqs, vm)
+	}
+
+	if len(verReqs) == 0 {
+		verReqs = nil
+	}
+
+	return verReqs, nil
+}
+
+func RepoVerReqsString(verReqs []RepoVersionReq) string {
+	s := ""
+	for i, r := range verReqs {
+		if i != 0 {
+			s += " "
+		}
+		s += r.String()
+	}
+
+	return s
+}
+
+type verSorter struct {
+	vers []RepoVersion
+}
+
+func (v verSorter) Len() int {
+	return len(v.vers)
+}
+func (v verSorter) Swap(i, j int) {
+	v.vers[i], v.vers[j] = v.vers[j], v.vers[i]
+}
+func (v verSorter) Less(i, j int) bool {
+	a := v.vers[i]
+	b := v.vers[j]
+
+	return CompareRepoVersions(a, b) < 0
+}
+
+func SortVersions(vers []RepoVersion) {
+	sorter := verSorter{
+		vers: vers,
+	}
+
+	sort.Sort(sorter)
+}
+
+func SortedVersions(vers []RepoVersion) []RepoVersion {
+	clone := make([]RepoVersion, len(vers))
+	copy(clone, vers)
+
+	SortVersions(clone)
+	return clone
+}
+
+func SortedVersionsDesc(vers []RepoVersion) []RepoVersion {
+	slice := SortedVersions(vers)
+	size := len(slice)
+	for i := 0; i < size/2; i++ {
+		j := size - 1 - i
+		slice[i], slice[j] = slice[j], slice[i]
+	}
+
+	return slice
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/parse/lex.go b/vendor/mynewt.apache.org/newt/newt/parse/lex.go
new file mode 100644
index 00000000..7701f4c2
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/parse/lex.go
@@ -0,0 +1,202 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package parse
+
+import (
+	"fmt"
+	"strings"
+
+	"mynewt.apache.org/newt/util"
+)
+
+type TokenCode int
+
+const (
+	TOKEN_NOT_EQUALS TokenCode = iota
+	TOKEN_NOT
+	TOKEN_EQUALS
+	TOKEN_LT
+	TOKEN_LTE
+	TOKEN_GT
+	TOKEN_GTE
+	TOKEN_AND
+	TOKEN_OR
+	TOKEN_XOR
+	TOKEN_LPAREN
+	TOKEN_RPAREN
+	TOKEN_STRING
+	TOKEN_NUMBER
+	TOKEN_IDENT
+)
+
+type Token struct {
+	Code   TokenCode
+	Text   string
+	Offset int
+}
+
+// Returns length of token on success; 0 if no match.
+type LexFn func(s string) (string, int, error)
+
+const delimChars = "!='\"&|^() \t\n"
+
+func lexString(s string, sought string) (string, int, error) {
+	if strings.HasPrefix(s, sought) {
+		return sought, len(sought), nil
+	}
+
+	return "", 0, nil
+}
+
+func lexStringFn(sought string) LexFn {
+	return func(s string) (string, int, error) { return lexString(s, sought) }
+}
+
+func lexLitNumber(s string) (string, int, error) {
+	var sub string
+	idx := strings.IndexAny(s, delimChars)
+	if idx == -1 {
+		sub = s
+	} else {
+		sub = s[:idx]
+	}
+	if _, ok := util.AtoiNoOctTry(sub); ok {
+		return sub, len(sub), nil
+	}
+
+	return "", 0, nil
+}
+
+func lexLitString(s string) (string, int, error) {
+	if s[0] != '"' {
+		return "", 0, nil
+	}
+
+	quote2 := strings.IndexByte(s[1:], '"')
+	if quote2 == -1 {
+		return "", 0, fmt.Errorf("unterminated quote: %s", s)
+	}
+
+	return s[1 : quote2+1], quote2 + 2, nil
+}
+
+func lexIdent(s string) (string, int, error) {
+	idx := strings.IndexAny(s, delimChars)
+	if idx == -1 {
+		return s, len(s), nil
+	} else {
+		return s[:idx], idx, nil
+	}
+}
+
+type lexEntry struct {
+	code TokenCode
+	fn   LexFn
+}
+
+var lexEntries = []lexEntry{
+	{TOKEN_NOT_EQUALS, lexStringFn("!=")},
+	{TOKEN_EQUALS, lexStringFn("==")},
+	{TOKEN_AND, lexStringFn("&&")},
+	{TOKEN_OR, lexStringFn("||")},
+	{TOKEN_XOR, lexStringFn("^^")},
+	{TOKEN_LTE, lexStringFn("<=")},
+	{TOKEN_GTE, lexStringFn(">=")},
+	{TOKEN_NOT, lexStringFn("!")},
+	{TOKEN_LT, lexStringFn("<")},
+	{TOKEN_GT, lexStringFn(">")},
+	{TOKEN_LPAREN, lexStringFn("(")},
+	{TOKEN_RPAREN, lexStringFn(")")},
+	{TOKEN_STRING, lexLitString},
+	{TOKEN_NUMBER, lexLitNumber},
+	{TOKEN_IDENT, lexIdent},
+}
+
+func lexOneToken(expr string, offset int) (Token, int, error) {
+	var t Token
+
+	subexpr := expr[offset:]
+	for _, e := range lexEntries {
+		text, sz, err := e.fn(subexpr)
+		if err != nil {
+			return t, 0, err
+		}
+
+		if sz != 0 {
+			t.Code = e.code
+			t.Text = text
+			t.Offset = offset
+			return t, sz, nil
+		}
+	}
+
+	return t, 0, nil
+}
+
+func skipSpaceLeft(s string, offset int) int {
+	sub := s[offset:]
+	newSub := strings.TrimLeft(sub, " \t\n'")
+	return len(sub) - len(newSub)
+}
+
+// Tokenizes a string.
+func Lex(expr string) ([]Token, error) {
+	tokens := []Token{}
+	off := 0
+
+	off += skipSpaceLeft(expr, off)
+	for off < len(expr) {
+		t, skip, err := lexOneToken(expr, off)
+		if err != nil {
+			return nil, err
+		}
+
+		if skip == 0 {
+			return nil, fmt.Errorf("Invalid token starting with: %s", expr)
+		}
+
+		tokens = append(tokens, t)
+
+		off += skip
+		off += skipSpaceLeft(expr, off)
+	}
+
+	return tokens, nil
+}
+
+// Produces a string representation of a token sequence.
+func SprintfTokens(tokens []Token) string {
+	s := ""
+
+	for _, t := range tokens {
+		switch t.Code {
+		case TOKEN_NUMBER:
+			s += fmt.Sprintf("#[%s] ", t.Text)
+		case TOKEN_IDENT:
+			s += fmt.Sprintf("i[%s] ", t.Text)
+		case TOKEN_STRING:
+			s += fmt.Sprintf("\"%s\" ", t.Text)
+		default:
+			s += fmt.Sprintf("%s ", t.Text)
+		}
+	}
+
+	return s
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/parse/parse.go b/vendor/mynewt.apache.org/newt/newt/parse/parse.go
new file mode 100644
index 00000000..f6aeba0f
--- /dev/null
+++ b/vendor/mynewt.apache.org/newt/newt/parse/parse.go
@@ -0,0 +1,590 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+package parse
+
+import (
+	"fmt"
+
+	"mynewt.apache.org/newt/util"
+)
+
+// expr     ::= <unary><expr> | "("<expr>")" |
+//              <expr><binary><expr> | <ident> | <literal>
+// ident    ::= <printable-char> { <printable-char> }
+// literal  ::= """ <printable-char> { <printable-char> } """
+// unary    ::= "!"
+// binary   ::= "&&" | "^^" | "||" | "==" | "!=" | "<" | "<=" | ">" | ">="
+
+type ParseCode int
+
+const (
+	PARSE_NOT_EQUALS ParseCode = iota
+	PARSE_NOT
+	PARSE_EQUALS
+	PARSE_LT
+	PARSE_LTE
+	PARSE_GT
+	PARSE_GTE
+	PARSE_AND
+	PARSE_OR
+	PARSE_XOR
+	PARSE_NUMBER
+	PARSE_STRING
+	PARSE_IDENT
+)
+
+type Node struct {
+	Code ParseCode
+	Data string
+
+	Left  *Node
+	Right *Node
+}
+
+func (n *Node) String() string {
+	s := ""
+
+	if n.Left != nil {
+		s += n.Left.String()
+	}
+
+	s += fmt.Sprintf("%s", n.Data)
+
+	if n.Right != nil {
+		s += n.Right.String()
+	}
+
+	return s
+}
+
+func (n *Node) RpnString() string {
+	s := fmt.Sprintf("<%s>", n.Data)
+	if n.Left != nil {
+		s += " " + n.Left.RpnString()
+	}
+	if n.Right != nil {
+		s += " " + n.Right.RpnString()
+	}
+
+	return s
+}
+
+// Searches a tokenized expression.  The location of the first token that
+// matches a member of the supplied token set is returned.  This function does
+// not descend into parenthesized expressions.
+func findAnyToken(tokens []Token, any []TokenCode) (int, error) {
+	pcount := 0
+
+	for _, a := range any {
+		for i, t := range tokens {
+			if t.Code == TOKEN_LPAREN {
+				pcount++
+			} else if t.Code == TOKEN_RPAREN {
+				pcount--
+				if pcount < 0 {
+					return -1, fmt.Errorf("imbalanced parenthesis")
+				}
+			} else if pcount == 0 && t.Code == a {
+				return i, nil
+			}
+		}
+
+	}
+	return -1, nil
+}
+
+func binTokenToParse(t TokenCode) ParseCode {
+	return map[TokenCode]ParseCode{
+		TOKEN_NOT_EQUALS: PARSE_NOT_EQUALS,
+		TOKEN_EQUALS:     PARSE_EQUALS,
+		TOKEN_LT:         PARSE_LT,
+		TOKEN_LTE:        PARSE_LTE,
+		TOKEN_GT:         PARSE_GT,
+		TOKEN_GTE:        PARSE_GTE,
+		TOKEN_AND:        PARSE_AND,
+		TOKEN_OR:         PARSE_OR,
+		TOKEN_XOR:        PARSE_XOR,
+	}[t]
+}
+
+// Removes the outer layer of parentheses from a tokenized expression.
+func stripParens(tokens []Token) ([]Token, error) {
+	if tokens[0].Code != TOKEN_LPAREN {
+		panic("internal error: stripParens() received unparenthesized string")
+	}
+
+	pcount := 1
+	for i := 1; i < len(tokens); i++ {
+		switch tokens[i].Code {
+		case TOKEN_LPAREN:
+			pcount++
+
+		case TOKEN_RPAREN:
+			pcount--
+			if pcount == 0 {
+				return tokens[1:i], nil
+			}
+
+		default:
+		}
+	}
+
+	return nil, fmt.Errorf("unterminated parenthesis")
+}
+
+var binaryTokens = []TokenCode{
+	// Lowest precedence.
+	TOKEN_AND,
+	TOKEN_XOR,
+	TOKEN_OR,
+	TOKEN_EQUALS,
+	TOKEN_NOT_EQUALS,
+	TOKEN_LT,
+	TOKEN_LTE,
+	TOKEN_GT,
+	TOKEN_GTE,
+	// Highest precedence.
+}
+
+func FindBinaryToken(tokens []Token) int {
+	binIdx, err := findAnyToken(tokens, binaryTokens)
+	if err != nil {
+		return -1
+	}
+	return binIdx
+}
+
+// Recursively parses a tokenized expression.
+//
+// @param tokens                The sequence of tokens representing the
+//                                  expression to parse.  This is acquired by a
+//                                  call to `Lex()`.
+//
+// @return *Node                The expression parse tree.
+func Parse(tokens []Token) (*Node, error) {
+	if len(tokens) == 0 {
+		return nil, nil
+	}
+
+	////// Terminal symbols.
+
+	if len(tokens) == 1 {
+		switch tokens[0].Code {
+		case TOKEN_NUMBER:
+			return &Node{
+				Code: PARSE_NUMBER,
+				Data: tokens[0].Text,
+			}, nil
+
+		case TOKEN_STRING:
+			return &Node{
+				Code: PARSE_STRING,
+				Data: tokens[0].Text,
+			}, nil
+
+		case TOKEN_IDENT:
+			return &Node{
+				Code: PARSE_IDENT,
+				Data: tokens[0].Text,
+			}, nil
+
+		default:
+			return nil, fmt.Errorf("invalid expression: %s", tokens[0].Text)
+		}
+	}
+
+	////// Nonterminal symbols.
+
+	// <expr><binary><expr>
+	binIdx, err := findAnyToken(tokens, binaryTokens)
+	if err != nil {
+		return nil, err
+	}
+	if binIdx == 0 || binIdx == len(tokens)-1 {
+		return nil, fmt.Errorf("binary operator %s at start or end",
+			tokens[binIdx].Text)
+	}
+	if binIdx != -1 {
+		n := &Node{
+			Code: binTokenToParse(tokens[binIdx].Code),
+			Data: tokens[binIdx].Text,
+		}
+
+		l, err := Parse(tokens[0:binIdx])
+		if err != nil {
+			return nil, err
+		}
+
+		r, err := Parse(tokens[binIdx+1 : len(tokens)])
+		if err != nil {
+			return nil, err
+		}
+
+		n.Left = l
+		n.Right = r
+
+		return n, nil
+	}
+
+	// <unary><expr>
+	if tokens[0].Code == TOKEN_NOT {
+		n := &Node{
+			Code: PARSE_NOT,
+			Data: tokens[0].Text,
+		}
+		r, err := Parse(tokens[1:])
+		if err != nil {
+			return nil, err
+		}
+		n.Right = r
+		return n, nil
+	}
+
+	// "("<expr>")"
+	if tokens[0].Code == TOKEN_LPAREN {
+		stripped, err := stripParens(tokens)
+		if err != nil {
+			return nil, err
+		}
+
+		return Parse(stripped)
+	}
+
+	return nil, fmt.Errorf("invalid expression")
+}
+
+// Evaluates two expressions into boolean values.
+func evalTwo(expr1 *Node, expr2 *Node,
+	settings map[string]string) (bool, bool, error) {
+
+	v1, err := Eval(expr1, settings)
+	if err != nil {
+		return false, false, err
+	}
+	v2, err := Eval(expr2, settings)
+	if err != nil {
+		return false, false, err
+	}
+
+	return v1, v2, nil
+}
+
+func coerceToInt(n *Node, settings map[string]string) (int, error) {
+	switch n.Code {
+	case PARSE_NUMBER:
+		num, ok := util.AtoiNoOctTry(n.Data)
+		if !ok {
+			return 0,
+				util.FmtNewtError("expression contains invalid number: `%s`",
+					n.Data)
+		}
+		return num, nil
+
+	case PARSE_IDENT:
+		val := settings[n.Data]
+		num, ok := util.AtoiNoOctTry(val)
+		if !ok {
+			return 0,
+				util.FmtNewtError("setting %s has value `%s`, "+
+					"which is not a number", n.Data, val)
+		}
+		return num, nil
+
+	default:
+		return 0,
+			util.FmtNewtError("expression `%s` is not a valid number",
+				n.String())
+	}
+}
+
+func coerceTwoInts(left *Node, right *Node,
+	settings map[string]string, opStr string) (int, int, error) {
+
+	lnum, err := coerceToInt(left, settings)
+	if err != nil {
+		return 0, 0, util.FmtNewtError("cannot apply %s to `%s`; "+
+			"operand not a number", opStr, left.String())
+	}
+
+	rnum, err := coerceToInt(right, settings)
+	if err != nil {
+		return 0, 0, util.FmtNewtError("cannot apply %s to `%s`; "+
+			"operand not a number", opStr, right.String())
+	}
+
+	return lnum, rnum, nil
+}
+
+type equalsFn func(left *Node, right *Node, settings map[string]string) bool
+type equalsEntry struct {
+	LeftCode  ParseCode
+	RightCode ParseCode
+	Fn        equalsFn
+}
+
+var equalsDispatch = []equalsEntry{
+	// <ident1> == <ident2>
+	// True if both syscfg settings have identical text values.
+	equalsEntry{
+		LeftCode:  PARSE_IDENT,
+		RightCode: PARSE_IDENT,
+		Fn: func(left *Node, right *Node, settings map[string]string) bool {
+			return settings[left.Data] == settings[right.Data]
+		},
+	},
+
+	// <ident> == <number>
+	// True if the syscfg setting's value is a valid representation of the
+	// number on the right.
+	equalsEntry{
+		LeftCode:  PARSE_IDENT,
+		RightCode: PARSE_NUMBER,
+		Fn: func(left *Node, right *Node, settings map[string]string) bool {
+			lnum, ok := util.AtoiNoOctTry(settings[left.Data])
+			if !ok {
+				return false
+			}
+			rnum, ok := util.AtoiNoOctTry(right.Data)
+			if !ok {
+				return false
+			}
+			return lnum == rnum
+		},
+	},
+
+	// <ident> == <string>
+	// True if the syscfg setting's text value is identical to the string on
+	// the right.
+	equalsEntry{
+		LeftCode:  PARSE_IDENT,
+		RightCode: PARSE_STRING,
+		Fn: func(left *Node, right *Node, settings map[string]string) bool {
+			return settings[left.Data] == right.Data
+		},
+	},
+
+	// <number1> == <number2>
+	// True if both numbers have the same value.
+	equalsEntry{
+		LeftCode:  PARSE_NUMBER,
+		RightCode: PARSE_NUMBER,
+		Fn: func(left *Node, right *Node, settings map[string]string) bool {
+			lnum, ok := util.AtoiNoOctTry(left.Data)
+			if !ok {
+				return false
+			}
+			rnum, ok := util.AtoiNoOctTry(right.Data)
+			if !ok {
+				return false
+			}
+			return lnum == rnum
+		},
+	},
+
+	// <number> == <string>
+	// True if the string is a valid representation of the number.
+	equalsEntry{
+		LeftCode:  PARSE_NUMBER,
+		RightCode: PARSE_STRING,
+		Fn: func(left *Node, right *Node, settings map[string]string) bool {
+			return left.Data == right.Data
+		},
+	},
+
+	// <string1> == <string2>
+	// True if both strings are identical (case-sensitive).
+	equalsEntry{
+		LeftCode:  PARSE_STRING,
+		RightCode: PARSE_STRING,
+		Fn: func(left *Node, right *Node, settings map[string]string) bool {
+			return left.Data == right.Data
+		},
+	},
+}
+
+func evalEqualsOnce(
+	left *Node, right *Node, settings map[string]string) (bool, bool) {
+
+	for _, entry := range equalsDispatch {
+		if entry.LeftCode == left.Code && entry.RightCode == right.Code {
+			return entry.Fn(left, right, settings), true
+		}
+	}
+
+	return false, false
+}
+
+// Evaluates an equals expression (`x == y`)
+//
+// @param left                  The fully-parsed left operand.
+// @param left                  The fully-parsed right operand.
+// @param settings              The map of syscfg settings.
+//
+// @return bool                 Whether the expression evaluates to true.
+func evalEquals(
+	left *Node, right *Node, settings map[string]string) (bool, error) {
+
+	// The equals operator has special semantics.  Rather than evaluating both
+	// operands as booleans and then comparing, the behavior of this operator
+	// varies based on the types of operands.  Perform a table lookup using the
+	// operand types, and call the appropriate comparison function if a match
+	// is found.
+	val, ok := evalEqualsOnce(left, right, settings)
+	if ok {
+		return val, nil
+	}
+	val, ok = evalEqualsOnce(right, left, settings)
+	if ok {
+		return val, nil
+	}
+
+	// No special procedure identified.  Fallback to evaluating both operands
+	// as booleans and comparing the results.
+	booll, boolr, err := evalTwo(left, right, settings)
+	if err != nil {
+		return false, err
+	}
+	return booll == boolr, nil
+}
+
+// Evaluates a fully-parsed expression.
+//
+// @param node                  The root of the expression to evaluate.
+// @param settings              The map of syscfg settings.
+//
+// @return bool                 Whether the expression evaluates to true.
+func Eval(expr *Node, settings map[string]string) (bool, error) {
+	switch expr.Code {
+	case PARSE_NOT:
+		r, err := Eval(expr.Right, settings)
+		if err != nil {
+			return false, err
+		}
+		return !r, nil
+
+	case PARSE_EQUALS:
+		return evalEquals(expr.Left, expr.Right, settings)
+
+	case PARSE_NOT_EQUALS:
+		v, err := evalEquals(expr.Left, expr.Right, settings)
+		if err != nil {
+			return false, err
+		}
+		return !v, nil
+
+	case PARSE_LT:
+		l, r, err := coerceTwoInts(expr.Left, expr.Right, settings, "<")
+		if err != nil {
+			return false, err
+		}
+		return l < r, nil
+
+	case PARSE_LTE:
+		l, r, err := coerceTwoInts(expr.Left, expr.Right, settings, "<=")
+		if err != nil {
+			return false, err
+		}
+		return l <= r, nil
+
+	case PARSE_GT:
+		l, r, err := coerceTwoInts(expr.Left, expr.Right, settings, ">")
+		if err != nil {
+			return false, err
+		}
+		return l > r, nil
+
+	case PARSE_GTE:
+		l, r, err := coerceTwoInts(expr.Left, expr.Right, settings, ">=")
+		if err != nil {
+			return false, err
+		}
+		return l >= r, nil
+
+	case PARSE_AND:
+		l, r, err := evalTwo(expr.Left, expr.Right, settings)
+		if err != nil {
+			return false, err
+		}
+		return l && r, nil
+
+	case PARSE_OR:
+		l, r, err := evalTwo(expr.Left, expr.Right, settings)
+		if err != nil {
+			return false, err
+		}
+		return l || r, nil
+
+	case PARSE_XOR:
+		l, r, err := evalTwo(expr.Left, expr.Right, settings)
+		if err != nil {
+			return false, err
+		}
+		return (l && !r) || (!l && r), nil
+
+	case PARSE_NUMBER:
+		num, ok := util.AtoiNoOctTry(expr.Data)
+		return ok && num != 0, nil
+
+	case PARSE_STRING:
+		return ValueIsTrue(expr.Data), nil
+
+	case PARSE_IDENT:
+		val := settings[expr.Data]
+		return ValueIsTrue(val), nil
+
+	default:
+		return false, fmt.Errorf("invalid parse code: %d", expr.Code)
+	}
+}
+
+// Parses and evaluates string containing a syscfg expression.
+//
+// @param expr                  The expression to parse.
+// @param settings              The map of syscfg settings.
+//
+// @return bool                 Whether the expression evaluates to true.
+func ParseAndEval(expr string, settings map[string]string) (bool, error) {
+	tokens, err := Lex(expr)
+	if err != nil {
+		return false, err
+	}
+
+	n, err := Parse(tokens)
+	if err != nil {
+		return false, fmt.Errorf("error parsing [%s]: %s\n", expr, err.Error())
+	}
+
+	v, err := Eval(n, settings)
+	return v, err
+}
+
+// Evaluates the truthfulness of a text expression.
+func ValueIsTrue(val string) bool {
+	if val == "" {
+		return false
+	}
+
+	i, ok := util.AtoiNoOctTry(val)
+	if ok && i == 0 {
+		return false
+	}
+
+	return true
+}
diff --git a/vendor/mynewt.apache.org/newt/newt/pkg/bsp_package.go b/vendor/mynewt.apache.org/newt/newt/pkg/bsp_package.go
index 146347f2..56399a00 100644
--- a/vendor/mynewt.apache.org/newt/newt/pkg/bsp_package.go
+++ b/vendor/mynewt.apache.org/newt/newt/pkg/bsp_package.go
@@ -26,8 +26,8 @@ import (
 	"mynewt.apache.org/newt/newt/flash"
 	"mynewt.apache.org/newt/newt/interfaces"
 	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
-	"mynewt.apache.org/newt/viper"
 )
 
 const BSP_YAML_FILENAME = "bsp.yml"
@@ -41,15 +41,15 @@ type BspPackage struct {
 	DownloadScript     string
 	DebugScript        string
 	FlashMap           flash.FlashMap
-	BspV               *viper.Viper
+	BspV               ycfg.YCfg
 }
 
 func (bsp *BspPackage) resolvePathSetting(
-	features map[string]bool, key string) (string, error) {
+	settings map[string]string, key string) (string, error) {
 
 	proj := interfaces.GetProject()
 
-	val := newtutil.GetStringFeatures(bsp.BspV, features, key)
+	val := bsp.BspV.GetValString(key, settings)
 	if val == "" {
 		return "", nil
 	}
@@ -65,21 +65,23 @@ func (bsp *BspPackage) resolvePathSetting(
 // Interprets a setting as either a single linker script or a list of linker
 // scripts.
 func (bsp *BspPackage) resolveLinkerScriptSetting(
-	features map[string]bool, key string) ([]string, error) {
+	settings map[string]string, key string) ([]string, error) {
 
 	paths := []string{}
 
 	// Assume config file specifies a list of scripts.
-	vals := newtutil.GetStringSliceFeatures(bsp.BspV, features, key)
+	vals := bsp.BspV.GetValStringSlice(key, settings)
 	if vals == nil {
 		// Couldn't read a list of scripts; try to interpret setting as a
 		// single script.
-		path, err := bsp.resolvePathSetting(features, key)
+		path, err := bsp.resolvePathSetting(settings, key)
 		if err != nil {
 			return nil, err
 		}
 
-		paths = append(paths, path)
+		if path != "" {
+			paths = append(paths, path)
+		}
 	} else {
 		proj := interfaces.GetProject()
 
@@ -92,55 +94,52 @@ func (bsp *BspPackage) resolveLinkerScriptSetting(
 					bsp.Name(), key)
 			}
 
-			paths = append(paths, path)
+			if path != "" {
+				paths = append(paths, path)
+			}
 		}
 	}
 
 	return paths, nil
 }
 
-func (bsp *BspPackage) Reload(features map[string]bool) error {
+func (bsp *BspPackage) Reload(settings map[string]string) error {
 	var err error
 
-	if features == nil {
-		features = map[string]bool{
-			strings.ToUpper(runtime.GOOS): true,
-		}
-	} else {
-		features[strings.ToUpper(runtime.GOOS)] = true
+	if settings == nil {
+		settings = map[string]string{}
 	}
-	bsp.BspV, err = util.ReadConfig(bsp.BasePath(),
+	settings[strings.ToUpper(runtime.GOOS)] = "1"
+
+	bsp.BspV, err = newtutil.ReadConfig(bsp.BasePath(),
 		strings.TrimSuffix(BSP_YAML_FILENAME, ".yml"))
 	if err != nil {
 		return err
 	}
 	bsp.AddCfgFilename(bsp.BasePath() + BSP_YAML_FILENAME)
 
-	bsp.CompilerName = newtutil.GetStringFeatures(bsp.BspV,
-		features, "bsp.compiler")
-
-	bsp.Arch = newtutil.GetStringFeatures(bsp.BspV,
-		features, "bsp.arch")
+	bsp.CompilerName = bsp.BspV.GetValString("bsp.compiler", settings)
+	bsp.Arch = bsp.BspV.GetValString("bsp.arch", settings)
 
 	bsp.LinkerScripts, err = bsp.resolveLinkerScriptSetting(
-		features, "bsp.linkerscript")
+		settings, "bsp.linkerscript")
 	if err != nil {
 		return err
 	}
 
 	bsp.Part2LinkerScripts, err = bsp.resolveLinkerScriptSetting(
-		features, "bsp.part2linkerscript")
+		settings, "bsp.part2linkerscript")
 	if err != nil {
 		return err
 	}
 
 	bsp.DownloadScript, err = bsp.resolvePathSetting(
-		features, "bsp.downloadscript")
+		settings, "bsp.downloadscript")
 	if err != nil {
 		return err
 	}
 	bsp.DebugScript, err = bsp.resolvePathSetting(
-		features, "bsp.debugscript")
+		settings, "bsp.debugscript")
 	if err != nil {
 		return err
 	}
@@ -154,8 +153,7 @@ func (bsp *BspPackage) Reload(features map[string]bool) error {
 			"(bsp.arch)")
 	}
 
-	ymlFlashMap := newtutil.GetStringMapFeatures(bsp.BspV, features,
-		"bsp.flash_map")
+	ymlFlashMap := bsp.BspV.GetValStringMap("bsp.flash_map", settings)
 	if ymlFlashMap == nil {
 		return util.NewNewtError("BSP does not specify a flash map " +
 			"(bsp.flash_map)")
@@ -173,7 +171,7 @@ func NewBspPackage(lpkg *LocalPackage) (*BspPackage, error) {
 		CompilerName:   "",
 		DownloadScript: "",
 		DebugScript:    "",
-		BspV:           viper.New(),
+		BspV:           ycfg.YCfg{},
 	}
 	lpkg.Load()
 	bsp.LocalPackage = lpkg
diff --git a/vendor/mynewt.apache.org/newt/newt/pkg/localpackage.go b/vendor/mynewt.apache.org/newt/newt/pkg/localpackage.go
index 7a6beb49..6927b382 100644
--- a/vendor/mynewt.apache.org/newt/newt/pkg/localpackage.go
+++ b/vendor/mynewt.apache.org/newt/newt/pkg/localpackage.go
@@ -26,7 +26,6 @@ import (
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"sort"
 	"strconv"
 	"strings"
 
@@ -35,8 +34,8 @@ import (
 	"mynewt.apache.org/newt/newt/interfaces"
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/repo"
+	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
-	"mynewt.apache.org/newt/viper"
 	"mynewt.apache.org/newt/yaml"
 )
 
@@ -57,6 +56,7 @@ type LocalPackage struct {
 	name        string
 	basePath    string
 	packageType interfaces.PackageType
+	linkedName  string
 
 	// General information about the package
 	desc *PackageDesc
@@ -70,10 +70,10 @@ type LocalPackage struct {
 	injectedSettings map[string]string
 
 	// Settings read from pkg.yml.
-	PkgV *viper.Viper
+	PkgY ycfg.YCfg
 
 	// Settings read from syscfg.yml.
-	SyscfgV *viper.Viper
+	SyscfgY ycfg.YCfg
 
 	// Names of all source yml files; used to determine if rebuild required.
 	cfgFilenames []string
@@ -82,8 +82,8 @@ type LocalPackage struct {
 func NewLocalPackage(r *repo.Repo, pkgDir string) *LocalPackage {
 	pkg := &LocalPackage{
 		desc:             &PackageDesc{},
-		PkgV:             viper.New(),
-		SyscfgV:          viper.New(),
+		PkgY:             ycfg.YCfg{},
+		SyscfgY:          ycfg.YCfg{},
 		repo:             r,
 		basePath:         filepath.ToSlash(filepath.Clean(pkgDir)),
 		init:             map[string]int{},
@@ -96,15 +96,24 @@ func (pkg *LocalPackage) Name() string {
 	return pkg.name
 }
 
+func (pkg *LocalPackage) NameWithRepo() string {
+	r := pkg.Repo()
+	return newtutil.BuildPackageString(r.Name(), pkg.Name())
+}
+
 func (pkg *LocalPackage) FullName() string {
 	r := pkg.Repo()
 	if r.IsLocal() {
 		return pkg.Name()
 	} else {
-		return newtutil.BuildPackageString(r.Name(), pkg.Name())
+		return pkg.NameWithRepo()
 	}
 }
 
+func (pkg *LocalPackage) LinkedName() string {
+	return pkg.linkedName
+}
+
 func (pkg *LocalPackage) BasePath() string {
 	return pkg.basePath
 }
@@ -128,8 +137,6 @@ func (pkg *LocalPackage) Desc() *PackageDesc {
 
 func (pkg *LocalPackage) SetName(name string) {
 	pkg.name = name
-	// XXX: Also set "pkg.name" in viper object (possibly just remove cached
-	// variable from code entirely).
 }
 
 func (pkg *LocalPackage) SetBasePath(basePath string) {
@@ -138,14 +145,10 @@ func (pkg *LocalPackage) SetBasePath(basePath string) {
 
 func (pkg *LocalPackage) SetType(packageType interfaces.PackageType) {
 	pkg.packageType = packageType
-	// XXX: Also set "pkg.type" in viper object (possibly just remove cached
-	// variable from code entirely).
 }
 
 func (pkg *LocalPackage) SetDesc(desc *PackageDesc) {
 	pkg.desc = desc
-	// XXX: Also set desc fields in viper object (possibly just remove cached
-	// variable from code entirely).
 }
 
 func (pkg *LocalPackage) SetRepo(r *repo.Repo) {
@@ -192,13 +195,13 @@ func (pkg *LocalPackage) AddCfgFilename(cfgFilename string) {
 	pkg.cfgFilenames = append(pkg.cfgFilenames, cfgFilename)
 }
 
-func (pkg *LocalPackage) readDesc(v *viper.Viper) (*PackageDesc, error) {
+func (pkg *LocalPackage) readDesc(yc ycfg.YCfg) (*PackageDesc, error) {
 	pdesc := &PackageDesc{}
 
-	pdesc.Author = v.GetString("pkg.author")
-	pdesc.Homepage = v.GetString("pkg.homepage")
-	pdesc.Description = v.GetString("pkg.description")
-	pdesc.Keywords = v.GetStringSlice("pkg.keywords")
+	pdesc.Author = yc.GetValString("pkg.author", nil)
+	pdesc.Homepage = yc.GetValString("pkg.homepage", nil)
+	pdesc.Description = yc.GetValString("pkg.description", nil)
+	pdesc.Keywords = yc.GetValStringSlice("pkg.keywords", nil)
 
 	return pdesc, nil
 }
@@ -206,8 +209,8 @@ func (pkg *LocalPackage) readDesc(v *viper.Viper) (*PackageDesc, error) {
 func (pkg *LocalPackage) sequenceString(key string) string {
 	var buffer bytes.Buffer
 
-	if pkg.PkgV != nil {
-		for _, f := range pkg.PkgV.GetStringSlice(key) {
+	if pkg.PkgY != nil {
+		for _, f := range pkg.PkgY.GetValStringSlice(key, nil) {
 			buffer.WriteString("    - " + yaml.EscapeString(f) + "\n")
 		}
 	}
@@ -219,38 +222,21 @@ func (pkg *LocalPackage) sequenceString(key string) string {
 	}
 }
 
-func (lpkg *LocalPackage) SaveSyscfgVals() error {
+func (lpkg *LocalPackage) SaveSyscfg() error {
 	dirpath := lpkg.BasePath()
 	if err := os.MkdirAll(dirpath, 0755); err != nil {
 		return util.NewNewtError(err.Error())
 	}
 
 	filepath := dirpath + "/" + SYSCFG_YAML_FILENAME
-
-	syscfgVals := lpkg.SyscfgV.GetStringMapString("syscfg.vals")
-	if syscfgVals == nil || len(syscfgVals) == 0 {
-		os.Remove(filepath)
-		return nil
-	}
-
 	file, err := os.Create(filepath)
 	if err != nil {
 		return util.NewNewtError(err.Error())
 	}
 	defer file.Close()
 
-	names := make([]string, 0, len(syscfgVals))
-	for k, _ := range syscfgVals {
-		names = append(names, k)
-	}
-	sort.Strings(names)
-
-	fmt.Fprintf(file, "### Package: %s\n", lpkg.Name())
-	fmt.Fprintf(file, "\n")
-	fmt.Fprintf(file, "syscfg.vals:\n")
-	for _, name := range names {
-		fmt.Fprintf(file, "    %s: %s\n", name, yaml.EscapeString(syscfgVals[name]))
-	}
+	s := newtutil.YCfgToYaml(lpkg.SyscfgY)
+	file.WriteString(s)
 
 	return nil
 }
@@ -271,9 +257,7 @@ func (pkg *LocalPackage) Save() error {
 	}
 	defer file.Close()
 
-	file.WriteString("### Package: " + pkg.Name() + "\n")
-
-	// XXX: Just iterate viper object's settings rather than calling out
+	// XXX: Just iterate ycfg object's settings rather than calling out
 	// cached settings individually.
 	file.WriteString("pkg.name: " + yaml.EscapeString(pkg.Name()) + "\n")
 	file.WriteString("pkg.type: " +
@@ -289,20 +273,31 @@ func (pkg *LocalPackage) Save() error {
 
 	file.WriteString(pkg.sequenceString("pkg.aflags"))
 	file.WriteString(pkg.sequenceString("pkg.cflags"))
+	file.WriteString(pkg.sequenceString("pkg.cxxflags"))
 	file.WriteString(pkg.sequenceString("pkg.lflags"))
 
 	return nil
 }
 
-// Load reads everything that isn't identity specific into the
-// package
+func matchNamePath(name, path string) bool {
+	// assure that name and path use the same path separator...
+	names := strings.Split(name, "/")
+	name = strings.Join(names, "/")
+
+	if strings.HasSuffix(path, name) {
+		return true
+	}
+	return false
+}
+
+// Load reads everything that isn't identity specific into the package
 func (pkg *LocalPackage) Load() error {
 	// Load configuration
 	log.Debugf("Loading configuration for package %s", pkg.basePath)
 
 	var err error
 
-	pkg.PkgV, err = util.ReadConfig(pkg.basePath,
+	pkg.PkgY, err = newtutil.ReadConfig(pkg.basePath,
 		strings.TrimSuffix(PACKAGE_FILE_NAME, ".yml"))
 	if err != nil {
 		return err
@@ -310,18 +305,54 @@ func (pkg *LocalPackage) Load() error {
 	pkg.AddCfgFilename(pkg.basePath + "/" + PACKAGE_FILE_NAME)
 
 	// Set package name from the package
-	pkg.name = pkg.PkgV.GetString("pkg.name")
+	pkg.name = pkg.PkgY.GetValString("pkg.name", nil)
+	if pkg.name == "" {
+		return util.FmtNewtError(
+			"Package \"%s\" missing \"pkg.name\" field in its `pkg.yml` file",
+			pkg.basePath)
+	}
+
+	if !matchNamePath(pkg.name, pkg.basePath) {
+		return util.FmtNewtError(
+			"Package \"%s\" has incorrect \"pkg.name\" field in its "+
+				"`pkg.yml` file (pkg.name=%s)", pkg.basePath, pkg.name)
+	}
 
-	typeString := pkg.PkgV.GetString("pkg.type")
+	typeString := pkg.PkgY.GetValString("pkg.type", nil)
 	pkg.packageType = PACKAGE_TYPE_LIB
-	for t, n := range PackageTypeNames {
-		if typeString == n {
-			pkg.packageType = t
-			break
+	if len(typeString) > 0 {
+		found := false
+		for t, n := range PackageTypeNames {
+			if typeString == n {
+				pkg.packageType = t
+				found = true
+				break
+			}
+		}
+
+		if !found {
+			return util.FmtNewtError(
+				"Package \"%s\" has incorrect \"pkg.type\" field in its "+
+					"`pkg.yml` file (pkg.type=%s)", pkg.basePath, typeString)
+		}
+	}
+
+	if pkg.packageType == PACKAGE_TYPE_TRANSIENT {
+		n := pkg.PkgY.GetValString("pkg.link", nil)
+		if len(n) == 0 {
+			return util.FmtNewtError(
+				"Transient package \"%s\" does not specify target "+
+					"package in its `pkg.yml` file (pkg.name=%s)",
+				pkg.basePath, pkg.name)
 		}
+
+		pkg.linkedName = n
+
+		// We don't really want anything else for this package
+		return nil
 	}
 
-	init := pkg.PkgV.GetStringMapString("pkg.init")
+	init := pkg.PkgY.GetValStringMapString("pkg.init", nil)
 	for name, stageStr := range init {
 		stage, err := strconv.ParseInt(stageStr, 10, 64)
 		if err != nil {
@@ -330,22 +361,22 @@ func (pkg *LocalPackage) Load() error {
 		}
 		pkg.init[name] = int(stage)
 	}
-	initFnName := pkg.PkgV.GetString("pkg.init_function")
-	initStage := pkg.PkgV.GetInt("pkg.init_stage")
+	initFnName := pkg.PkgY.GetValString("pkg.init_function", nil)
+	initStage := pkg.PkgY.GetValInt("pkg.init_stage", nil)
 
 	if initFnName != "" {
 		pkg.init[initFnName] = initStage
 	}
 
 	// Read the package description from the file
-	pkg.desc, err = pkg.readDesc(pkg.PkgV)
+	pkg.desc, err = pkg.readDesc(pkg.PkgY)
 	if err != nil {
 		return err
 	}
 
 	// Load syscfg settings.
 	if util.NodeExist(pkg.basePath + "/" + SYSCFG_YAML_FILENAME) {
-		pkg.SyscfgV, err = util.ReadConfig(pkg.basePath,
+		pkg.SyscfgY, err = newtutil.ReadConfig(pkg.basePath,
 			strings.TrimSuffix(SYSCFG_YAML_FILENAME, ".yml"))
 		if err != nil {
 			return err
@@ -387,6 +418,11 @@ func (pkg *LocalPackage) Clone(newRepo *repo.Repo,
 func LoadLocalPackage(repo *repo.Repo, pkgDir string) (*LocalPackage, error) {
 	pkg := NewLocalPackage(repo, pkgDir)
 	err := pkg.Load()
+	if err != nil {
+		err = util.FmtNewtError("%s; ignoring package.", err.Error())
+		return nil, err
+	}
+
 	return pkg, err
 }
 
@@ -403,7 +439,7 @@ func ReadLocalPackageRecursive(repo *repo.Repo,
 
 	dirList, err := repo.FilteredSearchList(pkgName, searchedMap)
 	if err != nil {
-		return warnings, util.NewNewtError(err.Error())
+		return append(warnings, err.Error()), nil
 	}
 
 	for _, name := range dirList {
@@ -419,9 +455,7 @@ func ReadLocalPackageRecursive(repo *repo.Repo,
 		}
 	}
 
-	if util.NodeNotExist(filepath.Join(basePath, pkgName,
-		PACKAGE_FILE_NAME)) {
-
+	if util.NodeNotExist(filepath.Join(basePath, pkgName, PACKAGE_FILE_NAME)) {
 		return warnings, nil
 	}
 
diff --git a/vendor/mynewt.apache.org/newt/newt/pkg/package.go b/vendor/mynewt.apache.org/newt/newt/pkg/package.go
index 58bf5238..f4f6feb0 100644
--- a/vendor/mynewt.apache.org/newt/newt/pkg/package.go
+++ b/vendor/mynewt.apache.org/newt/newt/pkg/package.go
@@ -37,6 +37,7 @@ const (
 	PACKAGE_TYPE_SDK
 	PACKAGE_TYPE_GENERATED
 	PACKAGE_TYPE_LIB
+	PACKAGE_TYPE_TRANSIENT
 	PACKAGE_TYPE_BSP
 	PACKAGE_TYPE_UNITTEST
 	PACKAGE_TYPE_APP
@@ -49,6 +50,7 @@ var PackageTypeNames = map[interfaces.PackageType]string{
 	PACKAGE_TYPE_SDK:       "sdk",
 	PACKAGE_TYPE_GENERATED: "generated",
 	PACKAGE_TYPE_LIB:       "lib",
+	PACKAGE_TYPE_TRANSIENT: "transient",
 	PACKAGE_TYPE_BSP:       "bsp",
 	PACKAGE_TYPE_UNITTEST:  "unittest",
 	PACKAGE_TYPE_APP:       "app",
diff --git a/vendor/mynewt.apache.org/newt/newt/project/pkgwriter.go b/vendor/mynewt.apache.org/newt/newt/project/pkgwriter.go
index bcf39cdb..5a0f6db7 100644
--- a/vendor/mynewt.apache.org/newt/newt/project/pkgwriter.go
+++ b/vendor/mynewt.apache.org/newt/newt/project/pkgwriter.go
@@ -24,10 +24,11 @@ import (
 	"io/ioutil"
 	"os"
 	"path"
-	"regexp"
+	"path/filepath"
 	"strings"
 
 	"mynewt.apache.org/newt/newt/downloader"
+	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/util"
 )
 
@@ -104,60 +105,129 @@ func (pw *PackageWriter) ConfigurePackage(template string, loc string) error {
 	return nil
 }
 
-func (pw *PackageWriter) cleanupPackageFile(pfile string) error {
-	data, err := ioutil.ReadFile(pfile)
-	if err != nil {
-		return util.ChildNewtError(err)
-	}
+// Creates a table of search-replace pairs.  These pairs are simple
+// substitution rules (i.e., not regexes) that get applied to filenames,
+// directory names, and the contents of YAML files.
+func (pw *PackageWriter) replacementTable() [][]string {
+	pkgBase := path.Base(pw.fullName)
 
-	// Search & replace file contents
-	re := regexp.MustCompile("your-pkg-name")
-	res := re.ReplaceAllString(string(data), "\""+pw.fullName+"\"")
+	return [][]string{
+		{`$$pkgfullname`, pw.fullName},
+		{`$$pkgdir`, path.Dir(pw.fullName)},
+		{`$$pkgname`, path.Base(pw.fullName)},
 
-	if err := ioutil.WriteFile(pfile, []byte(res), 0666); err != nil {
-		return util.ChildNewtError(err)
+		// Legacy.
+		{`your-pkg-name`, `"` + pw.fullName + `"`},
+		{`your-path`, pkgBase},
+		{`your-source`, pkgBase},
+		{`your-file`, pkgBase},
 	}
+}
 
-	return nil
+// Applies all the substitution rules in the supplied table to a string.
+func replaceText(s string, table [][]string) string {
+	for _, r := range table {
+		s = strings.Replace(s, r[0], r[1], -1)
+	}
+
+	return s
 }
 
-func (pw *PackageWriter) fixupPkg() error {
-	pkgBase := path.Base(pw.fullName)
+// Applies all the substitution rules in the supplied table to the contents of
+// a file.  If the file contents change as a result, the file gets rewritten.
+func fixupFileText(path string, table [][]string) error {
+	data, err := ioutil.ReadFile(path)
+	if err != nil {
+		return util.ChildNewtError(err)
+	}
 
-	// Move include file to name after package name
-	if err := util.MoveFile(pw.targetPath+"/include/your-path/your-file.h",
-		pw.targetPath+"/include/your-path/"+pkgBase+".h"); err != nil {
+	s1 := string(data)
+	s2 := replaceText(s1, table)
 
-		if !util.IsNotExist(err) {
-			return err
+	if s2 != s1 {
+		if err := ioutil.WriteFile(path, []byte(s2), 0666); err != nil {
+			return util.ChildNewtError(err)
 		}
 	}
 
-	// Move source file
-	if err := util.MoveFile(pw.targetPath+"/src/your-source.c",
-		pw.targetPath+"/src/"+pkgBase+".c"); err != nil {
+	return nil
+}
 
-		if !util.IsNotExist(err) {
+// Retrieves the names of all child files and directories.
+//
+// @param path                  The root directory where the traversal starts.
+//
+// @return []string             All descendent files.
+//         []string             All descendent directories.
+//         error                Error
+func collectPaths(path string) ([]string, []string, error) {
+	files := []string{}
+	dirs := []string{}
+
+	collect := func(path string, f os.FileInfo, err error) error {
+		if err != nil {
 			return err
 		}
+
+		if f.IsDir() {
+			dirs = append(dirs, path)
+		} else {
+			files = append(files, path)
+		}
+		return nil
+	}
+	if err := filepath.Walk(path, collect); err != nil {
+		return nil, nil, util.ChildNewtError(err)
 	}
 
-	if err := util.CopyDir(pw.targetPath+"/include/your-path/",
-		pw.targetPath+"/include/"+pkgBase+"/"); err != nil {
+	return files, dirs, nil
+}
 
-		if !util.IsNotExist(err) {
-			return err
+// Customizes a template package.  Renames generic files and directories and
+// substitutes text in YAML files.
+func (pw *PackageWriter) fixupPkg() error {
+	table := pw.replacementTable()
+	pkgDir := pw.targetPath
+
+	// Apply the replacement patterns to directory names.
+	_, dirs, err := collectPaths(pkgDir)
+	if err != nil {
+		return err
+	}
+	for _, d1 := range dirs {
+		d2 := replaceText(d1, table)
+		if d1 != d2 {
+			// Make parent directory to allow multiple replacements in path.
+			if err := os.MkdirAll(filepath.Dir(d2), os.ModePerm); err != nil {
+				return util.ChildNewtError(err)
+			}
+			if err := os.Rename(d1, d2); err != nil {
+				return util.ChildNewtError(err)
+			}
 		}
 	}
 
-	if err := os.RemoveAll(pw.targetPath + "/include/your-path/"); err != nil {
-		if !util.IsNotExist(err) {
-			return util.ChildNewtError(err)
+	// Replace text inside YAML files.
+	files, _, err := collectPaths(pkgDir)
+	if err != nil {
+		return err
+	}
+	for _, f := range files {
+		if strings.HasSuffix(f, ".yml") {
+			if err := fixupFileText(f, table); err != nil {
+				return err
+			}
 		}
 	}
 
-	if err := pw.cleanupPackageFile(pw.targetPath + "/pkg.yml"); err != nil {
-		return err
+	// Apply the replacement patterns to file names.
+	for _, f1 := range files {
+		f2 := replaceText(f1, table)
+		if f2 != f1 {
+			if err := os.Rename(f1, f2); err != nil {
+				return util.ChildNewtError(err)
+			}
+		}
 	}
 
 	return nil
@@ -173,10 +243,15 @@ func (pw *PackageWriter) WritePackage() error {
 		"Download package template for package type %s.\n",
 		strings.ToLower(pw.template))
 
-	tmpdir, err := dl.DownloadRepo(pw.repo.branch)
+	tmpdir, err := newtutil.MakeTempRepoDir()
 	if err != nil {
 		return err
 	}
+	defer os.RemoveAll(tmpdir)
+
+	if err := dl.Clone(pw.repo.branch, tmpdir); err != nil {
+		return err
+	}
 
 	if err := os.RemoveAll(tmpdir + "/.git/"); err != nil {
 		return util.NewNewtError(err.Error())
diff --git a/vendor/mynewt.apache.org/newt/newt/project/project.go b/vendor/mynewt.apache.org/newt/newt/project/project.go
index 4fd98026..fb29d374 100644
--- a/vendor/mynewt.apache.org/newt/newt/project/project.go
+++ b/vendor/mynewt.apache.org/newt/newt/project/project.go
@@ -20,7 +20,6 @@
 package project
 
 import (
-	"bufio"
 	"fmt"
 	"os"
 	"path"
@@ -30,13 +29,15 @@ import (
 	log "github.com/Sirupsen/logrus"
 
 	"mynewt.apache.org/newt/newt/compat"
+	"mynewt.apache.org/newt/newt/deprepo"
 	"mynewt.apache.org/newt/newt/downloader"
+	"mynewt.apache.org/newt/newt/install"
 	"mynewt.apache.org/newt/newt/interfaces"
 	"mynewt.apache.org/newt/newt/newtutil"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/repo"
+	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
-	"mynewt.apache.org/newt/viper"
 )
 
 var globalProject *Project = nil
@@ -57,15 +58,30 @@ type Project struct {
 
 	packages interfaces.PackageList
 
-	projState *ProjectState
+	// Contains all the repos that form this project.  Each repo is in one of
+	// two states:
+	//    * description: Only the repo's basic description fields have been
+	//                   read from `project.yml` or from a dependent repo's
+	//                   `repository.yml` file.  This repo's `repository.yml`
+	//                   file still needs to be read.
+	//    * complete: The repo's `repository.yml` file exists and has been
+	//                read.
+	repos deprepo.RepoMap
+
+	// The local repository at the top-level of the project.  This repo is
+	// excluded from most repo operations.
+	localRepo *repo.Repo
+
+	// Required versions of installed repos, as read from `project.yml`.
+	rootRepoReqs deprepo.RequirementMap
 
-	// Repositories configured on this project
-	repos    map[string]*repo.Repo
 	warnings []string
 
-	localRepo *repo.Repo
+	// Indicates the repos whose version we couldn't detect.  Prevents
+	// duplicate warnings.
+	unknownRepoVers map[string]struct{}
 
-	v *viper.Viper
+	yc ycfg.YCfg
 }
 
 func initProject(dir string) error {
@@ -169,279 +185,214 @@ func (proj *Project) FindRepoPath(rname string) string {
 	return r.Path()
 }
 
-func (proj *Project) LocalRepo() *repo.Repo {
-	return proj.localRepo
-}
+func (proj *Project) GetRepoVersion(
+	rname string) (*newtutil.RepoVersion, error) {
 
-func (proj *Project) Warnings() []string {
-	return proj.warnings
-}
+	// First, try to read the repo's `version.yml` file.
+	r := proj.repos[rname]
+	if r == nil {
+		return nil, nil
+	}
 
-func (proj *Project) upgradeCheck(r *repo.Repo, vers *repo.Version,
-	force bool) (bool, error) {
-	rdesc, err := r.GetRepoDesc()
+	ver, err := r.InstalledVersion()
 	if err != nil {
-		return false, err
-	}
-
-	branch, newVers, _ := rdesc.Match(r)
-	if newVers == nil {
-		util.StatusMessage(util.VERBOSITY_DEFAULT,
-			"No matching version to upgrade to "+
-				"found for %s.  Please check your project requirements.",
-			r.Name())
-		return false, util.NewNewtError(fmt.Sprintf("Cannot find a "+
-			"version of repository %s that matches project requirements.",
-			r.Name()))
-	}
-
-	// If the change between the old repository and the new repository would cause
-	// and upgrade.  Then prompt for an upgrade response, unless the force option
-	// is present.
-	if vers.CompareVersions(newVers, vers) != 0 ||
-		vers.Stability() != newVers.Stability() {
-		if !force {
-			str := ""
-			if newVers.Stability() != repo.VERSION_STABILITY_NONE {
-				str += "(" + branch + ")"
-			}
+		return nil, err
+	}
 
-			fmt.Printf("Would you like to upgrade repository %s from %s to %s %s? [Yn] ",
-				r.Name(), vers.String(), newVers.String(), str)
-			line, more, err := bufio.NewReader(os.Stdin).ReadLine()
-			if more || err != nil {
-				return false, util.NewNewtError(fmt.Sprintf(
-					"Couldn't read upgrade response: %s\n", err.Error()))
-			}
+	if ver == nil {
+		commit, err := r.CurrentHash()
+		if err != nil {
+			return nil, err
+		}
+		if proj.unknownRepoVers == nil {
+			proj.unknownRepoVers = map[string]struct{}{}
+		}
 
-			// Anything but no means yes.
-			answer := strings.ToUpper(strings.Trim(string(line), " "))
-			if answer == "N" || answer == "NO" {
-				fmt.Printf("User says don't upgrade, skipping upgrade of %s\n",
-					r.Name())
-				return true, nil
-			}
+		if _, ok := proj.unknownRepoVers[rname]; !ok {
+			proj.unknownRepoVers[rname] = struct{}{}
+
+			util.StatusMessage(util.VERBOSITY_QUIET,
+				"WARNING: Could not detect version of installed repo \"%s\"; "+
+					"assuming 0.0.0/%s\n", r.Name(), commit)
+		}
+		ver = &newtutil.RepoVersion{
+			Commit: commit,
 		}
-	} else {
-		util.StatusMessage(util.VERBOSITY_VERBOSE,
-			"Repository %s doesn't need to be upgraded, latest "+
-				"version installed.\n", r.Name())
-		return true, nil
 	}
 
-	return false, nil
+	return ver, nil
 }
 
-func (proj *Project) checkVersionRequirements(r *repo.Repo, upgrade bool, force bool) (bool, error) {
-	rdesc, err := r.GetRepoDesc()
-	if err != nil {
-		return false, err
-	}
+// XXX: Incorrect comment.
+// Indicates whether the specified repo is present in the `project.state` file.
+func (proj *Project) RepoIsInstalled(rname string) bool {
+	ver, err := proj.GetRepoVersion(rname)
+	return err == nil && ver != nil
+}
 
-	rname := r.Name()
+func (proj *Project) RepoIsRoot(rname string) bool {
+	return proj.rootRepoReqs[rname] != nil
+}
 
-	vers := proj.projState.GetInstalledVersion(rname)
-	if vers != nil {
-		ok := rdesc.SatisfiesVersion(vers, r.VersionRequirements())
-		if !ok && !upgrade {
-			util.StatusMessage(util.VERBOSITY_QUIET, "WARNING: Installed "+
-				"version %s of repository %s does not match desired "+
-				"version %s in project file.  You can fix this by either upgrading"+
-				" your repository, or modifying the project.yml file.\n",
-				vers, rname, r.VersionRequirementsString())
-			return true, err
-		} else {
-			if !upgrade {
-				util.StatusMessage(util.VERBOSITY_VERBOSE, "%s correct version already installed\n", r.Name())
-				return true, nil
-			} else {
-				skip, err := proj.upgradeCheck(r, vers, force)
-				return skip, err
-			}
-		}
-	} else {
-		// Fallthrough and perform the installation.
-		// Check to make sure that this repository contains a version
-		// that can satisfy.
-		_, _, ok := rdesc.Match(r)
-		if !ok {
-			fmt.Printf("WARNING: No matching repository version found for repository "+
-				"%s specified in project.\n", r.Name())
-			return true, err
+func (proj *Project) LocalRepo() *repo.Repo {
+	return proj.localRepo
+}
+
+func (proj *Project) Warnings() []string {
+	return proj.warnings
+}
+
+// Selects repositories from the global state that satisfy the specified
+// predicate.
+func (proj *Project) SelectRepos(pred func(r *repo.Repo) bool) []*repo.Repo {
+	all := proj.repos.Sorted()
+	var filtered []*repo.Repo
+
+	for _, r := range all {
+		if pred(r) {
+			filtered = append(filtered, r)
 		}
 	}
 
-	return false, nil
+	return filtered
 }
 
-func (proj *Project) checkDeps(r *repo.Repo) error {
-	repos, updated, err := r.UpdateDesc()
-	if err != nil {
-		return err
-	}
+// Installs or upgrades repos matching the specified predicate.
+func (proj *Project) InstallIf(
+	upgrade bool, force bool, ask bool,
+	predicate func(r *repo.Repo) bool) error {
 
-	if !updated {
-		return nil
+	// Make sure we have an up to date copy of all `repository.yml` files.
+	if err := proj.downloadRepositoryYmlFiles(); err != nil {
+		return err
 	}
 
-	for _, newRepo := range repos {
-		curRepo, ok := proj.repos[newRepo.Name()]
-		if !ok {
-			proj.repos[newRepo.Name()] = newRepo
-			return proj.UpdateRepos()
-		} else {
-			// Add any dependencies we might have found here.
-			for _, dep := range newRepo.Deps() {
-				newRepo.DownloadDesc()
-				newRepo.ReadDesc()
-				curRepo.AddDependency(dep)
-			}
-		}
-	}
+	// Now that all repos have been successfully fetched, we can finish the
+	// install procedure locally.
 
-	return nil
-}
+	// Determine which repos the user wants to install or upgrade.
+	specifiedRepoList := proj.SelectRepos(predicate)
 
-func (proj *Project) UpdateRepos() error {
-	repoList := proj.Repos()
-	for _, r := range repoList {
-		if r.IsLocal() {
-			continue
-		}
+	inst, err := install.NewInstaller(proj.repos, proj.rootRepoReqs)
+	if err != nil {
+		return err
+	}
 
-		err := proj.checkDeps(r)
-		if err != nil {
-			return err
-		}
+	if upgrade {
+		return inst.Upgrade(specifiedRepoList, force, ask)
+	} else {
+		return inst.Install(specifiedRepoList, force, ask)
 	}
-	return nil
 }
 
-func (proj *Project) Install(upgrade bool, force bool) error {
-	repoList := proj.Repos()
+// Syncs (i.e., applies `git pull` to) repos matching the specified predicate.
+func (proj *Project) SyncIf(
+	force bool, ask bool, predicate func(r *repo.Repo) bool) error {
 
-	for rname, _ := range repoList {
-		// Ignore the local repo on install
-		if rname == repo.REPO_NAME_LOCAL {
-			continue
-		}
-
-		// First thing we do is update repository description.  This
-		// will get us available branches and versions in the repository.
-		if err := proj.UpdateRepos(); err != nil {
-			return err
-		}
+	// Make sure we have an up to date copy of all `repository.yml` files.
+	if err := proj.downloadRepositoryYmlFiles(); err != nil {
+		return err
 	}
 
-	// Get repository list, and print every repo and it's dependencies.
-	if err := repo.CheckDeps(upgrade, proj.Repos()); err != nil {
+	// Determine which repos the user wants to sync.
+	repoList := proj.SelectRepos(predicate)
+
+	inst, err := install.NewInstaller(proj.repos, proj.rootRepoReqs)
+	if err != nil {
 		return err
 	}
 
-	for rname, r := range proj.Repos() {
-		if r.IsLocal() {
-			continue
-		}
-		// Check the version requirements on this repository, and see
-		// whether or not we need to install/upgrade it.
-		skip, err := proj.checkVersionRequirements(r, upgrade, force)
-		if err != nil {
-			return err
-		}
-		if skip {
-			continue
-		}
+	return inst.Sync(repoList, force, ask)
+}
 
-		// Do the hard work of actually copying and installing the repository.
-		rvers, err := r.Install(upgrade || force)
-		if err != nil {
-			return err
-		}
+func (proj *Project) InfoIf(predicate func(r *repo.Repo) bool,
+	remote bool) error {
 
-		if upgrade {
-			util.StatusMessage(util.VERBOSITY_VERBOSE, "%s successfully upgraded to version %s\n",
-				r.Name(), rvers.String())
-		} else {
-			util.StatusMessage(util.VERBOSITY_VERBOSE, "%s successfully installed version %s\n",
-				r.Name(), rvers.String())
+	if remote {
+		// Make sure we have an up to date copy of all `repository.yml` files.
+		if err := proj.downloadRepositoryYmlFiles(); err != nil {
+			return err
 		}
-
-		// Update the project state with the new repository version information.
-		proj.projState.Replace(rname, rvers)
 	}
 
-	// Save the project state, including any updates or changes to the project
-	// information that either install or upgrade caused.
-	if err := proj.projState.Save(); err != nil {
+	// Determine which repos the user wants info about.
+	repoList := proj.SelectRepos(predicate)
+
+	// Ignore errors.  We will deal with bad repos individually when we display
+	// info about them.
+	inst, _ := install.NewInstaller(proj.repos, proj.rootRepoReqs)
+	if err := inst.Info(repoList, remote); err != nil {
 		return err
 	}
 
 	return nil
 }
 
-func (proj *Project) Upgrade(force bool) error {
-	return proj.Install(true, force)
-}
-
-func (proj *Project) loadRepo(rname string, v *viper.Viper) error {
-	varName := fmt.Sprintf("repository.%s", rname)
+// Loads a complete repo definition from the appropriate `repository.yml` file.
+// The supplied fields form a basic repo description as read from `project.yml`
+// or from another repo's dependency list.
+//
+// @param name                  The name of the repo to read.
+// @param fields                Fields containing the basic repo description.
+//
+// @return *Repo                The fully-read repo on success; nil on failure.
+// @return error                Error on failure.
+func (proj *Project) loadRepo(name string, fields map[string]string) (
+	*repo.Repo, error) {
 
-	repoVars := v.GetStringMapString(varName)
-	if len(repoVars) == 0 {
-		return util.NewNewtError(fmt.Sprintf("Missing configuration for "+
-			"repository %s.", rname))
-	}
-	if repoVars["type"] == "" {
-		return util.NewNewtError(fmt.Sprintf("Missing type for repository " +
-			rname))
+	// First, read the repo description from the supplied fields.
+	if fields["type"] == "" {
+		return nil,
+			util.FmtNewtError("Missing type for repository %s", name)
 	}
 
-	dl, err := downloader.LoadDownloader(rname, repoVars)
+	dl, err := downloader.LoadDownloader(name, fields)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
-	rversreq := repoVars["vers"]
-	r, err := repo.NewRepo(rname, rversreq, dl)
+	// Construct a new repo object from the basic description information.
+	r, err := repo.NewRepo(name, dl)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	for _, ignDir := range ignoreSearchDirs {
 		r.AddIgnoreDir(ignDir)
 	}
 
-	rd, err := repo.NewRepoDependency(rname, rversreq)
-	if err != nil {
-		return err
+	// Read the full repo definition from its `repository.yml` file.
+	if err := r.Read(); err != nil {
+		return r, err
 	}
-	rd.Storerepo = r
 
-	proj.localRepo.AddDependency(rd)
-
-	// Read the repo's descriptor file so that we have its newt version
-	// compatibility map.
-	r.ReadDesc()
-
-	rvers := proj.projState.GetInstalledVersion(rname)
-	code, msg := r.CheckNewtCompatibility(rvers, newtutil.NewtVersion)
-	switch code {
-	case compat.NEWT_COMPAT_GOOD:
-	case compat.NEWT_COMPAT_WARN:
-		util.StatusMessage(util.VERBOSITY_QUIET, "WARNING: %s.\n", msg)
-	case compat.NEWT_COMPAT_ERROR:
-		return util.NewNewtError(msg)
+	// Warn the user about incompatibilities with this version of newt.
+	ver, err := proj.GetRepoVersion(name)
+	if err != nil {
+		return nil, err
+	}
+	if ver != nil {
+		code, msg := r.CheckNewtCompatibility(*ver, newtutil.NewtVersion)
+		switch code {
+		case compat.NEWT_COMPAT_GOOD:
+		case compat.NEWT_COMPAT_WARN:
+			util.StatusMessage(util.VERBOSITY_QUIET, "WARNING: %s.\n", msg)
+		case compat.NEWT_COMPAT_ERROR:
+			return nil, util.NewNewtError(msg)
+		}
 	}
 
-	log.Debugf("Loaded repository %s (type: %s, user: %s, repo: %s)", rname,
-		repoVars["type"], repoVars["user"], repoVars["repo"])
+	// XXX: This log message assumes a "github" type repo.
+	log.Debugf("Loaded repository %s (type: %s, user: %s, repo: %s)", name,
+		fields["type"], fields["user"], fields["repo"])
 
-	proj.repos[r.Name()] = r
-	return nil
+	return r, nil
 }
 
 func (proj *Project) checkNewtVer() error {
-	compatSms := proj.v.GetStringMapString("project.newt_compatibility")
+	compatSms := proj.yc.GetValStringMapString(
+		"project.newt_compatibility", nil)
+
 	// If this project doesn't have a newt compatibility map, just assume there
 	// is no incompatibility.
 	if len(compatSms) == 0 {
@@ -470,8 +421,78 @@ func (proj *Project) checkNewtVer() error {
 	}
 }
 
+// Loads the `repository.yml` file for each depended-on repo.  This
+func (proj *Project) loadRepoDeps(download bool) error {
+	seen := map[string]struct{}{}
+
+	loadDeps := func(r *repo.Repo) ([]*repo.Repo, error) {
+		var newRepos []*repo.Repo
+
+		depMap := r.CommitDepMap()
+		for _, depSlice := range depMap {
+			for _, dep := range depSlice {
+				if _, ok := seen[dep.Name]; !ok {
+					seen[r.Name()] = struct{}{}
+
+					depRepo := proj.repos[dep.Name]
+					if depRepo == nil {
+						depRepo, _ = proj.loadRepo(dep.Name, dep.Fields)
+						proj.repos[dep.Name] = depRepo
+					}
+					newRepos = append(newRepos, depRepo)
+
+					if download {
+						if _, err := depRepo.UpdateDesc(); err != nil {
+							return nil, err
+						}
+					}
+				}
+			}
+		}
+
+		return newRepos, nil
+	}
+
+	curRepos := proj.repos.Sorted()
+	for len(curRepos) > 0 {
+		var nextRepos []*repo.Repo
+
+		for _, r := range curRepos {
+			depRepos, err := loadDeps(r)
+			if err != nil {
+				return err
+			}
+
+			nextRepos = append(nextRepos, depRepos...)
+		}
+
+		curRepos = nextRepos
+	}
+
+	return nil
+}
+
+func (proj *Project) downloadRepositoryYmlFiles() error {
+	// Download the `repository.yml` file for each root-level repo (those
+	// specified in the `project.yml` file).
+	for _, r := range proj.repos.Sorted() {
+		if !r.IsLocal() {
+			if _, err := r.UpdateDesc(); err != nil {
+				return err
+			}
+		}
+	}
+
+	// Download the `repository.yml` file for each depended-on repo.
+	if err := proj.loadRepoDeps(true); err != nil {
+		return err
+	}
+
+	return nil
+}
+
 func (proj *Project) loadConfig() error {
-	v, err := util.ReadConfig(proj.BasePath,
+	yc, err := newtutil.ReadConfig(proj.BasePath,
 		strings.TrimSuffix(PROJECT_FILE_NAME, ".yml"))
 	if err != nil {
 		return util.NewNewtError(err.Error())
@@ -479,14 +500,9 @@ func (proj *Project) loadConfig() error {
 	// Store configuration object for access to future values,
 	// this avoids keeping every string around as a project variable when
 	// we need to process it later.
-	proj.v = v
+	proj.yc = yc
 
-	proj.projState, err = LoadProjectState()
-	if err != nil {
-		return err
-	}
-
-	proj.name = v.GetString("project.name")
+	proj.name = yc.GetValString("project.name", nil)
 
 	// Local repository always included in initialization
 	r, err := repo.NewLocalRepo(proj.name)
@@ -500,14 +516,34 @@ func (proj *Project) loadConfig() error {
 		r.AddIgnoreDir(ignDir)
 	}
 
-	rstrs := v.GetStringSlice("project.repositories")
-	for _, repoName := range rstrs {
-		if err := proj.loadRepo(repoName, v); err != nil {
-			return err
+	// Assume every item starting with "repository." is a repository descriptor
+	// and try to load it.
+	for k, _ := range yc.AllSettings() {
+		repoName := strings.TrimPrefix(k, "repository.")
+		if repoName != k {
+			fields := yc.GetValStringMapString(k, nil)
+			r, _ := proj.loadRepo(repoName, fields)
+
+			verReqs, err := newtutil.ParseRepoVersionReqs(fields["vers"])
+			if err != nil {
+				return util.FmtNewtError(
+					"Repo \"%s\" contains invalid version requirement: %s (%s)",
+					repoName, fields["vers"], err.Error())
+			}
+
+			proj.repos[repoName] = r
+			proj.rootRepoReqs[repoName] = verReqs
 		}
 	}
 
-	ignoreDirs := v.GetStringSlice("project.ignore_dirs")
+	// Read `repository.yml` files belonging to dependee repos from disk.
+	// These repos might not be specified in the `project.yml` file, but they
+	// are still part of the project.
+	if err := proj.loadRepoDeps(false); err != nil {
+		return err
+	}
+
+	ignoreDirs := yc.GetValStringSlice("project.ignore_dirs", nil)
 	for _, ignDir := range ignoreDirs {
 		repoName, dirName, err := newtutil.ParsePackageString(ignDir)
 		if err != nil {
@@ -539,6 +575,7 @@ func (proj *Project) Init(dir string) error {
 	interfaces.SetProject(proj)
 
 	proj.repos = map[string]*repo.Repo{}
+	proj.rootRepoReqs = map[string][]newtutil.RepoVersionReq{}
 
 	// Load Project configuration
 	if err := proj.loadConfig(); err != nil {
@@ -548,42 +585,20 @@ func (proj *Project) Init(dir string) error {
 	return nil
 }
 
-func matchNamePath(name, path string) bool {
-	// assure that name and path use the same path separator...
-	names := filepath.SplitList(name)
-	name = filepath.Join(names...)
-
-	if strings.HasSuffix(path, name) {
-		return true
-	}
-	return false
-}
-
 func (proj *Project) ResolveDependency(dep interfaces.DependencyInterface) interfaces.PackageInterface {
 	type NamePath struct {
 		name string
 		path string
 	}
 
-	var errorPkgs []NamePath
 	for _, pkgList := range proj.packages {
 		for _, pkg := range *pkgList {
-			name := pkg.Name()
-			path := pkg.BasePath()
-			if !matchNamePath(name, path) {
-				errorPkgs = append(errorPkgs, NamePath{name: name, path: path})
-			}
 			if dep.SatisfiesDependency(pkg) {
 				return pkg
 			}
 		}
 	}
 
-	for _, namepath := range errorPkgs {
-		util.StatusMessage(util.VERBOSITY_VERBOSE,
-			"Package name \"%s\" doesn't match path \"%s\"\n", namepath.name, namepath.path)
-	}
-
 	return nil
 }
 
@@ -602,10 +617,12 @@ func (proj *Project) ResolvePackage(
 	var repo interfaces.RepoInterface
 	if repoName == "" {
 		repo = dfltRepo
-	} else {
+	} else if proj.repos[repoName] != nil {
 		repo = proj.repos[repoName]
+	} else {
+		return nil, util.FmtNewtError("invalid package name: %s (unkwn repo %s)",
+			name, repoName)
 	}
-
 	dep, err := pkg.NewDependency(repo, pkgName)
 	if err != nil {
 		return nil, util.FmtNewtError("invalid package name: %s (%s)", name,
@@ -673,15 +690,7 @@ func (proj *Project) loadPackageList() error {
 	repos := proj.Repos()
 	for name, repo := range repos {
 		list, warnings, err := pkg.ReadLocalPackages(repo, repo.Path())
-		if err != nil {
-			/* Failed to read the repo's package list.  Report the failure as a
-			 * warning if the project state indicates that this repo should be
-			 * installed.
-			 */
-			if proj.projState.installedRepos[name] != nil {
-				util.StatusMessage(util.VERBOSITY_QUIET, err.Error()+"\n")
-			}
-		} else {
+		if err == nil {
 			proj.packages[name] = list
 		}
 
diff --git a/vendor/mynewt.apache.org/newt/newt/project/projectstate.go b/vendor/mynewt.apache.org/newt/newt/project/projectstate.go
deleted file mode 100644
index 0e0cc3b2..00000000
--- a/vendor/mynewt.apache.org/newt/newt/project/projectstate.go
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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.
- */
-
-package project
-
-import (
-	"bufio"
-	"fmt"
-	"os"
-	"strings"
-
-	"mynewt.apache.org/newt/newt/interfaces"
-	"mynewt.apache.org/newt/newt/repo"
-	"mynewt.apache.org/newt/util"
-)
-
-const PROJECT_STATE_FILE = "project.state"
-
-type ProjectState struct {
-	installedRepos map[string]*repo.Version
-}
-
-func (ps *ProjectState) GetInstalledVersion(rname string) *repo.Version {
-	v, _ := ps.installedRepos[rname]
-	return v
-}
-
-func (ps *ProjectState) Replace(rname string, rvers *repo.Version) {
-	ps.installedRepos[rname] = rvers
-}
-
-func (ps *ProjectState) StateFile() string {
-	return interfaces.GetProject().Path() + "/" + PROJECT_STATE_FILE
-}
-
-func (ps *ProjectState) Save() error {
-	file, err := os.Create(ps.StateFile())
-	if err != nil {
-		return util.NewNewtError(err.Error())
-	}
-	defer file.Close()
-
-	for k, v := range ps.installedRepos {
-		str := ""
-		if v.Tag() == "" {
-			str = fmt.Sprintf("%s,%d.%d.%d\n", k, v.Major(), v.Minor(), v.Revision())
-		} else {
-			str = fmt.Sprintf("%s,%s-tag\n", k, v.Tag())
-		}
-		file.WriteString(str)
-	}
-
-	return nil
-}
-
-func (ps *ProjectState) Init() error {
-	ps.installedRepos = map[string]*repo.Version{}
-
-	path := ps.StateFile()
-
-	// Read project state file.  If doesn't exist, it will be empty until somebody
-	// installs a repo
-	if util.NodeNotExist(path) {
-		return nil
-	}
-
-	file, err := os.Open(path)
-	if err != nil {
-		return err
-	}
-	defer file.Close()
-
-	scanner := bufio.NewScanner(file)
-	for scanner.Scan() {
-		line := strings.Split(scanner.Text(), ",")
-		if len(line) != 2 {
-			return util.NewNewtError(fmt.Sprintf(
-				"Invalid format for line in project.state file: %s\n", line))
-		}
-
-		repoName := line[0]
-		repoVers, err := repo.LoadVersion(line[1])
-		if err != nil {
-			return err
-		}
-
-		ps.installedRepos[repoName] = repoVers
-	}
-	return nil
-}
-
-func LoadProjectState() (*ProjectState, error) {
-	ps := &ProjectState{}
-	if err := ps.Init(); err != nil {
-		return nil, err
-	}
-	return ps, nil
-}
diff --git a/vendor/mynewt.apache.org/newt/newt/repo/repo.go b/vendor/mynewt.apache.org/newt/newt/repo/repo.go
index 77cff0f9..da381e7c 100644
--- a/vendor/mynewt.apache.org/newt/newt/repo/repo.go
+++ b/vendor/mynewt.apache.org/newt/newt/repo/repo.go
@@ -20,14 +20,12 @@
 package repo
 
 import (
-	"bufio"
 	"fmt"
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"strconv"
+	"sort"
 	"strings"
-	"time"
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/spf13/cast"
@@ -36,64 +34,59 @@ import (
 	"mynewt.apache.org/newt/newt/downloader"
 	"mynewt.apache.org/newt/newt/interfaces"
 	"mynewt.apache.org/newt/newt/newtutil"
+	"mynewt.apache.org/newt/newt/ycfg"
 	"mynewt.apache.org/newt/util"
-	"mynewt.apache.org/newt/viper"
 )
 
 const REPO_NAME_LOCAL = "local"
 const REPO_DEFAULT_PERMS = 0755
 
 const REPO_FILE_NAME = "repository.yml"
+const REPO_VER_FILE_NAME = "version.yml"
 const REPOS_DIR = "repos"
 
 type Repo struct {
 	name       string
 	downloader downloader.Downloader
 	localPath  string
-	versreq    []interfaces.VersionReqInterface
-	rdesc      *RepoDesc
-	deps       []*RepoDependency
 	ignDirs    []string
 	updated    bool
 	local      bool
 	ncMap      compat.NewtCompatMap
-}
 
-type RepoDesc struct {
-	name string
-	vers map[*Version]string
-}
+	// True if this repo was cloned during this invocation of newt.
+	newlyCloned bool
 
-type RepoDependency struct {
-	versreq   []interfaces.VersionReqInterface
-	name      string
-	Storerepo *Repo
-}
+	// commit => [dependencies]
+	deps map[string][]*RepoDependency
 
-func (rd *RepoDependency) String() string {
-	rstr := "<"
+	// version => commit
+	vers map[newtutil.RepoVersion]string
+}
 
-	for idx, vr := range rd.versreq {
-		if idx != 0 {
-			rstr = rstr + " " + vr.Version().String()
-		} else {
-			rstr = rstr + vr.Version().String()
-		}
-	}
-	rstr = rstr + ">"
-	return rstr
+type RepoDependency struct {
+	Name    string
+	VerReqs []newtutil.RepoVersionReq
+	Fields  map[string]string
 }
 
-func (r *Repo) Deps() []*RepoDependency {
+func (r *Repo) CommitDepMap() map[string][]*RepoDependency {
 	return r.deps
 }
 
-func (r *Repo) AddDependency(rd *RepoDependency) {
-	r.deps = append(r.deps, rd)
-}
+func (r *Repo) AllDeps() []*RepoDependency {
+	commits := make([]string, 0, len(r.deps))
+	for commit, _ := range r.deps {
+		commits = append(commits, commit)
+	}
+	sort.Strings(commits)
 
-func (rd *RepoDependency) Name() string {
-	return rd.name
+	deps := []*RepoDependency{}
+	for _, b := range commits {
+		deps = append(deps, r.deps[b]...)
+	}
+
+	return deps
 }
 
 func (r *Repo) AddIgnoreDir(ignDir string) {
@@ -117,8 +110,15 @@ func (repo *Repo) FilteredSearchList(
 	path := filepath.Join(repo.Path(), curPath)
 	dirList, err := ioutil.ReadDir(path)
 	if err != nil {
-		return list, util.FmtNewtError("failed to read repo \"%s\": %s",
-			repo.Name(), err.Error())
+		// The repo could not be found in the `repos` directory.  Display a
+		// warning if the `project.state` file indicates that the repo has been
+		// installed.
+		var warning error
+		if interfaces.GetProject().RepoIsInstalled(repo.Name()) {
+			warning = util.FmtNewtError("failed to read repo \"%s\": %s",
+				repo.Name(), err.Error())
+		}
+		return list, warning
 	}
 
 	for _, dirEnt := range dirList {
@@ -160,241 +160,6 @@ func (repo *Repo) FilteredSearchList(
 	return list, nil
 }
 
-func NewRepoDependency(rname string, verstr string) (*RepoDependency, error) {
-	var err error
-
-	rd := &RepoDependency{}
-	rd.versreq, err = LoadVersionMatches(verstr)
-	if err != nil {
-		return nil, err
-	}
-	rd.name = rname
-
-	return rd, nil
-}
-
-func pickVersion(repo *Repo, versions []*Version) ([]*Version, error) {
-	fmt.Printf("Dependency list for %s contains a specific commit tag, "+
-		"so normal version number/stability comparison cannot be done.\n",
-		repo.Name())
-	fmt.Printf("If the following list does not contain the requirement to use, " +
-		"then modify your project.yml so that it does.\n")
-	for {
-		for i, vers := range versions {
-			fmt.Printf(" %d) %s\n", i, vers.String())
-		}
-		fmt.Printf("Pick the index of a version to use from above list: ")
-		line, _, err := bufio.NewReader(os.Stdin).ReadLine()
-		if err != nil {
-			return nil, util.NewNewtError(fmt.Sprintf("Couldn't read "+
-				"response: %s", err.Error()))
-		}
-		idx, err := strconv.ParseUint(string(line), 10, 8)
-		if err != nil {
-			fmt.Printf("Error: could not parse the response.\n")
-		} else {
-			repo.versreq, err = LoadVersionMatches(versions[idx].String())
-			return []*Version{versions[idx]}, nil
-		}
-	}
-}
-
-func CheckDeps(upgrade bool, checkRepos map[string]*Repo) error {
-	// For each dependency, get it's version
-	depArray := map[string][]*Version{}
-
-	for _, checkRepo := range checkRepos {
-		for _, rd := range checkRepo.Deps() {
-			lookupRepo := checkRepos[rd.Name()]
-
-			_, vers, ok := lookupRepo.rdesc.Match(rd.Storerepo)
-			if !ok {
-				return util.NewNewtError(fmt.Sprintf("No "+
-					"matching version for dependent repository %s", rd.name))
-			}
-			log.Debugf("Dependency for %s: %s (%s)", checkRepo.Name(), rd.Name(), vers.String())
-
-			_, ok = depArray[rd.Name()]
-			if !ok {
-				depArray[rd.Name()] = []*Version{}
-			}
-			depArray[rd.Name()] = append(depArray[rd.Name()], vers)
-		}
-	}
-
-	for repoName, depVersList := range depArray {
-		if len(depVersList) <= 1 {
-			continue
-		}
-
-		pickVer := false
-		for _, depVers := range depVersList {
-			if depVers.Tag() != "" {
-				pickVer = true
-				break
-			}
-		}
-		if pickVer {
-			newArray, err := pickVersion(checkRepos[repoName],
-				depArray[repoName])
-			depArray[repoName] = newArray
-			if err != nil {
-				return err
-			}
-		}
-	}
-	for repoName, depVersList := range depArray {
-		for _, depVers := range depVersList {
-			for _, curVers := range depVersList {
-				if depVers.CompareVersions(depVers, curVers) != 0 ||
-					depVers.Stability() != curVers.Stability() {
-					return util.NewNewtError(fmt.Sprintf(
-						"Conflict detected.  Repository %s has multiple dependency versions on %s. "+
-							"Notion of repository version is %s, whereas required is %s ",
-						repoName, curVers, depVers))
-				}
-			}
-		}
-	}
-
-	return nil
-}
-
-func (rd *RepoDesc) MatchVersion(searchVers *Version) (string, *Version, bool) {
-	for vers, curBranch := range rd.vers {
-		if vers.CompareVersions(vers, searchVers) == 0 &&
-			searchVers.Stability() == vers.Stability() {
-			return curBranch, vers, true
-		}
-	}
-	return "", nil, false
-}
-
-func (rd *RepoDesc) Match(r *Repo) (string, *Version, bool) {
-	log.Debugf("Requires repository version %s for %s\n", r.VersionRequirements(),
-		r.Name())
-	for vers, branch := range rd.vers {
-		if vers.SatisfiesVersion(r.VersionRequirements()) {
-			log.Debugf("Found matching version %s for repo %s",
-				vers.String(), r.Name())
-			if vers.Stability() != VERSION_STABILITY_NONE {
-				// Load the branch as a version, and search for it
-				searchVers, err := LoadVersion(branch)
-				if err != nil {
-					return "", nil, false
-				}
-				// Need to match the NONE stability in order to find the right
-				// branch.
-				searchVers.stability = VERSION_STABILITY_NONE
-
-				var ok bool
-				branch, vers, ok = rd.MatchVersion(searchVers)
-				if !ok {
-					return "", nil, false
-				}
-				log.Debugf("Founding matching version %s for search version %s, related branch is %s\n",
-					vers, searchVers, branch)
-
-			}
-
-			return branch, vers, true
-		} else {
-			log.Debugf("Rejected version %s for repo %s",
-				vers.String(), r.Name())
-		}
-	}
-
-	/*
-	 * No match so far. See if requirements have a repository tag directly.
-	 * If so, then return that as the branch.
-	 */
-	for _, versreq := range r.VersionRequirements() {
-		tag := versreq.Version().Tag()
-		if tag != "" {
-			log.Debugf("Requirements for %s have a tag option %s\n",
-				r.Name(), tag)
-			return tag, NewTag(tag), true
-		}
-	}
-	return "", nil, false
-}
-
-func (rd *RepoDesc) SatisfiesVersion(vers *Version, versReqs []interfaces.VersionReqInterface) bool {
-	var err error
-	versMatches := []interfaces.VersionReqInterface{}
-	for _, versReq := range versReqs {
-		versMatch := &VersionMatch{}
-		versMatch.compareType = versReq.CompareType()
-
-		if versReq.Version().Stability() != VERSION_STABILITY_NONE {
-			// Look up this item in the RepoDescription, and get a version
-			searchVers := versReq.Version().(*Version)
-			branch, _, ok := rd.MatchVersion(searchVers)
-			if !ok {
-				return false
-			}
-			versMatch.Vers, err = LoadVersion(branch)
-			if err != nil {
-				return false
-			}
-		} else {
-			versMatch.Vers = versReq.Version().(*Version)
-		}
-
-		versMatches = append(versMatches, versMatch)
-	}
-
-	return vers.SatisfiesVersion(versMatches)
-}
-
-func (rd *RepoDesc) Init(name string, versBranchMap map[string]string) error {
-	rd.name = name
-	rd.vers = map[*Version]string{}
-
-	for versStr, branch := range versBranchMap {
-		log.Debugf("Printing version %s for remote repo %s", versStr, name)
-		vers, err := LoadVersion(versStr)
-		if err != nil {
-			return err
-		}
-
-		// store branch->version mapping
-		rd.vers[vers] = branch
-	}
-
-	return nil
-}
-
-func (rd *RepoDesc) String() string {
-	name := rd.name + "@"
-	for k, v := range rd.vers {
-		name += fmt.Sprintf("%s=%s", k.String(), v)
-		name += "#"
-	}
-
-	return name
-}
-
-func NewRepoDesc(name string, versBranchMap map[string]string) (*RepoDesc, error) {
-	rd := &RepoDesc{}
-
-	if err := rd.Init(name, versBranchMap); err != nil {
-		return nil, err
-	}
-
-	return rd, nil
-}
-
-func (r *Repo) GetRepoDesc() (*RepoDesc, error) {
-	if r.rdesc == nil {
-		return nil, util.NewNewtError(fmt.Sprintf(
-			"Repository description for %s not yet initialized.  Must "+
-				"download it first. ", r.Name()))
-	} else {
-		return r.rdesc, nil
-	}
-}
-
 func (r *Repo) Name() string {
 	return r.name
 }
@@ -407,22 +172,17 @@ func (r *Repo) IsLocal() bool {
 	return r.local
 }
 
-func (r *Repo) VersionRequirements() []interfaces.VersionReqInterface {
-	return r.versreq
+func (r *Repo) IsNewlyCloned() bool {
+	return r.newlyCloned
 }
 
-func (r *Repo) VersionRequirementsString() string {
-	str := ""
-	for _, vreq := range r.versreq {
-		str += vreq.String()
-	}
-
-	return str
+func RepoFilePath(repoName string) string {
+	return interfaces.GetProject().Path() + "/" + REPOS_DIR + "/" +
+		".configs/" + repoName
 }
 
 func (r *Repo) repoFilePath() string {
-	return interfaces.GetProject().Path() + "/" + REPOS_DIR + "/" +
-		".configs/" + r.name + "/"
+	return RepoFilePath(r.name)
 }
 
 func (r *Repo) patchesFilePath() string {
@@ -430,14 +190,19 @@ func (r *Repo) patchesFilePath() string {
 		"/.patches/"
 }
 
-func (r *Repo) downloadRepo(branchName string) error {
+func (r *Repo) downloadRepo(commit string) error {
 	dl := r.downloader
 
-	// Download the git repo, returns the git repo, checked out to that branch
-	tmpdir, err := dl.DownloadRepo(branchName)
+	tmpdir, err := newtutil.MakeTempRepoDir()
 	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Error download repository %s, : %s",
-			r.Name(), err.Error()))
+		return err
+	}
+	defer os.RemoveAll(tmpdir)
+
+	// Download the git repo, returns the git repo, checked out to that commit
+	if err := dl.Clone(commit, tmpdir); err != nil {
+		return util.FmtNewtError("Error downloading repository %s: %s",
+			r.Name(), err.Error())
 	}
 
 	// Copy the Git repo into the the desired local path of the repo
@@ -448,330 +213,326 @@ func (r *Repo) downloadRepo(branchName string) error {
 		return err
 	}
 
+	r.newlyCloned = true
 	return nil
 }
 
-func (r *Repo) checkExists() bool {
+func (r *Repo) CheckExists() bool {
 	return util.NodeExist(r.Path())
 }
 
-func (r *Repo) updateRepo(branchName string) error {
-	dl := r.downloader
-	err := dl.UpdateRepo(r.Path(), branchName)
-	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Error updating\n"))
+func (r *Repo) updateRepo(commit string) error {
+	// Clone the repo if it doesn't exist.
+	if err := r.ensureExists(); err != nil {
+		return err
 	}
-	return nil
-}
 
-func (r *Repo) cleanupRepo(branchName string) error {
-	dl := r.downloader
-	err := dl.CleanupRepo(r.Path(), branchName)
-	if err != nil {
-		return util.NewNewtError(fmt.Sprintf("Error cleaning and updating\n"))
+	// Fetch and checkout the specified commit.
+	if err := r.downloader.Pull(r.Path(), commit); err != nil {
+		return util.FmtNewtError(
+			"Error updating \"%s\": %s", r.Name(), err.Error())
 	}
+
 	return nil
 }
 
-func (r *Repo) saveLocalDiff() (string, error) {
-	dl := r.downloader
-	diff, err := dl.LocalDiff(r.Path())
-	if err != nil {
-		return "", util.NewNewtError(fmt.Sprintf(
-			"Error creating diff for \"%s\" : %s", r.Name(), err.Error()))
-	}
-
-	// NOTE: date was not a typo: https://golang.org/pkg/time/#Time.Format
-	timenow := time.Now().Format("20060102_150405")
-	filename := r.patchesFilePath() + r.Name() + "_" + timenow + ".diff"
+// Indicates whether the specified repo is in a clean or dirty state.
+//
+// @return string               Text describing repo's dirty state, or "" if
+//                                  clean.
+// @return error                Error.
+func (r *Repo) DirtyState() (string, error) {
+	return r.downloader.DirtyState(r.Path())
+}
 
-	f, err := os.Create(filename)
+func (r *Repo) Install(ver newtutil.RepoVersion) error {
+	commit, err := r.CommitFromVer(ver)
 	if err != nil {
-		return "", util.NewNewtError(fmt.Sprintf(
-			"Error creating repo diff file \"%s\"", filename))
+		return err
 	}
-	defer f.Close()
 
-	_, err = f.Write(diff)
-	if err != nil {
-		return "", util.NewNewtError(fmt.Sprintf(
-			"Error writing repo diff file \"%s\"", filename))
+	if err := r.updateRepo(commit); err != nil {
+		return err
 	}
 
-	return filename, nil
+	return nil
 }
 
-func (r *Repo) currentBranch() (string, error) {
-	dl := r.downloader
-	branch, err := dl.CurrentBranch(r.Path())
+func (r *Repo) Upgrade(ver newtutil.RepoVersion) error {
+	commit, err := r.CommitFromVer(ver)
 	if err != nil {
-		return "", util.NewNewtError(fmt.Sprintf("Error finding current branch for \"%s\" : %s",
-			r.Name(), err.Error()))
+		return err
 	}
-	return filepath.Base(branch), nil
-}
 
-func (r *Repo) Install(force bool) (*Version, error) {
-	exists := util.NodeExist(r.Path())
-	if exists && !force {
-		return nil, util.NewNewtError(fmt.Sprintf(
-			"Repository %s already exists, provide the -f option "+
-				"to overwrite", r.Name()))
+	if err := r.updateRepo(commit); err != nil {
+		return err
 	}
 
-	branchName, vers, found := r.rdesc.Match(r)
-	if !found {
-		return nil, util.NewNewtError(fmt.Sprintf("No repository "+
-			"matching description %s found", r.rdesc.String()))
+	return nil
+}
+
+// @return bool                 True if the sync succeeded.
+// @return error                Fatal error.
+func (r *Repo) Sync(ver newtutil.RepoVersion) (bool, error) {
+	// Sync is only allowed if a branch is checked out.
+	branch, err := r.downloader.CurrentBranch(r.localPath)
+	if err != nil {
+		return false, err
 	}
 
-	// if the repo is already cloned, try to cleanup and checkout the requested branch
-	if exists {
-		err := r.cleanupRepo(branchName)
-		if err == nil {
-			return vers, nil
+	if branch == "" {
+		commits, err := r.CurrentCommits()
+		if err != nil {
+			return false, err
 		}
 
-		// cleanup failed, so remove current copy and let download clone again...
-		if err := os.RemoveAll(r.Path()); err != nil {
-			return nil, util.NewNewtError(err.Error())
-		}
+		util.StatusMessage(util.VERBOSITY_DEFAULT,
+			"Skipping \"%s\": not using a branch (current-commits=%v)\n",
+			r.Name(), commits)
+		return false, nil
 	}
 
-	// repo was not already cloned or cleanup failed...
-	if err := r.downloadRepo(branchName); err != nil {
-		return nil, err
+	// Determine the upstream associated with the current branch.  This is the
+	// upstream that will be pulled from.
+	upstream, err := r.downloader.UpstreamFor(r.localPath, branch)
+	if err != nil {
+		return false, err
+	}
+	if upstream == "" {
+		util.StatusMessage(util.VERBOSITY_QUIET,
+			"Failed to sync repo \"%s\": no upstream being tracked "+
+				"(branch=%s)\n",
+			r.Name(), branch)
+		return false, nil
 	}
 
-	return vers, nil
+	util.StatusMessage(util.VERBOSITY_DEFAULT,
+		"Syncing repository \"%s\" (%s)... ", r.Name(), upstream)
+
+	// Pull from upstream.
+	err = r.updateRepo(branch)
+	if err == nil {
+		util.StatusMessage(util.VERBOSITY_DEFAULT, "success\n")
+		return true, nil
+	} else {
+		util.StatusMessage(util.VERBOSITY_QUIET, "failed: %s\n",
+			strings.TrimSpace(err.Error()))
+		return false, nil
+	}
 }
 
-func (r *Repo) Sync(vers *Version, force bool) (bool, bool, error) {
-	var exists bool
+// Fetches all remotes and downloads an up to date copy of `repository.yml`
+// from master.  The repo object is then populated with the contents of the
+// downladed file.  If this repo has already had its descriptor updated, this
+// function is a no-op.
+func (r *Repo) UpdateDesc() (bool, error) {
 	var err error
-	var currBranch string
-
-	exists = r.checkExists()
-
-	// Update the repo description
-	if _, updated, err := r.UpdateDesc(); updated != true || err != nil {
-		return exists, false, util.NewNewtError("Cannot update repository description.")
-	}
 
-	branchName, _, found := r.rdesc.MatchVersion(vers)
-	if found == false {
-		return exists, false, util.NewNewtError(fmt.Sprintf(
-			"Branch description for %s not found", r.Name()))
+	if r.updated {
+		return false, nil
 	}
 
-	if exists {
-		// Here assuming that if the branch was changed by the user,
-		// the user must know what he's doing...
-		// but, if -f is passed let's just save the work and re-clone
-		currBranch, err = r.currentBranch()
+	util.StatusMessage(util.VERBOSITY_VERBOSE, "[%s]:\n", r.Name())
 
-		// currBranch == HEAD means we're dettached from HEAD, so
-		// ignore and move to "new" tag
-		if err != nil {
-			return exists, false, err
-		} else if currBranch != "HEAD" && currBranch != branchName {
-			msg := "Unexpected local branch for %s: \"%s\" != \"%s\"\n"
-			if force {
-				util.StatusMessage(util.VERBOSITY_VERBOSE,
-					msg, r.rdesc.name, currBranch, branchName)
-			} else {
-				err = util.NewNewtError(
-					fmt.Sprintf(msg, r.rdesc.name, currBranch, branchName))
-				return exists, false, err
-			}
-		}
+	// Download `repository.yml`.
+	if err = r.DownloadDesc(); err != nil {
+		return false, err
+	}
 
-		// Don't try updating if on an invalid branch...
-		if currBranch == "HEAD" || currBranch == branchName {
-			util.StatusMessage(util.VERBOSITY_VERBOSE, "Updating repository...\n")
-			err = r.updateRepo(branchName)
-			if err == nil {
-				util.StatusMessage(util.VERBOSITY_VERBOSE, "Update successful!\n")
-				return exists, true, err
-			} else {
-				util.StatusMessage(util.VERBOSITY_VERBOSE, "Update failed!\n")
-				if !force {
-					return exists, false, err
-				}
-			}
-		}
+	// Read `repository.yml` and populate this repo object.
+	if err := r.Read(); err != nil {
+		return false, err
+	}
 
-		filename, err := r.saveLocalDiff()
-		if err != nil {
-			return exists, false, err
-		}
-		wd, _ := os.Getwd()
-		filename, _ = filepath.Rel(wd, filename)
+	r.updated = true
 
-		util.StatusMessage(util.VERBOSITY_DEFAULT, "Saved local diff: "+
-			"\"%s\"\n", filename)
+	return true, nil
+}
 
-		err = r.cleanupRepo(branchName)
-		if err != nil {
-			return exists, false, err
+func (r *Repo) ensureExists() error {
+	// Clone the repo if it doesn't exist.
+	if !r.CheckExists() {
+		if err := r.downloadRepo("master"); err != nil {
+			return err
 		}
+	}
 
-	} else {
-		// fresh or updating was unsuccessfull and force was given...
-		err = r.downloadRepo(branchName)
-		if err != nil {
-			return exists, false, err
-		}
+	// Make sure the repo's "origin" remote points to the correct URL.  This is
+	// necessary in case the user changed his `project.yml` file to point to a
+	// different fork.
+	if err := r.downloader.FixupOrigin(r.localPath); err != nil {
+		return err
 	}
 
-	return exists, true, nil
+	return nil
 }
 
-func (r *Repo) UpdateDesc() ([]*Repo, bool, error) {
-	var err error
+func (r *Repo) downloadFile(commit string, srcPath string) (string, error) {
+	dl := r.downloader
 
-	if r.updated {
-		return nil, false, nil
+	// Clone the repo if it doesn't exist.
+	if err := r.ensureExists(); err != nil {
+		return "", err
 	}
 
-	util.StatusMessage(util.VERBOSITY_VERBOSE, "[%s]:\n", r.Name())
-
-	if err = r.DownloadDesc(); err != nil {
-		return nil, false, err
+	cpath := r.repoFilePath()
+	if err := os.MkdirAll(cpath, REPO_DEFAULT_PERMS); err != nil {
+		return "", util.ChildNewtError(err)
 	}
 
-	_, repos, err := r.ReadDesc()
-	if err != nil {
-		fmt.Printf("ReadDesc: %v\n", err)
-		return nil, false, err
+	if err := dl.FetchFile(commit, r.localPath, srcPath, cpath); err != nil {
+		return "", util.FmtNewtError(
+			"Download of \"%s\" from repo:%s commit:%s failed: %s",
+			srcPath, r.Name(), commit, err.Error())
 	}
 
-	r.updated = true
+	util.StatusMessage(util.VERBOSITY_VERBOSE,

  (This diff was longer than 20,000 lines, and has been truncated...)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services