diff --git a/README.md b/README.md index ad492d7..d494ceb 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,8 @@ When passing options objects, the following special keys are supported: - `$nullOnError`: Return null instead of throwing on error - `$onStdout`: Callback for stdout in spawn mode - `$onStderr`: Callback for stderr in spawn mode +- `$env`: Object of environment variables to set on the spawned process +- `$config`: Object of `key=value` config overrides injected as `-c` flags before the subcommand (e.g. `{ $config: { 'gc.auto': '0' } }`) ### Common Methods diff --git a/index.d.ts b/index.d.ts index 863f1c5..2572b25 100644 --- a/index.d.ts +++ b/index.d.ts @@ -33,6 +33,8 @@ declare module 'git-client' { $cwd?: string; /** Custom environment variables */ $env?: Record; + /** Inject `-c key=value` config overrides before the subcommand */ + $config?: Record; /** Additional options */ $options?: Record; /** Any git command options */ diff --git a/lib/Git.js b/lib/Git.js index 78c0d14..a873c9e 100644 --- a/lib/Git.js +++ b/lib/Git.js @@ -714,6 +714,11 @@ class Git { delete arg.$env; } + if ('$config' in arg) { + execOptions.config = Object.assign(execOptions.config || {}, arg.$config); + delete arg.$config; + } + if ('$preserveEnv' in arg) { execOptions.preserveEnv = arg.$preserveEnv; delete arg.$preserveEnv; @@ -765,6 +770,16 @@ class Git { gitOptions['work-tree'] = execOptions.workTree; } + if (execOptions.config) { + const configArgs = []; + for (const key in execOptions.config) { + configArgs.push(`${key}=${execOptions.config[key]}`); + } + if (configArgs.length) { + gitOptions['c'] = configArgs; + } + } + commandArgs.unshift.apply(commandArgs, Git.cliOptionsToArgs(gitOptions)); diff --git a/package-lock.json b/package-lock.json index a9cbf2a..1863c04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2160,9 +2160,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, "license": "MIT" }, @@ -2270,9 +2270,9 @@ } }, "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -2618,9 +2618,9 @@ } }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { diff --git a/test/git.js b/test/git.js index 1149240..9b18b11 100644 --- a/test/git.js +++ b/test/git.js @@ -69,6 +69,33 @@ test('other git executes with correct git dir with override', async t => { t.is(await fs.realpath(gitDir), repo1Dir); }); +test('$config injects -c = before subcommand', async t => { + // Read back a config value that only exists via $config injection + const value = await git.config( + { $config: { 'holo.injected': 'yes' } }, + '--get', + 'holo.injected', + ); + + t.is(value, 'yes'); +}); + +test('$config supports multiple entries', async t => { + const first = await git.config( + { $config: { 'holo.first': '1', 'holo.second': '2' } }, + '--get', + 'holo.first', + ); + const second = await git.config( + { $config: { 'holo.first': '1', 'holo.second': '2' } }, + '--get', + 'holo.second', + ); + + t.is(first, '1'); + t.is(second, '2'); +}); + test('checkout git repo to temporary directory', async t => { const [tmpWorkTree, tmpIndexFilePath] = await Promise.all([tmp.dir(), tmp.tmpName()]);