isomorphic-git 1.41.1 → 1.41.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.
@@ -5,8 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
6
 
7
7
  var ignore = _interopDefault(require('ignore'));
8
- var AsyncLock = _interopDefault(require('async-lock'));
9
8
  var Hash = _interopDefault(require('sha.js/sha1.js'));
9
+ var AsyncLock = _interopDefault(require('async-lock'));
10
10
  var crc32 = _interopDefault(require('crc-32'));
11
11
  var pako = _interopDefault(require('pako'));
12
12
  var crypto$1 = require('crypto');
@@ -1524,10 +1524,43 @@ function compareStats(entry, stats, filemode = true, trustino = true) {
1524
1524
  return staleness
1525
1525
  }
1526
1526
 
1527
- // import Lock from '../utils.js'
1527
+ // A single process-wide lock shared by everything that serializes file
1528
+ // operations (the index, refs, the shallow file, blob writes). It is keyed by
1529
+ // path, so unrelated resources never contend. Centralizing it here also means
1530
+ // there is exactly one place to reset it (see `_resetLock`).
1531
+ //
1532
+ // Created lazily (not at module load) so this module has no top-level side
1533
+ // effect and stays tree-shakeable.
1534
+ let lock;
1535
+
1536
+ function getLock() {
1537
+ if (lock === undefined) lock = new AsyncLock({ maxPending: Infinity });
1538
+ return lock
1539
+ }
1540
+
1541
+ /**
1542
+ * Run `callback` while holding the shared lock for `key`, then release it.
1543
+ *
1544
+ * @template T
1545
+ * @param {string | string[]} key - Resource key(s) to lock (usually a filepath).
1546
+ * @param {() => (Promise<T> | T)} callback
1547
+ * @returns {Promise<T>}
1548
+ */
1549
+ function acquireLock(key, callback) {
1550
+ return getLock().acquire(key, callback)
1551
+ }
1528
1552
 
1529
- // const lm = new LockManager()
1530
- let lock = null;
1553
+ /**
1554
+ * Discard the shared lock so the next `acquireLock` starts a fresh one. Intended
1555
+ * for test harnesses that run many independent scenarios inside one long-lived
1556
+ * module instance: if a scenario leaves an operation stalled (e.g. a filesystem
1557
+ * that hangs), its still-held lock would otherwise block every later scenario
1558
+ * that touches the same path. Resetting abandons that stalled queue so the next
1559
+ * scenario starts clean. It is a no-op for normal library use.
1560
+ */
1561
+ function _resetLock() {
1562
+ lock = undefined;
1563
+ }
1531
1564
 
1532
1565
  const IndexCache = Symbol('IndexCache');
1533
1566
 
@@ -1598,10 +1631,9 @@ class GitIndexManager {
1598
1631
  }
1599
1632
 
1600
1633
  const filepath = `${gitdir}/index`;
1601
- if (lock === null) lock = new AsyncLock({ maxPending: Infinity });
1602
1634
  let result;
1603
1635
  let unmergedPaths = [];
