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.
487 lines
13 KiB
TypeScript
487 lines
13 KiB
TypeScript
import * as exec from '@actions/exec'
|
|
import * as io from '@actions/io'
|
|
import * as path from 'path'
|
|
import {
|
|
CacheFilename,
|
|
CompressionMethod,
|
|
GnuTarPathOnWindows,
|
|
ManifestFilename,
|
|
SystemTarPathOnWindows,
|
|
TarFilename
|
|
} from '../src/internal/constants'
|
|
import * as tar from '../src/internal/tar'
|
|
import * as utils from '../src/internal/cacheUtils'
|
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
import fs = require('fs')
|
|
|
|
jest.mock('@actions/exec')
|
|
jest.mock('@actions/io')
|
|
|
|
const IS_WINDOWS = process.platform === 'win32'
|
|
const IS_MAC = process.platform === 'darwin'
|
|
|
|
const defaultTarPath = IS_MAC ? 'gtar' : 'tar'
|
|
|
|
const defaultEnv = {MSYS: 'winsymlinks:nativestrict'}
|
|
|
|
function getTempDir(): string {
|
|
return path.join(__dirname, '_temp', 'tar')
|
|
}
|
|
|
|
beforeAll(async () => {
|
|
jest.spyOn(io, 'which').mockImplementation(async tool => {
|
|
return tool
|
|
})
|
|
|
|
process.env['GITHUB_WORKSPACE'] = process.cwd()
|
|
await jest.requireActual('@actions/io').rmRF(getTempDir())
|
|
})
|
|
|
|
beforeEach(async () => {
|
|
jest.restoreAllMocks()
|
|
})
|
|
|
|
afterAll(async () => {
|
|
delete process.env['GITHUB_WORKSPACE']
|
|
await jest.requireActual('@actions/io').rmRF(getTempDir())
|
|
})
|
|
|
|
test('zstd extract tar', async () => {
|
|
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
|
|
const archivePath = IS_WINDOWS
|
|
? `${process.env['windir']}\\fakepath\\cache.tar`
|
|
: 'cache.tar'
|
|
const workspace = process.env['GITHUB_WORKSPACE']
|
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
|
|
|
await tar.extractTar(archivePath, CompressionMethod.Zstd)
|
|
|
|
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"${tarPath}"`,
|
|
'-xf',
|
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
|
'-P',
|
|
'-C',
|
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace
|
|
]
|
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
|
.concat([
|
|
'--use-compress-program',
|
|
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
|
|
])
|
|
.join(' '),
|
|
undefined,
|
|
{
|
|
cwd: undefined,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
})
|
|
|
|
test('zstd extract tar with windows BSDtar', async () => {
|
|
if (IS_WINDOWS) {
|
|
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
|
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`
|
|
const workspace = process.env['GITHUB_WORKSPACE']
|
|
const tarPath = SystemTarPathOnWindows
|
|
|
|
await tar.extractTar(archivePath, CompressionMethod.Zstd)
|
|
|
|
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
|
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}"`,
|
|
'-xf',
|
|
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
|
'-P',
|
|
'-C',
|
|
`"${workspace?.replace(/\\/g, '/')}"`
|
|
].join(' '),
|
|
undefined,
|
|
{
|
|
cwd: tempDirectory,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
}
|
|
})
|
|
|
|
test('gzip extract tar', async () => {
|
|
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
const archivePath = IS_WINDOWS
|
|
? `${process.env['windir']}\\fakepath\\cache.tar`
|
|
: 'cache.tar'
|
|
const workspace = process.env['GITHUB_WORKSPACE']
|
|
|
|
await tar.extractTar(archivePath, CompressionMethod.Gzip)
|
|
|
|
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"${tarPath}"`,
|
|
'-xf',
|
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
|
'-P',
|
|
'-C',
|
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace
|
|
]
|
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
|
.concat(['-z'])
|
|
.join(' '),
|
|
undefined,
|
|
{
|
|
cwd: undefined,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
})
|
|
|
|
test('gzip extract GNU tar on windows with GNUtar in path', async () => {
|
|
if (IS_WINDOWS) {
|
|
// GNU tar present in path but not at default location
|
|
jest
|
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
|
.mockReturnValue(Promise.resolve('tar'))
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
|
const workspace = process.env['GITHUB_WORKSPACE']
|
|
|
|
await tar.extractTar(archivePath, CompressionMethod.Gzip)
|
|
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"tar"`,
|
|
'-xf',
|
|
archivePath.replace(/\\/g, '/'),
|
|
'-P',
|
|
'-C',
|
|
workspace?.replace(/\\/g, '/'),
|
|
'--force-local',
|
|
'-z'
|
|
].join(' '),
|
|
undefined,
|
|
{
|
|
cwd: undefined,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
}
|
|
})
|
|
|
|
test('zstd create tar', async () => {
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
|
|
const archiveFolder = getTempDir()
|
|
const workspace = process.env['GITHUB_WORKSPACE']
|
|
const sourceDirectories = ['~/.npm/cache', `${workspace}/dist`]
|
|
|
|
await fs.promises.mkdir(archiveFolder, {recursive: true})
|
|
|
|
await tar.createTar(archiveFolder, sourceDirectories, CompressionMethod.Zstd)
|
|
|
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
|
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"${tarPath}"`,
|
|
'--posix',
|
|
'-cf',
|
|
IS_WINDOWS ? CacheFilename.Zstd.replace(/\\/g, '/') : CacheFilename.Zstd,
|
|
'--exclude',
|
|
IS_WINDOWS ? CacheFilename.Zstd.replace(/\\/g, '/') : CacheFilename.Zstd,
|
|
'-P',
|
|
'-C',
|
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace,
|
|
'--files-from',
|
|
ManifestFilename
|
|
]
|
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
|
.concat([
|
|
'--use-compress-program',
|
|
IS_WINDOWS ? '"zstd -T0 --long=30"' : 'zstdmt --long=30'
|
|
])
|
|
.join(' '),
|
|
undefined, // args
|
|
{
|
|
cwd: archiveFolder,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
})
|
|
|
|
test('zstd create tar with windows BSDtar', async () => {
|
|
if (IS_WINDOWS) {
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
jest
|
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
|
.mockReturnValue(Promise.resolve(''))
|
|
|
|
const archiveFolder = getTempDir()
|
|
const workspace = process.env['GITHUB_WORKSPACE']
|
|
const sourceDirectories = ['~/.npm/cache', `${workspace}/dist`]
|
|
|
|
await fs.promises.mkdir(archiveFolder, {recursive: true})
|
|
|
|
await tar.createTar(
|
|
archiveFolder,
|
|
sourceDirectories,
|
|
CompressionMethod.Zstd
|
|
)
|
|
|
|
const tarPath = SystemTarPathOnWindows
|
|
|
|
expect(execMock).toHaveBeenCalledTimes(2)
|
|
|
|
expect(execMock).toHaveBeenNthCalledWith(
|
|
1,
|
|
[
|
|
`"${tarPath}"`,
|
|
'--posix',
|
|
'-cf',
|
|
TarFilename.replace(/\\/g, '/'),
|
|
'--exclude',
|
|
TarFilename.replace(/\\/g, '/'),
|
|
'-P',
|
|
'-C',
|
|
workspace?.replace(/\\/g, '/'),
|
|
'--files-from',
|
|
ManifestFilename
|
|
].join(' '),
|
|
undefined, // args
|
|
{
|
|
cwd: archiveFolder,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
|
|
expect(execMock).toHaveBeenNthCalledWith(
|
|
2,
|
|
[
|
|
'zstd -T0 --long=30 --force -o',
|
|
CacheFilename.Zstd.replace(/\\/g, '/'),
|
|
TarFilename.replace(/\\/g, '/')
|
|
].join(' '),
|
|
undefined, // args
|
|
{
|
|
cwd: archiveFolder,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
}
|
|
})
|
|
|
|
test('gzip create tar', async () => {
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
|
|
const archiveFolder = getTempDir()
|
|
const workspace = process.env['GITHUB_WORKSPACE']
|
|
const sourceDirectories = ['~/.npm/cache', `${workspace}/dist`]
|
|
|
|
await fs.promises.mkdir(archiveFolder, {recursive: true})
|
|
|
|
await tar.createTar(archiveFolder, sourceDirectories, CompressionMethod.Gzip)
|
|
|
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
|
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"${tarPath}"`,
|
|
'--posix',
|
|
'-cf',
|
|
IS_WINDOWS ? CacheFilename.Gzip.replace(/\\/g, '/') : CacheFilename.Gzip,
|
|
'--exclude',
|
|
IS_WINDOWS ? CacheFilename.Gzip.replace(/\\/g, '/') : CacheFilename.Gzip,
|
|
'-P',
|
|
'-C',
|
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace,
|
|
'--files-from',
|
|
ManifestFilename
|
|
]
|
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
|
.concat(['-z'])
|
|
.join(' '),
|
|
undefined, // args
|
|
{
|
|
cwd: archiveFolder,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
})
|
|
|
|
test('zstd list tar', async () => {
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
|
|
const archivePath = IS_WINDOWS
|
|
? `${process.env['windir']}\\fakepath\\cache.tar`
|
|
: 'cache.tar'
|
|
|
|
await tar.listTar(archivePath, CompressionMethod.Zstd)
|
|
|
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"${tarPath}"`,
|
|
'-tf',
|
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
|
'-P'
|
|
]
|
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
|
.concat([
|
|
'--use-compress-program',
|
|
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
|
|
])
|
|
.join(' '),
|
|
undefined,
|
|
{
|
|
cwd: undefined,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
})
|
|
|
|
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 () => {
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
|
|
const archivePath = IS_WINDOWS
|
|
? `${process.env['windir']}\\fakepath\\cache.tar`
|
|
: 'cache.tar'
|
|
|
|
await tar.listTar(archivePath, CompressionMethod.ZstdWithoutLong)
|
|
|
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"${tarPath}"`,
|
|
'-tf',
|
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
|
'-P'
|
|
]
|
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
|
.concat(['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'])
|
|
.join(' '),
|
|
undefined,
|
|
{
|
|
cwd: undefined,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
})
|
|
|
|
test('gzip list tar', async () => {
|
|
const execMock = jest.spyOn(exec, 'exec')
|
|
const archivePath = IS_WINDOWS
|
|
? `${process.env['windir']}\\fakepath\\cache.tar`
|
|
: 'cache.tar'
|
|
|
|
await tar.listTar(archivePath, CompressionMethod.Gzip)
|
|
|
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
|
expect(execMock).toHaveBeenCalledTimes(1)
|
|
expect(execMock).toHaveBeenCalledWith(
|
|
[
|
|
`"${tarPath}"`,
|
|
'-tf',
|
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
|
'-P'
|
|
]
|
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
|
.concat(['-z'])
|
|
.join(' '),
|
|
undefined,
|
|
{
|
|
cwd: undefined,
|
|
env: expect.objectContaining(defaultEnv)
|
|
}
|
|
)
|
|
})
|