Skip to content

Commit

Permalink
add spawnOptions plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
dluxemburg committed Jun 10, 2021
1 parent 8603971 commit b952ced
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 3 deletions.
10 changes: 10 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ const git: SimpleGit = simpleGit('/some/path', { config: ['http.proxy=someproxy'
await git.pull();
```

To set the user identity or group identity of the spawned git commands to something other than the owner of
the current Node process, supply a `spawnOptions` option with a `uid`, a `gid`, or both:

```typescript
const git: SimpleGit = simpleGit('/some/path', { spawnOptions: { uid: 1000 } });

// any command executed will belong to system user 1000
await git.pull();
```

## Configuring Plugins

- [Error Detection](./docs/PLUGIN-ERRORS.md)
Expand Down
2 changes: 2 additions & 0 deletions src/lib/git-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
errorDetectionPlugin,
PluginStore,
progressMonitorPlugin,
spawnOptionsPlugin,
timeoutPlugin
} from './plugins';
import { createInstanceConfig, folderExists } from './utils';
Expand Down Expand Up @@ -53,6 +54,7 @@ export function gitInstanceFactory(baseDir?: string | Partial<SimpleGitOptions>,

config.progress && plugins.add(progressMonitorPlugin(config.progress));
config.timeout && plugins.add(timeoutPlugin(config.timeout));
config.spawnOptions && plugins.add(spawnOptionsPlugin(config.spawnOptions));

plugins.add(errorDetectionPlugin(errorDetectionHandler(true)));
config.errors && plugins.add(errorDetectionPlugin(config.errors));
Expand Down
1 change: 1 addition & 0 deletions src/lib/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export * from './error-detection.plugin';
export * from './plugin-store';
export * from './progress-monitor-plugin';
export * from './simple-git-plugin';
export * from './spawn-options-plugin';
export * from './timout-plugin';
6 changes: 5 additions & 1 deletion src/lib/plugins/simple-git-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChildProcess } from 'child_process';
import { ChildProcess, SpawnOptions } from 'child_process';
import { GitExecutorResult } from '../types';

type SimpleGitTaskPluginContext = {
Expand All @@ -11,6 +11,10 @@ export interface SimpleGitPluginTypes {
data: string[];
context: SimpleGitTaskPluginContext & {};
};
'spawn.options': {
data: Partial<SpawnOptions>;
context: SimpleGitTaskPluginContext & {};
};
'spawn.after': {
data: void;
context: SimpleGitTaskPluginContext & {
Expand Down
14 changes: 14 additions & 0 deletions src/lib/plugins/spawn-options-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { SpawnOptions } from 'child_process';
import { pick } from '../utils';
import { SimpleGitPlugin } from './simple-git-plugin';

export function spawnOptionsPlugin(spawnOptions: Partial<SpawnOptions>): SimpleGitPlugin<'spawn.options'> {
const options = pick(spawnOptions, ['uid', 'gid']);

return {
type: 'spawn.options',
action(data) {
return {...options, ...data};
},
};
}
4 changes: 2 additions & 2 deletions src/lib/runners/git-executor-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ export class GitExecutorChain implements SimpleGitExecutor {

private async gitResponse<R>(task: SimpleGitTask<R>, command: string, args: string[], outputHandler: Maybe<outputHandler>, logger: OutputLogger): Promise<GitExecutorResult> {
const outputLogger = logger.sibling('output');
const spawnOptions: SpawnOptions = {
const spawnOptions: SpawnOptions = this._plugins.exec('spawn.options', {
cwd: this.cwd,
env: this.env,
windowsHide: true,
};
}, pluginContext(task, task.commands));

return new Promise((done) => {
const stdOut: Buffer[] = [];
Expand Down
4 changes: 4 additions & 0 deletions src/lib/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { SpawnOptions } from 'child_process';

import { SimpleGitTask } from './tasks';
import { SimpleGitProgressEvent } from './handlers';

Expand Down Expand Up @@ -85,6 +87,8 @@ export interface SimpleGitPluginConfig {
*/
block: number;
};

spawnOptions: Pick<SpawnOptions, 'uid' | 'gid'>;
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/lib/utils/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,10 @@ export function prefixedArray<T>(input: T[], prefix: T): T[] {
export function bufferToString (input: Buffer | Buffer[]): string {
return (Array.isArray(input) ? Buffer.concat(input) : input).toString('utf-8');
}

/**
* Get a new object from a source object with only the listed properties.
*/
export function pick (source: Record<string, any>, properties: string[]) {
return Object.assign({}, ...properties.map((property) => property in source ? {[property]: source[property]} : {}));
}
4 changes: 4 additions & 0 deletions test/unit/__fixtures__/expectations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ export function assertChildProcessEnvironmentVariables(env: any) {
expect(mockChildProcessModule.$mostRecent()).toHaveProperty('$env', env);
}

export function assertChildProcessSpawnOptions(options: any) {
expect(mockChildProcessModule.$mostRecent().$options).toMatchObject(options);
}

9 changes: 9 additions & 0 deletions test/unit/plugins.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SimpleGit } from '../../typings';
import {
assertChildProcessSpawnOptions,
assertExecutedCommands,
assertExecutedCommandsContainsOnce,
closeWithSuccess,
Expand All @@ -24,6 +25,14 @@ describe('plugins', () => {
assertExecutedCommands('-c', 'a', '-c', 'bcd', 'foo');
});

it('allows setting uid and gid', async () => {
git = newSimpleGit({spawnOptions: {uid: 1, gid: 2}});
git.init();

await closeWithSuccess();
assertChildProcessSpawnOptions({uid: 1, gid: 2});
});

describe('progress', () => {

it('emits progress events when counting objects', async () => {
Expand Down

0 comments on commit b952ced

Please sign in to comment.