Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(import-dependents), fix algorithm to get some missing paths #8669

Merged
merged 4 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion e2e/harmony/import-harmony.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,19 +382,26 @@ describe('import functionality on Harmony', function () {
// create the following graph:
// comp1 -> comp2 -> comp3 -> comp4
// comp1 -> comp-a -> comp4
// comp1 -> comp-a2 -> comp3 -> comp4
// comp1 -> comp-b
before(() => {
helper = new Helper();
helper.scopeHelper.setNewLocalAndRemoteScopes();
helper.fixtures.populateComponents(4);
helper.fs.outputFile('comp-a/index.js', `require('${helper.general.getPackageNameByCompName('comp4', false)}');`);
helper.fs.outputFile(
'comp-a2/index.js',
`require('${helper.general.getPackageNameByCompName('comp3', false)}');`
);
helper.fs.outputFile('comp-b/index.js');
helper.command.addComponent('comp-a');
helper.command.addComponent('comp-b');
helper.command.addComponent('comp-a2');
helper.command.compile();
helper.fs.appendFile(
'comp1/index.js',
`\nrequire('${helper.general.getPackageNameByCompName('comp-a', false)}');`
`\nrequire('${helper.general.getPackageNameByCompName('comp-a', false)}');
require('${helper.general.getPackageNameByCompName('comp-a2', false)}')`
);
helper.fs.appendFile(
'comp1/index.js',
Expand All @@ -415,6 +422,7 @@ describe('import functionality on Harmony', function () {
expect(bitMap).to.have.property('comp3');
expect(bitMap).to.have.property('comp4');
expect(bitMap).to.have.property('comp-a');
expect(bitMap).to.have.property('comp-a2');
expect(bitMap).to.not.have.property('comp-b');
});
it('with --dependents-via should limit to graph traversing through the given id', () => {
Expand Down
46 changes: 23 additions & 23 deletions scopes/component/graph/component-id-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,32 +94,33 @@ export class ComponentIdGraph extends Graph<ComponentID, DepEdgeType> {
through?: ComponentID[]
): string[][] {
const removeVerFromIdStr = (idStr: string) => idStr.split('@')[0];
const targetsStr = targets.map((t) => t.toStringWithoutVersion());

const traverseDFS = (
node: string,
visitedInPath: string[],
visitedInGraph: string[] = [],
allPaths: string[][]
) => {
if (visitedInPath.includes(node)) return;
visitedInPath.push(node);
if (targetsStr.includes(removeVerFromIdStr(node))) {
allPaths.push(visitedInPath);
return;
const findAllPathsBFS = (start: string[], end: string[]): string[][] => {
const paths: string[][] = [];
const visited = new Set<string>();
const queue: { node: string; path: string[] }[] = [];
start.forEach((s) => queue.push({ node: s, path: [s] }));
while (queue.length) {
const { node, path } = queue.shift()!;
if (end.includes(removeVerFromIdStr(node))) {
paths.push([...path]);
} else {
visited.add(node);
const successors = this.outEdges(node).map((e) => e.targetId);
for (const successor of successors) {
if (!visited.has(successor)) {
queue.push({ node: successor, path: [...path, successor] });
}
}
}
}
if (visitedInGraph.includes(node)) return;
visitedInGraph.push(node);
const successors = Array.from(this.successorMap(node).values());
successors.forEach((s) => {
traverseDFS(s.id, [...visitedInPath], visitedInGraph, allPaths);
});
return paths;
};

let allPaths: string[][] = [];
sources.forEach((source) => {
traverseDFS(source.toString(), [], [], allPaths);
});
const targetsStr = targets.map((t) => t.toStringWithoutVersion());
const sourcesStr = sources.map((s) => s.toString());

let allPaths = findAllPathsBFS(sourcesStr, targetsStr);

if (through?.length) {
allPaths = allPaths.filter((pathWithVer) => {
Expand All @@ -128,7 +129,6 @@ export class ComponentIdGraph extends Graph<ComponentID, DepEdgeType> {
});
}

const sourcesStr = sources.map((s) => s.toString());
const filtered = allPaths.filter((path) => {
if (path.length < 3) {
// if length is 1, the source and target are the same.
Expand Down
6 changes: 3 additions & 3 deletions scopes/scope/importer/dependents-getter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class DependentsGetter {

async getDependents(targetCompIds: ComponentID[]): Promise<ComponentID[]> {
this.logger.setStatusLine('finding dependents');
const { silent } = this.options;
const { silent, dependentsAll } = this.options;
const graph = await this.graph.getGraphIds();
const sourceIds = this.workspace.listIds();
const getIdsForThrough = () => {
Expand All @@ -34,7 +34,7 @@ export class DependentsGetter {
.map((id) => ComponentID.fromString(id));
};
const allPaths = graph.findAllPathsFromSourcesToTargets(sourceIds, targetCompIds, getIdsForThrough());
const selectedPaths = silent ? allPaths : await this.promptDependents(allPaths);
const selectedPaths = silent || dependentsAll ? allPaths : await this.promptDependents(allPaths);
const uniqAsStrings = uniq(selectedPaths.flat());

const ids: ComponentID[] = [];
Expand Down Expand Up @@ -72,7 +72,7 @@ export class DependentsGetter {
this.logger.clearStatusLine();

const totalToShow = SHOW_ALL_PATHS_LIMIT;
if (allPaths.length >= totalToShow) {
if (allPaths.length > totalToShow) {
return this.promptLevelByLevel(allPaths);
}
const firstItems = allPaths.slice(0, totalToShow);
Expand Down
4 changes: 3 additions & 1 deletion scopes/scope/importer/import-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export type ImportOptions = {
importDependenciesDirectly?: boolean; // default: false, normally it imports them as packages, not as imported
importDependents?: boolean;
dependentsVia?: string;
dependentsAll?: boolean;
silent?: boolean; // don't show prompt for --dependents flag
fromOriginalScope?: boolean; // default: false, otherwise, it fetches flattened dependencies from their dependents
saveInLane?: boolean; // save the imported component on the current lane (won't be available on main)
Expand Down Expand Up @@ -442,7 +443,8 @@ bit import ${idsFromRemote.map((id) => id.toStringWithoutVersion()).join(' ')}`)
const bitIds: ComponentID[] = this.options.lanes
? await this.getBitIdsForLanes()
: await this.getBitIdsForNonLanes();
const shouldImportDependents = this.options.importDependents || this.options.dependentsVia;
const shouldImportDependents =
this.options.importDependents || this.options.dependentsVia || this.options.dependentsAll;
if (this.options.importDependenciesDirectly || shouldImportDependents) {
if (this.options.importDependenciesDirectly) {
const dependenciesIds = await this.getFlattenedDepsUnique(bitIds);
Expand Down
8 changes: 8 additions & 0 deletions scopes/scope/importer/import.cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type ImportFlags = {
dependents?: boolean;
dependentsDryRun?: boolean;
dependentsVia?: string;
dependentsAll?: boolean;
silent?: boolean;
allHistory?: boolean;
fetchDeps?: boolean;
Expand Down Expand Up @@ -85,6 +86,11 @@ export class ImportCmd implements Command {
'dependents-via <string>',
'same as --dependents except the traversal must go through the specified component. to specify multiple components, wrap with quotes and separate by a comma',
],
[
'',
'dependents-all',
'same as --dependents except not prompting for selecting paths but rather selecting all paths and showing final confirmation before importing',
],
[
'',
'dependents-dry-run',
Expand Down Expand Up @@ -214,6 +220,7 @@ export class ImportCmd implements Command {
dependentsDryRun = false,
silent,
dependentsVia,
dependentsAll,
allHistory = false,
fetchDeps = false,
trackOnly = false,
Expand Down Expand Up @@ -268,6 +275,7 @@ export class ImportCmd implements Command {
importDependenciesDirectly: dependencies,
importDependents: dependents,
dependentsVia,
dependentsAll,
silent,
allHistory,
fetchDeps,
Expand Down