Skip to content

Commit 20c37ab

Browse files
fix: Use 'fs' methods if in C9 (#4374)
* fix: Use 'fs' methods if in C9 Problem: We recently made some changes to our file system code that used the vscode.workspace.fs instance. The issue is that some of its methods are not supported in C9 Solution: If in C9 use the original "fs" instance methods instead for delete, readdir, and mkdir. Also added tests. Signed-off-by: nkomonen <[email protected]> * changelog item Signed-off-by: nkomonen <[email protected]> --------- Signed-off-by: nkomonen <[email protected]>
1 parent 4fdcbb6 commit 20c37ab

File tree

4 files changed

+83
-7
lines changed

4 files changed

+83
-7
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Cloud9: certain filesystem calls did not work in Cloud9"
4+
}
12.8 MB
Binary file not shown.

src/srcShared/fs.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55
import * as vscode from 'vscode'
6-
import * as actualFs from 'fs'
6+
import { promises as fsPromises } from 'fs'
77
import { isCloud9 } from '../shared/extensionUtilities'
8-
import { ToolkitError } from '../shared/errors'
98
import _path from 'path'
109

1110
const fs = vscode.workspace.fs
@@ -44,9 +43,8 @@ export class FileSystemCommon {
4443
// Certain URIs are not supported with vscode.workspace.fs in C9
4544
// so revert to using `fs` which works.
4645
if (isCloud9()) {
47-
return actualFs.mkdir(uriPath.fsPath, { recursive: true }, err => {
48-
throw new ToolkitError(`Failed mkdir() in Cloud9: ${uriPath.fsPath}: ${err}`)
49-
})
46+
await fsPromises.mkdir(uriPath.fsPath, { recursive: true })
47+
return
5048
}
5149

5250
return fs.createDirectory(uriPath)
@@ -120,11 +118,27 @@ export class FileSystemCommon {
120118

121119
async delete(uri: vscode.Uri | string): Promise<void> {
122120
const path = FileSystemCommon.getUri(uri)
121+
122+
// vscode.workspace.fs.delete is not supported in C9
123+
if (isCloud9()) {
124+
await fsPromises.rm(path.fsPath, { recursive: true })
125+
return
126+
}
127+
123128
return fs.delete(path, { recursive: true })
124129
}
125130

126131
async readdir(uri: vscode.Uri | string): Promise<[string, vscode.FileType][]> {
127132
const path = FileSystemCommon.getUri(uri)
133+
134+
// readdir is not a supported vscode API in Cloud9
135+
if (isCloud9()) {
136+
return (await fsPromises.readdir(path.fsPath, { withFileTypes: true })).map(e => [
137+
e.name,
138+
e.isDirectory() ? vscode.FileType.Directory : vscode.FileType.File,
139+
])
140+
}
141+
128142
return await fs.readDirectory(path)
129143
}
130144

src/test/srcShared/fs.test.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,34 @@
66
import assert from 'assert'
77
import * as vscode from 'vscode'
88
import * as path from 'path'
9-
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs'
9+
import { existsSync, mkdirSync, promises as fsPromises, readFileSync, rmSync, writeFileSync } from 'fs'
1010
import { FakeExtensionContext } from '../fakeExtensionContext'
1111
import { fsCommon } from '../../srcShared/fs'
1212
import * as os from 'os'
1313
import { isMinimumVersion } from '../../shared/vscode/env'
14+
import Sinon from 'sinon'
15+
import * as extensionUtilities from '../../shared/extensionUtilities'
1416

1517
function isWin() {
1618
return os.platform() === 'win32'
1719
}
1820

1921
describe('FileSystem', function () {
2022
let fakeContext: vscode.ExtensionContext
23+
let sandbox: Sinon.SinonSandbox
2124

2225
before(async function () {
2326
fakeContext = await FakeExtensionContext.create()
2427
})
2528

2629
beforeEach(async function () {
2730
await makeTestRoot()
31+
sandbox = Sinon.createSandbox()
2832
})
2933

3034
afterEach(async function () {
3135
await deleteTestRoot()
36+
sandbox.restore()
3237
})
3338

3439
describe('readFileAsString()', function () {
@@ -153,12 +158,25 @@ describe('FileSystem', function () {
153158
const paths = ['a', 'a/b', 'a/b/c', 'a/b/c/d/']
154159

155160
paths.forEach(async function (p) {
156-
it(`creates path: '${p}'`, async function () {
161+
it(`creates folder: '${p}'`, async function () {
157162
const dirPath = createTestPath(p)
158163
await fsCommon.mkdir(dirPath)
159164
assert.ok(existsSync(dirPath))
160165
})
161166
})
167+
168+
paths.forEach(async function (p) {
169+
it(`creates folder but uses the "fs" module if in C9: '${p}'`, async function () {
170+
sandbox.stub(extensionUtilities, 'isCloud9').returns(true)
171+
const mkdirSpy = sandbox.spy(fsPromises, 'mkdir')
172+
const dirPath = createTestPath(p)
173+
174+
await fsCommon.mkdir(dirPath)
175+
176+
assert.ok(existsSync(dirPath))
177+
assert.ok(mkdirSpy.calledOnce)
178+
})
179+
})
162180
})
163181

164182
describe('readdir()', function () {
@@ -192,6 +210,32 @@ describe('FileSystem', function () {
192210
function sorted(i: [string, vscode.FileType][]) {
193211
return i.sort((a, b) => a[0].localeCompare(b[0]))
194212
}
213+
214+
it('uses the "fs" readdir implementation if in C9', async function () {
215+
sandbox.stub(extensionUtilities, 'isCloud9').returns(true)
216+
const readdirSpy = sandbox.spy(fsPromises, 'readdir')
217+
218+
await makeFile('a.txt')
219+
await makeFile('b.txt')
220+
await makeFile('c.txt')
221+
mkdirSync(createTestPath('dirA'))
222+
mkdirSync(createTestPath('dirB'))
223+
mkdirSync(createTestPath('dirC'))
224+
225+
const files = await fsCommon.readdir(testRootPath())
226+
assert.deepStrictEqual(
227+
sorted(files),
228+
sorted([
229+
['a.txt', vscode.FileType.File],
230+
['b.txt', vscode.FileType.File],
231+
['c.txt', vscode.FileType.File],
232+
['dirA', vscode.FileType.Directory],
233+
['dirB', vscode.FileType.Directory],
234+
['dirC', vscode.FileType.Directory],
235+
])
236+
)
237+
assert.ok(readdirSpy.calledOnce)
238+
})
195239
})
196240

197241
describe('delete()', function () {
@@ -209,6 +253,20 @@ describe('FileSystem', function () {
209253

210254
assert.ok(!existsSync(dirPath))
211255
})
256+
257+
it('uses the "fs" rm method if in C9', async function () {
258+
sandbox.stub(extensionUtilities, 'isCloud9').returns(true)
259+
const rmdirSpy = sandbox.spy(fsPromises, 'rm')
260+
// Folder with subfolders
261+
const dirPath = await makeFolder('a/b/deleteMe')
262+
263+
mkdirSync(dirPath, { recursive: true })
264+
265+
await fsCommon.delete(dirPath)
266+
267+
assert.ok(!existsSync(dirPath))
268+
assert.ok(rmdirSpy.calledOnce)
269+
})
212270
})
213271

214272
describe('stat()', function () {

0 commit comments

Comments
 (0)