Skip to content

Commit b11af51

Browse files
committed
fix(@angular-devkit/schematics): bundle of small fixes
Empty host is now a HostTree. Branches are now real branch where changing the original Tree does not affect the new branch.
1 parent 68bff2e commit b11af51

File tree

3 files changed

+107
-12
lines changed

3 files changed

+107
-12
lines changed

packages/angular_devkit/schematics/src/tree/empty.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { VirtualTree } from './virtual';
8+
import { HostTree } from './host-tree';
99

1010

11-
export class EmptyTree extends VirtualTree {
11+
export class EmptyTree extends HostTree {
1212
constructor() { super(); }
1313
}

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

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
normalize,
1717
virtualFs,
1818
} from '@angular-devkit/core';
19+
import { ReadonlyHost } from '../../../core/src/virtual-fs/host';
20+
import { CordHostRecord } from '../../../core/src/virtual-fs/host/record';
1921
import {
2022
ContentHasMutatedException,
2123
FileAlreadyExistException,
@@ -99,21 +101,94 @@ export class HostTree implements Tree {
99101

100102
private _dirCache = new Map<Path, HostDirEntry>();
101103

104+
102105
[TreeSymbol]() {
103106
return this;
104107
}
105108

106-
constructor(backend: virtualFs.ReadonlyHost<{}> = new virtualFs.Empty()) {
107-
this._record = new virtualFs.CordHost(new virtualFs.SafeReadonlyHost(backend));
109+
constructor(protected _backend: virtualFs.ReadonlyHost<{}> = new virtualFs.Empty()) {
110+
this._record = new virtualFs.CordHost(new virtualFs.SafeReadonlyHost(_backend));
108111
this._recordSync = new virtualFs.SyncDelegateHost(this._record);
109112
}
110113

111114
protected _normalizePath(path: string): Path {
112115
return normalize('/' + path);
113116
}
114117

118+
protected _willCreate(path: Path) {
119+
let current: ReadonlyHost = this._record;
120+
while (current && current != this._backend) {
121+
if (!(current instanceof virtualFs.CordHost)) {
122+
break;
123+
}
124+
125+
if (current.willCreate(path)) {
126+
return true;
127+
}
128+
129+
current = current.backend;
130+
}
131+
132+
return false;
133+
}
134+
protected _willOverwrite(path: Path) {
135+
let current: ReadonlyHost = this._record;
136+
while (current && current != this._backend) {
137+
if (!(current instanceof virtualFs.CordHost)) {
138+
break;
139+
}
140+
141+
if (current.willOverwrite(path)) {
142+
return true;
143+
}
144+
145+
current = current.backend;
146+
}
147+
148+
return false;
149+
}
150+
protected _willDelete(path: Path) {
151+
let current: ReadonlyHost = this._record;
152+
while (current && current != this._backend) {
153+
if (!(current instanceof virtualFs.CordHost)) {
154+
break;
155+
}
156+
157+
if (current.willDelete(path)) {
158+
return true;
159+
}
160+
161+
current = current.backend;
162+
}
163+
164+
return false;
165+
}
166+
protected _willRename(path: Path) {
167+
let current: ReadonlyHost = this._record;
168+
while (current && current != this._backend) {
169+
if (!(current instanceof virtualFs.CordHost)) {
170+
break;
171+
}
172+
173+
if (current.willRename(path)) {
174+
return true;
175+
}
176+
177+
current = current.backend;
178+
}
179+
180+
return false;
181+
}
182+
183+
115184
branch(): Tree {
116-
return new HostTree(this._record);
185+
// Freeze our own records, and swap. This is so the branch and this Tree don't share the same
186+
// history anymore.
187+
const record = this._record;
188+
this._record = new virtualFs.CordHost(record);
189+
this._recordSync = new virtualFs.SyncDelegateHost(this._record);
190+
191+
return new HostTree(record);
117192
}
118193

119194
merge(other: Tree, strategy: MergeStrategy = MergeStrategy.Default): void {
@@ -138,7 +213,7 @@ export class HostTree implements Tree {
138213
case 'c': {
139214
const { path, content } = action;
140215

141-
if ((this._record.willCreate(path) || this._record.willOverwrite(path))) {
216+
if ((this._willCreate(path) || this._willOverwrite(path))) {
142217
if (!creationConflictAllowed) {
143218
throw new MergeConflictException(path);
144219
}
@@ -155,7 +230,7 @@ export class HostTree implements Tree {
155230
const { path, content } = action;
156231

157232
// Ignore if content is the same (considered the same change).
158-
if (this._record.willOverwrite(path) && !overwriteConflictAllowed) {
233+
if (this._willOverwrite(path) && !overwriteConflictAllowed) {
159234
throw new MergeConflictException(path);
160235
}
161236
// We use write here as merge validation has already been done, and we want to let
@@ -167,7 +242,7 @@ export class HostTree implements Tree {
167242

168243
case 'r': {
169244
const { path, to } = action;
170-
if (this._record.willRename(path)) {
245+
if (this._willRename(path)) {
171246
// No override possible for renaming.
172247
throw new MergeConflictException(path);
173248
}
@@ -178,7 +253,7 @@ export class HostTree implements Tree {
178253

179254
case 'd': {
180255
const { path } = action;
181-
if (this._record.willDelete(path) && !deleteConflictAllowed) {
256+
if (this._willDelete(path) && !deleteConflictAllowed) {
182257
throw new MergeConflictException(path);
183258
}
184259
this._recordSync.delete(path);
@@ -235,7 +310,12 @@ export class HostTree implements Tree {
235310
return maybeCache;
236311
}
237312
visit(visitor: FileVisitor): void {
238-
this.root.visit(visitor);
313+
const allFiles: [Path, FileEntry | null | undefined][] = [];
314+
this.root.visit((path, entry) => {
315+
allFiles.push([path, entry]);
316+
});
317+
318+
allFiles.forEach(([path, entry]) => visitor(path, entry));
239319
}
240320

241321
// Change content of host files.
@@ -290,8 +370,21 @@ export class HostTree implements Tree {
290370
throw new SchematicsException('Apply not implemented on host trees.');
291371
}
292372
get actions(): Action[] {
373+
// Create a list of all records until we hit our original backend. This is to support branches
374+
// that diverge from each others.
375+
const allRecords: CordHostRecord[] = [...this._record.records()];
376+
let current = this._record.backend;
377+
while (current != this._backend) {
378+
if (!(current instanceof virtualFs.CordHost)) {
379+
break;
380+
}
381+
382+
allRecords.unshift(...current.records());
383+
current = current.backend;
384+
}
385+
293386
return clean(
294-
this._record.records()
387+
allRecords
295388
.map(record => {
296389
switch (record.kind) {
297390
case 'create':

packages/angular_devkit/schematics/src/tree/static.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import { FilePredicate, MergeStrategy, Tree } from './interface';
1111
import { VirtualTree } from './virtual';
1212

1313

14-
export function empty() { return new VirtualTree(); }
14+
export function empty() {
15+
return new HostTree();
16+
}
1517

1618
export function branch(tree: Tree) {
1719
if (tree instanceof HostTree) {

0 commit comments

Comments
 (0)