1
- const printTree = require ( "print-tree" ) ;
2
-
3
1
const path = require ( "./path.js" ) ;
4
2
const { ENOENT , EEXIST , ENOTEMPTY } = require ( "./errors.js" ) ;
5
3
6
4
const STAT = 0 ;
7
5
8
6
module . exports = class CacheFS {
9
7
constructor ( ) {
8
+ const root = this . _makeRoot ( ) ;
9
+ this . _root = new Map ( [ [ "/" , root ] ] ) ;
10
+ }
11
+ _makeRoot ( ) {
10
12
let root = new Map ( ) ;
11
13
let stat = { mode : 0o777 , type : "dir" , size : 0 , mtimeMs : Date . now ( ) } ;
12
14
root . set ( STAT , stat ) ;
13
- this . _root = new Map ( [ [ "/" , root ] ] ) ;
15
+ return root
14
16
}
15
- _print ( ) {
16
- const root = [ ...this . _root . entries ( ) ] [ 0 ] ;
17
- return printTree (
18
- root ,
19
- node => {
20
- let stat = node [ 1 ] . get ( STAT ) ;
17
+ print ( root ) {
18
+ root = root || this . _root . get ( "/" )
19
+ let str = "" ;
20
+ const printTree = ( root , indent ) => {
21
+ for ( let [ file , node ] of root ) {
22
+ if ( file === 0 ) continue ;
23
+ let stat = node . get ( STAT ) ;
21
24
let mode = stat . mode . toString ( 8 ) ;
22
25
if ( stat . type === "file" ) {
23
- return `${ node [ 0 ] } [mode=${ mode } size=${ stat . size } mtime=${ stat . mtimeMs } ]` ;
26
+ str += `\n${ "\t" . repeat ( indent ) } ${ file } \t${ mode } \t${ stat . size } \t${
27
+ stat . mtimeMs
28
+ } `;
24
29
} else {
25
- return `${ node [ 0 ] } [mode=${ mode } ]` ;
30
+ str += `\n${ "\t" . repeat ( indent ) } ${ file } \t${ mode } ` ;
31
+ printTree ( node , indent + 1 ) ;
26
32
}
27
- } ,
28
- node => {
29
- if ( node [ 1 ] === null ) {
30
- // it's a file
31
- return [ ] ;
32
- } else {
33
- // it's a dir
34
- return [ ...node [ 1 ] . entries ( ) ] . filter ( ( [ key ] ) => typeof key === "string" ) ;
33
+ }
34
+ } ;
35
+ printTree ( root , 0 ) ;
36
+ return str . trimStart ( ) ;
37
+ }
38
+ parse ( print ) {
39
+ function mk ( stat ) {
40
+ if ( stat . length === 1 ) {
41
+ let [ mode ] = stat
42
+ mode = parseInt ( mode , 8 ) ;
43
+ return new Map ( [
44
+ [ STAT , { mode, type : "dir" , size : 0 , mtimeMs : Date . now ( ) } ]
45
+ ] ) ;
46
+ } else {
47
+ let [ mode , size , mtimeMs ] = stat ;
48
+ mode = parseInt ( mode , 8 ) ;
49
+ size = parseInt ( size ) ;
50
+ mtimeMs = parseInt ( mtimeMs ) ;
51
+ return new Map ( [ [ STAT , { mode, type : "file" , size, mtimeMs } ] ] ) ;
52
+ }
53
+ }
54
+
55
+ let lines = print . trim ( ) . split ( "\n" ) ;
56
+ let _root = this . _makeRoot ( ) ;
57
+ let stack = [
58
+ { indent : - 1 , node : _root } ,
59
+ { indent : 0 , node : null }
60
+ ] ;
61
+ for ( let line of lines ) {
62
+ // let [, prefix, filename, stat]
63
+ let prefix = line . match ( / ^ \t * / ) [ 0 ] ;
64
+ let indent = prefix . length ;
65
+ line = line . slice ( indent ) ;
66
+ let [ filename , ...stat ] = line . split ( "\t" ) ;
67
+ let node = mk ( stat ) ;
68
+ if ( indent <= stack [ stack . length - 1 ] . indent ) {
69
+ while ( indent <= stack [ stack . length - 1 ] . indent ) {
70
+ stack . pop ( ) ;
35
71
}
36
72
}
37
- ) ;
73
+ stack . push ( { indent, node } ) ;
74
+ let cd = stack [ stack . length - 2 ] . node ;
75
+ cd . set ( filename , node ) ;
76
+ }
77
+ return _root ;
38
78
}
39
79
_lookup ( filepath ) {
40
80
let dir = this . _root ;
@@ -44,27 +84,6 @@ module.exports = class CacheFS {
44
84
}
45
85
return dir ;
46
86
}
47
- // _mkdirp(filepath) {
48
- // let dir = this._root;
49
- // let traversing = true;
50
- // let tmp;
51
- // for (let part of path.split(filepath)) {
52
- // if (traversing) {
53
- // tmp = dir.get(part);
54
- // if (tmp) {
55
- // dir = tmp;
56
- // } else {
57
- // traversing = false;
58
- // }
59
- // }
60
- // if (!traversing) {
61
- // tmp = new Map();
62
- // dir.set(part, tmp);
63
- // dir = tmp;
64
- // }
65
- // }
66
- // return dir;
67
- // }
68
87
mkdir ( filepath , { mode } ) {
69
88
if ( filepath === "/" ) throw new EEXIST ( ) ;
70
89
let dir = this . _lookup ( path . dirname ( filepath ) ) ;
0 commit comments