diff --git a/packages/tool-cache/__tests__/data/test.tar.gz b/packages/tool-cache/__tests__/data/test.tar.gz index 9ba362f6..ea74cafe 100644 Binary files a/packages/tool-cache/__tests__/data/test.tar.gz and b/packages/tool-cache/__tests__/data/test.tar.gz differ diff --git a/packages/tool-cache/__tests__/tool-cache.test.ts b/packages/tool-cache/__tests__/tool-cache.test.ts index be176f1b..543280a5 100644 --- a/packages/tool-cache/__tests__/tool-cache.test.ts +++ b/packages/tool-cache/__tests__/tool-cache.test.ts @@ -268,97 +268,89 @@ describe('@actions/tool-cache', function() { await io.rmRF(tempDir) } }) - } else { - it('extract .tar.gz', async () => { - const tempDir = path.join(tempPath, 'test-install-tar.gz') - - await io.mkdirP(tempDir) - - // copy the .tar.gz file to the test dir - const _tgzFile: string = path.join(tempDir, 'test.tar.gz') - await io.cp(path.join(__dirname, 'data', 'test.tar.gz'), _tgzFile) - - // extract/cache - const extPath: string = await tc.extractTar(_tgzFile) - await tc.cacheDir(extPath, 'my-tgz-contents', '1.1.0') - const toolPath: string = tc.find('my-tgz-contents', '1.1.0') - - expect(fs.existsSync(toolPath)).toBeTruthy() - expect(fs.existsSync(`${toolPath}.complete`)).toBeTruthy() - expect(fs.existsSync(path.join(toolPath, 'file.txt'))).toBeTruthy() - expect( - fs.existsSync(path.join(toolPath, 'file-with-ç-character.txt')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(toolPath, 'folder', 'nested-file.txt')) - ).toBeTruthy() - expect( - fs.readFileSync( - path.join(toolPath, 'folder', 'nested-file.txt'), - 'utf8' - ) - ).toBe('folder/nested-file.txt contents') - }) - - it('extract .tar.gz to a directory that does not exist', async () => { - const tempDir = path.join(tempPath, 'test-install-tar.gz') - const destDir = path.join(tempDir, 'not-exist') - - await io.mkdirP(tempDir) - - // copy the .tar.gz file to the test dir - const _tgzFile: string = path.join(tempDir, 'test.tar.gz') - await io.cp(path.join(__dirname, 'data', 'test.tar.gz'), _tgzFile) - - // extract/cache - const extPath: string = await tc.extractTar(_tgzFile, destDir) - await tc.cacheDir(extPath, 'my-tgz-contents', '1.1.0') - const toolPath: string = tc.find('my-tgz-contents', '1.1.0') - - expect(extPath).toContain('not-exist') - expect(fs.existsSync(toolPath)).toBeTruthy() - expect(fs.existsSync(`${toolPath}.complete`)).toBeTruthy() - expect(fs.existsSync(path.join(toolPath, 'file.txt'))).toBeTruthy() - expect( - fs.existsSync(path.join(toolPath, 'file-with-ç-character.txt')) - ).toBeTruthy() - expect( - fs.existsSync(path.join(toolPath, 'folder', 'nested-file.txt')) - ).toBeTruthy() - expect( - fs.readFileSync( - path.join(toolPath, 'folder', 'nested-file.txt'), - 'utf8' - ) - ).toBe('folder/nested-file.txt contents') - }) - - it('extract .tar.xz', async () => { - const tempDir = path.join(tempPath, 'test-install-tar.xz') - - await io.mkdirP(tempDir) - - // copy the .tar.gz file to the test dir - const _txzFile: string = path.join(tempDir, 'test.tar.xz') - await io.cp(path.join(__dirname, 'data', 'test.tar.xz'), _txzFile) - - // extract/cache - const extPath: string = await tc.extractTar(_txzFile, undefined, 'x') - await tc.cacheDir(extPath, 'my-txz-contents', '1.1.0') - const toolPath: string = tc.find('my-txz-contents', '1.1.0') - - expect(fs.existsSync(toolPath)).toBeTruthy() - expect(fs.existsSync(`${toolPath}.complete`)).toBeTruthy() - expect(fs.existsSync(path.join(toolPath, 'bar.txt'))).toBeTruthy() - expect( - fs.existsSync(path.join(toolPath, 'foo', 'hello.txt')) - ).toBeTruthy() - expect( - fs.readFileSync(path.join(toolPath, 'foo', 'hello.txt'), 'utf8') - ).toBe('foo/hello: world') - }) } + it('extract .tar.gz', async () => { + const tempDir = path.join(tempPath, 'test-install-tar.gz') + + await io.mkdirP(tempDir) + + // copy the .tar.gz file to the test dir + const _tgzFile: string = path.join(tempDir, 'test.tar.gz') + await io.cp(path.join(__dirname, 'data', 'test.tar.gz'), _tgzFile) + + // extract/cache + const extPath: string = await tc.extractTar(_tgzFile) + await tc.cacheDir(extPath, 'my-tgz-contents', '1.1.0') + const toolPath: string = tc.find('my-tgz-contents', '1.1.0') + + expect(fs.existsSync(toolPath)).toBeTruthy() + expect(fs.existsSync(`${toolPath}.complete`)).toBeTruthy() + expect(fs.existsSync(path.join(toolPath, 'file.txt'))).toBeTruthy() + expect( + fs.existsSync(path.join(toolPath, 'file-with-ç-character.txt')) + ).toBeTruthy() + expect( + fs.existsSync(path.join(toolPath, 'folder', 'nested-file.txt')) + ).toBeTruthy() + expect( + fs.readFileSync(path.join(toolPath, 'folder', 'nested-file.txt'), 'utf8') + ).toBe('folder/nested-file.txt contents') + }) + + it('extract .tar.gz to a directory that does not exist', async () => { + const tempDir = path.join(tempPath, 'test-install-tar.gz') + const destDir = path.join(tempDir, 'not-exist') + + await io.mkdirP(tempDir) + + // copy the .tar.gz file to the test dir + const _tgzFile: string = path.join(tempDir, 'test.tar.gz') + await io.cp(path.join(__dirname, 'data', 'test.tar.gz'), _tgzFile) + + // extract/cache + const extPath: string = await tc.extractTar(_tgzFile, destDir) + await tc.cacheDir(extPath, 'my-tgz-contents', '1.1.0') + const toolPath: string = tc.find('my-tgz-contents', '1.1.0') + + expect(extPath).toContain('not-exist') + expect(fs.existsSync(toolPath)).toBeTruthy() + expect(fs.existsSync(`${toolPath}.complete`)).toBeTruthy() + expect(fs.existsSync(path.join(toolPath, 'file.txt'))).toBeTruthy() + expect( + fs.existsSync(path.join(toolPath, 'file-with-ç-character.txt')) + ).toBeTruthy() + expect( + fs.existsSync(path.join(toolPath, 'folder', 'nested-file.txt')) + ).toBeTruthy() + expect( + fs.readFileSync(path.join(toolPath, 'folder', 'nested-file.txt'), 'utf8') + ).toBe('folder/nested-file.txt contents') + }) + + it('extract .tar.xz', async () => { + const tempDir = path.join(tempPath, 'test-install-tar.xz') + + await io.mkdirP(tempDir) + + // copy the .tar.gz file to the test dir + const _txzFile: string = path.join(tempDir, 'test.tar.xz') + await io.cp(path.join(__dirname, 'data', 'test.tar.xz'), _txzFile) + + // extract/cache + const extPath: string = await tc.extractTar(_txzFile, undefined, 'x') + await tc.cacheDir(extPath, 'my-txz-contents', '1.1.0') + const toolPath: string = tc.find('my-txz-contents', '1.1.0') + + expect(fs.existsSync(toolPath)).toBeTruthy() + expect(fs.existsSync(`${toolPath}.complete`)).toBeTruthy() + expect(fs.existsSync(path.join(toolPath, 'bar.txt'))).toBeTruthy() + expect(fs.existsSync(path.join(toolPath, 'foo', 'hello.txt'))).toBeTruthy() + expect( + fs.readFileSync(path.join(toolPath, 'foo', 'hello.txt'), 'utf8') + ).toBe('foo/hello: world') + }) + it('installs a zip and finds it', async () => { const tempDir = path.join(__dirname, 'test-install-zip') try { diff --git a/packages/tool-cache/src/tool-cache.ts b/packages/tool-cache/src/tool-cache.ts index 972eea0b..87265ff9 100644 --- a/packages/tool-cache/src/tool-cache.ts +++ b/packages/tool-cache/src/tool-cache.ts @@ -202,9 +202,41 @@ export async function extractTar( throw new Error("parameter 'file' is required") } + // Create dest dest = await _createExtractFolder(dest) - const tarPath: string = await io.which('tar', true) - await exec(`"${tarPath}"`, [flags, '-C', dest, '-f', file]) + + // Determine whether GNU tar + let versionOutput = '' + await exec('tar --version', [], { + ignoreReturnCode: true, + listeners: { + stdout: (data: Buffer) => (versionOutput += data.toString()), + stderr: (data: Buffer) => (versionOutput += data.toString()) + } + }) + const isGnuTar = versionOutput.toUpperCase().includes('GNU TAR') + + // Initialize args + const args = [flags] + + let destArg = dest + let fileArg = file + if (IS_WINDOWS && isGnuTar) { + args.push('--force-local') + destArg = dest.replace(/\\/g, '/') + + // Technically only the dest needs to have `/` but for aesthetic consistency + // convert slashes in the file arg too. + fileArg = file.replace(/\\/g, '/') + } + + if (isGnuTar) { + // Suppress warnings when using GNU tar to extract archives created by BSD tar + args.push('--warning=no-unknown-keyword') + } + + args.push('-C', destArg, '-f', fileArg) + await exec(`tar`, args) return dest }