microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
caa0dc5eb84731caee69a4d06915c6a3856ec289

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/common/node/fileSystem.ts

189lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as nodeFs from "fs";
5import * as path from "path";
6import * as mkdirp from "mkdirp";
7
8export class FileSystem {
9 private fs: typeof nodeFs;
10
11 constructor({ fs = nodeFs } = {}) {
12 this.fs = fs;
13 }
14
15 public ensureDirectory(dir: string): Promise<void> {
16 return this.stat(dir).then(
17 (stat: nodeFs.Stats): void => {
18 if (stat.isDirectory()) {
19 return;
20 }
21 throw new Error(`Expected ${dir} to be a directory`);
22 },
23 (err: Error & { code?: string }): Promise<any> => {
24 if (err && err.code === "ENOENT") {
25 return this.mkDir(dir);
26 }
27 throw err;
28 },
29 );
30 }
31
32 public ensureFileWithContents(file: string, contents: string): Promise<void> {
33 return this.stat(file).then(
34 (stat: nodeFs.Stats) => {
35 if (!stat.isFile()) {
36 throw new Error(`Expected ${file} to be a file`);
37 }
38
39 return this.readFile(file).then(existingContents => {
40 if (contents !== existingContents) {
41 return this.writeFile(file, contents);
42 }
43 return Promise.resolve();
44 });
45 },
46 (err: Error & { code?: string }): Promise<any> => {
47 if (err && err.code === "ENOENT") {
48 return this.writeFile(file, contents);
49 }
50 throw err;
51 },
52 );
53 }
54
55 /**
56 * Helper function to check if a file or directory exists
57 */
58 public existsSync(filename: string): boolean {
59 return this.fs.existsSync(filename);
60 }
61
62 /**
63 * Helper (asynchronous) function to check if a file or directory exists
64 */
65 public exists(filename: string): Promise<boolean> {
66 return this.stat(filename)
67 .then(() => {
68 return Promise.resolve(true);
69 })
70 .catch(() => {
71 return Promise.resolve(false);
72 });
73 }
74
75 /**
76 * Helper async function to read the contents of a directory
77 */
78 public readDir(directory: string): Promise<string[]> {
79 return this.fs.promises.readdir(directory);
80 }
81
82 /**
83 * Helper (synchronous) function to create a directory recursively
84 */
85 public makeDirectoryRecursiveSync(dirPath: string): void {
86 let parentPath = path.dirname(dirPath);
87 if (!this.existsSync(parentPath)) {
88 this.makeDirectoryRecursiveSync(parentPath);
89 }
90
91 this.fs.mkdirSync(dirPath);
92 }
93
94 /**
95 * Helper function to asynchronously copy a file
96 */
97 public copyFile(from: string, to: string): Promise<void> {
98 return this.fs.promises.copyFile(from, to);
99 }
100
101 public deleteFileIfExistsSync(filename: string): void {
102 if (this.existsSync(filename)) {
103 this.fs.unlinkSync(filename);
104 }
105 }
106
107 public readFile(filename: string, encoding: string = "utf8"): Promise<string | Buffer> {
108 return this.fs.promises.readFile(filename, { encoding });
109 }
110
111 public writeFile(filename: string, data: any): Promise<void> {
112 return this.fs.promises.writeFile(filename, data);
113 }
114
115 public static writeFileToFolder(folder: string, basename: string, data: any): Promise<void> {
116 if (!nodeFs.existsSync(folder)) {
117 mkdirp.sync(folder);
118 }
119 return nodeFs.promises.writeFile(path.join(folder, basename), data);
120 }
121
122 public unlink(filename: string): Promise<void> {
123 return this.fs.promises.unlink(filename);
124 }
125
126 public mkDir(p: string): Promise<void> {
127 return this.fs.promises.mkdir(p);
128 }
129
130 public stat(fsPath: string): Promise<nodeFs.Stats> {
131 return this.fs.promises.stat(fsPath);
132 }
133
134 public directoryExists(directoryPath: string): Promise<boolean> {
135 return this.stat(directoryPath)
136 .then(stats => {
137 return stats.isDirectory();
138 })
139 .catch(reason => {
140 return reason.code === "ENOENT" ? false : Promise.reject<boolean>(reason);
141 });
142 }
143
144 /**
145 * Delete 'dirPath' if it's an empty folder. If not fail.
146 *
147 * @param {dirPath} path to the folder
148 * @returns {void} Nothing
149 */
150 public rmdir(dirPath: string): Promise<void> {
151 return this.fs.promises.rmdir(dirPath);
152 }
153
154 public async removePathRecursivelyAsync(p: string): Promise<void> {
155 const exists = await this.exists(p);
156 if (exists) {
157 const stats = await this.stat(p);
158 if (stats.isDirectory()) {
159 const childPaths = await this.readDir(p);
160 await Promise.all(
161 childPaths.map(childPath =>
162 this.removePathRecursivelyAsync(path.join(p, childPath)),
163 ),
164 );
165 await this.rmdir(p);
166 } else {
167 /* file */
168 return this.unlink(p);
169 }
170 }
171 return Promise.resolve();
172 }
173
174 public removePathRecursivelySync(p: string): void {
175 if (this.fs.existsSync(p)) {
176 let stats = this.fs.statSync(p);
177 if (stats.isDirectory()) {
178 let contents = this.fs.readdirSync(p);
179 contents.forEach(childPath =>
180 this.removePathRecursivelySync(path.join(p, childPath)),
181 );
182 this.fs.rmdirSync(p);
183 } else {
184 /* file */
185 this.fs.unlinkSync(p);
186 }
187 }
188 }
189}
190