@teambit/lanes
Version:
187 lines (184 loc) • 9.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.LaneSwitcher = void 0;
function _laneId() {
const data = require("@teambit/lane-id");
_laneId = function () {
return data;
};
return data;
}
function _componentId() {
const data = require("@teambit/component-id");
_componentId = function () {
return data;
};
return data;
}
function _bitError() {
const data = require("@teambit/bit-error");
_bitError = function () {
return data;
};
return data;
}
function _lanesModules() {
const data = require("@teambit/lanes.modules.create-lane");
_lanesModules = function () {
return data;
};
return data;
}
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
class LaneSwitcher {
// populated by `this.populateSwitchProps()`, if default-lane, it's undefined
constructor(workspace, logger, switchProps, checkoutProps, lanes) {
this.workspace = workspace;
this.logger = logger;
this.switchProps = switchProps;
this.checkoutProps = checkoutProps;
this.lanes = lanes;
_defineProperty(this, "consumer", void 0);
_defineProperty(this, "laneIdToSwitchTo", void 0);
// populated by `this.populateSwitchProps()`
_defineProperty(this, "laneToSwitchTo", void 0);
this.consumer = this.workspace.consumer;
}
async switch() {
this.logger.setStatusLine(`switching lanes`);
if (this.workspace.isOnMain()) {
await (0, _lanesModules().throwForStagedComponents)(this.workspace);
}
await this.populateSwitchProps();
const bitMapIds = this.workspace.consumer.bitmapIdsFromCurrentLaneIncludeRemoved;
const idsToSwitch = this.switchProps.ids || [];
const ids = idsToSwitch.map(id => {
const bitMapId = bitMapIds.searchWithoutVersion(id);
return bitMapId || id;
});
const checkoutProps = _objectSpread(_objectSpread({}, this.checkoutProps), {}, {
ids,
allowAddingComponentsFromScope: true,
versionPerId: await this.workspace.resolveMultipleComponentIds(idsToSwitch),
lane: this.laneToSwitchTo
});
const results = await this.lanes.checkout.checkout(checkoutProps);
await this.saveLanesData();
await this.consumer.onDestroy('lane-switch');
return results;
}
async populateSwitchProps() {
const laneId = await this.consumer.scope.lanes.parseLaneIdFromString(this.switchProps.laneName);
const skipFetch = this.switchProps.skipFetch;
const localLane = await this.consumer.scope.loadLane(laneId);
const getMainIds = async () => {
if (!skipFetch) {
const allIds = this.workspace.listIds();
try {
await this.workspace.scope.legacyScope.scopeImporter.importWithoutDeps(allIds, {
cache: false,
ignoreMissingHead: true
});
} catch (err) {
this.logger.consoleWarning(`failed to fetch the latest from the remote, falling back to local state. ${err.message}\nuse --skip-fetch to skip this step.`);
}
}
return this.consumer.getIdsOfDefaultLane();
};
const mainIds = await getMainIds();
if (laneId.isDefault()) {
await this.populatePropsAccordingToDefaultLane();
this.switchProps.ids = mainIds;
} else {
let laneIds;
if (skipFetch) {
if (!localLane) {
throw new (_bitError().BitError)(`unable to switch to lane "${laneId.toString()}" with --skip-fetch: the lane doesn't exist in the local scope. run without --skip-fetch to fetch it from the remote.`);
}
laneIds = this.populatePropsAccordingToLocalLane(localLane);
} else {
try {
laneIds = await this.populatePropsAccordingToRemoteLane(laneId);
} catch (err) {
if (!localLane) throw err;
this.logger.consoleWarning(`failed to fetch lane "${laneId.toString()}" from the remote, falling back to local state. ${err.message}\nuse --skip-fetch to skip this step.`);
laneIds = this.populatePropsAccordingToLocalLane(localLane);
}
}
const idsOnLaneOnly = laneIds.filter(id => !mainIds.find(i => i.isEqualWithoutVersion(id)));
const idsOnMainOnly = mainIds.filter(id => !laneIds.find(i => i.isEqualWithoutVersion(id)));
this.switchProps.ids = [...idsOnMainOnly, ...laneIds];
this.switchProps.laneBitIds = idsOnLaneOnly;
}
await this.populateIdsAccordingToPattern();
}
async populateIdsAccordingToPattern() {
if (!this.switchProps.pattern) {
return;
}
if (this.consumer.bitMap.getAllBitIdsFromAllLanes().length) {
// if the workspace is not empty, it's possible that it has components from lane-x, and is now switching
// partially to lane-y, while lane-y has the same components as lane-x. in which case, the user ends up with
// an invalid state of components from lane-x and lane-y together.
throw new (_bitError().BitError)('error: use --pattern only when the workspace is empty');
}
const allIds = this.switchProps.ids || [];
this.switchProps.ids = await this.workspace.filterIdsFromPoolIdsByPattern(this.switchProps.pattern, allIds);
}
async populatePropsAccordingToRemoteLane(remoteLaneId) {
this.laneIdToSwitchTo = remoteLaneId;
this.logger.debug(`populatePropsAccordingToRemoteLane, remoteLaneId: ${remoteLaneId.toString()}`);
this.throwForSwitchingToCurrentLane();
const remoteLane = await this.lanes.fetchLaneWithItsComponents(remoteLaneId);
this.switchProps.laneName = remoteLaneId.name;
this.switchProps.localTrackedLane = this.consumer.scope.lanes.getAliasByLaneId(remoteLaneId) || undefined;
this.switchProps.remoteLane = remoteLane;
this.laneToSwitchTo = remoteLane;
this.logger.debug(`populatePropsAccordingToRemoteLane, completed`);
return [...remoteLane.toComponentIds()];
}
async populatePropsAccordingToDefaultLane() {
this.laneIdToSwitchTo = _laneId().LaneId.from(_laneId().DEFAULT_LANE, this.consumer.scope.name);
this.throwForSwitchingToCurrentLane();
}
populatePropsAccordingToLocalLane(localLane) {
this.laneIdToSwitchTo = localLane.toLaneId();
this.laneToSwitchTo = localLane;
this.throwForSwitchingToCurrentLane();
return [...localLane.toComponentIds()];
}
throwForSwitchingToCurrentLane() {
if (this.consumer.getCurrentLaneId().isEqual(this.laneIdToSwitchTo)) {
const laneIdStr = this.laneIdToSwitchTo.isDefault() ? this.laneIdToSwitchTo.name : this.laneIdToSwitchTo.toString();
throw new (_bitError().BitError)(`already checked out to "${laneIdStr}".
to be up to date with the remote lane, please run "bit checkout head"`);
}
}
async saveLanesData() {
const localLaneName = this.switchProps.alias || this.laneIdToSwitchTo.name;
if (this.switchProps.remoteLane) {
if (!this.switchProps.localTrackedLane) {
this.consumer.scope.lanes.trackLane({
localLane: localLaneName,
remoteLane: this.laneIdToSwitchTo.name,
remoteScope: this.laneIdToSwitchTo.scope
});
}
}
this.consumer.setCurrentLane(this.laneIdToSwitchTo, !this.laneToSwitchTo?.isNew);
this.consumer.bitMap.syncWithIds(_componentId().ComponentIdList.fromArray(this.switchProps.ids || []), _componentId().ComponentIdList.fromArray(this.switchProps.laneBitIds || []));
// If this cache isn't cleared, here's what can happen:
// Switching from "lane-dev" to "main": while on "lane-dev", ModelComponent keeps in-memory props
// `laneHeadLocal` and `laneHeadRemote`. Methods like `headIncludeRemote()` use them and may return
// the lane-dev head instead of the head on main.
this.consumer.scope.objects.clearObjectsFromCache();
}
}
exports.LaneSwitcher = LaneSwitcher;
//# sourceMappingURL=switch-lanes.js.map