isomorphic-git 1.9.1 β†’ 1.10.2

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
@@ -168,6 +168,7 @@ unless there is a major version bump.
168
168
  - [indexPack](https://isomorphic-git.github.io/docs/indexPack.html)
169
169
  - [init](https://isomorphic-git.github.io/docs/init.html)
170
170
  - [isDescendent](https://isomorphic-git.github.io/docs/isDescendent.html)
171
+ - [isIgnored](https://isomorphic-git.github.io/docs/isIgnored.html)
171
172
  - [listBranches](https://isomorphic-git.github.io/docs/listBranches.html)
172
173
  - [listFiles](https://isomorphic-git.github.io/docs/listFiles.html)
173
174
  - [listNotes](https://isomorphic-git.github.io/docs/listNotes.html)
@@ -321,21 +322,23 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
321
322
  <td align="center"><a href="http://eaf4.com"><img src="https://avatars0.githubusercontent.com/u/319282?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Edward Faulkner</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=ef4" title="Code">πŸ’»</a></td>
322
323
  <td align="center"><a href="https://github.com/KSXGitHub"><img src="https://avatars2.githubusercontent.com/u/11488886?v=4?s=60" width="60px;" alt=""/><br /><sub><b>KhαΊ£i</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/issues?q=author%3AKSXGitHub" title="Bug reports">πŸ›</a></td>
323
324
  <td align="center"><a href="https://crutchcorn.dev/"><img src="https://avatars0.githubusercontent.com/u/9100169?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Corbin Crutchley</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=crutchcorn" title="Code">πŸ’»</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=crutchcorn" title="Documentation">πŸ“–</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=crutchcorn" title="Tests">⚠️</a></td>
324
- <td align="center"><a href="https://onetwo.ren/"><img src="https://avatars1.githubusercontent.com/u/3746270?v=4?s=60" width="60px;" alt=""/><br /><sub><b>lin onetwo</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=linonetwo" title="Code">πŸ’»</a></td>
325
+ <td align="center"><a href="https://github.com/snowyu"><img src="https://avatars1.githubusercontent.com/u/327887?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Riceball LEE</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=snowyu" title="Code">πŸ’»</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=snowyu" title="Documentation">πŸ“–</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=snowyu" title="Tests">⚠️</a></td>
325
326
  </tr>
326
327
  <tr>
328
+ <td align="center"><a href="https://onetwo.ren/"><img src="https://avatars1.githubusercontent.com/u/3746270?v=4?s=60" width="60px;" alt=""/><br /><sub><b>lin onetwo</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=linonetwo" title="Code">πŸ’»</a></td>
327
329
  <td align="center"><a href="https://github.com/linfaxin"><img src="https://avatars2.githubusercontent.com/u/3705017?v=4?s=60" width="60px;" alt=""/><br /><sub><b>ζž—ζ³•ι‘«</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/issues?q=author%3Alinfaxin" title="Bug reports">πŸ›</a></td>
328
- <td align="center"><a href="https://github.com/snowyu"><img src="https://avatars1.githubusercontent.com/u/327887?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Riceball LEE</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=snowyu" title="Code">πŸ’»</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=snowyu" title="Documentation">πŸ“–</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=snowyu" title="Tests">⚠️</a></td>
329
330
  <td align="center"><a href="https://github.com/willstott101"><img src="https://avatars2.githubusercontent.com/u/335152?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Will Stott</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=willstott101" title="Code">πŸ’»</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=willstott101" title="Tests">⚠️</a></td>
330
331
  <td align="center"><a href="http://mtnspring.org/"><img src="https://avatars2.githubusercontent.com/u/223277?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Seth Nickell</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/issues?q=author%3Asnickell" title="Bug reports">πŸ›</a></td>
331
332
  <td align="center"><a href="https://www.alextitarenko.me/"><img src="https://avatars0.githubusercontent.com/u/3290313?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Alex Titarenko</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=alex-titarenko" title="Code">πŸ’»</a></td>
332
333
  <td align="center"><a href="https://github.com/mmkal"><img src="https://avatars2.githubusercontent.com/u/15040698?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Misha Kaletsky</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=mmkal" title="Code">πŸ’»</a></td>
333
334
  <td align="center"><a href="https://github.com/rczulch"><img src="https://avatars1.githubusercontent.com/u/54646976?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Richard C. Zulch</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=rczulch" title="Code">πŸ’»</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=rczulch" title="Documentation">πŸ“–</a></td>
334
- <td align="center"><a href="https://scrapbox.io/mkizka/README"><img src="https://avatars.githubusercontent.com/u/30231179?v=4?s=60" width="60px;" alt=""/><br /><sub><b>mkizka</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=mkizka" title="Code">πŸ’»</a></td>
335
335
  </tr>
336
336
  <tr>
337
+ <td align="center"><a href="https://scrapbox.io/mkizka/README"><img src="https://avatars.githubusercontent.com/u/30231179?v=4?s=60" width="60px;" alt=""/><br /><sub><b>mkizka</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=mkizka" title="Code">πŸ’»</a></td>
337
338
  <td align="center"><a href="https://ryotak.me/"><img src="https://avatars.githubusercontent.com/u/49341894?v=4?s=60" width="60px;" alt=""/><br /><sub><b>RyotaK</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/issues?q=author%3ARy0taK" title="Bug reports">πŸ›</a></td>
338
339
  <td align="center"><a href="https://github.com/strangedev"><img src="https://avatars.githubusercontent.com/u/3045979?v=4?s=60" width="60px;" alt=""/><br /><sub><b>Noah Hummel</b></sub></a><br /><a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=strangedev" title="Code">πŸ’»</a> <a href="https://github.com/isomorphic-git/isomorphic-git/commits?author=strangedev" title="Tests">⚠️</a></td>
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
+ <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>
339
342
  </tr>
340
343
  </table>
341
344
 
@@ -1,8 +1,8 @@
1
1
  [
2
2
  "HeadlessChrome 0.0.0 (Linux 0.0.0)",
3
- "Firefox 89.0.0 (Ubuntu 0.0.0)",
4
- "Chrome Mobile 89.0.4389 (Android 0.0.0)",
5
- "Chrome 79.0.3945 (Windows 10 0.0.0)",
3
+ "Firefox 94.0.0 (Ubuntu 0.0.0)",
6
4
  "Safari 13.1.0 (Mac OS X 10.15.4)",
7
- "Mobile Safari 13.0.0 (iOS 13.0.0)"
5
+ "Chrome 79.0.3945 (Windows 10 0.0.0)",
6
+ "Mobile Safari 13.0.0 (iOS 13.0.0)",
7
+ "Chrome Mobile 94.0.4606 (Android 0.0.0)"
8
8
  ]
package/index.cjs CHANGED
@@ -1694,8 +1694,8 @@ class GitRefManager {
1694
1694
  if (serverRef.startsWith('refs/tags') && !serverRef.endsWith('^{}')) {
1695
1695
  // Git's behavior is to only fetch tags that do not conflict with tags already present.
1696
1696
  if (!(await GitRefManager.exists({ fs, gitdir, ref: serverRef }))) {
1697
- // If there is a dereferenced an annotated tag value available, prefer that.
1698
- const oid = refs.get(serverRef + '^{}') || refs.get(serverRef);
1697
+ // Always use the object id of the tag itself, and not the peeled object id.
1698
+ const oid = refs.get(serverRef);
1699
1699
  actualRefsToWrite.set(serverRef, oid);
1700
1700
  }
1701
1701
  }
@@ -2405,7 +2405,7 @@ async function listpack(stream, onData) {
2405
2405
  const inflator = new pako.Inflate();
2406
2406
  while (!inflator.result) {
2407
2407
  const chunk = await reader.chunk();
2408
- if (reader.ended) break
2408
+ if (!chunk) break
2409
2409
  inflator.push(chunk, false);
2410
2410
  if (inflator.err) {
2411
2411
  throw new InternalError(`Pako error: ${inflator.msg}`)
@@ -4069,6 +4069,33 @@ class GitIgnoreManager {
4069
4069
  }
4070
4070
  }
4071
4071
 
4072
+ /**
4073
+ * Removes the directory at the specified filepath recursively. Used internally to replicate the behavior of
4074
+ * fs.promises.rm({ recursive: true, force: true }) from Node.js 14 and above when not available. If the provided
4075
+ * filepath resolves to a file, it will be removed.
4076
+ *
4077
+ * @param {import('../models/FileSystem.js').FileSystem} fs
4078
+ * @param {string} filepath - The file or directory to remove.
4079
+ */
4080
+ async function rmRecursive(fs, filepath) {
4081
+ const entries = await fs.readdir(filepath);
4082
+ if (entries == null) {
4083
+ await fs.rm(filepath);
4084
+ } else if (entries.length) {
4085
+ await Promise.all(
4086
+ entries.map(entry => {
4087
+ const subpath = join(filepath, entry);
4088
+ return fs.lstat(subpath).then(stat => {
4089
+ if (!stat) return
4090
+ return stat.isDirectory() ? rmRecursive(fs, subpath) : fs.rm(subpath)
4091
+ })
4092
+ })
4093
+ ).then(() => fs.rmdir(filepath));
4094
+ } else {
4095
+ await fs.rmdir(filepath);
4096
+ }
4097
+ }
4098
+
4072
4099
  /**
4073
4100
  * This is just a collection of helper functions really. At least that's how it started.
4074
4101
  */
@@ -4081,6 +4108,13 @@ class FileSystem {
4081
4108
  this._readFile = fs.promises.readFile.bind(fs.promises);
4082
4109
  this._writeFile = fs.promises.writeFile.bind(fs.promises);
4083
4110
  this._mkdir = fs.promises.mkdir.bind(fs.promises);
4111
+ if (fs.promises.rm) {
4112
+ this._rm = fs.promises.rm.bind(fs.promises);
4113
+ } else if (fs.promises.rmdir.length > 1) {
4114
+ this._rm = fs.promises.rmdir.bind(fs.promises);
4115
+ } else {
4116
+ this._rm = rmRecursive.bind(null, this);
4117
+ }
4084
4118
  this._rmdir = fs.promises.rmdir.bind(fs.promises);
4085
4119
  this._unlink = fs.promises.unlink.bind(fs.promises);
4086
4120
  this._stat = fs.promises.stat.bind(fs.promises);
@@ -4092,6 +4126,13 @@ class FileSystem {
4092
4126
  this._readFile = pify(fs.readFile.bind(fs));
4093
4127
  this._writeFile = pify(fs.writeFile.bind(fs));
4094
4128
  this._mkdir = pify(fs.mkdir.bind(fs));
4129
+ if (fs.rm) {
4130
+ this._rm = pify(fs.rm.bind(fs));
4131
+ } else if (fs.rmdir.length > 2) {
4132
+ this._rm = pify(fs.rmdir.bind(fs));
4133
+ } else {
4134
+ this._rm = rmRecursive.bind(null, this);
4135
+ }
4095
4136
  this._rmdir = pify(fs.rmdir.bind(fs));
4096
4137
  this._unlink = pify(fs.unlink.bind(fs));
4097
4138
  this._stat = pify(fs.stat.bind(fs));
@@ -4200,9 +4241,13 @@ class FileSystem {
4200
4241
  /**
4201
4242
  * Delete a directory without throwing an error if it is already deleted.
4202
4243
  */
4203
- async rmdir(filepath) {
4244
+ async rmdir(filepath, opts) {
4204
4245
  try {
4205
- await this._rmdir(filepath);
4246
+ if (opts && opts.recursive) {
4247
+ await this._rm(filepath, opts);
4248
+ } else {
4249
+ await this._rmdir(filepath);
4250
+ }
4206
4251
  } catch (err) {
4207
4252
  if (err.code !== 'ENOENT') throw err
4208
4253
  }
@@ -6380,7 +6425,14 @@ async function parseRefsAdResponse(stream, { service }) {
6380
6425
  let lineOne = await read();
6381
6426
  // skip past any flushes
6382
6427
  while (lineOne === null) lineOne = await read();
6428
+
6383
6429
  if (lineOne === true) throw new EmptyServerResponseError()
6430
+
6431
+ // Handle protocol v2 responses (Bitbucket Server doesn't include a `# service=` line)
6432
+ if (lineOne.includes('version 2')) {
6433
+ return parseCapabilitiesV2(read)
6434
+ }
6435
+
6384
6436
  // Clients MUST ignore an LF at the end of the line.
6385
6437
  if (lineOne.toString('utf8').replace(/\n$/, '') !== `# service=${service}`) {
6386
6438
  throw new ParseError(`# service=${service}\\n`, lineOne.toString('utf8'))
@@ -6392,10 +6444,12 @@ async function parseRefsAdResponse(stream, { service }) {
6392
6444
  // are returned.
6393
6445
  if (lineTwo === true) return { capabilities, refs, symrefs }
6394
6446
  lineTwo = lineTwo.toString('utf8');
6447
+
6395
6448
  // Handle protocol v2 responses
6396
6449
  if (lineTwo.includes('version 2')) {
6397
6450
  return parseCapabilitiesV2(read)
6398
6451
  }
6452
+
6399
6453
  const [firstRef, capabilitiesLine] = splitAndAssert(lineTwo, '\x00', '\\x00');
6400
6454
  capabilitiesLine.split(' ').map(x => capabilities.add(x));
6401
6455
  const [ref, name] = splitAndAssert(firstRef, ' ', ' ');
@@ -6803,8 +6857,8 @@ function filterCapabilities(server, client) {
6803
6857
 
6804
6858
  const pkg = {
6805
6859
  name: 'isomorphic-git',
6806
- version: '1.9.1',
6807
- agent: 'git/isomorphic-git@1.9.1',
6860
+ version: '1.10.2',
6861
+ agent: 'git/isomorphic-git@1.10.2',
6808
6862
  };
6809
6863
 
6810
6864
  class FIFO {
@@ -7518,37 +7572,6 @@ async function _init({
7518
7572
  await fs.write(gitdir + '/HEAD', `ref: refs/heads/${defaultBranch}\n`);
7519
7573
  }
7520
7574
 
7521
- /**
7522
- * @param {object} args
7523
- * @param {import('../models/FileSystem.js').FileSystem} args.fs
7524
- * @param {string} args.dirname
7525
- */
7526
- async function deleteRecursively({ fs, dirname }) {
7527
- const filesToDelete = [];
7528
- const directoriesToDelete = [];
7529
- const pathsToTraverse = [dirname];
7530
-
7531
- while (pathsToTraverse.length > 0) {
7532
- const path = pathsToTraverse.pop();
7533
-
7534
- if ((await fs._stat(path)).isDirectory()) {
7535
- directoriesToDelete.push(path);
7536
- pathsToTraverse.push(
7537
- ...(await fs.readdir(path)).map(subPath => join(path, subPath))
7538
- );
7539
- } else {
7540
- filesToDelete.push(path);
7541
- }
7542
- }
7543
-
7544
- for (const path of filesToDelete) {
7545
- await fs.rm(path);
7546
- }
7547
- for (const path of directoriesToDelete.reverse()) {
7548
- await fs.rmdir(path);
7549
- }
7550
- }
7551
-
7552
7575
  // @ts-check
7553
7576
 
7554
7577
  /**
@@ -7648,14 +7671,11 @@ async function _clone({
7648
7671
  });
7649
7672
  } catch (err) {
7650
7673
  // Remove partial local repository, see #1283
7651
- try {
7652
- await deleteRecursively({ fs, dirname: gitdir });
7653
- } catch (err) {
7654
- // Ignore this error, we are already failing.
7655
- // This try-catch is necessary so the original error is
7656
- // not masked by potential errors in deleteRecursively.
7657
- }
7658
-
7674
+ // Ignore any error as we are already failing.
7675
+ // The catch is necessary so the original error is not masked.
7676
+ await fs
7677
+ .rmdir(gitdir, { recursive: true, maxRetries: 10 })
7678
+ .catch(() => undefined);
7659
7679
  throw err
7660
7680
  }
7661
7681
  }
@@ -9866,6 +9886,47 @@ async function isDescendent({
9866
9886
 
9867
9887
  // @ts-check
9868
9888
 
9889
+ /**
9890
+ * Test whether a filepath should be ignored (because of .gitignore or .git/exclude)
9891
+ *
9892
+ * @param {object} args
9893
+ * @param {FsClient} args.fs - a file system client
9894
+ * @param {string} args.dir - The [working tree](dir-vs-gitdir.md) directory path
9895
+ * @param {string} [args.gitdir=join(dir, '.git')] - [required] The [git directory](dir-vs-gitdir.md) path
9896
+ * @param {string} args.filepath - The filepath to test
9897
+ *
9898
+ * @returns {Promise<boolean>} Resolves to true if the file should be ignored
9899
+ *
9900
+ * @example
9901
+ * await git.isIgnored({ fs, dir: '/tutorial', filepath: 'docs/add.md' })
9902
+ *
9903
+ */
9904
+ async function isIgnored({
9905
+ fs,
9906
+ dir,
9907
+ gitdir = join(dir, '.git'),
9908
+ filepath,
9909
+ }) {
9910
+ try {
9911
+ assertParameter('fs', fs);
9912
+ assertParameter('dir', dir);
9913
+ assertParameter('gitdir', gitdir);
9914
+ assertParameter('filepath', filepath);
9915
+
9916
+ return GitIgnoreManager.isIgnored({
9917
+ fs: new FileSystem(fs),
9918
+ dir,
9919
+ gitdir,
9920
+ filepath,
9921
+ })
9922
+ } catch (err) {
9923
+ err.caller = 'git.isIgnored';
9924
+ throw err
9925
+ }
9926
+ }
9927
+
9928
+ // @ts-check
9929
+
9869
9930
  /**
9870
9931
  * List branches
9871
9932
  *
@@ -10560,6 +10621,10 @@ async function _log({
10560
10621
  let lastCommit;
10561
10622
  let isOk;
10562
10623
 
10624
+ function endCommit(commit) {
10625
+ if (isOk && filepath) commits.push(commit);
10626
+ }
10627
+
10563
10628
  while (tips.length > 0) {
10564
10629
  const commit = tips.pop();
10565
10630
 
@@ -10669,10 +10734,6 @@ async function _log({
10669
10734
  tips.sort((a, b) => compareAge(a.commit, b.commit));
10670
10735
  }
10671
10736
  return commits
10672
-
10673
- function endCommit(commit) {
10674
- if (isOk && filepath) commits.push(commit);
10675
- }
10676
10737
  }
10677
10738
 
10678
10739
  // @ts-check
@@ -14083,6 +14144,7 @@ var index = {
14083
14144
  indexPack,
14084
14145
  init,
14085
14146
  isDescendent,
14147
+ isIgnored,
14086
14148
  listBranches,
14087
14149
  listFiles,
14088
14150
  listNotes,
@@ -14150,6 +14212,7 @@ exports.hashBlob = hashBlob;
14150
14212
  exports.indexPack = indexPack;
14151
14213
  exports.init = init;
14152
14214
  exports.isDescendent = isDescendent;
14215
+ exports.isIgnored = isIgnored;
14153
14216
  exports.listBranches = listBranches;
14154
14217
  exports.listFiles = listFiles;
14155
14218
  exports.listNotes = listNotes;
package/index.d.ts CHANGED
@@ -659,6 +659,7 @@ declare namespace index {
659
659
  export { indexPack };
660
660
  export { init };
661
661
  export { isDescendent };
662
+ export { isIgnored };
662
663
  export { listBranches };
663
664
  export { listFiles };
664
665
  export { listNotes };
@@ -1762,6 +1763,27 @@ export function isDescendent({ fs, dir, gitdir, oid, ancestor, depth, cache, }:
1762
1763
  depth?: number;
1763
1764
  cache?: any;
1764
1765
  }): Promise<boolean>;
1766
+ /**
1767
+ * Test whether a filepath should be ignored (because of .gitignore or .git/exclude)
1768
+ *
1769
+ * @param {object} args
1770
+ * @param {FsClient} args.fs - a file system client
1771
+ * @param {string} args.dir - The [working tree](dir-vs-gitdir.md) directory path
1772
+ * @param {string} [args.gitdir=join(dir, '.git')] - [required] The [git directory](dir-vs-gitdir.md) path
1773
+ * @param {string} args.filepath - The filepath to test
1774
+ *
1775
+ * @returns {Promise<boolean>} Resolves to true if the file should be ignored
1776
+ *
1777
+ * @example
1778
+ * await git.isIgnored({ fs, dir: '/tutorial', filepath: 'docs/add.md' })
1779
+ *
1780
+ */
1781
+ export function isIgnored({ fs, dir, gitdir, filepath, }: {
1782
+ fs: CallbackFsClient | PromiseFsClient;
1783
+ dir: string;
1784
+ gitdir?: string;
1785
+ filepath: string;
1786
+ }): Promise<boolean>;
1765
1787
  /**
1766
1788
  * List branches
1767
1789
  *
package/index.js CHANGED
@@ -1688,8 +1688,8 @@ class GitRefManager {
1688
1688
  if (serverRef.startsWith('refs/tags') && !serverRef.endsWith('^{}')) {
1689
1689
  // Git's behavior is to only fetch tags that do not conflict with tags already present.
1690
1690
  if (!(await GitRefManager.exists({ fs, gitdir, ref: serverRef }))) {
1691
- // If there is a dereferenced an annotated tag value available, prefer that.
1692
- const oid = refs.get(serverRef + '^{}') || refs.get(serverRef);
1691
+ // Always use the object id of the tag itself, and not the peeled object id.
1692
+ const oid = refs.get(serverRef);
1693
1693
  actualRefsToWrite.set(serverRef, oid);
1694
1694
  }
1695
1695
  }
@@ -2399,7 +2399,7 @@ async function listpack(stream, onData) {
2399
2399
  const inflator = new pako.Inflate();
2400
2400
  while (!inflator.result) {
2401
2401
  const chunk = await reader.chunk();
2402
- if (reader.ended) break
2402
+ if (!chunk) break
2403
2403
  inflator.push(chunk, false);
2404
2404
  if (inflator.err) {
2405
2405
  throw new InternalError(`Pako error: ${inflator.msg}`)
@@ -4063,6 +4063,33 @@ class GitIgnoreManager {
4063
4063
  }
4064
4064
  }
4065
4065
 
4066
+ /**
4067
+ * Removes the directory at the specified filepath recursively. Used internally to replicate the behavior of
4068
+ * fs.promises.rm({ recursive: true, force: true }) from Node.js 14 and above when not available. If the provided
4069
+ * filepath resolves to a file, it will be removed.
4070
+ *
4071
+ * @param {import('../models/FileSystem.js').FileSystem} fs
4072
+ * @param {string} filepath - The file or directory to remove.
4073
+ */
4074
+ async function rmRecursive(fs, filepath) {
4075
+ const entries = await fs.readdir(filepath);
4076
+ if (entries == null) {
4077
+ await fs.rm(filepath);
4078
+ } else if (entries.length) {
4079
+ await Promise.all(
4080
+ entries.map(entry => {
4081
+ const subpath = join(filepath, entry);
4082
+ return fs.lstat(subpath).then(stat => {
4083
+ if (!stat) return
4084
+ return stat.isDirectory() ? rmRecursive(fs, subpath) : fs.rm(subpath)
4085
+ })
4086
+ })
4087
+ ).then(() => fs.rmdir(filepath));
4088
+ } else {
4089
+ await fs.rmdir(filepath);
4090
+ }
4091
+ }
4092
+
4066
4093
  /**
4067
4094
  * This is just a collection of helper functions really. At least that's how it started.
4068
4095
  */
@@ -4075,6 +4102,13 @@ class FileSystem {
4075
4102
  this._readFile = fs.promises.readFile.bind(fs.promises);
4076
4103
  this._writeFile = fs.promises.writeFile.bind(fs.promises);
4077
4104
  this._mkdir = fs.promises.mkdir.bind(fs.promises);
4105
+ if (fs.promises.rm) {
4106
+ this._rm = fs.promises.rm.bind(fs.promises);
4107
+ } else if (fs.promises.rmdir.length > 1) {
4108
+ this._rm = fs.promises.rmdir.bind(fs.promises);
4109
+ } else {
4110
+ this._rm = rmRecursive.bind(null, this);
4111
+ }
4078
4112
  this._rmdir = fs.promises.rmdir.bind(fs.promises);
4079
4113
  this._unlink = fs.promises.unlink.bind(fs.promises);
4080
4114
  this._stat = fs.promises.stat.bind(fs.promises);
@@ -4086,6 +4120,13 @@ class FileSystem {
4086
4120
  this._readFile = pify(fs.readFile.bind(fs));
4087
4121
  this._writeFile = pify(fs.writeFile.bind(fs));
4088
4122
  this._mkdir = pify(fs.mkdir.bind(fs));
4123
+ if (fs.rm) {
4124
+ this._rm = pify(fs.rm.bind(fs));
4125
+ } else if (fs.rmdir.length > 2) {
4126
+ this._rm = pify(fs.rmdir.bind(fs));
4127
+ } else {
4128
+ this._rm = rmRecursive.bind(null, this);
4129
+ }
4089
4130
  this._rmdir = pify(fs.rmdir.bind(fs));
4090
4131
  this._unlink = pify(fs.unlink.bind(fs));
4091
4132
  this._stat = pify(fs.stat.bind(fs));
@@ -4194,9 +4235,13 @@ class FileSystem {
4194
4235
  /**
4195
4236
  * Delete a directory without throwing an error if it is already deleted.
4196
4237
  */
4197
- async rmdir(filepath) {
4238
+ async rmdir(filepath, opts) {
4198
4239
  try {
4199
- await this._rmdir(filepath);
4240
+ if (opts && opts.recursive) {
4241
+ await this._rm(filepath, opts);
4242
+ } else {
4243
+ await this._rmdir(filepath);
4244
+ }
4200
4245
  } catch (err) {
4201
4246
  if (err.code !== 'ENOENT') throw err
4202
4247
  }
@@ -6374,7 +6419,14 @@ async function parseRefsAdResponse(stream, { service }) {
6374
6419
  let lineOne = await read();
6375
6420
  // skip past any flushes
6376
6421
  while (lineOne === null) lineOne = await read();
6422
+
6377
6423
  if (lineOne === true) throw new EmptyServerResponseError()
6424
+
6425
+ // Handle protocol v2 responses (Bitbucket Server doesn't include a `# service=` line)
6426
+ if (lineOne.includes('version 2')) {
6427
+ return parseCapabilitiesV2(read)
6428
+ }
6429
+
6378
6430
  // Clients MUST ignore an LF at the end of the line.
6379
6431
  if (lineOne.toString('utf8').replace(/\n$/, '') !== `# service=${service}`) {
6380
6432
  throw new ParseError(`# service=${service}\\n`, lineOne.toString('utf8'))
@@ -6386,10 +6438,12 @@ async function parseRefsAdResponse(stream, { service }) {
6386
6438
  // are returned.
6387
6439
  if (lineTwo === true) return { capabilities, refs, symrefs }
6388
6440
  lineTwo = lineTwo.toString('utf8');
6441
+
6389
6442
  // Handle protocol v2 responses
6390
6443
  if (lineTwo.includes('version 2')) {
6391
6444
  return parseCapabilitiesV2(read)
6392
6445
  }
6446
+
6393
6447
  const [firstRef, capabilitiesLine] = splitAndAssert(lineTwo, '\x00', '\\x00');
6394
6448
  capabilitiesLine.split(' ').map(x => capabilities.add(x));
6395
6449
  const [ref, name] = splitAndAssert(firstRef, ' ', ' ');
@@ -6797,8 +6851,8 @@ function filterCapabilities(server, client) {
6797
6851
 
6798
6852
  const pkg = {
6799
6853
  name: 'isomorphic-git',
6800
- version: '1.9.1',
6801
- agent: 'git/isomorphic-git@1.9.1',
6854
+ version: '1.10.2',
6855
+ agent: 'git/isomorphic-git@1.10.2',
6802
6856
  };
6803
6857
 
6804
6858
  class FIFO {
@@ -7512,37 +7566,6 @@ async function _init({
7512
7566
  await fs.write(gitdir + '/HEAD', `ref: refs/heads/${defaultBranch}\n`);
7513
7567
  }
7514
7568
 
7515
- /**
7516
- * @param {object} args
7517
- * @param {import('../models/FileSystem.js').FileSystem} args.fs
7518
- * @param {string} args.dirname
7519
- */
7520
- async function deleteRecursively({ fs, dirname }) {
7521
- const filesToDelete = [];
7522
- const directoriesToDelete = [];
7523
- const pathsToTraverse = [dirname];
7524
-
7525
- while (pathsToTraverse.length > 0) {
7526
- const path = pathsToTraverse.pop();
7527
-
7528
- if ((await fs._stat(path)).isDirectory()) {
7529
- directoriesToDelete.push(path);
7530
- pathsToTraverse.push(
7531
- ...(await fs.readdir(path)).map(subPath => join(path, subPath))
7532
- );
7533
- } else {
7534
- filesToDelete.push(path);
7535
- }
7536
- }
7537
-
7538
- for (const path of filesToDelete) {
7539
- await fs.rm(path);
7540
- }
7541
- for (const path of directoriesToDelete.reverse()) {
7542
- await fs.rmdir(path);
7543
- }
7544
- }
7545
-
7546
7569
  // @ts-check
7547
7570
 
7548
7571
  /**
@@ -7642,14 +7665,11 @@ async function _clone({
7642
7665
  });
7643
7666
  } catch (err) {
7644
7667
  // Remove partial local repository, see #1283
7645
- try {
7646
- await deleteRecursively({ fs, dirname: gitdir });
7647
- } catch (err) {
7648
- // Ignore this error, we are already failing.
7649
- // This try-catch is necessary so the original error is
7650
- // not masked by potential errors in deleteRecursively.
7651
- }
7652
-
7668
+ // Ignore any error as we are already failing.
7669
+ // The catch is necessary so the original error is not masked.
7670
+ await fs
7671
+ .rmdir(gitdir, { recursive: true, maxRetries: 10 })
7672
+ .catch(() => undefined);
7653
7673
  throw err
7654
7674
  }
7655
7675
  }
@@ -9860,6 +9880,47 @@ async function isDescendent({
9860
9880
 
9861
9881
  // @ts-check
9862
9882
 
9883
+ /**
9884
+ * Test whether a filepath should be ignored (because of .gitignore or .git/exclude)
9885
+ *
9886
+ * @param {object} args
9887
+ * @param {FsClient} args.fs - a file system client
9888
+ * @param {string} args.dir - The [working tree](dir-vs-gitdir.md) directory path
9889
+ * @param {string} [args.gitdir=join(dir, '.git')] - [required] The [git directory](dir-vs-gitdir.md) path
9890
+ * @param {string} args.filepath - The filepath to test
9891
+ *
9892
+ * @returns {Promise<boolean>} Resolves to true if the file should be ignored
9893
+ *
9894
+ * @example
9895
+ * await git.isIgnored({ fs, dir: '/tutorial', filepath: 'docs/add.md' })
9896
+ *
9897
+ */
9898
+ async function isIgnored({
9899
+ fs,
9900
+ dir,
9901
+ gitdir = join(dir, '.git'),
9902
+ filepath,
9903
+ }) {
9904
+ try {
9905
+ assertParameter('fs', fs);
9906
+ assertParameter('dir', dir);
9907
+ assertParameter('gitdir', gitdir);
9908
+ assertParameter('filepath', filepath);
9909
+
9910
+ return GitIgnoreManager.isIgnored({
9911
+ fs: new FileSystem(fs),
9912
+ dir,
9913
+ gitdir,
9914
+ filepath,
9915
+ })
9916
+ } catch (err) {
9917
+ err.caller = 'git.isIgnored';
9918
+ throw err
9919
+ }
9920
+ }
9921
+
9922
+ // @ts-check
9923
+
9863
9924
  /**
9864
9925
  * List branches
9865
9926
  *
@@ -10554,6 +10615,10 @@ async function _log({
10554
10615
  let lastCommit;
10555
10616
  let isOk;
10556
10617
 
10618
+ function endCommit(commit) {
10619
+ if (isOk && filepath) commits.push(commit);
10620
+ }
10621
+
10557
10622
  while (tips.length > 0) {
10558
10623
  const commit = tips.pop();
10559
10624
 
@@ -10663,10 +10728,6 @@ async function _log({
10663
10728
  tips.sort((a, b) => compareAge(a.commit, b.commit));
10664
10729
  }
10665
10730
  return commits
10666
-
10667
- function endCommit(commit) {
10668
- if (isOk && filepath) commits.push(commit);
10669
- }
10670
10731
  }
10671
10732
 
10672
10733
  // @ts-check
@@ -14077,6 +14138,7 @@ var index = {
14077
14138
  indexPack,
14078
14139
  init,
14079
14140
  isDescendent,
14141
+ isIgnored,
14080
14142
  listBranches,
14081
14143
  listFiles,
14082
14144
  listNotes,
@@ -14113,4 +14175,4 @@ var index = {
14113
14175
  };
14114
14176
 
14115
14177
  export default index;
14116
- export { Errors, STAGE, TREE, WORKDIR, add, addNote, addRemote, annotatedTag, branch, checkout, clone, commit, currentBranch, deleteBranch, deleteRef, deleteRemote, deleteTag, expandOid, expandRef, fastForward, fetch, findMergeBase, findRoot, getConfig, getConfigAll, getRemoteInfo, getRemoteInfo2, hashBlob, indexPack, init, isDescendent, listBranches, listFiles, listNotes, listRemotes, listServerRefs, listTags, log, merge, packObjects, pull, push, readBlob, readCommit, readNote, readObject, readTag, readTree, remove, removeNote, renameBranch, resetIndex, resolveRef, setConfig, status, statusMatrix, tag, version, walk, writeBlob, writeCommit, writeObject, writeRef, writeTag, writeTree };
14178
+ export { Errors, STAGE, TREE, WORKDIR, add, addNote, addRemote, annotatedTag, branch, checkout, clone, commit, currentBranch, deleteBranch, deleteRef, deleteRemote, deleteTag, expandOid, expandRef, fastForward, fetch, findMergeBase, findRoot, getConfig, getConfigAll, getRemoteInfo, getRemoteInfo2, hashBlob, indexPack, init, isDescendent, isIgnored, listBranches, listFiles, listNotes, listRemotes, listServerRefs, listTags, log, merge, packObjects, pull, push, readBlob, readCommit, readNote, readObject, readTag, readTree, remove, removeNote, renameBranch, resetIndex, resolveRef, setConfig, status, statusMatrix, tag, version, walk, writeBlob, writeCommit, writeObject, writeRef, writeTag, writeTree };