chore(cache): minimize tar isolation diff
Restore the existing helper layout and separate test cases rather than bundling unrelated consolidation with the bug fix. Leave archive creation unchanged and retain only the read isolation, necessary path handling, and regression coverage.
This commit is contained in:
1 parent
dd137a579c
commit
fce8715913
2 files changed
+121
-58
No files matched your search
+76
-29
@@ -84,56 +84,57 @@ test('zstd extract tar', async () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test.each([
|
test('zstd extract tar with windows BSDtar', async () => {
|
||||||
{operation: 'extract', read: tar.extractTar, flag: '-xf'},
|
if (IS_WINDOWS) {
|
||||||
{operation: 'list', read: tar.listTar, flag: '-tf'}
|
|
||||||
])(
|
|
||||||
'zstd $operation tar with windows BSDtar',
|
|
||||||
async ({operation, read, flag}) => {
|
|
||||||
if (!IS_WINDOWS) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
||||||
const execMock = jest.spyOn(exec, 'exec')
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
const tempDirectory = getTempDir()
|
const tempDirectory = getTempDir()
|
||||||
jest.spyOn(utils, 'createTempDirectory').mockResolvedValue(tempDirectory)
|
jest.spyOn(utils, 'createTempDirectory').mockResolvedValue(tempDirectory)
|
||||||
jest.spyOn(utils, 'getGnuTarPathOnWindows').mockResolvedValue('')
|
jest
|
||||||
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
||||||
|
.mockReturnValue(Promise.resolve(''))
|
||||||
|
|
||||||
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
||||||
const workspace = process.env['GITHUB_WORKSPACE']
|
const workspace = process.env['GITHUB_WORKSPACE']
|
||||||
const options = {
|
const tarPath = SystemTarPathOnWindows
|
||||||
cwd: tempDirectory,
|
|
||||||
env: expect.objectContaining(defaultEnv)
|
|
||||||
}
|
|
||||||
const tarArgs = [`"${SystemTarPathOnWindows}"`, flag, TarFilename, '-P']
|
|
||||||
if (operation === 'extract') {
|
|
||||||
tarArgs.push('-C', `"${workspace?.replace(/\\/g, '/')}"`)
|
|
||||||
}
|
|
||||||
|
|
||||||
await read(archivePath, CompressionMethod.Zstd)
|
await tar.extractTar(archivePath, CompressionMethod.Zstd)
|
||||||
|
|
||||||
if (operation === 'extract') {
|
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
||||||
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
|
||||||
}
|
|
||||||
expect(execMock).toHaveBeenCalledTimes(2)
|
expect(execMock).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
expect(execMock).toHaveBeenNthCalledWith(
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
1,
|
1,
|
||||||
[
|
[
|
||||||
'zstd -d --long=30 --force -o',
|
'zstd -d --long=30 --force -o',
|
||||||
TarFilename,
|
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
`"${archivePath.replace(/\\/g, '/')}"`
|
`"${archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')}"`
|
||||||
].join(' '),
|
].join(' '),
|
||||||
undefined,
|
undefined,
|
||||||
options
|
{
|
||||||
|
cwd: tempDirectory,
|
||||||
|
env: expect.objectContaining(defaultEnv)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(execMock).toHaveBeenNthCalledWith(
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
2,
|
2,
|
||||||
tarArgs.join(' '),
|
[
|
||||||
|
`"${tarPath}"`,
|
||||||
|
'-xf',
|
||||||
|
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P',
|
||||||
|
'-C',
|
||||||
|
`"${workspace?.replace(/\\/g, '/')}"`
|
||||||
|
].join(' '),
|
||||||
undefined,
|
undefined,
|
||||||
options
|
{
|
||||||
|
cwd: tempDirectory,
|
||||||
|
env: expect.objectContaining(defaultEnv)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
|
|
||||||
test('gzip extract tar', async () => {
|
test('gzip extract tar', async () => {
|
||||||
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
||||||
@@ -279,7 +280,7 @@ test('zstd create tar with windows BSDtar', async () => {
|
|||||||
TarFilename.replace(/\\/g, '/'),
|
TarFilename.replace(/\\/g, '/'),
|
||||||
'-P',
|
'-P',
|
||||||
'-C',
|
'-C',
|
||||||
`"${workspace?.replace(/\\/g, '/')}"`,
|
workspace?.replace(/\\/g, '/'),
|
||||||
'--files-from',
|
'--files-from',
|
||||||
ManifestFilename
|
ManifestFilename
|
||||||
].join(' '),
|
].join(' '),
|
||||||
@@ -379,6 +380,52 @@ test('zstd list tar', async () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('zstd list tar with windows BSDtar', async () => {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
|
const tempDirectory = getTempDir()
|
||||||
|
jest.spyOn(utils, 'createTempDirectory').mockResolvedValue(tempDirectory)
|
||||||
|
jest
|
||||||
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
||||||
|
.mockReturnValue(Promise.resolve(''))
|
||||||
|
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
||||||
|
|
||||||
|
await tar.listTar(archivePath, CompressionMethod.Zstd)
|
||||||
|
|
||||||
|
const tarPath = SystemTarPathOnWindows
|
||||||
|
expect(execMock).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
'zstd -d --long=30 --force -o',
|
||||||
|
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
`"${archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')}"`
|
||||||
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
cwd: tempDirectory,
|
||||||
|
env: expect.objectContaining(defaultEnv)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
[
|
||||||
|
`"${tarPath}"`,
|
||||||
|
'-tf',
|
||||||
|
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P'
|
||||||
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
cwd: tempDirectory,
|
||||||
|
env: expect.objectContaining(defaultEnv)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('zstdWithoutLong list tar', async () => {
|
test('zstdWithoutLong list tar', async () => {
|
||||||
const execMock = jest.spyOn(exec, 'exec')
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
|
|
||||||
|
|||||||
+45
-29
@@ -19,17 +19,6 @@ interface TarCommands {
|
|||||||
requiresTempDirectory: boolean
|
requiresTempDirectory: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBsdTarZstd(
|
|
||||||
tarPath: ArchiveTool,
|
|
||||||
compressionMethod: CompressionMethod
|
|
||||||
): boolean {
|
|
||||||
return (
|
|
||||||
IS_WINDOWS &&
|
|
||||||
tarPath.type === ArchiveToolType.BSD &&
|
|
||||||
compressionMethod !== CompressionMethod.Gzip
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns tar path and type: BSD or GNU
|
// Returns tar path and type: BSD or GNU
|
||||||
async function getTarPath(): Promise<ArchiveTool> {
|
async function getTarPath(): Promise<ArchiveTool> {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
@@ -74,16 +63,14 @@ async function getTarArgs(
|
|||||||
archivePath = ''
|
archivePath = ''
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
const args = [`"${tarPath.path}"`]
|
const args = [`"${tarPath.path}"`]
|
||||||
const BSD_TAR_ZSTD = isBsdTarZstd(tarPath, compressionMethod)
|
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
||||||
const tarFile = BSD_TAR_ZSTD
|
const tarFile = 'cache.tar'
|
||||||
? TarFilename
|
const workingDirectory = getWorkingDirectory()
|
||||||
: (type === 'create'
|
// Speficic args for BSD tar on windows for workaround
|
||||||
? utils.getCacheFileName(compressionMethod)
|
const BSD_TAR_ZSTD =
|
||||||
: archivePath
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
).replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
const workingDirectory = BSD_TAR_ZSTD
|
IS_WINDOWS
|
||||||
? quoteAbsolutePath(getWorkingDirectory())
|
|
||||||
: getWorkingDirectory().replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
|
||||||
|
|
||||||
// Method specific args
|
// Method specific args
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -91,21 +78,41 @@ async function getTarArgs(
|
|||||||
args.push(
|
args.push(
|
||||||
'--posix',
|
'--posix',
|
||||||
'-cf',
|
'-cf',
|
||||||
tarFile,
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
'--exclude',
|
'--exclude',
|
||||||
tarFile,
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
'-P',
|
'-P',
|
||||||
'-C',
|
'-C',
|
||||||
workingDirectory,
|
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
'--files-from',
|
'--files-from',
|
||||||
ManifestFilename
|
ManifestFilename
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
case 'extract':
|
case 'extract':
|
||||||
args.push('-xf', tarFile, '-P', '-C', workingDirectory)
|
args.push(
|
||||||
|
'-xf',
|
||||||
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P',
|
||||||
|
'-C',
|
||||||
|
BSD_TAR_ZSTD
|
||||||
|
? quoteAbsolutePath(workingDirectory)
|
||||||
|
: workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||||
|
)
|
||||||
break
|
break
|
||||||
case 'list':
|
case 'list':
|
||||||
args.push('-tf', tarFile, '-P')
|
args.push(
|
||||||
|
'-tf',
|
||||||
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P'
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,7 +150,10 @@ async function getCommands(
|
|||||||
type !== 'create'
|
type !== 'create'
|
||||||
? await getDecompressionProgram(tarPath, compressionMethod, archivePath)
|
? await getDecompressionProgram(tarPath, compressionMethod, archivePath)
|
||||||
: await getCompressionProgram(tarPath, compressionMethod)
|
: await getCompressionProgram(tarPath, compressionMethod)
|
||||||
const BSD_TAR_ZSTD = isBsdTarZstd(tarPath, compressionMethod)
|
const BSD_TAR_ZSTD =
|
||||||
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
|
IS_WINDOWS
|
||||||
|
|
||||||
if (BSD_TAR_ZSTD && type !== 'create') {
|
if (BSD_TAR_ZSTD && type !== 'create') {
|
||||||
args = [[...compressionArgs].join(' '), [...tarArgs].join(' ')]
|
args = [[...compressionArgs].join(' '), [...tarArgs].join(' ')]
|
||||||
@@ -175,7 +185,10 @@ async function getDecompressionProgram(
|
|||||||
// unzstd is equivalent to 'zstd -d'
|
// unzstd is equivalent to 'zstd -d'
|
||||||
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
||||||
// Using 30 here because we also support 32-bit self-hosted runners.
|
// Using 30 here because we also support 32-bit self-hosted runners.
|
||||||
const BSD_TAR_ZSTD = isBsdTarZstd(tarPath, compressionMethod)
|
const BSD_TAR_ZSTD =
|
||||||
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
|
IS_WINDOWS
|
||||||
switch (compressionMethod) {
|
switch (compressionMethod) {
|
||||||
case CompressionMethod.Zstd:
|
case CompressionMethod.Zstd:
|
||||||
return BSD_TAR_ZSTD
|
return BSD_TAR_ZSTD
|
||||||
@@ -208,7 +221,10 @@ async function getCompressionProgram(
|
|||||||
compressionMethod: CompressionMethod
|
compressionMethod: CompressionMethod
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
||||||
const BSD_TAR_ZSTD = isBsdTarZstd(tarPath, compressionMethod)
|
const BSD_TAR_ZSTD =
|
||||||
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
|
IS_WINDOWS
|
||||||
switch (compressionMethod) {
|
switch (compressionMethod) {
|
||||||
case CompressionMethod.Zstd:
|
case CompressionMethod.Zstd:
|
||||||
return BSD_TAR_ZSTD
|
return BSD_TAR_ZSTD
|
||||||
|
|||||||
Reference in new issue
Block a user