Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/core/src/amazonq/lsp/lspController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { AuthUtil } from '../../codewhisperer'
import { isWeb } from '../../shared/extensionGlobals'
import { getUserAgent } from '../../shared/telemetry/util'
import { isAmazonInternalOs } from '../../shared/vscode/env'
import { fs as fs2 } from '../../shared/fs/fs'

function getProjectPaths() {
const workspaceFolders = vscode.workspace.workspaceFolders
Expand Down Expand Up @@ -266,7 +267,7 @@ export class LspController {
if (!downloadNodeOk) {
return false
}
fs.chmodSync(nodeRuntimeTempPath, 0o755)
await fs2.chmod(nodeRuntimeTempPath, 0o755)
fs.moveSync(nodeRuntimeTempPath, nodeRuntimePath)
return true
} catch (e) {
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/awsService/ec2/sshKeyPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
import { fs } from '../../shared'
import { chmodSync } from 'fs'
import { ToolkitError } from '../../shared/errors'
import { tryRun } from '../../shared/utilities/pathFind'
import { Timeout } from '../../shared/utilities/timeoutUtils'
Expand Down Expand Up @@ -39,7 +38,7 @@ export class SshKeyPair {
if (!keyGenerated) {
throw new ToolkitError('ec2: Unable to generate ssh key pair')
}
chmodSync(keyPath, 0o600)
await fs.chmod(keyPath, 0o600)
}
/**
* Attempts to generate an ssh key pair. Returns true if successful, false otherwise.
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/shared/fs/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import vscode from 'vscode'
import os from 'os'
import { promises as nodefs, constants as nodeConstants, WriteFileOptions } from 'fs'
import { chmod } from 'fs/promises'
import { isCloud9 } from '../extensionUtilities'
import _path from 'path'
import {
Expand Down Expand Up @@ -357,6 +358,20 @@ export class FileSystem {
return await vfs.stat(path)
}

/**
* Change permissions on file. Note that this will do nothing on browser.
* @param uri file whose permissions should be set.
* @param mode new permissions in octal notation.
* More info: https://nodejs.org/api/fs.html#fspromiseschmodpath-mode
* Examples: https://www.geeksforgeeks.org/node-js-fspromises-chmod-method/
*/
async chmod(uri: vscode.Uri | string, mode: number): Promise<void> {
if (!this.isWeb) {
const path = toUri(uri)
await chmod(path.fsPath, mode)
}
}

/**
* Deletes a file or directory. It is not an error if the file/directory does not exist, unless
* its parent directory is not listable (executable).
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/shared/sam/debugger/csharpSamDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { chmod, ensureDir, writeFile } from 'fs-extra'
import { ensureDir, writeFile } from 'fs-extra'
import * as os from 'os'
import * as path from 'path'
import {
Expand All @@ -24,6 +24,7 @@ import { getLogger } from '../../logger'
import * as vscode from 'vscode'
import * as nls from 'vscode-nls'
import globals from '../../extensionGlobals'
import fs from '../../fs/fs'
const localize = nls.loadMessageBundle()

/**
Expand Down Expand Up @@ -203,7 +204,7 @@ async function downloadInstallScript(debuggerPath: string): Promise<string> {
}

await writeFile(installScriptPath, installScript, 'utf8')
await chmod(installScriptPath, 0o700)
await fs.chmod(installScriptPath, 0o700)

return installScriptPath
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/shared/sam/debugger/goSamDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ async function makeInstallScript(debuggerPath: string, isWindows: boolean): Prom
script += `go build -o "${delvePath}" "${delveRepo}/cmd/dlv"\n`

await fs.writeFile(installScriptPath, script, 'utf8')
await fs.chmod(installScriptPath, 0o755)
await fs2.chmod(installScriptPath, 0o755)

return { path: installScriptPath, options: installOptions }
}
Expand Down
11 changes: 10 additions & 1 deletion packages/core/src/test/awsService/ec2/sshKeyPair.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
*/
import * as vscode from 'vscode'
import assert from 'assert'
import nodefs from 'fs'
import * as sinon from 'sinon'
import * as path from 'path'
import * as os from 'os'
import { SshKeyPair } from '../../../awsService/ec2/sshKeyPair'
import { createTestWorkspaceFolder, installFakeClock } from '../../testUtil'
import { InstalledClock } from '@sinonjs/fake-timers'
import { ChildProcess } from '../../../shared/utilities/processUtils'
import { fs } from '../../../shared'
import { fs, globals } from '../../../shared'

describe('SshKeyUtility', async function () {
let temporaryDirectory: string
Expand Down Expand Up @@ -50,6 +52,13 @@ describe('SshKeyUtility', async function () {
assert.notStrictEqual(beforeContent, afterContent)
})

it('sets permission of the file to read/write owner', async function () {
if (!globals.isWeb && os.platform() !== 'win32') {
const result = nodefs.statSync(keyPair.getPrivateKeyPath())
assert.strictEqual(result.mode & 0o777, 0o600)
}
})

it('defaults to ed25519 key type', async function () {
const process = new ChildProcess(`ssh-keygen`, ['-vvv', '-l', '-f', keyPath])
const result = await process.run()
Expand Down
18 changes: 18 additions & 0 deletions packages/core/src/test/shared/fs/fs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import vscode from 'vscode'
import * as path from 'path'
import * as utils from 'util'
import { existsSync, mkdirSync, promises as nodefs, readFileSync } from 'fs'
import { stat } from 'fs/promises'
import nodeFs from 'fs'
import fs, { FileSystem } from '../../../shared/fs/fs'
import * as os from 'os'
Expand Down Expand Up @@ -385,6 +386,23 @@ describe('FileSystem', function () {
})
})

describe('chmod()', async function () {
it('changes permissions when not on web, otherwise does not throw', async function () {
const filePath = await testFolder.write('test.txt', 'hello world', { mode: 0o777 })
await fs.chmod(filePath, 0o644)
// chmod doesn't exist on windows, non-unix permission system.
if (!globals.isWeb && os.platform() !== 'win32') {
const result = await stat(filePath)
assert.strictEqual(result.mode & 0o777, 0o644)
}
})

it('throws if no file exists', async function () {
const filePath = testFolder.pathFrom('thisDoesNotExist.txt')
await assert.rejects(() => fs.chmod(filePath, 0o644))
})
})

describe('rename()', async () => {
it('renames a file', async () => {
const oldPath = await testFolder.write('oldFile.txt', 'hello world')
Expand Down
26 changes: 15 additions & 11 deletions packages/core/src/test/shared/utilities/processUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import assert from 'assert'
import * as fs from 'fs-extra'
import { fs as fs2 } from '../../../shared'
import * as os from 'os'
import * as path from 'path'
import { makeTemporaryToolkitFolder, tryRemoveFolder } from '../../../shared/filesystemUtilities'
Expand Down Expand Up @@ -80,7 +81,7 @@ describe('ChildProcess', async function () {
if (process.platform !== 'win32') {
it('runs and captures stdout - unix', async function () {
const scriptFile = path.join(tempFolder, 'test-script.sh')
writeShellFile(scriptFile)
await writeShellFile(scriptFile)

const childProcess = new ChildProcess(scriptFile)

Expand All @@ -89,7 +90,7 @@ describe('ChildProcess', async function () {

it('errs when starting twice - unix', async function () {
const scriptFile = path.join(tempFolder, 'test-script.sh')
writeShellFile(scriptFile)
await writeShellFile(scriptFile)

const childProcess = new ChildProcess(scriptFile)

Expand Down Expand Up @@ -120,7 +121,7 @@ describe('ChildProcess', async function () {
writeBatchFile(command)
} else {
command = path.join(subfolder, 'test script.sh')
writeShellFile(command)
await writeShellFile(command)
}

const childProcess = new ChildProcess(command)
Expand All @@ -140,14 +141,17 @@ describe('ChildProcess', async function () {
describe('Extra options', function () {
let childProcess: ChildProcess

beforeEach(function () {
beforeEach(async function () {
const isWindows = process.platform === 'win32'
const command = path.join(tempFolder, `test-script.${isWindows ? 'bat' : 'sh'}`)

if (isWindows) {
writeBatchFile(command, ['@echo %1', '@echo %2', '@echo "%3"', 'SLEEP 20', 'exit 1'].join(os.EOL))
} else {
writeShellFile(command, ['echo $1', 'echo $2', 'echo "$3"', 'sleep 20', 'exit 1'].join(os.EOL))
await writeShellFile(
command,
['echo $1', 'echo $2', 'echo "$3"', 'sleep 20', 'exit 1'].join(os.EOL)
)
}

childProcess = new ChildProcess(command, ['1', '2'], { collect: false })
Expand Down Expand Up @@ -277,7 +281,7 @@ describe('ChildProcess', async function () {
if (process.platform !== 'win32') {
it('detects running processes and successfully stops a running process - Unix', async function () {
const scriptFile = path.join(tempFolder, 'test-script.sh')
writeShellFileWithDelays(scriptFile)
await writeShellFileWithDelays(scriptFile)

const childProcess = new ChildProcess('sh', [scriptFile])
const result = childProcess.run()
Expand All @@ -291,7 +295,7 @@ describe('ChildProcess', async function () {

it('can stop() previously stopped processes - Unix', async function () {
const scriptFile = path.join(tempFolder, 'test-script.sh')
writeShellFileWithDelays(scriptFile)
await writeShellFileWithDelays(scriptFile)

const childProcess = new ChildProcess(scriptFile)

Expand Down Expand Up @@ -331,17 +335,17 @@ describe('ChildProcess', async function () {
fs.writeFileSync(filename, `@echo OFF${os.EOL}echo hi`)
}

function writeShellFile(filename: string, contents = 'echo hi'): void {
async function writeShellFile(filename: string, contents = 'echo hi'): Promise<void> {
fs.writeFileSync(filename, `#!/bin/sh\n${contents}`)
fs.chmodSync(filename, 0o744)
await fs2.chmod(filename, 0o744)
}

function writeShellFileWithDelays(filename: string): void {
async function writeShellFileWithDelays(filename: string): Promise<void> {
const file = `
echo hi
sleep 20
echo bye`
writeShellFile(filename, file)
await writeShellFile(filename, file)
}
})

Expand Down
28 changes: 13 additions & 15 deletions packages/core/src/test/testUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/

import assert from 'assert'
import * as nodeFsSync from 'fs'
import * as path from 'path'
import * as vscode from 'vscode'
import * as FakeTimers from '@sinonjs/fake-timers'
Expand All @@ -14,10 +13,9 @@ import globals from '../shared/extensionGlobals'
import { waitUntil } from '../shared/utilities/timeoutUtils'
import { MetricName, MetricShapes } from '../shared/telemetry/telemetry'
import { keys, selectFrom } from '../shared/utilities/tsUtils'
import fs2 from '../shared/fs/fs'
import fs from '../shared/fs/fs'
import { DeclaredCommand } from '../shared/vscode/commands2'
import { mkdirSync, existsSync } from 'fs'
import * as nodefs from 'fs/promises'
import { randomBytes } from 'crypto'
import request from '../shared/request'
import { stub } from 'sinon'
Expand All @@ -33,15 +31,15 @@ export async function toFile(o: any, filepath: string | vscode.Uri) {
const file = typeof filepath === 'string' ? filepath : filepath.fsPath
const text = o === undefined ? '' : o.toString()
const dir = path.dirname(file)
await fs2.mkdir(dir)
await fs2.writeFile(file, text)
await fs.mkdir(dir)
await fs.writeFile(file, text)
}

/**
* Gets the contents of `filepath` as UTF-8 encoded string.
*/
export async function fromFile(filepath: string): Promise<string> {
return fs2.readFileAsString(filepath)
return fs.readFileAsString(filepath)
}

/** Gets the full path to the Toolkit source root on this machine. */
Expand Down Expand Up @@ -97,7 +95,7 @@ export class TestFolder {
await toFile(content ?? '', filePath)

if (options?.mode !== undefined) {
await nodefs.chmod(filePath, options.mode)
await fs.chmod(filePath, options.mode)
}

return filePath
Expand Down Expand Up @@ -144,7 +142,7 @@ export async function createTestWorkspaceFolder(name?: string, subDir?: string):
testTempDirs.push(tempFolder)
const finalWsFolder = subDir === undefined ? tempFolder : path.join(tempFolder, subDir)
if (subDir !== undefined && subDir.length > 0) {
await nodefs.mkdir(finalWsFolder, { recursive: true })
await fs.mkdir(finalWsFolder)
}
return {
uri: vscode.Uri.file(finalWsFolder),
Expand All @@ -157,7 +155,7 @@ export async function createTestFile(fileName: string): Promise<vscode.Uri> {
const tempFolder = await makeTemporaryToolkitFolder()
testTempDirs.push(tempFolder) // ensures this is deleted at the end
const tempFilePath = path.join(tempFolder, fileName)
await fs2.writeFile(tempFilePath, '')
await fs.writeFile(tempFilePath, '')
return vscode.Uri.file(tempFilePath)
}

Expand Down Expand Up @@ -205,7 +203,7 @@ export async function createTestWorkspace(

do {
const tempFilePath = path.join(workspace.uri.fsPath, `${fileNamePrefix}${n}${fileNameSuffix}`)
await fs2.writeFile(tempFilePath, fileContent)
await fs.writeFile(tempFilePath, fileContent)
} while (--n > 0)

return workspace
Expand Down Expand Up @@ -236,7 +234,7 @@ export function assertEqualPaths(actual: string, expected: string, message?: str
* Asserts that UTF-8 contents of `file` are equal to `expected`.
*/
export async function assertFileText(file: string, expected: string, message?: string | Error) {
const actualContents = await fs2.readFileAsString(file)
const actualContents = await fs.readFileAsString(file)
assert.strictEqual(actualContents, expected, message)
}

Expand All @@ -250,12 +248,12 @@ export async function tickPromise<T>(promise: Promise<T>, clock: FakeTimers.Inst
* Creates an executable file (including any parent directories) with the given contents.
*/
export async function createExecutableFile(filepath: string, contents: string): Promise<void> {
await fs2.mkdir(path.dirname(filepath))
await fs.mkdir(path.dirname(filepath))
if (process.platform === 'win32') {
await fs2.writeFile(filepath, `@echo OFF$\r\n${contents}\r\n`)
await fs.writeFile(filepath, `@echo OFF$\r\n${contents}\r\n`)
} else {
await fs2.writeFile(filepath, `#!/bin/sh\n${contents}`)
nodeFsSync.chmodSync(filepath, 0o744)
await fs.writeFile(filepath, `#!/bin/sh\n${contents}`)
await fs.chmod(filepath, 0o744)
}
}

Expand Down
Loading