@teambit/checkout
Version:
168 lines (163 loc) • 8.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.applyVersion = applyVersion;
exports.removeFilesIfNeeded = removeFilesIfNeeded;
exports.throwForFailures = throwForFailures;
exports.updateFileStatus = updateFileStatus;
function _component() {
const data = require("@teambit/component.sources");
_component = function () {
return data;
};
return data;
}
function _legacy() {
const data = require("@teambit/legacy.utils");
_legacy = function () {
return data;
};
return data;
}
function _bitError() {
const data = require("@teambit/bit-error");
_bitError = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function _componentModules() {
const data = require("@teambit/component.modules.merge-helper");
_componentModules = function () {
return data;
};
return data;
}
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
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); }
/**
* This function optionally returns "component" object. If it returns, it means it needs to be written to the filesystem.
* Otherwise, it means the component is already up to date and no need to write it.
*
* If no need to change anything (ours), then don't return the component object.
* Otherwise, either return the component object as is (if no conflicts or "theirs"), or change the files in this
* component object. Later, this component object is written to the filesystem.
*
* 1) when the files are modified with conflicts and the strategy is "ours", or forceOurs was used, leave the FS as is.
*
* 2) when the files are modified with conflicts and the strategy is "theirs", or forceTheirs was used, write the
* component according to "component" object
*
* 3) when files are modified with no conflict or files are modified with conflicts and the
* strategy is manual, load the component according to id.version and update component.files.
* applyModifiedVersion() docs explains what files are updated/added.
*
* Side note:
* Deleted file => if files are in used version but not in the modified one, no need to delete it. (similar to git).
* Added file => if files are not in used version but in the modified one, they'll be under mergeResults.addFiles
*/
async function applyVersion(consumer, id, componentFromFS,
// it can be null only when isLanes is true
mergeResults, checkoutProps) {
if (!checkoutProps.isLane && !componentFromFS) throw new Error(`applyVersion expect to get componentFromFS for ${id.toString()}`);
const {
mergeStrategy,
forceOurs
} = checkoutProps;
let filesStatus = {};
if (mergeResults?.hasConflicts && mergeStrategy === _componentModules().MergeOptions.ours || forceOurs) {
// even when isLane is true, the mergeResults is possible only when the component is on the filesystem
// otherwise it's impossible to have conflicts
if (!componentFromFS) throw new Error(`applyVersion expect to get componentFromFS for ${id.toString()}`);
componentFromFS.files.forEach(file => {
filesStatus[(0, _legacy().pathNormalizeToLinux)(file.relative)] = _componentModules().FileStatus.unchanged;
});
consumer.bitMap.updateComponentId(id);
return {
applyVersionResult: {
id,
filesStatus
}
};
}
const component = await consumer.loadComponentFromModelImportIfNeeded(id);
const componentMap = componentFromFS && componentFromFS.componentMap;
if (componentFromFS && !componentMap) throw new (_bitError().BitError)('applyVersion: componentMap was not found');
const files = component.files;
updateFileStatus(files, filesStatus, componentFromFS || undefined);
await removeFilesIfNeeded(filesStatus, consumer, componentFromFS || undefined);
if (mergeResults) {
// update files according to the merge results
const {
filesStatus: modifiedStatus,
modifiedFiles
} = (0, _componentModules().applyModifiedVersion)(files, mergeResults, mergeStrategy);
filesStatus = _objectSpread(_objectSpread({}, filesStatus), modifiedStatus);
component.files = modifiedFiles;
}
// in case of forceTheirs, the mergeResults is undefined, the "component" object is according to "theirs", so it'll work
// expected. (later, it writes the component object).
return {
applyVersionResult: {
id,
filesStatus
},
component
};
}
function updateFileStatus(files, filesStatus, componentFromFS) {
files.forEach(file => {
const fileFromFs = componentFromFS?.files.find(f => f.relative === file.relative);
const areFilesEqual = fileFromFs && Buffer.compare(fileFromFs.contents, file.contents) === 0;
// @ts-ignore
filesStatus[(0, _legacy().pathNormalizeToLinux)(file.relative)] = areFilesEqual ? _componentModules().FileStatus.unchanged : _componentModules().FileStatus.updated;
});
}
/**
* when files exist on the filesystem but not on the checked out versions, they need to be deleted.
* without this function, these files would be left on the filesystem. (we don't delete the comp-dir before writing).
* this needs to be done *before* the component is written to the filesystem, otherwise, it won't work when a file
* has a case change. e.g. from uppercase to lowercase. (see merge-lane.e2e 'renaming files from uppercase to lowercase').
*/
async function removeFilesIfNeeded(filesStatus, consumer, componentFromFS) {
if (!componentFromFS) return;
// @todo: if the component is not in the FS, it should be passed as undefined here.
// in the case this is coming from merge-lane, it's sometimes populated from the scope.
const isExistOnFs = consumer.bitMap.getComponentIdIfExist(componentFromFS.id, {
ignoreVersion: true
});
if (!isExistOnFs) return;
const filePathsFromFS = componentFromFS.files || [];
const dataToPersist = new (_component().DataToPersist)();
filePathsFromFS.forEach(file => {
const filename = (0, _legacy().pathNormalizeToLinux)(file.relative);
if (!filesStatus[filename]) {
// @ts-ignore todo: typescript has a good point here. it should be the string "removed", not chalk.green(removed).
filesStatus[filename] = _componentModules().FileStatus.removed;
}
if (filesStatus[filename] === _componentModules().FileStatus.removed) {
dataToPersist.removePath(new (_component().RemovePath)(file.path));
}
});
await dataToPersist.persistAllToFS();
}
function throwForFailures(allComponentsStatus) {
const failedComponents = allComponentsStatus.filter(c => c.unchangedMessage && !c.unchangedLegitimately);
if (failedComponents.length) {
const failureMsgs = failedComponents.map(failedComponent => `${_chalk().default.bold(failedComponent.id.toString())} - ${_chalk().default.red(failedComponent.unchangedMessage)}`).join('\n');
throw new (_bitError().BitError)(`unable to proceed due to the following failures:\n${failureMsgs}`);
}
}
//# sourceMappingURL=checkout-version.js.map