feat(core): use the native hasher by default (#15071)
This commit is contained in:
parent
e575c49c3e
commit
7d80f25833
@ -8,12 +8,13 @@ import { join } from 'path';
|
||||
import { NativeFileHasher } from './native-file-hasher';
|
||||
|
||||
function createFileHasher(): FileHasherBase {
|
||||
// special case for unit tests
|
||||
if (workspaceRoot === '/root') {
|
||||
return new NodeBasedFileHasher();
|
||||
}
|
||||
try {
|
||||
if (process.env.NX_NATIVE_HASHER) {
|
||||
if (
|
||||
!(
|
||||
process.env.NX_NON_NATIVE_HASHER &&
|
||||
process.env.NX_NON_NATIVE_HASHER == 'false'
|
||||
)
|
||||
) {
|
||||
return new NativeFileHasher();
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import '../../utils/testing/mock-fs';
|
||||
import { TempFs } from '../../utils/testing/temp-fs';
|
||||
const tempFs = new TempFs('explicit-package-json');
|
||||
|
||||
import { buildExplicitPackageJsonDependencies } from './explicit-package-json-dependencies';
|
||||
import { vol } from 'memfs';
|
||||
|
||||
import { createProjectFileMap } from '../file-map-utils';
|
||||
import { defaultFileHasher } from '../../hasher/file-hasher';
|
||||
import {
|
||||
@ -9,15 +11,11 @@ import {
|
||||
} from '../../config/project-graph';
|
||||
import { ProjectGraphBuilder } from '../project-graph-builder';
|
||||
|
||||
jest.mock('nx/src/utils/workspace-root', () => ({
|
||||
workspaceRoot: '/root',
|
||||
}));
|
||||
|
||||
describe('explicit package json dependencies', () => {
|
||||
let ctx: ProjectGraphProcessorContext;
|
||||
let projects: Record<string, ProjectGraphProjectNode>;
|
||||
let fsJson;
|
||||
beforeEach(() => {
|
||||
|
||||
beforeEach(async () => {
|
||||
const projectsConfigurations = {
|
||||
projects: {
|
||||
proj: {
|
||||
@ -39,12 +37,12 @@ describe('explicit package json dependencies', () => {
|
||||
npmScope: 'proj',
|
||||
};
|
||||
|
||||
fsJson = {
|
||||
await tempFs.createFiles({
|
||||
'./package.json': `{
|
||||
"name": "test",
|
||||
"dependencies": [],
|
||||
"devDependencies": []
|
||||
}`,
|
||||
"name": "test",
|
||||
"dependencies": [],
|
||||
"devDependencies": []
|
||||
}`,
|
||||
'./nx.json': JSON.stringify(nxJsonConfiguration),
|
||||
'./tsconfig.base.json': JSON.stringify({}),
|
||||
'./libs/proj2/package.json': JSON.stringify({ name: 'proj2' }),
|
||||
@ -53,10 +51,9 @@ describe('explicit package json dependencies', () => {
|
||||
dependencies: { proj2: '*', external: '12.0.0' },
|
||||
devDependencies: { proj3: '*' },
|
||||
}),
|
||||
};
|
||||
vol.fromJSON(fsJson, '/root');
|
||||
});
|
||||
|
||||
defaultFileHasher.init();
|
||||
await defaultFileHasher.init();
|
||||
|
||||
ctx = {
|
||||
projectsConfigurations,
|
||||
@ -89,6 +86,10 @@ describe('explicit package json dependencies', () => {
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
tempFs.cleanup();
|
||||
});
|
||||
|
||||
it(`should add dependencies for projects based on deps in package.json`, () => {
|
||||
const builder = new ProjectGraphBuilder();
|
||||
Object.values(projects).forEach((p) => {
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import '../../utils/testing/mock-fs';
|
||||
import { vol } from 'memfs';
|
||||
import { TempFs } from '../../utils/testing/temp-fs';
|
||||
const tempFs = new TempFs('explicit-project-deps');
|
||||
|
||||
import { defaultFileHasher } from '../../hasher/file-hasher';
|
||||
import { createProjectFileMap } from '../file-map-utils';
|
||||
import { ProjectGraphBuilder } from '../project-graph-builder';
|
||||
import { buildExplicitTypeScriptDependencies } from './explicit-project-dependencies';
|
||||
|
||||
jest.mock('nx/src/utils/workspace-root', () => ({
|
||||
workspaceRoot: '/root',
|
||||
}));
|
||||
|
||||
// projectName => tsconfig import path
|
||||
const dependencyProjectNamesToImportPaths = {
|
||||
proj2: '@proj/my-second-proj',
|
||||
@ -18,13 +15,13 @@ const dependencyProjectNamesToImportPaths = {
|
||||
|
||||
describe('explicit project dependencies', () => {
|
||||
beforeEach(() => {
|
||||
vol.reset();
|
||||
tempFs.reset();
|
||||
});
|
||||
|
||||
describe('static imports, dynamic imports, and commonjs requires', () => {
|
||||
it('should build explicit dependencies for static imports, and top-level dynamic imports and commonjs requires', () => {
|
||||
it('should build explicit dependencies for static imports, and top-level dynamic imports and commonjs requires', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -68,9 +65,9 @@ describe('explicit project dependencies', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should build explicit dependencies for static exports', () => {
|
||||
it('should build explicit dependencies for static exports', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -108,9 +105,9 @@ describe('explicit project dependencies', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it(`should build explicit dependencies for TypeScript's import/export require syntax, and side-effectful import`, () => {
|
||||
it(`should build explicit dependencies for TypeScript's import/export require syntax, and side-effectful import`, async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -148,9 +145,9 @@ describe('explicit project dependencies', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should build explicit dependencies for nested dynamic imports and commonjs requires', () => {
|
||||
it('should build explicit dependencies for nested dynamic imports and commonjs requires', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -209,9 +206,9 @@ describe('explicit project dependencies', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should build explicit dependencies when relative paths are used', () => {
|
||||
it('should build explicit dependencies when relative paths are used', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -248,9 +245,9 @@ describe('explicit project dependencies', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not build explicit dependencies when nx-ignore-next-line comments are present', () => {
|
||||
it('should not build explicit dependencies when nx-ignore-next-line comments are present', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -340,9 +337,9 @@ describe('explicit project dependencies', () => {
|
||||
expect(res).toEqual([]);
|
||||
});
|
||||
|
||||
it('should not build explicit dependencies for stringified or templatized import/require statements', () => {
|
||||
it('should not build explicit dependencies for stringified or templatized import/require statements', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -423,9 +420,9 @@ describe('explicit project dependencies', () => {
|
||||
* https://angular.io/guide/deprecations#loadchildren-string-syntax
|
||||
*/
|
||||
describe('legacy Angular loadChildren string syntax', () => {
|
||||
it('should build explicit dependencies for legacy Angular loadChildren string syntax', () => {
|
||||
it('should build explicit dependencies for legacy Angular loadChildren string syntax', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -476,9 +473,9 @@ describe('explicit project dependencies', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not build explicit dependencies when nx-ignore-next-line comments are present', () => {
|
||||
it('should not build explicit dependencies when nx-ignore-next-line comments are present', async () => {
|
||||
const sourceProjectName = 'proj';
|
||||
const { ctx, builder } = createVirtualWorkspace({
|
||||
const { ctx, builder } = await createVirtualWorkspace({
|
||||
sourceProjectName,
|
||||
sourceProjectFiles: [
|
||||
{
|
||||
@ -544,7 +541,7 @@ interface VirtualWorkspaceConfig {
|
||||
* Prepares a minimal workspace and virtual file-system for the given files and dependency
|
||||
* projects in order to be able to execute `buildExplicitTypeScriptDependencies()` in the tests.
|
||||
*/
|
||||
function createVirtualWorkspace(config: VirtualWorkspaceConfig) {
|
||||
async function createVirtualWorkspace(config: VirtualWorkspaceConfig) {
|
||||
const nxJson = {
|
||||
npmScope: 'proj',
|
||||
};
|
||||
@ -625,9 +622,9 @@ function createVirtualWorkspace(config: VirtualWorkspaceConfig) {
|
||||
|
||||
fsJson['./tsconfig.base.json'] = JSON.stringify(tsConfig);
|
||||
|
||||
vol.fromJSON(fsJson, '/root');
|
||||
await tempFs.createFiles(fsJson);
|
||||
|
||||
defaultFileHasher.init();
|
||||
await defaultFileHasher.init();
|
||||
|
||||
return {
|
||||
ctx: {
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
import '../utils/testing/mock-fs';
|
||||
import { TempFs } from '../utils/testing/temp-fs';
|
||||
const tempFs = new TempFs('explicit-package-json');
|
||||
|
||||
import { vol, fs } from 'memfs';
|
||||
|
||||
jest.mock('nx/src/utils/workspace-root', () => ({
|
||||
workspaceRoot: '/root',
|
||||
}));
|
||||
import { buildProjectGraph } from './build-project-graph';
|
||||
import * as fastGlob from 'fast-glob';
|
||||
import { defaultFileHasher } from '../hasher/file-hasher';
|
||||
import { ProjectsConfigurations } from '../config/workspace-json-project-json';
|
||||
import { NxJsonConfiguration } from '../config/nx-json';
|
||||
import { stripIndents } from '../utils/strip-indents';
|
||||
import { DependencyType } from '../config/project-graph';
|
||||
@ -16,7 +11,6 @@ import { DependencyType } from '../config/project-graph';
|
||||
describe('project graph', () => {
|
||||
let packageJson: any;
|
||||
let packageLockJson: any;
|
||||
let projects: ProjectsConfigurations;
|
||||
let nxJson: NxJsonConfiguration;
|
||||
let tsConfigJson: any;
|
||||
let filesJson: any;
|
||||
@ -190,8 +184,8 @@ describe('project graph', () => {
|
||||
'./apps/api/project.json': JSON.stringify(apiProjectJson),
|
||||
};
|
||||
|
||||
vol.reset();
|
||||
vol.fromJSON(filesJson, '/root');
|
||||
tempFs.reset();
|
||||
await tempFs.createFiles(filesJson);
|
||||
await defaultFileHasher.init();
|
||||
|
||||
const globResults = [
|
||||
@ -208,17 +202,13 @@ describe('project graph', () => {
|
||||
});
|
||||
|
||||
it('should throw an appropriate error for an invalid json config', async () => {
|
||||
vol.appendFileSync('/root/tsconfig.base.json', 'invalid');
|
||||
tempFs.appendFile('tsconfig.base.json', 'invalid');
|
||||
try {
|
||||
await buildProjectGraph();
|
||||
fail('Invalid tsconfigs should cause project graph to throw error');
|
||||
} catch (e) {
|
||||
expect(e.message).toMatchInlineSnapshot(`
|
||||
"InvalidSymbol in /root/tsconfig.base.json at 1:248
|
||||
[0m[31m[1m>[22m[39m[90m 1 | [39m{\\"compilerOptions\\":{\\"baseUrl\\":\\".\\",\\"paths\\":{\\"@nrwl/shared/util\\":[\\"libs/shared/util/src/index.ts\\"],\\"@nrwl/shared-util-data\\":[\\"libs/shared/util/data/src/index.ts\\"],\\"@nrwl/ui\\":[\\"libs/ui/src/index.ts\\"],\\"@nrwl/lazy-lib\\":[\\"libs/lazy-lib/src/index.ts\\"]}}}invalid[0m
|
||||
[0m [90m | [39m [31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[31m[1m^[22m[39m[0m
|
||||
"
|
||||
`);
|
||||
expect(e.message).toContain(`${tempFs.tempDir}/tsconfig.base.json`);
|
||||
expect(e.message).toContain(`invalid`);
|
||||
}
|
||||
});
|
||||
|
||||
@ -284,8 +274,8 @@ describe('project graph', () => {
|
||||
});
|
||||
|
||||
it('should handle circular dependencies', async () => {
|
||||
fs.writeFileSync(
|
||||
'/root/libs/shared/util/src/index.ts',
|
||||
tempFs.writeFile(
|
||||
'libs/shared/util/src/index.ts',
|
||||
`import * as ui from '@nrwl/ui';`
|
||||
);
|
||||
|
||||
|
||||
57
packages/nx/src/utils/testing/temp-fs.ts
Normal file
57
packages/nx/src/utils/testing/temp-fs.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import { join } from 'path';
|
||||
import { tmpdir } from 'os';
|
||||
import {
|
||||
mkdtempSync,
|
||||
readFile,
|
||||
outputFile,
|
||||
rmSync,
|
||||
emptyDirSync,
|
||||
} from 'fs-extra';
|
||||
import { joinPathFragments } from '../path';
|
||||
import { appendFileSync, writeFileSync } from 'fs';
|
||||
|
||||
type NestedFiles = {
|
||||
[fileName: string]: string;
|
||||
};
|
||||
|
||||
export class TempFs {
|
||||
readonly tempDir: string;
|
||||
constructor(private dirname: string, overrideWorkspaceRoot = true) {
|
||||
this.tempDir = mkdtempSync(join(tmpdir(), this.dirname));
|
||||
if (overrideWorkspaceRoot) {
|
||||
process.env.NX_WORKSPACE_ROOT_PATH = this.tempDir;
|
||||
}
|
||||
}
|
||||
|
||||
async createFiles(fileObject: NestedFiles) {
|
||||
await Promise.all(
|
||||
Object.keys(fileObject).map(async (path) => {
|
||||
await this.createFile(path, fileObject[path]);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async createFile(filePath: string, content: string) {
|
||||
await outputFile(joinPathFragments(this.tempDir, filePath), content);
|
||||
}
|
||||
|
||||
async readFile(filePath: string): Promise<string> {
|
||||
return await readFile(filePath, 'utf-8');
|
||||
}
|
||||
|
||||
appendFile(filePath: string, content: string) {
|
||||
appendFileSync(joinPathFragments(this.tempDir, filePath), content);
|
||||
}
|
||||
|
||||
writeFile(filePath: string, content: string) {
|
||||
writeFileSync(joinPathFragments(this.tempDir, filePath), content);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rmSync(this.tempDir, { recursive: true });
|
||||
}
|
||||
|
||||
reset() {
|
||||
emptyDirSync(this.tempDir);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user