13
0
Fork 0
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:
Carlos Precioso 2026-06-17 16:03:58 +02:00
parent e5654ed8b5
commit 2c202d47b9
3 changed files with 30 additions and 139 deletions

145
dist/index.js generated vendored
View file

@ -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

File diff suppressed because one or more lines are too long

View file

@ -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: