[Pkg-javascript-commits] [node-yarnpkg] 03/05: New upstream version 0.18.0

Paolo Greppi paolog-guest at moszumanska.debian.org
Fri Dec 16 17:15:27 UTC 2016


This is an automated email from the git hooks/post-receive script.

paolog-guest pushed a commit to branch master
in repository node-yarnpkg.

commit 1ad75a6ac6afcad810887246f2226f25e2d65f86
Author: Paolo Greppi <paolo.greppi at libpf.com>
Date:   Fri Dec 16 16:04:15 2016 +0000

    New upstream version 0.18.0
---
 .github/ISSUE_TEMPLATE.md                          |    1 +
 .gitignore                                         |    1 +
 .travis.yml                                        |    2 -
 CONTRIBUTING.md                                    |   15 +-
 README.md                                          |    6 +-
 __tests__/__mocks__/request.js                     |   13 +
 __tests__/cli/aliases.js                           |    6 +-
 __tests__/commands/_helpers.js                     |    3 +-
 __tests__/commands/add.js                          |   28 +
 __tests__/commands/cache.js                        |   32 +
 __tests__/commands/global.js                       |   61 +
 __tests__/commands/install/integration-deduping.js |  200 +++
 .../{install.js => install/integration.js}         |  396 ++---
 __tests__/commands/install/unit.js                 |   43 +
 __tests__/commands/{ls.js => list.js}              |   10 +-
 __tests__/commands/outdated.js                     |   25 +-
 __tests__/commands/pack.js                         |  182 ++
 __tests__/commands/remove.js                       |   23 +-
 __tests__/commands/run.js                          |    3 +-
 __tests__/commands/self-update.js                  |  118 --
 __tests__/constants.js                             |    8 +-
 .../.gitkeep}                                      |    0
 .../fixtures/global/add-with-prefix-env/.yarnrc    |    1 +
 .../add-with-prefix-flag/.gitkeep}                 |    0
 .../add-without-flag/.gitkeep}                     |    0
 .../install/install-file-relative/package.json     |    5 +
 .../install/install-file-relative/root-a/index.js  |    1 +
 .../install-file-relative/root-a/package.json      |    4 +
 .../install-file-relative/root-b/package.json      |    7 +
 .../install-file-relative/sub/sub-a/package.json   |    7 +
 .../install-from-authed-private-registry/.npmrc    |    2 +
 .../package.json                                   |    5 +
 .../a/d/c/package.json                             |    4 +
 .../a/d/package.json                               |    7 +
 .../a/package.json                                 |    7 +
 .../b/c/package.json                               |    4 +
 .../b/package.json                                 |    7 +
 .../package.json                                   |    4 +-
 .../package.json                                   |    2 +-
 .../install-prod-deduped-dev-dep/a/c/package.json  |    4 +
 .../install-prod-deduped-dev-dep/a/package.json    |    7 +
 .../install-prod-deduped-dev-dep/b/c/package.json  |    4 +
 .../install-prod-deduped-dev-dep/b/package.json    |    7 +
 .../install-prod-deduped-dev-dep}/package.json     |    4 +-
 .../install/install-prod-deduped-dev-dep/yarn.lock |   19 +
 .../install-production}/package.json               |    8 +-
 .../fixtures/install/install-production/yarn.lock  |   90 +
 .../.npmrc                                         |    1 +
 .../mirror-for-offline/dep-a-1.0.0.tgz             |  Bin 0 -> 234 bytes
 .../mirror-for-offline/dep-incompatible-1.0.0.tgz  |  Bin 0 -> 271 bytes
 .../package.json                                   |    5 +
 .../yarn.lock                                      |   11 +
 .../fixtures/{ls => list}/depth-flag/package.json  |    0
 .../fixtures/{ls => list}/depth-flag/yarn.lock     |    0
 .../{ls => list}/lockfile-outdated/package.json    |    0
 .../{ls => list}/lockfile-outdated/yarn.lock       |    0
 .../fixtures/{ls => list}/no-args/package.json     |    0
 __tests__/fixtures/{ls => list}/no-args/yarn.lock  |    0
 .../fixtures/{ls => list}/one-arg/package.json     |    0
 __tests__/fixtures/{ls => list}/one-arg/yarn.lock  |    0
 .../wanted-newer-than-current/package.json         |    9 +
 .../outdated/wanted-newer-than-current/yarn.lock   | 1742 ++++++++++++++++++++
 .../pack/files-exclude-dotdir/.dotdir/a.js         |    2 +
 .../fixtures/pack/files-exclude-dotdir/index.js    |    2 +
 .../pack/files-exclude-dotdir/package.json         |    7 +
 .../files-exclude-dotfile/.dotfile}                |    0
 __tests__/fixtures/pack/files-exclude-dotfile/a.js |    2 +
 __tests__/fixtures/pack/files-exclude-dotfile/b.js |    2 +
 __tests__/fixtures/pack/files-exclude-dotfile/c.js |    2 +
 .../fixtures/pack/files-exclude-dotfile/index.js   |    2 +
 .../pack/files-exclude-dotfile/package.json        |    7 +
 __tests__/fixtures/pack/files-exclude/a.js         |    2 +
 __tests__/fixtures/pack/files-exclude/b.js         |    2 +
 __tests__/fixtures/pack/files-exclude/c.js         |    2 +
 __tests__/fixtures/pack/files-exclude/index.js     |    2 +
 __tests__/fixtures/pack/files-exclude/package.json |    7 +
 .../files-include-mandatory/changelog}             |    0
 .../fixtures/pack/files-include-mandatory/index.js |    2 +
 .../files-include-mandatory/license}               |    0
 .../pack/files-include-mandatory/package.json      |    7 +
 .../files-include-mandatory/readme.md}             |    0
 __tests__/fixtures/pack/files-include/a.js         |    2 +
 __tests__/fixtures/pack/files-include/b.js         |    2 +
 __tests__/fixtures/pack/files-include/c.js         |    2 +
 __tests__/fixtures/pack/files-include/index.js     |    1 +
 __tests__/fixtures/pack/files-include/package.json |    7 +
 __tests__/fixtures/pack/minimal/index.js           |    1 +
 __tests__/fixtures/pack/minimal/package.json       |    6 +
 .../scoped-package/node_modules/.yarn-integrity    |    2 +-
 .../node_modules/@dengorbachev/bar/package.json    |   11 +
 .../node_modules/@dengorbachev/foo/package.json    |   11 +
 .../node_modules/@scoped/package/.npmignore        |   22 -
 .../node_modules/@scoped/package/.travis.yml       |    3 -
 .../node_modules/@scoped/package/Makefile          |   12 -
 .../node_modules/@scoped/package/Readme.md         |   54 -
 .../@scoped/package/examples/custom_path.js        |   14 -
 .../@scoped/package/examples/module.js             |   14 -
 .../node_modules/@scoped/package/lib/package.js    |   64 -
 .../node_modules/@scoped/package/package.json      |   21 -
 .../@scoped/package/test/index.test.js             |   42 -
 .../@scoped/package/test/nested/two/nested.test.js |   22 -
 .../node_modules/@scoped/package/test/package.json |    5 -
 .../@scoped/package/test/support/package.json      |    5 -
 .../fixtures/remove/scoped-package/package.json    |    3 +-
 __tests__/fixtures/remove/scoped-package/yarn.lock |   11 +-
 .../fixtures/request-cache/GET/localhost/.bin      |    6 -
 __tests__/package-hoister.js                       |   44 +
 appveyor.yml                                       |   11 +-
 circle.yml                                         |    2 +
 end_to_end_tests/data/start-ubuntu.sh              |    2 +-
 gulpfile.js                                        |    5 +
 package.json                                       |    9 +-
 .../win-chocolatey/tools/chocolateyinstall.ps1.in  |    6 +-
 resources/win-chocolatey/yarn.nuspec               |    4 +-
 resources/winsetup/YarnSetup.wixproj               |    4 +-
 scripts/build-chocolatey.ps1                       |    6 +-
 scripts/install-latest.sh                          |   92 +-
 src/cli/aliases.js                                 |    6 +-
 src/cli/commands/add.js                            |    9 +-
 src/cli/commands/check.js                          |   15 +-
 src/cli/commands/global.js                         |    3 +
 src/cli/commands/index.js                          |    3 +-
 src/cli/commands/install.js                        |  209 ++-
 src/cli/commands/licenses.js                       |    9 +-
 src/cli/commands/{ls.js => list.js}                |   10 +-
 src/cli/commands/outdated.js                       |   80 +-
 src/cli/commands/pack.js                           |   17 +-
 src/cli/commands/run.js                            |   12 +-
 src/cli/commands/self-update.js                    |   83 -
 src/cli/commands/upgrade-interactive.js            |   60 +-
 src/cli/commands/why.js                            |    2 +-
 src/cli/index.js                                   |   34 +-
 src/config.js                                      |   26 +-
 src/constants.js                                   |   13 +
 src/fetchers/tarball-fetcher.js                    |   20 +-
 src/lockfile/parse.js                              |   14 +-
 src/package-compatibility.js                       |    3 +-
 src/package-hoister.js                             |   44 +-
 src/package-install-scripts.js                     |    1 +
 src/package-linker.js                              |   18 +-
 src/package-reference.js                           |   49 -
 src/package-request.js                             |   63 +-
 src/package-resolver.js                            |   12 -
 src/registries/base-registry.js                    |   10 +
 src/registries/npm-registry.js                     |   10 +-
 src/registries/yarn-registry.js                    |    2 +-
 src/reporters/lang/en.js                           |   10 +-
 src/resolvers/exotics/file-resolver.js             |   40 +-
 src/resolvers/exotics/hosted-git-resolver.js       |    2 +-
 src/resolvers/exotics/tarball-resolver.js          |    2 +-
 src/resolvers/registries/npm-resolver.js           |    2 +-
 src/types.js                                       |   11 +-
 src/util/fs.js                                     |   30 +
 src/util/normalize-manifest/fix.js                 |   27 +-
 src/util/normalize-manifest/index.js               |    3 +-
 src/util/normalize-manifest/validate.js            |   11 -
 yarn.lock                                          |  183 +-
 157 files changed, 3758 insertions(+), 1132 deletions(-)

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index e0195fc..706bde4 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -6,6 +6,7 @@
 **What is the current behavior?**
 
 **If the current behavior is a bug, please provide the steps to reproduce.**
+<!-- If you can, provide a link to a public repository which contains the files necessary to reproduce this. -->
 
 **What is the expected behavior?**
 
diff --git a/.gitignore b/.gitignore
index df7b760..d6b4ddb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
 fbkpm_modules
 test/fixtures/**/.fbkpm
 /tmp/
+/__tests__/fixtures/request-cache/GET/localhost/.bin
 
 # IDE
 .idea/
diff --git a/.travis.yml b/.travis.yml
index 338b88b..4def1dc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -43,8 +43,6 @@ matrix:
       os: osx
 
 before_install:
-  # Repo for newer Node.js versions
-  - curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
   - ./scripts/bootstrap-env-ubuntu.sh
 
 install:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3b63ef7..edffe01 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -5,32 +5,35 @@ please read the [code of conduct](CODE_OF_CONDUCT.md).
 
 ## Setup
 
-> Install yarn on your system: https://yarnpkg.com/en/docs/install
+1. Install yarn on your system: https://yarnpkg.com/en/docs/install
+1. Fork the repo: https://github.com/yarnpkg/yarn
+1. Run the following commands:
 
 ```sh
-$ git clone https://github.com/yarnpkg/yarn.git
+$ git clone YOUR_YARN_REPO_URL
 $ cd yarn
 $ yarn
+$ yarn run build
 ```
 
 ## Building
 
 ```sh
-$ npm run build
+$ yarn run build
 ```
 
 ```sh
-$ npm run watch
+$ yarn run watch
 ```
 
 ## Testing
 
 ```sh
-$ npm run test
+$ yarn run test
 ```
 
 ```sh
-$ npm run lint
+$ yarn run lint
 ```
 
 ## Pull Requests
diff --git a/README.md b/README.md
index a42574b..02c9f30 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
 
 <p align="center">
   <a href="https://travis-ci.org/yarnpkg/yarn"><img alt="Travis Status" src="https://travis-ci.org/yarnpkg/yarn.svg"></a>
-  <a href="https://circleci.com/gh/yarnpkg/yarn"><img alt="Circle Status" src="https://circleci.com/gh/yarnpkg/yarn.svg?style=svg&circle-token=5f0a78473b0f440afb218bf2b82323cc6b3cb43f"></a>
+  <a href="https://circleci.com/gh/yarnpkg/yarn"><img alt="Circle Status" src="https://circleci.com/gh/yarnpkg/yarn.svg?style=shield&circle-token=5f0a78473b0f440afb218bf2b82323cc6b3cb43f"></a>
   <a href="https://ci.appveyor.com/project/kittens/yarn/branch/master"><img alt="Appveyor Status" src="https://ci.appveyor.com/api/projects/status/0xdv8chwe2kmk463?svg=true"></a>
   <a href="https://discord.gg/yarnpkg"><img alt="Discord Chat" src="https://discordapp.com/api/guilds/226791405589233664/widget.png"></a>
 </p>
@@ -36,6 +36,10 @@
 
 Read the [Installation Guide](https://yarnpkg.com/en/docs/install) on our website for detailed instructions on how to install Yarn.
 
+## Using Yarn
+
+Read the [Usage Guide](https://yarnpkg.com/en/docs/usage) on our website for detailed instructions on how to use Yarn.
+
 ## Contributing to Yarn
 
 Contributions are always welcome, no matter how large or small. Before contributing, please read the [code of conduct](CODE_OF_CONDUCT.md).
diff --git a/__tests__/__mocks__/request.js b/__tests__/__mocks__/request.js
index 7acf72f..423e084 100644
--- a/__tests__/__mocks__/request.js
+++ b/__tests__/__mocks__/request.js
@@ -15,6 +15,8 @@ const fs = require('fs');
 
 const CACHE_DIR = path.join(__dirname, '..', 'fixtures', 'request-cache');
 
+let authedRequests = [];
+
 function getRequestAlias(params: Object): string {
   const parts = url.parse(params.path);
   const pathname = cleanAlias(parts.pathname);
@@ -45,6 +47,9 @@ module.exports = function(params: Object): Request {
 
 module.exports.Request = Request;
 
+module.exports.__resetAuthedRequests = (): void => { authedRequests = []; };
+module.exports.__getAuthedRequests = (): Array<Object> => authedRequests;
+
 const httpMock = {
   request(options: Object, callback?: ?Function): ClientRequest {
     const alias = getRequestAlias(options);
@@ -55,6 +60,14 @@ const httpMock = {
     // TODO better way to do this
     const httpModule = options.uri.href.startsWith('https:') ? https : http;
 
+    // expose authorized requests to the tests for assertion
+    if (options.headers.authorization) {
+      authedRequests.push({
+        url: options.uri.href,
+        headers: options.headers,
+      });
+    }
+
     if (allowCache && fs.existsSync(loc)) {
       // cached
       options.agent = null;
diff --git a/__tests__/cli/aliases.js b/__tests__/cli/aliases.js
index aac94ca..c26734b 100644
--- a/__tests__/cli/aliases.js
+++ b/__tests__/cli/aliases.js
@@ -6,7 +6,7 @@ test('shorthands and affordances', () => {
   expect(aliases['run-script']).toBe('run');
   expect(aliases['c']).toBe('config');
   expect(aliases['i']).toBe('install');
-  expect(aliases['list']).toBe('ls');
+  expect(aliases['ls']).toBe('list');
   expect(aliases['rb']).toBe('rebuild');
   expect(aliases['runScript']).toBe('run');
   expect(aliases['t']).toBe('test');
@@ -20,8 +20,8 @@ test('shorthands and affordances', () => {
   expect(aliases['adduser']).toBe('login');
   expect(aliases['author']).toBe('owner');
   expect(aliases['isntall']).toBe('install');
-  expect(aliases['la']).toBe('ls');
-  expect(aliases['ll']).toBe('ls');
+  expect(aliases['la']).toBe('list');
+  expect(aliases['ll']).toBe('list');
   expect(aliases['r']).toBe('remove');
   expect(aliases['rm']).toBe('remove');
   expect(aliases['show']).toBe('info');
diff --git a/__tests__/commands/_helpers.js b/__tests__/commands/_helpers.js
index 44b72a5..6691d2e 100644
--- a/__tests__/commands/_helpers.js
+++ b/__tests__/commands/_helpers.js
@@ -112,8 +112,9 @@ export async function run<T, R>(
       binLinks: !!flags.binLinks,
       cwd,
       globalFolder: path.join(cwd, '.yarn-global'),
-      cacheFolder: path.join(cwd, '.yarn-cache'),
+      cacheFolder: flags.cacheFolder || path.join(cwd, '.yarn-cache'),
       linkFolder: path.join(cwd, '.yarn-link'),
+      production: flags.production,
     });
 
     const install = await factory(args, flags, config, reporter, lockfile, () => out);
diff --git a/__tests__/commands/add.js b/__tests__/commands/add.js
index 0933d3c..c9dfe6f 100644
--- a/__tests__/commands/add.js
+++ b/__tests__/commands/add.js
@@ -11,6 +11,8 @@ import {run as check} from '../../src/cli/commands/check.js';
 import * as fs from '../../src/util/fs.js';
 import assert from 'assert';
 import semver from 'semver';
+import {promisify} from '../../src/util/promise';
+import fsNode from 'fs';
 
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
 
@@ -574,3 +576,29 @@ test.concurrent('add should generate correct integrity file', (): Promise<void>
     expect(allCorrect).toBe(true);
   });
 });
+
+test.concurrent('add infers line endings from existing win32 manifest file', async (): Promise<void> => {
+  await runAdd(['is-online'], {}, 'add-infers-line-endings-from-existing-manifest-file',
+    async (config): Promise<void> => {
+      const lockfile = await promisify(fsNode.readFile)(path.join(config.cwd, 'package.json'), 'utf8');
+      assert(/\r\n/.test(lockfile));
+      assert(!/[^\r]\n/.test(lockfile));
+    },
+    async (cwd): Promise<void> => {
+      const existingLockfile = '{ "dependencies": {} }\r\n';
+      await promisify(fsNode.writeFile)(path.join(cwd, 'package.json'), existingLockfile, 'utf8');
+    });
+});
+
+test.concurrent('add infers line endings from existing unix manifest file', async (): Promise<void> => {
+  await runAdd(['is-online'], {}, 'add-infers-line-endings-from-existing-manifest-file',
+    async (config): Promise<void> => {
+      const lockfile = await promisify(fsNode.readFile)(path.join(config.cwd, 'package.json'), 'utf8');
+      assert(/[^\r]\n/.test(lockfile));
+      assert(!/\r\n/.test(lockfile));
+    },
+    async (cwd): Promise<void> => {
+      const existingLockfile = '{ "dependencies": {} }\n';
+      await promisify(fsNode.writeFile)(path.join(cwd, 'package.json'), existingLockfile, 'utf8');
+    });
+});
diff --git a/__tests__/commands/cache.js b/__tests__/commands/cache.js
new file mode 100644
index 0000000..17ee603
--- /dev/null
+++ b/__tests__/commands/cache.js
@@ -0,0 +1,32 @@
+/* @flow */
+
+import type {CLIFunctionReturn} from '../../src/types.js';
+import * as reporters from '../../src/reporters/index.js';
+import * as configCmd from '../../src/cli/commands/config.js';
+import {run as buildRun} from './_helpers.js';
+import * as fs from '../../src/util/fs.js';
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
+
+const runConfig = buildRun.bind(
+  null,
+  reporters.ConsoleReporter,
+  '',
+  (args, flags, config, reporter): CLIFunctionReturn => {
+    return configCmd.run(config, reporter, flags, args);
+  },
+);
+
+test('write cache-folder config into .yarnrc file', (): Promise<void> => {
+  return runConfig(['set', 'cache-folder', 'folder_dir_for_test'], {}, '', async (config) => {
+    const configFile = await fs.readFile(config.registries.yarn.homeConfigLoc);
+    expect(configFile).toContain('folder_dir_for_test');
+  });
+});
+
+test('cache-folder flag has higher priorities than .yarnrc file', (): Promise<void> => {
+  return runConfig(['set', 'cache-folder', 'set_config_folder_dir'], {'cacheFolder': 'flag_config_folder_dir'},
+    '', (config) => {
+      expect(config.cacheFolder).toContain('flag_config_folder_dir');
+    });
+});
diff --git a/__tests__/commands/global.js b/__tests__/commands/global.js
new file mode 100644
index 0000000..46d5f15
--- /dev/null
+++ b/__tests__/commands/global.js
@@ -0,0 +1,61 @@
+/* @flow */
+
+import type {CLIFunctionReturn} from '../../src/types.js';
+import {ConsoleReporter} from '../../src/reporters/index.js';
+import {run as buildRun} from './_helpers.js';
+import {run as global} from '../../src/cli/commands/global.js';
+import * as fs from '../../src/util/fs.js';
+import assert from 'assert';
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
+
+const os = require('os');
+const path = require('path');
+
+const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'global');
+const runGlobal = buildRun.bind(
+  null,
+  ConsoleReporter,
+  fixturesLoc,
+  (args, flags, config, reporter): CLIFunctionReturn => {
+    return global(config, reporter, flags, args);
+  },
+);
+
+function getGlobalPath(prefix, name): string {
+  if (process.platform === 'win32') {
+    return path.join(prefix, name);
+  } else {
+    return path.join(prefix, 'bin', name);
+  }
+}
+
+function getTempGlobalFolder(): string {
+  return path.join(os.tmpdir(), `yarn-global-${Math.random()}`);
+}
+
+test.concurrent('add without flag', (): Promise<void> => {
+  return runGlobal(['add', 'react-native-cli'], {}, 'add-without-flag', async (config) => {
+    assert.ok(await fs.exists(path.join(config.globalFolder, 'node_modules', 'react-native-cli')));
+    assert.ok(await fs.exists(path.join(config.globalFolder, 'node_modules', '.bin', 'react-native')));
+  });
+});
+
+test.concurrent('add with prefix flag', (): Promise<void> => {
+  const tmpGlobalFolder = getTempGlobalFolder();
+  return runGlobal(['add', 'react-native-cli'], {prefix: tmpGlobalFolder}, 'add-with-prefix-flag', async (config) => {
+    assert.ok(await fs.exists(getGlobalPath(tmpGlobalFolder, 'react-native')));
+  });
+});
+
+// don't run this test in `concurrent`, it will affect other tests
+test('add with PREFIX enviroment variable', (): Promise<void> => {
+  const tmpGlobalFolder = getTempGlobalFolder();
+  const envPrefix = process.env.PREFIX;
+  process.env.PREFIX = tmpGlobalFolder;
+  return runGlobal(['add', 'react-native-cli'], {}, 'add-with-prefix-env', async (config) => {
+    assert.ok(await fs.exists(getGlobalPath(tmpGlobalFolder, 'react-native')));
+    // restore env
+    process.env.PREFIX = envPrefix;
+  });
+});
diff --git a/__tests__/commands/install/integration-deduping.js b/__tests__/commands/install/integration-deduping.js
new file mode 100644
index 0000000..05db034
--- /dev/null
+++ b/__tests__/commands/install/integration-deduping.js
@@ -0,0 +1,200 @@
+/* @flow */
+
+import {getPackageVersion, runInstall} from '../_helpers.js';
+
+const assert = require('assert');
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 0', (): Promise<void> => {
+  // A at 2.0.1 -> B at 2.0.0
+  // B at 1.0.0
+  // should result in B at 2.0.0 not flattened
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-0', async (config) => {
+    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-a/dep-b'), '2.0.0');
+  });
+});
+
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 1', (): Promise<void> => {
+  // A at 2.0.1 -> B at 2.0.0
+  // should result in B at 2.0.0 flattened
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-1', async (config) => {
+    assert.equal(await getPackageVersion(config, 'dep-b'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.1');
+  });
+});
+
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 2', (): Promise<void> => {
+  // A at 2 -> B at 2 -> C at 2
+  //            -> D at 1
+  // B at 1 -> C at 1
+  // should become
+  // A at 2
+  // A at 2 -> B at 2
+  // A at 2 -> C at 2
+  // D at 1
+  // C at 1
+  // B at 1
+
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-2', async (config) => {
+    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-a/dep-b'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-a/dep-c'), '2.0.0');
+  });
+});
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 3', (): Promise<void> => {
+  // A at 2 -> B at 2 -> C at 2
+  //            -> D at 1
+  //     -> C at 1
+  // should become
+  // A at 2
+  // B at 2 -> C at 2
+  // C at 1
+  // D at 1
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-3', async (config) => {
+    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b/dep-c'), '2.0.0');
+  });
+});
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 4', (): Promise<void> => {
+  // A at 2 -> B at 2 -> D at 1 -> C at 2
+  //
+  //     -> C at 1
+
+  // should become
+  // A at 2
+  // D at 1 -> C at 2
+  // C at 1
+  // B at 2
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-4', async (config) => {
+    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d/dep-c'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b'), '2.0.0');
+  });
+});
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 5', (): Promise<void> => {
+  // A at 1 -> B at 1
+  // C at 1 -> D at 1 -> A at 2 -> B at 2
+
+  // should become
+
+  // A at 1
+  // B at 1
+  // C at 1
+  // D at 1 -> A at 2
+  //     -> B at 2
+
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-5', async (config) => {
+    assert.equal(await getPackageVersion(config, 'dep-a'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d/dep-a'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d/dep-b'), '2.0.0');
+
+  });
+});
+
+test.concurrent(
+  'install should dedupe dependencies avoiding conflicts 6 (jest/jest-runtime case)',
+  (): Promise<void> => {
+    // C at 1 -> D at 1 -> E at 1
+    // B at 1 -> C at 1 -> D at 1 -> E at 1
+    // D at 2
+    // E at 2
+
+    // should become
+
+    // C at 1 -> D at 1
+    //     -> E at 1
+    // B at 1
+    // D at 2
+    // E at 2
+
+    return runInstall({}, 'install-should-dedupe-avoiding-conflicts-6', async (config): Promise<void> => {
+      assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
+      assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
+      assert.equal(await getPackageVersion(config, 'dep-d'), '2.0.0');
+      assert.equal(await getPackageVersion(config, 'dep-e'), '2.0.0');
+
+      assert.equal(await getPackageVersion(config, 'dep-c/dep-d'), '1.0.0');
+      assert.equal(await getPackageVersion(config, 'dep-c/dep-e'), '1.0.0');
+    });
+  },
+);
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 7', (): Promise<void> => {
+  // A at 1 -> C at 1 -> D at 1 -> E at 1
+  // B at 1 -> C at 1 -> D at 1 -> E at 1
+  // C at 2
+  // D at 2
+  // E at 2
+
+  // should become
+
+  // A at 1 -> C at 1
+  //     -> D at 1
+  //     -> E at 1
+  // B at 1 -> C at 1
+  //     -> D at 1
+  //     -> E at 1
+  // C at 2
+  // D at 2
+  // E at 2
+
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-7', async (config) => {
+    assert.equal(await getPackageVersion(config, 'dep-a'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-c'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-d'), '2.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-e'), '2.0.0');
+
+    assert.equal(await getPackageVersion(config, 'dep-a/dep-c'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-a/dep-d'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-a/dep-e'), '1.0.0');
+
+    assert.equal(await getPackageVersion(config, 'dep-b/dep-c'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b/dep-d'), '1.0.0');
+    assert.equal(await getPackageVersion(config, 'dep-b/dep-e'), '1.0.0');
+  });
+});
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 8', (): Promise<void> => {
+  // revealed in https://github.com/yarnpkg/yarn/issues/112
+  // adapted for https://github.com/yarnpkg/yarn/issues/1158
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-8', async (config) => {
+    assert.equal(await getPackageVersion(config, 'glob'), '5.0.15');
+    assert.equal(await getPackageVersion(config, 'findup-sync/glob'), '4.3.5');
+    assert.equal(await getPackageVersion(config, 'inquirer'), '0.8.5');
+    assert.equal(await getPackageVersion(config, 'lodash'), '3.10.1');
+    assert.equal(await getPackageVersion(config, 'ast-query/lodash'), '4.15.0');
+    assert.equal(await getPackageVersion(config, 'run-async'), '0.1.0');
+  });
+});
+
+test.concurrent('install should dedupe dependencies avoiding conflicts 9', (): Promise<void> => {
+  // revealed in https://github.com/yarnpkg/yarn/issues/112
+  // adapted for https://github.com/yarnpkg/yarn/issues/1158
+  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-9', async (config) => {
+    assert.equal(await getPackageVersion(config, 'glob'), '5.0.15');
+    assert.equal(await getPackageVersion(config, 'findup-sync/glob'), '4.3.5');
+    assert.equal(await getPackageVersion(config, 'inquirer'), '0.8.5');
+    assert.equal(await getPackageVersion(config, 'lodash'), '3.10.1');
+    assert.equal(await getPackageVersion(config, 'ast-query/lodash'), '4.15.0');
+    assert.equal(await getPackageVersion(config, 'run-async'), '0.1.0');
+  });
+});
diff --git a/__tests__/commands/install.js b/__tests__/commands/install/integration.js
similarity index 66%
rename from __tests__/commands/install.js
rename to __tests__/commands/install/integration.js
index 3930eb0..e95a122 100644
--- a/__tests__/commands/install.js
+++ b/__tests__/commands/install/integration.js
@@ -1,21 +1,25 @@
 /* @flow */
 
-import {run as check} from '../../src/cli/commands/check.js';
-import * as constants from '../../src/constants.js';
-import * as reporters from '../../src/reporters/index.js';
-import {Install} from '../../src/cli/commands/install.js';
-import Lockfile from '../../src/lockfile/wrapper.js';
-import Config from '../../src/config.js';
-import * as fs from '../../src/util/fs.js';
-import assert from 'assert';
-import semver from 'semver';
-import {getPackageVersion, explodeLockfile, runInstall, createLockfile} from './_helpers.js';
+import {run as check} from '../../../src/cli/commands/check.js';
+import * as constants from '../../../src/constants.js';
+import {Install} from '../../../src/cli/commands/install.js';
+import Lockfile from '../../../src/lockfile/wrapper.js';
+import * as fs from '../../../src/util/fs.js';
+import {getPackageVersion, explodeLockfile, runInstall, createLockfile} from '../_helpers.js';
+import {promisify} from '../../../src/util/promise';
 
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
 
