mirror of
https://github.com/jdx/mise-action.git
synced 2026-07-02 09:39:30 +00:00
refactor: extract mise tarball directly into miseDir()
Strip the leading `mise/` component and extract straight into miseDir(), so the binary lands at miseBinPath and man pages, completions, etc. land in their native locations. Removes the temp dir and the cross-device copy entirely. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e5654ed8b5
commit
2c202d47b9
3 changed files with 30 additions and 139 deletions
145
dist/index.js
generated
vendored
145
dist/index.js
generated
vendored
|
|
@ -28779,31 +28779,9 @@ var __awaiter$j = (undefined && undefined.__awaiter) || function (thisArg, _argu
|
|||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
const { chmod, copyFile: copyFile$1, lstat, mkdir, open, readdir, rename, rm, rmdir, stat, symlink, unlink } = fs.promises;
|
||||
const { chmod, copyFile, lstat, mkdir, open, readdir, rename, rm, rmdir, stat, symlink, unlink } = fs.promises;
|
||||
// export const {open} = 'fs'
|
||||
const IS_WINDOWS$d = process.platform === 'win32';
|
||||
/**
|
||||
* Custom implementation of readlink to ensure Windows junctions
|
||||
* maintain trailing backslash for backward compatibility with Node.js < 24
|
||||
*
|
||||
* In Node.js 20, Windows junctions (directory symlinks) always returned paths
|
||||
* with trailing backslashes. Node.js 24 removed this behavior, which breaks
|
||||
* code that relied on this format for path operations.
|
||||
*
|
||||
* This implementation restores the Node 20 behavior by adding a trailing
|
||||
* backslash to all junction results on Windows.
|
||||
*/
|
||||
function readlink(fsPath) {
|
||||
return __awaiter$j(this, void 0, void 0, function* () {
|
||||
const result = yield fs.promises.readlink(fsPath);
|
||||
// On Windows, restore Node 20 behavior: add trailing backslash to all results
|
||||
// since junctions on Windows are always directory links
|
||||
if (IS_WINDOWS$d && !result.endsWith('\\')) {
|
||||
return `${result}\\`;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
fs.constants.O_RDONLY;
|
||||
function exists(fsPath) {
|
||||
return __awaiter$j(this, void 0, void 0, function* () {
|
||||
|
|
@ -28949,47 +28927,6 @@ var __awaiter$i = (undefined && undefined.__awaiter) || function (thisArg, _argu
|
|||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Copies a file or folder.
|
||||
* Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js
|
||||
*
|
||||
* @param source source path
|
||||
* @param dest destination path
|
||||
* @param options optional. See CopyOptions.
|
||||
*/
|
||||
function cp(source_1, dest_1) {
|
||||
return __awaiter$i(this, arguments, void 0, function* (source, dest, options = {}) {
|
||||
const { force, recursive, copySourceDirectory } = readCopyOptions(options);
|
||||
const destStat = (yield exists(dest)) ? yield stat(dest) : null;
|
||||
// Dest is an existing file, but not forcing
|
||||
if (destStat && destStat.isFile() && !force) {
|
||||
return;
|
||||
}
|
||||
// If dest is an existing directory, should copy inside.
|
||||
const newDest = destStat && destStat.isDirectory() && copySourceDirectory
|
||||
? path$1.join(dest, path$1.basename(source))
|
||||
: dest;
|
||||
if (!(yield exists(source))) {
|
||||
throw new Error(`no such file or directory: ${source}`);
|
||||
}
|
||||
const sourceStat = yield stat(source);
|
||||
if (sourceStat.isDirectory()) {
|
||||
if (!recursive) {
|
||||
throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`);
|
||||
}
|
||||
else {
|
||||
yield cpDirRecursive(source, newDest, 0, force);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (path$1.relative(source, newDest) === '') {
|
||||
// a file cannot be copied to itself
|
||||
throw new Error(`'${newDest}' and '${source}' are the same file`);
|
||||
}
|
||||
yield copyFile(source, newDest, force);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Moves a path.
|
||||
*
|
||||
|
|
@ -29149,64 +29086,6 @@ function findInPath(tool) {
|
|||
return matches;
|
||||
});
|
||||
}
|
||||
function readCopyOptions(options) {
|
||||
const force = options.force == null ? true : options.force;
|
||||
const recursive = Boolean(options.recursive);
|
||||
const copySourceDirectory = options.copySourceDirectory == null
|
||||
? true
|
||||
: Boolean(options.copySourceDirectory);
|
||||
return { force, recursive, copySourceDirectory };
|
||||
}
|
||||
function cpDirRecursive(sourceDir, destDir, currentDepth, force) {
|
||||
return __awaiter$i(this, void 0, void 0, function* () {
|
||||
// Ensure there is not a run away recursive copy
|
||||
if (currentDepth >= 255)
|
||||
return;
|
||||
currentDepth++;
|
||||
yield mkdirP(destDir);
|
||||
const files = yield readdir(sourceDir);
|
||||
for (const fileName of files) {
|
||||
const srcFile = `${sourceDir}/${fileName}`;
|
||||
const destFile = `${destDir}/${fileName}`;
|
||||
const srcFileStat = yield lstat(srcFile);
|
||||
if (srcFileStat.isDirectory()) {
|
||||
// Recurse
|
||||
yield cpDirRecursive(srcFile, destFile, currentDepth, force);
|
||||
}
|
||||
else {
|
||||
yield copyFile(srcFile, destFile, force);
|
||||
}
|
||||
}
|
||||
// Change the mode for the newly created directory
|
||||
yield chmod(destDir, (yield stat(sourceDir)).mode);
|
||||
});
|
||||
}
|
||||
// Buffered file copy
|
||||
function copyFile(srcFile, destFile, force) {
|
||||
return __awaiter$i(this, void 0, void 0, function* () {
|
||||
if ((yield lstat(srcFile)).isSymbolicLink()) {
|
||||
// unlink/re-link it
|
||||
try {
|
||||
yield lstat(destFile);
|
||||
yield unlink(destFile);
|
||||
}
|
||||
catch (e) {
|
||||
// Try to override file permission
|
||||
if (e.code === 'EPERM') {
|
||||
yield chmod(destFile, '0666');
|
||||
yield unlink(destFile);
|
||||
}
|
||||
// other errors = it doesn't exist, no work to do
|
||||
}
|
||||
// Copy over symlink
|
||||
const symlinkFull = yield readlink(srcFile);
|
||||
yield symlink(symlinkFull, destFile, IS_WINDOWS$d ? 'junction' : null);
|
||||
}
|
||||
else if (!(yield exists(destFile)) || force) {
|
||||
yield copyFile$1(srcFile, destFile);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var __awaiter$h = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
|
|
@ -89957,20 +89836,26 @@ async function setupMise(version, fetchFromGitHub = false) {
|
|||
}
|
||||
case '.tar.zst': {
|
||||
const archivePath = await downloadTool(url);
|
||||
const extractDir = await extractTar(archivePath, undefined, [
|
||||
// Extract straight into miseDir(): the tarball is laid out
|
||||
// as `mise/{bin,man,share,...}`, so stripping the leading
|
||||
// `mise/` component drops the binary at miseBinPath and the
|
||||
// rest in their native mise data-dir locations. This avoids
|
||||
// a temp dir and a cross-device copy (rename fails EXDEV when
|
||||
// the temp dir and miseDir() are on different mounts).
|
||||
await extractTar(archivePath, miseDir(), [
|
||||
'--zstd',
|
||||
'-x'
|
||||
'-x',
|
||||
'--strip-components=1'
|
||||
]);
|
||||
// Use cp, not mv: the extraction temp dir and the mise
|
||||
// bin dir can live on different mounts (e.g. inside Alpine
|
||||
// containers), and rename across devices fails with EXDEV.
|
||||
await cp(path$1.join(extractDir, 'mise', 'bin', 'mise'), miseBinPath);
|
||||
break;
|
||||
}
|
||||
case '.tar.gz': {
|
||||
const archivePath = await downloadTool(url);
|
||||
const extractDir = await extractTar(archivePath);
|
||||
await cp(path$1.join(extractDir, 'mise', 'bin', 'mise'), miseBinPath);
|
||||
await extractTar(archivePath, miseDir(), [
|
||||
'-x',
|
||||
'-z',
|
||||
'--strip-components=1'
|
||||
]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
22
src/index.ts
22
src/index.ts
|
|
@ -345,20 +345,26 @@ async function setupMise(
|
|||
}
|
||||
case '.tar.zst': {
|
||||
const archivePath = await tc.downloadTool(url)
|
||||
const extractDir = await tc.extractTar(archivePath, undefined, [
|
||||
// Extract straight into miseDir(): the tarball is laid out
|
||||
// as `mise/{bin,man,share,...}`, so stripping the leading
|
||||
// `mise/` component drops the binary at miseBinPath and the
|
||||
// rest in their native mise data-dir locations. This avoids
|
||||
// a temp dir and a cross-device copy (rename fails EXDEV when
|
||||
// the temp dir and miseDir() are on different mounts).
|
||||
await tc.extractTar(archivePath, miseDir(), [
|
||||
'--zstd',
|
||||
'-x'
|
||||
'-x',
|
||||
'--strip-components=1'
|
||||
])
|
||||
// Use cp, not mv: the extraction temp dir and the mise
|
||||
// bin dir can live on different mounts (e.g. inside Alpine
|
||||
// containers), and rename across devices fails with EXDEV.
|
||||
await io.cp(path.join(extractDir, 'mise', 'bin', 'mise'), miseBinPath)
|
||||
break
|
||||
}
|
||||
case '.tar.gz': {
|
||||
const archivePath = await tc.downloadTool(url)
|
||||
const extractDir = await tc.extractTar(archivePath)
|
||||
await io.cp(path.join(extractDir, 'mise', 'bin', 'mise'), miseBinPath)
|
||||
await tc.extractTar(archivePath, miseDir(), [
|
||||
'-x',
|
||||
'-z',
|
||||
'--strip-components=1'
|
||||
])
|
||||
break
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue