Skip to content

Commit 0529260

Browse files
author
Kaylie Kwon
committed
WIP
1 parent 5e19f03 commit 0529260

File tree

13 files changed

+162
-37
lines changed

13 files changed

+162
-37
lines changed

__tests__/commands/install/resolutions.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,10 @@ test.concurrent('install with simple exact resolutions should override all versi
1717

1818
test.concurrent('install with subtree exact resolutions should override subtree versions', (): Promise<void> => {
1919
return runInstall({}, {source: 'resolutions', cwd: 'subtree-exact'}, async config => {
20-
expect(await getPackageVersion(config, 'a')).toEqual('1.0.0');
21-
expect(await getPackageVersion(config, 'b')).toEqual('1.0.0');
22-
expect(await getPackageVersion(config, 'd1')).toEqual('3.0.0');
23-
expect(await getPackageVersion(config, 'b/d1')).toEqual('2.0.0');
20+
expect(await getPackageVersion(config, 'left-pad')).toEqual('1.0.0');
2421
expect(await getPackageVersion(config, 'd2')).toEqual('1.0.0');
25-
expect(await isPackagePresent(config, 'a/d1')).toEqual(false);
26-
expect(await isPackagePresent(config, 'a/d2')).toEqual(false);
27-
expect(await isPackagePresent(config, 'b/d2')).toEqual(false);
22+
expect(await getPackageVersion(config, 'd2/left-pad')).toEqual('1.1.1');
23+
expect(await getPackageVersion(config, 'c')).toEqual('1.0.0');
24+
expect(await getPackageVersion(config, 'c/left-pad')).toEqual('1.1.2');
2825
});
2926
});

__tests__/fixtures/install/resolutions/c-1/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"name": "c",
33
"version": "1.0.0",
44
"dependencies": {
5-
"a": "file:../a-2"
5+
"left-pad": "~1.1.1"
66
}
77
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{
22
"name": "d2",
3-
"version": "1.0.0"
3+
"version": "1.0.0",
4+
"dependencies": {
5+
"left-pad": "^1.0.0"
6+
}
47
}

__tests__/fixtures/install/resolutions/subtree-exact/package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
"name": "project",
33
"version": "1.0.0",
44
"dependencies": {
5-
"a": "file:../a-1",
6-
"b": "file:../b-1"
5+
"left-pad": "1.0.0",
6+
"c": "file:../c-1",
7+
"d2": "file:../d2-1"
78
},
89
"resolutions": {
9-
"a/d1": "file:../d1-3"
10+
"d2/left-pad": "1.1.1",
11+
"c/**/left-pad": "1.1.2"
1012
}
1113
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"gulp-util": "^3.0.7",
7777
"gulp-watch": "^4.3.5",
7878
"jest": "20.0.4",
79+
"minimatch": "^3.0.4",
7980
"mock-stdin": "^0.3.0",
8081
"prettier": "^1.5.2",
8182
"temp": "^0.8.3",

src/cli/commands/import.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class ImportPackageRequest extends PackageRequest {
177177
}
178178

179179
getParentHumanName(): string {
180-
return [this.getRootName()].concat(this.getParentNames()).join(' > ');
180+
return [this.getRootName()].concat(this.parentNames).join(' > ');
181181
}
182182

183183
reportResolvedRangeMatch(info: Manifest, resolved: Manifest) {

src/cli/commands/install.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import * as fs from '../../util/fs.js';
2626
import map from '../../util/map.js';
2727
import {version as YARN_VERSION, getInstallationMethod} from '../../util/yarn-version.js';
2828
import WorkspaceLayout from '../../workspace-layout.js';
29+
import Resolutions from '../../resolutions.js';
2930

3031
const emoji = require('node-emoji');
3132
const invariant = require('invariant');
@@ -165,13 +166,13 @@ export class Install {
165166
constructor(flags: Object, config: Config, reporter: Reporter, lockfile: Lockfile) {
166167
this.rootManifestRegistries = [];
167168
this.rootPatternsToOrigin = map();
168-
this.resolutions = map();
169169
this.lockfile = lockfile;
170170
this.reporter = reporter;
171171
this.config = config;
172172
this.flags = normalizeFlags(config, flags);
173-
174-
this.resolver = new PackageResolver(config, lockfile);
173+
this.resolutions = map();
174+
this._resolutions = new Resolutions(config);
175+
this.resolver = new PackageResolver(config, lockfile, this._resolutions);
175176
this.integrityChecker = new InstallationIntegrityChecker(config);
176177
this.linker = new PackageLinker(config, this.resolver);
177178
this.scripts = new PackageInstallScripts(config, this.resolver, this.flags.force);
@@ -189,6 +190,7 @@ export class Install {
189190
linker: PackageLinker;
190191
rootPatternsToOrigin: {[pattern: string]: string};
191192
integrityChecker: InstallationIntegrityChecker;
193+
_resolutions: Resolutions;
192194

193195
/**
194196
* Create a list of dependency requests from the current directories manifests.
@@ -231,6 +233,7 @@ export class Install {
231233
const projectManifestJson = await this.config.readJson(loc);
232234
await normalizeManifest(projectManifestJson, this.config.lockfileFolder, this.config, true);
233235

236+
this._resolutions.init(projectManifestJson.resolutions);
234237
Object.assign(this.resolutions, projectManifestJson.resolutions);
235238
Object.assign(manifest, projectManifestJson);
236239

src/package-request.js

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type ResolverRegistryNames = $Keys<typeof registryResolvers>;
2525
export default class PackageRequest {
2626
constructor(req: DependencyRequestPattern, resolver: PackageResolver) {
2727
this.parentRequest = req.parentRequest;
28+
this.parentNames = [];
2829
this.lockfile = resolver.lockfile;
2930
this.registry = req.registry;
3031
this.reporter = resolver.reporter;
@@ -38,6 +39,7 @@ export default class PackageRequest {
3839
}
3940

4041
parentRequest: ?PackageRequest;
42+
parentNames: Array<string>;
4143
lockfile: Lockfile;
4244
reporter: Reporter;
4345
resolver: PackageResolver;
@@ -47,20 +49,6 @@ export default class PackageRequest {
4749
optional: boolean;
4850
foundInfo: ?Manifest;
4951

50-
getParentNames(): Array<string> {
51-
const chain = [];
52-
53-
let request = this.parentRequest;
54-
while (request) {
55-
const info = this.resolver.getStrictResolvedPattern(request.pattern);
56-
chain.unshift(info.name);
57-
58-
request = request.parentRequest;
59-
}
60-
61-
return chain;
62-
}
63-
6452
getLocked(remoteType: string): ?Object {
6553
// always prioritise root lockfile
6654
const shrunk = this.lockfile.getLocked(this.pattern);
@@ -110,7 +98,6 @@ export default class PackageRequest {
11098
// "foo": "http://foo.com/bar.tar.gz"
11199
// then we use the foo name
112100
data.name = name;
113-
114101
return data;
115102
}
116103

@@ -267,6 +254,7 @@ export default class PackageRequest {
267254
!info.fresh || frozen
268255
? this.resolver.getExactVersionMatch(name, solvedRange, info)
269256
: this.resolver.getHighestRangeVersionMatch(name, solvedRange, info);
257+
270258
if (resolved) {
271259
this.resolver.reportPackageWithExistingVersion(this, info);
272260
return;
@@ -290,11 +278,10 @@ export default class PackageRequest {
290278
ref.setFresh(fresh);
291279
info._reference = ref;
292280
info._remote = remote;
293-
294281
// start installation of dependencies
295282
const promises = [];
296283
const deps = [];
297-
284+
const parentNames = [...this.parentNames, name];
298285
// normal deps
299286
for (const depName in info.dependencies) {
300287
const depPattern = depName + '@' + info.dependencies[depName];
@@ -306,6 +293,7 @@ export default class PackageRequest {
306293
// dependencies of optional dependencies should themselves be optional
307294
optional: this.optional,
308295
parentRequest: this,
296+
parentNames,
309297
}),
310298
);
311299
}
@@ -320,6 +308,7 @@ export default class PackageRequest {
320308
registry: remote.registry,
321309
optional: true,
322310
parentRequest: this,
311+
parentNames,
323312
}),
324313
);
325314
}
@@ -334,6 +323,7 @@ export default class PackageRequest {
334323
registry: remote.registry,
335324
optional: false,
336325
parentRequest: this,
326+
parentNames,
337327
}),
338328
);
339329
}

src/package-resolver.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import BlockingQueue from './util/blocking-queue.js';
1212
import Lockfile from './lockfile/wrapper.js';
1313
import map from './util/map.js';
1414
import WorkspaceLayout from './workspace-layout.js';
15+
import Resolutions from './resolutions';
1516

1617
const invariant = require('invariant');
1718
const semver = require('semver');
@@ -23,11 +24,12 @@ export type ResolverOptions = {|
2324
|};
2425

2526
export default class PackageResolver {
26-
constructor(config: Config, lockfile: Lockfile) {
27+
constructor(config: Config, lockfile: Lockfile, resolutions: Resolutions) {
2728
this.patternsByPackage = map();
2829
this.fetchingPatterns = map();
2930
this.fetchingQueue = new BlockingQueue('resolver fetching');
3031
this.patterns = map();
32+
this.resolutions = resolutions || new Resolutions(config);
3133
this.usedRegistries = new Set();
3234
this.flat = false;
3335

@@ -44,6 +46,8 @@ export default class PackageResolver {
4446

4547
workspaceLayout: ?WorkspaceLayout;
4648

49+
resolutions: Resolutions;
50+
4751
// list of registries that have been used in this resolution
4852
usedRegistries: Set<RegistryNames>;
4953

@@ -358,7 +362,8 @@ export default class PackageResolver {
358362
*/
359363

360364
getResolvedPattern(pattern: string): ?Manifest {
361-
return this.patterns[pattern];
365+
const resolutionPattern = this.resolutions.getResolutionByPattern(pattern) || pattern;
366+
return this.patterns[resolutionPattern];
362367
}
363368

364369
/**
@@ -450,8 +455,10 @@ export default class PackageResolver {
450455
* TODO description
451456
*/
452457

453-
async find(req: DependencyRequestPattern): Promise<void> {
458+
async find(initialReq: DependencyRequestPattern): Promise<void> {
459+
const req = this.resolveToResolution(initialReq);
454460
const fetchKey = `${req.registry}:${req.pattern}`;
461+
455462
if (this.fetchingPatterns[fetchKey]) {
456463
return;
457464
} else {
@@ -532,4 +539,20 @@ export default class PackageResolver {
532539
req.resolveToExistingVersion(info);
533540
}
534541
}
542+
543+
resolveToResolution(req: DependencyRequestPattern): ?string {
544+
const {parentNames, pattern} = req;
545+
546+
if (!parentNames) {
547+
return req;
548+
}
549+
550+
const resolution = this.resolutions.find(pattern, parentNames);
551+
552+
if (resolution) {
553+
req.pattern = resolution;
554+
}
555+
556+
return req;
557+
}
535558
}

src/reporters/lang/en.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ const messages = {
117117
'Pattern $0 is trying to unpack in the same destination $1 as pattern $2. This could result in a non deterministic behavior, skipping.',
118118
incorrectLockfileEntry: 'Lockfile has incorrect entry for $0. Ignoring it.',
119119

120+
invalidResolutionName: 'Resolution field $0 does not end with a valid package name and will be ignored',
121+
invalidResolutionVersion: 'Resolution field $0 has an invalid version entry and may be ignored',
122+
incompatibleResolutionVersion: 'Resolution field $0 is incompatible with requested version $1',
123+
120124
yarnOutdated: "Your current version of Yarn is out of date. The latest version is $0 while you're on $1.",
121125
yarnOutdatedInstaller: 'To upgrade, download the latest installer at $0.',
122126
yarnOutdatedCommand: 'To upgrade, run the following command:',

0 commit comments

Comments
 (0)