@@ -16,6 +16,8 @@ import {
16
16
normalize ,
17
17
virtualFs ,
18
18
} from '@angular-devkit/core' ;
19
+ import { ReadonlyHost } from '../../../core/src/virtual-fs/host' ;
20
+ import { CordHostRecord } from '../../../core/src/virtual-fs/host/record' ;
19
21
import {
20
22
ContentHasMutatedException ,
21
23
FileAlreadyExistException ,
@@ -99,21 +101,94 @@ export class HostTree implements Tree {
99
101
100
102
private _dirCache = new Map < Path , HostDirEntry > ( ) ;
101
103
104
+
102
105
[ TreeSymbol ] ( ) {
103
106
return this ;
104
107
}
105
108
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 ) ) ;
108
111
this . _recordSync = new virtualFs . SyncDelegateHost ( this . _record ) ;
109
112
}
110
113
111
114
protected _normalizePath ( path : string ) : Path {
112
115
return normalize ( '/' + path ) ;
113
116
}
114
117
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
+
115
184
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 ) ;
117
192
}
118
193
119
194
merge ( other : Tree , strategy : MergeStrategy = MergeStrategy . Default ) : void {
@@ -138,7 +213,7 @@ export class HostTree implements Tree {
138
213
case 'c' : {
139
214
const { path, content } = action ;
140
215
141
- if ( ( this . _record . willCreate ( path ) || this . _record . willOverwrite ( path ) ) ) {
216
+ if ( ( this . _willCreate ( path ) || this . _willOverwrite ( path ) ) ) {
142
217
if ( ! creationConflictAllowed ) {
143
218
throw new MergeConflictException ( path ) ;
144
219
}
@@ -155,7 +230,7 @@ export class HostTree implements Tree {
155
230
const { path, content } = action ;
156
231
157
232
// Ignore if content is the same (considered the same change).
158
- if ( this . _record . willOverwrite ( path ) && ! overwriteConflictAllowed ) {
233
+ if ( this . _willOverwrite ( path ) && ! overwriteConflictAllowed ) {
159
234
throw new MergeConflictException ( path ) ;
160
235
}
161
236
// 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 {
167
242
168
243
case 'r' : {
169
244
const { path, to } = action ;
170
- if ( this . _record . willRename ( path ) ) {
245
+ if ( this . _willRename ( path ) ) {
171
246
// No override possible for renaming.
172
247
throw new MergeConflictException ( path ) ;
173
248
}
@@ -178,7 +253,7 @@ export class HostTree implements Tree {
178
253
179
254
case 'd' : {
180
255
const { path } = action ;
181
- if ( this . _record . willDelete ( path ) && ! deleteConflictAllowed ) {
256
+ if ( this . _willDelete ( path ) && ! deleteConflictAllowed ) {
182
257
throw new MergeConflictException ( path ) ;
183
258
}
184
259
this . _recordSync . delete ( path ) ;
@@ -235,7 +310,12 @@ export class HostTree implements Tree {
235
310
return maybeCache ;
236
311
}
237
312
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 ) ) ;
239
319
}
240
320
241
321
// Change content of host files.
@@ -290,8 +370,21 @@ export class HostTree implements Tree {
290
370
throw new SchematicsException ( 'Apply not implemented on host trees.' ) ;
291
371
}
292
372
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
+
293
386
return clean (
294
- this . _record . records ( )
387
+ allRecords
295
388
. map ( record => {
296
389
switch ( record . kind ) {
297
390
case 'create' :
0 commit comments