Skip to content

Commit

Permalink
improve bit link --rewire to preserve the internal paths (#2839)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidfirst committed Jul 14, 2020
1 parent a759288 commit bc90436
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 19 deletions.
48 changes: 43 additions & 5 deletions src/consumer/component-ops/codemod-components.ts
@@ -1,11 +1,12 @@
import path from 'path';
import Component from '../component/consumer-component';
import { SourceFile } from '../component/sources';
import { RelativeComponentsAuthoredEntry } from '../component/dependencies/dependency-resolver/dependencies-resolver';
import componentIdToPackageName from '../../utils/bit/component-id-to-package-name';
import replacePackageName from '../../utils/string/replace-package-name';
import DataToPersist from '../component/sources/data-to-persist';
import { BitId, BitIds } from '../../bit-id';
import { pathNormalizeToLinux } from '../../utils';
import { pathNormalizeToLinux, pathJoinLinux, pathRelativeLinux } from '../../utils';
import { Consumer } from '..';
import IncorrectRootDir from '../component/exceptions/incorrect-root-dir';
import { ImportSpecifier } from '../component/dependencies/files-dependency-builder/types/dependency-tree-type';
Expand All @@ -24,7 +25,7 @@ export async function changeCodeFromRelativeToModulePaths(
const componentsWithRelativeIssues = components.filter(c => c.issues && c.issues.relativeComponentsAuthored);
const dataToPersist = new DataToPersist();
const codemodResults = componentsWithRelativeIssues.map(component => {
const { files, warnings } = codemodComponent(component);
const { files, warnings } = codemodComponent(consumer, component);
dataToPersist.addManyFiles(files);
return { id: component.id, changedFiles: files.map(f => f.relative), warnings };
});
Expand All @@ -42,7 +43,7 @@ async function loadComponents(consumer: Consumer, bitIds: BitId[]): Promise<Comp
return components;
}

function codemodComponent(component: Component): { files: SourceFile[]; warnings?: string[] } {
function codemodComponent(consumer: Consumer, component: Component): { files: SourceFile[]; warnings?: string[] } {
const issues = component.issues;
const files: SourceFile[] = [];
if (!issues || !issues.relativeComponentsAuthored) return { files };
Expand All @@ -55,7 +56,7 @@ function codemodComponent(component: Component): { files: SourceFile[]; warnings
let newFileString = fileBefore;
relativeInstances.forEach((relativeEntry: RelativeComponentsAuthoredEntry) => {
const id = relativeEntry.componentId;
if (isLinkFileHasDifferentImportType(relativeEntry.importSpecifiers)) {
if (isLinkFileHasDifferentImportType(relativeEntry.relativePath.importSpecifiers)) {
warnings.push(
`"${file.relative}" requires "${id.toString()}" through a link-file ("${
relativeEntry.importSource
Expand All @@ -67,7 +68,8 @@ function codemodComponent(component: Component): { files: SourceFile[]; warnings
const cssFamily = ['.css', '.scss', '.less', '.sass'];
const isCss = cssFamily.includes(file.extname);
const packageNameSupportCss = isCss ? `~${packageName}` : packageName;
newFileString = replacePackageName(newFileString, relativeEntry.importSource, packageNameSupportCss);
const stringToReplace = getNameWithoutInternalPath(consumer, relativeEntry);
newFileString = replacePackageName(newFileString, stringToReplace, packageNameSupportCss);
});
if (fileBefore !== newFileString) {
// @ts-ignore
Expand All @@ -78,6 +80,42 @@ function codemodComponent(component: Component): { files: SourceFile[]; warnings
return { files, warnings };
}

/**
* e.g.
* importSource: '../workspace/workspace.ui'
* sourceRelativePath: 'extensions/workspace/workspace.ui.tsx'
* rootDir in .bitmap: 'extensions/workspace'.
*
* expected to return "../workspace", as this is the path to the package root without the internal path.
*
* eventually, only this string is replaced by the new package-name and the internal-path part
* remains intact. ('../workspace/workspace.ui' => '@bit/workspace/workspace.ui').
*/
function getNameWithoutInternalPath(consumer: Consumer, relativeEntry: RelativeComponentsAuthoredEntry): string {
const importSource = relativeEntry.importSource;
const componentMap = consumer.bitMap.getComponentIfExist(relativeEntry.componentId);
if (!componentMap) return importSource;
const rootDir = componentMap.trackDir || componentMap.rootDir;
if (!rootDir) return importSource;
const mainFile = componentMap.trackDir ? componentMap.mainFile : pathJoinLinux(rootDir, componentMap.mainFile);
const filePathRelativeToWorkspace = relativeEntry.relativePath.sourceRelativePath;
if (filePathRelativeToWorkspace === mainFile) {
return importSource;
}
// the importSource is not the main-file but an internal file, remove the internal part.
const internalPath = pathRelativeLinux(rootDir, filePathRelativeToWorkspace);
const removeLastOccurrence = (str, toRemove) => str.replace(new RegExp(`/${toRemove}$`), '');
if (importSource.endsWith(internalPath)) {
return removeLastOccurrence(importSource, internalPath);
}
const internalPathNoExt = internalPath.replace(path.extname(internalPath), '');
if (importSource.endsWith(internalPathNoExt)) {
return removeLastOccurrence(importSource, internalPathNoExt);
}
// unable to find anything useful. just return the importSource.
return importSource;
}

/**
* if this is a link-file (a file that only import and export other files), bit doesn't require
* the user to track it and it knows to skip it. If however, the link file uses default import and
Expand Down
Expand Up @@ -53,7 +53,7 @@ export interface UntrackedFileDependencyEntry {
export type RelativeComponentsAuthoredEntry = {
importSource: string;
componentId: BitId;
importSpecifiers: ImportSpecifier[] | undefined;
relativePath: RelativePath;
};

type UntrackedDependenciesIssues = Record<string, UntrackedFileDependencyEntry>;
Expand Down Expand Up @@ -617,12 +617,7 @@ either, use the ignore file syntax or change the require statement to have a mod
this._pushToRelativeComponentsIssues(originFile, componentId);
return false;
}
this._pushToRelativeComponentsAuthoredIssues(
originFile,
componentId,
depFileObject.importSource,
depsPaths.importSpecifiers
);
this._pushToRelativeComponentsAuthoredIssues(originFile, componentId, depFileObject.importSource, depsPaths);

const allDependencies: Dependency[] = [
...this.allDependencies.dependencies,
Expand Down Expand Up @@ -1149,16 +1144,11 @@ either, use the ignore file syntax or change the require statement to have a mod
this.issues.relativeComponents[originFile] = [componentId];
}
}
_pushToRelativeComponentsAuthoredIssues(
originFile,
componentId,
importSource: string,
importSpecifiers: ImportSpecifier[] | undefined
) {
_pushToRelativeComponentsAuthoredIssues(originFile, componentId, importSource: string, relativePath: RelativePath) {
if (!this.issues.relativeComponentsAuthored[originFile]) {
this.issues.relativeComponentsAuthored[originFile] = [];
}
this.issues.relativeComponentsAuthored[originFile].push({ importSource, componentId, importSpecifiers });
this.issues.relativeComponentsAuthored[originFile].push({ importSource, componentId, relativePath });
}
_pushToMissingBitsIssues(originFile: PathLinuxRelative, componentId: BitId) {
this.issues.missingBits[originFile]
Expand Down

0 comments on commit bc90436

Please sign in to comment.