@teambit/merge-lanes 1.0.161 → 1.0.163

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.
@@ -40,7 +40,7 @@ function _lanes() {
40
40
  return data;
41
41
  }
42
42
  function _merging() {
43
- const data = _interopRequireDefault(require("@teambit/merging"));
43
+ const data = _interopRequireWildcard(require("@teambit/merging"));
44
44
  _merging = function () {
45
45
  return data;
46
46
  };
@@ -74,16 +74,16 @@ function _pMapSeries() {
74
74
  };
75
75
  return data;
76
76
  }
77
- function _scope() {
78
- const data = require("@teambit/scope");
79
- _scope = function () {
77
+ function _mergeVersion() {
78
+ const data = require("@teambit/legacy/dist/consumer/versions-ops/merge-version");
79
+ _mergeVersion = function () {
80
80
  return data;
81
81
  };
82
82
  return data;
83
83
  }
84
- function _scopeComponentsImporter() {
85
- const data = _interopRequireDefault(require("@teambit/legacy/dist/scope/component-ops/scope-components-importer"));
86
- _scopeComponentsImporter = function () {
84
+ function _scope() {
85
+ const data = require("@teambit/scope");
86
+ _scope = function () {
87
87
  return data;
88
88
  };
89
89
  return data;
@@ -206,13 +206,18 @@ class MergeLanesMain {
206
206
  this.importer = importer;
207
207
  this.checkout = checkout;
208
208
  }
209
-
210
- // eslint-disable-next-line complexity
211
- async mergeLane(laneName, options) {
209
+ async mergeLaneByCLI(laneName, options) {
212
210
  if (!this.workspace) {
213
211
  throw new (_bitError().BitError)(`unable to merge a lane outside of Bit workspace`);
214
212
  }
215
- const consumer = this.workspace.consumer;
213
+ const currentLaneId = this.workspace.consumer.getCurrentLaneId();
214
+ const otherLaneId = await this.workspace.consumer.getParsedLaneId(laneName);
215
+ return this.mergeLane(otherLaneId, currentLaneId, options);
216
+ }
217
+
218
+ // eslint-disable-next-line complexity
219
+ async mergeLane(otherLaneId, currentLaneId, options) {
220
+ const consumer = this.workspace?.consumer;
216
221
  const {
217
222
  mergeStrategy,
218
223
  noSnap,
@@ -231,18 +236,17 @@ class MergeLanesMain {
231
236
  skipFetch,
232
237
  excludeNonLaneComps
233
238
  } = options;
234
- const currentLaneId = consumer.getCurrentLaneId();
239
+ const legacyScope = this.scope.legacyScope;
235
240
  if (tag && !currentLaneId.isDefault()) {
236
241
  throw new (_bitError().BitError)(`--tag only possible when on main. currently checked out to ${currentLaneId.toString()}`);
237
242
  }
238
- const otherLaneId = await consumer.getParsedLaneId(laneName);
239
243
  if (otherLaneId.isEqual(currentLaneId)) {
240
244
  throw new (_bitError().BitError)(`unable to merge lane "${otherLaneId.toString()}", you're already at this lane. to get updates, simply run "bit checkout head"`);
241
245
  }
242
246
  if (resolveUnrelated && currentLaneId.isDefault()) {
243
247
  throw new (_bitError().BitError)(`unable to resolve unrelated when on main. switch to ${otherLaneId.toString()} and run "bit lane merge main --resolve-unrelated"`);
244
248
  }
245
- const currentLane = currentLaneId.isDefault() ? null : await consumer.scope.loadLane(currentLaneId);
249
+ const currentLane = currentLaneId.isDefault() ? null : await legacyScope.loadLane(currentLaneId);
246
250
  const isDefaultLane = otherLaneId.isDefault();
247
251
  if (isDefaultLane) {
248
252
  if (!skipFetch) {
@@ -253,13 +257,13 @@ class MergeLanesMain {
253
257
  }
254
258
  let laneToFetchArtifactsFrom;
255
259
  const getOtherLane = async () => {
256
- let lane = await consumer.scope.loadLane(otherLaneId);
260
+ let lane = await legacyScope.loadLane(otherLaneId);
257
261
  const shouldFetch = !lane || !skipFetch && !lane.isNew;
258
262
  if (shouldFetch) {
259
263
  // don't assign `lane` to the result of this command. otherwise, if you have local snaps, it'll ignore them and use the remote-lane.
260
264
  const otherLane = await this.lanes.fetchLaneWithItsComponents(otherLaneId);
261
265
  laneToFetchArtifactsFrom = otherLane;
262
- lane = await consumer.scope.loadLane(otherLaneId);
266
+ lane = await legacyScope.loadLane(otherLaneId);
263
267
  }
264
268
  return lane;
265
269
  };
@@ -286,9 +290,9 @@ class MergeLanesMain {
286
290
  mergeStrategy
287
291
  }, currentLane, otherLane);
288
292
  if (pattern) {
289
- const componentIds = await this.workspace.resolveMultipleComponentIds(idsToMerge);
290
- const compIdsFromPattern = await this.workspace.filterIdsFromPoolIdsByPattern(pattern, componentIds);
291
- allComponentsStatus = await filterComponentsStatus(allComponentsStatus, compIdsFromPattern, idsToMerge, this.workspace, includeDeps, otherLane || undefined, shouldSquash);
293
+ const componentIds = idsToMerge;
294
+ const compIdsFromPattern = await (this.workspace || this.scope).filterIdsFromPoolIdsByPattern(pattern, componentIds);
295
+ allComponentsStatus = await filterComponentsStatus(allComponentsStatus, compIdsFromPattern, idsToMerge, legacyScope, includeDeps, otherLane || undefined, shouldSquash);
292
296
  idsToMerge.forEach(bitId => {
293
297
  if (!allComponentsStatus.find(c => c.id.isEqualWithoutVersion(bitId))) {
294
298
  allComponentsStatus.push({
@@ -299,10 +303,10 @@ class MergeLanesMain {
299
303
  }
300
304
  });
301
305
  }
302
- if (existingOnWorkspaceOnly) {
306
+ if (existingOnWorkspaceOnly && this.workspace) {
303
307
  const workspaceIds = await this.workspace.listIds();
304
308
  const compIdsFromPattern = workspaceIds.filter(id => allComponentsStatus.find(c => c.id.isEqualWithoutVersion(id)));
305
- allComponentsStatus = await filterComponentsStatus(allComponentsStatus, compIdsFromPattern, idsToMerge, this.workspace, includeDeps, otherLane || undefined, shouldSquash);
309
+ allComponentsStatus = await filterComponentsStatus(allComponentsStatus, compIdsFromPattern, idsToMerge, legacyScope, includeDeps, otherLane || undefined, shouldSquash);
306
310
  idsToMerge.forEach(bitId => {
307
311
  if (!allComponentsStatus.find(c => c.id.isEqualWithoutVersion(bitId))) {
308
312
  allComponentsStatus.push({
@@ -315,14 +319,14 @@ class MergeLanesMain {
315
319
  }
316
320
  (0, _checkout().throwForFailures)(allComponentsStatus);
317
321
  if (shouldSquash) {
318
- await squashSnaps(allComponentsStatus, otherLaneId, consumer);
322
+ await squashSnaps(allComponentsStatus, currentLaneId, otherLaneId, legacyScope);
319
323
  }
320
324
  if (laneToFetchArtifactsFrom) {
321
325
  const ids = allComponentsStatus.map(c => c.id);
322
326
  await this.importer.importHeadArtifactsFromLane(laneToFetchArtifactsFrom, ids, true);
323
327
  }
324
- const lastMerged = new (_lastMerged().LastMerged)(this.scope, consumer, this.logger);
325
- const snapshot = await lastMerged.takeSnapshot(currentLane);
328
+ const lastMerged = consumer ? new (_lastMerged().LastMerged)(this.scope, consumer, this.logger) : undefined;
329
+ const snapshot = await lastMerged?.takeSnapshot(currentLane);
326
330
  const mergeResults = await this.merging.mergeSnaps({
327
331
  mergeStrategy,
328
332
  allComponentsStatus,
@@ -334,7 +338,7 @@ class MergeLanesMain {
334
338
  build,
335
339
  skipDependencyInstallation
336
340
  });
337
- await lastMerged.persistSnapshot(snapshot);
341
+ if (snapshot) await lastMerged?.persistSnapshot(snapshot);
338
342
  const mergedSuccessfully = !mergeResults.failedComponents || mergeResults.failedComponents.length === 0 || mergeResults.failedComponents.every(failedComponent => failedComponent.unchangedLegitimately);
339
343
  let deleteResults = {};
340
344
  if (!keepReadme && otherLane && otherLane.readmeComponent && mergedSuccessfully) {
@@ -348,7 +352,7 @@ class MergeLanesMain {
348
352
  };
349
353
  }
350
354
  const configMergeResults = allComponentsStatus.map(c => c.configMergeResult);
351
- await this.workspace.consumer.onDestroy(`lane-merge (${otherLaneId.name})`);
355
+ await this.workspace?.consumer.onDestroy(`lane-merge (${otherLaneId.name})`);
352
356
  return {
353
357
  mergeResults,
354
358
  deleteResults,
@@ -408,19 +412,20 @@ class MergeLanesMain {
408
412
  if (this.workspace) {
409
413
  throw new (_bitError().BitError)(`unable to run this command from a workspace, please create a new bare-scope and run it from there`);
410
414
  }
411
- const fromLaneId = _laneId().LaneId.parse(fromLane);
412
- const fromLaneObj = await this.lanes.importLaneObject(fromLaneId);
415
+ const fromLaneId = await this.lanes.parseLaneId(fromLane);
416
+ const fromLaneObj = fromLaneId.isDefault() ? undefined : await this.lanes.importLaneObject(fromLaneId);
413
417
  const toLaneId = toLane === _laneId().DEFAULT_LANE ? this.lanes.getDefaultLaneId() : _laneId().LaneId.parse(toLane);
414
418
  const toLaneObj = toLaneId.isDefault() ? undefined : await this.lanes.importLaneObject(toLaneId);
415
- const fromLaneBitIds = fromLaneObj.toBitIds();
419
+ const fromLaneBitIds = fromLaneObj?.toComponentIds();
420
+ const toLaneCompIds = toLaneObj?.toComponentIds();
421
+ const laneIds = fromLaneBitIds || toLaneCompIds; // one of them must be defined.
416
422
  const getIdsToMerge = async () => {
417
- if (!options.pattern) return fromLaneBitIds;
418
- const laneCompIds = await this.scope.resolveMultipleComponentIds(fromLaneBitIds);
419
- const ids = await this.scope.filterIdsFromPoolIdsByPattern(options.pattern, laneCompIds);
423
+ if (!options.pattern) return laneIds;
424
+ const ids = await this.scope.filterIdsFromPoolIdsByPattern(options.pattern, laneIds);
420
425
  return _componentId().ComponentIdList.fromArray(ids.map(id => id));
421
426
  };
422
427
  const idsToMerge = await getIdsToMerge();
423
- const scopeComponentsImporter = _scopeComponentsImporter().default.getInstance(this.scope.legacyScope);
428
+ const scopeComponentsImporter = this.scope.legacyScope.scopeImporter;
424
429
  await scopeComponentsImporter.importWithoutDeps(idsToMerge.toVersionLatest(), {
425
430
  cache: false,
426
431
  lane: fromLaneObj,
@@ -437,7 +442,77 @@ class MergeLanesMain {
437
442
  includeVersionHistory: true,
438
443
  reason: `of "to" lane (${toLaneId.name}) for lane-merge to get all version-history`
439
444
  });
440
- await this.importer.importHeadArtifactsFromLane(fromLaneObj, undefined, true);
445
+ await this.importer.importHeadArtifactsFromLane(fromLaneObj || toLaneObj, undefined, true);
446
+ const shouldSquash = !toLaneObj && !options.noSquash; // only when merging to main we squash.
447
+
448
+ const exportIfNeeded = async (idsToExport, laneToExport) => {
449
+ if (!options.push) return [];
450
+ const compIdsList = _componentId().ComponentIdList.fromArray(idsToExport);
451
+ const {
452
+ exported
453
+ } = await this.exporter.exportMany({
454
+ scope: this.scope.legacyScope,
455
+ ids: compIdsList,
456
+ idsWithFutureScope: compIdsList,
457
+ laneObject: laneToExport,
458
+ allVersions: false,
459
+ // no need to export anything else other than the head. the normal calculation of what to export won't apply here
460
+ // as it is done from the scope.
461
+ exportHeadsOnly: shouldSquash,
462
+ // all artifacts must be pushed. they're all considered "external" in this case, because it's running from a
463
+ // bare-scope, but we don't want to ignore them, otherwise, they'll be missing from the component-scopes.
464
+ ignoreMissingExternalArtifacts: false,
465
+ exportOrigin: 'lane-merge'
466
+ });
467
+ return exported;
468
+ };
469
+ if (fromLaneId.isDefault()) {
470
+ // current -> target (to)
471
+ // other -> source (from)
472
+ options.mergeStrategy = 'manual';
473
+ options.excludeNonLaneComps = true;
474
+ options.skipDependencyInstallation = true;
475
+ this.scope.legacyScope.setCurrentLaneId(toLaneId);
476
+ this.scope.legacyScope.scopeImporter.shouldOnlyFetchFromCurrentLane = true;
477
+ const result = await this.mergeLane(fromLaneId, toLaneId, options);
478
+ const {
479
+ mergeSnapResults,
480
+ leftUnresolvedConflicts,
481
+ failedComponents,
482
+ components
483
+ } = result.mergeResults;
484
+ this.logger.debug(`found the following config conflicts: ${result.configMergeResults.map(c => `\n${c.compIdStr}\n${c.generateMergeConflictFile()}`).join('\n')}`);
485
+ const componentsWithConfigConflicts = result.configMergeResults.filter(c => c.hasConflicts()).map(c => c.compIdStr);
486
+ const conflicts = [];
487
+ const merged = [];
488
+ components?.forEach(c => {
489
+ const files = Object.keys(c.filesStatus).filter(f => c.filesStatus[f] === _mergeVersion().FileStatus.manual || c.filesStatus[f] === _mergeVersion().FileStatus.binaryConflict);
490
+ const config = componentsWithConfigConflicts.includes(c.id.toStringWithoutVersion());
491
+ if (files.length || config) {
492
+ conflicts.push({
493
+ id: c.id,
494
+ files,
495
+ config
496
+ });
497
+ } else merged.push(c.id);
498
+ });
499
+ const snappedIds = mergeSnapResults?.snappedComponents.map(c => c.id) || [];
500
+ const laneToExport = await this.lanes.loadLane(toLaneId); // needs to be loaded again after the merge as it changed
501
+ const exportedIds = leftUnresolvedConflicts ? [] : await exportIfNeeded(idsToMerge.map(id => id.changeVersion(undefined)), laneToExport);
502
+ return {
503
+ mergedNow: merged,
504
+ mergedPreviously: failedComponents?.filter(({
505
+ unchangedMessage
506
+ }) => unchangedMessage === _merging().compIsAlreadyMergedMsg).map(c => c.id) || [],
507
+ exportedIds,
508
+ unmerged: failedComponents?.map(c => ({
509
+ id: c.id,
510
+ reason: c.unchangedMessage
511
+ })) || [],
512
+ conflicts,
513
+ snappedIds
514
+ };
515
+ }
441
516
  await this.throwIfNotUpToDate(fromLaneId, toLaneId);
442
517
  const repo = this.scope.legacyScope.objects;
443
518
  // loop through all components, make sure they're all ahead of main (it might not be on main yet).
@@ -445,7 +520,6 @@ class MergeLanesMain {
445
520
  // then, change the component object head to point to this changed version
446
521
  const mergedPreviously = [];
447
522
  const mergedNow = [];
448
- const shouldSquash = !toLaneObj && !options.noSquash; // only when merging to main we squash.
449
523
  const log = await getLogForSquash(fromLaneId);
450
524
  const bitObjectsPerComp = await (0, _pMapSeries().default)(idsToMerge, async id => {
451
525
  const modelComponent = await this.scope.legacyScope.getModelComponent(id);
@@ -487,32 +561,16 @@ class MergeLanesMain {
487
561
  const bitObjectsFlat = bitObjects.flat();
488
562
  if (toLaneObj) bitObjectsFlat.push(toLaneObj);
489
563
  await repo.writeObjectsToTheFS(bitObjectsFlat);
490
- let exportedIds = [];
491
- if (options.push) {
492
- const ids = (0, _lodash().compact)(bitObjectsPerComp).map(b => b.id);
493
- const bitIds = _componentId().ComponentIdList.fromArray(ids);
494
- const {
495
- exported
496
- } = await this.exporter.exportMany({
497
- scope: this.scope.legacyScope,
498
- ids: shouldSquash ? bitIds : new (_componentId().ComponentIdList)(),
499
- idsWithFutureScope: shouldSquash ? bitIds : new (_componentId().ComponentIdList)(),
500
- laneObject: toLaneObj,
501
- allVersions: false,
502
- // no need to export anything else other than the head. the normal calculation of what to export won't apply here
503
- // as it is done from the scope.
504
- exportHeadsOnly: shouldSquash,
505
- // all artifacts must be pushed. they're all considered "external" in this case, because it's running from a
506
- // bare-scope, but we don't want to ignore them, otherwise, they'll be missing from the component-scopes.
507
- ignoreMissingExternalArtifacts: false,
508
- exportOrigin: 'lane-merge'
509
- });
510
- exportedIds = exported.map(id => id.toString());
511
- }
564
+ const ids = (0, _lodash().compact)(bitObjectsPerComp).map(b => b.id);
565
+ const exportedIds = await exportIfNeeded(ids, toLaneObj);
512
566
  return {
513
- mergedPreviously: mergedPreviously.map(id => id.toString()),
514
- mergedNow: mergedNow.map(id => id.toString()),
515
- exportedIds
567
+ mergedPreviously,
568
+ mergedNow,
569
+ exportedIds,
570
+ unmerged: mergedPreviously.map(id => ({
571
+ id,
572
+ reason: 'already merged'
573
+ }))
516
574
  };
517
575
  }
518
576
  async throwIfNotUpToDate(fromLaneId, toLaneId) {
@@ -539,7 +597,7 @@ exports.MergeLanesMain = MergeLanesMain;
539
597
  _defineProperty(MergeLanesMain, "slots", []);
540
598
  _defineProperty(MergeLanesMain, "dependencies", [_lanes().LanesAspect, _cli().CLIAspect, _workspace().default, _merging().default, _logger().LoggerAspect, _remove().RemoveAspect, _scope().ScopeAspect, _export().ExportAspect, _importer().default, _checkout().default, _globalConfig().default]);
541
599
  _defineProperty(MergeLanesMain, "runtime", _cli().MainRuntime);
542
- async function filterComponentsStatus(allComponentsStatus, compIdsToKeep, allBitIds, workspace, includeDeps = false, otherLane,
600
+ async function filterComponentsStatus(allComponentsStatus, compIdsToKeep, allBitIds, legacyScope, includeDeps = false, otherLane,
543
601
  // lane that gets merged into the current lane. if not provided, it's main that gets merged into the current lane
544
602
  shouldSquash) {
545
603
  const bitIdsFromPattern = _componentId().ComponentIdList.fromArray(compIdsToKeep);
@@ -571,7 +629,7 @@ shouldSquash) {
571
629
  if (!targetVersions.length) {
572
630
  return undefined;
573
631
  }
574
- const modelComponent = await workspace.consumer.scope.getModelComponent(compId);
632
+ const modelComponent = await legacyScope.getModelComponent(compId);
575
633
  if (shouldSquash) {
576
634
  // no need to check all versions, we merge only the head
577
635
  const headOnTarget = otherLane ? otherLane.getComponent(compId)?.head : modelComponent.head;
@@ -589,7 +647,7 @@ shouldSquash) {
589
647
 
590
648
  // all these versions needs to be imported to load them later and check whether they have dependencies on the target lane
591
649
  const toImport = (0, _lodash().compact)(versionsToCheckPerId).map(c => c.targetVersions.map(v => c.compId.changeVersion(v.toString()))).flat();
592
- await workspace.consumer.scope.scopeImporter.importWithoutDeps(_componentId().ComponentIdList.fromArray(toImport), {
650
+ await legacyScope.scopeImporter.importWithoutDeps(_componentId().ComponentIdList.fromArray(toImport), {
593
651
  lane: otherLane,
594
652
  cache: true,
595
653
  includeVersionHistory: false,
@@ -601,7 +659,7 @@ shouldSquash) {
601
659
  modelComponent
602
660
  }) => {
603
661
  await (0, _pMapSeries().default)(targetVersions, async remoteVersion => {
604
- const versionObj = await modelComponent.loadVersion(remoteVersion.toString(), workspace.consumer.scope.objects);
662
+ const versionObj = await modelComponent.loadVersion(remoteVersion.toString(), legacyScope.objects);
605
663
  const flattenedDeps = versionObj.getAllFlattenedDependencies();
606
664
  const depsNotIncludeInPattern = flattenedDeps.filter(id => bitIdsNotFromPattern.find(bitId => bitId.isEqualWithoutVersion(id)));
607
665
  if (!depsNotIncludeInPattern.length) {
@@ -609,7 +667,7 @@ shouldSquash) {
609
667
  }
610
668
  const depsOnLane = [];
611
669
  await Promise.all(depsNotIncludeInPattern.map(async dep => {
612
- const isOnLane = await workspace.consumer.scope.isIdOnLane(dep, otherLane);
670
+ const isOnLane = await legacyScope.isIdOnLane(dep, otherLane);
613
671
  if (isOnLane) {
614
672
  depsOnLane.push(dep);
615
673
  }
@@ -656,8 +714,8 @@ async function getLogForSquash(otherLaneId) {
656
714
  });
657
715
  return log;
658
716
  }
659
- async function squashSnaps(allComponentsStatus, otherLaneId, consumer) {
660
- const currentLaneName = consumer.getCurrentLaneId().name;
717
+ async function squashSnaps(allComponentsStatus, currentLaneId, otherLaneId, scope) {
718
+ const currentLaneName = currentLaneId.name;
661
719
  const succeededComponents = allComponentsStatus.filter(c => !c.unchangedMessage);
662
720
  const log = await getLogForSquash(otherLaneId);
663
721
  await Promise.all(succeededComponents.map(async ({
@@ -668,12 +726,12 @@ async function squashSnaps(allComponentsStatus, otherLaneId, consumer) {
668
726
  if (!divergeData) {
669
727
  throw new Error(`unable to squash. divergeData is missing from ${id.toString()}`);
670
728
  }
671
- const modifiedComp = await squashOneComp(currentLaneName, otherLaneId, id, divergeData, log, consumer.scope, componentFromModel);
729
+ const modifiedComp = await squashOneComp(currentLaneName, otherLaneId, id, divergeData, log, scope, componentFromModel);
672
730
  if (modifiedComp) {
673
- consumer.scope.objects.add(modifiedComp);
674
- const modelComponent = await consumer.scope.getModelComponent(id);
675
- const versionHistory = await modelComponent.updateRebasedVersionHistory(consumer.scope.objects, [modifiedComp]);
676
- if (versionHistory) consumer.scope.objects.add(versionHistory);
731
+ scope.objects.add(modifiedComp);
732
+ const modelComponent = await scope.getModelComponent(id);
733
+ const versionHistory = await modelComponent.updateRebasedVersionHistory(scope.objects, [modifiedComp]);
734
+ if (versionHistory) scope.objects.add(versionHistory);
677
735
  }
678
736
  }));
679
737
  }