isomorphic-git 1.41.5 → 1.41.7

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
@@ -3651,6 +3651,10 @@ async function _readObject({
3651
3651
  oid,
3652
3652
  format = 'content',
3653
3653
  }) {
3654
+ if (!['deflated', 'wrapped', 'content'].includes(format)) {
3655
+ throw new InternalError(`invalid requested format "${format}"`)
3656
+ }
3657
+
3654
3658
  // Curry the current read method so that the packfile un-deltification
3655
3659
  // process can acquire external ref-deltas.
3656
3660
  const getExternalRefDelta = oid => _readObject({ fs, cache, gitdir, oid });
@@ -3710,11 +3714,7 @@ async function _readObject({
3710
3714
  result.object = object;
3711
3715
  result.format = 'content';
3712
3716
 
3713
- if (format === 'content') {
3714
- return result
3715
- }
3716
-
3717
- throw new InternalError(`invalid requested format "${format}"`)
3717
+ return result
3718
3718
  }
3719
3719
 
3720
3720
  class AlreadyExistsError extends BaseError {
@@ -9728,8 +9728,8 @@ function filterCapabilities(server, client) {
9728
9728
 
9729
9729
  const pkg = {
9730
9730
  name: 'isomorphic-git',
9731
- version: '1.41.5',
9732
- agent: 'git/isomorphic-git@1.41.5',
9731
+ version: '1.41.7',
9732
+ agent: 'git/isomorphic-git@1.41.7',
9733
9733
  };
9734
9734
 
9735
9735
  class FIFO {
@@ -11225,44 +11225,70 @@ async function _findMergeBase({ fs, cache, gitdir, oids }) {
11225
11225
  // and computing virtual merge bases is just too much for me to fathom right now.
11226
11226
 
11227
11227
  // If we start N independent walkers, one at each of the given `oids`, and walk backwards
11228
- // through ancestors, eventually we'll discover a commit where each one of these N walkers
11229
- // has passed through. So we just need to keep track of which walkers have visited each commit
11230
- // until we find a commit that N distinct walkers has visited.
11228
+ // through ancestors, eventually we'll discover commits where each one of these N walkers
11229
+ // has passed through. We cannot stop at the first common commit because a better common
11230
+ // ancestor may still be present in another branch of the graph.
11231
11231
  const visits = {};
11232
11232
  const passes = oids.length;
11233
+ const common = new Set();
11234
+ const parents = new Map();
11235
+ const shallows = await GitShallowManager.read({ fs, gitdir });
11236
+ const readParents = async oid => {
11237
+ if (parents.has(oid)) return parents.get(oid)
11238
+ const { object, type } = await _readObject({ fs, cache, gitdir, oid });
11239
+ if (type !== 'commit') {
11240
+ throw new ObjectTypeError(oid, type, 'commit')
11241
+ }
11242
+ const commit = GitCommit.from(object);
11243
+ const { parent } = commit.parseHeaders();
11244
+ const result = shallows.has(oid) ? [] : parent;
11245
+ parents.set(oid, result);
11246
+ return result
11247
+ };
11233
11248
  let heads = oids.map((oid, index) => ({ index, oid }));
11234
11249
  while (heads.length) {
11235
11250
  // Count how many times we've passed each commit
11236
- const result = new Set();
11237
11251
  for (const { oid, index } of heads) {
11252
+ await readParents(oid);
11238
11253
  if (!visits[oid]) visits[oid] = new Set();
11239
11254
  visits[oid].add(index);
11240
11255
  if (visits[oid].size === passes) {
11241
- result.add(oid);
11256
+ common.add(oid);
11242
11257
  }
11243
11258
  }
11244
- if (result.size > 0) {
11245
- return [...result]
11246
- }
11247
- // We haven't found a common ancestor yet
11248
11259
  const newheads = new Map();
11249
11260
  for (const { oid, index } of heads) {
11250
- try {
11251
- const { object } = await _readObject({ fs, cache, gitdir, oid });
11252
- const commit = GitCommit.from(object);
11253
- const { parent } = commit.parseHeaders();
11254
- for (const oid of parent) {
11255
- if (!visits[oid] || !visits[oid].has(index)) {
11256
- newheads.set(oid + ':' + index, { oid, index });
11257
- }
11261
+ // Parents of a common commit cannot be better merge bases.
11262
+ if (common.has(oid)) continue
11263
+ for (const parent of await readParents(oid)) {
11264
+ if (!visits[parent] || !visits[parent].has(index)) {
11265
+ newheads.set(parent + ':' + index, { oid: parent, index });
11258
11266
  }
11259
- } catch (err) {
11260
- // do nothing
11261
11267
  }
11262
11268
  }
11263
11269
  heads = Array.from(newheads.values());
11264
11270
  }
11265
- return []
11271
+
11272
+ if (common.size < 2) return [...common]
11273
+
11274
+ // A merge base is only "best" when it is not an ancestor of another
11275
+ // common ancestor. This also keeps independent criss-cross bases.
11276
+ const redundant = new Set();
11277
+ for (const oid of common) {
11278
+ const ancestors = [...(await readParents(oid))];
11279
+ const seen = new Set();
11280
+ while (ancestors.length) {
11281
+ const ancestor = ancestors.pop();
11282
+ if (seen.has(ancestor)) continue
11283
+ seen.add(ancestor);
11284
+ if (common.has(ancestor)) {
11285
+ redundant.add(ancestor);
11286
+ } else {
11287
+ ancestors.push(...(await readParents(ancestor)));
11288
+ }
11289
+ }
11290
+ }
11291
+ return [...common].filter(oid => !redundant.has(oid))
11266
11292
  }
11267
11293
 
11268
11294
  // @ts-check
package/index.js CHANGED
@@ -3638,6 +3638,10 @@ async function _readObject({
3638
3638
  oid,
3639
3639
  format = 'content',
3640
3640
  }) {
3641
+ if (!['deflated', 'wrapped', 'content'].includes(format)) {
3642
+ throw new InternalError(`invalid requested format "${format}"`)
3643
+ }
3644
+
3641
3645
  // Curry the current read method so that the packfile un-deltification
3642
3646
  // process can acquire external ref-deltas.
3643
3647
  const getExternalRefDelta = oid => _readObject({ fs, cache, gitdir, oid });
@@ -3697,11 +3701,7 @@ async function _readObject({
3697
3701
  result.object = object;
3698
3702
  result.format = 'content';
3699
3703
 
3700
- if (format === 'content') {
3701
- return result
3702
- }
3703
-
3704
- throw new InternalError(`invalid requested format "${format}"`)
3704
+ return result
3705
3705
  }
3706
3706
 
3707
3707
  class AlreadyExistsError extends BaseError {
@@ -9715,8 +9715,8 @@ function filterCapabilities(server, client) {
9715
9715
 
9716
9716
  const pkg = {
9717
9717
  name: 'isomorphic-git',
9718
- version: '1.41.5',
9719
- agent: 'git/isomorphic-git@1.41.5',
9718
+ version: '1.41.7',
9719
+ agent: 'git/isomorphic-git@1.41.7',
9720
9720
  };
9721
9721
 
9722
9722
  class FIFO {
@@ -11212,44 +11212,70 @@ async function _findMergeBase({ fs, cache, gitdir, oids }) {
11212
11212
  // and computing virtual merge bases is just too much for me to fathom right now.
11213
11213
 
11214
11214
  // If we start N independent walkers, one at each of the given `oids`, and walk backwards
11215
- // through ancestors, eventually we'll discover a commit where each one of these N walkers
11216
- // has passed through. So we just need to keep track of which walkers have visited each commit
11217
- // until we find a commit that N distinct walkers has visited.
11215
+ // through ancestors, eventually we'll discover commits where each one of these N walkers
11216
+ // has passed through. We cannot stop at the first common commit because a better common
11217
+ // ancestor may still be present in another branch of the graph.
11218
11218
  const visits = {};
11219
11219
  const passes = oids.length;
11220
+ const common = new Set();
11221
+ const parents = new Map();
11222
+ const shallows = await GitShallowManager.read({ fs, gitdir });
11223
+ const readParents = async oid => {
11224
+ if (parents.has(oid)) return parents.get(oid)
11225
+ const { object, type } = await _readObject({ fs, cache, gitdir, oid });
11226
+ if (type !== 'commit') {
11227
+ throw new ObjectTypeError(oid, type, 'commit')
11228
+ }
11229
+ const commit = GitCommit.from(object);
11230
+ const { parent } = commit.parseHeaders();
11231
+ const result = shallows.has(oid) ? [] : parent;
11232
+ parents.set(oid, result);
11233
+ return result
11234
+ };
11220
11235
  let heads = oids.map((oid, index) => ({ index, oid }));
11221
11236
  while (heads.length) {
11222
11237
  // Count how many times we've passed each commit
11223
- const result = new Set();
11224
11238
  for (const { oid, index } of heads) {
11239
+ await readParents(oid);
11225
11240
  if (!visits[oid]) visits[oid] = new Set();
11226
11241
  visits[oid].add(index);
11227
11242
  if (visits[oid].size === passes) {
11228
- result.add(oid);
11243
+ common.add(oid);
11229
11244
  }
11230
11245
  }
11231
- if (result.size > 0) {
11232
- return [...result]
11233
- }
11234
- // We haven't found a common ancestor yet
11235
11246
  const newheads = new Map();
11236
11247
  for (const { oid, index } of heads) {
11237
- try {
11238
- const { object } = await _readObject({ fs, cache, gitdir, oid });
11239
- const commit = GitCommit.from(object);
11240
- const { parent } = commit.parseHeaders();
11241
- for (const oid of parent) {
11242
- if (!visits[oid] || !visits[oid].has(index)) {
11243
- newheads.set(oid + ':' + index, { oid, index });
11244
- }
11248
+ // Parents of a common commit cannot be better merge bases.
11249
+ if (common.has(oid)) continue
11250
+ for (const parent of await readParents(oid)) {
11251
+ if (!visits[parent] || !visits[parent].has(index)) {
11252
+ newheads.set(parent + ':' + index, { oid: parent, index });
11245
11253
  }
11246
- } catch (err) {
11247
- // do nothing
11248
11254
  }
11249
11255
  }
11250
11256
  heads = Array.from(newheads.values());
11251
11257
  }
11252
- return []
11258
+
11259
+ if (common.size < 2) return [...common]
11260
+
11261
+ // A merge base is only "best" when it is not an ancestor of another
11262
+ // common ancestor. This also keeps independent criss-cross bases.
11263
+ const redundant = new Set();
11264
+ for (const oid of common) {
11265
+ const ancestors = [...(await readParents(oid))];
11266
+ const seen = new Set();
11267
+ while (ancestors.length) {
11268
+ const ancestor = ancestors.pop();
11269
+ if (seen.has(ancestor)) continue
11270
+ seen.add(ancestor);
11271
+ if (common.has(ancestor)) {
11272
+ redundant.add(ancestor);
11273
+ } else {
11274
+ ancestors.push(...(await readParents(ancestor)));
11275
+ }
11276
+ }
11277
+ }
11278
+ return [...common].filter(oid => !redundant.has(oid))
11253
11279
  }
11254
11280
 
11255
11281
  // @ts-check