Skip to content

Commit 8bf63b6

Browse files
committed
fix(@angular-devkit/schematics): Fix merge that causes an overwrite
This fixes #11337 to allow for merging of a tree with another when the the file already exists in the tree being merged into.
1 parent cc51432 commit 8bf63b6

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

packages/angular_devkit/schematics/src/tree/host-tree.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class HostDirEntry implements DirEntry {
5656
readonly path: Path,
5757
protected _host: virtualFs.SyncDelegateHost,
5858
protected _tree: Tree,
59-
) {}
59+
) { }
6060

6161
get subdirs(): PathFragment[] {
6262
return this._host.list(this.path)
@@ -180,7 +180,7 @@ export class HostTree implements Tree {
180180
case 'c': {
181181
const { path, content } = action;
182182

183-
if ((this._willCreate(path) || this._willOverwrite(path))) {
183+
if (this._willCreate(path) || this._willOverwrite(path) || this.exists(path)) {
184184
const existingContent = this.read(path);
185185
if (existingContent && content.equals(existingContent)) {
186186
// Identical outcome; no action required

packages/angular_devkit/schematics/src/tree/host-tree_spec.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,47 @@
77
*/
88
import { normalize, virtualFs } from '@angular-devkit/core';
99
import { FilterHostTree, HostTree } from './host-tree';
10+
import { MergeStrategy } from './interface';
1011

1112
describe('HostTree', () => {
13+
describe('merge', () => {
14+
it('should create files from each tree', () => {
15+
const tree = new HostTree();
16+
tree.create('/file1', 'a');
17+
const tree2 = new HostTree();
18+
tree2.create('/file2', 'a');
19+
tree.merge(tree2);
20+
expect(tree.actions[0].kind).toEqual('c');
21+
expect(tree.actions[1].kind).toEqual('c');
22+
});
23+
24+
it('should overwrite if the file exists in one tree', () => {
25+
const tree = new HostTree();
26+
tree.create('/file1', 'a');
27+
const tree2 = new HostTree();
28+
tree2.create('/file1', 'b');
29+
tree.merge(tree2, MergeStrategy.Overwrite);
30+
expect(tree.actions[0].kind).toEqual('c');
31+
});
1232

33+
it('should throw if the file exists in one tree with the correct MergeStrategy', () => {
34+
const tree = new HostTree();
35+
tree.create('/file1', 'a');
36+
const tree2 = new HostTree();
37+
tree2.create('/file1', 'b');
38+
expect(() => tree.merge(tree2)).toThrow();
39+
});
40+
41+
it('should not have a second action if the file content is the same', () => {
42+
const tree = new HostTree();
43+
tree.create('/file1', 'a');
44+
const tree2 = new HostTree();
45+
tree2.create('/file1', 'a');
46+
tree.merge(tree2, MergeStrategy.Overwrite);
47+
expect(tree.actions[0].kind).toEqual('c');
48+
expect(tree.actions.length).toEqual(1);
49+
});
50+
});
1351
});
1452

1553
describe('FilterHostTree', () => {

tests/legacy-cli/e2e/tests/generate/component/component-duplicate.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ng } from '../../../utils/process';
22
import { expectToFail } from '../../../utils/utils';
33
import { oneLine } from 'common-tags';
4+
import { readFileSync, writeFileSync } from 'fs';
45

56
export default function () {
67
return ng('generate', 'component', 'test-component')
@@ -12,5 +13,10 @@ export default function () {
1213
in ${output.stdout}.`);
1314
}
1415
})
16+
.then(() => {
17+
const filePath = 'src/app.component.ts';
18+
const contents = '// new content\n' + readFileSync(filePath);
19+
writeFileSync(filePath, contents);
20+
})
1521
.then(() => expectToFail(() => ng('generate', 'component', 'test-component')));
1622
}

0 commit comments

Comments
 (0)