+const request = require('request');
+const assert = require('assert');
+const semver = require('semver');
+const fsNode = require('fs');
 const path = require('path');
+const os = require('os');
 
-const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'install');
+beforeEach(request.__resetAuthedRequests);
+// $FlowFixMe
+afterEach(request.__resetAuthedRequests);
 
 test.concurrent('properly find and save build artifacts', async () => {
   await runInstall({}, 'artifacts-finds-and-saves', async (config): Promise<void> => {
@@ -63,36 +67,85 @@ test.concurrent("removes extraneous files that aren't in module or artifacts", a
   }, create);
 });
 
-test.concurrent('integrity hash respects flat and production flags', async () => {
-  const cwd = path.join(fixturesLoc, 'noop');
-  const reporter = new reporters.NoopReporter();
-  const config = new Config(reporter);
-  await config.init({cwd});
+test.concurrent("production mode with deduped dev dep shouldn't be removed", async () => {
+  await runInstall({production: true}, 'install-prod-deduped-dev-dep', async (config) => {
+    assert.equal(
+      (await fs.readJson(path.join(config.cwd, 'node_modules', 'a', 'package.json'))).version,
+      '1.0.0',
+    );
 
-  const lockfile = new Lockfile();
+    assert.equal(
+      (await fs.readJson(path.join(config.cwd, 'node_modules', 'c', 'package.json'))).version,
+      '1.0.0',
+    );
 
-  const install = new Install({}, config, reporter, lockfile);
+    assert.ok(
+      !await fs.exists(path.join(config.cwd, 'node_modules', 'b')),
+    );
+  });
+});
 
-  const install2 = new Install({flat: true}, config, reporter, lockfile);
-  expect(install2.generateIntegrityHash('foo', [])).not.toEqual(install.generateIntegrityHash('foo', []));
+test.concurrent('hoisting should factor ignored dependencies', async () => {
+  // you should only modify this test if you know what you're doing
+  // when we calculate hoisting we need to factor in ignored dependencies in it
+  // so we get deterministic hoisting across environments, for example in production mode
+  // we should still be taking dev dependencies into consideration
 
-  const install3 = new Install({production: true}, config, reporter, lockfile);
-  expect(install3.generateIntegrityHash('foo', [])).not.toEqual(install.generateIntegrityHash('foo', []));
-  expect(install3.generateIntegrityHash('foo', [])).not.toEqual(install2.generateIntegrityHash('foo', []));
-});
+  async function checkNormal(config): Promise<void> {
+    assert.equal(
+      (await fs.readJson(path.join(config.cwd, 'node_modules', 'a', 'package.json'))).version,
+      '1.0.0',
+    );
 
-test.concurrent('flat arg is inherited from root manifest', async (): Promise<void> => {
-  const cwd = path.join(fixturesLoc, 'top-level-flat-parameter');
-  const reporter = new reporters.NoopReporter();
-  const config = new Config(reporter);
-  await config.init({cwd});
-  const install = new Install({}, config, reporter, new Lockfile());
-  return install.fetchRequestFromCwd().then(function([,, manifest]) {
-    assert.equal(manifest.flat, true);
-    assert.equal(install.flags.flat, true);
+    assert.equal(
+      (await fs.readJson(path.join(config.cwd, 'node_modules', 'd', 'package.json'))).version,
+      '1.0.0',
+    );
+
+    assert.equal(
+      (await fs.readJson(path.join(config.cwd, 'node_modules', 'd', 'node_modules', 'c', 'package.json'))).version,
+      '2.0.0',
+    );
+  }
+
+  await runInstall({}, 'install-ignored-retains-hoisting-structure', async (config) => {
+    await checkNormal(config);
+
+    assert.equal(
+      (await fs.readJson(path.join(config.cwd, 'node_modules', 'b', 'package.json'))).version,
+      '3.0.0',
+    );
+
+    assert.equal(
+      (await fs.readJson(path.join(config.cwd, 'node_modules', 'c', 'package.json'))).version,
+      '5.0.0',
+    );
+  });
+
+  await runInstall({production: true}, 'install-ignored-retains-hoisting-structure', async (config) => {
+    await checkNormal(config);
+
+    assert.ok(
+      !await fs.exists(path.join(config.cwd, 'node_modules', 'b')),
+    );
+
+    assert.ok(
+      !await fs.exists(path.join(config.cwd, 'node_modules', 'c')),
+    );
   });
 });
 
+test.concurrent('--production flag ignores dev dependencies', () => {
+  return runInstall({production: true}, 'install-production', async (config) => {
+    assert.ok(
+      !await fs.exists(path.join(config.cwd, 'node_modules', 'lodash')),
+    );
+
+    assert.ok(
+      await fs.exists(path.join(config.cwd, 'node_modules', 'react')),
+    );
+  });
+});
 
 test.concurrent("doesn't write new lockfile if existing one satisfied", (): Promise<void> => {
   return runInstall({}, 'install-dont-write-lockfile-if-satisfied', async (config): Promise<void> => {
@@ -122,6 +175,15 @@ test.concurrent('root install with optional deps', (): Promise<void> => {
   return runInstall({}, 'root-install-with-optional-dependency');
 });
 
+test.concurrent('install file: protocol with relative paths', (): Promise<void> => {
+  return runInstall({noLockfile: true}, 'install-file-relative', async (config) => {
+    assert.equal(
+      await fs.readFile(path.join(config.cwd, 'node_modules', 'root-a', 'index.js')),
+      'foobar\n',
+    );
+  });
+});
+
 test.concurrent('install file: protocol', (): Promise<void> => {
   return runInstall({noLockfile: true}, 'install-file', async (config) => {
     assert.equal(
@@ -177,194 +239,10 @@ test.concurrent('install from github', (): Promise<void> => {
   return runInstall({}, 'install-github');
 });
 
-test.concurrent('install should dedupe dependencies avoiding conflicts 0', (): Promise<void> => {
-  // A at 2.0.1 -> B at 2.0.0
-  // B at 1.0.0
-  // should result in B at 2.0.0 not flattened
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-0', async (config) => {
-    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-a/dep-b'), '2.0.0');
-  });
-});
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 1', (): Promise<void> => {
-  // A at 2.0.1 -> B at 2.0.0
-  // should result in B at 2.0.0 flattened
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-1', async (config) => {
-    assert.equal(await getPackageVersion(config, 'dep-b'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.1');
-  });
-});
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 2', (): Promise<void> => {
-  // A at 2 -> B at 2 -> C at 2
-  //            -> D at 1
-  // B at 1 -> C at 1
-  // should become
-  // A at 2
-  // A at 2 -> B at 2
-  // A at 2 -> C at 2
-  // D at 1
-  // C at 1
-  // B at 1
-
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-2', async (config) => {
-    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-a/dep-b'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-a/dep-c'), '2.0.0');
-  });
-});
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 3', (): Promise<void> => {
-  // A at 2 -> B at 2 -> C at 2
-  //            -> D at 1
-  //     -> C at 1
-  // should become
-  // A at 2
-  // B at 2 -> C at 2
-  // C at 1
-  // D at 1
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-3', async (config) => {
-    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b/dep-c'), '2.0.0');
-  });
-});
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 4', (): Promise<void> => {
-  // A at 2 -> B at 2 -> D at 1 -> C at 2
-  //
-  //     -> C at 1
-
-  // should become
-  // A at 2
-  // D at 1 -> C at 2
-  // C at 1
-  // B at 2
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-4', async (config) => {
-    assert.equal(await getPackageVersion(config, 'dep-a'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d/dep-c'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b'), '2.0.0');
-  });
-});
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 5', (): Promise<void> => {
-  // A at 1 -> B at 1
-  // C at 1 -> D at 1 -> A at 2 -> B at 2
-
-  // should become
-
-  // A at 1
-  // B at 1
-  // C at 1
-  // D at 1 -> A at 2
-  //     -> B at 2
-
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-5', async (config) => {
-    assert.equal(await getPackageVersion(config, 'dep-a'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d/dep-a'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d/dep-b'), '2.0.0');
-
-  });
-});
-
-test.concurrent(
-  'install should dedupe dependencies avoiding conflicts 6 (jest/jest-runtime case)',
-  (): Promise<void> => {
-    // C at 1 -> D at 1 -> E at 1
-    // B at 1 -> C at 1 -> D at 1 -> E at 1
-    // D at 2
-    // E at 2
-
-    // should become
-
-    // C at 1 -> D at 1
-    //     -> E at 1
-    // B at 1
-    // D at 2
-    // E at 2
-
-    return runInstall({}, 'install-should-dedupe-avoiding-conflicts-6', async (config): Promise<void> => {
-      assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
-      assert.equal(await getPackageVersion(config, 'dep-c'), '1.0.0');
-      assert.equal(await getPackageVersion(config, 'dep-d'), '2.0.0');
-      assert.equal(await getPackageVersion(config, 'dep-e'), '2.0.0');
-
-      assert.equal(await getPackageVersion(config, 'dep-c/dep-d'), '1.0.0');
-      assert.equal(await getPackageVersion(config, 'dep-c/dep-e'), '1.0.0');
-    });
-  },
-);
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 7', (): Promise<void> => {
-  // A at 1 -> C at 1 -> D at 1 -> E at 1
-  // B at 1 -> C at 1 -> D at 1 -> E at 1
-  // C at 2
-  // D at 2
-  // E at 2
-
-  // should become
-
-  // A at 1 -> C at 1
-  //     -> D at 1
-  //     -> E at 1
-  // B at 1 -> C at 1
-  //     -> D at 1
-  //     -> E at 1
-  // C at 2
-  // D at 2
-  // E at 2
-
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-7', async (config) => {
-    assert.equal(await getPackageVersion(config, 'dep-a'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-c'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-d'), '2.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-e'), '2.0.0');
-
-    assert.equal(await getPackageVersion(config, 'dep-a/dep-c'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-a/dep-d'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-a/dep-e'), '1.0.0');
-
-    assert.equal(await getPackageVersion(config, 'dep-b/dep-c'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b/dep-d'), '1.0.0');
-    assert.equal(await getPackageVersion(config, 'dep-b/dep-e'), '1.0.0');
-  });
-});
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 8', (): Promise<void> => {
-  // revealed in https://github.com/yarnpkg/yarn/issues/112
-  // adapted for https://github.com/yarnpkg/yarn/issues/1158
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-8', async (config) => {
-    assert.equal(await getPackageVersion(config, 'glob'), '5.0.15');
-    assert.equal(await getPackageVersion(config, 'findup-sync/glob'), '4.3.5');
-    assert.equal(await getPackageVersion(config, 'inquirer'), '0.8.5');
-    assert.equal(await getPackageVersion(config, 'lodash'), '3.10.1');
-    assert.equal(await getPackageVersion(config, 'ast-query/lodash'), '4.15.0');
-    assert.equal(await getPackageVersion(config, 'run-async'), '0.1.0');
-  });
-});
-
-test.concurrent('install should dedupe dependencies avoiding conflicts 9', (): Promise<void> => {
-  // revealed in https://github.com/yarnpkg/yarn/issues/112
-  // adapted for https://github.com/yarnpkg/yarn/issues/1158
-  return runInstall({}, 'install-should-dedupe-avoiding-conflicts-9', async (config) => {
-    assert.equal(await getPackageVersion(config, 'glob'), '5.0.15');
-    assert.equal(await getPackageVersion(config, 'findup-sync/glob'), '4.3.5');
-    assert.equal(await getPackageVersion(config, 'inquirer'), '0.8.5');
-    assert.equal(await getPackageVersion(config, 'lodash'), '3.10.1');
-    assert.equal(await getPackageVersion(config, 'ast-query/lodash'), '4.15.0');
-    assert.equal(await getPackageVersion(config, 'run-async'), '0.1.0');
+test.concurrent('check and install should verify integrity in the same way when flat', (): Promise<void> => {
+  return runInstall({flat: true}, 'install-should-dedupe-avoiding-conflicts-1', async (config, reporter) => {
+    // Will raise if check doesn't flatten the patterns
+    await check(config, reporter, {flat: true, integrity: true}, []);
   });
 });
 
@@ -499,17 +377,6 @@ test.concurrent('install should circumvent circular dependencies', (): Promise<v
   });
 });
 
-// fix https://github.com/yarnpkg/yarn/issues/466
-test.concurrent('install should resolve circular dependencies 2', (): Promise<void> => {
-  return runInstall({}, 'install-should-circumvent-circular-dependencies-2', async (config, reporter) => {
-    assert.equal(
-      await getPackageVersion(config, 'es5-ext'),
-      '0.10.12',
-    );
-  });
-});
-
-
 // don't run this test in `concurrent`, it will affect other tests
 test('install should respect NODE_ENV=production', (): Promise<void> => {
   const env = process.env.NODE_ENV;
@@ -521,7 +388,6 @@ test('install should respect NODE_ENV=production', (): Promise<void> => {
   });
 });
 
-
 test.concurrent('install should resolve circular dependencies 2', (): Promise<void> => {
   return runInstall({}, 'install-should-circumvent-circular-dependencies-2', async (config, reporter) => {
     assert.equal(
@@ -590,7 +456,6 @@ test.concurrent('install should respect --no-bin-links flag', (): Promise<void>
   });
 });
 
-
 test.concurrent('install should update a dependency to yarn and mirror (PR import scenario 2)', (): Promise<void> => {
   // mime-types at 2.0.0 is gets updated to mime-types at 2.1.11 via
   // a change in package.json,
@@ -738,3 +603,66 @@ test.concurrent('lockfile should be created when missing even if integrity match
     expect(await fs.exists(path.join(config.cwd, 'yarn.lock')));
   });
 });
+
+test.concurrent('install infers line endings from existing win32 lockfile', async (): Promise<void> => {
+  await runInstall({}, 'install-infers-line-endings-from-existing-lockfile',
+    async (config): Promise<void> => {
+      const lockfile = await promisify(fsNode.readFile)(path.join(config.cwd, 'yarn.lock'), 'utf8');
+      assert(/\r\n/.test(lockfile));
+      assert(!/[^\r]\n/.test(lockfile));
+    },
+    async (cwd): Promise<void> => {
+      const existingLockfile = '# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\r\n';
+      await promisify(fsNode.writeFile)(path.join(cwd, 'yarn.lock'), existingLockfile, 'utf8');
+    });
+});
+
+test.concurrent('install infers line endings from existing unix lockfile', async (): Promise<void> => {
+  await runInstall({}, 'install-infers-line-endings-from-existing-lockfile',
+    async (config): Promise<void> => {
+      const lockfile = await promisify(fsNode.readFile)(path.join(config.cwd, 'yarn.lock'), 'utf8');
+      assert(/[^\r]\n/.test(lockfile));
+      assert(!/\r\n/.test(lockfile));
+    },
+    async (cwd): Promise<void> => {
+      const existingLockfile = '# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n';
+      await promisify(fsNode.writeFile)(path.join(cwd, 'yarn.lock'), existingLockfile, 'utf8');
+    });
+});
+
+test.concurrent('install uses OS line endings when lockfile doesn\'t exist', async (): Promise<void> => {
+  await runInstall({}, 'install-infers-line-endings-from-existing-lockfile',
+    async (config): Promise<void> => {
+      const lockfile = await promisify(fsNode.readFile)(path.join(config.cwd, 'yarn.lock'), 'utf8');
+      assert(lockfile.indexOf(os.EOL) >= 0);
+    });
+});
+
+// sync test because we need to get all the requests to confirm their validity
+test('install a scoped module from authed private registry', (): Promise<void> => {
+  return runInstall({noLockfile: true}, 'install-from-authed-private-registry', async (config) => {
+    const authedRequests = request.__getAuthedRequests();
+    assert.equal(authedRequests[0].url, 'https://registry.yarnpkg.com/@types%2flodash');
+    assert.equal(authedRequests[0].headers.authorization, 'Bearer abc123');
+    assert.equal(authedRequests[1].url, 'https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.37.tgz');
+    assert.equal(authedRequests[1].headers.authorization, 'Bearer abc123');
+    assert.equal(
+      (await fs.readFile(path.join(config.cwd, 'node_modules', '@types', 'lodash', 'index.d.ts'))).split('\n')[0],
+      '// Type definitions for Lo-Dash 4.14',
+    );
+  });
+});
+
+test.concurrent('install a module with incompatible optional dependency should skip dependency',
+  (): Promise<void> => {
+    return runInstall({}, 'install-should-skip-incompatible-optional-dep', async (config) => {
+      assert.ok(!(await fs.exists(path.join(config.cwd, 'node_modules', 'dep-incompatible'))));
+    });
+  });
+
+test.concurrent('install a module with incompatible optional dependency should skip transient dependencies',
+  (): Promise<void> => {
+    return runInstall({}, 'install-should-skip-incompatible-optional-dep', async (config) => {
+      assert.ok(!(await fs.exists(path.join(config.cwd, 'node_modules', 'dep-a'))));
+    });
+  });
diff --git a/__tests__/commands/install/unit.js b/__tests__/commands/install/unit.js
new file mode 100644
index 0000000..db831b0
--- /dev/null
+++ b/__tests__/commands/install/unit.js
@@ -0,0 +1,43 @@
+/* @flow */
+
+import * as reporters from '../../../src/reporters/index.js';
+import {Install} from '../../../src/cli/commands/install.js';
+import Lockfile from '../../../src/lockfile/wrapper.js';
+import Config from '../../../src/config.js';
+
+const assert = require('assert');
+const path = require('path');
+
+const fixturesLoc = path.join(__dirname, '..', '..', 'fixtures', 'install');
+
+test.concurrent('integrity hash respects flat and production flags', async () => {
+  const cwd = path.join(fixturesLoc, 'noop');
+  const reporter = new reporters.NoopReporter();
+  const config = new Config(reporter);
+  await config.init({cwd});
+
+  const lockfile = new Lockfile();
+
+  const install = new Install({}, config, reporter, lockfile);
+
+  const install2 = new Install({flat: true}, config, reporter, lockfile);
+  expect(install2.generateIntegrityHash('foo', [])).not.toEqual(install.generateIntegrityHash('foo', []));
+
+  const config2 = new Config(reporter);
+  await config2.init({cwd, production: true});
+  const install3 = new Install({}, config2, reporter, lockfile);
+  expect(install3.generateIntegrityHash('foo', [])).not.toEqual(install.generateIntegrityHash('foo', []));
+  expect(install3.generateIntegrityHash('foo', [])).not.toEqual(install2.generateIntegrityHash('foo', []));
+});
+
+test.concurrent('flat arg is inherited from root manifest', async (): Promise<void> => {
+  const cwd = path.join(fixturesLoc, 'top-level-flat-parameter');
+  const reporter = new reporters.NoopReporter();
+  const config = new Config(reporter);
+  await config.init({cwd});
+  const install = new Install({}, config, reporter, new Lockfile());
+  return install.fetchRequestFromCwd().then(function({manifest}) {
+    assert.equal(manifest.flat, true);
+    assert.equal(install.flags.flat, true);
+  });
+});
diff --git a/__tests__/commands/ls.js b/__tests__/commands/list.js
similarity index 95%
rename from __tests__/commands/ls.js
rename to __tests__/commands/list.js
index c78f020..70d12a1 100644
--- a/__tests__/commands/ls.js
+++ b/__tests__/commands/list.js
@@ -3,7 +3,7 @@
 import type {Tree} from '../../src/reporters/types.js';
 import {BufferReporter} from '../../src/reporters/index.js';
 import {run as buildRun} from './_helpers.js';
-import {getParent, getReqDepth, run as list} from '../../src/cli/commands/ls.js';
+import {getParent, getReqDepth, run as list} from '../../src/cli/commands/list.js';
 import * as reporters from '../../src/reporters/index.js';
 
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
@@ -23,7 +23,7 @@ function makeTree(
   };
 }
 
-const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'ls');
+const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'list');
 const runList = buildRun.bind(null, BufferReporter, fixturesLoc, (args, flags, config, reporter): Promise<void> => {
   return list(config, reporter, flags, args);
 });
@@ -53,7 +53,7 @@ test.concurrent('lists everything with no args', (): Promise<void> => {
       makeTree('is-plain-obj at 1.1.0'),
     ];
 
-    rprtr.tree('ls', trees);
+    rprtr.tree('list', trees);
 
     expect(tree).toEqual(rprtr.getBuffer());
   });
@@ -68,7 +68,7 @@ test.concurrent('respects depth flag', (): Promise<void> => {
       makeTree('is-plain-obj at 1.1.0'),
     ];
 
-    rprtr.tree('ls', trees);
+    rprtr.tree('list', trees);
 
     expect(tree).toEqual(rprtr.getBuffer());
   });
@@ -82,7 +82,7 @@ test.concurrent('accepts an argument', (): Promise<void> => {
       makeTree('is-plain-obj at 1.1.0'),
     ];
 
-    rprtr.tree('ls', trees);
+    rprtr.tree('list', trees);
 
     expect(tree).toEqual(rprtr.getBuffer());
   });
diff --git a/__tests__/commands/outdated.js b/__tests__/commands/outdated.js
index b9e3de7..bae3f76 100644
--- a/__tests__/commands/outdated.js
+++ b/__tests__/commands/outdated.js
@@ -6,6 +6,7 @@ import {ConsoleReporter, JSONReporter} from '../../src/reporters/index.js';
 
 jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
 
+const semver = require('semver');
 const stream = require('stream');
 const path = require('path');
 
@@ -98,6 +99,18 @@ test.concurrent('hides when current > latest (next, beta tag)', (): Promise<void
   );
 });
 
