Skip to content

Commit 6ccf465

Browse files
Broccohansl
authored andcommitted
fix(@angular/cli): Update project root determination
fixes #10513
1 parent 0add4c9 commit 6ccf465

File tree

4 files changed

+187
-28
lines changed

4 files changed

+187
-28
lines changed

package-lock.json

Lines changed: 19 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@angular/cli/lib/cli/index.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as path from 'path';
22
import { filter } from 'rxjs/operators';
33
import { logging, terminal } from '@angular-devkit/core';
44
import { runCommand } from '../../models/command-runner';
5-
import { findUp } from '../../utilities/find-up';
5+
import { getProjectDetails } from '../../utilities/project';
66

77

88
function loadCommands() {
@@ -53,15 +53,12 @@ export default async function(options: any) {
5353
loggingSubscription = initializeLogging(logger);
5454
}
5555

56-
const possibleConfigNames = ['angular.json', '.angular.json'];
57-
const workspacePath = findUp(possibleConfigNames, process.cwd());
58-
const projectRoot = workspacePath !== null
59-
? path.dirname(workspacePath)
60-
: process.cwd();
56+
let projectDetails = getProjectDetails();
57+
if (projectDetails === null) {
58+
projectDetails = { root: process.cwd() };
59+
}
6160
const context = {
62-
project: {
63-
root: projectRoot
64-
}
61+
project: projectDetails
6562
};
6663

6764
try {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,65 @@
1+
import * as fs from 'fs';
2+
import * as os from 'os';
3+
import * as path from 'path';
14
import { findUp } from './find-up';
25

36
export function insideProject(): boolean {
47
const possibleConfigFiles = ['angular.json', '.angular.json'];
58

69
return findUp(possibleConfigFiles, process.cwd()) !== null;
710
}
11+
12+
export interface ProjectDetails {
13+
root: string;
14+
configFile?: string;
15+
}
16+
17+
export function getProjectDetails(): ProjectDetails | null {
18+
const currentDir = process.cwd();
19+
const possibleConfigFiles = [
20+
'angular.json',
21+
'.angular.json',
22+
'angular-cli.json',
23+
'.angular-cli.json',
24+
];
25+
const configFilePath = findUp(possibleConfigFiles, currentDir);
26+
if (configFilePath === null) {
27+
return null;
28+
}
29+
const configFileName = path.basename(configFilePath);
30+
31+
const possibleDir = path.dirname(configFilePath);
32+
33+
const homedir = os.homedir();
34+
if (possibleDir === homedir) {
35+
const packageJsonPath = path.join(possibleDir, 'package.json');
36+
if (!fs.existsSync(packageJsonPath)) {
37+
// No package.json
38+
return null;
39+
}
40+
const packageJsonBuffer = fs.readFileSync(packageJsonPath);
41+
const packageJsonText = packageJsonBuffer === null ? '{}' : packageJsonBuffer.toString();
42+
const packageJson = JSON.parse(packageJsonText);
43+
if (!containsCliDep(packageJson)) {
44+
// No CLI dependency
45+
return null;
46+
}
47+
}
48+
return {
49+
root: possibleDir,
50+
configFile: configFileName,
51+
};
52+
}
53+
54+
function containsCliDep(obj: any): boolean {
55+
const pkgName = '@angular/cli';
56+
if (obj) {
57+
if (obj.dependencies && obj.dependencies[pkgName]) {
58+
return true;
59+
}
60+
if (obj.devDependencies && obj.devDependencies[pkgName]) {
61+
return true;
62+
}
63+
}
64+
return false;
65+
}

tests/acceptance/project.spec.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { getProjectDetails } from '@angular/cli/utilities/project';
2+
import * as mockFs from 'mock-fs';
3+
import * as os from 'os';
4+
import {join} from 'path';
5+
6+
const homedir = os.homedir();
7+
const cwds = [`${homedir}/proj`, `${homedir}/proj/abc`];
8+
cwds.forEach(cwd => {
9+
describe(`getProjectDetails (cwd: ${cwd})`, () => {
10+
beforeEach(() => {
11+
spyOn(process, 'cwd').and.callFake(() => cwd);
12+
});
13+
14+
afterEach(() => {
15+
mockFs.restore();
16+
});
17+
18+
it('should handle finding "angular.json"', () => {
19+
mockFs({
20+
[`${homedir}/proj/angular.json`]: 'foo'
21+
});
22+
const result = getProjectDetails();
23+
expect(result.root).toEqual(join(homedir, 'proj'));
24+
expect(result.configFile).toEqual('angular.json');
25+
});
26+
27+
it('should handle finding ".angular.json"', () => {
28+
mockFs({
29+
[`${homedir}/proj/.angular.json`]: 'foo'
30+
});
31+
const result = getProjectDetails();
32+
expect(result.root).toEqual(join(homedir, 'proj'));
33+
expect(result.configFile).toEqual('.angular.json');
34+
});
35+
36+
it('should handle finding "angular-cli.json"', () => {
37+
mockFs({
38+
[`${homedir}/proj/angular-cli.json`]: 'foo'
39+
});
40+
const result = getProjectDetails();
41+
expect(result.root).toEqual(join(homedir, 'proj'));
42+
expect(result.configFile).toEqual('angular-cli.json');
43+
});
44+
45+
it('should handle finding ".angular-cli.json"', () => {
46+
mockFs({
47+
[`${homedir}/proj/.angular-cli.json`]: 'foo'
48+
});
49+
const result = getProjectDetails();
50+
expect(result.root).toEqual(join(homedir, 'proj'));
51+
expect(result.configFile).toEqual('.angular-cli.json');
52+
});
53+
54+
it('should handle not finding a config file at all', () => {
55+
mockFs({});
56+
const result = getProjectDetails();
57+
expect(result).toEqual(null);
58+
});
59+
60+
it('should handle searching up the home directory', () => {
61+
mockFs({
62+
[`${homedir}/angular.json`]: 'foo'
63+
});
64+
const result = getProjectDetails();
65+
expect(result).toEqual(null);
66+
});
67+
68+
it('should handle searching up the home directory', () => {
69+
mockFs({
70+
[`${homedir}/.angular-cli.json`]: 'foo'
71+
});
72+
const result = getProjectDetails();
73+
expect(result).toEqual(null);
74+
});
75+
76+
it('should handle searching up the home directory and finding a project', () => {
77+
mockFs({
78+
[`${homedir}/angular.json`]: 'foo',
79+
[`${homedir}/package.json`]: JSON.stringify({
80+
dependencies: {
81+
'@angular/cli': '0.0.0'
82+
}
83+
})
84+
});
85+
const result = getProjectDetails();
86+
expect(result.root).toEqual(homedir);
87+
expect(result.configFile).toEqual('angular.json');
88+
});
89+
90+
it('should handle searching up the home directory and finding a project', () => {
91+
mockFs({
92+
[`${homedir}/.angular-cli.json`]: 'foo',
93+
[`${homedir}/package.json`]: JSON.stringify({
94+
dependencies: {
95+
'@angular/cli': '0.0.0'
96+
}
97+
})
98+
});
99+
const result = getProjectDetails();
100+
expect(result.root).toEqual(homedir);
101+
expect(result.configFile).toEqual('.angular-cli.json');
102+
});
103+
});
104+
});

0 commit comments

Comments
 (0)