isomorphic-git 1.12.1 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -139,7 +139,7 @@ unless there is a major version bump.
139
139
  <!-- prettier-ignore-start -->
140
140
  <!-- markdownlint-disable -->
141
141
 
142
- <!-- autogenerated_by: __tests__/__helpers__/generate-docs.js -->
142
+ <!-- autogenerated_by: __tests__/__helpers__/generate-docs.cjs -->
143
143
 
144
144
  - [add](https://isomorphic-git.github.io/docs/add.html)
145
145
  - [addNote](https://isomorphic-git.github.io/docs/addNote.html)
@@ -340,6 +340,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
340
340
  <td align="center"><a href="https://github.com/mtlewis"><img src="https://avatars.githubusercontent.com/u/542836?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Mike Lewis</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=mtlewis" title="Documentation">📖</a></td>
341
341
  <td align="center"><a href="https://twitter.com/SamVerschueren"><img src="https://avatars.githubusercontent.com/u/1913805?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Sam Verschueren</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=SamVerschueren" title="Code">💻</a></td>
342
342
  <td align="center"><a href="http://vitorluizc.github.io/"><img src="https://avatars.githubusercontent.com/u/9027363?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Vitor Luiz Cavalcanti</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=VitorLuizC" title="Documentation">📖</a></td>
343
+ <td align="center"><a href="https://www.platformdemos.com/"><img src="https://avatars.githubusercontent.com/u/4261788?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Shane McLaughlin</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=mshanemc" title="Code">💻</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=mshanemc" title="Documentation">📖</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=mshanemc" title="Tests">⚠️</a></td>
343
344
  </tr>
344
345
  </table>
345
346
 
package/index.cjs CHANGED
@@ -871,7 +871,7 @@ class GitIndexManager {
871
871
  const filepath = `${gitdir}/index`;
872
872
  if (lock === null) lock = new AsyncLock({ maxPending: Infinity });
873
873
  let result;
874
- await lock.acquire(filepath, async function() {
874
+ await lock.acquire(filepath, async () => {
875
875
  // Acquire a file lock while we're reading the index
876
876
  // to make sure other processes aren't writing to it
877
877
  // simultaneously, which could result in a corrupted index.
@@ -891,6 +891,7 @@ class GitIndexManager {
891
891
  index._dirty = false;
892
892
  }
893
893
  });
894
+
894
895
  return result
895
896
  }
896
897
  }
@@ -4022,6 +4023,23 @@ function WORKDIR() {
4022
4023
 
4023
4024
  // @ts-check
4024
4025
 
4026
+ class MultipleGitError extends BaseError {
4027
+ /**
4028
+ * @param {Error[]} errors
4029
+ * @param {string} message
4030
+ */
4031
+ constructor(errors) {
4032
+ super(
4033
+ `There are multiple errors that were thrown by the method. Please refer to the "errors" property to see more`
4034
+ );
4035
+ this.code = this.name = MultipleGitError.code;
4036
+ this.data = { errors };
4037
+ this.errors = errors;
4038
+ }
4039
+ }
4040
+ /** @type {'MultipleGitError'} */
4041
+ MultipleGitError.code = 'MultipleGitError';
4042
+
4025
4043
  // I'm putting this in a Manager because I reckon it could benefit
4026
4044
  // from a LOT of cacheing.
4027
4045
  class GitIgnoreManager {
@@ -4412,12 +4430,6 @@ function assertParameter(name, value) {
4412
4430
  }
4413
4431
  }
4414
4432
 
4415
- function posixifyPathBuffer(buffer) {
4416
- let idx;
4417
- while (~(idx = buffer.indexOf(92))) buffer[idx] = 47;
4418
- return buffer
4419
- }
4420
-
4421
4433
  // @ts-check
4422
4434
 
4423
4435
  /**
@@ -4427,7 +4439,7 @@ function posixifyPathBuffer(buffer) {
4427
4439
  * @param {FsClient} args.fs - a file system implementation
4428
4440
  * @param {string} args.dir - The [working tree](dir-vs-gitdir.md) directory path
4429
4441
  * @param {string} [args.gitdir=join(dir, '.git')] - [required] The [git directory](dir-vs-gitdir.md) path
4430
- * @param {string} args.filepath - The path to the file to add to the index
4442
+ * @param {string|string[]} args.filepath - The path to the file to add to the index
4431
4443
  * @param {object} [args.cache] - a [cache](cache.md) object
4432
4444
  *
4433
4445
  * @returns {Promise<void>} Resolves successfully once the git index has been updated
@@ -4449,11 +4461,11 @@ async function add({
4449
4461
  assertParameter('fs', _fs);
4450
4462
  assertParameter('dir', dir);
4451
4463
  assertParameter('gitdir', gitdir);
4452
- assertParameter('filepath', filepath);
4464
+ assertParameter('filepaths', filepath);
4453
4465
 
4454
4466
  const fs = new FileSystem(_fs);
4455
- await GitIndexManager.acquire({ fs, gitdir, cache }, async function(index) {
4456
- await addToIndex({ dir, gitdir, fs, filepath, index });
4467
+ await GitIndexManager.acquire({ fs, gitdir, cache }, async index => {
4468
+ return addToIndex({ dir, gitdir, fs, filepath, index })
4457
4469
  });
4458
4470
  } catch (err) {
4459
4471
  err.caller = 'git.add';
@@ -4463,29 +4475,56 @@ async function add({
4463
4475
 
4464
4476
  async function addToIndex({ dir, gitdir, fs, filepath, index }) {
4465
4477
  // TODO: Should ignore UNLESS it's already in the index.
4466
- const ignored = await GitIgnoreManager.isIgnored({
4467
- fs,
4468
- dir,
4469
- gitdir,
4470
- filepath,
4478
+ filepath = Array.isArray(filepath) ? filepath : [filepath];
4479
+ const promises = filepath.map(async currentFilepath => {
4480
+ const ignored = await GitIgnoreManager.isIgnored({
4481
+ fs,
4482
+ dir,
4483
+ gitdir,
4484
+ filepath: currentFilepath,
4485
+ });
4486
+ if (ignored) return
4487
+ const stats = await fs.lstat(join(dir, currentFilepath));
4488
+ if (!stats) throw new NotFoundError(currentFilepath)
4489
+
4490
+ if (stats.isDirectory()) {
4491
+ const children = await fs.readdir(join(dir, currentFilepath));
4492
+ const promises = children.map(child =>
4493
+ addToIndex({
4494
+ dir,
4495
+ gitdir,
4496
+ fs,
4497
+ filepath: [join(currentFilepath, child)],
4498
+ index,
4499
+ })
4500
+ );
4501
+ await Promise.all(promises);
4502
+ } else {
4503
+ const object = stats.isSymbolicLink()
4504
+ ? await fs.readlink(join(dir, currentFilepath))
4505
+ : await fs.read(join(dir, currentFilepath));
4506
+ if (object === null) throw new NotFoundError(currentFilepath)
4507
+ const oid = await _writeObject({ fs, gitdir, type: 'blob', object });
4508
+ index.insert({ filepath: currentFilepath, stats, oid });
4509
+ }
4471
4510
  });
4472
- if (ignored) return
4473
- const stats = await fs.lstat(join(dir, filepath));
4474
- if (!stats) throw new NotFoundError(filepath)
4475
- if (stats.isDirectory()) {
4476
- const children = await fs.readdir(join(dir, filepath));
4477
- const promises = children.map(child =>
4478
- addToIndex({ dir, gitdir, fs, filepath: join(filepath, child), index })
4479
- );
4480
- await Promise.all(promises);
4481
- } else {
4482
- const object = stats.isSymbolicLink()
4483
- ? await fs.readlink(join(dir, filepath)).then(posixifyPathBuffer)
4484
- : await fs.read(join(dir, filepath));
4485
- if (object === null) throw new NotFoundError(filepath)
4486
- const oid = await _writeObject({ fs, gitdir, type: 'blob', object });
4487
- index.insert({ filepath, stats, oid });
4511
+
4512
+ const settledPromises = await Promise.allSettled(promises);
4513
+ const rejectedPromises = settledPromises
4514
+ .filter(settle => settle.status === 'rejected')
4515
+ .map(settle => settle.reason);
4516
+ if (rejectedPromises.length > 1) {
4517
+ throw new MultipleGitError(rejectedPromises)
4518
+ }
4519
+ if (rejectedPromises.length === 1) {
4520
+ throw rejectedPromises[0]
4488
4521
  }
4522
+
4523
+ const fulfilledPromises = settledPromises
4524
+ .filter(settle => settle.status === 'fulfilled' && settle.value)
4525
+ .map(settle => settle.value);
4526
+
4527
+ return fulfilledPromises
4489
4528
  }
4490
4529
 
4491
4530
  // @ts-check
@@ -5840,7 +5879,7 @@ async function analyze({
5840
5879
 
5841
5880
  // This is a kind of silly pattern but it worked so well for me in the past
5842
5881
  // and it makes intuitively demonstrating exhaustiveness so *easy*.
5843
- // This checks for the presense and/or absense of each of the 3 entries,
5882
+ // This checks for the presense and/or absence of each of the 3 entries,
5844
5883
  // converts that to a 3-bit binary representation, and then handles
5845
5884
  // every possible combination (2^3 or 8 cases) with a lookup table.
5846
5885
  const key = [!!stage, !!commit, !!workdir].map(Number).join('');
@@ -6873,8 +6912,8 @@ function filterCapabilities(server, client) {
6873
6912
 
6874
6913
  const pkg = {
6875
6914
  name: 'isomorphic-git',
6876
- version: '1.12.1',
6877
- agent: 'git/isomorphic-git@1.12.1',
6915
+ version: '1.14.0',
6916
+ agent: 'git/isomorphic-git@1.14.0',
6878
6917
  };
6879
6918
 
6880
6919
  class FIFO {
@@ -8644,6 +8683,7 @@ async function mergeBlobs({
8644
8683
  * @param {string} args.gitdir
8645
8684
  * @param {string} [args.ours]
8646
8685
  * @param {string} args.theirs
8686
+ * @param {boolean} args.fastForward
8647
8687
  * @param {boolean} args.fastForwardOnly
8648
8688
  * @param {boolean} args.dryRun
8649
8689
  * @param {boolean} args.noUpdateBranch
@@ -8670,6 +8710,7 @@ async function _merge({
8670
8710
  gitdir,
8671
8711
  ours,
8672
8712
  theirs,
8713
+ fastForward = true,
8673
8714
  fastForwardOnly = false,
8674
8715
  dryRun = false,
8675
8716
  noUpdateBranch = false,
@@ -8720,7 +8761,7 @@ async function _merge({
8720
8761
  alreadyMerged: true,
8721
8762
  }
8722
8763
  }
8723
- if (baseOid === ourOid) {
8764
+ if (fastForward && baseOid === ourOid) {
8724
8765
  if (!dryRun && !noUpdateBranch) {
8725
8766
  await GitRefManager.writeRef({ fs, gitdir, ref: ours, value: theirOid });
8726
8767
  }
@@ -8794,6 +8835,7 @@ async function _merge({
8794
8835
  * @param {string} [args.remoteRef]
8795
8836
  * @param {string} [args.corsProxy]
8796
8837
  * @param {boolean} args.singleBranch
8838
+ * @param {boolean} args.fastForward
8797
8839
  * @param {boolean} args.fastForwardOnly
8798
8840
  * @param {Object<string, string>} [args.headers]
8799
8841
  * @param {Object} args.author
@@ -8826,6 +8868,7 @@ async function _pull({
8826
8868
  url,
8827
8869
  remote,
8828
8870
  remoteRef,
8871
+ fastForward,
8829
8872
  fastForwardOnly,
8830
8873
  corsProxy,
8831
8874
  singleBranch,
@@ -8870,6 +8913,7 @@ async function _pull({
8870
8913
  gitdir,
8871
8914
  ours: ref,
8872
8915
  theirs: fetchHead,
8916
+ fastForward,
8873
8917
  fastForwardOnly,
8874
8918
  message: `Merge ${fetchHeadDescription}`,
8875
8919
  author,
@@ -10849,6 +10893,7 @@ async function log({
10849
10893
  * @param {string} [args.gitdir=join(dir,'.git')] - [required] The [git directory](dir-vs-gitdir.md) path
10850
10894
  * @param {string} [args.ours] - The branch receiving the merge. If undefined, defaults to the current branch.
10851
10895
  * @param {string} args.theirs - The branch to be merged
10896
+ * @param {boolean} [args.fastForward = true] - If false, create a merge commit in all cases.
10852
10897
  * @param {boolean} [args.fastForwardOnly = false] - If true, then non-fast-forward merges will throw an Error instead of performing a merge.
10853
10898
  * @param {boolean} [args.dryRun = false] - If true, simulates a merge so you can test whether it would succeed.
10854
10899
  * @param {boolean} [args.noUpdateBranch = false] - If true, does not update the branch pointer after creating the commit.
@@ -10886,6 +10931,7 @@ async function merge({
10886
10931
  gitdir = join(dir, '.git'),
10887
10932
  ours,
10888
10933
  theirs,
10934
+ fastForward = true,
10889
10935
  fastForwardOnly = false,
10890
10936
  dryRun = false,
10891
10937
  noUpdateBranch = false,
@@ -10903,7 +10949,9 @@ async function merge({
10903
10949
  const fs = new FileSystem(_fs);
10904
10950
 
10905
10951
  const author = await normalizeAuthorObject({ fs, gitdir, author: _author });
10906
- if (!author && !fastForwardOnly) throw new MissingNameError('author')
10952
+ if (!author && (!fastForwardOnly || !fastForward)) {
10953
+ throw new MissingNameError('author')
10954
+ }
10907
10955
 
10908
10956
  const committer = await normalizeCommitterObject({
10909
10957
  fs,
@@ -10911,7 +10959,7 @@ async function merge({
10911
10959
  author,
10912
10960
  committer: _committer,
10913
10961
  });
10914
- if (!committer && !fastForwardOnly) {
10962
+ if (!committer && (!fastForwardOnly || !fastForward)) {
10915
10963
  throw new MissingNameError('committer')
10916
10964
  }
10917
10965
 
@@ -10921,6 +10969,7 @@ async function merge({
10921
10969
  gitdir,
10922
10970
  ours,
10923
10971
  theirs,
10972
+ fastForward,
10924
10973
  fastForwardOnly,
10925
10974
  dryRun,
10926
10975
  noUpdateBranch,
@@ -11125,6 +11174,7 @@ async function packObjects({
11125
11174
  * @param {string} [args.remoteRef] - (Added in 1.1.0) The name of the branch on the remote to fetch. By default this is the configured remote tracking branch.
11126
11175
  * @param {string} [args.corsProxy] - Optional [CORS proxy](https://www.npmjs.com/%40isomorphic-git/cors-proxy). Overrides value in repo config.
11127
11176
  * @param {boolean} [args.singleBranch = false] - Instead of the default behavior of fetching all the branches, only fetch a single branch.
11177
+ * @param {boolean} [args.fastForward = true] - If false, only create merge commits.
11128
11178
  * @param {boolean} [args.fastForwardOnly = false] - Only perform simple fast-forward merges. (Don't create merge commits.)
11129
11179
  * @param {Object<string, string>} [args.headers] - Additional headers to include in HTTP requests, similar to git's `extraHeader` config
11130
11180
  * @param {Object} [args.author] - The details about the author.
@@ -11167,6 +11217,7 @@ async function pull({
11167
11217
  url,
11168
11218
  remote,
11169
11219
  remoteRef,
11220
+ fastForward = true,
11170
11221
  fastForwardOnly = false,
11171
11222
  corsProxy,
11172
11223
  singleBranch,
@@ -11208,6 +11259,7 @@ async function pull({
11208
11259
  url,
11209
11260
  remote,
11210
11261
  remoteRef,
11262
+ fastForward,
11211
11263
  fastForwardOnly,
11212
11264
  corsProxy,
11213
11265
  singleBranch,
@@ -13331,27 +13383,37 @@ async function statusMatrix({
13331
13383
  if (!filter(filepath)) return
13332
13384
  }
13333
13385
 
13334
- // For now, just bail on directories
13335
- const headType = head && (await head.type());
13336
- if (headType === 'tree' || headType === 'special') return
13386
+ const [headType, workdirType, stageType] = await Promise.all([
13387
+ head && head.type(),
13388
+ workdir && workdir.type(),
13389
+ stage && stage.type(),
13390
+ ]);
13391
+
13392
+ const isBlob = [headType, workdirType, stageType].includes('blob');
13393
+
13394
+ // For now, bail on directories unless the file is also a blob in another tree
13395
+ if ((headType === 'tree' || headType === 'special') && !isBlob) return
13337
13396
  if (headType === 'commit') return null
13338
13397
 
13339
- const workdirType = workdir && (await workdir.type());
13340
- if (workdirType === 'tree' || workdirType === 'special') return
13398
+ if ((workdirType === 'tree' || workdirType === 'special') && !isBlob)
13399
+ return
13341
13400
 
13342
- const stageType = stage && (await stage.type());
13343
13401
  if (stageType === 'commit') return null
13344
- if (stageType === 'tree' || stageType === 'special') return
13402
+ if ((stageType === 'tree' || stageType === 'special') && !isBlob) return
13345
13403
 
13346
- // Figure out the oids, using the staged oid for the working dir oid if the stats match.
13347
- const headOid = head ? await head.oid() : undefined;
13348
- const stageOid = stage ? await stage.oid() : undefined;
13404
+ // Figure out the oids for files, using the staged oid for the working dir oid if the stats match.
13405
+ const headOid = headType === 'blob' ? await head.oid() : undefined;
13406
+ const stageOid = stageType === 'blob' ? await stage.oid() : undefined;
13349
13407
  let workdirOid;
13350
- if (!head && workdir && !stage) {
13408
+ if (
13409
+ headType !== 'blob' &&
13410
+ workdirType === 'blob' &&
13411
+ stageType !== 'blob'
13412
+ ) {
13351
13413
  // We don't actually NEED the sha. Any sha will do
13352
13414
  // TODO: update this logic to handle N trees instead of just 3.
13353
13415
  workdirOid = '42';
13354
- } else if (workdir) {
13416
+ } else if (workdirType === 'blob') {
13355
13417
  workdirOid = await workdir.oid();
13356
13418
  }
13357
13419
  const entry = [undefined, headOid, workdirOid, stageOid];
package/index.d.ts CHANGED
@@ -751,7 +751,7 @@ export function WORKDIR(): Walker;
751
751
  * @param {FsClient} args.fs - a file system implementation
752
752
  * @param {string} args.dir - The [working tree](dir-vs-gitdir.md) directory path
753
753
  * @param {string} [args.gitdir=join(dir, '.git')] - [required] The [git directory](dir-vs-gitdir.md) path
754
- * @param {string} args.filepath - The path to the file to add to the index
754
+ * @param {string|string[]} args.filepath - The path to the file to add to the index
755
755
  * @param {object} [args.cache] - a [cache](cache.md) object
756
756
  *
757
757
  * @returns {Promise<void>} Resolves successfully once the git index has been updated
@@ -766,7 +766,7 @@ export function add({ fs: _fs, dir, gitdir, filepath, cache, }: {
766
766
  fs: CallbackFsClient | PromiseFsClient;
767
767
  dir: string;
768
768
  gitdir?: string;
769
- filepath: string;
769
+ filepath: string | string[];
770
770
  cache?: any;
771
771
  }): Promise<void>;
772
772
  /**
@@ -2097,6 +2097,7 @@ export function log({ fs, dir, gitdir, filepath, ref, depth, since, force, follo
2097
2097
  * @param {string} [args.gitdir=join(dir,'.git')] - [required] The [git directory](dir-vs-gitdir.md) path
2098
2098
  * @param {string} [args.ours] - The branch receiving the merge. If undefined, defaults to the current branch.
2099
2099
  * @param {string} args.theirs - The branch to be merged
2100
+ * @param {boolean} [args.fastForward = true] - If false, create a merge commit in all cases.
2100
2101
  * @param {boolean} [args.fastForwardOnly = false] - If true, then non-fast-forward merges will throw an Error instead of performing a merge.
2101
2102
  * @param {boolean} [args.dryRun = false] - If true, simulates a merge so you can test whether it would succeed.
2102
2103
  * @param {boolean} [args.noUpdateBranch = false] - If true, does not update the branch pointer after creating the commit.
@@ -2127,13 +2128,14 @@ export function log({ fs, dir, gitdir, filepath, ref, depth, since, force, follo
2127
2128
  * console.log(m)
2128
2129
  *
2129
2130
  */
2130
- export function merge({ fs: _fs, onSign, dir, gitdir, ours, theirs, fastForwardOnly, dryRun, noUpdateBranch, message, author: _author, committer: _committer, signingKey, cache, }: {
2131
+ export function merge({ fs: _fs, onSign, dir, gitdir, ours, theirs, fastForward, fastForwardOnly, dryRun, noUpdateBranch, message, author: _author, committer: _committer, signingKey, cache, }: {
2131
2132
  fs: CallbackFsClient | PromiseFsClient;
2132
2133
  onSign?: SignCallback;
2133
2134
  dir?: string;
2134
2135
  gitdir?: string;
2135
2136
  ours?: string;
2136
2137
  theirs: string;
2138
+ fastForward?: boolean;
2137
2139
  fastForwardOnly?: boolean;
2138
2140
  dryRun?: boolean;
2139
2141
  noUpdateBranch?: boolean;
@@ -2210,6 +2212,7 @@ export function packObjects({ fs, dir, gitdir, oids, write, cache, }: {
2210
2212
  * @param {string} [args.remoteRef] - (Added in 1.1.0) The name of the branch on the remote to fetch. By default this is the configured remote tracking branch.
2211
2213
  * @param {string} [args.corsProxy] - Optional [CORS proxy](https://www.npmjs.com/%40isomorphic-git/cors-proxy). Overrides value in repo config.
2212
2214
  * @param {boolean} [args.singleBranch = false] - Instead of the default behavior of fetching all the branches, only fetch a single branch.
2215
+ * @param {boolean} [args.fastForward = true] - If false, only create merge commits.
2213
2216
  * @param {boolean} [args.fastForwardOnly = false] - Only perform simple fast-forward merges. (Don't create merge commits.)
2214
2217
  * @param {Object<string, string>} [args.headers] - Additional headers to include in HTTP requests, similar to git's `extraHeader` config
2215
2218
  * @param {Object} [args.author] - The details about the author.
@@ -2238,7 +2241,7 @@ export function packObjects({ fs, dir, gitdir, oids, write, cache, }: {
2238
2241
  * console.log('done')
2239
2242
  *
2240
2243
  */
2241
- export function pull({ fs: _fs, http, onProgress, onMessage, onAuth, onAuthSuccess, onAuthFailure, dir, gitdir, ref, url, remote, remoteRef, fastForwardOnly, corsProxy, singleBranch, headers, author: _author, committer: _committer, signingKey, cache, }: {
2244
+ export function pull({ fs: _fs, http, onProgress, onMessage, onAuth, onAuthSuccess, onAuthFailure, dir, gitdir, ref, url, remote, remoteRef, fastForward, fastForwardOnly, corsProxy, singleBranch, headers, author: _author, committer: _committer, signingKey, cache, }: {
2242
2245
  fs: CallbackFsClient | PromiseFsClient;
2243
2246
  http: HttpClient;
2244
2247
  onProgress?: ProgressCallback;
@@ -2254,6 +2257,7 @@ export function pull({ fs: _fs, http, onProgress, onMessage, onAuth, onAuthSucce
2254
2257
  remoteRef?: string;
2255
2258
  corsProxy?: string;
2256
2259
  singleBranch?: boolean;
2260
+ fastForward?: boolean;
2257
2261
  fastForwardOnly?: boolean;
2258
2262
  headers?: {
2259
2263
  [x: string]: string;