Skip to content

Commit

Permalink
Add example documentation for the output handler
Browse files Browse the repository at this point in the history
  • Loading branch information
steveukx committed Apr 9, 2023
1 parent a3a94e7 commit 4f7d401
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
49 changes: 49 additions & 0 deletions examples/git-output-handler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
## Output Handler

As `simple-git` receives data on either `stdout` or `stderr` streams from the `git`
child processes it spawns, the data is buffered for parsing when the process has
completed.

Add an `outputHandler` to the instance to pipe these streams to another target, for
example piping to the main process `stdout` / `stderr`:

```typescript
import { InitResult, SimpleGit, simpleGit } from "simple-git";

const git: SimpleGit = simpleGit()
.outputHandler((_command, stdout, stderr) => {
stdout.pipe(process.stdout);
stderr.pipe(process.stderr);
});

const init: InitResult = await git.init();
```

Note: there is a single `outputHandler` per `simple-git` instance, calling the method again
will overwrite the existing `outputHandler`.

Other uses for the `outputHandler` can include tracking the processes for metrics purposes,
such as checking how many commands are currently being executed:

```typescript
let processes = new Set();
const currentlyRunning = () => processes.size;
const git = context.git.outputHandler((_command, stdout, stderr) => {
const start = new Date();
const onClose = () => processes.delete(start);

stdout.on('close', onClose);
stderr.on('close', onClose);

processes.add(start);
});

expect(currentlyRunning()).toBe(0);
const queue = [git.init(), git.add('*.txt')];

await wait(0);
expect(currentlyRunning()).toBe(2);

await Promise.all(queue);
expect(currentlyRunning()).toBe(0);
```
4 changes: 2 additions & 2 deletions simple-git/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ For type details of the response for each of the tasks, please see the [TypeScri
# API

| API | What it does |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ---------------------------------------------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `.add([fileA, ...], handlerFn)` | adds one or more files to be under source control |
| `.addAnnotatedTag(tagName, tagMessage, handlerFn)` | adds an annotated tag to the head of the current branch |
| `.addTag(name, handlerFn)` | adds a lightweight tag to the head of the current branch |
Expand All @@ -201,7 +201,7 @@ For type details of the response for each of the tasks, please see the [TypeScri
| `.fetch([options, ] handlerFn)` | update the local working copy database with changes from the default remote repo and branch, when supplied the options argument can be a standard [options object](#how-to-specify-options) either an array of string commands as supported by the [git fetch](https://git-scm.com/docs/git-fetch). |
| `.fetch(remote, branch, handlerFn)` | update the local working copy database with changes from a remote repo |
| `.fetch(handlerFn)` | update the local working copy database with changes from the default remote repo and branch |
| `.outputHandler(handlerFn)` | attaches a handler that will be called with the name of the command being run and the `stdout` and `stderr` [readable streams](https://nodejs.org/api/stream.html#stream_class_stream_readable) created by the [child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess) running that command |
| `.outputHandler(handlerFn)` | attaches a handler that will be called with the name of the command being run and the `stdout` and `stderr` [readable streams](https://nodejs.org/api/stream.html#stream_class_stream_readable) created by the [child process](https://nodejs.org/api/child_process.html#child_process_class_childprocess) running that command, see [examples](https://github.com/steveukx/git-js/blob/main/examples/git-output-handler.md) |
| `.raw(args, [handlerFn])` | Execute any arbitrary array of commands supported by the underlying git binary. When the git process returns a non-zero signal on exit and it printed something to `stderr`, the command will be treated as an error, otherwise treated as a success. |
| `.rebase([options,] handlerFn)` | Rebases the repo, `options` should be supplied as an array of string parameters supported by the [git rebase](https://git-scm.com/docs/git-rebase) command, or an object of options (see details below for option formats). |
| `.revert(commit , [options , [handlerFn]])` | reverts one or more commits in the working copy. The commit can be any regular commit-ish value (hash, name or offset such as `HEAD~2`) or a range of commits (eg: `master~5..master~2`). When supplied the [options](#how-to-specify-options) argument contain any options accepted by [git-revert](https://git-scm.com/docs/git-revert). |
Expand Down
34 changes: 34 additions & 0 deletions simple-git/test/integration/output-handler.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createTestContext, setUpInit, SimpleGitTestContext, wait } from '@simple-git/test-utils';

describe('outputHandler', function () {
let context: SimpleGitTestContext;

beforeEach(async () => (context = await createTestContext()));
beforeEach(async () => {
await setUpInit(context);
await context.files('aaa.txt', 'bbb.txt', 'ccc.other');
});

it('using the outputHandler to count currently running processes', async () => {
let processes = new Set();
const currentlyRunning = () => processes.size;
const git = context.git.outputHandler((_x, stdout, stderr) => {
const start = new Date();
const onClose = () => processes.delete(start);

stdout.on('close', onClose);
stderr.on('close', onClose);

processes.add(start);
});

expect(currentlyRunning()).toBe(0);
const queue = [git.init(), git.add('*.txt')];

await wait(0);
expect(currentlyRunning()).toBe(2);

await Promise.all(queue);
expect(currentlyRunning()).toBe(0);
});
});

0 comments on commit 4f7d401

Please sign in to comment.