-
Notifications
You must be signed in to change notification settings - Fork 1.7k
fix extractTar on Windows #264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8424027
6c95eda
e372509
0071524
443db38
4b8b9fd
46de6c6
9eee88d
6af6cc0
67b788f
45be6ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -268,96 +268,88 @@ 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) | ||
| it('extract .tar.gz', async () => { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no changes here, just eliminated the |
||
| const tempDir = path.join(tempPath, 'test-install-tar.gz') | ||
|
|
||
| // 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) | ||
| await io.mkdirP(tempDir) | ||
|
|
||
| // 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') | ||
| // 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) | ||
|
|
||
| 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') | ||
| }) | ||
| // 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') | ||
|
|
||
| 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') | ||
| 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') | ||
| }) | ||
|
|
||
| await io.mkdirP(tempDir) | ||
| 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') | ||
|
|
||
| // 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) | ||
| await io.mkdirP(tempDir) | ||
|
|
||
| // 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') | ||
| // 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) | ||
|
|
||
| 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') | ||
| }) | ||
| // 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') | ||
|
|
||
| it('extract .tar.xz', async () => { | ||
| const tempDir = path.join(tempPath, 'test-install-tar.xz') | ||
| 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') | ||
| }) | ||
|
|
||
| await io.mkdirP(tempDir) | ||
| it('extract .tar.xz', async () => { | ||
| const tempDir = path.join(tempPath, 'test-install-tar.xz') | ||
|
|
||
| // 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) | ||
| await io.mkdirP(tempDir) | ||
|
|
||
| // 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') | ||
| // 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) | ||
|
|
||
| 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') | ||
| }) | ||
| } | ||
| // 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') | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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') | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider debugging this so we can troubleshoot easier if for some reason this breaks. (Analyzing text output of a cli can be a little fragile)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the output flows to the console too, so we're good wrt that aspect |
||
|
|
||
| // Initialize args | ||
| const args = [flags] | ||
|
|
||
| let destArg = dest | ||
| let fileArg = file | ||
| if (IS_WINDOWS && isGnuTar) { | ||
| args.push('--force-local') | ||
| destArg = dest.replace(/\\/g, '/') | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can add for file too, but when i tested
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i'll push this change, aesthetically it will look good for consistency |
||
|
|
||
| // 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 | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i had to recreate test.tar.gz with the option
--format paxotherwise bsdtar doesnt preserve UTF file names correctlyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i added a README.txt to the archive for future reference