isomorphic-git 1.41.1 → 1.41.3
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/index.cjs +54 -34
- package/index.js +54 -34
- package/index.umd.min.js +1 -1
- package/index.umd.min.js.map +1 -1
- package/managers/index.cjs +44 -29
- package/managers/index.js +44 -29
- package/managers/index.umd.min.js +1 -1
- package/managers/index.umd.min.js.map +1 -1
- package/package.json +1 -1
package/managers/index.cjs
CHANGED
|
@@ -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
|
-
//
|
|
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
|
-
|
|
1530
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
//
|
|
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
|
-
|
|
1523
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
6486
|
+
await acquireLock(filepath, async () => {
|
|
6472
6487
|
const appendTo = (await this.fs.exists(filepath))
|
|
6473
6488
|
? await this.fs.read(filepath, 'utf8')
|
|
6474
6489
|
: '';
|