+test.concurrent('shows when wanted > current and current > latest', (): Promise<void> => {
+  return runOutdated([], {}, 'wanted-newer-than-current',
+    (config, reporter, out): ?Promise<void> => {
+      const json: Object = JSON.parse(out);
+
+      expect(json.data.body.length).toBe(1);
+      expect(json.data.body[0][0]).toBe('webpack');
+      expect(semver.lt(json.data.body[0][1], json.data.body[0][2]));
+    },
+  );
+});
+
 test.concurrent('displays correct dependency types', (): Promise<void> => {
   return runOutdated([], {}, 'display-dependency-type',
     (config, reporter, out): ?Promise<void> => {
@@ -106,12 +119,12 @@ test.concurrent('displays correct dependency types', (): Promise<void> => {
 
       // peerDependencies aren't included in the output
       expect(json.data.body.length).toBe(3);
-      expect(body[0][0]).toBe('is-online');
-      expect(body[0][4]).toBe('optionalDependencies');
-      expect(body[1][0]).toBe('left-pad');
-      expect(body[1][4]).toBe('dependencies');
-      expect(body[2][0]).toBe('max-safe-integer');
-      expect(body[2][4]).toBe('devDependencies');
+      expect(body[0][0]).toBe('left-pad');
+      expect(body[0][4]).toBe('dependencies');
+      expect(body[1][0]).toBe('max-safe-integer');
+      expect(body[1][4]).toBe('devDependencies');
+      expect(body[2][0]).toBe('is-online');
+      expect(body[2][4]).toBe('optionalDependencies');
     },
   );
 });
diff --git a/__tests__/commands/pack.js b/__tests__/commands/pack.js
new file mode 100644
index 0000000..4e63adc
--- /dev/null
+++ b/__tests__/commands/pack.js
@@ -0,0 +1,182 @@
+/* @flow */
+import type {Reporter} from '../../src/reporters/index.js';
+
+import * as fs from '../../src/util/fs.js';
+import assert from 'assert';
+import {run as pack} from '../../src/cli/commands/pack.js';
+import * as reporters from '../../src/reporters/index.js';
+import Config from '../../src/config.js';
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
+
+const path = require('path');
+const os = require('os');
+const stream = require('stream');
+
+const zlib = require('zlib');
+const tar = require('tar');
+const fs2 = require('fs');
+
+const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'pack');
+
+export function runPack(
+  flags: Object,
+  name: string,
+  checkArchive?: ?(config: Config) => ?Promise<void>,
+): Promise<void> {
+  return run(() => {
+    return pack;
+  }, flags, path.join(fixturesLoc, name), checkArchive);
+}
+
+export async function run(
+  factory: () => (config: Config, reporter: Reporter, flags: Object, args: Array<string>) => Promise<void>,
+  flags: Object,
+  dir: string,
+  checkArchive: ?(config: Config) => ?Promise<void>,
+): Promise<void> {
+  let out = '';
+  const stdout = new stream.Writable({
+    decodeStrings: false,
+    write(data, encoding, cb) {
+      out += data;
+      cb();
+    },
+  });
+
+  const reporter = new reporters.ConsoleReporter({stdout, stderr: stdout});
+
+  const cwd = path.join(
+    os.tmpdir(),
+    `yarn-${path.basename(dir)}-${Math.random()}`,
+  );
+  await fs.unlink(cwd);
+  await fs.copy(dir, cwd, reporter);
+
+  for (const {basename, absolute} of await fs.walk(cwd)) {
+    if (basename.toLowerCase() === '.ds_store') {
+      await fs.unlink(absolute);
+    }
+  }
+
+  try {
+    const config = new Config(reporter);
+    await config.init({
+      cwd,
+      globalFolder: path.join(cwd, '.yarn/.global'),
+      cacheFolder: path.join(cwd, '.yarn'),
+      linkFolder: path.join(cwd, '.yarn/.link'),
+    });
+
+    await pack(config, reporter, flags, []);
+
+    try {
+      if (checkArchive) {
+        await checkArchive(config);
+      }
+    } finally {
+      // clean up
+      await fs.unlink(cwd);
+    }
+  } catch (err) {
+    throw new Error(`${err && err.stack} \nConsole output:\n ${out}`);
+  }
+}
+
+export async function getFilesFromArchive(source, destination): Promise<Array<string>> {
+  const unzip = new Promise((resolve, reject) => {
+    fs2.createReadStream(source)
+      .pipe(zlib.createUnzip())
+      .pipe(tar.Extract({path: destination, strip: 1}))
+      .on('end', () => {
+        resolve();
+      })
+      .on('error', (error) => {
+        reject(error);
+      });
+  });
+  await unzip;
+  const files = await fs.readdir(destination);
+  return files;
+}
+
+// skip for now because this test fails on travis
+test.concurrent.skip('pack should work with a minimal example', (): Promise<void> => {
+  return runPack({}, 'minimal', async (config): Promise<void> => {
+    const {cwd} = config;
+    const files = await getFilesFromArchive(
+      path.join(cwd, 'pack-minimal-test-v1.0.0.tgz'),
+      path.join(cwd, 'pack-minimal-test-v1.0.0'),
+    );
+
+    assert.ok(files);
+  });
+});
+
+test.concurrent('pack should inlude all files listed in the files array', (): Promise<void> => {
+  return runPack({}, 'files-include', async (config): Promise<void> => {
+    const {cwd} = config;
+    const files = await getFilesFromArchive(
+      path.join(cwd, 'files-include-v1.0.0.tgz'),
+      path.join(cwd, 'files-include-v1.0.0'),
+    );
+    const expected = ['index.js', 'a.js', 'b.js'];
+    expected.forEach((filename) => {
+      assert(files.indexOf(filename) >= 0);
+    });
+  });
+});
+
+test.concurrent('pack should include mandatory files not listed in files array if files not empty',
+(): Promise<void> => {
+  return runPack({}, 'files-include-mandatory', async (config): Promise<void> => {
+    const {cwd} = config;
+    const files = await getFilesFromArchive(
+      path.join(cwd, 'files-include-mandatory-v1.0.0.tgz'),
+      path.join(cwd, 'files-include-mandatory-v1.0.0'),
+    );
+    const expected = ['package.json', 'readme.md', 'license', 'changelog'];
+    expected.forEach((filename) => {
+      assert(files.indexOf(filename) >= 0);
+    });
+  });
+});
+
+test.concurrent('pack should exclude all other files if files array is not empty',
+(): Promise<void> => {
+  return runPack({}, 'files-exclude', async (config): Promise<void> => {
+    const {cwd} = config;
+    const files = await getFilesFromArchive(
+      path.join(cwd, 'files-exclude-v1.0.0.tgz'),
+      path.join(cwd, 'files-exclude-v1.0.0'),
+    );
+    const excluded = ['c.js'];
+    excluded.forEach((filename) => {
+      assert(!(files.indexOf(filename) >= 0));
+    });
+  });
+});
+
+test.concurrent('pack should exclude all dotflies if not in files and files not empty',
+(): Promise<void> => {
+  return runPack({}, 'files-exclude-dotfile', async (config): Promise<void> => {
+    const {cwd} = config;
+    const files = await getFilesFromArchive(
+      path.join(cwd, 'files-exclude-dotfile-v1.0.0.tgz'),
+      path.join(cwd, 'files-exclude-dotfile-v1.0.0'),
+    );
+    assert(!(files.indexOf('.dotfile') >= 0));
+  });
+});
+
+test.concurrent('pack should exclude all files in dot-directories if not in files and files not empty ',
+(): Promise<void> => {
+  return runPack({}, 'files-exclude-dotdir', async (config): Promise<void> => {
+    const {cwd} = config;
+    const files = await getFilesFromArchive(
+      path.join(cwd, 'files-exclude-dotdir-v1.0.0.tgz'),
+      path.join(cwd, 'files-exclude-dotdir-v1.0.0'),
+    );
+    assert(!(files.indexOf('a.js') >= 0));
+  });
+});
diff --git a/__tests__/commands/remove.js b/__tests__/commands/remove.js
index 416899c..01ee886 100644
--- a/__tests__/commands/remove.js
+++ b/__tests__/commands/remove.js
@@ -78,9 +78,9 @@ test.concurrent('removes multiple installed packages', (): Promise<void> => {
 });
 
 
-test.concurrent('removes scoped packages', (): Promise<void> => {
-  return runRemove(['@scoped/package'], {}, 'scoped-package', async (config): Promise<void> => {
-    assert(!await fs.exists(path.join(config.cwd, 'node_modules/@scoped')));
+test.concurrent('removes the whole scope when all scoped packages are removed', (): Promise<void> => {
+  return runRemove(['@dengorbachev/foo', '@dengorbachev/bar'], {}, 'scoped-package', async (config): Promise<void> => {
+    assert(!await fs.exists(path.join(config.cwd, 'node_modules/@dengorbachev')));
 
     assert.deepEqual(
       JSON.parse(await fs.readFile(path.join(config.cwd, 'package.json'))).dependencies,
@@ -93,6 +93,23 @@ test.concurrent('removes scoped packages', (): Promise<void> => {
   });
 });
 
+test.concurrent('removes a single scoped package', (): Promise<void> => {
+  return runRemove(['@dengorbachev/foo'], {}, 'scoped-package', async (config): Promise<void> => {
+    assert(!await fs.exists(path.join(config.cwd, 'node_modules/@dengorbachev/foo')));
+
+    assert.deepEqual(
+      JSON.parse(await fs.readFile(path.join(config.cwd, 'package.json'))).dependencies,
+      {
+        '@dengorbachev/bar': '^1.0.0',
+      },
+    );
+
+    const lockFileContent = await fs.readFile(path.join(config.cwd, 'yarn.lock'));
+    const lockFileLines = explodeLockfile(lockFileContent);
+    assert.equal(lockFileLines.length, 3);
+  });
+});
+
 test.concurrent('removes subdependencies', (): Promise<void> => {
   // A at 1 -> B at 1
   // C at 1
diff --git a/__tests__/commands/run.js b/__tests__/commands/run.js
index cd41ba2..dfc45a2 100644
--- a/__tests__/commands/run.js
+++ b/__tests__/commands/run.js
@@ -25,8 +25,7 @@ test('lists all available commands with no arguments', (): Promise<void> => {
   return runRun([], {}, 'no-args', (config, reporter): ?Promise<void> => {
     const rprtr = new reporters.BufferReporter({stdout: null, stdin: null});
     const scripts = ['build', 'prestart', 'start'];
-    // Notice `cat-names` is below twice as there is a bug with output duplication
-    const bins = ['cat-names', 'cat-names'];
+    const bins = ['cat-names'];
 
     // Emulate run output
     rprtr.error(rprtr.lang('commandNotSpecified'));
diff --git a/__tests__/commands/self-update.js b/__tests__/commands/self-update.js
deleted file mode 100644
index b6583f4..0000000
--- a/__tests__/commands/self-update.js
+++ /dev/null
@@ -1,118 +0,0 @@
-/* @flow */
-
-import roadrunner from 'roadrunner';
-import BlockingQueue from '../../src/util/blocking-queue.js';
-import * as child from '../../src/util/child.js';
-import Config from '../../src/config.js';
-import {SELF_UPDATE_DOWNLOAD_FOLDER, CACHE_FILENAME} from '../../src/constants.js';
-import * as fs from '../../src/util/fs.js';
-import {run as selfUpdate} from '../../src/cli/commands/self-update.js';
-import * as reporters from '../../src/reporters/index.js';
-
-const path = require('path');
-const stream = require('stream');
-// these tests touch "updates" folder and must be run in sequence
-const queue = new BlockingQueue('self-update-tests', 1);
-
-jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
-const updatesFolder = path.resolve(__dirname, '..', '..', SELF_UPDATE_DOWNLOAD_FOLDER);
-const updateTempFolder = path.resolve(__dirname, '..', '..', 'updates_temp');
-
-declare function beforeAll(fn: Function): void;
-declare function afterAll(fn: Function): void;
-
-beforeAll(async (done) => {
-  if (await fs.exists(updatesFolder)) {
-    await fs.rename(updatesFolder, updateTempFolder);
-  }
-  done();
-});
-
-afterAll(async (done) => {
-  if (await fs.exists(updateTempFolder)) {
-    await fs.rename(updateTempFolder, updatesFolder);
-  }
-  done();
-});
-
-let queueCounter = 0;
-function run(checks: (reporter: reporters.Reporter, config: Config) => Promise<void>): Promise<void> {
-  return queue.push(`${queueCounter++}`, async () => {
-    let out = '';
-    const stdout = new stream.Writable({
-      decodeStrings: false,
-      write(data, encoding, cb) {
-        out += data;
-        cb();
-      },
-    });
-    try {
-      const reporter = new reporters.ConsoleReporter({stdout, stderr: stdout});
-      const cwd = path.resolve(updatesFolder, '..');
-      const config = new Config(reporter);
-      await config.init({cwd});
-      roadrunner.reset(CACHE_FILENAME);
-      await checks(reporter, config);
-    } catch (err) {
-      throw new Error(`${err} \nConsole output:\n ${out}`);
-    } finally {
-      roadrunner.reset(CACHE_FILENAME);
-      await fs.unlink(updatesFolder);
-    }
-  });
-}
-
-xit('Self-update should download a release and symlink it as "current"', (): Promise<void> => {
-  return run(async (reporter, config) => {
-    await selfUpdate(config, reporter, {version: () => '0.0.1'}, []);
-
-    const currentFolder = path.resolve(updatesFolder, 'current');
-    expect(await fs.exists(currentFolder)).toBe(true);
-    const packageJson = await fs.readJson(path.resolve(updatesFolder, 'current', 'package.json'));
-
-    expect(await fs.exists(await fs.realpath(currentFolder))).toBe(true);
-    const version = await child.exec('node bin/yarn.js -V');
-
-    expect(version[0].trim()).toBe(packageJson.version);
-  });
-});
-
-
-xit('Self-update should work from self-updated location', (): Promise<void> => {
-  return run(async (reporter, config) => {
-    // mock an existing self-update
-    await child.exec('npm run build');
-    const versionFolder = path.resolve(updatesFolder, '0.2.0');
-    await fs.copy(path.resolve(updatesFolder, '..'), versionFolder, reporter);
-    await fs.symlink(versionFolder, path.resolve(updatesFolder, 'current'));
-    let packageJson = await fs.readJson(path.resolve(updatesFolder, 'current', 'package.json'));
-    packageJson.version = '0.2.0';
-    await fs.writeFile(path.resolve(updatesFolder, 'current', 'package.json'),
-      JSON.stringify(packageJson, null, 4));
-    let version = await child.exec('node bin/yarn.js -V');
-    expect(version[0].trim()).toBe('0.2.0');
-
-    // mock a to_clean folder
-    packageJson.version = '0.1.0';
-    fs.mkdirp(path.resolve(updatesFolder, '0.1.0'));
-    await fs.symlink(path.resolve(updatesFolder, '0.1.0'), path.resolve(updatesFolder, 'to_clean'));
-    await fs.writeFile(path.resolve(updatesFolder, '0.1.0', 'package.json'),
-      JSON.stringify(packageJson, null, 4));
-
-    await child.exec('node bin/yarn.js self-update');
-
-    // new version is current
-    version = await child.exec('node bin/yarn.js -V');
-    const currentFolder = path.resolve(updatesFolder, 'current');
-    expect(await fs.exists(currentFolder)).toBe(true);
-    packageJson = await fs.readJson(path.resolve(updatesFolder, 'current', 'package.json'));
-    expect(version[0].trim()).toBe(packageJson.version);
-
-    expect(await fs.exists(path.resolve(updatesFolder, '0.1.0'))).toBe(false);
-    expect(await fs.exists(path.resolve(updatesFolder, '0.2.0'))).toBe(true);
-    expect(await fs.exists(await fs.realpath(currentFolder))).toBe(true);
-
-    packageJson = await fs.readJson(path.resolve(updatesFolder, 'to_clean', 'package.json'));
-    expect(packageJson.version).toBe('0.2.0');
-  });
-}, 180000); // 3 minutes
diff --git a/__tests__/constants.js b/__tests__/constants.js
index 1a36165..1075229 100644
--- a/__tests__/constants.js
+++ b/__tests__/constants.js
@@ -1,6 +1,6 @@
 /* @flow */
 
-import {getPathKey} from '../src/constants.js';
+import {getPathKey, isRootUser} from '../src/constants.js';
 
 test('getPathKey', () => {
   expect(getPathKey('win32', {PATH: 'foobar'})).toBe('PATH');
@@ -10,3 +10,9 @@ test('getPathKey', () => {
   expect(getPathKey('linux', {})).toBe('PATH');
   expect(getPathKey('darwin', {})).toBe('PATH');
 });
+
+test('isRootUser', () => {
+  expect(isRootUser(null)).toBe(false);
+  expect(isRootUser(1001)).toBe(false);
+  expect(isRootUser(0)).toBe(true);
+});
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md b/__tests__/fixtures/add/add-infers-line-endings-from-existing-manifest-file/.gitkeep
similarity index 100%
copy from __tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md
copy to __tests__/fixtures/add/add-infers-line-endings-from-existing-manifest-file/.gitkeep
diff --git a/__tests__/fixtures/global/add-with-prefix-env/.yarnrc b/__tests__/fixtures/global/add-with-prefix-env/.yarnrc
new file mode 100644
index 0000000..3100b0f
--- /dev/null
+++ b/__tests__/fixtures/global/add-with-prefix-env/.yarnrc
@@ -0,0 +1 @@
+prefix ""
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md b/__tests__/fixtures/global/add-with-prefix-flag/.gitkeep
similarity index 100%
copy from __tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md
copy to __tests__/fixtures/global/add-with-prefix-flag/.gitkeep
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md b/__tests__/fixtures/global/add-without-flag/.gitkeep
similarity index 100%
copy from __tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md
copy to __tests__/fixtures/global/add-without-flag/.gitkeep
diff --git a/__tests__/fixtures/install/install-file-relative/package.json b/__tests__/fixtures/install/install-file-relative/package.json
new file mode 100644
index 0000000..0b3d8b0
--- /dev/null
+++ b/__tests__/fixtures/install/install-file-relative/package.json
@@ -0,0 +1,5 @@
+{
+  "dependencies": {
+    "sub-a": "file:sub/sub-a"
+  }
+}
\ No newline at end of file
diff --git a/__tests__/fixtures/install/install-file-relative/root-a/index.js b/__tests__/fixtures/install/install-file-relative/root-a/index.js
new file mode 100644
index 0000000..323fae0
--- /dev/null
+++ b/__tests__/fixtures/install/install-file-relative/root-a/index.js
@@ -0,0 +1 @@
+foobar
diff --git a/__tests__/fixtures/install/install-file-relative/root-a/package.json b/__tests__/fixtures/install/install-file-relative/root-a/package.json
new file mode 100644
index 0000000..08c9795
--- /dev/null
+++ b/__tests__/fixtures/install/install-file-relative/root-a/package.json
@@ -0,0 +1,4 @@
+{
+  "name": "root-a",
+  "version": "1.0.0"
+}
\ No newline at end of file
diff --git a/__tests__/fixtures/install/install-file-relative/root-b/package.json b/__tests__/fixtures/install/install-file-relative/root-b/package.json
new file mode 100644
index 0000000..62e3715
--- /dev/null
+++ b/__tests__/fixtures/install/install-file-relative/root-b/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "root-b",
+  "version": "1.0.0",
+  "dependencies": {
+    "root-a": "file:../root-a"
+  }
+}
\ No newline at end of file
diff --git a/__tests__/fixtures/install/install-file-relative/sub/sub-a/package.json b/__tests__/fixtures/install/install-file-relative/sub/sub-a/package.json
new file mode 100644
index 0000000..938c4be
--- /dev/null
+++ b/__tests__/fixtures/install/install-file-relative/sub/sub-a/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "sub-a",
+  "version": "1.0.0",
+  "dependencies": {
+    "root-b": "file:../../root-b"
+  }
+}
\ No newline at end of file
diff --git a/__tests__/fixtures/install/install-from-authed-private-registry/.npmrc b/__tests__/fixtures/install/install-from-authed-private-registry/.npmrc
new file mode 100644
index 0000000..c86299f
--- /dev/null
+++ b/__tests__/fixtures/install/install-from-authed-private-registry/.npmrc
@@ -0,0 +1,2 @@
+//registry.yarnpkg.com/:_authToken=abc123
+ at types:registry=https://registry.yarnpkg.com/
diff --git a/__tests__/fixtures/install/install-from-authed-private-registry/package.json b/__tests__/fixtures/install/install-from-authed-private-registry/package.json
new file mode 100644
index 0000000..a02c5b4
--- /dev/null
+++ b/__tests__/fixtures/install/install-from-authed-private-registry/package.json
@@ -0,0 +1,5 @@
+{
+  "dependencies": {
+    "@types/lodash": "4.14.37"
+  }
+}
diff --git a/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/d/c/package.json b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/d/c/package.json
new file mode 100644
index 0000000..eede1fc
--- /dev/null
+++ b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/d/c/package.json
@@ -0,0 +1,4 @@
+{
+  "name": "c",
+  "version": "2.0.0"
+}
diff --git a/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/d/package.json b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/d/package.json
new file mode 100644
index 0000000..c72e25d
--- /dev/null
+++ b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/d/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "d",
+  "version": "1.0.0",
+  "dependencies": {
+    "c": "file:c"
+  }
+}
diff --git a/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/package.json b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/package.json
new file mode 100644
index 0000000..70c2188
--- /dev/null
+++ b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/a/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "a",
+  "version": "1.0.0",
+  "dependencies": {
+    "d": "file:d"
+  }
+}
diff --git a/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/b/c/package.json b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/b/c/package.json
new file mode 100644
index 0000000..adc77bb
--- /dev/null
+++ b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/b/c/package.json
@@ -0,0 +1,4 @@
+{
+  "name": "c",
+  "version": "5.0.0"
+}
diff --git a/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/b/package.json b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/b/package.json
new file mode 100644
index 0000000..d162143
--- /dev/null
+++ b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/b/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "b",
+  "version": "3.0.0",
+  "dependencies": {
+    "c": "file:c"
+  }
+}
diff --git a/__tests__/fixtures/ls/no-args/package.json b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/package.json
similarity index 52%
copy from __tests__/fixtures/ls/no-args/package.json
copy to __tests__/fixtures/install/install-ignored-retains-hoisting-structure/package.json
index f208422..b08417d 100644
--- a/__tests__/fixtures/ls/no-args/package.json
+++ b/__tests__/fixtures/install/install-ignored-retains-hoisting-structure/package.json
@@ -1,8 +1,8 @@
 {
   "dependencies": {
-    "left-pad": "^1.1.3"
+    "a": "file:a"
   },
   "devDependencies": {
-    "sort-keys": "^1.1.2"
+    "b": "file:b"
   }
 }
diff --git a/__tests__/fixtures/ls/lockfile-outdated/package.json b/__tests__/fixtures/install/install-infers-line-endings-from-existing-lockfile/package.json
similarity index 52%
copy from __tests__/fixtures/ls/lockfile-outdated/package.json
copy to __tests__/fixtures/install/install-infers-line-endings-from-existing-lockfile/package.json
index 839f760..d55c9af 100644
--- a/__tests__/fixtures/ls/lockfile-outdated/package.json
+++ b/__tests__/fixtures/install/install-infers-line-endings-from-existing-lockfile/package.json
@@ -1,5 +1,5 @@
 {
   "dependencies": {
-    "left-pad": "^1.1.3"
+    "left-pad": "1.1.1"
   }
 }
diff --git a/__tests__/fixtures/install/install-prod-deduped-dev-dep/a/c/package.json b/__tests__/fixtures/install/install-prod-deduped-dev-dep/a/c/package.json
new file mode 100644
index 0000000..abd3384
--- /dev/null
+++ b/__tests__/fixtures/install/install-prod-deduped-dev-dep/a/c/package.json
@@ -0,0 +1,4 @@
+{
+  "name": "c",
+  "version": "1.0.0"
+}
diff --git a/__tests__/fixtures/install/install-prod-deduped-dev-dep/a/package.json b/__tests__/fixtures/install/install-prod-deduped-dev-dep/a/package.json
new file mode 100644
index 0000000..af49eed
--- /dev/null
+++ b/__tests__/fixtures/install/install-prod-deduped-dev-dep/a/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "a",
+  "version": "1.0.0",
+  "dependencies": {
+    "c": "file:c"
+  }
+}
diff --git a/__tests__/fixtures/install/install-prod-deduped-dev-dep/b/c/package.json b/__tests__/fixtures/install/install-prod-deduped-dev-dep/b/c/package.json
new file mode 100644
index 0000000..abd3384
--- /dev/null
+++ b/__tests__/fixtures/install/install-prod-deduped-dev-dep/b/c/package.json
@@ -0,0 +1,4 @@
+{
+  "name": "c",
+  "version": "1.0.0"
+}
diff --git a/__tests__/fixtures/install/install-prod-deduped-dev-dep/b/package.json b/__tests__/fixtures/install/install-prod-deduped-dev-dep/b/package.json
new file mode 100644
index 0000000..018eedc
--- /dev/null
+++ b/__tests__/fixtures/install/install-prod-deduped-dev-dep/b/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "b",
+  "version": "1.0.0",
+  "dependencies": {
+    "c": "file:c"
+  }
+}
diff --git a/__tests__/fixtures/ls/no-args/package.json b/__tests__/fixtures/install/install-prod-deduped-dev-dep/package.json
similarity index 52%
copy from __tests__/fixtures/ls/no-args/package.json
copy to __tests__/fixtures/install/install-prod-deduped-dev-dep/package.json
index f208422..b08417d 100644
--- a/__tests__/fixtures/ls/no-args/package.json
+++ b/__tests__/fixtures/install/install-prod-deduped-dev-dep/package.json
@@ -1,8 +1,8 @@
 {
   "dependencies": {
-    "left-pad": "^1.1.3"
+    "a": "file:a"
   },
   "devDependencies": {
-    "sort-keys": "^1.1.2"
+    "b": "file:b"
   }
 }
diff --git a/__tests__/fixtures/install/install-prod-deduped-dev-dep/yarn.lock b/__tests__/fixtures/install/install-prod-deduped-dev-dep/yarn.lock
new file mode 100644
index 0000000..1adb0d4
--- /dev/null
+++ b/__tests__/fixtures/install/install-prod-deduped-dev-dep/yarn.lock
@@ -0,0 +1,19 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"a at file:a":
+  version "1.0.0"
+  dependencies:
+    c "file:c"
+
+"b at file:b":
+  version "1.0.0"
+  dependencies:
+    c "file:c"
+
+"c at file:a/c":
+  version "1.0.0"
+
+"c at file:b/c":
+  version "1.0.0"
diff --git a/__tests__/fixtures/ls/no-args/package.json b/__tests__/fixtures/install/install-production/package.json
similarity index 52%
copy from __tests__/fixtures/ls/no-args/package.json
copy to __tests__/fixtures/install/install-production/package.json
index f208422..0458572 100644
--- a/__tests__/fixtures/ls/no-args/package.json
+++ b/__tests__/fixtures/install/install-production/package.json
@@ -1,8 +1,8 @@
 {
-  "dependencies": {
-    "left-pad": "^1.1.3"
-  },
   "devDependencies": {
-    "sort-keys": "^1.1.2"
+    "lodash": "^4.16.4"
+  },
+  "dependencies": {
+    "react": "^15.4.1"
   }
 }
diff --git a/__tests__/fixtures/install/install-production/yarn.lock b/__tests__/fixtures/install/install-production/yarn.lock
new file mode 100644
index 0000000..916b0c5
--- /dev/null
+++ b/__tests__/fixtures/install/install-production/yarn.lock
@@ -0,0 +1,90 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+asap@~2.0.3:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f"
+
+core-js@^1.0.0:
+  version "1.2.7"
+  resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
+
+encoding@^0.1.11:
+  version "0.1.12"
+  resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+  dependencies:
+    iconv-lite "~0.4.13"
+
+fbjs@^0.8.4:
+  version "0.8.6"
+  resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.6.tgz#7eb67d6986b2d5007a9b6e92e0e7cb6f75cad290"
+  dependencies:
+    core-js "^1.0.0"
+    isomorphic-fetch "^2.1.1"
+    loose-envify "^1.0.0"
+    object-assign "^4.1.0"
+    promise "^7.1.1"
+    ua-parser-js "^0.7.9"
+
+iconv-lite@~0.4.13:
+  version "0.4.15"
+  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
+
+is-stream@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+
+isomorphic-fetch@^2.1.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
+  dependencies:
+    node-fetch "^1.0.1"
+    whatwg-fetch ">=0.10.0"
+
+js-tokens@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5"
+
+lodash@^4.16.4:
+  version "4.17.2"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.2.tgz#34a3055babe04ce42467b607d700072c7ff6bf42"
+
+loose-envify@^1.0.0, loose-envify@^1.1.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.0.tgz#6b26248c42f6d4fa4b0d8542f78edfcde35642a8"
+  dependencies:
+    js-tokens "^2.0.0"
+
+node-fetch@^1.0.1:
+  version "1.6.3"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
+  dependencies:
+    encoding "^0.1.11"
+    is-stream "^1.0.1"
+
+object-assign@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
+
+promise@^7.1.1:
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
+  dependencies:
+    asap "~2.0.3"
+
+react@^15.4.1:
+  version "15.4.1"
+  resolved "https://registry.yarnpkg.com/react/-/react-15.4.1.tgz#498e918602677a3983cd0fd206dfe700389a0dd6"
+  dependencies:
+    fbjs "^0.8.4"
+    loose-envify "^1.1.0"
+    object-assign "^4.1.0"
+
+ua-parser-js@^0.7.9:
+  version "0.7.12"
+  resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
+
+whatwg-fetch@>=0.10.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.1.tgz#078b9461bbe91cea73cbce8bb122a05f9e92b772"
diff --git a/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/.npmrc b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/.npmrc
new file mode 100644
index 0000000..9465b97
--- /dev/null
+++ b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/.npmrc
@@ -0,0 +1 @@
+yarn-offline-mirror=./mirror-for-offline
diff --git a/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/mirror-for-offline/dep-a-1.0.0.tgz b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/mirror-for-offline/dep-a-1.0.0.tgz
new file mode 100644
index 0000000..4e82187
Binary files /dev/null and b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/mirror-for-offline/dep-a-1.0.0.tgz differ
diff --git a/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/mirror-for-offline/dep-incompatible-1.0.0.tgz b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/mirror-for-offline/dep-incompatible-1.0.0.tgz
new file mode 100644
index 0000000..545c63f
Binary files /dev/null and b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/mirror-for-offline/dep-incompatible-1.0.0.tgz differ
diff --git a/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/package.json b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/package.json
new file mode 100644
index 0000000..7de3833
--- /dev/null
+++ b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/package.json
@@ -0,0 +1,5 @@
+{
+  "optionalDependencies": {
+    "dep-incompatible": "1.0.0"
+  }
+}
diff --git a/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/yarn.lock b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/yarn.lock
new file mode 100644
index 0000000..d9c5950
--- /dev/null
+++ b/__tests__/fixtures/install/install-should-skip-incompatible-optional-dep/yarn.lock
@@ -0,0 +1,11 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+dep-incompatible at 1.0.0:
+  version "1.0.0"
+  resolved dep-incompatible-1.0.0.tgz#d06b95482893472aabc08e86e76580cfae058333
+  dependencies:
+    dep-a "1.0.0"
+
+dep-a at 1.0.0:
+  version "1.0.0"
+  resolved dep-a-1.0.0.tgz#13cb7dfcabff56d3ce39c10c1b9a0900134e615d
diff --git a/__tests__/fixtures/ls/depth-flag/package.json b/__tests__/fixtures/list/depth-flag/package.json
similarity index 100%
rename from __tests__/fixtures/ls/depth-flag/package.json
rename to __tests__/fixtures/list/depth-flag/package.json
diff --git a/__tests__/fixtures/ls/depth-flag/yarn.lock b/__tests__/fixtures/list/depth-flag/yarn.lock
similarity index 100%
rename from __tests__/fixtures/ls/depth-flag/yarn.lock
rename to __tests__/fixtures/list/depth-flag/yarn.lock
diff --git a/__tests__/fixtures/ls/lockfile-outdated/package.json b/__tests__/fixtures/list/lockfile-outdated/package.json
similarity index 100%
rename from __tests__/fixtures/ls/lockfile-outdated/package.json
rename to __tests__/fixtures/list/lockfile-outdated/package.json
diff --git a/__tests__/fixtures/ls/lockfile-outdated/yarn.lock b/__tests__/fixtures/list/lockfile-outdated/yarn.lock
similarity index 100%
rename from __tests__/fixtures/ls/lockfile-outdated/yarn.lock
rename to __tests__/fixtures/list/lockfile-outdated/yarn.lock
diff --git a/__tests__/fixtures/ls/no-args/package.json b/__tests__/fixtures/list/no-args/package.json
similarity index 100%
rename from __tests__/fixtures/ls/no-args/package.json
rename to __tests__/fixtures/list/no-args/package.json
diff --git a/__tests__/fixtures/ls/no-args/yarn.lock b/__tests__/fixtures/list/no-args/yarn.lock
similarity index 100%
rename from __tests__/fixtures/ls/no-args/yarn.lock
rename to __tests__/fixtures/list/no-args/yarn.lock
diff --git a/__tests__/fixtures/ls/one-arg/package.json b/__tests__/fixtures/list/one-arg/package.json
similarity index 100%
rename from __tests__/fixtures/ls/one-arg/package.json
rename to __tests__/fixtures/list/one-arg/package.json
diff --git a/__tests__/fixtures/ls/one-arg/yarn.lock b/__tests__/fixtures/list/one-arg/yarn.lock
similarity index 100%
rename from __tests__/fixtures/ls/one-arg/yarn.lock
rename to __tests__/fixtures/list/one-arg/yarn.lock
diff --git a/__tests__/fixtures/outdated/wanted-newer-than-current/package.json b/__tests__/fixtures/outdated/wanted-newer-than-current/package.json
new file mode 100644
index 0000000..2f9c5e5
--- /dev/null
+++ b/__tests__/fixtures/outdated/wanted-newer-than-current/package.json
@@ -0,0 +1,9 @@
+{
+  "name": "wanted-newer-than-current",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "dependencies": {
+    "webpack": "beta"
+  }
+}
diff --git a/__tests__/fixtures/outdated/wanted-newer-than-current/yarn.lock b/__tests__/fixtures/outdated/wanted-newer-than-current/yarn.lock
new file mode 100644
index 0000000..7431075
--- /dev/null
+++ b/__tests__/fixtures/outdated/wanted-newer-than-current/yarn.lock
@@ -0,0 +1,1742 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+Base64@~0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/Base64/-/Base64-0.2.1.tgz#ba3a4230708e186705065e66babdd4c35cf60028"
+
+abbrev at 1:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
+
+acorn@^3.2.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+
+ajv@^4.7.0:
+  version "4.9.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.9.0.tgz#5a358085747b134eb567d6d15e015f1d7802f45c"
+  dependencies:
+    co "^4.6.0"
+    json-stable-stringify "^1.0.1"
+
+align-text@^0.1.1, align-text@^0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
+  dependencies:
+    kind-of "^3.0.2"
+    longest "^1.0.1"
+    repeat-string "^1.5.2"
+
+ansi-regex@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107"
+
+ansi-styles@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+
+anymatch@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
+  dependencies:
+    arrify "^1.0.0"
+    micromatch "^2.1.5"
+
+aproba@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.0.4.tgz#2713680775e7614c8ba186c065d4e2e52d1072c0"
+
+are-we-there-yet@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3"
+  dependencies:
+    delegates "^1.0.0"
+    readable-stream "^2.0.0 || ^1.1.13"
+
+arr-diff@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
+  dependencies:
+    arr-flatten "^1.0.1"
+
+arr-flatten@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b"
+
+array-unique@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+
+arrify@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+
+asn1.js@^4.0.0:
+  version "4.9.0"
+  resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.0.tgz#f71a1243f3e79d46d7b07d7fbf4824ee73af054a"
+  dependencies:
+    bn.js "^4.0.0"
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+
+asn1@~0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+
+assert-plus@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
+
+assert-plus@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
+assert@^1.1.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
+  dependencies:
+    util "0.10.3"
+
+async-each@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
+
+async at 2.0.0-rc.4:
+  version "2.0.0-rc.4"
+  resolved "https://registry.yarnpkg.com/async/-/async-2.0.0-rc.4.tgz#9b7f60724c17962a973f787419e0ebc5571dbad8"
+  dependencies:
+    lodash "^4.3.0"
+
+async@^1.3.0:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+
+async@~0.2.6:
+  version "0.2.10"
+  resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
+
+asynckit@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+
+aws-sign2@~0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
+
+aws4@^1.2.1:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755"
+
+balanced-match@^0.4.1:
+  version "0.4.2"
+  resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+
+base64-js@^1.0.2:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.0.tgz#a39992d723584811982be5e290bb6a53d86700f1"
+
+bcrypt-pbkdf@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz#3ca76b85241c7170bf7d9703e7b9aa74630040d4"
+  dependencies:
+    tweetnacl "^0.14.3"
+
+big.js@^3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
+
+binary-extensions@^1.0.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.7.0.tgz#6c1610db163abfb34edfe42fa423343a1e01185d"
+
+block-stream@*:
+  version "0.0.9"
+  resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+  dependencies:
+    inherits "~2.0.0"
+
+bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
+  version "4.11.6"
+  resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
+
+boom at 2.x.x:
+  version "2.10.1"
+  resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
+  dependencies:
+    hoek "2.x.x"
+
+brace-expansion@^1.0.0:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
+  dependencies:
+    balanced-match "^0.4.1"
+    concat-map "0.0.1"
+
+braces@^1.8.2:
+  version "1.8.5"
+  resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
+  dependencies:
+    expand-range "^1.8.1"
+    preserve "^0.2.0"
+    repeat-element "^1.1.2"
+
+brorand@^1.0.1:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.0.6.tgz#4028706b915f91f7b349a2e0bf3c376039d216e5"
+
+browserify-aes@^1.0.0, browserify-aes@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.0.6.tgz#5e7725dbdef1fd5930d4ebab48567ce451c48a0a"
+  dependencies:
+    buffer-xor "^1.0.2"
+    cipher-base "^1.0.0"
+    create-hash "^1.1.0"
+    evp_bytestokey "^1.0.0"
+    inherits "^2.0.1"
+
+browserify-cipher@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a"
+  dependencies:
+    browserify-aes "^1.0.4"
+    browserify-des "^1.0.0"
+    evp_bytestokey "^1.0.0"
+
+browserify-des@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd"
+  dependencies:
+    cipher-base "^1.0.1"
+    des.js "^1.0.0"
+    inherits "^2.0.1"
+
+browserify-rsa@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
+  dependencies:
+    bn.js "^4.1.0"
+    randombytes "^2.0.1"
+
+browserify-sign@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.0.tgz#10773910c3c206d5420a46aad8694f820b85968f"
+  dependencies:
+    bn.js "^4.1.1"
+    browserify-rsa "^4.0.0"
+    create-hash "^1.1.0"
+    create-hmac "^1.1.2"
+    elliptic "^6.0.0"
+    inherits "^2.0.1"
+    parse-asn1 "^5.0.0"
+
+browserify-zlib@~0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
+  dependencies:
+    pako "~0.2.0"
+
+buffer-shims@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
+
+buffer-xor@^1.0.2:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+
+buffer@^4.3.0:
+  version "4.9.1"
+  resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
+  dependencies:
+    base64-js "^1.0.2"
+    ieee754 "^1.1.4"
+    isarray "^1.0.0"
+
+builtin-modules@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+
+camelcase@^1.0.2:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
+
+camelcase@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
+
+caseless@~0.11.0:
+  version "0.11.0"
+  resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
+
+center-align@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
+  dependencies:
+    align-text "^0.1.3"
+    lazy-cache "^1.0.3"
+
+chalk@^1.1.1:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+  dependencies:
+    ansi-styles "^2.2.1"
+    escape-string-regexp "^1.0.2"
+    has-ansi "^2.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^2.0.0"
+
+chokidar@^1.4.3:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
+  dependencies:
+    anymatch "^1.3.0"
+    async-each "^1.0.0"
+    glob-parent "^2.0.0"
+    inherits "^2.0.1"
+    is-binary-path "^1.0.0"
+    is-glob "^2.0.0"
+    path-is-absolute "^1.0.0"
+    readdirp "^2.0.0"
+  optionalDependencies:
+    fsevents "^1.0.0"
+
+cipher-base@^1.0.0, cipher-base@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07"
+  dependencies:
+    inherits "^2.0.1"
+
+cliui@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
+  dependencies:
+    center-align "^0.1.1"
+    right-align "^0.1.1"
+    wordwrap "0.0.2"
+
+cliui@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
+  dependencies:
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wrap-ansi "^2.0.0"
+
+clone@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149"
+
+co@^4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+
+code-point-at@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+
+combined-stream@^1.0.5, combined-stream@~1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
+  dependencies:
+    delayed-stream "~1.0.0"
+
+commander@^2.9.0:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
+  dependencies:
+    graceful-readlink ">= 1.0.0"
+
+concat-map at 0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+console-browserify@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
+  dependencies:
+    date-now "^0.1.4"
+
+console-control-strings@^1.0.0, console-control-strings@~1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+
+constants-browserify@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+
+core-util-is@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+
+create-ecdh@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d"
+  dependencies:
+    bn.js "^4.1.0"
+    elliptic "^6.0.0"
+
+create-hash@^1.1.0, create-hash@^1.1.1:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.2.tgz#51210062d7bb7479f6c65bb41a92208b1d61abad"
+  dependencies:
+    cipher-base "^1.0.1"
+    inherits "^2.0.1"
+    ripemd160 "^1.0.0"
+    sha.js "^2.3.6"
+
+create-hmac@^1.1.0, create-hmac@^1.1.2:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.4.tgz#d3fb4ba253eb8b3f56e39ea2fbcb8af747bd3170"
+  dependencies:
+    create-hash "^1.1.0"
+    inherits "^2.0.1"
+
+cryptiles at 2.x.x:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
+  dependencies:
+    boom "2.x.x"
+
+crypto-browserify@^3.11.0:
+  version "3.11.0"
+  resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522"
+  dependencies:
+    browserify-cipher "^1.0.0"
+    browserify-sign "^4.0.0"
+    create-ecdh "^4.0.0"
+    create-hash "^1.1.0"
+    create-hmac "^1.1.0"
+    diffie-hellman "^5.0.0"
+    inherits "^2.0.1"
+    pbkdf2 "^3.0.3"
+    public-encrypt "^4.0.0"
+    randombytes "^2.0.0"
+
+dashdash@^1.12.0:
+  version "1.14.0"
+  resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.0.tgz#29e486c5418bf0f356034a993d51686a33e84141"
+  dependencies:
+    assert-plus "^1.0.0"
+
+date-now@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
+
+debug@~2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
+  dependencies:
+    ms "0.7.1"
+
+decamelize@^1.0.0, decamelize@^1.1.1:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+
+deep-extend@~0.4.0:
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
+
+delayed-stream@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+
+delegates@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+
+des.js@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
+  dependencies:
+    inherits "^2.0.1"
+    minimalistic-assert "^1.0.0"
+
+diffie-hellman@^5.0.0:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
+  dependencies:
+    bn.js "^4.1.0"
+    miller-rabin "^4.0.0"
+    randombytes "^2.0.0"
+
+domain-browser@^1.1.1:
+  version "1.1.7"
+  resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
+
+ecc-jsbn@~0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
+  dependencies:
+    jsbn "~0.1.0"
+
+elliptic@^6.0.0:
+  version "6.3.2"
+  resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.2.tgz#e4c81e0829cf0a65ab70e998b8232723b5c1bc48"
+  dependencies:
+    bn.js "^4.4.0"
+    brorand "^1.0.1"
+    hash.js "^1.0.0"
+    inherits "^2.0.1"
+
+emojis-list@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
+
+enhanced-resolve@^2.2.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz#a115c32504b6302e85a76269d7a57ccdd962e359"
+  dependencies:
+    graceful-fs "^4.1.2"
+    memory-fs "^0.3.0"
+    object-assign "^4.0.1"
+    tapable "^0.2.3"
+
+errno@^0.1.3:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
+  dependencies:
+    prr "~0.0.0"
+
+error-ex@^1.2.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.0.tgz#e67b43f3e82c96ea3a584ffee0b9fc3325d802d9"
+  dependencies:
+    is-arrayish "^0.2.1"
+
+escape-string-regexp@^1.0.2:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+
+events@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
+
+evp_bytestokey@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz#497b66ad9fef65cd7c08a6180824ba1476b66e53"
+  dependencies:
+    create-hash "^1.1.1"
+
+expand-brackets@^0.1.4:
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
+  dependencies:
+    is-posix-bracket "^0.1.0"
+
+expand-range@^1.8.1:
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
+  dependencies:
+    fill-range "^2.1.0"
+
+extend@~3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
+
+extglob@^0.3.1:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
+  dependencies:
+    is-extglob "^1.0.0"
+
+extsprintf at 1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
+
+filename-regex@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775"
+
+fill-range@^2.1.0:
+  version "2.2.3"
+  resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
+  dependencies:
+    is-number "^2.1.0"
+    isobject "^2.0.0"
+    randomatic "^1.1.3"
+    repeat-element "^1.1.2"
+    repeat-string "^1.5.2"
+
+find-up@^1.0.0:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+  dependencies:
+    path-exists "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+for-in@^0.1.5:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8"
+
+for-own@^0.1.4:
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.4.tgz#0149b41a39088c7515f51ebe1c1386d45f935072"
+  dependencies:
+    for-in "^0.1.5"
+
+forever-agent@~0.6.1:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+
+form-data@~2.1.1:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4"
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.5"
+    mime-types "^2.1.12"
+
+fs.realpath@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+fsevents@^1.0.0:
+  version "1.0.15"
+  resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.15.tgz#fa63f590f3c2ad91275e4972a6cea545fb0aae44"
+  dependencies:
+    nan "^2.3.0"
+    node-pre-gyp "^0.6.29"
+
+fstream-ignore@~1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
+  dependencies:
+    fstream "^1.0.0"
+    inherits "2"
+    minimatch "^3.0.0"
+
+fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822"
+  dependencies:
+    graceful-fs "^4.1.2"
+    inherits "~2.0.0"
+    mkdirp ">=0.5 0"
+    rimraf "2"
+
+gauge@~2.6.0:
+  version "2.6.0"
+  resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.6.0.tgz#d35301ad18e96902b4751dcbbe40f4218b942a46"
+  dependencies:
+    aproba "^1.0.3"
+    console-control-strings "^1.0.0"
+    has-color "^0.1.7"
+    has-unicode "^2.0.0"
+    object-assign "^4.1.0"
+    signal-exit "^3.0.0"
+    string-width "^1.0.1"
+    strip-ansi "^3.0.1"
+    wide-align "^1.1.0"
+
+generate-function@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
+
+generate-object-property@^1.1.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
+  dependencies:
+    is-property "^1.0.0"
+
+get-caller-file@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
+
+getpass@^0.1.1:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6"
+  dependencies:
+    assert-plus "^1.0.0"
+
+glob-base@^0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
+  dependencies:
+    glob-parent "^2.0.0"
+    is-glob "^2.0.0"
+
+glob-parent@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
+  dependencies:
+    is-glob "^2.0.0"
+
+glob@^7.0.5:
+  version "7.1.1"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^3.0.2"
+    once "^1.3.0"
+    path-is-absolute "^1.0.0"
+
+graceful-fs@^4.1.2:
+  version "4.1.10"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.10.tgz#f2d720c22092f743228775c75e3612632501f131"
+
+"graceful-readlink@>= 1.0.0":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
+
+har-validator@~2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d"
+  dependencies:
+    chalk "^1.1.1"
+    commander "^2.9.0"
+    is-my-json-valid "^2.12.4"
+    pinkie-promise "^2.0.0"
+
+has-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+  dependencies:
+    ansi-regex "^2.0.0"
+
+has-color@^0.1.7:
+  version "0.1.7"
+  resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f"
+
+has-flag@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+
+has-unicode@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+
+hash.js@^1.0.0:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.0.3.tgz#1332ff00156c0a0ffdd8236013d07b77a0451573"
+  dependencies:
+    inherits "^2.0.1"
+
+hawk@~3.1.3:
+  version "3.1.3"
+  resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
+  dependencies:
+    boom "2.x.x"
+    cryptiles "2.x.x"
+    hoek "2.x.x"
+    sntp "1.x.x"
+
+hoek at 2.x.x:
+  version "2.16.3"
+  resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
+
+hosted-git-info@^2.1.4:
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.1.5.tgz#0ba81d90da2e25ab34a332e6ec77936e1598118b"
+
+http-browserify@^1.3.2:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/http-browserify/-/http-browserify-1.7.0.tgz#33795ade72df88acfbfd36773cefeda764735b20"
+  dependencies:
+    Base64 "~0.2.0"
+    inherits "~2.0.1"
+
+http-signature@~1.1.0:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
+  dependencies:
+    assert-plus "^0.2.0"
+    jsprim "^1.2.2"
+    sshpk "^1.7.0"
+
+https-browserify at 0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
+
+ieee754@^1.1.4:
+  version "1.1.8"
+  resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
+
+indexof at 0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
+
+inflight@^1.0.4:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+  dependencies:
+    once "^1.3.0"
+    wrappy "1"
+
+inherits at 2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+inherits at 2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+
+ini@~1.3.0:
+  version "1.3.4"
+  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
+
+interpret@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c"
+
+invert-kv@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+
+is-arrayish@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+
+is-binary-path@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
+  dependencies:
+    binary-extensions "^1.0.0"
+
+is-buffer@^1.0.2:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b"
+
+is-builtin-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+  dependencies:
+    builtin-modules "^1.0.0"
+
+is-dotfile@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d"
+
+is-equal-shallow@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
+  dependencies:
+    is-primitive "^2.0.0"
+
+is-extendable@^0.1.1:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+
+is-extglob@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
+
+is-fullwidth-code-point@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+  dependencies:
+    number-is-nan "^1.0.0"
+
+is-glob@^2.0.0, is-glob@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
+  dependencies:
+    is-extglob "^1.0.0"
+
+is-my-json-valid@^2.12.4:
+  version "2.15.0"
+  resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b"
+  dependencies:
+    generate-function "^2.0.0"
+    generate-object-property "^1.1.0"
+    jsonpointer "^4.0.0"
+    xtend "^4.0.0"
+
+is-number@^2.0.2, is-number@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
+  dependencies:
+    kind-of "^3.0.2"
+
+is-posix-bracket@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
+
+is-primitive@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
+
+is-property@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
+
+is-typedarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+
+is-utf8@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+
+isarray at 1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+
+isobject@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+  dependencies:
+    isarray "1.0.0"
+
+isstream@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+
+jodid25519@^1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
+  dependencies:
+    jsbn "~0.1.0"
+
+jsbn@~0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd"
+
+json-schema at 0.2.3:
+  version "0.2.3"
+  resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+
+json-stable-stringify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+  dependencies:
+    jsonify "~0.0.0"
+
+json-stringify-safe@~5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+
+json5@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.0.tgz#9b20715b026cbe3778fd769edccd822d8332a5b2"
+
+jsonify@~0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+
+jsonpointer@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.0.tgz#6661e161d2fc445f19f98430231343722e1fcbd5"
+
+jsprim@^1.2.2:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252"
+  dependencies:
+    extsprintf "1.0.2"
+    json-schema "0.2.3"
+    verror "1.3.6"
+
+kind-of@^3.0.2:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.0.4.tgz#7b8ecf18a4e17f8269d73b501c9f232c96887a74"
+  dependencies:
+    is-buffer "^1.0.2"
+
+lazy-cache@^1.0.3:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
+
+lcid@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
+  dependencies:
+    invert-kv "^1.0.0"
+
+load-json-file@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
+  dependencies:
+    graceful-fs "^4.1.2"
+    parse-json "^2.2.0"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+    strip-bom "^2.0.0"
+
+loader-runner@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.2.0.tgz#824c1b699c4e7a2b6501b85902d5b862bf45b3fa"
+
+loader-utils@^0.2.11:
+  version "0.2.16"
+  resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d"
+  dependencies:
+    big.js "^3.1.3"
+    emojis-list "^2.0.0"
+    json5 "^0.5.0"
+    object-assign "^4.0.1"
+
+lodash.assign@^4.0.3, lodash.assign@^4.0.6:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
+
+lodash@^4.3.0:
+  version "4.17.1"
+  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.1.tgz#e75eaf17a34730c6491d9956f4d81f3a044f01bf"
+
+longest@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+
+memory-fs@^0.3.0, memory-fs@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20"
+  dependencies:
+    errno "^0.1.3"
+    readable-stream "^2.0.1"
+
+micromatch@^2.1.5:
+  version "2.3.11"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
+  dependencies:
+    arr-diff "^2.0.0"
+    array-unique "^0.2.1"
+    braces "^1.8.2"
+    expand-brackets "^0.1.4"
+    extglob "^0.3.1"
+    filename-regex "^2.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.1"
+    kind-of "^3.0.2"
+    normalize-path "^2.0.1"
+    object.omit "^2.0.0"
+    parse-glob "^3.0.4"
+    regex-cache "^0.4.2"
+
+miller-rabin@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.0.tgz#4a62fb1d42933c05583982f4c716f6fb9e6c6d3d"
+  dependencies:
+    bn.js "^4.0.0"
+    brorand "^1.0.1"
+
+mime-db@~1.24.0:
+  version "1.24.0"
+  resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.24.0.tgz#e2d13f939f0016c6e4e9ad25a8652f126c467f0c"
+
+mime-types@^2.1.12, mime-types@~2.1.7:
+  version "2.1.12"
+  resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.12.tgz#152ba256777020dd4663f54c2e7bc26381e71729"
+  dependencies:
+    mime-db "~1.24.0"
+
+minimalistic-assert@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
+
+minimatch@^3.0.0, minimatch@^3.0.2:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
+  dependencies:
+    brace-expansion "^1.0.0"
+
+minimist at 0.0.8:
+  version "0.0.8"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+
+minimist@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+
+"mkdirp@>=0.5 0", mkdirp@~0.5.0, mkdirp@~0.5.1:
+  version "0.5.1"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+  dependencies:
+    minimist "0.0.8"
+
+ms at 0.7.1:
+  version "0.7.1"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
+
+nan@^2.3.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/nan/-/nan-2.4.0.tgz#fb3c59d45fe4effe215f0b890f8adf6eb32d2232"
+
+node-libs-browser@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-1.0.0.tgz#ff8ad6c2cfa78043bdd0091ec07f0aaa581620fc"
+  dependencies:
+    assert "^1.1.1"
+    browserify-zlib "~0.1.4"
+    buffer "^4.3.0"
+    console-browserify "^1.1.0"
+    constants-browserify "^1.0.0"
+    crypto-browserify "^3.11.0"
+    domain-browser "^1.1.1"
+    events "^1.0.0"
+    http-browserify "^1.3.2"
+    https-browserify "0.0.1"
+    os-browserify "~0.2.0"
+    path-browserify "0.0.0"
+    process "~0.11.0"
+    punycode "^1.2.4"
+    querystring-es3 "~0.2.0"
+    readable-stream "^2.0.5"
+    stream-browserify "^2.0.1"
+    string_decoder "~0.10.25"
+    timers-browserify "^1.0.1"
+    tty-browserify "0.0.0"
+    url "~0.11.0"
+    util "~0.10.3"
+    vm-browserify "0.0.4"
+
+node-pre-gyp@^0.6.29:
+  version "0.6.31"
+  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.31.tgz#d8a00ddaa301a940615dbcc8caad4024d58f6017"
+  dependencies:
+    mkdirp "~0.5.1"
+    nopt "~3.0.6"
+    npmlog "^4.0.0"
+    rc "~1.1.6"
+    request "^2.75.0"
+    rimraf "~2.5.4"
+    semver "~5.3.0"
+    tar "~2.2.1"
+    tar-pack "~3.3.0"
+
+node-uuid@~1.4.7:
+  version "1.4.7"
+  resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.7.tgz#6da5a17668c4b3dd59623bda11cf7fa4c1f60a6f"
+
+nopt@~3.0.6:
+  version "3.0.6"
+  resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+  dependencies:
+    abbrev "1"
+
+normalize-package-data@^2.3.2:
+  version "2.3.5"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.5.tgz#8d924f142960e1777e7ffe170543631cc7cb02df"
+  dependencies:
+    hosted-git-info "^2.1.4"
+    is-builtin-module "^1.0.0"
+    semver "2 || 3 || 4 || 5"
+    validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a"
+
+npmlog@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.0.tgz#e094503961c70c1774eb76692080e8d578a9f88f"
+  dependencies:
+    are-we-there-yet "~1.1.2"
+    console-control-strings "~1.1.0"
+    gauge "~2.6.0"
+    set-blocking "~2.0.0"
+
+number-is-nan@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+
+oauth-sign@~0.8.1:
+  version "0.8.2"
+  resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
+
+object-assign@^4.0.1, object-assign@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
+
+object.omit@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
+  dependencies:
+    for-own "^0.1.4"
+    is-extendable "^0.1.1"
+
+once@^1.3.0, once@~1.3.3:
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
+  dependencies:
+    wrappy "1"
+
+os-browserify@~0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f"
+
+os-locale@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
+  dependencies:
+    lcid "^1.0.0"
+
+pako@~0.2.0:
+  version "0.2.9"
+  resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
+
+parse-asn1@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.0.0.tgz#35060f6d5015d37628c770f4e091a0b5a278bc23"
+  dependencies:
+    asn1.js "^4.0.0"
+    browserify-aes "^1.0.0"
+    create-hash "^1.1.0"
+    evp_bytestokey "^1.0.0"
+    pbkdf2 "^3.0.3"
+
+parse-glob@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
+  dependencies:
+    glob-base "^0.3.0"
+    is-dotfile "^1.0.0"
+    is-extglob "^1.0.0"
+    is-glob "^2.0.0"
+
+parse-json@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+  dependencies:
+    error-ex "^1.2.0"
+
+path-browserify at 0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
+
+path-exists@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+  dependencies:
+    pinkie-promise "^2.0.0"
+
+path-is-absolute@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+
+path-type@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
+  dependencies:
+    graceful-fs "^4.1.2"
+    pify "^2.0.0"
+    pinkie-promise "^2.0.0"
+
+pbkdf2@^3.0.3:
+  version "3.0.9"
+  resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.9.tgz#f2c4b25a600058b3c3773c086c37dbbee1ffe693"
+  dependencies:
+    create-hmac "^1.1.2"
+
+pify@^2.0.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+
+pinkie-promise@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+  dependencies:
+    pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+  version "2.0.4"
+  resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+
+preserve@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+
+process-nextick-args@~1.0.6:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
+
+process@~0.11.0:
+  version "0.11.9"
+  resolved "https://registry.yarnpkg.com/process/-/process-0.11.9.tgz#7bd5ad21aa6253e7da8682264f1e11d11c0318c1"
+
+prr@~0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
+
+public-encrypt@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6"
+  dependencies:
+    bn.js "^4.1.0"
+    browserify-rsa "^4.0.0"
+    create-hash "^1.1.0"
+    parse-asn1 "^5.0.0"
+    randombytes "^2.0.1"
+
+punycode at 1.3.2:
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+
+punycode@^1.2.4, punycode@^1.4.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+
+qs@~6.3.0:
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442"
+
+querystring-es3@~0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+
+querystring at 0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+
+randomatic@^1.1.3:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.5.tgz#5e9ef5f2d573c67bd2b8124ae90b5156e457840b"
+  dependencies:
+    is-number "^2.0.2"
+    kind-of "^3.0.2"
+
+randombytes@^2.0.0, randombytes@^2.0.1:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.3.tgz#674c99760901c3c4112771a31e521dc349cc09ec"
+
+rc@~1.1.6:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9"
+  dependencies:
+    deep-extend "~0.4.0"
+    ini "~1.3.0"
+    minimist "^1.2.0"
+    strip-json-comments "~1.0.4"
+
+read-pkg-up@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
+  dependencies:
+    find-up "^1.0.0"
+    read-pkg "^1.0.0"
+
+read-pkg@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+  dependencies:
+    load-json-file "^1.0.0"
+    normalize-package-data "^2.3.2"
+    path-type "^1.0.0"
+
+"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
+  dependencies:
+    buffer-shims "^1.0.0"
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "~1.0.0"
+    process-nextick-args "~1.0.6"
+    string_decoder "~0.10.x"
+    util-deprecate "~1.0.1"
+
+readable-stream@~2.1.4:
+  version "2.1.5"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0"
+  dependencies:
+    buffer-shims "^1.0.0"
+    core-util-is "~1.0.0"
+    inherits "~2.0.1"
+    isarray "~1.0.0"
+    process-nextick-args "~1.0.6"
+    string_decoder "~0.10.x"
+    util-deprecate "~1.0.1"
+
+readdirp@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
+  dependencies:
+    graceful-fs "^4.1.2"
+    minimatch "^3.0.2"
+    readable-stream "^2.0.2"
+    set-immediate-shim "^1.0.1"
+
+regex-cache@^0.4.2:
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145"
+  dependencies:
+    is-equal-shallow "^0.1.3"
+    is-primitive "^2.0.0"
+
+repeat-element@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
+
+repeat-string@^1.5.2:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
+
+request@^2.75.0:
+  version "2.78.0"
+  resolved "https://registry.yarnpkg.com/request/-/request-2.78.0.tgz#e1c8dec346e1c81923b24acdb337f11decabe9cc"
+  dependencies:
+    aws-sign2 "~0.6.0"
+    aws4 "^1.2.1"
+    caseless "~0.11.0"
+    combined-stream "~1.0.5"
+    extend "~3.0.0"
+    forever-agent "~0.6.1"
+    form-data "~2.1.1"
+    har-validator "~2.0.6"
+    hawk "~3.1.3"
+    http-signature "~1.1.0"
+    is-typedarray "~1.0.0"
+    isstream "~0.1.2"
+    json-stringify-safe "~5.0.1"
+    mime-types "~2.1.7"
+    node-uuid "~1.4.7"
+    oauth-sign "~0.8.1"
+    qs "~6.3.0"
+    stringstream "~0.0.4"
+    tough-cookie "~2.3.0"
+    tunnel-agent "~0.4.1"
+
+require-directory@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+
+require-main-filename@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+
+right-align@^0.1.1:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
+  dependencies:
+    align-text "^0.1.1"
+
+rimraf at 2, rimraf@~2.5.1, rimraf@~2.5.4:
+  version "2.5.4"
+  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
+  dependencies:
+    glob "^7.0.5"
+
+ripemd160@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-1.0.1.tgz#93a4bbd4942bc574b69a8fa57c71de10ecca7d6e"
+
+"semver at 2 || 3 || 4 || 5", semver@~5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+
+set-immediate-shim@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+
+sha.js@^2.3.6:
+  version "2.4.8"
+  resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.8.tgz#37068c2c476b6baf402d14a49c67f597921f634f"
+  dependencies:
+    inherits "^2.0.1"
+
+signal-exit@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.1.tgz#5a4c884992b63a7acd9badb7894c3ee9cfccad81"
+
+sntp at 1.x.x:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
+  dependencies:
+    hoek "2.x.x"
+
+source-list-map@~0.1.0:
+  version "0.1.6"
+  resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.6.tgz#e1e6f94f0b40c4d28dcf8f5b8766e0e45636877f"
+
+source-map@^0.5.3, source-map@~0.5.1, source-map@~0.5.3:
+  version "0.5.6"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
+
+spdx-correct@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
+  dependencies:
+    spdx-license-ids "^1.0.2"
+
+spdx-expression-parse@~1.0.0:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
+
+spdx-license-ids@^1.0.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
+
+sshpk@^1.7.0:
+  version "1.10.1"
+  resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.1.tgz#30e1a5d329244974a1af61511339d595af6638b0"
+  dependencies:
+    asn1 "~0.2.3"
+    assert-plus "^1.0.0"
+    dashdash "^1.12.0"
+    getpass "^0.1.1"
+  optionalDependencies:
+    bcrypt-pbkdf "^1.0.0"
+    ecc-jsbn "~0.1.1"
+    jodid25519 "^1.0.0"
+    jsbn "~0.1.0"
+    tweetnacl "~0.14.0"
+
+stream-browserify@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
+  dependencies:
+    inherits "~2.0.1"
+    readable-stream "^2.0.2"
+
+string-width@^1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+  dependencies:
+    code-point-at "^1.0.0"
+    is-fullwidth-code-point "^1.0.0"
+    strip-ansi "^3.0.0"
+
+string_decoder@~0.10.25, string_decoder@~0.10.x:
+  version "0.10.31"
+  resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+
+stringstream@~0.0.4:
+  version "0.0.5"
+  resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
+
+strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  dependencies:
+    ansi-regex "^2.0.0"
+
+strip-bom@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
+  dependencies:
+    is-utf8 "^0.2.0"
+
+strip-json-comments@~1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
+
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+
+supports-color@^3.1.0:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
+  dependencies:
+    has-flag "^1.0.0"
+
+tapable@^0.2.3, tapable@~0.2.3:
+  version "0.2.4"
+  resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.4.tgz#a7814605089d4ba896c33c7e3566e13dcd194aa5"
+
+tar-pack@~3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae"
+  dependencies:
+    debug "~2.2.0"
+    fstream "~1.0.10"
+    fstream-ignore "~1.0.5"
+    once "~1.3.3"
+    readable-stream "~2.1.4"
+    rimraf "~2.5.1"
+    tar "~2.2.1"
+    uid-number "~0.0.6"
+
+tar@~2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
+  dependencies:
+    block-stream "*"
+    fstream "^1.0.2"
+    inherits "2"
+
+timers-browserify@^1.0.1:
+  version "1.4.2"
+  resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d"
+  dependencies:
+    process "~0.11.0"
+
+tough-cookie@~2.3.0:
+  version "2.3.2"
+  resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
+  dependencies:
+    punycode "^1.4.1"
+
+tty-browserify at 0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
+
+tunnel-agent@~0.4.1:
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+  version "0.14.3"
+  resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.3.tgz#3da382f670f25ded78d7b3d1792119bca0b7132d"
+
+uglify-js@~2.7.3:
+  version "2.7.4"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.4.tgz#a295a0de12b6a650c031c40deb0dc40b14568bd2"
+  dependencies:
+    async "~0.2.6"
+    source-map "~0.5.1"
+    uglify-to-browserify "~1.0.0"
+    yargs "~3.10.0"
+
+uglify-to-browserify@~1.0.0:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+
+uid-number@~0.0.6:
+  version "0.0.6"
+  resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+
+url@~0.11.0:
+  version "0.11.0"
+  resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+  dependencies:
+    punycode "1.3.2"
+    querystring "0.2.0"
+
+util-deprecate@~1.0.1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+
+util at 0.10.3, util@~0.10.3:
+  version "0.10.3"
+  resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+  dependencies:
+    inherits "2.0.1"
+
+validate-npm-package-license@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
+  dependencies:
+    spdx-correct "~1.0.0"
+    spdx-expression-parse "~1.0.0"
+
+verror at 1.3.6:
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
+  dependencies:
+    extsprintf "1.0.2"
+
+vm-browserify at 0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
+  dependencies:
+    indexof "0.0.1"
+
+watchpack@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.1.0.tgz#42d44627464a2fadffc9308c0f7562cfde795f24"
+  dependencies:
+    async "2.0.0-rc.4"
+    chokidar "^1.4.3"
+    graceful-fs "^4.1.2"
+
+webpack-sources@^0.1.0:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.3.tgz#15ce2fb79d0a1da727444ba7c757bf164294f310"
+  dependencies:
+    source-list-map "~0.1.0"
+    source-map "~0.5.3"
+
+webpack at beta:
+  version "2.1.0-beta.25"
+  resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.1.0-beta.25.tgz#c35ff4da4ee70344a2f14c35258d95412709e9ed"
+  dependencies:
+    acorn "^3.2.0"
+    ajv "^4.7.0"
+    async "^1.3.0"
+    clone "^1.0.2"
+    enhanced-resolve "^2.2.0"
+    interpret "^1.0.0"
+    loader-runner "^2.2.0"
+    loader-utils "^0.2.11"
+    memory-fs "~0.3.0"
+    mkdirp "~0.5.0"
+    node-libs-browser "^1.0.0"
+    object-assign "^4.0.1"
+    source-map "^0.5.3"
+    supports-color "^3.1.0"
+    tapable "~0.2.3"
+    uglify-js "~2.7.3"
+    watchpack "^1.0.0"
+    webpack-sources "^0.1.0"
+    yargs "^4.7.1"
+
+which-module@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
+
+wide-align@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad"
+  dependencies:
+    string-width "^1.0.1"
+
+window-size at 0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
+
+window-size@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
+
+wordwrap at 0.0.2:
+  version "0.0.2"
+  resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
+
+wrap-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.0.0.tgz#7d30f8f873f9a5bbc3a64dabc8d177e071ae426f"
+  dependencies:
+    string-width "^1.0.1"
+
+wrappy at 1:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+xtend@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+
+y18n@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+
+yargs-parser@^2.4.1:
+  version "2.4.1"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4"
+  dependencies:
+    camelcase "^3.0.0"
+    lodash.assign "^4.0.6"
+
+yargs@^4.7.1:
+  version "4.8.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"
+  dependencies:
+    cliui "^3.2.0"
+    decamelize "^1.1.1"
+    get-caller-file "^1.0.1"
+    lodash.assign "^4.0.3"
+    os-locale "^1.4.0"
+    read-pkg-up "^1.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^1.0.1"
+    which-module "^1.0.0"
+    window-size "^0.2.0"
+    y18n "^3.2.1"
+    yargs-parser "^2.4.1"
+
+yargs@~3.10.0:
+  version "3.10.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
+  dependencies:
+    camelcase "^1.0.2"
+    cliui "^2.1.0"
+    decamelize "^1.0.0"
+    window-size "0.1.0"
diff --git a/__tests__/fixtures/pack/files-exclude-dotdir/.dotdir/a.js b/__tests__/fixtures/pack/files-exclude-dotdir/.dotdir/a.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotdir/.dotdir/a.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude-dotdir/index.js b/__tests__/fixtures/pack/files-exclude-dotdir/index.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotdir/index.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude-dotdir/package.json b/__tests__/fixtures/pack/files-exclude-dotdir/package.json
new file mode 100644
index 0000000..a73c585
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotdir/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "files-exclude-dotdir",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "files": ["index.js", "a.js", "b.js"]
+}
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md b/__tests__/fixtures/pack/files-exclude-dotfile/.dotfile
similarity index 100%
copy from __tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md
copy to __tests__/fixtures/pack/files-exclude-dotfile/.dotfile
diff --git a/__tests__/fixtures/pack/files-exclude-dotfile/a.js b/__tests__/fixtures/pack/files-exclude-dotfile/a.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotfile/a.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude-dotfile/b.js b/__tests__/fixtures/pack/files-exclude-dotfile/b.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotfile/b.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude-dotfile/c.js b/__tests__/fixtures/pack/files-exclude-dotfile/c.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotfile/c.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude-dotfile/index.js b/__tests__/fixtures/pack/files-exclude-dotfile/index.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotfile/index.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude-dotfile/package.json b/__tests__/fixtures/pack/files-exclude-dotfile/package.json
new file mode 100644
index 0000000..a0292be
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude-dotfile/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "files-exclude-dotfile",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "files": ["index.js", "a.js", "b.js"]
+}
diff --git a/__tests__/fixtures/pack/files-exclude/a.js b/__tests__/fixtures/pack/files-exclude/a.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude/a.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude/b.js b/__tests__/fixtures/pack/files-exclude/b.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude/b.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude/c.js b/__tests__/fixtures/pack/files-exclude/c.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude/c.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude/index.js b/__tests__/fixtures/pack/files-exclude/index.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude/index.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-exclude/package.json b/__tests__/fixtures/pack/files-exclude/package.json
new file mode 100644
index 0000000..ca88821
--- /dev/null
+++ b/__tests__/fixtures/pack/files-exclude/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "files-exclude",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "files": ["index.js", "a.js", "b.js"]
+}
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md b/__tests__/fixtures/pack/files-include-mandatory/changelog
similarity index 100%
copy from __tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md
copy to __tests__/fixtures/pack/files-include-mandatory/changelog
diff --git a/__tests__/fixtures/pack/files-include-mandatory/index.js b/__tests__/fixtures/pack/files-include-mandatory/index.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-include-mandatory/index.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md b/__tests__/fixtures/pack/files-include-mandatory/license
similarity index 100%
copy from __tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md
copy to __tests__/fixtures/pack/files-include-mandatory/license
diff --git a/__tests__/fixtures/pack/files-include-mandatory/package.json b/__tests__/fixtures/pack/files-include-mandatory/package.json
new file mode 100644
index 0000000..8747fee
--- /dev/null
+++ b/__tests__/fixtures/pack/files-include-mandatory/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "files-include-mandatory",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "files": ["index.js", "a.js", "b.js"]
+}
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md b/__tests__/fixtures/pack/files-include-mandatory/readme.md
similarity index 100%
rename from __tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/History.md
rename to __tests__/fixtures/pack/files-include-mandatory/readme.md
diff --git a/__tests__/fixtures/pack/files-include/a.js b/__tests__/fixtures/pack/files-include/a.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-include/a.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-include/b.js b/__tests__/fixtures/pack/files-include/b.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-include/b.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-include/c.js b/__tests__/fixtures/pack/files-include/c.js
new file mode 100644
index 0000000..66a7302
--- /dev/null
+++ b/__tests__/fixtures/pack/files-include/c.js
@@ -0,0 +1,2 @@
+/* @flow */
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-include/index.js b/__tests__/fixtures/pack/files-include/index.js
new file mode 100644
index 0000000..6be0237
--- /dev/null
+++ b/__tests__/fixtures/pack/files-include/index.js
@@ -0,0 +1 @@
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/files-include/package.json b/__tests__/fixtures/pack/files-include/package.json
new file mode 100644
index 0000000..917dfeb
--- /dev/null
+++ b/__tests__/fixtures/pack/files-include/package.json
@@ -0,0 +1,7 @@
+{
+  "name": "files-include",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT",
+  "files": ["index.js", "a.js", "b.js"]
+}
diff --git a/__tests__/fixtures/pack/minimal/index.js b/__tests__/fixtures/pack/minimal/index.js
new file mode 100644
index 0000000..6be0237
--- /dev/null
+++ b/__tests__/fixtures/pack/minimal/index.js
@@ -0,0 +1 @@
+console.log('hello world');
diff --git a/__tests__/fixtures/pack/minimal/package.json b/__tests__/fixtures/pack/minimal/package.json
new file mode 100644
index 0000000..ea643d7
--- /dev/null
+++ b/__tests__/fixtures/pack/minimal/package.json
@@ -0,0 +1,6 @@
+{
+  "name": "pack-minimal-test",
+  "version": "1.0.0",
+  "main": "index.js",
+  "license": "MIT"
+}
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/.yarn-integrity b/__tests__/fixtures/remove/scoped-package/node_modules/.yarn-integrity
index 531c001..ff230ab 100644
--- a/__tests__/fixtures/remove/scoped-package/node_modules/.yarn-integrity
+++ b/__tests__/fixtures/remove/scoped-package/node_modules/.yarn-integrity
@@ -1 +1 @@
-474bcc9efc4057590d34522e69b2321efbd7eafcd557a56c66b08d8ad6334cfd
\ No newline at end of file
+638fae19c136efd6d59f7519ecd8e02255b254d9c68d27af5198305d115a8533
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@dengorbachev/bar/package.json b/__tests__/fixtures/remove/scoped-package/node_modules/@dengorbachev/bar/package.json
new file mode 100644
index 0000000..2449e98
--- /dev/null
+++ b/__tests__/fixtures/remove/scoped-package/node_modules/@dengorbachev/bar/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "@dengorbachev/bar",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@dengorbachev/foo/package.json b/__tests__/fixtures/remove/scoped-package/node_modules/@dengorbachev/foo/package.json
new file mode 100644
index 0000000..9f4ceed
--- /dev/null
+++ b/__tests__/fixtures/remove/scoped-package/node_modules/@dengorbachev/foo/package.json
@@ -0,0 +1,11 @@
+{
+  "name": "@dengorbachev/foo",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC"
+}
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/.npmignore b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/.npmignore
deleted file mode 100644
index 3b3a32f..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/.npmignore
+++ /dev/null
@@ -1,22 +0,0 @@
-tmp
-node_modules
-*._
-*.tmp
-.monitor
-*.diff
-*.err
-*.orig
-*.log
-*.rej
-*.swo
-*.swp
-*.vi
-*~
-.DS_Store
-Thumbs.db
-.cache
-.project
-.settings
-.tmproj
-*.esproj
-nbproject
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/.travis.yml b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/.travis.yml
deleted file mode 100644
index b8e1f17..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/.travis.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-language: node_js
-node_js:
-  - 0.6
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/Makefile b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/Makefile
deleted file mode 100644
index 277485c..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-TESTS = $(shell find test -iname \*.test.js)
-
-test:
-	@NODE_ENV=test ./node_modules/.bin/mocha \
-	--require should \
-	--reporter spec \
-	$(TESTS)
-
-clean:
-	rm -f examples/tmp/*
-
-.PHONY: test clean
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/Readme.md b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/Readme.md
deleted file mode 100644
index c531965..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/Readme.md
+++ /dev/null
@@ -1,54 +0,0 @@
-[![Build Status](https://secure.travis-ci.org/vesln/package.png)](http://travis-ci.org/vesln/package)
-
-# package - Easy package.json exports.
-
-## Intro
-
-This module provides an easy and simple way to export package.json data.
-
-## Installation
-
-	$ npm install package
-
-## Usage
-
-	var package = require('package')(module); // contains package.json data.
-	var yourAwesomeModule = {};
-	yourAwesomeModule.version = package.version;
-
-## Tests
-
-	$ make test
-
-## Contribution
-
-Bug fixes and features are welcomed.
-
-## Other similar modules
-
-- pkginfo (https://github.com/indexzero/node-pkginfo) by indexzero.
-- JSON.parse + fs.readFile
-
-## License
-
-MIT License
-
-Copyright (C) 2012 Veselin Todorov
-
-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.
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/examples/custom_path.js b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/examples/custom_path.js
deleted file mode 100644
index a03c0cc..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/examples/custom_path.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * package - Easy package.json exports.
- * 
- * Author: Veselin Todorov <hi at vesln.com>
- * Licensed under the MIT License.
- */
-
-/**
- * Dependencies.
- */
-
-var package = require('../')(__dirname + '/..'); // parent dir.
-
-console.log(package); // This will contain the package.json data.
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/examples/module.js b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/examples/module.js
deleted file mode 100644
index c479069..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/examples/module.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * package - Easy package.json exports.
- * 
- * Author: Veselin Todorov <hi at vesln.com>
- * Licensed under the MIT License.
- */
-
-/**
- * Dependencies.
- */
-
-var package = require('../')(module);
-
-console.log(package); // This will contain the package.json data.
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/lib/package.js b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/lib/package.js
deleted file mode 100644
index 348db0c..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/lib/package.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * package - Easy package.json exports.
- * 
- * Author: Veselin Todorov <hi at vesln.com>
- * Licensed under the MIT License.
- */
-
-/**
- * Dependencies.
- */
-var fs = require('fs');
-var path = require('path');
-var exists = fs.existsSync || path.existsSync;
-
-/**
- * Package.
- * 
- * @param {String|null} location
- * @returns {Object} package.json data
- */
-var package = function(location) {
-  if (location === Object(location)) {
-    location = package.discover(location);
-  }
-  return package.read(path.normalize(location + '/package.json'));
-};
-
-/**
- * Reads and parses a package.json file.
- * 
- * @param {String} file
- * @returns {Object} package.json data
- */
-package.read = function(file) {
-  var data = fs.readFileSync(file, 'utf8');
-  return JSON.parse(data);
-};
-
-/**
- * Makes an atempt to find package.json file.
- * 
- * @returns {Object} package.json data
- */
-package.discover = function(module) {
-  var location = path.dirname(module.filename);
-  var found = null;
-  
-  while (!found) {
-    if (exists(location + '/package.json')) {
-      found = location;
-    } else if (location !== '/') {
-      location = path.dirname(location);
-    } else {
-      throw new Error('package.json can not be located');
-    }
-  }
-  
-  return found;
-};
-
-/**
- * Exporting the lib.
- */
-module.exports = package;
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/package.json b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/package.json
deleted file mode 100644
index 2b171b0..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/package.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
-    "name": "package"
-  , "version": "1.0.1"
-  , "description": "Easy package.json exports."
-  , "keywords": ["package.json"]
-  , "author": "Veselin Todorov <hi at vesln.com>"
-  , "devDependencies": {
-      "mocha": "0.3.3"
-    , "should": "0.3.2"
-  }
-  , "repository" : {
-      "type" : "git",
-      "url" : "http://github.com/vesln/package.git"
-  }
-  , "homepage": "http://github.com/vesln/package"
-  , "scripts": {
-      "test": "make test"
-  }
-  , "main": "./lib/package"
-  , "engines": { "node": ">= 0.6.0" }
-}
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/index.test.js b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/index.test.js
deleted file mode 100644
index c43364b..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/index.test.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * package - Easy package.json exports.
- * 
- * Author: Veselin Todorov <hi at vesln.com>
- * Licensed under the MIT License.
- */
-
-/**
- * Dependencies.
- */ 
-var package = require('../');
-
-describe('package', function() {
-  describe('read', function() {
-    it('should read and parse .json file', function() {
-      var result = package.read(__dirname + '/support/package.json');
-      result.should.eql({
-        name: 'test-package-json-file',
-        version: '0.0.1',
-        private: true 
-      });
-    });
-  });
-  
-  it('should read and parse given .json file', function() {
-    var result = package(__dirname + '/support');
-    result.should.eql({
-      name: 'test-package-json-file',
-      version: '0.0.1',
-      private: true 
-    });
-  });
-  
-  it('should autodiscover, read and parse package.json', function() {
-    var result = package(module);
-    result.should.eql({
-      name: 'test-package-json-file',
-      version: '0.0.1',
-      private: true 
-    });
-  });
-});
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/nested/two/nested.test.js b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/nested/two/nested.test.js
deleted file mode 100644
index 99c012e..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/nested/two/nested.test.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * package - Easy package.json exports.
- * 
- * Author: Veselin Todorov <hi at vesln.com>
- * Licensed under the MIT License.
- */
- 
-/**
- * Dependencies.
- */ 
-var package = require('../../../');
-
-describe('nested package json', function() {
-  it('should autodiscover, read and parse package.json', function() {
-    var result = package(module);
-    result.should.eql({
-      name: 'test-package-json-file',
-      version: '0.0.1',
-      private: true 
-    });
-  });
-});
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/package.json b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/package.json
deleted file mode 100644
index ed5e671..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    "name": "test-package-json-file"
-  , "version": "0.0.1"
-  , "private": true
-}
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/support/package.json b/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/support/package.json
deleted file mode 100644
index ed5e671..0000000
--- a/__tests__/fixtures/remove/scoped-package/node_modules/@scoped/package/test/support/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    "name": "test-package-json-file"
-  , "version": "0.0.1"
-  , "private": true
-}
\ No newline at end of file
diff --git a/__tests__/fixtures/remove/scoped-package/package.json b/__tests__/fixtures/remove/scoped-package/package.json
index 2bd6715..693e7c8 100644
--- a/__tests__/fixtures/remove/scoped-package/package.json
+++ b/__tests__/fixtures/remove/scoped-package/package.json
@@ -1,5 +1,6 @@
 {
   "dependencies": {
-    "@scoped/package": "^1.0.1"
+    "@dengorbachev/bar": "^1.0.0",
+    "@dengorbachev/foo": "^1.0.0"
   }
 }
diff --git a/__tests__/fixtures/remove/scoped-package/yarn.lock b/__tests__/fixtures/remove/scoped-package/yarn.lock
index 9825bb1..78e3e53 100644
--- a/__tests__/fixtures/remove/scoped-package/yarn.lock
+++ b/__tests__/fixtures/remove/scoped-package/yarn.lock
@@ -1,6 +1,11 @@
 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 # yarn lockfile v1
-"@scoped/package":
-  version "1.0.1"
-  resolved package-1.0.1.tgz#d25a1f99e2506dcb27d6704b83dca8a312e4edcc
 
+
+"@dengorbachev/bar@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@dengorbachev/bar/-/bar-1.0.0.tgz#f01d868a938353e52703a6751ebf07e92016060d"
+
+"@dengorbachev/foo@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@dengorbachev/foo/-/foo-1.0.0.tgz#67a8228a6cc54d7062b1de314bad734882302205"
diff --git a/__tests__/fixtures/request-cache/GET/localhost/.bin b/__tests__/fixtures/request-cache/GET/localhost/.bin
deleted file mode 100644
index 48da4c3..0000000
--- a/__tests__/fixtures/request-cache/GET/localhost/.bin
+++ /dev/null
@@ -1,6 +0,0 @@
-HTTP/1.1 200 OK
-Date: Thu, 24 Nov 2016 18:27:00 GMT
-Connection: close
-Content-Length: 2
-
-ok
\ No newline at end of file
diff --git a/__tests__/package-hoister.js b/__tests__/package-hoister.js
new file mode 100644
index 0000000..1454673
--- /dev/null
+++ b/__tests__/package-hoister.js
@@ -0,0 +1,44 @@
+/* @flow */
+
+import PackageHoister, {HoistManifest} from '../src/package-hoister.js';
+import type PackageResolver from '../src/package-resolver.js';
+import type PackageReference from '../src/package-reference.js';
+import type Config from '../src/config.js';
+import type {Manifest} from '../src/types.js';
+
+const path = require('path');
+
+test('Produces valid destination paths for scoped modules', () => {
+  const expected = path.join(__dirname, './node_modules/@scoped/dep');
+  const scopedPackageName = '@scoped/dep';
+
+  const config = (({
+    cwd: __dirname,
+    getFolder(): string {
+      return 'node_modules';
+    },
+  }: any): Config);
+
+  const resolver = (({}: any): PackageResolver);
+
+  const key = scopedPackageName;
+  const parts = [scopedPackageName];
+
+  const pkg = (({
+    _reference: (({}: any): PackageReference),
+  }: any): Manifest);
+
+  const info = new HoistManifest(key, parts, pkg, '', false);
+
+  const tree = new Map([
+    ['@scoped/dep', info],
+  ]);
+
+  const packageHoister = new PackageHoister(config, resolver, false);
+  packageHoister.tree = tree;
+
+  const result = packageHoister.init();
+  const [actual] = result[0];
+
+  expect(actual).toEqual(expected);
+});
diff --git a/appveyor.yml b/appveyor.yml
index 4611264..5844ff9 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -6,7 +6,7 @@ environment:
 branches:
   only:
   - master
-  - /.*-stable/
+  - /v[0-9]+(\.[0-9]+)*/
 
 install:
   - ps: Install-Product node $env:node_version
@@ -37,3 +37,12 @@ notifications:
       Authorization:
         secure: uH4c9HNDdRuL4omqqbTtBq3KgzjGTFmpvPdiNuk9391Z0YXRoRLA1Ptpa3seZ0Pt
     on_build_failure: false
+
+deploy:
+  - provider: Webhook
+    url: https://nightly.yarnpkg.com/release_appveyor
+    authorization:
+      secure: uH4c9HNDdRuL4omqqbTtBq3KgzjGTFmpvPdiNuk9391Z0YXRoRLA1Ptpa3seZ0Pt
+    on:
+      branch: /v[0-9]+(\.[0-9]+)*/
+      appveyor_repo_tag: true
diff --git a/circle.yml b/circle.yml
index 096979d..4a03a77 100644
--- a/circle.yml
+++ b/circle.yml
@@ -50,7 +50,9 @@ deployment:
     owner: yarnpkg
     commands:
       - ~/ghr/ghr --username yarnpkg --repository yarn --token $KPM_CIRCLE_RELEASE_TOKEN v$(dist/bin/yarn --version) artifacts/
+      - curl https://nightly.yarnpkg.com/sign_releases?token=$SIGN_TOKEN
       - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
+      - ./scripts/set-installation-method.js "`pwd`/package.json" npm
       - npm publish
 
 notify:
diff --git a/end_to_end_tests/data/start-ubuntu.sh b/end_to_end_tests/data/start-ubuntu.sh
index c9657c1..26fbe68 100755
--- a/end_to_end_tests/data/start-ubuntu.sh
+++ b/end_to_end_tests/data/start-ubuntu.sh
@@ -8,4 +8,4 @@ if [ -z "$1" ]; then
 fi;
 
 data_path=$(dirname $(readlink -f "$0"))
-docker run -v $data_path:/data -w=/data -e APT_PROXY=$APT_PROXY -e DEBIAN_FRONTEND=noninteractive $1 /data/run-ubuntu.sh
+docker run --rm -v $data_path:/data -w=/data -e APT_PROXY=$APT_PROXY -e DEBIAN_FRONTEND=noninteractive $1 /data/run-ubuntu.sh
diff --git a/gulpfile.js b/gulpfile.js
index a0bf1bc..136865d 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1,10 +1,13 @@
 'use strict';
 
+const argv = require('yargs').argv;
 const plumber = require('gulp-plumber');
 const newer = require('gulp-newer');
 const babel = require('gulp-babel');
+const sourcemaps = require('gulp-sourcemaps');
 const watch = require('gulp-watch');
 const gutil = require('gulp-util');
+const gulpif = require('gulp-if');
 const gulp = require('gulp');
 const path = require('path');
 const fs = require('fs');
@@ -19,7 +22,9 @@ function build(lib, opts) {
       },
     }))
     .pipe(newer(lib))
