mirror of https://github.com/actions/toolkit
parent
bf4ce74a0f
commit
c9af6bb1b3
|
@ -556,6 +556,45 @@ describe('rmRF', () => {
|
||||||
await assertNotExists(symlinkFile)
|
await assertNotExists(symlinkFile)
|
||||||
await assertNotExists(outerDirectory)
|
await assertNotExists(outerDirectory)
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
it('correctly escapes % on windows', async () => {
|
||||||
|
const root: string = path.join(getTestTemp(), 'rmRF_escape_test_win')
|
||||||
|
const directory: string = path.join(root, '%test%')
|
||||||
|
await io.mkdirP(root)
|
||||||
|
await io.mkdirP(directory)
|
||||||
|
const oldEnv = process.env['test']
|
||||||
|
process.env['test'] = 'thisshouldnotresolve'
|
||||||
|
|
||||||
|
await io.rmRF(directory)
|
||||||
|
await assertNotExists(directory)
|
||||||
|
process.env['test'] = oldEnv
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should throw for invalid characters', async () => {
|
||||||
|
const root: string = path.join(getTestTemp(), 'rmRF_invalidChar_Windows')
|
||||||
|
const errorString =
|
||||||
|
'File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'
|
||||||
|
await expect(io.rmRF(path.join(root, '"'))).rejects.toHaveProperty(
|
||||||
|
'message',
|
||||||
|
errorString
|
||||||
|
)
|
||||||
|
await expect(io.rmRF(path.join(root, '<'))).rejects.toHaveProperty(
|
||||||
|
'message',
|
||||||
|
errorString
|
||||||
|
)
|
||||||
|
await expect(io.rmRF(path.join(root, '>'))).rejects.toHaveProperty(
|
||||||
|
'message',
|
||||||
|
errorString
|
||||||
|
)
|
||||||
|
await expect(io.rmRF(path.join(root, '|'))).rejects.toHaveProperty(
|
||||||
|
'message',
|
||||||
|
errorString
|
||||||
|
)
|
||||||
|
await expect(io.rmRF(path.join(root, '*'))).rejects.toHaveProperty(
|
||||||
|
'message',
|
||||||
|
errorString
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
it('removes symlink folder with missing source using rmRF', async () => {
|
it('removes symlink folder with missing source using rmRF', async () => {
|
||||||
|
|
|
@ -166,3 +166,8 @@ function isUnixExecutable(stats: fs.Stats): boolean {
|
||||||
((stats.mode & 64) > 0 && stats.uid === process.getuid())
|
((stats.mode & 64) > 0 && stats.uid === process.getuid())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the path of cmd.exe in windows
|
||||||
|
export function getCmdPath(): string {
|
||||||
|
return process.env['COMSPEC'] ?? `cmd.exe`
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {promisify} from 'util'
|
||||||
import * as ioUtil from './io-util'
|
import * as ioUtil from './io-util'
|
||||||
|
|
||||||
const exec = promisify(childProcess.exec)
|
const exec = promisify(childProcess.exec)
|
||||||
|
const execFile = promisify(childProcess.execFile)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for cp/mv options
|
* Interface for cp/mv options
|
||||||
|
@ -117,11 +118,24 @@ export async function rmRF(inputPath: string): Promise<void> {
|
||||||
if (ioUtil.IS_WINDOWS) {
|
if (ioUtil.IS_WINDOWS) {
|
||||||
// Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
|
// Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
|
||||||
// program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
|
// program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
|
||||||
|
|
||||||
|
// Check for invalid characters
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
|
||||||
|
if (/[*"<>|]/.test(inputPath)) {
|
||||||
|
throw new Error(
|
||||||
|
'File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'
|
||||||
|
)
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
|
const cmdPath = ioUtil.getCmdPath()
|
||||||
if (await ioUtil.isDirectory(inputPath, true)) {
|
if (await ioUtil.isDirectory(inputPath, true)) {
|
||||||
await exec(`rd /s /q "${inputPath}"`)
|
await exec(`${cmdPath} /s /c "rd /s /q "%inputPath%""`, {
|
||||||
|
env: {inputPath}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
await exec(`del /f /a "${inputPath}"`)
|
await exec(`${cmdPath} /s /c "del /f /a "%inputPath%""`, {
|
||||||
|
env: {inputPath}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// if you try to delete a file that doesn't exist, desired result is achieved
|
// if you try to delete a file that doesn't exist, desired result is achieved
|
||||||
|
@ -149,7 +163,7 @@ export async function rmRF(inputPath: string): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDir) {
|
if (isDir) {
|
||||||
await exec(`rm -rf "${inputPath}"`)
|
await execFile(`rm`, [`-rf`, `${inputPath}`])
|
||||||
} else {
|
} else {
|
||||||
await ioUtil.unlink(inputPath)
|
await ioUtil.unlink(inputPath)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue