diff --git a/package.json b/package.json index c4482ef..8ef5adf 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,10 @@ "bin": "dist/index.js", "packageManager": "pnpm@9.12.1", "scripts": { - "build": "pkgroll --minify --export-condition=node --target=node12.19", + "build": "pkgroll --minify --target=node12.19", "lint": "lintroll --cache .", "type-check": "tsc --noEmit", - "test": "tsx -C import tests", + "test": "tsx tests", "prepack": "pnpm build && clean-pkg-json" }, "dependencies": { @@ -40,7 +40,6 @@ "byte-size": "^9.0.0", "clean-pkg-json": "^1.2.0", "cleye": "^1.3.2", - "execa": "^9.5.1", "fs-fixture": "^2.6.0", "kolorist": "^1.8.0", "lintroll": "^1.10.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cc15e05..a040f64 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,9 +33,6 @@ importers: cleye: specifier: ^1.3.2 version: 1.3.2 - execa: - specifier: ^9.5.1 - version: 9.5.1 fs-fixture: specifier: ^2.6.0 version: 2.6.0 diff --git a/src/index.ts b/src/index.ts index e5a917b..cf09319 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ import fs from 'node:fs/promises'; -import { execa } from 'execa'; +import spawn, { type SubprocessError } from 'nano-spawn'; import task from 'tasuku'; import { cli } from 'cleye'; import type { PackageJson } from '@npmcli/package-json'; @@ -87,7 +87,7 @@ const { stringify } = JSON; // Validate remote exists let remoteUrl; try { - const getRemoteUrl = await execa('git', ['remote', 'get-url', remote]); + const getRemoteUrl = await spawn('git', ['remote', 'get-url', remote]); remoteUrl = getRemoteUrl.stdout.trim(); } catch { throw new Error(`Git remote ${stringify(remote)} does not exist`); @@ -105,22 +105,20 @@ const { stringify } = JSON; } if (fresh) { - await execa('git', ['checkout', '--orphan', localTemporaryBranch]); + await spawn('git', ['checkout', '--orphan', localTemporaryBranch]); } else { - const gitFetch = await execa('git', ['fetch', '--depth=1', remote, `${publishBranch}:${localTemporaryBranch}`], { - reject: false, - }); + const gitFetch = await spawn('git', ['fetch', '--depth=1', remote, `${publishBranch}:${localTemporaryBranch}`]).catch(error => error as SubprocessError); - await execa('git', [ + await spawn('git', [ 'checkout', - ...(gitFetch.failed ? ['-b'] : []), + ...('exitCode' in gitFetch ? ['-b'] : []), localTemporaryBranch, ]); } // Checkout the files tree from the previous branch // This also applies any file deletions from the source branch - await execa('git', ['restore', '--source', currentBranch, ':/']); + await spawn('git', ['restore', '--source', currentBranch, ':/']); }); if (!dry) { @@ -134,10 +132,10 @@ const { stringify } = JSON; } setTitle('Running hook "prepare"'); - await execa('npm', ['run', '--if-present', 'prepare']); + await spawn('npm', ['run', '--if-present', 'prepare']); setTitle('Running hook "prepack"'); - await execa('npm', ['run', '--if-present', 'prepack']); + await spawn('npm', ['run', '--if-present', 'prepack']); }); if (!dry) { @@ -232,19 +230,19 @@ const { stringify } = JSON; // Remove all files from Git tree // This removes all files from the branch so only the publish files will be added - await execa('git', ['rm', '--cached', '-r', ':/'], { + await spawn('git', ['rm', '--cached', '-r', ':/']).catch( // Can fail if tree is empty: fatal: pathspec ':/' did not match any files - reject: false, - }); + () => {}, + ); - await execa('git', ['add', '-f', ...publishFiles]); + await spawn('git', ['add', '-f', ...publishFiles]); const { stdout: trackedFiles } = await gitStatusTracked(); if (trackedFiles.length === 0) { console.warn('⚠️ No new changes found to commit.'); } else { // -a is passed in so it can stage deletions from `git restore` - await execa('git', ['commit', '--no-verify', '-am', `Published branch ${stringify(currentBranch)}`]); + await spawn('git', ['commit', '--no-verify', '-am', `Published branch ${stringify(currentBranch)}`]); } commitSha = await getCurrentCommit(); @@ -262,7 +260,7 @@ const { stringify } = JSON; return; } - await execa('git', [ + await spawn('git', [ 'push', ...(fresh ? ['--force'] : []), '--no-verify', @@ -284,15 +282,15 @@ const { stringify } = JSON; } // In case commit failed and there are uncommitted changes - await execa('git', ['reset', '--hard']); + await spawn('git', ['reset', '--hard']); - await execa('git', ['checkout', '-f', currentBranch]); + await spawn('git', ['checkout', '-f', currentBranch]); // Delete local branch - await execa('git', ['branch', '-D', localTemporaryBranch], { + await spawn('git', ['branch', '-D', localTemporaryBranch]).catch( // Ignore failures (e.g. in case it didin't even succeed to create this branch) - reject: false, - }); + () => {}, + ); }); revertBranch.clear(); diff --git a/src/utils/git.ts b/src/utils/git.ts index 64c7b24..8e2c00a 100644 --- a/src/utils/git.ts +++ b/src/utils/git.ts @@ -1,6 +1,6 @@ -import { execa } from 'execa'; +import spawn, { type SubprocessError } from 'nano-spawn'; -export const gitStatusTracked = () => execa('git', ['status', '--porcelain', '--untracked-files=no']); +export const gitStatusTracked = () => spawn('git', ['status', '--porcelain', '--untracked-files=no']); export const assertCleanTree = async () => { const { stdout } = await gitStatusTracked().catch((error) => { @@ -21,21 +21,19 @@ export const getCurrentBranchOrTagName = async () => { * This commands supports older versions of Git, but since v2.22, you can do: * git branch --show-current */ - const getBranch = await execa( + const getBranch = await spawn( 'git', ['symbolic-ref', '--short', '-q', 'HEAD'], - { reject: false }, - ); + ).catch(error => error as SubprocessError); if (getBranch.stdout) { return getBranch.stdout; } - const getTag = await execa( + const getTag = await spawn( 'git', ['describe', '--tags'], - { reject: false }, - ); + ).catch(error => error as SubprocessError); if (getTag.stdout) { return getTag.stdout; @@ -45,6 +43,6 @@ export const getCurrentBranchOrTagName = async () => { }; export const getCurrentCommit = async () => { - const getCommit = await execa('git', ['rev-parse', '--short', 'HEAD']); + const getCommit = await spawn('git', ['rev-parse', '--short', 'HEAD']); return getCommit.stdout.trim(); };