Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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