bit-bin
Version:
<a href="https://opensource.org/licenses/Apache-2.0"><img alt="apache" src="https://img.shields.io/badge/License-Apache%202.0-blue.svg"></a> <a href="https://github.com/teambit/bit/blob/master/CONTRIBUTING.md"><img alt="prs" src="https://img.shields.io/b
374 lines (307 loc) • 11.3 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.mergeVersion = mergeVersion;
exports.getMergeStrategyInteractive = getMergeStrategyInteractive;
exports.getMergeStrategy = getMergeStrategy;
exports.FileStatus = exports.MergeOptions = exports.mergeOptionsCli = void 0;
function _bluebird() {
const data = require("bluebird");
_bluebird = function () {
return data;
};
return data;
}
function path() {
const data = _interopRequireWildcard(require("path"));
path = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
function _bitId() {
const data = require("../../../bit-id");
_bitId = function () {
return data;
};
return data;
}
function _prompts() {
const data = require("../../../prompts");
_prompts = function () {
return data;
};
return data;
}
function _path2() {
const data = require("../../../utils/path");
_path2 = function () {
return data;
};
return data;
}
function _twoWayMerge() {
const data = _interopRequireDefault(require("./two-way-merge"));
_twoWayMerge = function () {
return data;
};
return data;
}
function _generalError() {
const data = _interopRequireDefault(require("../../../error/general-error"));
_generalError = function () {
return data;
};
return data;
}
function _componentWriter() {
const data = _interopRequireDefault(require("../../component-ops/component-writer"));
_componentWriter = function () {
return data;
};
return data;
}
function _repositories() {
const data = require("../../../scope/repositories");
_repositories = function () {
return data;
};
return data;
}
const mergeOptionsCli = {
o: 'ours',
t: 'theirs',
m: 'manual'
};
exports.mergeOptionsCli = mergeOptionsCli;
const MergeOptions = {
ours: 'ours',
theirs: 'theirs',
manual: 'manual'
}; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
exports.MergeOptions = MergeOptions;
const FileStatus = {
merged: _chalk().default.green('auto-merged'),
manual: _chalk().default.red('CONFLICT'),
updated: _chalk().default.green('updated'),
added: _chalk().default.green('added'),
overridden: _chalk().default.yellow('overridden'),
unchanged: _chalk().default.green('unchanged')
}; // fileName is PathLinux. TS doesn't let anything else in the keys other than string and number
exports.FileStatus = FileStatus;
function mergeVersion(_x, _x2, _x3, _x4) {
return _mergeVersion.apply(this, arguments);
}
function _mergeVersion() {
_mergeVersion = (0, _bluebird().coroutine)(function* (consumer, version, ids, mergeStrategy) {
const {
components
} = yield consumer.loadComponents(_bitId().BitIds.fromArray(ids));
const allComponentsStatus = yield getAllComponentsStatus();
const componentWithConflict = allComponentsStatus.find(component => component.mergeResults.hasConflicts);
if (componentWithConflict && !mergeStrategy) {
mergeStrategy = yield getMergeStrategyInteractive();
}
const mergedComponentsP = allComponentsStatus.map(({
id,
componentFromFS,
mergeResults
}) => {
return applyVersion(consumer, id, componentFromFS, mergeResults, mergeStrategy);
});
const mergedComponents = yield Promise.all(mergedComponentsP);
return {
components: mergedComponents,
version
};
function getAllComponentsStatus() {
return _getAllComponentsStatus.apply(this, arguments);
}
function _getAllComponentsStatus() {
_getAllComponentsStatus = (0, _bluebird().coroutine)(function* () {
const tmp = new (_repositories().Tmp)(consumer.scope);
try {
const componentsStatus = yield Promise.all(components.map(component => getComponentStatus(consumer, component, version)));
yield tmp.clear();
return componentsStatus;
} catch (err) {
yield tmp.clear();
throw err;
}
});
return _getAllComponentsStatus.apply(this, arguments);
}
});
return _mergeVersion.apply(this, arguments);
}
function getComponentStatus(_x5, _x6, _x7) {
return _getComponentStatus.apply(this, arguments);
}
/**
* it doesn't matter whether the component is modified. the idea is to merge the
* specified version with the current version.
*
* 1) when there are conflicts and the strategy is "ours", don't do any change to the component.
*
* 2) when there are conflicts and the strategy is "theirs", add all files from the specified
* version and write the component.
*
* 3) when there is no conflict or there are conflicts and the strategy is manual, update
* component.files.
*
* it's going to be 2-way merge:
* current-file: is the current file.
* base-file: empty.
* other-file: the specified version.
*/
function _getComponentStatus() {
_getComponentStatus = (0, _bluebird().coroutine)(function* (consumer, component, version) {
const componentModel = yield consumer.scope.sources.get(component.id);
if (!componentModel) {
throw new (_generalError().default)(`component ${component.id.toString()} doesn't have any version yet`);
}
if (!componentModel.hasVersion(version)) {
throw new (_generalError().default)(`component ${component.id.toStringWithoutVersion()} doesn't have version ${version}`);
}
const existingBitMapId = consumer.bitMap.getBitId(component.id, {
ignoreVersion: true
});
const currentlyUsedVersion = existingBitMapId.version;
if (currentlyUsedVersion === version) {
throw new (_generalError().default)(`component ${component.id.toStringWithoutVersion()} is already at version ${version}`);
}
const otherComponent = yield consumer.loadComponentFromModel(component.id.changeVersion(version));
const mergeResults = yield (0, _twoWayMerge().default)({
consumer,
otherComponent,
otherVersion: version,
currentComponent: component,
// $FlowFixMe
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
currentVersion: currentlyUsedVersion
});
return {
componentFromFS: component,
id: component.id,
mergeResults
};
});
return _getComponentStatus.apply(this, arguments);
}
function applyVersion(_x8, _x9, _x10, _x11, _x12) {
return _applyVersion.apply(this, arguments);
}
function _applyVersion() {
_applyVersion = (0, _bluebird().coroutine)(function* (consumer, id, componentFromFS, mergeResults, mergeStrategy) {
const filesStatus = {};
if (mergeResults.hasConflicts && mergeStrategy === MergeOptions.ours) {
componentFromFS.files.forEach(file => {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
filesStatus[(0, _path2().pathNormalizeToLinux)(file.relative)] = FileStatus.unchanged;
});
return {
id,
filesStatus
};
}
const component = componentFromFS.componentFromModel;
if (!component) throw new (_generalError().default)('failed finding the component in the model');
const componentMap = componentFromFS.componentMap;
if (!componentMap) throw new (_generalError().default)('applyVersion: componentMap was not found');
const files = componentFromFS.files;
component.files = files;
files.forEach(file => {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
filesStatus[(0, _path2().pathNormalizeToLinux)(file.relative)] = FileStatus.unchanged;
}); // update files according to the merge results
const modifiedStatus = applyModifiedVersion(consumer, files, mergeResults, mergeStrategy);
const componentWriter = _componentWriter().default.getInstance({
component,
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
writeToPath: component.files[0].base,
// find the current path from the files. (we use the first one but it's the same for all)
writeConfig: false,
// never override the existing bit.json
writePackageJson: false,
deleteBitDirContent: false,
origin: componentMap.origin,
consumer,
bitMap: consumer.bitMap,
existingComponentMap: componentMap
});
yield componentWriter.write();
consumer.bitMap.removeComponent(component.id);
componentWriter.origin = componentMap.origin;
componentWriter.addComponentToBitMap(componentMap.rootDir);
return {
id,
filesStatus: Object.assign(filesStatus, modifiedStatus)
};
});
return _applyVersion.apply(this, arguments);
}
function applyModifiedVersion(consumer, componentFiles, mergeResults, mergeStrategy) {
const filesStatus = {};
mergeResults.modifiedFiles.forEach(file => {
const filePath = path().normalize(file.filePath); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
const foundFile = componentFiles.find(componentFile => componentFile.relative === filePath);
if (!foundFile) throw new (_generalError().default)(`file ${filePath} not found`);
if (mergeResults.hasConflicts && mergeStrategy === MergeOptions.theirs) {
// write the version of otherFile
const otherFile = file.otherFile; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
foundFile.contents = otherFile.contents;
filesStatus[file.filePath] = FileStatus.updated;
} else if (file.conflict) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
foundFile.contents = Buffer.from(file.conflict);
filesStatus[file.filePath] = FileStatus.manual;
} else if (file.output) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
foundFile.contents = Buffer.from(file.output);
filesStatus[file.filePath] = FileStatus.merged;
} else {
throw new (_generalError().default)('file does not have output nor conflict');
}
});
mergeResults.addFiles.forEach(file => {
const otherFile = file.otherFile;
componentFiles.push(otherFile);
filesStatus[file.filePath] = FileStatus.added;
});
return filesStatus;
}
function getMergeStrategyInteractive() {
return _getMergeStrategyInteractive.apply(this, arguments);
}
function _getMergeStrategyInteractive() {
_getMergeStrategyInteractive = (0, _bluebird().coroutine)(function* () {
try {
const result = yield (0, _prompts().resolveConflictPrompt)(); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
return mergeOptionsCli[result.mergeStrategy];
} catch (err) {
// probably user clicked ^C
throw new (_generalError().default)('the action has been canceled');
}
});
return _getMergeStrategyInteractive.apply(this, arguments);
}
function getMergeStrategy(ours, theirs, manual) {
if (ours && theirs || ours && manual || theirs && manual) {
throw new (_generalError().default)('please choose only one of the following: ours, theirs or manual');
}
if (ours) return MergeOptions.ours;
if (theirs) return MergeOptions.theirs;
if (manual) return MergeOptions.manual;
return null;
}
;