+    .pipe(gulpif(argv.sourcemaps, sourcemaps.init()))
     .pipe(babel(opts))
+    .pipe(gulpif(argv.sourcemaps, sourcemaps.write('.')))
     .pipe(gulp.dest(lib));
 }
 
diff --git a/package.json b/package.json
index 1efb87e..9b596d5 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "yarn",
   "installationMethod": "unknown",
-  "version": "0.17.9",
+  "version": "0.18.0",
   "license": "BSD-2-Clause",
   "preferGlobal": true,
   "dependencies": {
@@ -20,7 +20,7 @@
     "inquirer": "^1.2.2",
     "invariant": "^2.2.0",
     "is-builtin-module": "^1.0.0",
-    "is-ci": "^1.0.9",
+    "is-ci": "^1.0.10",
     "leven": "^2.0.0",
     "loud-rejection": "^1.2.0",
     "minimatch": "^3.0.3",
@@ -67,15 +67,18 @@
     "flow-bin": "0.33.0",
     "gulp": "^3.9.0",
     "gulp-babel": "^6.0.0",
+    "gulp-if": "^2.0.1",
     "gulp-newer": "^1.0.0",
     "gulp-plumber": "^1.0.1",
+    "gulp-sourcemaps": "^2.2.0",
     "gulp-util": "^3.0.7",
     "gulp-watch": "^4.3.5",
     "jest": "^16.0.1",
     "json-loader": "^0.5.4",
     "mock-stdin": "^0.3.0",
     "temp": "^0.8.3",
-    "webpack": "^2.1.0-beta.25"
+    "webpack": "^2.1.0-beta.25",
+    "yargs": "^6.3.0"
   },
   "repository": "yarnpkg/yarn",
   "bin": {
diff --git a/resources/win-chocolatey/tools/chocolateyinstall.ps1.in b/resources/win-chocolatey/tools/chocolateyinstall.ps1.in
index f51af5e..05e40cf 100644
--- a/resources/win-chocolatey/tools/chocolateyinstall.ps1.in
+++ b/resources/win-chocolatey/tools/chocolateyinstall.ps1.in
@@ -21,8 +21,8 @@ if (Test-Path "${env:ProgramFiles(x86)}\Yarn\package.json") {
   $path = "$env:ProgramFiles\Yarn\package.json"
 }
 $script = @"
-  `$package_manifest = Get-Content -Path '$path' | ConvertFrom-Json
-  `$package_manifest.installationMethod = 'choco'
-  ConvertTo-Json -InputObject `$package_manifest | Set-Content -Path '$path'
+  (Get-Content -Path '$path') ``
+    -replace 'installationMethod":.+', 'installationMethod": "choco",' ``
+    | Set-Content '$path'
 "@
 Start-ChocolateyProcessAsAdmin -Statements $script
diff --git a/resources/win-chocolatey/yarn.nuspec b/resources/win-chocolatey/yarn.nuspec
index e2a373f..bf774c5 100644
--- a/resources/win-chocolatey/yarn.nuspec
+++ b/resources/win-chocolatey/yarn.nuspec
@@ -15,7 +15,7 @@ focuses.
 
 **Determinism:** Based around a version lockfile which ensures that operations on
 the dependency graph can be easily transitioned. We check module directories
-and verify their integrity to ensure yarn install always produces the same file
+and verify their integrity to ensure Yarn install always produces the same file
 structure.
 
 **Security:** Strict guarantees are placed around package installation. You have
@@ -27,7 +27,7 @@ fetching in parallel. This ensures little idle time and maximum resource
 utilization.
 		</description>
 		<projectUrl>https://yarnpkg.com/</projectUrl>
-		<packageSourceUrl>https://github.com/yarnpkg/yarn</packageSourceUrl>
+		<packageSourceUrl>https://github.com/yarnpkg/yarn/tree/master/resources/win-chocolatey</packageSourceUrl>
 		<projectSourceUrl>https://github.com/yarnpkg/yarn</projectSourceUrl>
 		<licenseUrl>https://github.com/yarnpkg/yarn/raw/master/LICENSE</licenseUrl>
 		<requireLicenseAcceptance>false</requireLicenseAcceptance>
diff --git a/resources/winsetup/YarnSetup.wixproj b/resources/winsetup/YarnSetup.wixproj
index 1ad2da3..1039863 100644
--- a/resources/winsetup/YarnSetup.wixproj
+++ b/resources/winsetup/YarnSetup.wixproj
@@ -79,10 +79,10 @@
     />
   </Target>
   <Target Name="AfterBuild">
-    <!-- Rename installer to yarn-[version].msi -->
+    <!-- Rename installer to yarn-[version]-unsigned.msi -->
     <Copy
       SourceFiles="$(OutputPath)\Yarn.msi"
-      DestinationFiles="$(YarnDistPath)\..\artifacts\yarn-$(YarnVersion).msi"
+      DestinationFiles="$(YarnDistPath)\..\artifacts\yarn-$(YarnVersion)-unsigned.msi"
     />
   </Target>
 </Project>
diff --git a/scripts/build-chocolatey.ps1 b/scripts/build-chocolatey.ps1
index 6418020..5fc2e38 100644
--- a/scripts/build-chocolatey.ps1
+++ b/scripts/build-chocolatey.ps1
@@ -33,12 +33,12 @@ Invoke-WebRequest -Uri $url -OutFile $installer_file
 $hash = (Get-FileHash -Path $installer_file -Algorithm SHA256).Hash
 
 # Replace placeholders in chocolateyInstall.ps1
-(Get-Content .\resources\win-chocolatey\tools\chocolateyinstall.ps1.in) `
+(Get-Content $PSScriptRoot\..\resources\win-chocolatey\tools\chocolateyinstall.ps1.in) `
   -replace '{VERSION}', $latest_version `
   -replace '{CHECKSUM}', $hash | 
-  Set-Content .\resources\win-chocolatey\tools\chocolateyinstall.ps1
+  Set-Content $PSScriptRoot\..\resources\win-chocolatey\tools\chocolateyinstall.ps1
   
-choco pack .\resources\win-chocolatey\yarn.nuspec --version $latest_version
+choco pack $PSScriptRoot\..\resources\win-chocolatey\yarn.nuspec --version $latest_version
 mv *.nupkg artifacts
 
 if (!$Publish) {
diff --git a/scripts/install-latest.sh b/scripts/install-latest.sh
index de72dce..1585108 100755
--- a/scripts/install-latest.sh
+++ b/scripts/install-latest.sh
@@ -4,22 +4,61 @@ set -e
 reset="\e[0m"
 red="\e[0;31m"
 green="\e[0;32m"
+yellow="\e[0;33m"
 cyan="\e[0;36m"
 white="\e[0;37m"
+gpg_key=9D41F3C3
 
 yarn_get_tarball() {
   printf "$cyan> Downloading tarball...$reset\n"
   if [ "$1" = '--nightly' ]; then
     url=https://nightly.yarnpkg.com/latest.tar.gz
+  elif [ "$1" = '--version' ]; then
+    url="https://yarnpkg.com/downloads/$2/yarn-v$2.tar.gz"
   else
     url=https://yarnpkg.com/latest.tar.gz
   fi
-  curl -L -o yarn.tar.gz "$url" >/dev/null # get tarball
+  # Get both the tarball and its GPG signature
+  tarball_tmp=`mktemp -t yarn.XXXXXXXXXX.tar.gz`
+  curl -L -o "$tarball_tmp#1" "$url{,.asc}"
+  yarn_verify_integrity $tarball_tmp
 
   printf "$cyan> Extracting to ~/.yarn...$reset\n"
   mkdir .yarn
-  tar zxf yarn.tar.gz -C .yarn --strip 1 # extract tarball
-  rm -rf yarn.tar.gz # remove tarball
+  tar zxf $tarball_tmp -C .yarn --strip 1 # extract tarball
+  rm $tarball_tmp{,.asc}
+}
+
+# Verifies the GPG signature of the tarball
+yarn_verify_integrity() {
+  # Check if GPG is installed
+  if [[ -z "$(command -v gpg)" ]]; then
+    printf "$yellow> WARNING: GPG is not installed, integrity can not be verified!$reset\n"
+    return
+  fi
+
+  if [ "$YARN_GPG" == "no" ]; then
+    printf "$cyan> WARNING: Skipping GPG integrity check!$reset\n"
+    return
+  fi
+
+  printf "$cyan> Verifying integrity...$reset\n"
+  # Grab the public key if it doesn't already exist
+  gpg --list-keys $gpg_key >/dev/null 2>&1 || (curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --import)
+
+  if [ ! -f "$1.asc" ]; then
+    printf "$red> Could not download GPG signature for this Yarn release. This means the release can not be verified!$reset\n"
+    yarn_verify_or_quit "> Do you really want to continue?"
+    return
+  fi
+
+  # Actually perform the verification
+  if gpg --verify "$1.asc" $1; then
+    printf "$green> GPG signature looks good$reset\n"
+  else
+    printf "$red> GPG signature for this Yarn release is invalid! This is BAD and may mean the release has been tampered with. It is strongly recommended that you report this to the Yarn developers.$reset\n"
+    yarn_verify_or_quit "> Do you really want to continue?"
+  fi
 }
 
 yarn_link() {
@@ -99,22 +138,57 @@ yarn_detect_profile() {
 }
 
 yarn_reset() {
-  unset -f yarn_install yarn_reset yarn_get_tarball yarn_link yarn_detect_profile
+  unset -f yarn_install yarn_reset yarn_get_tarball yarn_link yarn_detect_profile yarn_verify_integrity yarn_verify_or_quit
 }
 
 yarn_install() {
   printf "${white}Installing Yarn!$reset\n"
 
   if [ -d "$HOME/.yarn" ]; then
-    printf "$red> ~/.yarn already exists, possibly from a past Yarn install.$reset\n"
-    printf "$red> Remove it (rm -rf ~/.yarn) and run this script again.$reset\n"
-    exit 0
+    if which yarn; then
+      local latest_url
+      local specified_version
+      local version_type
+      if [ "$1" = '--nightly' ]; then
+        latest_url=https://nightly.yarnpkg.com/latest-tar-version
+        specified_version=`curl -sS $latest_url`
+        version_type='latest'
+      elif [ "$1" = '--version' ]; then
+        specified_version=$2
+        version_type='specified'
+      else
+        latest_url=https://yarnpkg.com/latest-version
+        specified_version=`curl -sS $latest_url`
+        version_type='latest'
+      fi
+      yarn_version=`yarn -V`
+      yarn_alt_version=`yarn --version`
+      if [ "$specified_version" = "$yarn_version" -o "$specified_version" = "$yarn_alt_version" ]; then
+        printf "$green> Yarn is already at the $specified_version version.$reset\n"
+      else
+        rm -rf "$HOME/.yarn"
+      fi
+    else
+      printf "$red> $HOME/.yarn already exists, possibly from a past Yarn install.$reset\n"
+      printf "$red> Remove it (rm -rf $HOME/.yarn) and run this script again.$reset\n"
+      exit 0
+    fi
   fi
 
-  yarn_get_tarball $1
+  yarn_get_tarball $1 $2
   yarn_link
   yarn_reset
 }
 
+yarn_verify_or_quit() {
+  read -p "$1 [y/N] " -n 1 -r
+  echo
+  if [[ ! $REPLY =~ ^[Yy]$ ]]
+  then
+    printf "$red> Aborting$reset\n"
+    exit 1
+  fi
+}
+
 cd ~
-yarn_install $1
+yarn_install $1 $2
diff --git a/src/cli/aliases.js b/src/cli/aliases.js
index 41d72d7..097cf27 100644
--- a/src/cli/aliases.js
+++ b/src/cli/aliases.js
@@ -5,7 +5,7 @@ export default ({
   'run-script': 'run',
   c: 'config',
   i: 'install',
-  list: 'ls',
+  ls: 'list',
   ln: 'link',
   rb: 'rebuild',
   runScript: 'run',
@@ -22,8 +22,8 @@ export default ({
   adduser: 'login',
   author: 'owner',
   isntall: 'install',
-  la: 'ls',
-  ll: 'ls',
+  la: 'list',
+  ll: 'list',
   r: 'remove',
   rm: 'remove',
   show: 'info',
diff --git a/src/cli/commands/add.js b/src/cli/commands/add.js
index ae442e5..930c3b9 100644
--- a/src/cli/commands/add.js
+++ b/src/cli/commands/add.js
@@ -4,11 +4,10 @@ import type {Reporter} from '../../reporters/index.js';
 import type {InstallCwdRequest} from './install.js';
 import type {DependencyRequestPatterns, Manifest} from '../../types.js';
 import type Config from '../../config.js';
-import type {LsOptions} from './ls.js';
+import type {ListOptions} from './list.js';
 import Lockfile from '../../lockfile/wrapper.js';
-import * as PackageReference from '../../package-reference.js';
 import PackageRequest from '../../package-request.js';
-import {buildTree} from './ls.js';
+import {buildTree} from './list.js';
 import {wrapLifecycle, Install} from './install.js';
 import {MessageError} from '../../errors.js';
 
@@ -40,6 +39,7 @@ export class Add extends Install {
   /**
    * TODO
    */
+
   prepareRequests(requests: DependencyRequestPatterns): DependencyRequestPatterns {
     const requestsWithArgs = requests.slice();
 
@@ -47,7 +47,6 @@ export class Add extends Install {
       requestsWithArgs.push({
         pattern,
         registry: 'npm',
-        visibility: PackageReference.USED,
         optional: false,
       });
     }
@@ -128,7 +127,7 @@ export class Add extends Install {
 
   async maybeOutputSaveTree(patterns: Array<string>): Promise<void> {
     // don't limit the shown tree depth
-    const opts: LsOptions = {
+    const opts: ListOptions = {
       reqDepth: 0,
     };
     const {trees, count} = await buildTree(this.resolver, this.linker, patterns, opts, true, true);
diff --git a/src/cli/commands/check.js b/src/cli/commands/check.js
index f547938..405c746 100644
--- a/src/cli/commands/check.js
+++ b/src/cli/commands/check.js
@@ -40,10 +40,11 @@ export async function run(
   }
 
   // get patterns that are installed when running `yarn install`
-  const [, rawPatterns] = await install.hydrate();
+  const {patterns: rawPatterns} = await install.hydrate(true);
+  const patterns = await install.flatten(rawPatterns);
 
   // check if patterns exist in lockfile
-  for (const pattern of rawPatterns) {
+  for (const pattern of patterns) {
     if (!lockfile.getLocked(pattern)) {
       reportError(`Lockfile does not contain pattern: ${pattern}`);
     }
@@ -54,7 +55,7 @@ export async function run(
     const integrityLoc = await install.getIntegrityHashLocation();
 
     if (integrityLoc && await fs.exists(integrityLoc)) {
-      const match = await install.matchesIntegrityHash(rawPatterns);
+      const match = await install.matchesIntegrityHash(patterns);
       if (match.matches === false) {
         reportError(`Integrity hashes don't match, expected ${match.expected} but got ${match.actual}`);
       }
@@ -63,8 +64,12 @@ export async function run(
     }
   } else {
     // check if any of the node_modules are out of sync
-    const res = await install.linker.getFlatHoistedTree(rawPatterns);
-    for (const [loc, {originalKey, pkg}] of res) {
+    const res = await install.linker.getFlatHoistedTree(patterns);
+    for (const [loc, {originalKey, pkg, ignore}] of res) {
+      if (ignore) {
+        continue;
+      }
+
       const parts = humaniseLocation(loc);
 
       // grey out hoisted portions of key
diff --git a/src/cli/commands/global.js b/src/cli/commands/global.js
index 93c6bd3..e2ce958 100644
--- a/src/cli/commands/global.js
+++ b/src/cli/commands/global.js
@@ -35,6 +35,9 @@ async function updateCwd(config: Config): Promise<void> {
   await config.init({
     cwd: config.globalFolder,
     binLinks: true,
+    globalFolder: config.globalFolder,
+    cacheFolder: config.cacheFolder,
+    linkFolder: config.linkFolder,
   });
 }
 
diff --git a/src/cli/commands/index.js b/src/cli/commands/index.js
index bdb83ec..82442fc 100644
--- a/src/cli/commands/index.js
+++ b/src/cli/commands/index.js
@@ -16,14 +16,13 @@ import * as licenses from './licenses.js'; export {licenses};
 import * as link from './link.js'; export {link};
 import * as login from './login.js'; export {login};
 import * as logout from './logout.js'; export {logout};
-import * as ls from './ls.js'; export {ls};
+import * as list from './list.js'; export {list};
 import * as outdated from './outdated.js'; export {outdated};
 import * as owner from './owner.js'; export {owner};
 import * as pack from './pack.js'; export {pack};
 import * as publish from './publish.js'; export {publish};
 import * as remove from './remove.js'; export {remove};
 import * as run from './run.js'; export {run};
-import * as selfUpdate from './self-update.js'; export {selfUpdate};
 import * as tag from './tag.js'; export {tag};
 import * as team from './team.js'; export {team};
 import * as unlink from './unlink.js'; export {unlink};
diff --git a/src/cli/commands/install.js b/src/cli/commands/install.js
index f601905..3f5e104 100644
--- a/src/cli/commands/install.js
+++ b/src/cli/commands/install.js
@@ -10,7 +10,6 @@ import {registryNames} from '../../registries/index.js';
 import {MessageError} from '../../errors.js';
 import Lockfile from '../../lockfile/wrapper.js';
 import lockStringify from '../../lockfile/stringify.js';
-import * as PackageReference from '../../package-reference.js';
 import PackageFetcher from '../../package-fetcher.js';
 import PackageInstallScripts from '../../package-install-scripts.js';
 import PackageCompatibility from '../../package-compatibility.js';
@@ -26,14 +25,21 @@ import map from '../../util/map.js';
 import {sortAlpha} from '../../util/misc.js';
 
 const invariant = require('invariant');
+const semver = require('semver');
 const emoji = require('node-emoji');
+const isCI = require('is-ci');
 const path = require('path');
 
-export type InstallCwdRequest = [
-  DependencyRequestPatterns,
-  Array<string>,
-  Object
-];
+const {version: YARN_VERSION, installationMethod: YARN_INSTALL_METHOD} = require('../../../package.json');
+const ONE_DAY = 1000 * 60 * 60 * 24;
+
+export type InstallCwdRequest = {
+  requests: DependencyRequestPatterns,
+  patterns: Array<string>,
+  ignorePatterns: Array<string>,
+  usedPatterns: Array<string>,
+  manifest: Object,
+};
 
 export type IntegrityMatch = {
   actual: string,
@@ -51,7 +57,6 @@ type Flags = {
   har: boolean,
   force: boolean,
   flat: boolean,
-  production: boolean,
   lockfile: boolean,
   pureLockfile: boolean,
   skipIntegrity: boolean,
@@ -64,6 +69,47 @@ type Flags = {
   tilde: boolean,
 };
 
+/**
+ * Try and detect the installation method for Yarn and provide a command to update it with.
+ */
+
+function getUpdateCommand(): ?string {
+  if (YARN_INSTALL_METHOD === 'tar') {
+    return 'curl -o- -L https://yarnpkg.com/install.sh | bash';
+  }
+
+  if (YARN_INSTALL_METHOD === 'homebrew') {
+    return 'brew upgrade yarn';
+  }
+
+  if (YARN_INSTALL_METHOD === 'deb') {
+    return 'sudo apt-get update && sudo apt-get install yarn';
+  }
+
+  if (YARN_INSTALL_METHOD === 'rpm') {
+    return 'sudo yum install yarn';
+  }
+
+  if (YARN_INSTALL_METHOD === 'npm') {
+    return 'npm upgrade --global yarn';
+  }
+
+  if (YARN_INSTALL_METHOD === 'chocolatey') {
+    return 'choco upgrade yarn';
+  }
+
+  return null;
+}
+
+function getUpdateInstaller(): ?string {
+  // Windows
+  if (YARN_INSTALL_METHOD === 'msi') {
+    return 'https://yarnpkg.com/latest.msi';
+  }
+
+  return null;
+}
+
 function normalizeFlags(config: Config, rawFlags: Object): Flags {
   const flags = {
     // install
@@ -74,7 +120,6 @@ function normalizeFlags(config: Config, rawFlags: Object): Flags {
     ignoreOptional: !!rawFlags.ignoreOptional,
     force: !!rawFlags.force,
     flat: !!rawFlags.flat,
-    production: !!rawFlags.production,
     lockfile: rawFlags.lockfile !== false,
     pureLockfile: !!rawFlags.pureLockfile,
     skipIntegrity: !!rawFlags.skipIntegrity,
@@ -107,10 +152,6 @@ function normalizeFlags(config: Config, rawFlags: Object): Flags {
     flags.force = true;
   }
 
-  if (config.getOption('production') || process.env.NODE_ENV === 'production') {
-    flags.production = true;
-  }
-
   return flags;
 }
 
@@ -132,7 +173,7 @@ export class Install {
     this.resolver = new PackageResolver(config, lockfile);
     this.fetcher = new PackageFetcher(config, this.resolver);
     this.compatibility = new PackageCompatibility(config, this.resolver, this.flags.ignoreEngines);
-    this.linker = new PackageLinker(config, this.resolver, this.flags.ignoreOptional);
+    this.linker = new PackageLinker(config, this.resolver);
     this.scripts = new PackageInstallScripts(config, this.resolver, this.flags.force);
   }
 
@@ -159,6 +200,9 @@ export class Install {
     const deps = [];
     const manifest = {};
 
+    const ignorePatterns = [];
+    const usedPatterns = [];
+
     // exclude package names that are in install args
     const excludeNames = [];
     for (const pattern of excludePatterns) {
@@ -186,7 +230,7 @@ export class Install {
       Object.assign(this.resolutions, json.resolutions);
       Object.assign(manifest, json);
 
-      const pushDeps = (depType, {hint, visibility, optional}) => {
+      const pushDeps = (depType, {hint, optional}, isUsed) => {
         const depMap = json[depType];
         for (const name in depMap) {
           if (excludeNames.indexOf(name) >= 0) {
@@ -200,18 +244,21 @@ export class Install {
             pattern += '@' + depMap[name];
           }
 
+          if (isUsed) {
+            usedPatterns.push(pattern);
+          } else {
+            ignorePatterns.push(pattern);
+          }
+
           this.rootPatternsToOrigin[pattern] = depType;
           patterns.push(pattern);
-          deps.push({pattern, registry, visibility, hint, optional});
+          deps.push({pattern, registry, hint, optional});
         }
       };
 
-      pushDeps('dependencies', {hint: null, visibility: PackageReference.USED, optional: false});
-
-      const devVisibility = this.flags.production ? PackageReference.ENVIRONMENT_IGNORE : PackageReference.USED;
-      pushDeps('devDependencies', {hint: 'dev', visibility: devVisibility, optional: false});
-
-      pushDeps('optionalDependencies', {hint: 'optional', visibility: PackageReference.USED, optional: true});
+      pushDeps('dependencies', {hint: null, optional: false}, true);
+      pushDeps('devDependencies', {hint: 'dev', optional: false}, !this.config.production);
+      pushDeps('optionalDependencies', {hint: 'optional', optional: true}, !this.flags.ignoreOptional);
 
       break;
     }
@@ -221,7 +268,13 @@ export class Install {
       this.flags.flat = true;
     }
 
-    return [deps, patterns, manifest];
+    return {
+      requests: deps,
+      patterns,
+      manifest,
+      usedPatterns,
+      ignorePatterns,
+    };
   }
 
   /**
@@ -278,25 +331,51 @@ export class Install {
    * TODO description
    */
 
+  markIgnored(patterns: Array<string>) {
+    for (const pattern of patterns) {
+      const manifest = this.resolver.getStrictResolvedPattern(pattern);
+      const ref = manifest._reference;
+      invariant(ref, 'expected package reference');
+
+      if (ref.requests.length === 1) {
+        // this module was only depended on once by the root so we can safely ignore it
+        // if it was requested more than once then ignoring it would break a transitive
+        // dep that resolved to it
+        ref.ignore = true;
+      }
+    }
+  }
+
+  /**
+   * TODO description
+   */
+
   async init(): Promise<Array<string>> {
+    this.checkUpdate();
+
     // warn if we have a shrinkwrap
     if (await fs.exists(path.join(this.config.cwd, 'npm-shrinkwrap.json'))) {
-      this.reporter.error(this.reporter.lang('shrinkwrapWarning'));
+      this.reporter.warn(this.reporter.lang('shrinkwrapWarning'));
     }
 
     let patterns: Array<string> = [];
     const steps: Array<(curr: number, total: number) => Promise<{bailout: boolean} | void>> = [];
-    const [depRequests, rawPatterns] = await this.fetchRequestFromCwd();
+    const {
+      requests: depRequests,
+      patterns: rawPatterns,
+      ignorePatterns,
+      usedPatterns,
+    } = await this.fetchRequestFromCwd();
 
     steps.push(async (curr: number, total: number) => {
       this.reporter.step(curr, total, this.reporter.lang('resolvingPackages'), emoji.get('mag'));
       await this.resolver.init(this.prepareRequests(depRequests), this.flags.flat);
       patterns = await this.flatten(this.preparePatterns(rawPatterns));
-      return {bailout: await this.bailout(patterns)};
+      return {bailout: await this.bailout(usedPatterns)};
     });
 
-
     steps.push(async (curr: number, total: number) => {
+      this.markIgnored(ignorePatterns);
       this.reporter.step(curr, total, this.reporter.lang('fetchingPackages'), emoji.get('truck'));
       await this.fetcher.init();
       await this.compatibility.init();
@@ -356,6 +435,7 @@ export class Install {
 
     // fin!
     await this.saveLockfileAndIntegrity(patterns);
+    this.maybeOutputUpdate();
     this.config.requestManager.clearCache();
     return patterns;
   }
@@ -495,7 +575,7 @@ export class Install {
     const loc = path.join(this.config.cwd, constants.LOCKFILE_FILENAME);
 
     // write lockfile
-    await fs.writeFile(loc, lockSource);
+    await fs.writeFilePreservingEol(loc, lockSource);
 
     this._logSuccessSaveLockfile();
   }
@@ -575,6 +655,7 @@ export class Install {
   async writeIntegrityHash(lockSource: string, patterns: Array<string>): Promise<void> {
     const loc = await this.getIntegrityHashLocation();
     invariant(loc, 'expected integrity hash location');
+    await fs.mkdirp(path.dirname(loc));
     await fs.writeFile(loc, this.generateIntegrityHash(lockSource, patterns));
   }
 
@@ -591,7 +672,7 @@ export class Install {
       opts.push('flat');
     }
 
-    if (this.flags.production) {
+    if (this.config.production) {
       opts.push('production');
     }
 
@@ -614,14 +695,16 @@ export class Install {
 
   async hydrate(fetch?: boolean): Promise<InstallCwdRequest> {
     const request = await this.fetchRequestFromCwd();
-    const [depRequests, rawPatterns] = request;
+    const {requests: depRequests, patterns: rawPatterns, ignorePatterns} = request;
 
     await this.resolver.init(depRequests, this.flags.flat);
     await this.flatten(rawPatterns);
+    this.markIgnored(ignorePatterns);
 
     if (fetch) {
       // fetch packages, should hit cache most of the time
       await this.fetcher.init();
+      await this.compatibility.init();
 
       // expand minimal manifests
       for (const manifest of this.resolver.getManifests()) {
@@ -636,6 +719,72 @@ export class Install {
 
     return request;
   }
+
+  /**
+   * Check for updates every day and output a nag message if there's a newer version.
+   */
+
+  checkUpdate() {
+    if (!process.stdout.isTTY || isCI) {
+      // don't show upgrade dialog on CI or non-TTY terminals
+      return;
+    }
+
+    // only check for updates once a day
+    const lastUpdateCheck = Number(this.config.getOption('lastUpdateCheck')) || 0;
+    if (lastUpdateCheck && Date.now() - lastUpdateCheck < ONE_DAY) {
+      return;
+    }
+
+    // don't bug for updates on tagged releases
+    if (YARN_VERSION.indexOf('-') >= 0) {
+      return;
+    }
+
+    this._checkUpdate().catch(() => {
+      // swallow errors
+    });
+  }
+
+  async _checkUpdate(): Promise<void> {
+    let latestVersion = await this.config.requestManager.request({
+      url: 'https://yarnpkg.com/latest-version',
+    });
+    invariant(typeof latestVersion === 'string', 'expected string');
+    latestVersion = latestVersion.trim();
+    if (!semver.valid(latestVersion)) {
+      return;
+    }
+
+    // ensure we only check for updates periodically
+    this.config.registries.yarn.saveHomeConfig({
+      lastUpdateCheck: Date.now(),
+    });
+
+    if (semver.gt(latestVersion, YARN_VERSION)) {
+      this.maybeOutputUpdate = () => {
+        this.reporter.warn(this.reporter.lang('yarnOutdated', latestVersion, YARN_VERSION));
+
+        const command = getUpdateCommand();
+        if (command) {
+          this.reporter.info(this.reporter.lang('yarnOutdatedCommand'));
+          this.reporter.command(command);
+        } else {
+          const installer = getUpdateInstaller();
+          if (installer) {
+            this.reporter.info(this.reporter.lang('yarnOutdatedInstaller', installer));
+          }
+        }
+      };
+    }
+  }
+
+  /**
+   * Method to override with a possible upgrade message.
+   */
+
+  maybeOutputUpdate() {}
+  maybeOutputUpdate: any;
 }
 
 export function setFlags(commander: Object) {
@@ -701,7 +850,7 @@ export async function wrapLifecycle(config: Config, flags: Object, factory: () =
   await config.executeLifecycleScript('install');
   await config.executeLifecycleScript('postinstall');
 
-  if (!flags.production) {
+  if (!config.production) {
     await config.executeLifecycleScript('prepublish');
   }
 }
diff --git a/src/cli/commands/licenses.js b/src/cli/commands/licenses.js
index 8140d9c..1d9c913 100644
--- a/src/cli/commands/licenses.js
+++ b/src/cli/commands/licenses.js
@@ -14,11 +14,6 @@ export function hasWrapper(flags: Object, args: Array<string>): boolean {
   return args[0] != 'generate-disclaimer';
 }
 
-export function setFlags(commander: Object) {
-  setUsage(commander);
-  commander.option('--production', '');
-}
-
 async function getManifests(config: Config, flags: Object): Promise<Array<Manifest>> {
   const lockfile = await Lockfile.fromDirectory(config.cwd);
   const install = new Install({skipIntegrity: true, ...flags}, config, new NoopReporter(), lockfile);
@@ -52,7 +47,7 @@ async function getManifests(config: Config, flags: Object): Promise<Array<Manife
   return manifests;
 }
 
-const {setFlags: setUsage, run} = buildSubCommands('licenses', {
+export const {run, setFlags} = buildSubCommands('licenses', {
   async ls(
     config: Config,
     reporter: Reporter,
@@ -162,5 +157,3 @@ const {setFlags: setUsage, run} = buildSubCommands('licenses', {
     }
   },
 });
-
-export {run};
diff --git a/src/cli/commands/ls.js b/src/cli/commands/list.js
similarity index 96%
rename from src/cli/commands/ls.js
rename to src/cli/commands/list.js
index dcbbb13..c9ac82b 100644
--- a/src/cli/commands/ls.js
+++ b/src/cli/commands/list.js
@@ -12,7 +12,7 @@ const invariant = require('invariant');
 
 export const requireLockfile = true;
 
-export type LsOptions = {
+export type ListOptions = {
   reqDepth?: ?number,
 };
 
@@ -39,7 +39,7 @@ export async function buildTree(
   resolver: PackageResolver,
   linker: PackageLinker,
   patterns: Array<string>,
-  opts: LsOptions,
+  opts: ListOptions,
   onlyFresh?: boolean,
   ignoreHoisted?: boolean,
 ): Promise<{
@@ -176,10 +176,10 @@ export async function run(
 
   const lockfile = await Lockfile.fromDirectory(config.cwd, reporter);
   const install = new Install(flags, config, reporter, lockfile);
-  const [depRequests, patterns] = await install.fetchRequestFromCwd();
+  const {requests: depRequests, patterns} = await install.fetchRequestFromCwd();
   await install.resolver.init(depRequests, install.flags.flat);
 
-  const opts: LsOptions = {
+  const opts: ListOptions = {
     reqDepth: getReqDepth(flags.depth),
   };
 
@@ -189,5 +189,5 @@ export async function run(
     trees = trees.filter((tree) => filterTree(tree, args));
   }
 
-  reporter.tree('ls', trees);
+  reporter.tree('list', trees);
 }
diff --git a/src/cli/commands/outdated.js b/src/cli/commands/outdated.js
index 16f1dce..b545fb7 100644
--- a/src/cli/commands/outdated.js
+++ b/src/cli/commands/outdated.js
@@ -2,14 +2,9 @@
 
 import type {Reporter} from '../../reporters/index.js';
 import type Config from '../../config.js';
-import {MessageError} from '../../errors.js';
-import {sortAlpha} from '../../util/misc.js';
 import PackageRequest from '../../package-request.js';
 import Lockfile from '../../lockfile/wrapper.js';
 import {Install} from './install.js';
-import parsePackageName from '../../util/parse-package-name.js';
-
-const semver = require('semver');
 
 export const requireLockfile = true;
 
@@ -23,83 +18,32 @@ export async function run(
   flags: Object,
   args: Array<string>,
 ): Promise<void> {
-  const requestedDependencies = args.length ? new Set(args) : null;
-
   const lockfile = await Lockfile.fromDirectory(config.cwd);
   const install = new Install(flags, config, reporter, lockfile);
+  let deps = await PackageRequest.getOutdatedPackages(lockfile, install, config, reporter);
 
-  const items: Array<{
-    name: string,
-    current: string,
-    wanted: string,
-    latest: string,
-    packageType: string,
-  }> = [];
+  if (args.length) {
+    const requested = new Set(args);
 
-  let [, patterns] = await install.fetchRequestFromCwd();
-
-  if (requestedDependencies) {
-    patterns = patterns.filter(
-      (pattern) => requestedDependencies.has(parsePackageName(pattern).name),
-    );
+    deps = deps.filter(({name}) => requested.has(name));
   }
 
-  await Promise.all(patterns.map(async (pattern): Promise<void> => {
-    const locked = lockfile.getLocked(pattern);
-    if (!locked) {
-      throw new MessageError(reporter.lang('lockfileOutdated'));
-    }
-
-    const normalized = PackageRequest.normalizePattern(pattern);
-
-    const current = locked.version;
-    let name = locked.name;
-    const packageType = install.rootPatternsToOrigin[pattern];
-
-    let latest = '';
-    let wanted = '';
-
-    if (PackageRequest.getExoticResolver(pattern) ||
-        PackageRequest.getExoticResolver(normalized.range)) {
-      latest = wanted = 'exotic';
-    } else {
-      ({latest, wanted} = await config.registries[locked.registry].checkOutdated(config, name, normalized.range));
-    }
+  const getNameFromHint = (hint) => hint ? `${hint}Dependencies` : 'dependencies';
+  const getColorFromVersion = ({current, wanted, name}) => current === wanted ?
+    reporter.format.yellow(name) :
+    reporter.format.red(name);
 
-    if (latest !== 'exotic' && semver.gte(current, latest)) {
-      return;
-    }
-
-    if (current === wanted) {
-      name = reporter.format.yellow(name);
-    } else {
-      name = reporter.format.red(name);
-    }
-
-    items.push({
-      name,
-      current,
-      wanted,
-      latest,
-      packageType,
-    });
-  }));
-
-  if (items.length) {
-    let body = items.map((info): Array<string> => {
+  if (deps.length) {
+    const body = deps.map((info): Array<string> => {
       return [
-        info.name,
+        getColorFromVersion(info),
         info.current,
         reporter.format.green(info.wanted),
         reporter.format.magenta(info.latest),
-        info.packageType,
+        getNameFromHint(info.hint),
       ];
     });
 
-    body = body.sort((a, b): number => {
-      return sortAlpha(a[0], b[0]);
-    });
-
     reporter.table(['Package', 'Current', 'Wanted', 'Latest', 'Package Type'], body);
   }
 
diff --git a/src/cli/commands/pack.js b/src/cli/commands/pack.js
index 653d5b9..cf4cef1 100644
--- a/src/cli/commands/pack.js
+++ b/src/cli/commands/pack.js
@@ -39,7 +39,9 @@ const DEFAULT_IGNORE = ignoreLinesToRegex([
   '.gitignore',
   '.DS_Store',
   'node_modules',
+]);
 
+const NEVER_IGNORE = ignoreLinesToRegex([
   // never ignore these files
   '!package.json',
   '!readme*',
@@ -61,12 +63,16 @@ function addEntry(packer: any, entry: Object, buffer?: ?Buffer): Promise<void> {
 
 export async function pack(config: Config, dir: string): Promise<stream$Duplex> {
   const pkg = await config.readRootManifest();
+  const {bundledDependencies, files: onlyFiles} = pkg;
 
-  //
-  let filters: Array<IgnoreFilter> = DEFAULT_IGNORE.slice();
+  // inlude required files
+  let filters: Array<IgnoreFilter> = NEVER_IGNORE.slice();
+  // include default filters unless `files` is used
+  if (!onlyFiles) {
+    filters = filters.concat(DEFAULT_IGNORE);
+  }
 
   // include bundledDependencies
-  const {bundledDependencies} = pkg;
   if (bundledDependencies) {
     const folder = config.getFolder(pkg);
     filters = ignoreLinesToRegex(
@@ -76,15 +82,16 @@ export async function pack(config: Config, dir: string): Promise<stream$Duplex>
   }
 
   // `files` field
-  const {files: onlyFiles} = pkg;
   if (onlyFiles) {
     let lines = [
       '*', // ignore all files except those that are explicitly included with a negation filter
+      '.*', // files with "." as first character have to be excluded explicitly 
     ];
     lines = lines.concat(
       onlyFiles.map((filename: string): string => `!${filename}`),
     );
-    filters = ignoreLinesToRegex(lines, '.');
+    const regexes = ignoreLinesToRegex(lines, '.');
+    filters = filters.concat(regexes);
   }
 
   //
diff --git a/src/cli/commands/run.js b/src/cli/commands/run.js
index 56b7b21..53828c5 100644
--- a/src/cli/commands/run.js
+++ b/src/cli/commands/run.js
@@ -30,14 +30,18 @@ export async function run(
   const pkg = await config.readManifest(config.cwd);
   const scripts = map();
   const binCommands = [];
+  const visitedBinFolders = new Set();
   let pkgCommands = [];
   for (const registry of Object.keys(registries)) {
     const binFolder = path.join(config.cwd, config.registries[registry].folder, '.bin');
-    if (await fs.exists(binFolder)) {
-      for (const name of await fs.readdir(binFolder)) {
-        binCommands.push(name);
-        scripts[name] = `"${path.join(binFolder, name)}"`;
+    if (!visitedBinFolders.has(binFolder)) {
+      if (await fs.exists(binFolder)) {
+        for (const name of await fs.readdir(binFolder)) {
+          binCommands.push(name);
+          scripts[name] = `"${path.join(binFolder, name)}"`;
+        }
       }
+      visitedBinFolders.add(binFolder);
     }
   }
   if (pkg.scripts) {
diff --git a/src/cli/commands/self-update.js b/src/cli/commands/self-update.js
deleted file mode 100644
index 49df912..0000000
--- a/src/cli/commands/self-update.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/* @flow */
-
-import roadrunner from 'roadrunner';
-import semver from 'semver';
-import path from 'path';
-import type Config from '../../config.js';
-import {
-  CACHE_FILENAME,
-  SELF_UPDATE_DOWNLOAD_FOLDER,
-  SELF_UPDATE_TARBALL_URL,
-  SELF_UPDATE_VERSION_URL,
-} from '../../constants.js';
-import TarballFetcher from '../../fetchers/tarball-fetcher.js';
-import type {Reporter} from '../../reporters/index.js';
-import {exists, realpath, symlink, unlink} from '../../util/fs.js';
-
-export const noArguments = true;
-export const requireLockfile = false;
-
-export async function run(
-  config: Config,
-  reporter: Reporter,
-  flags: Object,
-  args: Array<string>,
-): Promise<void> {
-  const currentVersion = flags.version();
-  const latestVersion = await config.requestManager.request({
-    url: SELF_UPDATE_VERSION_URL,
-    headers: {
-      'Accept': 'text/plain',
-    },
-  });
-
-  // Check if we already use the latest or a newer version
-  if (semver.compare(currentVersion, latestVersion) >= 0) {
-    reporter.success(reporter.lang('selfUpdateNoNewer'));
-    return;
-  }
-
-  reporter.info(reporter.lang('selfUpdateDownloading', latestVersion));
-
-  const thisVersionRoot = path.resolve(__dirname, '..', '..', '..');
-  let updatesFolder = path.resolve(thisVersionRoot, '..');
-  const isCurrentVersionAnUpdate = path.basename(updatesFolder) === SELF_UPDATE_DOWNLOAD_FOLDER;
-
-  if (!isCurrentVersionAnUpdate) {
-    updatesFolder = path.resolve(thisVersionRoot, SELF_UPDATE_DOWNLOAD_FOLDER);
-  }
-
-  const locToUnzip = path.resolve(updatesFolder, latestVersion);
-
-  await unlink(locToUnzip);
-
-  const fetcher = new TarballFetcher(locToUnzip, {
-    type: 'tarball',
-    registry: 'yarn',
-    reference: SELF_UPDATE_TARBALL_URL,
-    hash: null,
-  }, config, false);
-  await fetcher.fetch();
-
-  // this links the downloaded release to bin/yarn.js
-  await symlink(locToUnzip, path.resolve(updatesFolder, 'current'));
-
-  // clean garbage
-  const pathToClean = path.resolve(updatesFolder, 'to_clean');
-  if (await exists(pathToClean)) {
-    const previousVersionToCleanup = await realpath(pathToClean);
-    await unlink(previousVersionToCleanup);
-    await unlink(pathToClean);
-  }
-
-  if (isCurrentVersionAnUpdate) {
-    // current yarn installation is an update, let's clean it next time an update is run
-    // because it may still be in use now
-    await symlink(thisVersionRoot, pathToClean);
-  }
-
-  // reset the roadrunner cache
-  roadrunner.reset(CACHE_FILENAME);
-
-  reporter.success(reporter.lang('selfUpdateReleased', latestVersion));
-}
diff --git a/src/cli/commands/upgrade-interactive.js b/src/cli/commands/upgrade-interactive.js
index 3cc6a10..cf14ce8 100644
--- a/src/cli/commands/upgrade-interactive.js
+++ b/src/cli/commands/upgrade-interactive.js
@@ -1,17 +1,16 @@
 /* @flow */
 
+import type {Dependency} from '../../types.js';
 import type {Reporter} from '../../reporters/index.js';
 import type Config from '../../config.js';
 import inquirer from 'inquirer';
 import repeat from 'repeating';
-import {MessageError} from '../../errors.js';
 import PackageRequest from '../../package-request.js';
 import {Add} from './add.js';
 import {Install} from './install.js';
 import Lockfile from '../../lockfile/wrapper.js';
 
 const tty = require('tty');
-const semver = require('semver');
 
 export const requireLockfile = true;
 
@@ -20,14 +19,6 @@ export function setFlags(commander: Object) {
   commander.usage('update');
 }
 
-type Dependency = {
-  name: string,
-  current: string,
-  wanted: string,
-  latest: string,
-  hint: ?string
-};
-
 type InquirerResponses<K, T> = {[key: K]: Array<T>};
 
 // Prompt user with Inquirer
@@ -55,37 +46,9 @@ export async function run(
 ): Promise<void> {
   const lockfile = await Lockfile.fromDirectory(config.cwd);
   const install = new Install(flags, config, reporter, lockfile);
-  const [deps] = await install.fetchRequestFromCwd();
-
-  const allDeps = await Promise.all(deps.map(async ({pattern, hint}): Promise<Dependency> => {
-    const locked = lockfile.getLocked(pattern);
-    if (!locked) {
-      throw new MessageError(reporter.lang('lockfileOutdated'));
-    }
-
-    const {name, version: current} = locked;
-    let latest = '';
-    let wanted = '';
-
-    const normalized = PackageRequest.normalizePattern(pattern);
-
-    if (PackageRequest.getExoticResolver(pattern) ||
-        PackageRequest.getExoticResolver(normalized.range)) {
-      latest = wanted = 'exotic';
-    } else {
-      ({latest, wanted} = await config.registries[locked.registry].checkOutdated(config, name, normalized.range));
-    }
+  const deps = await PackageRequest.getOutdatedPackages(lockfile, install, config, reporter);
 
-    return ({name, current, wanted, latest, hint});
-  }));
-
-  const isDepOld = ({latest, current}) => latest !== 'exotic' && semver.lt(current, latest);
-  const isDepExpected = ({current, wanted}) => current === wanted;
-  const orderByExpected = (depA, depB) => isDepExpected(depA) && !isDepExpected(depB) ? 1 : -1;
-
-  const outdatedDeps = allDeps.filter(isDepOld).sort(orderByExpected);
-
-  if (!outdatedDeps.length) {
+  if (!deps.length) {
     reporter.success(reporter.lang('allDependenciesUpToDate'));
     return;
   }
@@ -93,7 +56,7 @@ export async function run(
   const getNameFromHint = (hint) => hint ? `${hint}Dependencies` : 'dependencies';
 
   const maxLengthArr = {name: 0, current: 0, latest: 0};
-  outdatedDeps.forEach((dep) =>
+  deps.forEach((dep) =>
     ['name', 'current', 'latest'].forEach((key) => {
       maxLengthArr[key] = Math.max(maxLengthArr[key], dep[key].length);
     }),
@@ -106,15 +69,26 @@ export async function run(
   const colorizeName = ({current, wanted}) =>
     (current === wanted) ? reporter.format.yellow : reporter.format.red;
 
+  const colorizeDiff = (from, to) => {
+    const parts = to.split('.');
+    const fromParts = from.split('.');
+
+    const index = parts.findIndex((part, i) => part !== fromParts[i]);
+    const splitIndex = index >= 0 ? index : parts.length;
+
+    const colorized = reporter.format.green(parts.slice(splitIndex).join('.'));
+    return parts.slice(0, splitIndex).concat(colorized).join('.');
+  };
+
   const makeRow = (dep) => {
     const padding = addPadding(dep);
     const name = colorizeName(dep)(padding('name'));
     const current = reporter.format.blue(padding('current'));
-    const latest = reporter.format.green(padding('latest'));
+    const latest = colorizeDiff(dep.current, padding('latest'));
     return `${name}  ${current}  ❯  ${latest}`;
   };
 
-  const groupedDeps = outdatedDeps.reduce((acc, dep) => {
+  const groupedDeps = deps.reduce((acc, dep) => {
     const {hint, name, latest} = dep;
     const key = getNameFromHint(hint);
     const xs = acc[key] || [];
diff --git a/src/cli/commands/why.js b/src/cli/commands/why.js
index cfeb07c..78ae997 100644
--- a/src/cli/commands/why.js
+++ b/src/cli/commands/why.js
@@ -142,7 +142,7 @@ export async function run(
   reporter.step(2, 4, reporter.lang('whyInitGraph'), emoji.get('truck'));
   const lockfile = await Lockfile.fromDirectory(config.cwd, reporter);
   const install = new Install(flags, config, reporter, lockfile);
-  const [depRequests, patterns] = await install.fetchRequestFromCwd();
+  const {requests: depRequests, patterns} = await install.fetchRequestFromCwd();
   await install.resolver.init(depRequests, install.flags.flat);
   const hoisted = await install.linker.getFlatHoistedTree(patterns);
 
diff --git a/src/cli/index.js b/src/cli/index.js
index 209c072..fe5cd6f 100644
--- a/src/cli/index.js
+++ b/src/cli/index.js
@@ -50,7 +50,7 @@ commander.option('--ignore-scripts', "don't run lifecycle scripts");
 commander.option('--har', 'save HAR output of network traffic');
 commander.option('--ignore-platform', 'ignore platform checks');
 commander.option('--ignore-engines', 'ignore engines check');
-commander.option('--ignore-optional', '');
+commander.option('--ignore-optional', 'ignore optional dependencies');
 commander.option('--force', 'ignore all caches');
 commander.option('--no-bin-links', "don't generate bin links when setting up packages");
 commander.option('--flat', 'only allow one version of a package');
@@ -199,6 +199,9 @@ let outputWrapper = true;
 if (typeof command.hasWrapper === 'function') {
   outputWrapper = command.hasWrapper(commander, commander.args);
 }
+if (commander.json) {
+  outputWrapper = false;
+}
 if (outputWrapper) {
   reporter.header(commandName, pkg);
 }
@@ -265,26 +268,28 @@ const runEventuallyWithNetwork = (mutexPort: ?string): Promise<void> => {
       port: +mutexPort || constants.SINGLE_INSTANCE_PORT,
     };
 
-    const clients = [];
-    const server = net.createServer((client: net$Socket) => {
-      clients.push(client);
-    });
+    const server = net.createServer();
 
     server.on('error', () => {
-      // another yarnn instance exists, let's connect to it to know when it dies.
+      // another Yarn instance exists, let's connect to it to know when it dies.
       reporter.warn(reporter.lang('waitingInstance'));
       const socket = net.createConnection(connectionOptions);
 
       socket
-        .on('data', () => {
-          // the server has informed us he's going to die soon™.
-          socket.unref(); // let it die
-          process.nextTick(() => {
-            ok(runEventuallyWithNetwork(mutexPort));
-          });
+        .on('connect', () => {
+          // Allow the program to exit if this is the only active server in the event system.
+          socket.unref();
+        })
+        .on('close', (hadError?: boolean) => {
+          // the `close` event gets always called after the `error` event
+          if (!hadError) {
+            process.nextTick(() => {
+              ok(runEventuallyWithNetwork(mutexPort));
+            });
+          }
         })
         .on('error', () => {
-          // No server to listen to ? :O let's retry to become the next server then.
+          // No server to listen to ? Let's retry to become the next server then.
           process.nextTick(() => {
             ok(runEventuallyWithNetwork(mutexPort));
           });
@@ -292,9 +297,6 @@ const runEventuallyWithNetwork = (mutexPort: ?string): Promise<void> => {
     });
 
     const onServerEnd = (): Promise<void> => {
-      clients.forEach((client) => {
-        client.write('closing. kthanx, bye.');
-      });
       server.close();
       return Promise.resolve();
     };
diff --git a/src/config.js b/src/config.js
index b8161fd..556a400 100644
--- a/src/config.js
+++ b/src/config.js
@@ -175,9 +175,6 @@ export default class Config {
     this._init(opts);
 
     await fs.mkdirp(this.globalFolder);
-    await fs.mkdirp(this.cacheFolder);
-    await fs.mkdirp(this.tempFolder);
-
     await fs.mkdirp(this.linkFolder);
     this.linkedModules = await fs.readdir(this.linkFolder);
 
@@ -203,6 +200,16 @@ export default class Config {
       cert: String(opts.cert || this.getOption('cert') || ''),
       key: String(opts.key || this.getOption('key') || ''),
     });
+
+    //init & create cacheFolder, tempFolder
+    this.cacheFolder = String(opts.cacheFolder || this.getOption('cache-folder') || constants.MODULE_CACHE_DIRECTORY);
+    this.tempFolder = opts.tempFolder || path.join(this.cacheFolder, '.tmp');
+    await fs.mkdirp(this.cacheFolder);
+    await fs.mkdirp(this.tempFolder);
+
+    if (this.getOption('production') || process.env.NODE_ENV === 'production') {
+      this.production = true;
+    }
   }
 
   _init(opts: ConfigOptions) {
@@ -221,9 +228,7 @@ export default class Config {
     this.preferOffline = !!opts.preferOffline;
     this.modulesFolder = opts.modulesFolder;
     this.globalFolder = opts.globalFolder || constants.GLOBAL_MODULE_DIRECTORY;
-    this.cacheFolder = opts.cacheFolder || constants.MODULE_CACHE_DIRECTORY;
     this.linkFolder = opts.linkFolder || constants.LINK_REGISTRY_DIRECTORY;
-    this.tempFolder = opts.tempFolder || path.join(this.cacheFolder, '.tmp');
     this.production = !!opts.production;
     this.offline = !!opts.offline;
     this.binLinks = !!opts.binLinks;
@@ -363,7 +368,8 @@ export default class Config {
   }
 
   /**
-   * Read normalized package info.
+   * Read normalized package info according yarn-metadata.json
+   * throw an error if package.json was not found 
    */
 
   async readManifest(dir: string, priorityRegistry?: RegistryNames, isRoot?: boolean = false): Promise<Manifest> {
@@ -376,6 +382,11 @@ export default class Config {
     }
   }
 
+ /**
+ * try get the manifest file by looking 
+ * 1. mainfest fiel in cache 
+ * 2. manifest file in registry
+ */
   maybeReadManifest(dir: string, priorityRegistry?: RegistryNames, isRoot?: boolean = false): Promise<?Manifest> {
     return this.getCache(`manifest-${dir}`, async (): Promise<?Manifest> => {
       const metadataLoc = path.join(dir, constants.METADATA_FILENAME);
@@ -400,6 +411,7 @@ export default class Config {
           return file;
         }
       }
+
       return null;
     });
   }
@@ -485,7 +497,7 @@ export default class Config {
         }
       }
 
-      await fs.writeFile(loc, JSON.stringify(object, null, indent || constants.DEFAULT_INDENT) + '\n');
+      await fs.writeFilePreservingEol(loc, JSON.stringify(object, null, indent || constants.DEFAULT_INDENT) + '\n');
     }
   }
 
diff --git a/src/constants.js b/src/constants.js
index f73f9ce..72ee138 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -88,3 +88,16 @@ export function getPathKey(platform: string, env: Env): string {
 
   return pathKey;
 }
+
+function getUid(): ?number {
+  if (process.platform !== 'win32' && process.getuid) {
+    return process.getuid();
+  }
+  return null;
+}
+
+export const ROOT_USER = isRootUser(getUid());
+
+export function isRootUser(uid: ?number): boolean {
+  return uid === 0;
+}
diff --git a/src/fetchers/tarball-fetcher.js b/src/fetchers/tarball-fetcher.js
index 46b0d14..4008432 100644
--- a/src/fetchers/tarball-fetcher.js
+++ b/src/fetchers/tarball-fetcher.js
@@ -1,5 +1,6 @@
 /* @flow */
 
+import http from 'http';
 import {SecurityError, MessageError} from '../errors.js';
 import type {FetchedOverride} from '../types.js';
 import {UnpackStream} from '../util/stream.js';
@@ -81,6 +82,12 @@ export default class TarballFetcher extends BaseFetcher {
     extractorStream
       .pipe(untarStream)
       .on('error', reject)
+      .on('entry', (entry: Object) => {
+        if (constants.ROOT_USER) {
+          entry.props.uid = entry.uid = 0;
+          entry.props.gid = entry.gid = 0;
+        }
+      })
       .on('end', () => {
         const expectHash = this.hash;
         const actualHash = validateStream.getHash();
@@ -151,6 +158,7 @@ export default class TarballFetcher extends BaseFetcher {
       },
       buffer: true,
       process: (req, resolve, reject) => {
+        const {reporter} = this.config;
         // should we save this to the offline cache?
         const mirrorPath = this.getMirrorPath();
         const tarballStorePath = path.join(this.dest, constants.TARBALL_FILENAME);
@@ -164,7 +172,17 @@ export default class TarballFetcher extends BaseFetcher {
           extractorStream,
         } = this.createExtractor(overwriteResolved, resolve, reject);
 
-        //
+        const handleRequestError = (res) => {
+          if (res.statusCode >= 400) {
+            // $FlowFixMe
+            const statusDescription = http.STATUS_CODES[res.statusCode];
+            reject(new Error(
+              reporter.lang('requestFailed', `${res.statusCode} ${statusDescription}`),
+            ));
+          }
+        };
+
+        req.on('response', handleRequestError);
         req.pipe(validateStream);
 
         validateStream
diff --git a/src/lockfile/parse.js b/src/lockfile/parse.js
index b599c05..04da160 100644
--- a/src/lockfile/parse.js
+++ b/src/lockfile/parse.js
@@ -81,13 +81,19 @@ export function* tokenise(input: string): Iterator<Token> {
       }
     } else if (input[0] === '"') {
       let val = '';
+
       for (let i = 0; ; i++) {
-        const char = input[i];
-        val += char;
-        if (i > 0 && char === '"' && input[i - 1] !== "\\" && input[i - 2] !== "\\") {
-          break;
+        const currentChar = input[i];
+        val += currentChar;
+
+        if (i > 0 && currentChar === '"') {
+          const isEscaped = input[i - 1] === "\\" && input[i - 2] !== "\\";
+          if (!isEscaped) {
+            break;
+          }
         }
       }
+
       chop = val.length;
 
       try {
diff --git a/src/package-compatibility.js b/src/package-compatibility.js
index a0fab5e..64b1f82 100644
--- a/src/package-compatibility.js
+++ b/src/package-compatibility.js
@@ -4,7 +4,6 @@ import type PackageResolver from './package-resolver.js';
 import type {Reporter} from './reporters/index.js';
 import type {Manifest} from './types.js';
 import type Config from './config.js';
-import * as PackageReference from './package-reference.js';
 import {MessageError} from './errors.js';
 import map from './util/map.js';
 import {entries} from './util/misc.js';
@@ -126,7 +125,7 @@ export default class PackageCompatibility {
       invariant(ref, 'expected package reference');
 
       if (ref.optional) {
-        ref.addVisibility(PackageReference.ENVIRONMENT_IGNORE);
+        ref.ignore = true;
 
         reporter.warn(`${human}: ${msg}`);
         if (!didIgnore) {
diff --git a/src/package-hoister.js b/src/package-hoister.js
index ab1c363..f205ce8 100644
--- a/src/package-hoister.js
+++ b/src/package-hoister.js
@@ -13,7 +13,8 @@ type Parts = Array<string>;
 let historyCounter = 0;
 
 export class HoistManifest {
-  constructor(key: string, parts: Parts, pkg: Manifest, loc: string) {
+  constructor(key: string, parts: Parts, pkg: Manifest, loc: string, isIgnored: boolean) {
+    this.ignore = isIgnored;
     this.loc = loc;
     this.pkg = pkg;
 
@@ -26,6 +27,7 @@ export class HoistManifest {
     this.addHistory(`Start position = ${key}`);
   }
 
+  ignore: boolean;
   pkg: Manifest;
   loc: string;
   parts: Parts;
@@ -40,8 +42,7 @@ export class HoistManifest {
 }
 
 export default class PackageHoister {
-  constructor(config: Config, resolver: PackageResolver, ignoreOptional: boolean) {
-    this.ignoreOptional = ignoreOptional;
+  constructor(config: Config, resolver: PackageResolver) {
     this.resolver = resolver;
     this.config = config;
 
@@ -50,7 +51,6 @@ export default class PackageHoister {
     this.tree = new Map();
   }
 
-  ignoreOptional: boolean;
   resolver: PackageResolver;
   config: Config;
 
@@ -123,25 +123,28 @@ export default class PackageHoister {
    */
 
   _seed(pattern: string, parent?: HoistManifest): ?HoistManifest {
+    //
+    const pkg = this.resolver.getStrictResolvedPattern(pattern);
+    const ref = pkg._reference;
+    invariant(ref, 'expected reference');
+
+    //
     let parentParts: Parts = [];
+    let isIgnored = ref.ignore;
 
     if (parent) {
       if (!this.tree.get(parent.key)) {
         return null;
       }
+      isIgnored = isIgnored || parent.ignore;
       parentParts = parent.parts;
     }
 
     //
-    const pkg = this.resolver.getStrictResolvedPattern(pattern);
-    const ref = pkg._reference;
-    invariant(ref, 'expected reference');
-
-    //
     const loc: string = this.config.generateHardModulePath(ref);
     const parts = parentParts.concat(pkg.name);
     const key: string = this.implodeKey(parts);
-    const info: HoistManifest = new HoistManifest(key, parts, pkg, loc);
+    const info: HoistManifest = new HoistManifest(key, parts, pkg, loc, isIgnored);
 
     //
     this.tree.set(key, info);
@@ -178,6 +181,11 @@ export default class PackageHoister {
       const existing = this.tree.get(checkKey);
       if (existing) {
         if (existing.loc === info.loc) {
+          // deduping an unignored reference to an ignored one
+          if (existing.ignore && !info.ignore) {
+            existing.ignore = false;
+          }
+
           existing.addHistory(`Deduped ${fullKey} to this item`);
           return {parts: checkParts, duplicate: true};
         } else {
@@ -349,7 +357,7 @@ export default class PackageHoister {
     for (const [key, info] of this.tree.entries()) {
       // decompress the location and push it to the flat tree. this path could be made
       // up of modules from different registries so we need to handle this specially
-      const parts = [];
+      const parts: Array<string> = [];
       const keyParts = key.split('#');
       for (let i = 0; i < keyParts.length; i++) {
         const key = keyParts.slice(0, i + 1).join('#');
@@ -363,13 +371,15 @@ export default class PackageHoister {
         // remove the first part which will be the folder name and replace it with a
         // hardcoded modules folder
         parts.shift();
-        parts.unshift(this.config.modulesFolder);
+        const modulesFolder = (this.config.modulesFolder == null) ? '' : this.config.modulesFolder;
+        parts.unshift(modulesFolder);
       } else {
         // first part will be the registry-specific module folder
-        parts.unshift(this.config.cwd);
+        const cwd = (this.config.cwd == null) ? '' : this.config.cwd;
+        parts.unshift(cwd);
       }
 
-      const loc = parts.join(path.sep);
+      const loc = path.join(...parts);
       flatTree.push([loc, info]);
     }
 
@@ -379,11 +389,7 @@ export default class PackageHoister {
       const ref = info.pkg._reference;
       invariant(ref, 'expected reference');
 
-      let ignored = ref.ignore;
-      if (ref.optional && this.ignoreOptional) {
-        ignored = true;
-      }
-      if (ignored) {
+      if (info.ignore) {
         info.addHistory('Deleted as this module was ignored');
       } else {
         visibleFlatTree.push([loc, info]);
diff --git a/src/package-install-scripts.js b/src/package-install-scripts.js
index ad516af..bb87b31 100644
--- a/src/package-install-scripts.js
+++ b/src/package-install-scripts.js
@@ -110,6 +110,7 @@ export default class PackageInstallScripts {
       invariant(ref, 'expected reference');
 
       if (ref.optional) {
+        ref.ignore = true;
         this.reporter.error(this.reporter.lang('optionalModuleScriptFail', err.message));
         this.reporter.info(this.reporter.lang('optionalModuleFail'));
       } else {
diff --git a/src/package-linker.js b/src/package-linker.js
index b637348..fb5a3d8 100644
--- a/src/package-linker.js
+++ b/src/package-linker.js
@@ -33,14 +33,12 @@ export async function linkBin(src: string, dest: string): Promise<void> {
 }
 
 export default class PackageLinker {
-  constructor(config: Config, resolver: PackageResolver, ignoreOptional: boolean) {
-    this.ignoreOptional = ignoreOptional;
+  constructor(config: Config, resolver: PackageResolver) {
     this.resolver = resolver;
     this.reporter = config.reporter;
     this.config = config;
   }
 
-  ignoreOptional: boolean;
   reporter: Reporter;
   resolver: PackageResolver;
   config: Config;
@@ -109,7 +107,7 @@ export default class PackageLinker {
   }
 
   getFlatHoistedTree(patterns: Array<string>): Promise<HoistManifestTuples> {
-    const hoister = new PackageHoister(this.config, this.resolver, this.ignoreOptional);
+    const hoister = new PackageHoister(this.config, this.resolver);
     hoister.seed(patterns);
     return Promise.resolve(hoister.init());
   }
@@ -150,15 +148,23 @@ export default class PackageLinker {
       });
     }
 
-    // register root packages as being possibly extraneous
+    // register root & scoped packages as being possibly extraneous
     const possibleExtraneous: Set<string> = new Set();
     for (const folder of this.config.registryFolders) {
       const loc = path.join(this.config.cwd, folder);
 
       if (await fs.exists(loc)) {
         const files = await fs.readdir(loc);
+        let filepath;
         for (const file of files) {
-          possibleExtraneous.add(path.join(loc, file));
+          filepath = path.join(loc, file);
+          possibleExtraneous.add(filepath);
+          if (file[0] === '@') { // it's a scope, not a package
+            const subfiles = await fs.readdir(filepath);
+            for (const subfile of subfiles) {
+              possibleExtraneous.add(path.join(filepath, subfile));
+            }
+          }
         }
       }
     }
diff --git a/src/package-reference.js b/src/package-reference.js
index a756837..7f72e37 100644
--- a/src/package-reference.js
+++ b/src/package-reference.js
@@ -8,14 +8,6 @@ import type PackageResolver from './package-resolver.js';
 import type {RegistryNames} from './registries/index.js';
 import {entries} from './util/misc.js';
 
-const invariant = require('invariant');
-
-export const ENVIRONMENT_IGNORE = 'ENVIRONMENT_IGNORE';
-export const REMOVED_ANCESTOR = 'REMOVED_ANCESTOR';
-export const USED = 'USED';
-
-export type VisibilityAction = 'ENVIRONMENT_IGNORE' | 'REMOVED_ANCESTOR' | 'USED';
-
 export default class PackageReference {
   constructor(
     request: PackageRequest,
@@ -39,7 +31,6 @@ export default class PackageReference {
     this.permissions = {};
     this.patterns = [];
     this.optional = null;
-    this.visibility = {[ENVIRONMENT_IGNORE]: 0, [REMOVED_ANCESTOR]: 0, [USED]: 0};
     this.root = false;
     this.ignore = false;
     this.fresh = false;
@@ -56,7 +47,6 @@ export default class PackageReference {
   version: string;
   uid: string;
   optional: ?boolean;
-  visibility: {[action: string]: number};
   ignore: boolean;
   fresh: boolean;
   dependencies: Array<string>;
@@ -129,43 +119,4 @@ export default class PackageReference {
       this.optional = false;
     }
   }
-
-  calculateVisibility() {
-    let nowIgnore = false;
-    const stack = this.visibility;
-
-    // if we don't use this module then mark it as ignored
-    if (stack[USED] === 0) {
-      nowIgnore = true;
-    }
-
-    // if we have removed as many ancestors as it's used then it's out of the tree
-    if (stack[REMOVED_ANCESTOR] >= stack[USED]) {
-      nowIgnore = true;
-    }
-
-    this.ignore = nowIgnore;
-  }
-
-  addVisibility(action: VisibilityAction, ancestry?: Set<PackageReference> = new Set()) {
-    this.visibility[action]++;
-    this.calculateVisibility();
-
-    if (ancestry.has(this)) {
-      return;
-    }
-    ancestry.add(this);
-
-    // go through and update all transitive dependencies to be ignored
-    for (const pattern of this.dependencies) {
-      const pkg = this.resolver.getResolvedPattern(pattern);
-      if (!pkg) {
-        continue;
-      }
-
-      const ref = pkg._reference;
-      invariant(ref, 'expected package reference');
-      ref.addVisibility(action, ancestry);
-    }
-  }
 }
diff --git a/src/package-request.js b/src/package-request.js
index 23c245a..ff49751 100644
--- a/src/package-request.js
+++ b/src/package-request.js
@@ -1,13 +1,13 @@
 /* @flow */
 
-import type {DependencyRequestPattern, Manifest} from './types.js';
+import type {Dependency, DependencyRequestPattern, Manifest} from './types.js';
 import type PackageResolver from './package-resolver.js';
 import type {Reporter} from './reporters/index.js';
 import type Config from './config.js';
-import type {VisibilityAction} from './package-reference.js';
+import type {Install} from './cli/commands/install';
 import {cleanDependencies} from './util/normalize-manifest/validate.js';
 import Lockfile from './lockfile/wrapper.js';
-import {USED as USED_VISIBILITY, default as PackageReference} from './package-reference.js';
+import PackageReference from './package-reference.js';
 import {registries as registryResolvers} from './resolvers/index.js';
 import {MessageError} from './errors.js';
 import {entries} from './util/misc.js';
@@ -16,13 +16,13 @@ import * as versionUtil from './util/version.js';
 import * as resolvers from './resolvers/index.js';
 
 const invariant = require('invariant');
+const semver = require('semver');
 
 type ResolverRegistryNames = $Keys<typeof registryResolvers>;
 
 export default class PackageRequest {
   constructor(req: DependencyRequestPattern, resolver: PackageResolver) {
     this.parentRequest = req.parentRequest;
-    this.visibility = req.visibility;
     this.lockfile = resolver.lockfile;
     this.registry = req.registry;
     this.reporter = resolver.reporter;
@@ -50,7 +50,6 @@ export default class PackageRequest {
   pattern: string;
   config: Config;
   registry: ResolverRegistryNames;
-  visibility: VisibilityAction;
   optional: boolean;
 
   getParentNames(): Array<string> {
@@ -242,7 +241,6 @@ export default class PackageRequest {
     const ref = new PackageReference(this, info, remote);
     ref.addPattern(this.pattern, info);
     ref.addOptional(this.optional);
-    ref.addVisibility(this.visibility);
     info._reference = ref;
     info._remote = remote;
 
@@ -257,7 +255,6 @@ export default class PackageRequest {
       promises.push(this.resolver.find({
         pattern: depPattern,
         registry: remote.registry,
-        visibility: USED_VISIBILITY,
         optional: false,
         parentRequest: this,
       }));
@@ -270,7 +267,6 @@ export default class PackageRequest {
       promises.push(this.resolver.find({
         pattern: depPattern,
         registry: remote.registry,
-        visibility: USED_VISIBILITY,
         optional: true,
         parentRequest: this,
       }));
@@ -279,10 +275,9 @@ export default class PackageRequest {
     await Promise.all(promises);
     ref.addDependencies(deps);
 
-    // Now that we have all dependencies, it's safe to propagate optional & visibility
+    // Now that we have all dependencies, it's safe to propagate optional
     for (const otherRequest of ref.requests.slice(1)) {
       ref.addOptional(otherRequest.optional);
-      ref.addVisibility(otherRequest.visibility);
     }
   }
 
@@ -311,4 +306,52 @@ export default class PackageRequest {
     // TODO possibly reconsider this behaviour
     return info.version === undefined ? info._uid : info.version;
   }
+
+  /**
+   * Gets all of the outdated packages and sorts them appropriately
+   */
+
+  static async getOutdatedPackages(
+    lockfile: Lockfile,
+    install: Install,
+    config: Config,
+    reporter: Reporter,
+  ): Promise<Array<Dependency>> {
+    const {requests: depReqPatterns} = await install.fetchRequestFromCwd();
+
+    const deps = await Promise.all(
+      depReqPatterns.map(async ({pattern, hint}): Promise<Dependency> => {
+        const locked = lockfile.getLocked(pattern);
+        if (!locked) {
+          throw new MessageError(reporter.lang('lockfileOutdated'));
+        }
+
+        const {name, version: current} = locked;
+        let latest = '';
+        let wanted = '';
+
+        const normalized = PackageRequest.normalizePattern(pattern);
+
+        if (PackageRequest.getExoticResolver(pattern) ||
+            PackageRequest.getExoticResolver(normalized.range)) {
+          latest = wanted = 'exotic';
+        } else {
+          const registry = config.registries[locked.registry];
+
+          ({latest, wanted} = await registry.checkOutdated(config, name, normalized.range));
+        }
+
+        return ({name, current, wanted, latest, hint});
+      }),
+    );
+
+    // Make sure to always output `exotic` versions to be compatible with npm
+    const isDepOld = ({current, latest, wanted}) => latest === 'exotic' || (
+      latest !== 'exotic' && (semver.lt(current, wanted) || semver.lt(current, latest))
+    );
+    const isDepExpected = ({current, wanted}) => current === wanted;
+    const orderByExpected = (depA, depB) => isDepExpected(depA) && !isDepExpected(depB) ? 1 : -1;
+
+    return deps.filter(isDepOld).sort(orderByExpected);
+  }
 }
diff --git a/src/package-resolver.js b/src/package-resolver.js
index ca4a161..4cca3a7 100644
--- a/src/package-resolver.js
+++ b/src/package-resolver.js
@@ -5,7 +5,6 @@ import type {RegistryNames} from './registries/index.js';
 import type PackageReference from './package-reference.js';
 import type {Reporter} from './reporters/index.js';
 import type Config from './config.js';
-import {REMOVED_ANCESTOR} from './package-reference.js';
 import PackageRequest from './package-request.js';
 import RequestManager from './util/request-manager.js';
 import BlockingQueue from './util/blocking-queue.js';
@@ -311,13 +310,8 @@ export default class PackageResolver {
       const ref = this.getStrictResolvedPattern(pattern)._reference;
       invariant(ref, 'expected package reference');
       const refPatterns = ref.patterns.slice();
-      ref.addVisibility(REMOVED_ANCESTOR);
       ref.prune();
 
-      for (const action in ref.visibility) {
-        collapseToReference.visibility[action] += ref.visibility[action];
-      }
-
       // add pattern to the manifest we're collapsing to
       for (const pattern of refPatterns) {
         collapseToReference.addPattern(pattern, collapseToManifest);
@@ -444,12 +438,6 @@ export default class PackageResolver {
       this.newPatterns.push(req.pattern);
     }
 
-    // propagate `visibility` option
-    const {parentRequest} = req;
-    if (parentRequest && parentRequest.visibility) {
-      req.visibility = parentRequest.visibility;
-    }
-
     const request = new PackageRequest(req, this);
     await request.find();
   }
diff --git a/src/registries/base-registry.js b/src/registries/base-registry.js
index ea47bad..9e1c1dd 100644
--- a/src/registries/base-registry.js
+++ b/src/registries/base-registry.js
@@ -64,6 +64,16 @@ export default class BaseRegistry {
     return this.config[key];
   }
 
+  getAvailableRegistries(): Array<string> {
+    const config = this.config;
+    return Object.keys(config).reduce((registries, option) => {
+      if (option === 'registry' || option.split(':')[1] === 'registry') {
+        registries.push(config[option]);
+      }
+      return registries;
+    }, []);
+  }
+
   loadConfig(): Promise<void> {
     return Promise.resolve();
   }
diff --git a/src/registries/npm-registry.js b/src/registries/npm-registry.js
index c696fe8..437c304 100644
--- a/src/registries/npm-registry.js
+++ b/src/registries/npm-registry.js
@@ -143,7 +143,15 @@ export default class NpmRegistry extends Registry {
   }
 
   getRegistry(packageName: string): string {
-    // Try scoped registry, and default registry
+    // Try extracting registry from the url, then scoped registry, and default registry
+    if (packageName.match(/^https?:/)) {
+      const availableRegistries = this.getAvailableRegistries();
+      const registry = availableRegistries.find((registry) => packageName.startsWith(registry));
+      if (registry) {
+        return registry;
+      }
+    }
+
     for (const scope of [this.getScope(packageName), '']) {
       const registry = this.getScopedOption(scope, 'registry')
                     || this.registries.yarn.getScopedOption(scope, 'registry');
diff --git a/src/registries/yarn-registry.js b/src/registries/yarn-registry.js
index f34f897..09fcaa4 100644
--- a/src/registries/yarn-registry.js
+++ b/src/registries/yarn-registry.js
@@ -114,6 +114,6 @@ export default class YarnRegistry extends NpmRegistry {
       this.homeConfig[key] = config[key];
     }
 
-    await fs.writeFile(this.homeConfigLoc, `${stringify(this.homeConfig)}\n`);
+    await fs.writeFilePreservingEol(this.homeConfigLoc, `${stringify(this.homeConfig)}\n`);
   }
 }
diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js
index 81c1d31..daa2231 100644
--- a/src/reporters/lang/en.js
+++ b/src/reporters/lang/en.js
@@ -29,8 +29,8 @@ const messages = {
   manifestLicenseInvalid: 'License should be a valid SPDX license expression',
   manifestLicenseNone: 'No license field',
   manifestStringExpected: '$0 is not a string',
-  manifestDependencyBuiltin: 'Dependency $0 listed in $1 is the name of a built-in module',
   manifestDependencyCollision: '$0 has dependency $1 with range $2 that collides with a dependency in $3 of the same name with version $4',
+  manifestDirectoryNotFound: 'Unable to read $0 directory of module $1',
 
   verboseFileCopy: 'Copying $0 to $1.',
   verboseFileSymlink: 'Creating symlink at $0 to $1.',
@@ -89,6 +89,10 @@ const messages = {
   noFilePermission: "We don't have permissions to touch the file $0.",
   allDependenciesUpToDate: 'All of your dependencies are up to date.',
 
+  yarnOutdated: "Your current version of Yarn is out of date. The latest version is $0 while you're on $1.",
+  yarnOutdatedInstaller: 'To upgrade, download the latest installer at $0.',
+  yarnOutdatedCommand: 'To upgrade, run the following command:',
+
   tooManyArguments: 'Too many arguments, maximum of $0.',
   tooFewArguments: 'Not enough arguments, expected at least $0.',
   noArguments: "This command doesn't require any arguments.",
@@ -217,16 +221,18 @@ const messages = {
   publishing: 'Publishing',
 
   infoFail: 'Received invalid response from npm.',
-  malformedRegistryResponse: 'Received malformed response from registry. The registry may be down.',
+  malformedRegistryResponse: 'Received malformed response from registry for $0. The registry may be down.',
 
   cantRequestOffline: 'Can\'t make a request in offline mode',
   requestManagerNotSetupHAR: 'RequestManager was not setup to capture HAR files',
   requestError: 'Request $0 returned a $1',
+  requestFailed: 'Request failed $0',
   tarballNotInNetworkOrCache: '$0: Tarball is not in network and can not be located in cache ($1)',
   fetchBadHash: 'Bad hash. Expected $0 but got $1 ',
   fetchErrorCorrupt: '$0. Mirror tarball appears to be corrupt. You can resolve this by running:\n\n  $ rm -rf $1\n  $ yarn install',
   errorDecompressingTarball: '$0. Error decompressing $1, it appears to be corrupt.',
   updateInstalling: 'Installing $0...',
+  hostedGitResolveError: 'Error connecting to repository. Please, check the url.',
 };
 
 export type LanguageKeys = $Keys<typeof messages>;
diff --git a/src/resolvers/exotics/file-resolver.js b/src/resolvers/exotics/file-resolver.js
index 7f2f89e..e0e63a3 100644
--- a/src/resolvers/exotics/file-resolver.js
+++ b/src/resolvers/exotics/file-resolver.js
@@ -10,6 +10,10 @@ import * as fs from '../../util/fs.js';
 const invariant = require('invariant');
 const path = require('path');
 
+type Dependencies = {
+  [key: string]: string
+};
+
 export default class FileResolver extends ExoticResolver {
   constructor(request: PackageRequest, fragment: string) {
     super(request, fragment);
@@ -42,6 +46,40 @@ export default class FileResolver extends ExoticResolver {
 
     manifest._uid = manifest.version;
 
-    return manifest;
+    // Normalize relative paths; if anything changes, make a copy of the manifest
+    const dependencies = this.normalizeDependencyPaths(manifest.dependencies, loc);
+    const optionalDependencies = this.normalizeDependencyPaths(manifest.optionalDependencies, loc);
+    
+    if (dependencies !== manifest.dependencies || optionalDependencies !== manifest.optionalDependencies) {
+      const _manifest = Object.assign({}, manifest);
+      if (dependencies != null) {
+        _manifest.dependencies = dependencies;
+      }
+      if (optionalDependencies != null) {
+        _manifest.optionalDependencies = optionalDependencies;
+      }
+      return _manifest;
+    } else {
+      return manifest;
+    }
+  }
+
+  normalizeDependencyPaths(section: ?Dependencies, loc: string): ?Dependencies {
+    if (section == null) {
+      return section;
+    }
+
+    let temp = section;
+
+    for (const [k, v] of util.entries(section)) {
+      if (typeof v === 'string' && v.startsWith('file:') && !path.isAbsolute(v)) {
+        if (temp === section) {
+          temp = Object.assign({}, section);
+        }
+        temp[k] = `file:${path.relative(this.config.cwd, path.join(loc, util.removePrefix(v, 'file:')))}`;
+      }
+    }
+
+    return temp;
   }
 }
diff --git a/src/resolvers/exotics/hosted-git-resolver.js b/src/resolvers/exotics/hosted-git-resolver.js
index bee1d62..76bf36d 100644
--- a/src/resolvers/exotics/hosted-git-resolver.js
+++ b/src/resolvers/exotics/hosted-git-resolver.js
@@ -102,7 +102,7 @@ export default class HostedGitResolver extends ExoticResolver {
 
       out = lines.join('\n');
     } else {
-      throw new Error('TODO');
+      throw new Error(this.reporter.lang('hostedGitResolveError'));
     }
 
     const refs = Git.parseRefs(out);
diff --git a/src/resolvers/exotics/tarball-resolver.js b/src/resolvers/exotics/tarball-resolver.js
index d8ecc7e..c974f84 100644
--- a/src/resolvers/exotics/tarball-resolver.js
+++ b/src/resolvers/exotics/tarball-resolver.js
@@ -37,7 +37,7 @@ export default class TarballResolver extends ExoticResolver {
 
     // local file reference - ignore patterns with names
     if (pattern.indexOf('@') < 0) {
-      if (pattern.endsWith('.tgz') || pattern.endsWith('tar.gz')) {
+      if (pattern.endsWith('.tgz') || pattern.endsWith('.tar.gz')) {
         return true;
       }
     }
diff --git a/src/resolvers/registries/npm-resolver.js b/src/resolvers/registries/npm-resolver.js
index 2eb4bdf..e5fd645 100644
--- a/src/resolvers/registries/npm-resolver.js
+++ b/src/resolvers/registries/npm-resolver.js
@@ -26,7 +26,7 @@ export default class NpmResolver extends RegistryResolver {
 
   static async findVersionInRegistryResponse(config: Config, range: string, body: RegistryResponse): Promise<Manifest> {
     if (!body['dist-tags']) {
-      throw new MessageError(config.reporter.lang('malformedRegistryResponse'));
+      throw new MessageError(config.reporter.lang('malformedRegistryResponse', body.name));
     }
 
     if (range in body['dist-tags']) {
diff --git a/src/types.js b/src/types.js
index 9b0c96c..02c9cfe 100644
--- a/src/types.js
+++ b/src/types.js
@@ -2,7 +2,6 @@
 
 import type {RegistryNames} from './registries/index.js';
 import type PackageReference from './package-reference.js';
-import type {VisibilityAction} from './package-reference.js';
 import type PackageRequest from './package-request.js';
 import type {FetcherNames} from './fetchers/index.js';
 import type {Reporter} from './reporters/index.js';
@@ -24,7 +23,6 @@ export type DependencyRequestPattern = {
   pattern: string,
   registry: RegistryNames,
   optional: boolean,
-  visibility: VisibilityAction,
   hint?: ?string,
   parentRequest?: ?PackageRequest,
 };
@@ -136,3 +134,12 @@ export type FetchedOverride = {
   hash: string,
   resolved: ?string,
 };
+
+// Used by outdated and upgrade-interactive
+export type Dependency = {
+  name: string,
+  current: string,
+  wanted: string,
+  latest: string,
+  hint: ?string
+};
diff --git a/src/util/fs.js b/src/util/fs.js
index af62978..19c57a9 100644
--- a/src/util/fs.js
+++ b/src/util/fs.js
@@ -8,6 +8,7 @@ import map from './map.js';
 
 const path = require('path');
 const fs = require('fs');
+const os = require('os');
 
 export const lockQueue = new BlockingQueue('fs lock');
 
@@ -480,3 +481,32 @@ export async function getFileSizeOnDisk(loc: string): Promise<number> {
 export function normalizeOS(body: string): string {
   return body.replace(/\r\n/g, '\n');
 }
+
+const cr = new Buffer('\r', 'utf8')[0];
+const lf = new Buffer('\n', 'utf8')[0];
+
+async function getEolFromFile(path: string) : Promise<string | void>  {
+  if (!(await exists(path))) {
+    return undefined;
+  }
+
+  const buffer = await readFileBuffer(path);
+
+  for (let i = 0; i < buffer.length; ++i) {
+    if (buffer[i] === cr) {
+      return '\r\n';
+    }
+    if (buffer[i] === lf) {
+      return '\n';
+    }
+  }
+  return undefined;
+}
+
+export async function writeFilePreservingEol(path: string, data: string) : Promise<void> {
+  const eol = (await getEolFromFile(path)) || os.EOL;
+  if (eol !== '\n') {
+    data = data.replace(/\n/g, eol);
+  }
+  await promisify(fs.writeFile)(path, data);
+}
diff --git a/src/util/normalize-manifest/fix.js b/src/util/normalize-manifest/fix.js
index a7ec079..0d3a398 100644
--- a/src/util/normalize-manifest/fix.js
+++ b/src/util/normalize-manifest/fix.js
@@ -20,10 +20,13 @@ type Dict<T> = {
   [key: string]: T;
 };
 
+type WarnFunction = (msg: string) => void;
+
 export default async function (
   info: Dict<mixed>,
   moduleLoc: string,
   reporter: Reporter,
+  warn: WarnFunction,
   looseSemver: boolean,
 ): Promise<void> {
   const files = await fs.readdir(moduleLoc);
@@ -190,12 +193,17 @@ export default async function (
 
     if (!info.bin && binDir && typeof binDir === 'string') {
       const bin = info.bin = {};
+      const fullBinDir = path.join(moduleLoc, binDir);
 
-      for (const scriptName of await fs.readdir(path.join(moduleLoc, binDir))) {
-        if (scriptName[0] === '.') {
-          continue;
+      if (await fs.exists(fullBinDir)) {
+        for (const scriptName of await fs.readdir(fullBinDir)) {
+          if (scriptName[0] === '.') {
+            continue;
+          }
+          bin[scriptName] = path.join('.', binDir, scriptName);
         }
-        bin[scriptName] = path.join('.', binDir, scriptName);
+      } else {
+        warn(reporter.lang('manifestDirectoryNotFound', binDir, info.name));
       }
     }
 
@@ -203,11 +211,16 @@ export default async function (
 
     if  (!info.man && typeof manDir === 'string') {
       const man = info.man = [];
+      const fullManDir = path.join(moduleLoc, manDir);
 
-      for (const filename of await fs.readdir(path.join(moduleLoc, manDir))) {
-        if (/^(.*?)\.[0-9]$/.test(filename)) {
-          man.push(path.join('.', manDir, filename));
+      if (await fs.exists(fullManDir)) {
+        for (const filename of await fs.readdir(fullManDir)) {
+          if (/^(.*?)\.[0-9]$/.test(filename)) {
+            man.push(path.join('.', manDir, filename));
+          }
         }
+      } else {
+        warn(reporter.lang('manifestDirectoryNotFound', manDir, info.name));
       }
     }
   }
diff --git a/src/util/normalize-manifest/index.js b/src/util/normalize-manifest/index.js
index a207d92..868dfa2 100644
--- a/src/util/normalize-manifest/index.js
+++ b/src/util/normalize-manifest/index.js
@@ -13,8 +13,6 @@ export default async function (
   config: Config,
   isRoot: boolean,
 ): Promise<Manifest> {
-  await fix(info, moduleLoc, config.reporter, config.looseSemver);
-
   // create human readable name
   const {name, version} = info;
   let human: ?string;
@@ -35,6 +33,7 @@ export default async function (
     config.reporter.warn(msg);
   }
 
+  await fix(info, moduleLoc, config.reporter, warn, config.looseSemver);
   try {
     validate(info, isRoot, config.reporter, warn);
   } catch (err) {
diff --git a/src/util/normalize-manifest/validate.js b/src/util/normalize-manifest/validate.js
index 8f4fe59..f78ee56 100644
--- a/src/util/normalize-manifest/validate.js
+++ b/src/util/normalize-manifest/validate.js
@@ -111,17 +111,6 @@ export function cleanDependencies(info: Object, isRoot: boolean, reporter: Repor
     depTypes.push([type, deps]);
   }
 
-  // check root dependencies for builtin module names
-  if (isRoot) {
-    for (const [type, deps] of depTypes) {
-      for (const name in deps) {
-        if (isBuiltinModule(name)) {
-          warn(reporter.lang('manifestDependencyBuiltin', name, type));
-        }
-      }
-    }
-  }
-
   // ensure that dependencies don't have ones that can collide
   for (const [type, deps] of depTypes) {
     for (const name in deps) {
diff --git a/yarn.lock b/yarn.lock
index 5a7a15d..381e4b8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1,5 +1,7 @@
 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 # yarn lockfile v1
+
+
 abab@^1.0.0:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d"
@@ -36,7 +38,7 @@ acorn@^3.0.4, acorn@^3.2.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
 
-acorn@^4.0.1:
+acorn@^4.0.1, acorn at 4.X:
   version "4.0.3"
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.3.tgz#1a3e850b428e73ba6b09d1cc527f5aaad4d03ef1"
 
@@ -224,6 +226,10 @@ asynckit@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
 
+atob@~1.1.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773"
+
 aws-sign2@~0.6.0:
   version "0.6.0"
   resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
@@ -1329,6 +1335,10 @@ chokidar@^1.4.3, chokidar@^1.5.2:
   optionalDependencies:
     fsevents "^1.0.0"
 
+ci-info@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534"
+
 cipher-base@^1.0.0, cipher-base@^1.0.1:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07"
@@ -1463,7 +1473,7 @@ constants-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
 
-convert-source-map@^1.1.0:
+convert-source-map@^1.1.0, convert-source-map at 1.X:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.3.0.tgz#e9f3e9c6e2728efc2676696a70eb382f73106a67"
 
@@ -1523,6 +1533,15 @@ crypto-browserify@^3.11.0:
     public-encrypt "^4.0.0"
     randombytes "^2.0.0"
 
+css at 2.X:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc"
+  dependencies:
+    inherits "^2.0.1"
+    source-map "^0.1.38"
+    source-map-resolve "^0.3.0"
+    urix "^0.1.0"
+
 "cssom@>= 0.3.0 < 0.4.0", cssom at 0.3.x:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.1.tgz#c9e37ef2490e64f6d1baa10fda852257082c25d3"
@@ -1566,7 +1585,15 @@ death@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/death/-/death-1.0.0.tgz#4d46e15488d4b636b699f0671b04632d752fd2de"
 
-debug@^2.1.1, debug@^2.2.0, debug@~2.2.0:
+debug-fabulous at 0.0.X:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.0.4.tgz#fa071c5d87484685424807421ca4b16b0b1a0763"
+  dependencies:
+    debug "2.X"
+    lazy-debug-legacy "0.0.X"
+    object-assign "4.1.0"
+
+debug@^2.1.1, debug@^2.2.0, debug@~2.2.0, debug at 2.X:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
   dependencies:
@@ -1660,6 +1687,10 @@ detect-indent@^3.0.0, detect-indent@^3.0.1:
     minimist "^1.1.0"
     repeating "^1.1.0"
 
+detect-newline at 2.X:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+
 detective@^4.3.1:
   version "4.3.1"
   resolved "https://registry.yarnpkg.com/detective/-/detective-4.3.1.tgz#9fb06dd1ee8f0ea4dbcc607cda39d9ce1d4f726f"
@@ -1700,6 +1731,15 @@ duplexer2 at 0.0.2:
   dependencies:
     readable-stream "~1.1.9"
 
+duplexify@^3.4.2:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604"
+  dependencies:
+    end-of-stream "1.0.0"
+    inherits "^2.0.1"
+    readable-stream "^2.0.0"
+    stream-shift "^1.0.0"
+
 ecc-jsbn@~0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
@@ -1731,6 +1771,12 @@ end-of-stream@~0.1.5:
   dependencies:
     once "~1.3.0"
 
+end-of-stream at 1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e"
+  dependencies:
+    once "~1.3.0"
+
 enhanced-resolve@^2.2.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-2.3.0.tgz#a115c32504b6302e85a76269d7a57ccdd962e359"
@@ -2149,6 +2195,10 @@ forever-agent@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
 
+fork-stream@^0.0.4:
+  version "0.0.4"
+  resolved "https://registry.yarnpkg.com/fork-stream/-/fork-stream-0.0.4.tgz#db849fce77f6708a5f8f386ae533a0907b54ae70"
+
 form-data@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.0.0.tgz#6f0aebadcc5da16c13e1ecc11137d85f9b883b25"
@@ -2384,6 +2434,10 @@ graceful-fs@~1.2.0:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364"
 
+graceful-fs at 4.X:
+  version "4.1.10"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.10.tgz#f2d720c22092f743228775c75e3612632501f131"
+
 "graceful-readlink@>= 1.0.0":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
@@ -2403,6 +2457,20 @@ gulp-babel@^6.0.0:
     through2 "^2.0.0"
     vinyl-sourcemaps-apply "^0.2.0"
 
+gulp-if:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/gulp-if/-/gulp-if-2.0.1.tgz#55f3edf82cecdfcf6035aa5d0686979aab0dac28"
+  dependencies:
+    gulp-match "^1.0.2"
+    ternary-stream "^2.0.0"
+    through2 "^2.0.1"
+
+gulp-match@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/gulp-match/-/gulp-match-1.0.2.tgz#f94c88e946f9faf8a50cb5a6e1b95cb5eeb33632"
+  dependencies:
+    minimatch "^3.0.0"
+
 gulp-newer@^1.0.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/gulp-newer/-/gulp-newer-1.3.0.tgz#d50ecacbb822eda492b57324a6c85a07fd9a55c1"
@@ -2418,6 +2486,21 @@ gulp-plumber@^1.0.1:
     gulp-util "^3"
     through2 "^2"
 
+gulp-sourcemaps:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.2.0.tgz#dea8a4dc9aa74630a04ae9cf1871a7a08bc1310d"
+  dependencies:
+    acorn "4.X"
+    convert-source-map "1.X"
+    css "2.X"
+    debug-fabulous "0.0.X"
+    detect-newline "2.X"
+    graceful-fs "4.X"
+    source-map "0.X"
+    strip-bom "3.X"
+    through2 "2.X"
+    vinyl "1.X"
+
 gulp-util@^3, gulp-util@^3.0.0, gulp-util@^3.0.6, gulp-util@^3.0.7:
   version "3.0.7"
   resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.7.tgz#78925c4b8f8b49005ac01a011c557e6218941cbb"
@@ -2698,7 +2781,13 @@ is-builtin-module@^1.0.0:
   dependencies:
     builtin-modules "^1.0.0"
 
-is-ci, is-ci@^1.0.9:
+is-ci:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e"
+  dependencies:
+    ci-info "^1.0.0"
+
+is-ci@^1.0.9:
   version "1.0.9"
   resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.9.tgz#de2c5ffe49ab3237fda38c47c8a3bbfd55bbcca7"
 
@@ -3248,6 +3337,10 @@ lazy-cache@^1.0.3:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
 
+lazy-debug-legacy at 0.0.X:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1"
+
 lcid@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
@@ -3596,6 +3689,12 @@ meow@^3.3.0:
     redent "^1.0.0"
     trim-newlines "^1.0.0"
 
+merge-stream@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.0.tgz#9cfd156fef35421e2b5403ce11dc6eb1962b026e"
+  dependencies:
+    readable-stream "^2.0.1"
+
 merge@^1.1.3:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.0.tgz#7531e39d4949c281a66b8c5a6e0265e8b05894da"
@@ -3859,7 +3958,7 @@ object-assign@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
 
-object-assign@^4.0.1, object-assign@^4.1.0:
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign at 4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0"
 
@@ -4421,6 +4520,10 @@ resolve-from@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
 
+resolve-url@~0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+
 resolve@^1.1.6, resolve@^1.1.7, resolve at 1.1.7, resolve at 1.1.x:
   version "1.1.7"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
@@ -4568,6 +4671,15 @@ source-list-map@~0.1.0:
   version "0.1.6"
   resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.6.tgz#e1e6f94f0b40c4d28dcf8f5b8766e0e45636877f"
 
+source-map-resolve@^0.3.0:
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761"
+  dependencies:
+    atob "~1.1.0"
+    resolve-url "~0.2.1"
+    source-map-url "~0.3.0"
+    urix "~0.1.0"
+
 source-map-support@^0.2.10:
   version "0.2.10"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.2.10.tgz#ea5a3900a1c1cb25096a0ae8cc5c2b4b10ded3dc"
@@ -4580,13 +4692,23 @@ source-map-support@^0.4.2:
   dependencies:
     source-map "^0.5.3"
 
+source-map-url@~0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9"
+
+source-map@^0.1.38:
+  version "0.1.43"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
+  dependencies:
+    amdefine ">=0.0.4"
+
 source-map@^0.4.4:
   version "0.4.4"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
   dependencies:
     amdefine ">=0.0.4"
 
-source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3:
+source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.3, source-map at 0.X:
   version "0.5.6"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
 
@@ -4661,6 +4783,10 @@ stream-consume@~0.1.0:
   version "0.1.0"
   resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f"
 
+stream-shift@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+
 string_decoder@~0.10.25, string_decoder@~0.10.x:
   version "0.10.31"
   resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
@@ -4715,7 +4841,7 @@ strip-bom@^2.0.0:
   dependencies:
     is-utf8 "^0.2.0"
 
-strip-bom@^3.0.0:
+strip-bom@^3.0.0, strip-bom at 3.X:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
 
@@ -4795,6 +4921,15 @@ temp@^0.8.3:
     os-tmpdir "^1.0.0"
     rimraf "~2.2.6"
 
+ternary-stream@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ternary-stream/-/ternary-stream-2.0.0.tgz#569fa9042b01456b7a1277c64f41d643d84570e6"
+  dependencies:
+    duplexify "^3.4.2"
+    fork-stream "^0.0.4"
+    merge-stream "^1.0.0"
+    through2 "^2.0.0"
+
 test-exclude@^2.1.1:
   version "2.1.3"
   resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-2.1.3.tgz#a8d8968e1da83266f9864f2852c55e220f06434a"
@@ -4828,7 +4963,7 @@ through2@^0.6.1:
     readable-stream ">=1.0.33-1 <1.1.0-0"
     xtend ">=4.0.0 <4.1.0-0"
 
-through2@^2, through2@^2.0.0:
+through2@^2, through2@^2.0.0, through2@^2.0.1, through2 at 2.X:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.1.tgz#384e75314d49f32de12eebb8136b8eb6b5d59da9"
   dependencies:
@@ -4934,6 +5069,10 @@ unique-stream@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b"
 
+urix@^0.1.0, urix@~0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+
 url@~0.11.0:
   version "0.11.0"
   resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
@@ -5025,7 +5164,7 @@ vinyl@^0.5.0:
     clone-stats "^0.0.1"
     replace-ext "0.0.1"
 
-vinyl@^1.1.0, vinyl@^1.2.0:
+vinyl@^1.1.0, vinyl@^1.2.0, vinyl at 1.X:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884"
   dependencies:
@@ -5174,6 +5313,25 @@ y18n@^3.2.0, y18n@^3.2.1:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
 
+yargs:
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.3.0.tgz#19c6dbb768744d571eb6ebae0c174cf2f71b188d"
+  dependencies:
+    camelcase "^3.0.0"
+    cliui "^3.2.0"
+    decamelize "^1.1.1"
+    get-caller-file "^1.0.1"
+    os-locale "^1.4.0"
+    read-pkg-up "^1.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^1.0.1"
+    set-blocking "^2.0.0"
+    string-width "^1.0.2"
+    which-module "^1.0.0"
+    window-size "^0.2.0"
+    y18n "^3.2.1"
+    yargs-parser "^4.0.2"
+
 yargs-parser@^2.4.1:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4"
@@ -5188,6 +5346,12 @@ yargs-parser@^3.2.0:
     camelcase "^3.0.0"
     lodash.assign "^4.1.0"
 
+yargs-parser@^4.0.2:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.0.2.tgz#7f7173a8c7cca1d81dc7c18692fc07c2c2e2b1e0"
+  dependencies:
+    camelcase "^3.0.0"
+
 yargs@^4.7.1:
   version "4.8.1"
   resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0"
@@ -5245,4 +5409,3 @@ yargs@~3.27.0:
     os-locale "^1.4.0"
     window-size "^0.1.2"
     y18n "^3.2.0"
-

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-yarnpkg.git



More information about the Pkg-javascript-commits mailing list