[6a3a178] | 1 | # @npmcli/git
|
---|
| 2 |
|
---|
| 3 | A utility for spawning git from npm CLI contexts.
|
---|
| 4 |
|
---|
| 5 | This is _not_ an implementation of git itself, it's just a thing that
|
---|
| 6 | spawns child processes to tell the system git CLI implementation to do
|
---|
| 7 | stuff.
|
---|
| 8 |
|
---|
| 9 | ## USAGE
|
---|
| 10 |
|
---|
| 11 | ```js
|
---|
| 12 | const git = require('@npmcli/git')
|
---|
| 13 | git.clone('git://foo/bar.git', 'some-branch', 'some-path', opts) // clone a repo
|
---|
| 14 | .then(() => git.spawn(['checkout', 'some-branch'], {cwd: 'bar'}))
|
---|
| 15 | .then(() => git.spawn(['you get the idea']))
|
---|
| 16 | ```
|
---|
| 17 |
|
---|
| 18 | ## API
|
---|
| 19 |
|
---|
| 20 | Most methods take an options object. Options are described below.
|
---|
| 21 |
|
---|
| 22 | ### `git.spawn(args, opts = {})`
|
---|
| 23 |
|
---|
| 24 | Launch a `git` subprocess with the arguments specified.
|
---|
| 25 |
|
---|
| 26 | All the other functions call this one at some point.
|
---|
| 27 |
|
---|
| 28 | Processes are launched using
|
---|
| 29 | [`@npmcli/promise-spawn`](http://npm.im/@npmcli/promise-spawn), with the
|
---|
| 30 | `stdioString: true` option enabled by default, since git output is
|
---|
| 31 | generally in readable string format.
|
---|
| 32 |
|
---|
| 33 | Return value is a `Promise` that resolves to a result object with `{cmd,
|
---|
| 34 | args, code, signal, stdout, stderr}` members, or rejects with an error with
|
---|
| 35 | the same fields, passed back from
|
---|
| 36 | [`@npmcli/promise-spawn`](http://npm.im/@npmcli/promise-spawn).
|
---|
| 37 |
|
---|
| 38 | ### `git.clone(repo, ref = 'HEAD', target = null, opts = {})` -> `Promise<sha String>`
|
---|
| 39 |
|
---|
| 40 | Clone the repository into `target` path (or the default path for the name
|
---|
| 41 | of the repository), checking out `ref`.
|
---|
| 42 |
|
---|
| 43 | Return value is the sha of the current HEAD in the locally cloned
|
---|
| 44 | repository.
|
---|
| 45 |
|
---|
| 46 | In lieu of a specific `ref`, you may also pass in a `spec` option, which is
|
---|
| 47 | a [`npm-package-arg`](http://npm.im/npm-package-arg) object for a `git`
|
---|
| 48 | package dependency reference. In this way, you can select SemVer tags
|
---|
| 49 | within a range, or any git committish value. For example:
|
---|
| 50 |
|
---|
| 51 | ```js
|
---|
| 52 | const npa = require('npm-package-arg')
|
---|
| 53 | git.clone('git@github.com:npm/git.git', '', null, {
|
---|
| 54 | spec: npa('github:npm/git#semver:1.x'),
|
---|
| 55 | })
|
---|
| 56 |
|
---|
| 57 | // only gitRange and gitCommittish are relevant, so this works, too
|
---|
| 58 | git.clone('git@github.com:npm/git.git', null, null, {
|
---|
| 59 | spec: { gitRange: '1.x' }
|
---|
| 60 | })
|
---|
| 61 | ```
|
---|
| 62 |
|
---|
| 63 | This will automatically do a shallow `--depth=1` clone on any hosts that
|
---|
| 64 | are known to support it. To force a shallow or deep clone, you can set the
|
---|
| 65 | `gitShallow` option to `true` or `false` respectively.
|
---|
| 66 |
|
---|
| 67 | ### `git.revs(repo, opts = {})` -> `Promise<rev doc Object>`
|
---|
| 68 |
|
---|
| 69 | Fetch a representation of all of the named references in a given
|
---|
| 70 | repository. The resulting doc is intentionally somewhat
|
---|
| 71 | [packument](https://www.npmjs.com/package/pacote#packuments)-like, so that
|
---|
| 72 | git semver ranges can be applied using the same
|
---|
| 73 | [`npm-pick-manifest`](http://npm.im/npm-pick-manifest) logic.
|
---|
| 74 |
|
---|
| 75 | The resulting object looks like:
|
---|
| 76 |
|
---|
| 77 | ```js
|
---|
| 78 | revs = {
|
---|
| 79 | versions: {
|
---|
| 80 | // all semver-looking tags go in here...
|
---|
| 81 | // version: { sha, ref, rawRef, type }
|
---|
| 82 | '1.0.0': {
|
---|
| 83 | sha: '1bc5fba3353f8e1b56493b266bc459276ab23139',
|
---|
| 84 | ref: 'v1.0.0',
|
---|
| 85 | rawRef: 'refs/tags/v1.0.0',
|
---|
| 86 | type: 'tag',
|
---|
| 87 | },
|
---|
| 88 | },
|
---|
| 89 | 'dist-tags': {
|
---|
| 90 | HEAD: '1.0.0',
|
---|
| 91 | latest: '1.0.0',
|
---|
| 92 | },
|
---|
| 93 | refs: {
|
---|
| 94 | // all the advertised refs that can be cloned down remotely
|
---|
| 95 | HEAD: { sha, ref, rawRef, type: 'head' },
|
---|
| 96 | master: { ... },
|
---|
| 97 | 'v1.0.0': { ... },
|
---|
| 98 | 'refs/tags/v1.0.0': { ... },
|
---|
| 99 | },
|
---|
| 100 | shas: {
|
---|
| 101 | // all named shas referenced above
|
---|
| 102 | // sha: [list, of, refs]
|
---|
| 103 | '6b2501f9183a1753027a9bf89a184b7d3d4602c7': [
|
---|
| 104 | 'HEAD',
|
---|
| 105 | 'master',
|
---|
| 106 | 'refs/heads/master',
|
---|
| 107 | ],
|
---|
| 108 | '1bc5fba3353f8e1b56493b266bc459276ab23139': [ 'v1.0.0', 'refs/tags/v1.0.0' ],
|
---|
| 109 | },
|
---|
| 110 | }
|
---|
| 111 | ```
|
---|
| 112 |
|
---|
| 113 | ### `git.is(opts)` -> `Promise<Boolean>`
|
---|
| 114 |
|
---|
| 115 | Resolve to `true` if the path argument refers to the root of a git
|
---|
| 116 | repository.
|
---|
| 117 |
|
---|
| 118 | It does this by looking for a file in `${path}/.git/index`, which is not an
|
---|
| 119 | airtight indicator, but at least avoids being fooled by an empty directory
|
---|
| 120 | or a file named `.git`.
|
---|
| 121 |
|
---|
| 122 | ### `git.find(opts)` -> `Promise<String | null>`
|
---|
| 123 |
|
---|
| 124 | Given a path, walk up the file system tree until a git repo working
|
---|
| 125 | directory is found. Since this calls `stat` a bunch of times, it's
|
---|
| 126 | probably best to only call it if you're reasonably sure you're likely to be
|
---|
| 127 | in a git project somewhere.
|
---|
| 128 |
|
---|
| 129 | Resolves to `null` if not in a git project.
|
---|
| 130 |
|
---|
| 131 | ### `git.isClean(opts = {})` -> `Promise<Boolean>`
|
---|
| 132 |
|
---|
| 133 | Return true if in a git dir, and that git dir is free of changes. This
|
---|
| 134 | will resolve `true` if the git working dir is clean, or `false` if not, and
|
---|
| 135 | reject if the path is not within a git directory or some other error
|
---|
| 136 | occurs.
|
---|
| 137 |
|
---|
| 138 | ## OPTIONS
|
---|
| 139 |
|
---|
| 140 | - `retry` An object to configure retry behavior for transient network
|
---|
| 141 | errors with exponential backoff.
|
---|
| 142 | - `retries`: Defaults to `opts.fetchRetries` or 2
|
---|
| 143 | - `factor`: Defaults to `opts.fetchRetryFactor` or 10
|
---|
| 144 | - `maxTimeout`: Defaults to `opts.fetchRetryMaxtimeout` or 60000
|
---|
| 145 | - `minTimeout`: Defaults to `opts.fetchRetryMintimeout` or 1000
|
---|
| 146 | - `git` Path to the `git` binary to use. Will look up the first `git` in
|
---|
| 147 | the `PATH` if not specified.
|
---|
| 148 | - `spec` The [`npm-package-arg`](http://npm.im/npm-package-arg) specifier
|
---|
| 149 | object for the thing being fetched (if relevant).
|
---|
| 150 | - `fakePlatform` set to a fake value of `process.platform` to use. (Just
|
---|
| 151 | for testing `win32` behavior on Unix, and vice versa.)
|
---|
| 152 | - `cwd` The current working dir for the git command. Particularly for
|
---|
| 153 | `find` and `is` and `isClean`, it's good to know that this defaults to
|
---|
| 154 | `process.cwd()`, as one might expect.
|
---|
| 155 | - Any other options that can be passed to
|
---|
| 156 | [`@npmcli/promise-spawn`](http://npm.im/@npmcli/promise-spawn), or
|
---|
| 157 | `child_process.spawn()`.
|
---|