1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.CachedFileSystem = exports.FileKind = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const inversify_1 = require("inversify");
|
6 | const ymir_1 = require("@fimbul/ymir");
|
7 | const bind_decorator_1 = require("bind-decorator");
|
8 | const utils_1 = require("../utils");
|
9 | const path = require("path");
|
10 | var FileKind;
|
11 | (function (FileKind) {
|
12 | FileKind[FileKind["NonExistent"] = 0] = "NonExistent";
|
13 | FileKind[FileKind["File"] = 1] = "File";
|
14 | FileKind[FileKind["Directory"] = 2] = "Directory";
|
15 | FileKind[FileKind["Other"] = 3] = "Other";
|
16 | })(FileKind = exports.FileKind || (exports.FileKind = {}));
|
17 | let CachedFileSystem = class CachedFileSystem {
|
18 | constructor(fs, cache) {
|
19 | this.fs = fs;
|
20 | this.realpath = this.fs.realpath === undefined ? undefined : (file) => {
|
21 | return utils_1.resolveCachedResult(this.realpathCache, this.fs.normalizePath(file), () => this.fs.realpath(file));
|
22 | };
|
23 | this.fileKindCache = cache.create();
|
24 | this.realpathCache = cache.create();
|
25 | this.direntCache = cache.create();
|
26 | }
|
27 | isFile(file) {
|
28 | return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(file), this.doGetKind) === 1 ;
|
29 | }
|
30 | isDirectory(dir) {
|
31 | return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(dir), this.doGetKind) === 2 ;
|
32 | }
|
33 | getKind(file) {
|
34 | return utils_1.resolveCachedResult(this.fileKindCache, this.fs.normalizePath(file), this.doGetKind);
|
35 | }
|
36 | doGetKind(file) {
|
37 | try {
|
38 | return statsToKind(this.fs.stat(file));
|
39 | }
|
40 | catch {
|
41 | return 0 ;
|
42 | }
|
43 | }
|
44 | readDirectory(dir) {
|
45 | dir = this.fs.normalizePath(dir);
|
46 | let cachedResult = this.direntCache.get(dir);
|
47 | if (cachedResult !== undefined)
|
48 | return cachedResult.map((entry) => ({ kind: this.fileKindCache.get(this.fs.normalizePath(path.join(dir, entry))), name: entry }));
|
49 | cachedResult = [];
|
50 | const result = [];
|
51 | for (const entry of this.fs.readDirectory(dir)) {
|
52 | if (typeof entry === 'string') {
|
53 | cachedResult.push(entry);
|
54 | result.push({ kind: this.getKind(path.join(dir, entry)), name: entry });
|
55 | }
|
56 | else {
|
57 | cachedResult.push(entry.name);
|
58 | const filePath = path.join(dir, entry.name);
|
59 | let kind;
|
60 | if (entry.isSymbolicLink()) {
|
61 | kind = this.getKind(filePath);
|
62 | }
|
63 | else {
|
64 | kind = statsToKind(entry);
|
65 | this.fileKindCache.set(this.fs.normalizePath(filePath), kind);
|
66 | }
|
67 | result.push({ kind, name: entry.name });
|
68 | }
|
69 | }
|
70 | this.direntCache.set(dir, cachedResult);
|
71 | return result;
|
72 | }
|
73 | readFile(file) {
|
74 | return this.fs.readFile(this.fs.normalizePath(file));
|
75 | }
|
76 | writeFile(file, content) {
|
77 | file = this.fs.normalizePath(file);
|
78 | this.fs.writeFile(file, content);
|
79 | this.updateCache(file, 1 );
|
80 | }
|
81 | remove(file) {
|
82 | file = this.fs.normalizePath(file);
|
83 | this.fs.deleteFile(file);
|
84 | this.updateCache(file, 0 );
|
85 | }
|
86 | createDirectory(dir) {
|
87 | dir = this.fs.normalizePath(dir);
|
88 | if (this.fileKindCache.get(dir) === 2 )
|
89 | return;
|
90 | return this.doCreateDirectory(dir);
|
91 | }
|
92 | doCreateDirectory(dir) {
|
93 | try {
|
94 | this.fs.createDirectory(dir);
|
95 | }
|
96 | catch (e) {
|
97 | try {
|
98 | const stat = this.fs.stat(dir);
|
99 | if (!stat.isDirectory())
|
100 | throw e;
|
101 | }
|
102 | catch {
|
103 | const parent = this.fs.normalizePath(path.dirname(dir));
|
104 | if (parent === dir)
|
105 | throw e;
|
106 | this.doCreateDirectory(parent);
|
107 | this.fs.createDirectory(dir);
|
108 | }
|
109 | }
|
110 | this.updateCache(dir, 2 );
|
111 | }
|
112 | updateCache(file, kind) {
|
113 |
|
114 | if (this.fileKindCache.get(file) === kind)
|
115 | return;
|
116 | this.fileKindCache.set(file, kind);
|
117 | if (kind === 0 )
|
118 | this.realpathCache.delete(file);
|
119 |
|
120 | this.direntCache.delete(this.fs.normalizePath(path.dirname(file)));
|
121 | }
|
122 | };
|
123 | tslib_1.__decorate([
|
124 | bind_decorator_1.default,
|
125 | tslib_1.__metadata("design:type", Function),
|
126 | tslib_1.__metadata("design:paramtypes", [String]),
|
127 | tslib_1.__metadata("design:returntype", Number)
|
128 | ], CachedFileSystem.prototype, "doGetKind", null);
|
129 | CachedFileSystem = tslib_1.__decorate([
|
130 | inversify_1.injectable(),
|
131 | tslib_1.__metadata("design:paramtypes", [ymir_1.FileSystem, ymir_1.CacheFactory])
|
132 | ], CachedFileSystem);
|
133 | exports.CachedFileSystem = CachedFileSystem;
|
134 | function statsToKind(stats) {
|
135 | return stats.isFile() ? 1 : stats.isDirectory() ? 2 : 3 ;
|
136 | }
|
137 |
|
\ | No newline at end of file |