Skip to content

Commit

Permalink
fix(@angular-devkit/schematics): bundle of small fixes
Browse files Browse the repository at this point in the history
Empty host is now a HostTree.

Branches are now real branch where changing the original Tree does not affect
the new branch.
  • Loading branch information
hansl committed Jun 6, 2018
1 parent 68bff2e commit b11af51
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 12 deletions.
4 changes: 2 additions & 2 deletions packages/angular_devkit/schematics/src/tree/empty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { VirtualTree } from './virtual';
import { HostTree } from './host-tree';


export class EmptyTree extends VirtualTree {
export class EmptyTree extends HostTree {
constructor() { super(); }
}
111 changes: 102 additions & 9 deletions packages/angular_devkit/schematics/src/tree/host-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
normalize,
virtualFs,
} from '@angular-devkit/core';
import { ReadonlyHost } from '../../../core/src/virtual-fs/host';
import { CordHostRecord } from '../../../core/src/virtual-fs/host/record';
import {
ContentHasMutatedException,
FileAlreadyExistException,
Expand Down Expand Up @@ -99,21 +101,94 @@ export class HostTree implements Tree {

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


[TreeSymbol]() {
return this;
}

constructor(backend: virtualFs.ReadonlyHost<{}> = new virtualFs.Empty()) {
this._record = new virtualFs.CordHost(new virtualFs.SafeReadonlyHost(backend));
constructor(protected _backend: virtualFs.ReadonlyHost<{}> = new virtualFs.Empty()) {
this._record = new virtualFs.CordHost(new virtualFs.SafeReadonlyHost(_backend));
this._recordSync = new virtualFs.SyncDelegateHost(this._record);
}

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

protected _willCreate(path: Path) {
let current: ReadonlyHost = this._record;
while (current && current != this._backend) {
if (!(current instanceof virtualFs.CordHost)) {
break;
}

if (current.willCreate(path)) {
return true;
}

current = current.backend;
}

return false;
}
protected _willOverwrite(path: Path) {
let current: ReadonlyHost = this._record;
while (current && current != this._backend) {
if (!(current instanceof virtualFs.CordHost)) {
break;
}

if (current.willOverwrite(path)) {
return true;
}

current = current.backend;
}

return false;
}
protected _willDelete(path: Path) {
let current: ReadonlyHost = this._record;
while (current && current != this._backend) {
if (!(current instanceof virtualFs.CordHost)) {
break;
}

if (current.willDelete(path)) {
return true;
}

current = current.backend;
}

return false;
}
protected _willRename(path: Path) {
let current: ReadonlyHost = this._record;
while (current && current != this._backend) {
if (!(current instanceof virtualFs.CordHost)) {
break;
}

if (current.willRename(path)) {
return true;
}

current = current.backend;
}

return false;
}


branch(): Tree {
return new HostTree(this._record);
// Freeze our own records, and swap. This is so the branch and this Tree don't share the same
// history anymore.
const record = this._record;
this._record = new virtualFs.CordHost(record);
this._recordSync = new virtualFs.SyncDelegateHost(this._record);

return new HostTree(record);
}

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

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

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

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

case 'd': {
const { path } = action;
if (this._record.willDelete(path) && !deleteConflictAllowed) {
if (this._willDelete(path) && !deleteConflictAllowed) {
throw new MergeConflictException(path);
}
this._recordSync.delete(path);
Expand Down Expand Up @@ -235,7 +310,12 @@ export class HostTree implements Tree {
return maybeCache;
}
visit(visitor: FileVisitor): void {
this.root.visit(visitor);
const allFiles: [Path, FileEntry | null | undefined][] = [];
this.root.visit((path, entry) => {
allFiles.push([path, entry]);
});

allFiles.forEach(([path, entry]) => visitor(path, entry));
}

// Change content of host files.
Expand Down Expand Up @@ -290,8 +370,21 @@ export class HostTree implements Tree {
throw new SchematicsException('Apply not implemented on host trees.');
}
get actions(): Action[] {
// Create a list of all records until we hit our original backend. This is to support branches
// that diverge from each others.
const allRecords: CordHostRecord[] = [...this._record.records()];
let current = this._record.backend;
while (current != this._backend) {
if (!(current instanceof virtualFs.CordHost)) {
break;
}

allRecords.unshift(...current.records());
current = current.backend;
}

return clean(
this._record.records()
allRecords
.map(record => {
switch (record.kind) {
case 'create':
Expand Down
4 changes: 3 additions & 1 deletion packages/angular_devkit/schematics/src/tree/static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import { FilePredicate, MergeStrategy, Tree } from './interface';
import { VirtualTree } from './virtual';


export function empty() { return new VirtualTree(); }
export function empty() {
return new HostTree();
}

export function branch(tree: Tree) {
if (tree instanceof HostTree) {
Expand Down

0 comments on commit b11af51

Please sign in to comment.