Skip to content

Commit

Permalink
Explicitly mark ignored deps of non-ignored packages as non-ignored (y…
Browse files Browse the repository at this point in the history
  • Loading branch information
blexrob committed Jan 22, 2017
1 parent 93fa0f7 commit 1246b14
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 10 deletions.
2 changes: 1 addition & 1 deletion __tests__/commands/install/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ test.concurrent('a subdependency of an optional dependency that fails should be
});

// disabled while fix is not merged
test.skip('should not loose dependencies when installing with --production',
test.concurrent('should not loose dependencies when installing with --production',
(): Promise<void> => {
// revealed https://github.com/yarnpkg/yarn/issues/2263
return runInstall({production: true}, 'prod-should-keep-subdeps', async (config) => {
Expand Down
2 changes: 1 addition & 1 deletion __tests__/package-hoister.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ test('Produces valid destination paths for scoped modules', () => {
_reference: (({}: any): PackageReference),
}: any): Manifest);

const info = new HoistManifest(key, parts, pkg, '', () => false);
const info = new HoistManifest(key, parts, pkg, '', false, false);

const tree = new Map([
['@scoped/dep', info],
Expand Down
79 changes: 71 additions & 8 deletions src/package-hoister.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ type Parts = Array<string>;
let historyCounter = 0;

export class HoistManifest {
constructor(key: string, parts: Parts, pkg: Manifest, loc: string, isIgnored: () => boolean) {
constructor(key: string, parts: Parts, pkg: Manifest, loc: string, isIgnored: boolean, inheritIsIgnored: boolean) {
this.isIgnored = isIgnored;
this.inheritIsIgnored = inheritIsIgnored;
this.loc = loc;
this.pkg = pkg;

Expand All @@ -27,7 +28,8 @@ export class HoistManifest {
this.addHistory(`Start position = ${key}`);
}

isIgnored: () => boolean;
isIgnored: boolean;
inheritIsIgnored: boolean;
pkg: Manifest;
loc: string;
parts: Parts;
Expand Down Expand Up @@ -92,6 +94,7 @@ export default class PackageHoister {
while (true) {
let queue = this.levelQueue;
if (!queue.length) {
this._propagateNonIgnored();
return;
}

Expand Down Expand Up @@ -130,16 +133,18 @@ export default class PackageHoister {

//
let parentParts: Parts = [];
let isIgnored = () => ref.ignore;
let isIgnored = ref.ignore;
let inheritIsIgnored = false;

if (parent) {
if (!this.tree.get(parent.key)) {
return null;
}
// non ignored dependencies inherit parent's ignored status
// parent may transition from ignored to non ignored when hoisted if it is used in another non ignored branch
if (!isIgnored() && parent.isIgnored()) {
isIgnored = () => !!parent && parent.isIgnored();
if (!isIgnored && parent.isIgnored) {
isIgnored = parent.isIgnored;
inheritIsIgnored = true;
}
parentParts = parent.parts;
}
Expand All @@ -148,7 +153,7 @@ export default class PackageHoister {
const loc: string = this.config.generateHardModulePath(ref);
const parts = parentParts.concat(pkg.name);
const key: string = this.implodeKey(parts);
const info: HoistManifest = new HoistManifest(key, parts, pkg, loc, isIgnored);
const info: HoistManifest = new HoistManifest(key, parts, pkg, loc, isIgnored, inheritIsIgnored);

//
this.tree.set(key, info);
Expand All @@ -162,6 +167,64 @@ export default class PackageHoister {
return info;
}

/**
* Propagate inherited ignore statuses from non-ignored to ignored packages
*/

_propagateNonIgnored() {
//
const tovisit: Array<HoistManifest> = [];

// enumerate all non-ignored packages
for (const entry of this.tree.entries()) {
if (!entry[1].isIgnored) {
tovisit.push(entry[1]);
}
}

// visit them
while (tovisit.length) {
const info = tovisit.shift();
const ref = info.pkg._reference;
invariant(ref, 'expected reference');

for (const depPattern of ref.dependencies) {
//
const depinfo = this._lookupDependency(info, depPattern);

//
if (depinfo && depinfo.isIgnored && depinfo.inheritIsIgnored) {
depinfo.isIgnored = false;
info.addHistory(`Mark as non-ignored because of usage by ${info.key}`);
tovisit.push(depinfo);
}
}
}
}

/**
* Looks up the package a dependency resolved to
*/

_lookupDependency(info: HoistManifest, depPattern: string): ?HoistManifest {
//
const pkg = this.resolver.getStrictResolvedPattern(depPattern);
const ref = pkg._reference;
invariant(ref, 'expected reference');

//
for (let i = info.parts.length; i >= 0; i--) {
const checkParts = info.parts.slice(0, i).concat(pkg.name);
const checkKey = this.implodeKey(checkParts);
const existing = this.tree.get(checkKey);
if (existing) {
return existing;
}
}

return null;
}

/**
* Find the highest position we can hoist this module to.
*/
Expand All @@ -186,7 +249,7 @@ export default class PackageHoister {
if (existing) {
if (existing.loc === info.loc) {
// switch to non ignored if earlier deduped version was ignored
if (existing.isIgnored() && !info.isIgnored()) {
if (existing.isIgnored && !info.isIgnored) {
existing.isIgnored = info.isIgnored;
}

Expand Down Expand Up @@ -392,7 +455,7 @@ export default class PackageHoister {
const ref = info.pkg._reference;
invariant(ref, 'expected reference');

if (info.isIgnored()) {
if (info.isIgnored) {
info.addHistory('Deleted as this module was ignored');
} else {
visibleFlatTree.push([loc, info]);
Expand Down

0 comments on commit 1246b14

Please sign in to comment.