diff --git a/__tests__/commands/upgrade.js b/__tests__/commands/upgrade.js index d449d61dd2..12f5aefbd8 100644 --- a/__tests__/commands/upgrade.js +++ b/__tests__/commands/upgrade.js @@ -102,6 +102,70 @@ test.concurrent('upgrades from fixed version to latest', (): Promise => { }); }); +test.concurrent('upgrades to latest matching package.json semver when no package name passed', (): Promise => { + return runUpgrade([], {}, 'range-to-latest', async (config): ?Promise => { + const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); + const lockEntryIndex = lockfile.indexOf('left-pad@<=1.1.1:'); + + expect(lockEntryIndex).toEqual(0); + expect(lockfile[lockEntryIndex + 1]).toContain('1.1.1'); + expect(pkg.dependencies).toEqual({'left-pad': '<=1.1.1'}); + }); +}); + +test.concurrent('--latest upgrades to latest ignoring package.json when no package name passed', (): Promise => { + return runUpgrade([], {latest: true}, 'range-to-latest', async (config): ?Promise => { + const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); + const lockEntryIndex = lockfile.indexOf('left-pad@^1.1.3:'); + + expect(lockEntryIndex).toEqual(0); + expect(lockfile.indexOf('left-pad@<=1.1.1:')).toEqual(-1); + expect(lockfile[lockEntryIndex + 1]).toContain('1.1.3'); + expect(pkg.dependencies).toEqual({'left-pad': '^1.1.3'}); + }); +}); + +test.concurrent('upgrades to latest matching semver when package name passed with version', (): Promise => { + return runUpgrade(['left-pad@~1.1.2'], {}, 'range-to-latest', async (config): ?Promise => { + const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); + const lockEntryIndex = lockfile.indexOf('left-pad@~1.1.2:'); + + expect(lockEntryIndex).toEqual(0); + expect(lockfile[lockEntryIndex + 1]).toContain('1.1.3'); + expect(pkg.dependencies).toEqual({'left-pad': '~1.1.2'}); + }); +}); + +test.concurrent('--latest upgrades to passed in version when package name passed with version', (): Promise => { + return runUpgrade(['left-pad@1.1.2'], {latest: true}, 'range-to-latest', async (config): ?Promise => { + const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); + const lockEntryIndex = lockfile.indexOf('left-pad@1.1.2:'); + + expect(lockEntryIndex).toEqual(0); + expect(lockfile.indexOf('left-pad@<=1.1.1:')).toEqual(-1); + expect(lockfile.indexOf('left-pad@^1.1.3:')).toEqual(-1); + expect(lockfile[lockEntryIndex + 1]).toContain('1.1.2'); + expect(pkg.dependencies).toEqual({'left-pad': '1.1.2'}); + }); +}); + +test.concurrent('upgrades to latest ignoring package.json semver when package name passed', (): Promise => { + return runUpgrade(['left-pad'], {}, 'range-to-latest', async (config): ?Promise => { + const lockfile = explodeLockfile(await fs.readFile(path.join(config.cwd, 'yarn.lock'))); + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); + const lockEntryIndex = lockfile.indexOf('left-pad@^1.1.3:'); + + expect(lockEntryIndex).toEqual(0); + expect(lockfile.indexOf('left-pad@<=1.1.1:')).toEqual(-1); + expect(lockfile[lockEntryIndex + 1]).toContain('1.1.3'); + expect(pkg.dependencies).toEqual({'left-pad': '^1.1.3'}); + }); +}); + test.concurrent('upgrades dependency packages not in registry', (): Promise => { const packages = ['yarn-test-git-repo', 'e2e-test-repo']; return runUpgrade(packages, {}, 'package-not-in-registry', async (config): ?Promise => { diff --git a/__tests__/fixtures/upgrade/range-to-latest/package.json b/__tests__/fixtures/upgrade/range-to-latest/package.json new file mode 100644 index 0000000000..d533bb520c --- /dev/null +++ b/__tests__/fixtures/upgrade/range-to-latest/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "left-pad": "<=1.1.1" + } +} diff --git a/src/cli/commands/upgrade.js b/src/cli/commands/upgrade.js index 9d45cc18bb..a4ee926df1 100644 --- a/src/cli/commands/upgrade.js +++ b/src/cli/commands/upgrade.js @@ -11,6 +11,7 @@ export function setFlags(commander: Object) { // TODO: support some flags that install command has commander.usage('upgrade [flags]'); commander.option('-S, --scope ', 'upgrade packages under the specified scope'); + commander.option('--latest', 'upgrade packages to the latest version, ignoring version ranges in package.json'); } export function hasWrapper(): boolean { @@ -20,7 +21,8 @@ export function hasWrapper(): boolean { export const requireLockfile = true; export async function run(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { - const lockfile = args.length ? await Lockfile.fromDirectory(config.lockfileFolder, reporter) : new Lockfile(); + const useLockfile = args.length || flags.latest; + const lockfile = useLockfile ? await Lockfile.fromDirectory(config.lockfileFolder, reporter) : new Lockfile(); const { dependencies, devDependencies, @@ -50,6 +52,9 @@ export async function run(config: Config, reporter: Reporter, flags: Object, arg } else { throw new MessageError(reporter.lang('scopeNotValid')); } + } else if (flags.latest && args.length === 0) { + addArgs = Object.keys(allDependencies) + .map(dependency => getDependency(allDependencies, dependency)); } else { addArgs = args.map(dependency => { return getDependency(allDependencies, dependency);