From e7cbd693eb2325191be243329da1aaf3d9341a79 Mon Sep 17 00:00:00 2001 From: eric sciple Date: Thu, 19 Dec 2019 10:44:08 -0500 Subject: [PATCH] fix extractTar on Windows (#264) --- .../tool-cache/__tests__/data/test.tar.gz | Bin 281 -> 729 bytes .../tool-cache/__tests__/tool-cache.test.ts | 170 +++++++++--------- packages/tool-cache/src/tool-cache.ts | 36 +++- 3 files changed, 115 insertions(+), 91 deletions(-) diff --git a/packages/tool-cache/__tests__/data/test.tar.gz b/packages/tool-cache/__tests__/data/test.tar.gz index 9ba362f6234fad6550b31467c4da52b32f3f149b..ea74cafe2211a115dd274b6f7a325a773fb458f5 100644 GIT binary patch literal 729 zcmV;~0w(<*iwFRHMEP9+1MQgKZksR^#(SNouzEQO>i@t+F1EE(Cv8&IZkl$9h?Aft zP=VWIeW5+b9%ipGlcuGKlCVmFX6pC5aj=mwKKcBe!$mwlH}Sv}Czoe$Pd}gec5aXM z45d^{Nvbx`YSB`Df4zVUMwn26=8`id31w2V;E2rky^u}Zlr}EhQcRI1yY6$h4Tn3% z?_Y&Hw*Lu&lBrFnrqA5|yIrR`^tGfy=uk&JH=67mjaNoP<%c0xOh;VzxFA>W&p&?p z?hnjupXne7IHx_%AG*^l@4G-pBBVVQKJ;djH2cwKy_epYS3-NLuW8i3`%kRupKGa) z2yJgkHLqO%mnJDpYz?_7(`-bJ-DVKaTlRV0=q|l>%`h*fu_f2>yt+syhFDWt-`(tw z?#P>ClH0K>GUj|x+{5i$Fn`+(v1^oXIxL5s2tIufCf2EgI{c~CAU$wfb zC9hon%lOwekeSk&fw#}Ru(|%@_4gmQcac0im*EE0s4c7Fpgyg9Ix?pqsQ4InB000000000000000000000000000000aESZ` L%t0o~08jt`&o_5+ literal 281 zcmV+!0p|W6iwFP!000001MSw)ZG$ir1yGOT1t5O5AD)L2M?s1}!j9UFI!K1;8nxS` z^rHzsF>Ta)gv19(Sh_s>)*DfrN*r^(lVkdRzYt_t+jNn#LJ={skX(LgLL5VECn-fZ zK8>M|Rt=D<)7z2r~g(aeE8Eo=f7;=i}SDN`8PW6|AyFM{?~9xUv}dV{Sd=%F9=qZ z=6^hF{Zz6Be)PZ8@ox9O^ZdJf{%gk?{cjCl`42uszpYA~2Fv}=&HXR`Cu#R5i~WBM fKc|n=000000000000000;8DE;vO4YL04M+eM2v~K 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 }