1604
- await lock.acquire(filepath, async () => {
1636
+ await acquireLock(filepath, async () => {
1605
1637
  // Acquire a file lock while we're reading the index
1606
1638
  // to make sure other processes aren't writing to it
1607
1639
  // simultaneously, which could result in a corrupted index.
@@ -1874,13 +1906,6 @@ function assertWritableRef(ref) {
1874
1906
  }
1875
1907
  }
1876
1908
 
1877
- let lock$1;
1878
-
1879
- async function acquireLock(ref, callback) {
1880
- if (lock$1 === undefined) lock$1 = new AsyncLock();
1881
- return lock$1.acquire(ref, callback)
1882
- }
1883
-
1884
1909
  /**
1885
1910
  * A class for managing Git references, including reading, writing, deleting, and resolving refs.
1886
1911
  */
@@ -3246,8 +3271,6 @@ function parseRemoteUrl({ url }) {
3246
3271
  }
3247
3272
  }
3248
3273
 
3249
- let lock$2 = null;
3250
-
3251
3274
  class GitShallowManager {
3252
3275
  /**
3253
3276
  * Reads the `shallow` file in the Git repository and returns a set of object IDs (OIDs).
@@ -3258,10 +3281,9 @@ class GitShallowManager {
3258
3281
  * @returns {Promise<Set<string>>} - A set of shallow object IDs.
3259
3282
  */
3260
3283
  static async read({ fs, gitdir }) {
3261
- if (lock$2 === null) lock$2 = new AsyncLock();
3262
3284
  const filepath = join(gitdir, 'shallow');
3263
3285
  const oids = new Set();
3264
- await lock$2.acquire(filepath, async function () {
3286
+ await acquireLock(filepath, async function () {
3265
3287
  const text = await fs.read(filepath, { encoding: 'utf8' });
3266
3288
  if (text === null) return oids // no file
3267
3289
  if (text.trim() === '') return oids // empty file
@@ -3284,18 +3306,17 @@ class GitShallowManager {
3284
3306
  * @returns {Promise<void>}
3285
3307
  */
3286
3308
  static async write({ fs, gitdir, oids }) {
3287
- if (lock$2 === null) lock$2 = new AsyncLock();
3288
3309
  const filepath = join(gitdir, 'shallow');
3289
3310
  if (oids.size > 0) {
3290
3311
  const text = [...oids].join('\n') + '\n';
3291
- await lock$2.acquire(filepath, async function () {
3312
+ await acquireLock(filepath, async function () {
3292
3313
  await fs.write(filepath, text, {
3293
3314
  encoding: 'utf8',
3294
3315
  });
3295
3316
  });
3296
3317
  } else {
3297
3318
  // No shallows
3298
- await lock$2.acquire(filepath, async function () {
3319
+ await acquireLock(filepath, async function () {
3299
3320
  await fs.rm(filepath);
3300
3321
  });
3301
3322
  }
@@ -6013,12 +6034,6 @@ const _TreeMap = {
6013
6034
  workdir: WORKDIR,
6014
6035
  };
6015
6036
 
6016
- let lock$3;
6017
- async function acquireLock$1(ref, callback) {
6018
- if (lock$3 === undefined) lock$3 = new AsyncLock();
6019
- return lock$3.acquire(ref, callback)
6020
- }
6021
-
6022
6037
  // make sure filepath, blob type and blob object (from loose objects) plus oid are in sync and valid
6023
6038
  async function checkAndWriteBlob(fs, gitdir, dir, filepath, oid = null) {
6024
6039
  const currentFilepath = join(dir, filepath);
@@ -6035,7 +6050,7 @@ async function checkAndWriteBlob(fs, gitdir, dir, filepath, oid = null) {
6035
6050
  : undefined;
6036
6051
  let retOid = objContent ? oid : undefined;
6037
6052
  if (!objContent) {
6038
- await acquireLock$1(currentFilepath, async () => {
6053
+ await acquireLock(currentFilepath, async () => {
6039
6054
  const object = stats.isSymbolicLink()
6040
6055
  ? await fs.readlink(currentFilepath).then(posixifyPathBuffer)
6041
6056
  : await fs.read(currentFilepath);
@@ -6250,7 +6265,7 @@ async function applyTreeChanges({
6250
6265
  });
6251
6266
 
6252
6267
  // apply the changes to work dir
6253
- await acquireLock$1(gitdir, async () => {
6268
+ await acquireLock(gitdir, async () => {
6254
6269
  for (const op of ops) {
6255
6270
  const currentFilepath = join(dir, op.filepath);
6256
6271
  switch (op.method) {
@@ -6481,7 +6496,7 @@ class GitStashManager {
6481
6496
  );
6482
6497
  const filepath = this.refLogsStashPath;
6483
6498
 
6484
- await acquireLock$1(filepath, async () => {
6499
+ await acquireLock(filepath, async () => {
6485
6500
  const appendTo = (await this.fs.exists(filepath))
6486
6501
  ? await this.fs.read(filepath, 'utf8')
6487
6502
  : '';
package/managers/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import ignore from 'ignore';
2
- import AsyncLock from 'async-lock';
3
2
  import Hash from 'sha.js/sha1.js';
3
+ import AsyncLock from 'async-lock';
4
4
  import crc32 from 'crc-32';
5
5
  import pako from 'pako';
6
6
 
@@ -1517,10 +1517,43 @@ function compareStats(entry, stats, filemode = true, trustino = true) {
1517
1517
  return staleness
1518
1518
  }
1519
1519
 
1520
- // import Lock from '../utils.js'
1520
+ // A single process-wide lock shared by everything that serializes file
1521
+ // operations (the index, refs, the shallow file, blob writes). It is keyed by
1522
+ // path, so unrelated resources never contend. Centralizing it here also means
1523
+ // there is exactly one place to reset it (see `_resetLock`).
1524
+ //
1525
+ // Created lazily (not at module load) so this module has no top-level side
1526
+ // effect and stays tree-shakeable.
1527
+ let lock;
1528
+
1529
+ function getLock() {
1530
+ if (lock === undefined) lock = new AsyncLock({ maxPending: Infinity });
1531
+ return lock
1532
+ }
1533
+
1534
+ /**
1535
+ * Run `callback` while holding the shared lock for `key`, then release it.
1536
+ *
1537
+ * @template T
1538
+ * @param {string | string[]} key - Resource key(s) to lock (usually a filepath).
1539
+ * @param {() => (Promise<T> | T)} callback
1540
+ * @returns {Promise<T>}
1541
+ */
1542
+ function acquireLock(key, callback) {
1543
+ return getLock().acquire(key, callback)
1544
+ }
1521
1545
 
1522
- // const lm = new LockManager()
1523
- let lock = null;
1546
+ /**
1547
+ * Discard the shared lock so the next `acquireLock` starts a fresh one. Intended
1548
+ * for test harnesses that run many independent scenarios inside one long-lived
1549
+ * module instance: if a scenario leaves an operation stalled (e.g. a filesystem
1550
+ * that hangs), its still-held lock would otherwise block every later scenario
1551
+ * that touches the same path. Resetting abandons that stalled queue so the next
1552
+ * scenario starts clean. It is a no-op for normal library use.
1553
+ */
1554
+ function _resetLock() {
1555
+ lock = undefined;
1556
+ }
1524
1557
 
1525
1558
  const IndexCache = Symbol('IndexCache');
1526
1559
 
@@ -1591,10 +1624,9 @@ class GitIndexManager {
1591
1624
  }
1592
1625
 
1593
1626
  const filepath = `${gitdir}/index`;
1594
- if (lock === null) lock = new AsyncLock({ maxPending: Infinity });
1595
1627
  let result;
1596
1628
  let unmergedPaths = [];
1597
- await lock.acquire(filepath, async () => {
1629
+ await acquireLock(filepath, async () => {
1598
1630
  // Acquire a file lock while we're reading the index
1599
1631
  // to make sure other processes aren't writing to it
1600
1632
  // simultaneously, which could result in a corrupted index.
@@ -1867,13 +1899,6 @@ function assertWritableRef(ref) {
1867
1899
  }
1868
1900
  }
1869
1901
 
1870
- let lock$1;
1871
-
1872
- async function acquireLock(ref, callback) {
1873
- if (lock$1 === undefined) lock$1 = new AsyncLock();
1874
- return lock$1.acquire(ref, callback)
1875
- }
1876
-
1877
1902
  /**
1878
1903
  * A class for managing Git references, including reading, writing, deleting, and resolving refs.
1879
1904
  */
@@ -3239,8 +3264,6 @@ function parseRemoteUrl({ url }) {
3239
3264
  }
3240
3265
  }
3241
3266
 
3242
- let lock$2 = null;
3243
-
3244
3267
  class GitShallowManager {
3245
3268
  /**
3246
3269
  * Reads the `shallow` file in the Git repository and returns a set of object IDs (OIDs).
@@ -3251,10 +3274,9 @@ class GitShallowManager {
3251
3274
  * @returns {Promise<Set<string>>} - A set of shallow object IDs.
3252
3275
  */
3253
3276
  static async read({ fs, gitdir }) {
3254
- if (lock$2 === null) lock$2 = new AsyncLock();
3255
3277
  const filepath = join(gitdir, 'shallow');
3256
3278
  const oids = new Set();
3257
- await lock$2.acquire(filepath, async function () {
3279
+ await acquireLock(filepath, async function () {
3258
3280
  const text = await fs.read(filepath, { encoding: 'utf8' });
3259
3281
  if (text === null) return oids // no file
3260
3282
  if (text.trim() === '') return oids // empty file
@@ -3277,18 +3299,17 @@ class GitShallowManager {
3277
3299
  * @returns {Promise<void>}
3278
3300
  */
3279
3301
  static async write({ fs, gitdir, oids }) {
3280
- if (lock$2 === null) lock$2 = new AsyncLock();
3281
3302
  const filepath = join(gitdir, 'shallow');
3282
3303
  if (oids.size > 0) {
3283
3304
  const text = [...oids].join('\n') + '\n';
3284
- await lock$2.acquire(filepath, async function () {
3305
+ await acquireLock(filepath, async function () {
3285
3306
  await fs.write(filepath, text, {
3286
3307
  encoding: 'utf8',
3287
3308
  });
3288
3309
  });
3289
3310
  } else {
3290
3311
  // No shallows
3291
- await lock$2.acquire(filepath, async function () {
3312
+ await acquireLock(filepath, async function () {
3292
3313
  await fs.rm(filepath);
3293
3314
  });
3294
3315
  }
@@ -6000,12 +6021,6 @@ const _TreeMap = {
6000
6021
  workdir: WORKDIR,
6001
6022
  };
6002
6023
 
6003
- let lock$3;
6004
- async function acquireLock$1(ref, callback) {
6005
- if (lock$3 === undefined) lock$3 = new AsyncLock();
6006
- return lock$3.acquire(ref, callback)
6007
- }
6008
-
6009
6024
  // make sure filepath, blob type and blob object (from loose objects) plus oid are in sync and valid
6010
6025
  async function checkAndWriteBlob(fs, gitdir, dir, filepath, oid = null) {
6011
6026
  const currentFilepath = join(dir, filepath);
@@ -6022,7 +6037,7 @@ async function checkAndWriteBlob(fs, gitdir, dir, filepath, oid = null) {
6022
6037
  : undefined;
6023
6038
  let retOid = objContent ? oid : undefined;
6024
6039
  if (!objContent) {
6025
- await acquireLock$1(currentFilepath, async () => {
6040
+ await acquireLock(currentFilepath, async () => {
6026
6041
  const object = stats.isSymbolicLink()
6027
6042
  ? await fs.readlink(currentFilepath).then(posixifyPathBuffer)
6028
6043
  : await fs.read(currentFilepath);
@@ -6237,7 +6252,7 @@ async function applyTreeChanges({
6237
6252
  });
6238
6253
 
6239
6254
  // apply the changes to work dir
6240
- await acquireLock$1(gitdir, async () => {
6255
+ await acquireLock(gitdir, async () => {
6241
6256
  for (const op of ops) {
6242
6257
  const currentFilepath = join(dir, op.filepath);
6243
6258
  switch (op.method) {
@@ -6468,7 +6483,7 @@ class GitStashManager {
6468
6483
  );
6469
6484
  const filepath = this.refLogsStashPath;
6470
6485
 
6471
- await acquireLock$1(filepath, async () => {
6486
+ await acquireLock(filepath, async () => {
6472
6487
  const appendTo = (await this.fs.exists(filepath))
6473
6488
  ? await this.fs.read(filepath, 'utf8')
6474
6489
  : '';