isomorphic-git 1.37.4 → 1.37.6

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 CHANGED
@@ -8,6 +8,7 @@ var AsyncLock = _interopDefault(require('async-lock'));
8
8
  var Hash = _interopDefault(require('sha.js/sha1.js'));
9
9
  var crc32 = _interopDefault(require('crc-32'));
10
10
  var pako = _interopDefault(require('pako'));
11
+ var crypto$1 = require('crypto');
11
12
  var pify = _interopDefault(require('pify'));
12
13
  var ignore = _interopDefault(require('ignore'));
13
14
  var cleanGitRef = _interopDefault(require('clean-git-ref'));
@@ -3368,6 +3369,19 @@ function readPackIndex({
3368
3369
  return p
3369
3370
  }
3370
3371
 
3372
+ const SHA1_CHUNK_SIZE = 8 * 1024 * 1024;
3373
+
3374
+ async function shasumRange(
3375
+ buffer,
3376
+ { start = 0, end = buffer.length } = {}
3377
+ ) {
3378
+ const hash = crypto$1.createHash('sha1');
3379
+ for (let i = start; i < end; i += SHA1_CHUNK_SIZE) {
3380
+ hash.update(buffer.subarray(i, Math.min(i + SHA1_CHUNK_SIZE, end)));
3381
+ }
3382
+ return hash.digest('hex')
3383
+ }
3384
+
3371
3385
  async function readObjectPacked({
3372
3386
  fs,
3373
3387
  cache,
@@ -3421,11 +3435,12 @@ async function readObjectPacked({
3421
3435
  )
3422
3436
  }
3423
3437
 
3424
- // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload
3425
- // This ensures true data integrity by verifying the entire packfile content
3426
- // Use subarray for zero-copy reading of large files
3427
- const payload = pack.subarray(0, -20);
3428
- const actualPayloadSha = await shasum(payload);
3438
+ // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload.
3439
+ // The Node package build swaps in a chunked implementation for large packs.
3440
+ const actualPayloadSha = await shasumRange(pack, {
3441
+ start: 0,
3442
+ end: pack.length - 20,
3443
+ });
3429
3444
  if (actualPayloadSha !== expectedShaFromIndex) {
3430
3445
  throw new InternalError(
3431
3446
  `Packfile payload corrupted: calculated ${actualPayloadSha} but expected ${expectedShaFromIndex}. The packfile may have been tampered with.`
@@ -7046,7 +7061,7 @@ async function _checkout({
7046
7061
  await GitIndexManager.acquire(
7047
7062
  { fs, gitdir, cache, allowUnmerged: true },
7048
7063
  async function (index) {
7049
- await Promise.all(
7064
+ const settled = await Promise.allSettled(
7050
7065
  ops
7051
7066
  .filter(
7052
7067
  ([method]) =>
@@ -7057,66 +7072,76 @@ async function _checkout({
7057
7072
  )
7058
7073
  .map(async function ([method, fullpath, oid, mode, chmod]) {
7059
7074
  const filepath = `${dir}/${fullpath}`;
7060
- try {
7061
- if (method !== 'create-index' && method !== 'mkdir-index') {
7062
- const { object } = await _readObject({
7063
- fs,
7064
- cache,
7065
- gitdir,
7066
- oid,
7067
- });
7068
- if (chmod) {
7069
- // Note: the mode option of fs.write only works when creating files,
7070
- // not updating them. Since the `fs` plugin doesn't expose `chmod` this
7071
- // is our only option.
7072
- await fs.rm(filepath);
7073
- }
7074
- if (mode === 0o100644) {
7075
- // regular file
7076
- await fs.write(filepath, object);
7077
- } else if (mode === 0o100755) {
7078
- // executable file
7079
- await fs.write(filepath, object, { mode: 0o777 });
7080
- } else if (mode === 0o120000) {
7081
- // symlink
7082
- await fs.writelink(filepath, object);
7083
- } else {
7084
- throw new InternalError(
7085
- `Invalid mode 0o${mode.toString(
7086
- 8
7087
- )} detected in blob ${oid}`
7088
- )
7089
- }
7090
- }
7091
-
7092
- const stats = await fs.lstat(filepath);
7093
- // We can't trust the executable bit returned by lstat on Windows,
7094
- // so we need to preserve this value from the TREE.
7095
- // TODO: Figure out how git handles this internally.
7096
- if (mode === 0o100755) {
7097
- stats.mode = 0o755;
7098
- }
7099
- // Submodules are present in the git index but use a unique mode different from trees
7100
- if (method === 'mkdir-index') {
7101
- stats.mode = 0o160000;
7102
- }
7103
- index.insert({
7104
- filepath: fullpath,
7105
- stats,
7075
+ if (method !== 'create-index' && method !== 'mkdir-index') {
7076
+ const { object } = await _readObject({
7077
+ fs,
7078
+ cache,
7079
+ gitdir,
7106
7080
  oid,
7107
7081
  });
7108
- if (onProgress) {
7109
- await onProgress({
7110
- phase: 'Updating workdir',
7111
- loaded: ++count,
7112
- total,
7113
- });
7082
+ if (chmod) {
7083
+ // Note: the mode option of fs.write only works when creating files,
7084
+ // not updating them. Since the `fs` plugin doesn't expose `chmod` this
7085
+ // is our only option.
7086
+ await fs.rm(filepath);
7114
7087
  }
7115
- } catch (e) {
7116
- console.log(e);
7088
+ if (mode === 0o100644) {
7089
+ // regular file
7090
+ await fs.write(filepath, object);
7091
+ } else if (mode === 0o100755) {
7092
+ // executable file
7093
+ await fs.write(filepath, object, { mode: 0o777 });
7094
+ } else if (mode === 0o120000) {
7095
+ // symlink
7096
+ await fs.writelink(filepath, object);
7097
+ } else {
7098
+ throw new InternalError(
7099
+ `Invalid mode 0o${mode.toString(
7100
+ 8
7101
+ )} detected in blob ${oid}`
7102
+ )
7103
+ }
7104
+ }
7105
+
7106
+ const stats = await fs.lstat(filepath);
7107
+ // We can't trust the executable bit returned by lstat on Windows,
7108
+ // so we need to preserve this value from the TREE.
7109
+ // TODO: Figure out how git handles this internally.
7110
+ if (mode === 0o100755) {
7111
+ stats.mode = 0o755;
7112
+ }
7113
+ // Submodules are present in the git index but use a unique mode different from trees
7114
+ if (method === 'mkdir-index') {
7115
+ stats.mode = 0o160000;
7116
+ }
7117
+ index.insert({
7118
+ filepath: fullpath,
7119
+ stats,
7120
+ oid,
7121
+ });
7122
+ if (onProgress) {
7123
+ await onProgress({
7124
+ phase: 'Updating workdir',
7125
+ loaded: ++count,
7126
+ total,
7127
+ });
7117
7128
  }
7118
7129
  })
7119
7130
  );
7131
+ const rejections = [];
7132
+ for (const result of settled) {
7133
+ if (result.status === 'rejected') {
7134
+ rejections.push(result.reason);
7135
+ // eslint-disable-next-line no-console
7136
+ console.error(
7137
+ '[isomorphic-git checkout] task rejected:',
7138
+ result.reason?.stack ?? result.reason
7139
+ );
7140
+ }
7141
+ }
7142
+ if (rejections.length > 0) {
7143
+ throw new MultipleGitError(rejections)
7144
+ }
7120
7145
  }
7121
7146
  );
7122
7147
  }
@@ -7485,27 +7510,34 @@ async function updateWorkingDir(
7485
7510
 
7486
7511
  async function batchAllSettled(operationName, tasks, onProgress, batchSize) {
7487
7512
  const results = [];
7488
- try {
7489
- for (let i = 0; i < tasks.length; i += batchSize) {
7490
- const batch = tasks.slice(i, i + batchSize).map(task => task());
7491
- const batchResults = await Promise.allSettled(batch);
7492
- batchResults.forEach(result => {
7493
- if (result.status === 'fulfilled') results.push(result.value);
7494
- });
7495
- if (onProgress) {
7496
- await onProgress({
7497
- phase: 'Updating workdir',
7498
- loaded: i + batch.length,
7499
- total: tasks.length,
7500
- });
7513
+ const rejections = [];
7514
+ for (let i = 0; i < tasks.length; i += batchSize) {
7515
+ const batch = tasks.slice(i, i + batchSize).map(task => task());
7516
+ const batchResults = await Promise.allSettled(batch);
7517
+ batchResults.forEach(result => {
7518
+ if (result.status === 'fulfilled') {
7519
+ results.push(result.value);
7520
+ } else {
7521
+ rejections.push(result.reason);
7522
+ // eslint-disable-next-line no-console
7523
+ console.error(
7524
+ `[isomorphic-git ${operationName}] task rejected:`,
7525
+ result.reason?.stack ?? result.reason
7526
+ );
7501
7527
  }
7528
+ });
7529
+ if (onProgress) {
7530
+ await onProgress({
7531
+ phase: 'Updating workdir',
7532
+ loaded: i + batch.length,
7533
+ total: tasks.length,
7534
+ });
7502
7535
  }
7503
-
7504
- return results
7505
- } catch (error) {
7506
- console.error(`Error during ${operationName}: ${error}`);
7507
7536
  }
7508
7537
 
7538
+ if (rejections.length > 0) {
7539
+ throw new MultipleGitError(rejections)
7540
+ }
7509
7541
  return results
7510
7542
  }
7511
7543
 
@@ -9311,8 +9343,8 @@ function filterCapabilities(server, client) {
9311
9343
 
9312
9344
  const pkg = {
9313
9345
  name: 'isomorphic-git',
9314
- version: '1.37.4',
9315
- agent: 'git/isomorphic-git@1.37.4',
9346
+ version: '1.37.6',
9347
+ agent: 'git/isomorphic-git@1.37.6',
9316
9348
  };
9317
9349
 
9318
9350
  class FIFO {
package/index.js CHANGED
@@ -3362,6 +3362,13 @@ function readPackIndex({
3362
3362
  return p
3363
3363
  }
3364
3364
 
3365
+ async function shasumRange(
3366
+ buffer,
3367
+ { start = 0, end = buffer.length } = {}
3368
+ ) {
3369
+ return shasum(buffer.subarray(start, end))
3370
+ }
3371
+
3365
3372
  async function readObjectPacked({
3366
3373
  fs,
3367
3374
  cache,
@@ -3415,11 +3422,12 @@ async function readObjectPacked({
3415
3422
  )
3416
3423
  }
3417
3424
 
3418
- // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload
3419
- // This ensures true data integrity by verifying the entire packfile content
3420
- // Use subarray for zero-copy reading of large files
3421
- const payload = pack.subarray(0, -20);
3422
- const actualPayloadSha = await shasum(payload);
3425
+ // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload.
3426
+ // The Node package build swaps in a chunked implementation for large packs.
3427
+ const actualPayloadSha = await shasumRange(pack, {
3428
+ start: 0,
3429
+ end: pack.length - 20,
3430
+ });
3423
3431
  if (actualPayloadSha !== expectedShaFromIndex) {
3424
3432
  throw new InternalError(
3425
3433
  `Packfile payload corrupted: calculated ${actualPayloadSha} but expected ${expectedShaFromIndex}. The packfile may have been tampered with.`
@@ -7040,7 +7048,7 @@ async function _checkout({
7040
7048
  await GitIndexManager.acquire(
7041
7049
  { fs, gitdir, cache, allowUnmerged: true },
7042
7050
  async function (index) {
7043
- await Promise.all(
7051
+ const settled = await Promise.allSettled(
7044
7052
  ops
7045
7053
  .filter(
7046
7054
  ([method]) =>
@@ -7051,66 +7059,76 @@ async function _checkout({
7051
7059
  )
7052
7060
  .map(async function ([method, fullpath, oid, mode, chmod]) {
7053
7061
  const filepath = `${dir}/${fullpath}`;
7054
- try {
7055
- if (method !== 'create-index' && method !== 'mkdir-index') {
7056
- const { object } = await _readObject({
7057
- fs,
7058
- cache,
7059
- gitdir,
7060
- oid,
7061
- });
7062
- if (chmod) {
7063
- // Note: the mode option of fs.write only works when creating files,
7064
- // not updating them. Since the `fs` plugin doesn't expose `chmod` this
7065
- // is our only option.
7066
- await fs.rm(filepath);
7067
- }
7068
- if (mode === 0o100644) {
7069
- // regular file
7070
- await fs.write(filepath, object);
7071
- } else if (mode === 0o100755) {
7072
- // executable file
7073
- await fs.write(filepath, object, { mode: 0o777 });
7074
- } else if (mode === 0o120000) {
7075
- // symlink
7076
- await fs.writelink(filepath, object);
7077
- } else {
7078
- throw new InternalError(
7079
- `Invalid mode 0o${mode.toString(
7080
- 8
7081
- )} detected in blob ${oid}`
7082
- )
7083
- }
7084
- }
7085
-
7086
- const stats = await fs.lstat(filepath);
7087
- // We can't trust the executable bit returned by lstat on Windows,
7088
- // so we need to preserve this value from the TREE.
7089
- // TODO: Figure out how git handles this internally.
7090
- if (mode === 0o100755) {
7091
- stats.mode = 0o755;
7092
- }
7093
- // Submodules are present in the git index but use a unique mode different from trees
7094
- if (method === 'mkdir-index') {
7095
- stats.mode = 0o160000;
7096
- }
7097
- index.insert({
7098
- filepath: fullpath,
7099
- stats,
7062
+ if (method !== 'create-index' && method !== 'mkdir-index') {
7063
+ const { object } = await _readObject({
7064
+ fs,
7065
+ cache,
7066
+ gitdir,
7100
7067
  oid,
7101
7068
  });
7102
- if (onProgress) {
7103
- await onProgress({
7104
- phase: 'Updating workdir',
7105
- loaded: ++count,
7106
- total,
7107
- });
7069
+ if (chmod) {
7070
+ // Note: the mode option of fs.write only works when creating files,
7071
+ // not updating them. Since the `fs` plugin doesn't expose `chmod` this
7072
+ // is our only option.
7073
+ await fs.rm(filepath);
7074
+ }
7075
+ if (mode === 0o100644) {
7076
+ // regular file
7077
+ await fs.write(filepath, object);
7078
+ } else if (mode === 0o100755) {
7079
+ // executable file
7080
+ await fs.write(filepath, object, { mode: 0o777 });
7081
+ } else if (mode === 0o120000) {
7082
+ // symlink
7083
+ await fs.writelink(filepath, object);
7084
+ } else {
7085
+ throw new InternalError(
7086
+ `Invalid mode 0o${mode.toString(
7087
+ 8
7088
+ )} detected in blob ${oid}`
7089
+ )
7108
7090
  }
7109
- } catch (e) {
7110
- console.log(e);
7091
+ }
7092
+
7093
+ const stats = await fs.lstat(filepath);
7094
+ // We can't trust the executable bit returned by lstat on Windows,
7095
+ // so we need to preserve this value from the TREE.
7096
+ // TODO: Figure out how git handles this internally.
7097
+ if (mode === 0o100755) {
7098
+ stats.mode = 0o755;
7099
+ }
7100
+ // Submodules are present in the git index but use a unique mode different from trees
7101
+ if (method === 'mkdir-index') {
7102
+ stats.mode = 0o160000;
7103
+ }
7104
+ index.insert({
7105
+ filepath: fullpath,
7106
+ stats,
7107
+ oid,
7108
+ });
7109
+ if (onProgress) {
7110
+ await onProgress({
7111
+ phase: 'Updating workdir',
7112
+ loaded: ++count,
7113
+ total,
7114
+ });
7111
7115
  }
7112
7116
  })
7113
7117
  );
7118
+ const rejections = [];
7119
+ for (const result of settled) {
7120
+ if (result.status === 'rejected') {
7121
+ rejections.push(result.reason);
7122
+ // eslint-disable-next-line no-console
7123
+ console.error(
7124
+ '[isomorphic-git checkout] task rejected:',
7125
+ result.reason?.stack ?? result.reason
7126
+ );
7127
+ }
7128
+ }
7129
+ if (rejections.length > 0) {
7130
+ throw new MultipleGitError(rejections)
7131
+ }
7114
7132
  }
7115
7133
  );
7116
7134
  }
@@ -7479,27 +7497,34 @@ async function updateWorkingDir(
7479
7497
 
7480
7498
  async function batchAllSettled(operationName, tasks, onProgress, batchSize) {
7481
7499
  const results = [];
7482
- try {
7483
- for (let i = 0; i < tasks.length; i += batchSize) {
7484
- const batch = tasks.slice(i, i + batchSize).map(task => task());
7485
- const batchResults = await Promise.allSettled(batch);
7486
- batchResults.forEach(result => {
7487
- if (result.status === 'fulfilled') results.push(result.value);
7488
- });
7489
- if (onProgress) {
7490
- await onProgress({
7491
- phase: 'Updating workdir',
7492
- loaded: i + batch.length,
7493
- total: tasks.length,
7494
- });
7500
+ const rejections = [];
7501
+ for (let i = 0; i < tasks.length; i += batchSize) {
7502
+ const batch = tasks.slice(i, i + batchSize).map(task => task());
7503
+ const batchResults = await Promise.allSettled(batch);
7504
+ batchResults.forEach(result => {
7505
+ if (result.status === 'fulfilled') {
7506
+ results.push(result.value);
7507
+ } else {
7508
+ rejections.push(result.reason);
7509
+ // eslint-disable-next-line no-console
7510
+ console.error(
7511
+ `[isomorphic-git ${operationName}] task rejected:`,
7512
+ result.reason?.stack ?? result.reason
7513
+ );
7495
7514
  }
7515
+ });
7516
+ if (onProgress) {
7517
+ await onProgress({
7518
+ phase: 'Updating workdir',
7519
+ loaded: i + batch.length,
7520
+ total: tasks.length,
7521
+ });
7496
7522
  }
7497
-
7498
- return results
7499
- } catch (error) {
7500
- console.error(`Error during ${operationName}: ${error}`);
7501
7523
  }
7502
7524
 
7525
+ if (rejections.length > 0) {
7526
+ throw new MultipleGitError(rejections)
7527
+ }
7503
7528
  return results
7504
7529
  }
7505
7530
 
@@ -9305,8 +9330,8 @@ function filterCapabilities(server, client) {
9305
9330
 
9306
9331
  const pkg = {
9307
9332
  name: 'isomorphic-git',
9308
- version: '1.37.4',
9309
- agent: 'git/isomorphic-git@1.37.4',
9333
+ version: '1.37.6',
9334
+ agent: 'git/isomorphic-git@1.37.6',
9310
9335
  };
9311
9336
 
9312
9337
  class FIFO {