@@ -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' ;
1921import {
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' :
0 commit comments