[Pkg-javascript-commits] [node-yarnpkg] 01/03: New upstream version 1.3.2
Paolo Greppi
paolog-guest at moszumanska.debian.org
Mon Jan 8 09:51:47 UTC 2018
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 2ed0dd5f2e7bbec580f716b4462095911d64ead0
Author: Paolo Greppi <paolo.greppi at libpf.com>
Date: Mon Jan 8 10:40:05 2018 +0100
New upstream version 1.3.2
---
.circleci/config.yml | 141 +++++++++++++++++++++
.travis.yml | 2 +-
CONTRIBUTING.md | 19 +++
__tests__/commands/__snapshots__/init.js.snap | 11 ++
__tests__/commands/__snapshots__/licenses.js.snap | 2 +-
__tests__/commands/_helpers.js | 35 +++--
__tests__/commands/add.js | 136 ++++++++++++++++++++
__tests__/commands/info.js | 21 ++-
__tests__/commands/init.js | 23 ++++
__tests__/commands/install/integration.js | 100 +++++++++++----
__tests__/commands/install/resolutions.js | 13 ++
__tests__/commands/install/workspaces-install.js | 33 ++++-
__tests__/commands/licenses.js | 2 +-
__tests__/commands/link.js | 14 +-
__tests__/commands/list.js | 5 +-
__tests__/commands/remove.js | 28 ++++
__tests__/commands/upgrade.js | 6 +
__tests__/config.js | 44 +++++++
__tests__/constants.js | 17 +--
.../add/add-already-added-dependency/package.json | 7 +
.../add-already-added-dev-dependency/package.json | 7 +
__tests__/fixtures/init/init-config/.yarnrc | 6 +
.../install-dont-overwrite-linked-scoped/.npmrc | 1 -
.../dir-to-link/package.json | 7 -
.../@fakescope-fake-dependency-1.0.1.tgz | Bin 576 -> 0 bytes
.../package.json | 5 -
.../install-dont-overwrite-linked-scoped/yarn.lock | 5 -
.../install-dont-overwrite-linked/package.json | 8 ++
.../install/install-with-comments/package.json | 3 +
.../resolutions/frozen-lockfile/package.json | 11 ++
.../install/resolutions/frozen-lockfile/yarn.lock | 12 ++
.../install/workspaces-install-bin/file.js | 0
.../install/workspaces-install-bin/package.json | 12 ++
.../packages/workspace-1/bin.js | 0
.../packages/workspace-1/package.json | 8 ++
.../packages/workspace-2/package.json | 10 ++
.../install/workspaces-install-bin/yarn.lock | 90 +++++++++++++
.../link/package-with-name-scoped/package.json | 3 +
.../abbrev/-/abbrev-1.1.1.tgz.bin | Bin 0 -> 2998 bytes
.../hoist-non-react-statics.bin | Bin 0 -> 1791 bytes
.../-/hoist-non-react-statics-1.2.0.tgz.bin | Bin 0 -> 7908 bytes
.../-/hoist-non-react-statics-2.3.1.tgz.bin | Bin 0 -> 3678 bytes
.../GET/registry.yarnpkg.com/react-refetch.bin | Bin 0 -> 19328 bytes
.../react-refetch/-/react-refetch-1.0.1.tgz.bin | Bin 0 -> 21852 bytes
.../react-refetch/-/react-refetch-1.0.3-0.tgz.bin | Bin 0 -> 21859 bytes
.../rimraf/-/rimraf-2.6.2.tgz.bin | Bin 0 -> 6231 bytes
.../GET/registry.yarnpkg.com/ui-select.bin | Bin 0 -> 2810 bytes
.../ui-select/-/ui-select-0.19.8.tgz.bin | Bin 0 -> 337664 bytes
.../ui-select/-/ui-select-0.20.0.tgz.bin | Bin 0 -> 334007 bytes
.../GET/registry.yarnpkg.com/warning.bin | Bin 0 -> 1136 bytes
.../warning/-/warning-2.1.0.tgz.bin | Bin 0 -> 3453 bytes
.../warning/-/warning-3.0.0.tgz.bin | Bin 0 -> 3547 bytes
__tests__/fixtures/upgrade/using-beta/package.json | 5 +
__tests__/fixtures/upgrade/using-beta/yarn.lock | 42 ++++++
__tests__/package-request.js | 41 ++++--
__tests__/registries/npm-registry.js | 14 +-
__tests__/util/git/git-spawn.js | 2 +
circle.yml | 57 ---------
package.json | 2 +-
src/cli/commands/add.js | 4 +
src/cli/commands/autoclean.js | 8 +-
src/cli/commands/create.js | 2 +-
src/cli/commands/info.js | 2 +-
src/cli/commands/init.js | 4 +-
src/cli/commands/install.js | 7 +
src/cli/commands/list.js | 3 +-
src/cli/commands/run.js | 4 +-
src/cli/commands/upgrade.js | 11 +-
src/cli/index.js | 21 ++-
src/config.js | 2 +-
src/constants.js | 15 ++-
src/integrity-checker.js | 8 ++
src/package-linker.js | 53 +++++---
src/package-request.js | 11 +-
src/package-resolver.js | 4 +-
src/registries/npm-registry.js | 12 +-
src/reporters/console/console-reporter.js | 2 +-
src/reporters/console/util.js | 8 ++
src/reporters/lang/en.js | 4 +-
src/resolution-map.js | 6 +
src/resolvers/registries/npm-resolver.js | 9 ++
src/util/env-replace.js | 4 +-
src/util/git/git-spawn.js | 4 +
src/util/normalize-manifest/fix.js | 4 +-
src/util/request-manager.js | 4 +-
85 files changed, 995 insertions(+), 231 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..ad90805
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,141 @@
+version: 2
+
+defaults: &defaults
+ working_directory: ~/project/yarn
+ docker:
+ - image: yarnpkg/dev:latest
+
+default_filters: &default_filters
+ tags:
+ only: /^v[0-9]+\.[0-9]+\.[0-9]+$/
+
+restore_node_modules: &restore_node_modules
+ restore_cache:
+ name: Restore node_modules cache
+ keys:
+ - v1-node-{{ .Branch }}-{{ checksum "yarn.lock" }}
+ - v1-node-{{ .Branch }}-
+ - v1-node-
+
+jobs:
+ install:
+ <<: *defaults
+ steps:
+ - checkout
+ - *restore_node_modules
+ - run:
+ name: Install Dependencies
+ command: yarn install
+ - save_cache:
+ name: Save yarn cache
+ key: v1-yarn-{{ .Branch }}-{{ checksum "yarn.lock" }}
+ paths:
+ - .cache/yarn
+ - save_cache:
+ name: Save node_modules cache
+ key: v1-node-{{ .Branch }}-{{ checksum "yarn.lock" }}
+ paths:
+ - node_modules/
+ - run:
+ name: Remove node_modules to cleanup workspace
+ command: rm -r node_modules/
+ - persist_to_workspace:
+ root: ~/project
+ paths:
+ - yarn
+ test:
+ <<: *defaults
+ steps:
+ - attach_workspace:
+ at: ~/project
+ - *restore_node_modules
+ - run:
+ name: Tests
+ command: |
+ node -v
+ if [ "$CIRCLE_BRANCH" == 'master' ]; then
+ ./scripts/set-dev-version.js
+ fi;
+ # Limit maxWorkers to 3 to avoid OOM on CircleCI
+ yarn test-ci --maxWorkers 3
+ yarn check-lockfile
+ lint:
+ <<: *defaults
+ steps:
+ - attach_workspace:
+ at: ~/project
+ - *restore_node_modules
+ - run:
+ name: Lint
+ command: yarn lint
+ build:
+ <<: *defaults
+ steps:
+ - attach_workspace:
+ at: ~/project
+ - *restore_node_modules
+ - run:
+ name: Build distribution
+ command: |
+ node -v
+ if [ "$CIRCLE_BRANCH" == 'master' ]; then
+ ./scripts/set-dev-version.js
+ fi;
+ yarn build-dist
+ ./scripts/build-deb.sh
+ - store_artifacts:
+ path: artifacts/
+ destination: yarnpkg
+ - persist_to_workspace:
+ root: ~/project
+ paths:
+ - yarn
+ publish:
+ <<: *defaults
+ steps:
+ - attach_workspace:
+ at: ~/project
+ - *restore_node_modules
+ - run:
+ name: Publish
+ command: |
+ # Only NPM is handled here - All other release files are handled in a webhook.
+ if [ "${CIRCLE_PROJECT_USERNAME}" == "yarnpkg" ]; then
+ echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
+ ./scripts/update-npm.sh
+ fi
+
+notify:
+ webhooks:
+ # Handles uploading stable/RC releases to GitHub
+ - url: https://nightly.yarnpkg.com/release_circleci
+ # Handles archiving all builds onto the nightly build site
+ - url: https://nightly.yarnpkg.com/archive_circleci
+
+workflows:
+ version: 2
+ install-test-build-and-publish:
+ jobs:
+ - install:
+ filters: *default_filters
+ - test:
+ filters: *default_filters
+ requires:
+ - install
+ - lint:
+ filters: *default_filters
+ requires:
+ - install
+ - build:
+ filters: *default_filters
+ requires:
+ - install
+ - publish:
+ filters:
+ <<: *default_filters
+ branches:
+ ignore: /.*/
+ requires:
+ - test
+ - lint
+ - build
diff --git a/.travis.yml b/.travis.yml
index 6fab908..b80f339 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -55,7 +55,7 @@ matrix:
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
- RAMDISK_SIZE=330;
+ RAMDISK_SIZE=350;
RAMDISK_SECTORS=$(( $RAMDISK_SIZE * 1024 * 1024 / 512 ));
RAMDISK=$(hdiutil attach -nomount ram://$RAMDISK_SECTORS);
newfs_hfs -v yarn_ramfs $RAMDISK;
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c72e5d8..6c54077 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -3,6 +3,25 @@
Contributions are always welcome, no matter how large or small. Substantial feature requests should be proposed as an [RFC](https://github.com/yarnpkg/rfcs). Before contributing,
please read the [code of conduct](CODE_OF_CONDUCT.md).
+## Find things to work on
+
+We label issues that we need help with the `help wanted` tag. We also categorize them with the following tags:
+
+ - cat-bug
+ - cat-feature
+ - cat-chore
+ - cat-performance
+
+These are the main categories that you can work on. We further mark issues with a `high-priority` tag or a `good first issue` tag to indicate their importance to the project and subjective level of easiness to get started on respectively. If you don't see the `triaged` tag or you see any of the `needs-confirmation`, `needs-repro-script`, `needs-discussion` tags, it may not be wise to start working on these issues.
+
+Here are a few quick links to get you started:
+
+ - [Good first bugs](https://github.com/yarnpkg/yarn/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Atriaged+label%3Acat-bug+label%3A%22good+first+issue%22)
+ - [Good first features](https://github.com/yarnpkg/yarn/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22help%20wanted%22%20label%3Atriaged%20label%3Acat-feature%20label%3A%22good%20first%20issue%22%20)
+ - [High impact issue that need help](https://github.com/yarnpkg/yarn/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Ahigh-priority+label%3Atriaged)
+ - [Issues need reproduction scripts](https://github.com/yarnpkg/yarn/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22needs-repro-script%22)
+ - [Issues need triaging](https://github.com/yarnpkg/yarn/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20-label%3Atriaged)
+
## Setup
You need at least the latest version of Node 6 to work on Yarn.
diff --git a/__tests__/commands/__snapshots__/init.js.snap b/__tests__/commands/__snapshots__/init.js.snap
index 0961fd6..7f5a00a 100644
--- a/__tests__/commands/__snapshots__/init.js.snap
+++ b/__tests__/commands/__snapshots__/init.js.snap
@@ -1,5 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`init-config 1`] = `
+Object {
+ "author": "Kittens McKitty <yarn at yarnpkg.com> (https://yarnpkg.com)",
+ "license": "BSD",
+ "main": "index.js",
+ "name": "init-config",
+ "private": true,
+ "version": "0.0.0-alpha",
+}
+`;
+
exports[`init-github 1`] = `
Object {
"license": "MIT",
diff --git a/__tests__/commands/__snapshots__/licenses.js.snap b/__tests__/commands/__snapshots__/licenses.js.snap
index 934b526..594ed7e 100644
--- a/__tests__/commands/__snapshots__/licenses.js.snap
+++ b/__tests__/commands/__snapshots__/licenses.js.snap
@@ -7,7 +7,7 @@ exports[`lists all licenses of the dependencies with the --json argument 1`] = `
"
`;
-exports[`should genereate disclaimer on demand 1`] = `
+exports[`should generate disclaimer on demand 1`] = `
"{\\"type\\":\\"warning\\",\\"data\\":\\"package.json: No license field\\"}
{\\"type\\":\\"warning\\",\\"data\\":\\"No license field\\"}
{\\"type\\":\\"warning\\",\\"data\\":\\"package.json: No license field\\"}
diff --git a/__tests__/commands/_helpers.js b/__tests__/commands/_helpers.js
index b73f39e..d8fd782 100644
--- a/__tests__/commands/_helpers.js
+++ b/__tests__/commands/_helpers.js
@@ -10,16 +10,17 @@ import * as fs from '../../src/util/fs.js';
import {Install} from '../../src/cli/commands/install.js';
import Config from '../../src/config.js';
import parsePackagePath from '../../src/util/parse-package-path.js';
-
+import type {CLIFunctionReturn} from '../../src/types.js';
+import {run as link} from '../../src/cli/commands/link.js';
const stream = require('stream');
const path = require('path');
-const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'install');
+const installFixturesLoc = path.join(__dirname, '..', 'fixtures', 'install');
export const runInstall = run.bind(
null,
ConsoleReporter,
- fixturesLoc,
+ installFixturesLoc,
async (args, flags, config, reporter, lockfile): Promise<Install> => {
const install = new Install(flags, config, reporter, lockfile);
await install.init();
@@ -30,6 +31,17 @@ export const runInstall = run.bind(
[],
);
+const linkFixturesLoc = path.join(__dirname, '..', 'fixtures', 'link');
+
+export const runLink = run.bind(
+ null,
+ ConsoleReporter,
+ linkFixturesLoc,
+ (args, flags, config, reporter): CLIFunctionReturn => {
+ return link(config, reporter, flags, args);
+ },
+);
+
export async function createLockfile(dir: string): Promise<Lockfile> {
const lockfileLoc = path.join(dir, constants.LOCKFILE_FILENAME);
let lockfile;
@@ -94,7 +106,7 @@ export async function run<T, R>(
) => Promise<T> | T,
args: Array<string>,
flags: Object,
- name: string | {source: string, cwd: string},
+ name: string | {source?: string, cwd: string},
checkInstalled: ?(config: Config, reporter: R, install: T, getStdout: () => string) => ?Promise<void>,
beforeInstall: ?(cwd: string) => ?Promise<void>,
): Promise<void> {
@@ -113,11 +125,16 @@ export async function run<T, R>(
if (fixturesLoc) {
const source = typeof name === 'string' ? name : name.source;
- const dir = path.join(fixturesLoc, source);
- cwd = await fs.makeTempDir(path.basename(dir));
- await fs.copy(dir, cwd, reporter);
- if (typeof name !== 'string') {
- cwd = path.join(cwd, name.cwd);
+ // if source wasn't set then assume we were given a complete path
+ if (typeof source === 'undefined') {
+ cwd = typeof name !== 'string' ? name.cwd : await fs.makeTempDir();
+ } else {
+ const dir = path.join(fixturesLoc, source);
+ cwd = await fs.makeTempDir(path.basename(dir));
+ await fs.copy(dir, cwd, reporter);
+ if (typeof name !== 'string') {
+ cwd = path.join(cwd, name.cwd);
+ }
}
} else {
// if fixture loc is not set then CWD is some empty temp dir
diff --git a/__tests__/commands/add.js b/__tests__/commands/add.js
index 2182bad..e3c89d8 100644
--- a/__tests__/commands/add.js
+++ b/__tests__/commands/add.js
@@ -147,6 +147,75 @@ test.concurrent('install with --optional flag', (): Promise<void> => {
});
});
+// Test if moduleAlreadyInManifest warning is displayed
+const moduleAlreadyInManifestChecker = ({expectWarnings}: {expectWarnings: boolean}) => async (
+ args,
+ flags,
+ config,
+ reporter,
+ lockfile,
+): Promise<void> => {
+ const add = new Add(args, flags, config, reporter, lockfile);
+ await add.init();
+
+ const output = reporter.getBuffer();
+ const warnings = output.filter(entry => entry.type === 'warning');
+
+ expect(warnings.some(warning => warning.data.toString().toLowerCase().indexOf('is already in') > -1)).toEqual(
+ expectWarnings,
+ );
+
+ expect(
+ warnings.some(
+ warning => warning.data.toString().toLowerCase().indexOf('please remove existing entry first before adding') > -1,
+ ),
+ ).toEqual(expectWarnings);
+};
+
+test.concurrent('warns when adding a devDependency as dependency', (): Promise<void> => {
+ return buildRun(
+ reporters.BufferReporter,
+ fixturesLoc,
+ moduleAlreadyInManifestChecker({expectWarnings: true}),
+ ['is-online'],
+ {},
+ 'add-already-added-dev-dependency',
+ );
+});
+
+test.concurrent("doesn't warn when adding a devDependency as devDependency", (): Promise<void> => {
+ return buildRun(
+ reporters.BufferReporter,
+ fixturesLoc,
+ moduleAlreadyInManifestChecker({expectWarnings: false}),
+ ['is-online'],
+ {dev: true},
+ 'add-already-added-dev-dependency',
+ );
+});
+
+test.concurrent('warns when adding a dependency as devDependency', (): Promise<void> => {
+ return buildRun(
+ reporters.BufferReporter,
+ fixturesLoc,
+ moduleAlreadyInManifestChecker({expectWarnings: true}),
+ ['is-online'],
+ {dev: true},
+ 'add-already-added-dependency',
+ );
+});
+
+test.concurrent("doesn't warn when adding a dependency as dependency", (): Promise<void> => {
+ return buildRun(
+ reporters.BufferReporter,
+ fixturesLoc,
+ moduleAlreadyInManifestChecker({expectWarnings: false}),
+ ['is-online'],
+ {},
+ 'add-already-added-dependency',
+ );
+});
+
test.concurrent('install with link: specifier', (): Promise<void> => {
return runAdd(['link:../left-pad'], {dev: true}, 'add-with-flag', async config => {
const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock')));
@@ -957,3 +1026,70 @@ test.concurrent('installing with --pure-lockfile and then adding should keep bui
expect(await fs.exists(path.join(config.cwd, 'node_modules', 'package-a', 'temp.txt'))).toBe(true);
});
});
+
+test.concurrent('preserves unaffected bin links after adding to workspace package', async () => {
+ await runInstall({binLinks: true}, 'workspaces-install-bin', async (config): Promise<void> => {
+ const reporter = new ConsoleReporter({});
+
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/touch`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/workspace-1`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/workspace-1`)).toEqual(true);
+
+ // add package
+ const childConfig = await makeConfigFromDirectory(`${config.cwd}/packages/workspace-1`, reporter, {binLinks: true});
+ await add(childConfig, reporter, {}, ['max-safe-integer at 1.0.0']);
+
+ expect(
+ JSON.parse(await fs.readFile(path.join(config.cwd, 'packages/workspace-1/package.json'))).dependencies,
+ ).toEqual({
+ 'max-safe-integer': '1.0.0',
+ });
+
+ // bin links should be preserved
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/touch`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/workspace-1`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/workspace-1`)).toEqual(true);
+ });
+});
+
+test.concurrent('installs "latest" instead of maxSatisfying if it satisfies requested pattern', (): Promise<void> => {
+ // Scenario:
+ // If a registry contains versions [1.0.0, 1.0.1, 1.0.2] and latest:1.0.1
+ // (note that "latest" is not the "newest" version)
+ // If yarn add ^1.0.0 is run, it should choose `1.0.1` because it is "latest" and satisfies the range,
+ // not `1.0.2` even though it is newer.
+ // This is behavior defined by the NPM implementation. See:
+ // * https://github.com/yarnpkg/yarn/issues/3560
+ // * https://git.io/vFmau
+ //
+ // In this test, `ui-select` has a max version of `0.20.0` but a `latest:0.19.8`
+ return runAdd(['ui-select@^0.X'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => {
+ const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock')));
+ const patternIndex = lockfile.indexOf('ui-select@^0.X:');
+ const versionIndex = patternIndex + 1;
+ const actualVersion = lockfile[versionIndex];
+
+ expect(actualVersion).toContain('0.19.8');
+ });
+});
+
+test.concurrent('installs "latest" instead of maxSatisfying if no requested pattern', (): Promise<void> => {
+ // Scenario:
+ // If a registry contains versions [1.0.0, 1.0.1, 1.0.2] and latest:1.0.1
+ // If `yarn add` is run, it should choose `1.0.1` because it is "latest", not `1.0.2` even though it is newer.
+ // In other words, when no range is explicitely given, Yarn should choose "latest".
+ //
+ // In this test, `ui-select` has a max version of `0.20.0` but a `latest:0.19.8`
+ return runAdd(['ui-select'], {}, 'latest-version-in-package', async (config, reporter, previousAdd) => {
+ const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock')));
+ const patternIndex = lockfile.indexOf('ui-select@^0.19.8:');
+ const versionIndex = patternIndex + 1;
+ const actualVersion = lockfile[versionIndex];
+
+ expect(actualVersion).toContain('0.19.8');
+ });
+});
diff --git a/__tests__/commands/info.js b/__tests__/commands/info.js
index c61b1a2..b123d67 100644
--- a/__tests__/commands/info.js
+++ b/__tests__/commands/info.js
@@ -7,8 +7,6 @@ import Config from '../../src/config.js';
import path from 'path';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
-// the mocked requests have stripped metadata, don't use it in the following tests
-jest.unmock('request');
const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'info');
@@ -48,6 +46,11 @@ const expectedKeys = [
// yarn now ships as built, single JS files so it has no dependencies and no scripts
const unexpectedKeys = ['dependencies', 'devDependencies', 'scripts'];
+beforeEach(() => {
+ // the mocked requests have stripped metadata, don't use it in the following tests
+ jest.unmock('request');
+});
+
test.concurrent('without arguments and in directory containing a valid package file', (): Promise<void> => {
return runInfo([], {}, 'local', (config, output): ?Promise<void> => {
const actualKeys = Object.keys(output);
@@ -88,6 +91,20 @@ test.concurrent('with two arguments and second argument "readme" shows readme st
});
});
+test.concurrent('with two arguments and second argument "version" shows `latest` version', (): Promise<void> => {
+ // Scenario:
+ // If a registry contains versions [1.0.0, 1.0.1, 1.0.2] and latest:1.0.1
+ // If `yarn info` is run, it should choose `1.0.1` because it is "latest", not `1.0.2` even though it is newer.
+ // In other words, when no range is explicitely given, Yarn should choose "latest".
+ //
+ // In this test, `ui-select` has a max version of `0.20.0` but a `latest:0.19.8`
+ jest.mock('../__mocks__/request.js');
+
+ return runInfo(['ui-select', 'version'], {}, '', (config, output): ?Promise<void> => {
+ expect(output).toEqual('0.19.8');
+ });
+});
+
test.concurrent('with two arguments and second argument as a simple field', (): Promise<void> => {
return runInfo(['yarn', 'repository'], {}, '', (config, output): ?Promise<void> => {
expect(output).toEqual({
diff --git a/__tests__/commands/init.js b/__tests__/commands/init.js
index b37d3ef..e2463f8 100644
--- a/__tests__/commands/init.js
+++ b/__tests__/commands/init.js
@@ -84,6 +84,29 @@ test.concurrent('init --yes --private should create package.json with defaults a
);
});
+test.concurrent('init should use init-* configs when defined', (): Promise<void> => {
+ return buildRun(
+ ConsoleReporter,
+ fixturesLoc,
+ (args, flags, config, reporter, lockfile): Promise<void> => {
+ return runInit(config, reporter, flags, args);
+ },
+ [],
+ {yes: true},
+ 'init-config',
+ async (config): Promise<void> => {
+ const {cwd} = config;
+ const manifestFile = await fs.readFile(path.join(cwd, 'package.json'));
+ const manifest = JSON.parse(manifestFile);
+
+ // Name is derived from directory name which is dynamic so check
+ // that separately and then remove from snapshot
+ expect(manifest.name).toEqual(path.basename(cwd));
+ expect({...manifest, name: 'init-config'}).toMatchSnapshot('init-config');
+ },
+ );
+});
+
test.concurrent('init using Github shorthand should resolve to full repository URL', (): Promise<void> => {
const questionMap = Object.freeze({
name: 'hi-github',
diff --git a/__tests__/commands/install/integration.js b/__tests__/commands/install/integration.js
index 7fd8051..c8523bf 100644
--- a/__tests__/commands/install/integration.js
+++ b/__tests__/commands/install/integration.js
@@ -11,7 +11,7 @@ import {parse} from '../../../src/lockfile';
import {Install, run as install} from '../../../src/cli/commands/install.js';
import Lockfile from '../../../src/lockfile';
import * as fs from '../../../src/util/fs.js';
-import {getPackageVersion, explodeLockfile, runInstall, createLockfile, run as buildRun} from '../_helpers.js';
+import {getPackageVersion, explodeLockfile, runInstall, runLink, createLockfile, run as buildRun} from '../_helpers.js';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150000;
@@ -640,6 +640,30 @@ test.concurrent('install with comments in manifest', (): Promise<void> => {
});
});
+test.concurrent('install with comments in manifest resolutions does not result in warning', (): Promise<void> => {
+ const fixturesLoc = path.join(__dirname, '..', '..', 'fixtures', 'install');
+
+ return buildRun(
+ reporters.BufferReporter,
+ fixturesLoc,
+ async (args, flags, config, reporter): Promise<void> => {
+ await install(config, reporter, flags, args);
+
+ const output = reporter.getBuffer();
+ const warnings = output.filter(entry => entry.type === 'warning');
+
+ expect(
+ warnings.some(warning => {
+ return warning.data.toString().indexOf(reporter.lang('invalidResolutionName', '//')) > -1;
+ }),
+ ).toEqual(false);
+ },
+ [],
+ {lockfile: false},
+ 'install-with-comments',
+ );
+});
+
test.concurrent('install with null versions in manifest', (): Promise<void> => {
return runInstall({}, 'install-with-null-version', async config => {
expect(await fs.exists(path.join(config.cwd, 'node_modules', 'left-pad'))).toEqual(true);
@@ -842,29 +866,6 @@ test('install a scoped module from authed private registry with a missing traili
});
});
-test.concurrent('install will not overwrite files in symlinked scoped directories', async (): Promise<void> => {
- await runInstall(
- {},
- 'install-dont-overwrite-linked-scoped',
- async (config): Promise<void> => {
- const dependencyPath = path.join(config.cwd, 'node_modules', '@fakescope', 'fake-dependency');
- expect('Symlinked scoped package test').toEqual(
- (await fs.readJson(path.join(dependencyPath, 'package.json'))).description,
- );
- expect(await fs.exists(path.join(dependencyPath, 'index.js'))).toEqual(false);
- },
- async cwd => {
- const dirToLink = path.join(cwd, 'dir-to-link');
-
- await fs.mkdirp(path.join(cwd, '.yarn-link', '@fakescope'));
- await fs.symlink(dirToLink, path.join(cwd, '.yarn-link', '@fakescope', 'fake-dependency'));
-
- await fs.mkdirp(path.join(cwd, 'node_modules', '@fakescope'));
- await fs.symlink(dirToLink, path.join(cwd, 'node_modules', '@fakescope', 'fake-dependency'));
- },
- );
-});
-
test.concurrent('install of scoped package with subdependency conflict should pass check', (): Promise<void> => {
return runInstall({}, 'install-scoped-package-with-subdependency-conflict', async (config, reporter) => {
let allCorrect = true;
@@ -1110,3 +1111,54 @@ test.concurrent('warns for missing bundledDependencies', (): Promise<void> => {
'missing-bundled-dep',
);
});
+
+test.concurrent('install will not overwrite linked scoped dependencies', async (): Promise<void> => {
+ // install only dependencies
+ await runInstall({production: true}, 'install-dont-overwrite-linked', async (installConfig): Promise<void> => {
+ // link our fake dep to the registry
+ await runLink([], {}, 'package-with-name-scoped', async (linkConfig): Promise<void> => {
+ // link our fake dependency in our node_modules
+ await runLink(
+ ['@fakescope/a-package'],
+ {linkFolder: linkConfig.linkFolder},
+ {cwd: installConfig.cwd},
+ async (): Promise<void> => {
+ // check that it exists (just in case)
+ const existed = await fs.exists(path.join(installConfig.cwd, 'node_modules', '@fakescope', 'a-package'));
+ expect(existed).toEqual(true);
+
+ // run install to install dev deps which would remove the linked dep if the bug was present
+ await runInstall({linkFolder: linkConfig.linkFolder}, {cwd: installConfig.cwd}, async (): Promise<void> => {
+ // if the linked dep is still there is a win :)
+ const existed = await fs.exists(path.join(installConfig.cwd, 'node_modules', '@fakescope', 'a-package'));
+ expect(existed).toEqual(true);
+ });
+ },
+ );
+ });
+ });
+});
+
+test.concurrent('install will not overwrite linked dependencies', async (): Promise<void> => {
+ // install only dependencies
+ await runInstall({production: true}, 'install-dont-overwrite-linked', async (installConfig): Promise<void> => {
+ // link our fake dep to the registry
+ await runLink([], {}, 'package-with-name', async (linkConfig): Promise<void> => {
+ // link our fake dependency in our node_modules
+ await runLink(['a-package'], {linkFolder: linkConfig.linkFolder}, {cwd: installConfig.cwd}, async (): Promise<
+ void,
+ > => {
+ // check that it exists (just in case)
+ const existed = await fs.exists(path.join(installConfig.cwd, 'node_modules', 'a-package'));
+ expect(existed).toEqual(true);
+
+ // run install to install dev deps which would remove the linked dep if the bug was present
+ await runInstall({linkFolder: linkConfig.linkFolder}, {cwd: installConfig.cwd}, async (): Promise<void> => {
+ // if the linked dep is still there is a win :)
+ const existed = await fs.exists(path.join(installConfig.cwd, 'node_modules', 'a-package'));
+ expect(existed).toEqual(true);
+ });
+ });
+ });
+ });
+});
diff --git a/__tests__/commands/install/resolutions.js b/__tests__/commands/install/resolutions.js
index 69b6c6f..92cb994 100644
--- a/__tests__/commands/install/resolutions.js
+++ b/__tests__/commands/install/resolutions.js
@@ -1,6 +1,7 @@
/* @flow */
import {getPackageVersion, isPackagePresent, runInstall} from '../_helpers.js';
+import {ConsoleReporter} from '../../../src/reporters/index.js';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150000;
@@ -27,6 +28,18 @@ test.concurrent('install with subtree exact resolutions should override subtree
});
});
+test.concurrent('install with --frozen-lockfile with resolutions', async (): Promise<void> => {
+ const reporter = new ConsoleReporter({});
+
+ try {
+ await runInstall({frozenLockfile: true}, {source: 'resolutions', cwd: 'frozen-lockfile'}, async config => {
+ expect(await getPackageVersion(config, 'left-pad')).toEqual('1.1.3');
+ });
+ } catch (err) {
+ expect(err.message).not.toContain(reporter.lang('frozenLockfileError'));
+ }
+});
+
test.concurrent('install with exotic resolutions should override versions', (): Promise<void> => {
return runInstall({}, {source: 'resolutions', cwd: 'exotic-version'}, async config => {
expect(await getPackageVersion(config, 'left-pad')).toEqual('1.1.1');
diff --git a/__tests__/commands/install/workspaces-install.js b/__tests__/commands/install/workspaces-install.js
index e2117e4..55ed6ce 100644
--- a/__tests__/commands/install/workspaces-install.js
+++ b/__tests__/commands/install/workspaces-install.js
@@ -1,10 +1,10 @@
/* @flow */
import {run as check} from '../../../src/cli/commands/check.js';
-import {Install} from '../../../src/cli/commands/install.js';
+import {Install, run as install} from '../../../src/cli/commands/install.js';
import * as reporters from '../../../src/reporters/index.js';
import * as fs from '../../../src/util/fs.js';
-import {runInstall, run as buildRun} from '../_helpers.js';
+import {runInstall, run as buildRun, makeConfigFromDirectory} from '../_helpers.js';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 150000;
@@ -242,4 +242,33 @@ test.concurrent('install should ignore node_modules in workspaces when used with
});
});
+test.concurrent('install should link binaries properly when run from child workspace', async () => {
+ await runInstall({binLinks: true}, 'workspaces-install-bin', async (config, reporter): Promise<void> => {
+ // initial install
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/touch`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/workspace-1`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/workspace-1`)).toEqual(true);
+
+ // reset package folders to simulate running 'install' from
+ // child workspace _before_ running it in the root (this is not
+ // possible to do without an initial install using the current
+ // testing infrastructure)
+ await fs.unlink(`${config.cwd}/node_modules`);
+ await fs.unlink(`${config.cwd}/packages/workspace-1/node_modules`);
+ await fs.unlink(`${config.cwd}/packages/workspace-2/node_modules`);
+
+ // run "install" in child package
+ const childConfig = await makeConfigFromDirectory(`${config.cwd}/packages/workspace-1`, reporter, {binLinks: true});
+ await install(childConfig, reporter, {}, []);
+
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/touch`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/workspace-1`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/workspace-1`)).toEqual(true);
+ });
+});
+
// TODO need more thorough tests for all kinds of checks: integrity, verify-tree
diff --git a/__tests__/commands/licenses.js b/__tests__/commands/licenses.js
index e37e4e4..c9660cd 100644
--- a/__tests__/commands/licenses.js
+++ b/__tests__/commands/licenses.js
@@ -25,7 +25,7 @@ test('lists all licenses of the dependencies with the --json argument', async ()
});
});
-test('should genereate disclaimer on demand', async (): Promise<void> => {
+test('should generate disclaimer on demand', async (): Promise<void> => {
await runLicenses(['generate-disclaimer'], {}, '', (config, reporter, stdout) => {
expect(stdout).toMatchSnapshot();
});
diff --git a/__tests__/commands/link.js b/__tests__/commands/link.js
index 59fd7db..a3c1129 100644
--- a/__tests__/commands/link.js
+++ b/__tests__/commands/link.js
@@ -1,24 +1,12 @@
/* @flow */
-import {run as buildRun} from './_helpers.js';
-import {run as link} from '../../src/cli/commands/link.js';
+import {runLink} from './_helpers.js';
import {ConsoleReporter} from '../../src/reporters/index.js';
-import type {CLIFunctionReturn} from '../../src/types.js';
import mkdir from './../_temp.js';
import * as fs from '../../src/util/fs.js';
const path = require('path');
-const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'link');
-const runLink = buildRun.bind(
- null,
- ConsoleReporter,
- fixturesLoc,
- (args, flags, config, reporter): CLIFunctionReturn => {
- return link(config, reporter, flags, args);
- },
-);
-
test.concurrent('creates folder in linkFolder', async (): Promise<void> => {
const linkFolder = await mkdir('link-folder');
await runLink([], {linkFolder}, 'package-with-name', async (config, reporter): Promise<void> => {
diff --git a/__tests__/commands/list.js b/__tests__/commands/list.js
index 0805073..b134d40 100644
--- a/__tests__/commands/list.js
+++ b/__tests__/commands/list.js
@@ -166,10 +166,7 @@ describe('list', () => {
});
test('does not list devDependencies when production', (): Promise<void> => {
- const isProduction: $FlowFixMe = require('../../src/constants').isProduction;
- isProduction.mockReturnValue(true);
-
- return runList([], {}, 'dev-deps-prod', (config, reporter): ?Promise<void> => {
+ return runList([], {production: true}, 'dev-deps-prod', (config, reporter): ?Promise<void> => {
expect(reporter.getBuffer()).toMatchSnapshot();
});
});
diff --git a/__tests__/commands/remove.js b/__tests__/commands/remove.js
index c2b71ae..40ef91e 100644
--- a/__tests__/commands/remove.js
+++ b/__tests__/commands/remove.js
@@ -171,3 +171,31 @@ test.concurrent('removes from workspace packages', async () => {
expect(lockFileLines[0]).toEqual('left-pad at 1.1.3:');
});
});
+
+test.concurrent('preserves unaffected bin links after removing workspace packages', async () => {
+ await runInstall({binLinks: true}, 'workspaces-install-bin', async (config): Promise<void> => {
+ const reporter = new ConsoleReporter({});
+
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/touch`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/workspace-1`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/workspace-1`)).toEqual(true);
+
+ // remove package
+ const childConfig = await makeConfigFromDirectory(`${config.cwd}/packages/workspace-1`, reporter, {binLinks: true});
+ await remove(childConfig, reporter, {}, ['left-pad']);
+ await check(childConfig, reporter, {verifyTree: true}, []);
+
+ expect(
+ JSON.parse(await fs.readFile(path.join(config.cwd, 'packages/workspace-1/package.json'))).devDependencies,
+ ).toEqual({});
+
+ // bin links should be preserved
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/touch`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/node_modules/.bin/workspace-1`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/rimraf`)).toEqual(true);
+ expect(await fs.exists(`${config.cwd}/packages/workspace-2/node_modules/.bin/workspace-1`)).toEqual(true);
+ });
+});
diff --git a/__tests__/commands/upgrade.js b/__tests__/commands/upgrade.js
index 166cc98..c70a327 100644
--- a/__tests__/commands/upgrade.js
+++ b/__tests__/commands/upgrade.js
@@ -404,3 +404,9 @@ test.concurrent('upgrade to workspace child preserves root dependencies', (): Pr
expect(childBPkg.dependencies['right-pad']).toEqual('1.0.0');
});
});
+
+test.concurrent('latest flag does not downgrade from a beta', (): Promise<void> => {
+ return runUpgrade([], {latest: true}, 'using-beta', async (config): ?Promise<void> => {
+ await expectInstalledDependency(config, 'react-refetch', '^1.0.3-0', '1.0.3-0');
+ });
+});
diff --git a/__tests__/config.js b/__tests__/config.js
new file mode 100644
index 0000000..b188305
--- /dev/null
+++ b/__tests__/config.js
@@ -0,0 +1,44 @@
+/* @flow */
+
+import Config from '../src/config.js';
+import {ConsoleReporter} from '../src/reporters/index.js';
+
+const stream = require('stream');
+
+const initConfig = async cfg => {
+ const stdout = new stream.Writable({
+ decodeStrings: false,
+ write(data, encoding, cb) {
+ cb();
+ },
+ });
+
+ const reporter = new ConsoleReporter({stdout, stderr: stdout});
+ const config = new Config(reporter);
+ await config.init(cfg);
+ return config;
+};
+
+test('getOption changes ~ to cwd when resolve=true', async () => {
+ const config = await initConfig({});
+ config.registries.yarn.config.cafile = '~/';
+ expect(config.getOption('cafile', true)).not.toContain('~');
+});
+
+test('getOption does not change ~ when resolve=false', async () => {
+ const config = await initConfig({});
+ config.registries.yarn.config.cafile = '~/';
+ expect(config.getOption('cafile', false)).toEqual('~/');
+});
+
+test('getOption does not change empty-string when resolve=true', async () => {
+ const config = await initConfig({});
+ config.registries.yarn.config.cafile = '';
+ expect(config.getOption('cafile', true)).toEqual('');
+});
+
+test('getOption does not change empty-string when resolve=false', async () => {
+ const config = await initConfig({});
+ config.registries.yarn.config.cafile = '';
+ expect(config.getOption('cafile', false)).toEqual('');
+});
diff --git a/__tests__/constants.js b/__tests__/constants.js
index 456f30f..1a36165 100644
--- a/__tests__/constants.js
+++ b/__tests__/constants.js
@@ -1,6 +1,6 @@
/* @flow */
-import {getPathKey, isProduction} from '../src/constants.js';
+import {getPathKey} from '../src/constants.js';
test('getPathKey', () => {
expect(getPathKey('win32', {PATH: 'foobar'})).toBe('PATH');
@@ -10,18 +10,3 @@ test('getPathKey', () => {
expect(getPathKey('linux', {})).toBe('PATH');
expect(getPathKey('darwin', {})).toBe('PATH');
});
-
-describe('isProduction', () => {
- const env = {
- NODE_ENV: '',
- };
- test('passing "development" should return false', () => {
- env.NODE_ENV = 'development';
- expect(isProduction(env)).toBe(false);
- });
-
- test('passing "production" should return true', () => {
- env.NODE_ENV = 'production';
- expect(isProduction(env)).toBe(true);
- });
-});
diff --git a/__tests__/fixtures/add/add-already-added-dependency/package.json b/__tests__/fixtures/add/add-already-added-dependency/package.json
new file mode 100644
index 0000000..ea7c7db
--- /dev/null
+++ b/__tests__/fixtures/add/add-already-added-dependency/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "foo",
+ "version": "1.0.0",
+ "dependencies": {
+ "is-online": "^7.0.0"
+ }
+}
diff --git a/__tests__/fixtures/add/add-already-added-dev-dependency/package.json b/__tests__/fixtures/add/add-already-added-dev-dependency/package.json
new file mode 100644
index 0000000..18b9223
--- /dev/null
+++ b/__tests__/fixtures/add/add-already-added-dev-dependency/package.json
@@ -0,0 +1,7 @@
+{
+ "name": "foo",
+ "version": "1.0.0",
+ "devDependencies": {
+ "is-online": "^7.0.0"
+ }
+}
diff --git a/__tests__/fixtures/init/init-config/.yarnrc b/__tests__/fixtures/init/init-config/.yarnrc
new file mode 100644
index 0000000..99cf7bd
--- /dev/null
+++ b/__tests__/fixtures/init/init-config/.yarnrc
@@ -0,0 +1,6 @@
+init-private true
+init-license BSD
+init-version "0.0.0-alpha"
+init-author-name "Kittens McKitty"
+init-author-email "yarn at yarnpkg.com"
+init-author-url "https://yarnpkg.com"
diff --git a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/.npmrc b/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/.npmrc
deleted file mode 100644
index 9465b97..0000000
--- a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-yarn-offline-mirror=./mirror-for-offline
diff --git a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/dir-to-link/package.json b/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/dir-to-link/package.json
deleted file mode 100644
index 5de00be..0000000
--- a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/dir-to-link/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "name": "@fakescope/fake-dependency",
- "description": "Symlinked scoped package test",
- "version": "1.0.1",
- "dependencies": {},
- "license": "MIT"
-}
diff --git a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/mirror-for-offline/@fakescope-fake-dependency-1.0.1.tgz b/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/mirror-for-offline/@fakescope-fake-dependency-1.0.1.tgz
deleted file mode 100644
index 29e48dd..0000000
Binary files a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/mirror-for-offline/@fakescope-fake-dependency-1.0.1.tgz and /dev/null differ
diff --git a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/package.json b/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/package.json
deleted file mode 100644
index a0cf66c..0000000
--- a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "dependencies": {
- "@fakescope/fake-dependency": "1.0.1"
- }
-}
diff --git a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/yarn.lock b/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/yarn.lock
deleted file mode 100644
index ca46137..0000000
--- a/__tests__/fixtures/install/install-dont-overwrite-linked-scoped/yarn.lock
+++ /dev/null
@@ -1,5 +0,0 @@
-# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
-# yarn lockfile v1
-"@fakescope/fake-dependency at 1.0.1":
- version "1.0.1"
- resolved "@fakescope-fake-dependency-1.0.1.tgz#477dafd486d856af0b3faf5a5f1c895001221609"
diff --git a/__tests__/fixtures/install/install-dont-overwrite-linked/package.json b/__tests__/fixtures/install/install-dont-overwrite-linked/package.json
new file mode 100644
index 0000000..86bcb81
--- /dev/null
+++ b/__tests__/fixtures/install/install-dont-overwrite-linked/package.json
@@ -0,0 +1,8 @@
+{
+ "dependencies": {
+ "left-pad": "1.1.3"
+ },
+ "devDependencies": {
+ "is-buffer": "^1.1.5"
+ }
+}
diff --git a/__tests__/fixtures/install/install-with-comments/package.json b/__tests__/fixtures/install/install-with-comments/package.json
index 01dea4a..60647f1 100644
--- a/__tests__/fixtures/install/install-with-comments/package.json
+++ b/__tests__/fixtures/install/install-with-comments/package.json
@@ -6,5 +6,8 @@
"comment"
],
"foo": "file:bar"
+ },
+ "resolutions": {
+ "//": "This is a comment."
}
}
diff --git a/__tests__/fixtures/install/resolutions/frozen-lockfile/package.json b/__tests__/fixtures/install/resolutions/frozen-lockfile/package.json
new file mode 100644
index 0000000..8c1b9a3
--- /dev/null
+++ b/__tests__/fixtures/install/resolutions/frozen-lockfile/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "project",
+ "version": "1.0.0",
+ "dependencies": {
+ "left-pad": "^1.0.0",
+ "d2": "file:../d2-1"
+ },
+ "resolutions": {
+ "left-pad": "^1.0.0"
+ }
+}
diff --git a/__tests__/fixtures/install/resolutions/frozen-lockfile/yarn.lock b/__tests__/fixtures/install/resolutions/frozen-lockfile/yarn.lock
new file mode 100644
index 0000000..a7b5307
--- /dev/null
+++ b/__tests__/fixtures/install/resolutions/frozen-lockfile/yarn.lock
@@ -0,0 +1,12 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"d2 at file:../d2-1":
+ version "1.0.0"
+ dependencies:
+ left-pad "^1.0.0"
+
+left-pad@^1.0.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.1.3.tgz#612f61c033f3a9e08e939f1caebeea41b6f3199a"
diff --git a/__tests__/fixtures/install/workspaces-install-bin/file.js b/__tests__/fixtures/install/workspaces-install-bin/file.js
new file mode 100644
index 0000000..e69de29
diff --git a/__tests__/fixtures/install/workspaces-install-bin/package.json b/__tests__/fixtures/install/workspaces-install-bin/package.json
new file mode 100644
index 0000000..3f03c73
--- /dev/null
+++ b/__tests__/fixtures/install/workspaces-install-bin/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "my-project",
+ "private": true,
+ "bin": {"file": "file.js"},
+ "dependencies": {},
+ "devDependencies": {
+ "touch": "^1.0.0"
+ },
+ "workspaces": [
+ "packages/*"
+ ]
+}
diff --git a/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-1/bin.js b/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-1/bin.js
new file mode 100755
index 0000000..e69de29
diff --git a/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-1/package.json b/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-1/package.json
new file mode 100644
index 0000000..216d9c1
--- /dev/null
+++ b/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-1/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "workspace-1",
+ "version": "1.0.0",
+ "bin": "./bin.js",
+ "devDependencies": {
+ "left-pad": "1.0.0"
+ }
+}
diff --git a/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-2/package.json b/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-2/package.json
new file mode 100644
index 0000000..99b6e83
--- /dev/null
+++ b/__tests__/fixtures/install/workspaces-install-bin/packages/workspace-2/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "workspace-2",
+ "version": "1.0.0",
+ "dependencies": {
+ "workspace-1": "^1.0.0"
+ },
+ "devDependencies": {
+ "rimraf": "^2.6.2"
+ }
+}
diff --git a/__tests__/fixtures/install/workspaces-install-bin/yarn.lock b/__tests__/fixtures/install/workspaces-install-bin/yarn.lock
new file mode 100644
index 0000000..eccf796
--- /dev/null
+++ b/__tests__/fixtures/install/workspaces-install-bin/yarn.lock
@@ -0,0 +1,90 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+abbrev at 1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
+brace-expansion@^1.1.7:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+concat-map at 0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+
+glob@^7.0.5:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+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:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+
+left-pad at 1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.0.0.tgz#c84e2417581bbb8eaf2b9e3d7a122e572ab1af37"
+
+minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ dependencies:
+ brace-expansion "^1.1.7"
+
+nopt@~1.0.10:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
+ dependencies:
+ abbrev "1"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ dependencies:
+ wrappy "1"
+
+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"
+
+rimraf@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+ dependencies:
+ glob "^7.0.5"
+
+touch@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/touch/-/touch-1.0.0.tgz#449cbe2dbae5a8c8038e30d71fa0ff464947c4de"
+ dependencies:
+ nopt "~1.0.10"
+
+wrappy at 1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
diff --git a/__tests__/fixtures/link/package-with-name-scoped/package.json b/__tests__/fixtures/link/package-with-name-scoped/package.json
new file mode 100644
index 0000000..203ee2b
--- /dev/null
+++ b/__tests__/fixtures/link/package-with-name-scoped/package.json
@@ -0,0 +1,3 @@
+{
+ "name": "@fakescope/a-package"
+}
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz.bin
new file mode 100644
index 0000000..ee73ef8
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics.bin
new file mode 100644
index 0000000..b51a414
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz.bin
new file mode 100644
index 0000000..14c5ea8
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz.bin
new file mode 100644
index 0000000..c82cb7c
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch.bin
new file mode 100644
index 0000000..81e4904
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch/-/react-refetch-1.0.1.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch/-/react-refetch-1.0.1.tgz.bin
new file mode 100644
index 0000000..02c66e9
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch/-/react-refetch-1.0.1.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch/-/react-refetch-1.0.3-0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch/-/react-refetch-1.0.3-0.tgz.bin
new file mode 100644
index 0000000..7157ab0
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-refetch/-/react-refetch-1.0.3-0.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz.bin
new file mode 100644
index 0000000..a13b93d
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select.bin
new file mode 100644
index 0000000..12d49f7
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select/-/ui-select-0.19.8.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select/-/ui-select-0.19.8.tgz.bin
new file mode 100644
index 0000000..0d28de6
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select/-/ui-select-0.19.8.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select/-/ui-select-0.20.0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select/-/ui-select-0.20.0.tgz.bin
new file mode 100644
index 0000000..fc9052b
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/ui-select/-/ui-select-0.20.0.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning.bin
new file mode 100644
index 0000000..f70b696
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning/-/warning-2.1.0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning/-/warning-2.1.0.tgz.bin
new file mode 100644
index 0000000..9a4176f
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning/-/warning-2.1.0.tgz.bin differ
diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning/-/warning-3.0.0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning/-/warning-3.0.0.tgz.bin
new file mode 100644
index 0000000..9f8a822
Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/warning/-/warning-3.0.0.tgz.bin differ
diff --git a/__tests__/fixtures/upgrade/using-beta/package.json b/__tests__/fixtures/upgrade/using-beta/package.json
new file mode 100644
index 0000000..8d9f8d9
--- /dev/null
+++ b/__tests__/fixtures/upgrade/using-beta/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "react-refetch": "^1.0.3-0"
+ }
+}
diff --git a/__tests__/fixtures/upgrade/using-beta/yarn.lock b/__tests__/fixtures/upgrade/using-beta/yarn.lock
new file mode 100644
index 0000000..ca571fb
--- /dev/null
+++ b/__tests__/fixtures/upgrade/using-beta/yarn.lock
@@ -0,0 +1,42 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+hoist-non-react-statics@^2.0.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
+
+invariant@^2.0.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
+ dependencies:
+ loose-envify "^1.0.0"
+
+js-tokens@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+lodash@^4.11.0:
+ version "4.17.4"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
+
+loose-envify@^1.0.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
+ dependencies:
+ js-tokens "^3.0.0"
+
+react-refetch@^1.0.3-0:
+ version "1.0.3-0"
+ resolved "https://registry.yarnpkg.com/react-refetch/-/react-refetch-1.0.3-0.tgz#e1e71bd98282e468b59aae05239d8a9523494f19"
+ dependencies:
+ hoist-non-react-statics "^2.0.0"
+ invariant "^2.0.0"
+ lodash "^4.11.0"
+ warning "^3.0.0"
+
+warning@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"
+ dependencies:
+ loose-envify "^1.0.0"
diff --git a/__tests__/package-request.js b/__tests__/package-request.js
index 814ceed..7b9afae 100644
--- a/__tests__/package-request.js
+++ b/__tests__/package-request.js
@@ -32,7 +32,7 @@ async function prepareRequest(pattern: string, version: string, resolved: string
return {request, reporter};
}
-test('Produce valid remote type for a git private dep', async () => {
+test('Produce valid remote type for a git-over-ssh dep', async () => {
const {request, reporter} = await prepareRequest(
'private-dep at github:yarnpkg/private-dep#1.0.0',
'1.0.0',
@@ -45,6 +45,32 @@ test('Produce valid remote type for a git private dep', async () => {
await reporter.close();
});
+test('Produce valid remote type for a git-over-https dep', async () => {
+ const {request, reporter} = await prepareRequest(
+ 'public-dep at yarnpkg/public-dep#1.0.0',
+ '1.0.0',
+ 'git+https://github.com/yarnpkg/public-dep#1fde368',
+ );
+
+ expect(request.getLocked('git')._remote.type).toBe('git');
+ expect(request.getLocked('tarball')._remote.type).toBe('git');
+
+ await reporter.close();
+});
+
+test('Produce valid remote type for a git public dep', async () => {
+ const {request, reporter} = await prepareRequest(
+ 'public-dep at yarnpkg/public-dep#1fde368',
+ '1.0.0',
+ 'https://codeload.github.com/yarnpkg/public-dep/tar.gz/1fde368',
+ );
+
+ expect(request.getLocked('git')._remote.type).toBe('git');
+ expect(request.getLocked('tarball')._remote.type).toBe('tarball');
+
+ await reporter.close();
+});
+
test('Check parentNames flowing in the request', async () => {
const {request: parentRequest, reporter: parentReporter} = await prepareRequest(
'parent at 1.0.0',
@@ -63,16 +89,3 @@ test('Check parentNames flowing in the request', async () => {
await parentReporter.close();
await childReporter.close();
});
-
-test('Produce valid remote type for a git public dep', async () => {
- const {request, reporter} = await prepareRequest(
- 'public-dep at yarnpkg/public-dep#1fde368',
- '1.0.0',
- 'https://codeload.github.com/yarnpkg/public-dep/tar.gz/1fde368',
- );
-
- expect(request.getLocked('git')._remote.type).toBe('git');
- expect(request.getLocked('tarball')._remote.type).toBe('tarball');
-
- await reporter.close();
-});
diff --git a/__tests__/registries/npm-registry.js b/__tests__/registries/npm-registry.js
index bf28d73..ab51e1b 100644
--- a/__tests__/registries/npm-registry.js
+++ b/__tests__/registries/npm-registry.js
@@ -4,7 +4,7 @@ import {resolve, join as pathJoin} from 'path';
import NpmRegistry from '../../src/registries/npm-registry.js';
import {BufferReporter} from '../../src/reporters/index.js';
-import homeDir from '../../src/util/user-home-dir.js';
+import homeDir, {home} from '../../src/util/user-home-dir.js';
describe('normalizeConfig', () => {
beforeAll(() => {
@@ -40,6 +40,18 @@ describe('normalizeConfig', () => {
const normalized = NpmRegistry.normalizeConfig({cafile: rooted})['cafile'];
expect(normalized).toEqual(rooted);
});
+
+ test('handles missing HOME', () => {
+ const realHome = process.env.HOME;
+ delete process.env.HOME;
+
+ try {
+ const normalized = NpmRegistry.normalizeConfig({cafile: '${HOME}/foo'})['cafile'];
+ expect(normalized).toEqual(resolve(home, 'foo'));
+ } finally {
+ process.env.HOME = realHome;
+ }
+ });
});
function createMocks(): Object {
diff --git a/__tests__/util/git/git-spawn.js b/__tests__/util/git/git-spawn.js
index 22b2b8e..7054488 100644
--- a/__tests__/util/git/git-spawn.js
+++ b/__tests__/util/git/git-spawn.js
@@ -34,6 +34,7 @@ describe('spawn', () => {
GIT_ASKPASS: '',
GIT_TERMINAL_PROMPT: 0,
GIT_SSH_COMMAND: '"ssh" -oBatchMode=yes',
+ GIT_SSH_VARIANT: 'ssh',
...process.env,
});
});
@@ -53,6 +54,7 @@ describe('spawn', () => {
GIT_ASKPASS: '',
GIT_TERMINAL_PROMPT: 0,
GIT_SSH_COMMAND: `"${plinkPath}" -batch`,
+ GIT_SSH_VARIANT: 'plink',
...process.env,
});
});
diff --git a/circle.yml b/circle.yml
deleted file mode 100644
index bfde41f..0000000
--- a/circle.yml
+++ /dev/null
@@ -1,57 +0,0 @@
-general:
- branches:
- ignore:
- - gh-pages
- artifacts:
- - "artifacts/"
-
-machine:
- node:
- version: 8
-
-dependencies:
- cache_directories:
- - "~/.cache/yarn"
-
- override:
- - which node
-
- # install dependencies
- - ./scripts/bootstrap-env-ubuntu.sh
-
- - yarn install
-
-test:
- override:
- - node -v
- - >
- if [ "$CIRCLE_BRANCH" == 'master' ]; then
- ./scripts/set-dev-version.js
- fi;
- - yarn lint
- # Limit maxWorkers to 3 to avoid OOM on CircleCI
- - yarn test-ci -- -- --maxWorkers 3
- - yarn check-lockfile
- - yarn run build-dist
- - yarn run build-deb
-
- # Test that installing as root works and that it also works
- # behind a user namespace which Circle CI tests are run under
- - sudo env "PATH=$PATH" bin/yarn install --force
-
-deployment:
- release:
- tag: /v[0-9]+(\.[0-9]+)*/
- owner: yarnpkg
- commands:
- # Only NPM is handled here - All other release files are handled in a webhook.
- - echo "Releasing $CIRCLE_TAG..."
- - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
- - ./scripts/update-npm.sh
-
-notify:
- webhooks:
- # Handles uploading stable/RC releases to GitHub
- - url: https://nightly.yarnpkg.com/release_circleci
- # Handles archiving all builds onto the nightly build site
- - url: https://nightly.yarnpkg.com/archive_circleci
diff --git a/package.json b/package.json
index 43ac51b..18b73e1 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "yarn",
"installationMethod": "unknown",
- "version": "1.2.1",
+ "version": "1.3.2",
"license": "BSD-2-Clause",
"preferGlobal": true,
"description": "📦🐈 Fast, reliable, and secure dependency management.",
diff --git a/src/cli/commands/add.js b/src/cli/commands/add.js
index 20309a1..a2f315c 100644
--- a/src/cli/commands/add.js
+++ b/src/cli/commands/add.js
@@ -195,6 +195,10 @@ export class Add extends Install {
object[target] = object[target] || {};
object[target][pkg.name] = version;
+
+ if (target !== this.flagToOrigin) {
+ this.reporter.warn(this.reporter.lang('moduleAlreadyInManifest', pkg.name, depType, this.flagToOrigin));
+ }
}
await this.config.saveRootManifests(manifests);
diff --git a/src/cli/commands/autoclean.js b/src/cli/commands/autoclean.js
index e97e65d..178aee3 100644
--- a/src/cli/commands/autoclean.js
+++ b/src/cli/commands/autoclean.js
@@ -40,6 +40,11 @@ Gulpfile.js
Gruntfile.js
# configs
+appveyor.yml
+circle.yml
+codeship-services.yml
+codeship-steps.yml
+wercker.yml
.tern-project
.gitattributes
.editorconfig
@@ -49,8 +54,7 @@ Gruntfile.js
.flowconfig
.documentup.json
.yarn-metadata.json
-.*.yml
-*.yml
+.travis.yml
# misc
*.md
diff --git a/src/cli/commands/create.js b/src/cli/commands/create.js
index 19e8b6a..e3983d7 100644
--- a/src/cli/commands/create.js
+++ b/src/cli/commands/create.js
@@ -29,5 +29,5 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg
const binFolder = await getBinFolder(config, {});
const command = path.resolve(binFolder, path.basename(commandName));
- await child.spawn(command, [...rest], {stdio: `inherit`, shell: true});
+ await child.spawn(command, rest, {stdio: `inherit`, shell: true});
}
diff --git a/src/cli/commands/info.js b/src/cli/commands/info.js
index b89bac0..db1f6e8 100644
--- a/src/cli/commands/info.js
+++ b/src/cli/commands/info.js
@@ -72,7 +72,7 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg
const versions = result.versions;
// $FlowFixMe
result.versions = Object.keys(versions).sort(semver.compareLoose);
- result.version = version || result.versions[result.versions.length - 1];
+ result.version = version || result['dist-tags'].latest;
result = Object.assign(result, versions[result.version]);
const fieldPath = args.shift();
diff --git a/src/cli/commands/init.js b/src/cli/commands/init.js
index 7d568aa..85f5951 100644
--- a/src/cli/commands/init.js
+++ b/src/cli/commands/init.js
@@ -96,7 +96,7 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg
{
key: 'private',
question: 'private',
- default: '',
+ default: config.getOption('init-private') || '',
inputFormatter: yn,
},
];
@@ -129,7 +129,7 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg
}
if (def) {
- question += ` (${def.toString()})`;
+ question += ` (${String(def)})`;
}
let answer;
diff --git a/src/cli/commands/install.js b/src/cli/commands/install.js
index 3488b80..66c8986 100644
--- a/src/cli/commands/install.js
+++ b/src/cli/commands/install.js
@@ -424,6 +424,12 @@ export class Install {
return false;
}
+ if (match.hardRefreshRequired) {
+ // e.g. node version doesn't match, force script installations
+ this.scripts.setForce(true);
+ return false;
+ }
+
if (!patterns.length && !match.integrityFileMissing) {
this.reporter.success(this.reporter.lang('nothingToInstall'));
await this.createEmptyManifestFolders();
@@ -504,6 +510,7 @@ export class Install {
steps.push(async (curr: number, total: number) => {
this.reporter.step(curr, total, this.reporter.lang('resolvingPackages'), emoji.get('mag'));
+ this.resolutionMap.setTopLevelPatterns(rawPatterns);
await this.resolver.init(this.prepareRequests(depRequests), {
isFlat: this.flags.flat,
isFrozen: this.flags.frozenLockfile,
diff --git a/src/cli/commands/list.js b/src/cli/commands/list.js
index 41d913c..ba29a13 100644
--- a/src/cli/commands/list.js
+++ b/src/cli/commands/list.js
@@ -8,7 +8,6 @@ import type {Tree, Trees} from '../../reporters/types.js';
import {Install} from './install.js';
import Lockfile from '../../lockfile';
-import {isProduction} from '../../constants';
const invariant = require('invariant');
const micromatch = require('micromatch');
@@ -199,7 +198,7 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg
});
let activePatterns = [];
- if (isProduction()) {
+ if (config.production) {
const devDeps = getDevDeps(manifest);
activePatterns = patterns.filter(pattern => !devDeps.has(pattern));
} else {
diff --git a/src/cli/commands/run.js b/src/cli/commands/run.js
index f3c941a..e18d033 100644
--- a/src/cli/commands/run.js
+++ b/src/cli/commands/run.js
@@ -74,8 +74,8 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg
}
if (cmds.length) {
- // propagate YARN_SILENT env variable to executed commands
- process.env.YARN_SILENT = '1';
+ // Disable wrapper in executed commands
+ process.env.YARN_WRAP_OUTPUT = 'false';
for (const [stage, cmd] of cmds) {
// only tack on trailing arguments for default script, ignore for pre and post - #1595
const cmdWithArgs = stage === action ? sh`${unquoted(cmd)} ${args}` : cmd;
diff --git a/src/cli/commands/upgrade.js b/src/cli/commands/upgrade.js
index c7d6886..ac1ff97 100644
--- a/src/cli/commands/upgrade.js
+++ b/src/cli/commands/upgrade.js
@@ -199,7 +199,6 @@ export async function getOutdated(
): Promise<Array<Dependency>> {
const install = new Install(flags, config, reporter, lockfile);
const outdatedFieldName = flags.latest ? 'latest' : 'wanted';
- const updateAll = patterns.length === 0;
// ensure scope is of the form `@scope/`
const normalizeScope = function() {
@@ -227,15 +226,7 @@ export async function getOutdated(
normalizeScope();
- const deps = (await PackageRequest.getOutdatedPackages(
- lockfile,
- install,
- config,
- reporter,
- patterns,
- flags,
- updateAll,
- ))
+ const deps = (await PackageRequest.getOutdatedPackages(lockfile, install, config, reporter, patterns, flags))
.filter(versionFilter)
.filter(scopeFilter.bind(this, flags));
deps.forEach(dep => {
diff --git a/src/cli/index.js b/src/cli/index.js
index 1b3d4c9..5024530 100644
--- a/src/cli/index.js
+++ b/src/cli/index.js
@@ -42,6 +42,14 @@ function findProjectRoot(base: string): string {
const boolify = val => val.toString().toLowerCase() !== 'false' && val !== '0';
+function boolifyWithDefault(val: any, defaultResult: boolean): boolean {
+ if (val === undefined || val === null || val === '') {
+ return defaultResult;
+ } else {
+ return boolify(val);
+ }
+}
+
export function main({
startArgs,
args,
@@ -164,7 +172,7 @@ export function main({
let warnAboutRunDashDash = false;
// we are using "yarn <script> -abc" or "yarn run <script> -abc", we want -abc to be script options, not yarn options
- if (command === commands.run) {
+ if (command === commands.run || command === commands.create) {
if (endArgs.length === 0) {
endArgs = ['--', ...args.splice(1)];
} else {
@@ -196,7 +204,7 @@ export function main({
emoji: process.stdout.isTTY && commander.emoji,
verbose: commander.verbose,
noProgress: !commander.progress,
- isSilent: process.env.YARN_SILENT === '1' || commander.silent,
+ isSilent: boolifyWithDefault(process.env.YARN_SILENT, false) || commander.silent,
});
const exit = exitCode => {
@@ -207,9 +215,10 @@ export function main({
reporter.initPeakMemoryCounter();
const config = new Config(reporter);
- const outputWrapper = !commander.json && command.hasWrapper(commander, commander.args);
+ const outputWrapperEnabled = boolifyWithDefault(process.env.YARN_WRAP_OUTPUT, true);
+ const shouldWrapOutput = outputWrapperEnabled && !commander.json && command.hasWrapper(commander, commander.args);
- if (outputWrapper) {
+ if (shouldWrapOutput) {
reporter.header(commandName, {name: 'yarn', version});
}
@@ -243,7 +252,7 @@ export function main({
}
return command.run(config, reporter, commander, commander.args).then(exitCode => {
- if (outputWrapper) {
+ if (shouldWrapOutput) {
reporter.footer(false);
}
return exitCode;
@@ -541,7 +550,7 @@ async function start(): Promise<void> {
const rc = getRcConfigForCwd(process.cwd());
const yarnPath = rc['yarn-path'];
- if (yarnPath && process.env.YARN_IGNORE_PATH !== '1') {
+ if (yarnPath && !boolifyWithDefault(process.env.YARN_IGNORE_PATH, false)) {
const argv = process.argv.slice(2);
const opts = {stdio: 'inherit', env: Object.assign({}, process.env, {YARN_IGNORE_PATH: 1})};
let exitCode = 0;
diff --git a/src/config.js b/src/config.js
index 3a70831..7d6f084 100644
--- a/src/config.js
+++ b/src/config.js
@@ -195,7 +195,7 @@ export default class Config {
getOption(key: string, resolve: boolean = false): mixed {
const value = this.registries.yarn.getOption(key);
- if (resolve && typeof value === 'string') {
+ if (resolve && typeof value === 'string' && value.length) {
return resolveWithHome(value);
}
diff --git a/src/constants.js b/src/constants.js
index 40c82b6..62c980c 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -10,8 +10,10 @@ type Env = {
};
export const DEPENDENCY_TYPES = ['devDependencies', 'dependencies', 'optionalDependencies', 'peerDependencies'];
+export const RESOLUTIONS = 'resolutions';
+export const MANIFEST_FIELDS = [RESOLUTIONS, ...DEPENDENCY_TYPES];
-export const SUPPORTED_NODE_VERSIONS = '^4.8.0 || ^5.7.0 || ^6.2.2 || ^8.0.0';
+export const SUPPORTED_NODE_VERSIONS = '^4.8.0 || ^5.7.0 || ^6.2.2 || >=8.0.0';
export const YARN_REGISTRY = 'https://registry.yarnpkg.com';
@@ -59,7 +61,12 @@ function getPreferredCacheDirectories(): Array<string> {
preferredCacheDirectories.push(getDirectory('cache'));
}
- preferredCacheDirectories.push(path.join(os.tmpdir(), '.yarn-cache'));
+ if (process.getuid) {
+ // $FlowFixMe: process.getuid exists, dammit
+ preferredCacheDirectories.push(path.join(os.tmpdir(), `.yarn-cache-${process.getuid()}`));
+ }
+
+ preferredCacheDirectories.push(path.join(os.tmpdir(), `.yarn-cache`));
return preferredCacheDirectories;
}
@@ -101,10 +108,6 @@ export const SINGLE_INSTANCE_FILENAME = '.yarn-single-instance';
export const ENV_PATH_KEY = getPathKey(process.platform, process.env);
-export function isProduction(env: Object = process.env): boolean {
- return env.NODE_ENV === 'production';
-}
-
export function getPathKey(platform: string, env: Env): string {
let pathKey = 'PATH';
diff --git a/src/integrity-checker.js b/src/integrity-checker.js
index 7e0e0ad..3dcd33c 100644
--- a/src/integrity-checker.js
+++ b/src/integrity-checker.js
@@ -19,6 +19,7 @@ export const integrityErrors = {
LINKED_MODULES_DONT_MATCH: 'integrityCheckLinkedModulesDontMatch',
PATTERNS_DONT_MATCH: 'integrityPatternsDontMatch',
MODULES_FOLDERS_MISSING: 'integrityModulesFoldersMissing',
+ NODE_VERSION_DOESNT_MATCH: 'integrityNodeDoesntMatch',
};
type IntegrityError = $Keys<typeof integrityErrors>;
@@ -37,6 +38,7 @@ type IntegrityHashLocation = {
};
type IntegrityFile = {
+ nodeVersion: string,
flags: Array<string>,
modulesFolders: Array<string>,
linkedModules: Array<string>,
@@ -54,6 +56,7 @@ type IntegrityFlags = {
};
const INTEGRITY_FILE_DEFAULTS = () => ({
+ nodeVersion: process.version,
modulesFolders: [],
flags: [],
linkedModules: [],
@@ -295,6 +298,10 @@ export default class InstallationIntegrityChecker {
return 'LINKED_MODULES_DONT_MATCH';
}
+ if (actual.nodeVersion !== expected.nodeVersion) {
+ return 'NODE_VERSION_DOESNT_MATCH';
+ }
+
let relevantExpectedFlags = expected.flags.slice();
// If we run "yarn" after "yarn --check-files", we shouldn't fail the less strict validation
@@ -386,6 +393,7 @@ export default class InstallationIntegrityChecker {
integrityMatches: integrityMatches === 'OK',
integrityError: integrityMatches === 'OK' ? undefined : integrityMatches,
missingPatterns,
+ hardRefreshRequired: integrityMatches === 'NODE_VERSION_DOESNT_MATCH',
};
}
diff --git a/src/package-linker.js b/src/package-linker.js
index 8f9a75f..e32fc24 100644
--- a/src/package-linker.js
+++ b/src/package-linker.js
@@ -304,8 +304,13 @@ export default class PackageLinker {
const stat = await fs.lstat(entryPath);
if (stat.isSymbolicLink()) {
- const packageName = entry;
- linkTargets.set(packageName, await fs.readlink(entryPath));
+ try {
+ const entryTarget = await fs.realpath(entryPath);
+ linkTargets.set(entry, entryTarget);
+ } catch (err) {
+ this.reporter.warn(this.reporter.lang('linkTargetMissing', entry));
+ await fs.unlink(entryPath);
+ }
} else if (stat.isDirectory() && entry[0] === '@') {
// if the entry is directory beginning with '@', then we're dealing with a package scope, which
// means we must iterate inside to retrieve the package names it contains
@@ -317,7 +322,13 @@ export default class PackageLinker {
if (stat2.isSymbolicLink()) {
const packageName = `${scopeName}/${entry2}`;
- linkTargets.set(packageName, await fs.readlink(entryPath2));
+ try {
+ const entryTarget = await fs.realpath(entryPath2);
+ linkTargets.set(packageName, entryTarget);
+ } catch (err) {
+ this.reporter.warn(this.reporter.lang('linkTargetMissing', packageName));
+ await fs.unlink(entryPath2);
+ }
}
}
}
@@ -334,7 +345,7 @@ export default class PackageLinker {
if (
(await fs.lstat(loc)).isSymbolicLink() &&
linkTargets.has(packageName) &&
- linkTargets.get(packageName) === (await fs.readlink(loc))
+ linkTargets.get(packageName) === (await fs.realpath(loc))
) {
possibleExtraneous.delete(loc);
copyQueue.delete(loc);
@@ -411,7 +422,7 @@ export default class PackageLinker {
topLevelDependencies,
async ([dest, pkg]) => {
if (pkg._reference && pkg._reference.location && pkg.bin && Object.keys(pkg.bin).length) {
- const binLoc = path.join(this.config.cwd, this.config.getFolder(pkg));
+ const binLoc = path.join(this.config.lockfileFolder, this.config.getFolder(pkg));
await this.linkSelfDependencies(pkg, dest, binLoc);
tickBin();
}
@@ -468,7 +479,7 @@ export default class PackageLinker {
let peerError = 'unmetPeer';
let resolvedLevelDistance = Infinity;
- let resolvedPeerPkgPattern;
+ let resolvedPeerPkg;
for (const peerPkg of peerPkgs) {
const peerPkgRef = peerPkg._reference;
if (!(peerPkgRef && peerPkgRef.patterns)) {
@@ -478,25 +489,31 @@ export default class PackageLinker {
if (isFinite(levelDistance) && levelDistance < resolvedLevelDistance) {
if (this._satisfiesPeerDependency(range, peerPkgRef.version)) {
resolvedLevelDistance = levelDistance;
- resolvedPeerPkgPattern = peerPkgRef.patterns;
- this.reporter.verbose(
- this.reporter.lang(
- 'selectedPeer',
- `${pkg.name}@${pkg.version}`,
- `${peerDepName}@${peerPkgRef.version}`,
- peerPkgRef.level,
- ),
- );
+ resolvedPeerPkg = peerPkgRef;
} else {
peerError = 'incorrectPeer';
}
}
}
- if (resolvedPeerPkgPattern) {
- ref.addDependencies(resolvedPeerPkgPattern);
+ if (resolvedPeerPkg) {
+ ref.addDependencies(resolvedPeerPkg.patterns);
+ this.reporter.verbose(
+ this.reporter.lang(
+ 'selectedPeer',
+ `${pkg.name}@${pkg.version}`,
+ `${peerDepName}@${resolvedPeerPkg.version}`,
+ resolvedPeerPkg.level,
+ ),
+ );
} else {
- this.reporter.warn(this.reporter.lang(peerError, `${pkg.name}@${pkg.version}`, `${peerDepName}@${range}`));
+ this.reporter.warn(
+ this.reporter.lang(
+ peerError,
+ `${refTree.join(' > ')} > ${pkg.name}@${pkg.version}`,
+ `${peerDepName}@${range}`,
+ ),
+ );
}
}
}
diff --git a/src/package-request.js b/src/package-request.js
index 5a36c19..25a1bbd 100644
--- a/src/package-request.js
+++ b/src/package-request.js
@@ -60,8 +60,9 @@ export default class PackageRequest {
if (shrunk && shrunk.resolved) {
const resolvedParts = versionUtil.explodeHashedUrl(shrunk.resolved);
- // If it's a private git url set remote to 'git'.
- const preferredRemoteType = resolvedParts.url.startsWith('git+ssh://') ? 'git' : remoteType;
+
+ // Detect Git protocols (git://HOST/PATH or git+PROTOCOL://HOST/PATH)
+ const preferredRemoteType = /^git(\+[a-z0-9]+)?:\/\//.test(resolvedParts.url) ? 'git' : remoteType;
return {
name: shrunk.name,
@@ -342,7 +343,6 @@ export default class PackageRequest {
reporter: Reporter,
filterByPatterns: ?Array<string>,
flags: ?Object,
- returnAllPackages: ?boolean,
): Promise<Array<Dependency>> {
const {requests: reqPatterns, workspaceLayout} = await install.fetchRequestFromCwd();
@@ -402,9 +402,8 @@ export default class PackageRequest {
// 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)));
+ latest === 'exotic' || (semver.lt(current, wanted) || semver.lt(current, latest));
const orderByName = (depA, depB) => depA.name.localeCompare(depB.name);
-
- return returnAllPackages ? deps.sort(orderByName) : deps.filter(isDepOld).sort(orderByName);
+ return deps.filter(isDepOld).sort(orderByName);
}
}
diff --git a/src/package-resolver.js b/src/package-resolver.js
index 8a76987..19b7f92 100644
--- a/src/package-resolver.js
+++ b/src/package-resolver.js
@@ -623,7 +623,9 @@ export default class PackageResolver {
invariant(resolutionManifest._reference, 'resolutions should have a resolved reference');
resolutionManifest._reference.patterns.push(pattern);
this.addPattern(pattern, resolutionManifest);
- this.lockfile.removePattern(pattern);
+ if (!this.resolutionMap.topLevelPatterns.has(pattern)) {
+ this.lockfile.removePattern(pattern);
+ }
} else {
this.resolutionMap.addToDelayQueue(req);
}
diff --git a/src/registries/npm-registry.js b/src/registries/npm-registry.js
index 124c777..4b72f43 100644
--- a/src/registries/npm-registry.js
+++ b/src/registries/npm-registry.js
@@ -5,6 +5,7 @@ import type RequestManager from '../util/request-manager.js';
import type {RegistryRequestOptions, CheckOutdatedReturn} from './base-registry.js';
import type Config from '../config.js';
import type {ConfigRegistries} from './index.js';
+import type {Env} from '../util/env-replace.js';
import {YARN_REGISTRY} from '../constants.js';
import * as fs from '../util/fs.js';
import NpmResolver from '../resolvers/registries/npm-resolver.js';
@@ -206,11 +207,20 @@ export default class NpmRegistry extends Registry {
return actuals;
}
+ static getConfigEnv(env: Env = process.env): Env {
+ // To match NPM's behavior, HOME is always the user's home directory.
+ const overrideEnv = {
+ HOME: home,
+ };
+ return Object.assign({}, env, overrideEnv);
+ }
+
static normalizeConfig(config: Object): Object {
+ const env = NpmRegistry.getConfigEnv();
config = Registry.normalizeConfig(config);
for (const key: string in config) {
- config[key] = envReplace(config[key]);
+ config[key] = envReplace(config[key], env);
if (isPathConfigOption(key)) {
config[key] = normalizePath(config[key]);
}
diff --git a/src/reporters/console/console-reporter.js b/src/reporters/console/console-reporter.js
index bf64bca..a1e047c 100644
--- a/src/reporters/console/console-reporter.js
+++ b/src/reporters/console/console-reporter.js
@@ -30,7 +30,7 @@ type Row = Array<string>;
type InquirerResponses<K, T> = {[key: K]: Array<T>};
// fixes bold on windows
-if (process.platform === 'win32' && process.env.TERM && !/^xterm/i.test(process.env.TERM)) {
+if (process.platform === 'win32' && !(process.env.TERM && /^xterm/i.test(process.env.TERM))) {
chalk.bold._styles[0].close += '\u001b[m';
}
diff --git a/src/reporters/console/util.js b/src/reporters/console/util.js
index 668566a..730f5a3 100644
--- a/src/reporters/console/util.js
+++ b/src/reporters/console/util.js
@@ -1,5 +1,6 @@
/* @flow */
+import tty from 'tty';
import type {Stdout} from '../types.js';
const readline = require('readline');
@@ -10,6 +11,12 @@ const CLEAR_RIGHT_OF_CURSOR = 1;
export function clearLine(stdout: Stdout) {
if (!supportsColor) {
+ if (stdout instanceof tty.WriteStream) {
+ if (stdout.columns > 0) {
+ stdout.write(`\r${' '.repeat(stdout.columns - 1)}`);
+ }
+ stdout.write(`\r`);
+ }
return;
}
@@ -19,6 +26,7 @@ export function clearLine(stdout: Stdout) {
export function toStartOfLine(stdout: Stdout) {
if (!supportsColor) {
+ stdout.write('\r');
return;
}
diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js
index ac0233d..8ab68cf 100644
--- a/src/reporters/lang/en.js
+++ b/src/reporters/lang/en.js
@@ -69,6 +69,7 @@ const messages = {
couldntFindVersionThatMatchesRange: "Couldn't find any versions for $0 that matches $1",
chooseVersionFromList: 'Please choose a version of $0 from this list:',
moduleNotInManifest: "This module isn't specified in a manifest.",
+ moduleAlreadyInManifest: '$0 is already in $1. Please remove existing entry first before adding it to $2.',
unknownFolderOrTarball: "Passed folder/tarball doesn't exist,",
unknownPackage: "Couldn't find package $0.",
unknownPackageName: "Couldn't find package name.",
@@ -172,6 +173,7 @@ const messages = {
linkUsing: 'Using linked module for $0.',
linkDisusing: 'Removed linked module $0.',
linkDisusingMessage: 'You will need to run `yarn` to re-install the package that was linked.',
+ linkTargetMissing: 'The target of linked module $0 is missing. Removing link.',
createInvalidBin: 'Invalid bin entry found in package $0.',
createMissingPackage:
@@ -361,7 +363,7 @@ const messages = {
deprecatedCommand: '$0 is deprecated. Please use $1.',
deprecatedListArgs: 'Filtering by arguments is deprecated. Please use the pattern option instead.',
implicitFileDeprecated:
- 'Using the "file:" protocol implicitly is deprecated. Please either the protocol or prepend the path $0 with "./".',
+ 'Using the "file:" protocol implicitly is deprecated. Please either prepend the protocol or prepend the path $0 with "./".',
unsupportedNodeVersion:
'You are using Node $0 which is not supported and may encounter bugs or unexpected behavior. Yarn supports the following semver range: $1',
diff --git a/src/resolution-map.js b/src/resolution-map.js
index fbc0af7..12e548d 100644
--- a/src/resolution-map.js
+++ b/src/resolution-map.js
@@ -33,12 +33,14 @@ export default class ResolutionMap {
this.config = config;
this.reporter = config.reporter;
this.delayQueue = new Set();
+ this.topLevelPatterns = new Set();
}
resolutionsByPackage: ResolutionInternalMap;
config: Config;
reporter: Reporter;
delayQueue: Set<DependencyRequestPattern>;
+ topLevelPatterns: Set<string>;
init(resolutions: ?ResolutionEntry = {}) {
for (const globPattern in resolutions) {
@@ -55,6 +57,10 @@ export default class ResolutionMap {
this.delayQueue.add(req);
}
+ setTopLevelPatterns(patterns: Array<string>) {
+ this.topLevelPatterns = new Set(patterns);
+ }
+
parsePatternInfo(globPattern: string, range: string): ?Object {
if (!isValidPackagePath(globPattern)) {
this.reporter.warn(this.reporter.lang('invalidResolutionName', globPattern));
diff --git a/src/resolvers/registries/npm-resolver.js b/src/resolvers/registries/npm-resolver.js
index b17fa7c..a2ed065 100644
--- a/src/resolvers/registries/npm-resolver.js
+++ b/src/resolvers/registries/npm-resolver.js
@@ -14,6 +14,7 @@ const inquirer = require('inquirer');
const tty = require('tty');
const invariant = require('invariant');
const path = require('path');
+const semver = require('semver');
const NPM_REGISTRY = /http[s]:\/\/registry.npmjs.org/g;
const NPM_REGISTRY_ID = 'npm';
@@ -41,6 +42,14 @@ export default class NpmResolver extends RegistryResolver {
range = body['dist-tags'][range];
}
+ // If the latest tag in the registry satisfies the requested range, then use that.
+ // Otherwise we will fall back to semver maxSatisfying.
+ // This mimics logic in NPM. See issue #3560
+ const latestVersion = body['dist-tags'] ? body['dist-tags'].latest : undefined;
+ if (latestVersion && semver.satisfies(latestVersion, range)) {
+ return body.versions[latestVersion];
+ }
+
const satisfied = await config.resolveConstraints(Object.keys(body.versions), range);
if (satisfied) {
return body.versions[satisfied];
diff --git a/src/util/env-replace.js b/src/util/env-replace.js
index 8e2bb62..dcee78a 100644
--- a/src/util/env-replace.js
+++ b/src/util/env-replace.js
@@ -1,7 +1,9 @@
/* @flow */
const ENV_EXPR = /(\\*)\$\{([^}]+)\}/g;
-export default function envReplace(value: string, env: {[key: string]: ?string} = process.env): string {
+export type Env = {[key: string]: ?string};
+
+export default function envReplace(value: string, env: Env = process.env): string {
if (typeof value !== 'string' || !value) {
return value;
}
diff --git a/src/util/git/git-spawn.js b/src/util/git/git-spawn.js
index b445bbd..50acd83 100644
--- a/src/util/git/git-spawn.js
+++ b/src/util/git/git-spawn.js
@@ -18,6 +18,10 @@ const sshExecutable = path.basename(sshCommand.toLowerCase(), '.exe');
const sshBatchArgs = BATCH_MODE_ARGS.get(sshExecutable);
if (!env.GIT_SSH_COMMAND && sshBatchArgs) {
+ // We have to manually specify `GIT_SSH_VARIANT`,
+ // because it's not automatically set when using `GIT_SSH_COMMAND` instead of `GIT_SSH`
+ // See: https://github.com/yarnpkg/yarn/issues/4729
+ env.GIT_SSH_VARIANT = sshExecutable;
env.GIT_SSH_COMMAND = `"${sshCommand}" ${sshBatchArgs}`;
}
diff --git a/src/util/normalize-manifest/fix.js b/src/util/normalize-manifest/fix.js
index 7adb848..8ce398e 100644
--- a/src/util/normalize-manifest/fix.js
+++ b/src/util/normalize-manifest/fix.js
@@ -1,6 +1,6 @@
/* @flow */
-import {DEPENDENCY_TYPES} from '../../constants';
+import {MANIFEST_FIELDS} from '../../constants';
import type {Reporter} from '../../reporters/index.js';
import {isValidLicense} from './util.js';
import {normalizePerson, extractDescription} from './util.js';
@@ -308,7 +308,7 @@ export default (async function(
}
}
- for (const dependencyType of DEPENDENCY_TYPES) {
+ for (const dependencyType of MANIFEST_FIELDS) {
const dependencyList = info[dependencyType];
if (dependencyList && typeof dependencyList === 'object') {
delete dependencyList['//'];
diff --git a/src/util/request-manager.js b/src/util/request-manager.js
index b8049e8..5c0f65f 100644
--- a/src/util/request-manager.js
+++ b/src/util/request-manager.js
@@ -412,9 +412,7 @@ export default class RequestManager {
if (params.url.startsWith('https:')) {
proxy = this.httpsProxy;
}
- if (proxy) {
- params.proxy = String(proxy);
- }
+ params.proxy = String(proxy);
if (this.ca != null) {
params.ca = this.ca;
--
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