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
287 lines (238 loc) • 9.54 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
function _bluebird() {
const data = require("bluebird");
_bluebird = function () {
return data;
};
return data;
}
function _ramda() {
const data = _interopRequireDefault(require("ramda"));
_ramda = function () {
return data;
};
return data;
}
function _utils() {
const data = require("../../../utils");
_utils = function () {
return data;
};
return data;
}
function _repositories() {
const data = require("../../../scope/repositories");
_repositories = function () {
return data;
};
return data;
}
function _mergeFiles() {
const data = _interopRequireDefault(require("../../../utils/merge-files"));
_mergeFiles = function () {
return data;
};
return data;
}
function _path() {
const data = require("../../../utils/path");
_path = function () {
return data;
};
return data;
}
function _generalError() {
const data = _interopRequireDefault(require("../../../error/general-error"));
_generalError = function () {
return data;
};
return data;
}
/**
* it's easier to understand with an example.
* a component bar/foo has two versions: 0.0.1, 0.0.2. Also, the component was modified locally.
* the user is running 'bit checkout 0.0.1 bar/foo' to switch the version of bar/foo to 0.0.1.
*
* the goal is to rewrite bar/foo to the filesystem as 0.0.1 and keeping the local changes.
* in other words, the changes the user did since 0.0.2 should be applied/merged on top of 0.0.1.
*
* to do the actual merge we use git, specifically `merge-file` command, so we try to use the same
* terminology as git. From the command help:
* `git merge-file <current-file> <base-file> <other-file>
* git merge-file incorporates all changes that lead from the <base-file> to <other-file> into
* <current-file>. The result ordinarily goes into <current-file>.`
*
* according to the example above:
* current-file => bar/foo@0.0.1
* base-file => bar/foo@0.0.2
* other-file => bar/foo@0.0.2 + modification
*/
var _default = /*#__PURE__*/function () {
var _threeWayMergeVersions = (0, _bluebird().coroutine)(function* ({
consumer,
otherComponent,
otherVersion,
currentComponent,
currentVersion,
baseComponent
}) {
// baseFiles and currentFiles come from the model, therefore their paths include the
// sharedOriginallyDir. fsFiles come from the Fs, therefore their paths don't include the
// sharedOriginallyDir.
// option 1) strip sharedOriginallyDir from baseFiles and currentFiles. the problem is that the
// sharedDir can be different if the dependencies were changes for example, as a result, it won't
// be possible to compare between the files as the paths are different.
// in the previous it was implemented this way and caused a bug, which now has an e2e-test to
// block it. see https://github.com/teambit/bit/pull/2070 PR.
// option 2) add sharedOriginallyDir to the fsFiles. we must go with this option.
const baseFiles = baseComponent.files;
const currentFiles = currentComponent.files;
const fsFiles = otherComponent.cloneFilesWithSharedDir();
const results = {
addFiles: [],
modifiedFiles: [],
unModifiedFiles: [],
overrideFiles: [],
hasConflicts: false
};
const getFileResult = (fsFile, baseFile, currentFile) => {
const filePath = (0, _path().pathNormalizeToLinux)(fsFile.relative);
if (!currentFile) {
// if !currentFile && !baseFile, the file was created after the last tag
// if !currentFile && baseFile, the file was created as part of the last tag
// either way, no need to do any calculation, the file should be added
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
results.addFiles.push({
filePath,
fsFile
});
return;
}
if (!baseFile) {
// if currentFile && !baseFile, the file was deleted as part of the last tag
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
results.overrideFiles.push({
filePath,
fsFile
});
return;
} // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
const fsFileHash = (0, _utils().sha1)(fsFile.contents);
const baseFileHash = baseFile.file.hash;
const currentFileHash = currentFile.file.hash;
if (fsFileHash === currentFileHash) {
// no need to check also for fsFileHash === baseFileHash, as long as fs == current, no need to take any action
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
results.unModifiedFiles.push({
filePath,
fsFile
});
return;
}
if (fsFileHash === baseFileHash) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
results.overrideFiles.push({
filePath,
fsFile
});
return;
} // it was changed in both, there is a chance for conflict
// @ts-ignore it's a hack to pass the data, version is not a valid attribute.
fsFile.version = otherVersion; // @ts-ignore it's a hack to pass the data, version is not a valid attribute.
baseFile.version = otherVersion; // @ts-ignore it's a hack to pass the data, version is not a valid attribute.
currentFile.version = currentVersion; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
results.modifiedFiles.push({
filePath,
fsFile,
baseFile,
currentFile,
output: null,
conflict: null
});
};
fsFiles.forEach(fsFile => {
const relativePath = (0, _path().pathNormalizeToLinux)(fsFile.relative);
const baseFile = baseFiles.find(file => file.relativePath === relativePath);
const currentFile = currentFiles.find(file => file.relativePath === relativePath);
getFileResult(fsFile, baseFile, currentFile);
});
if (_ramda().default.isEmpty(results.modifiedFiles)) return results;
const conflictResults = yield getMergeResults(consumer, results.modifiedFiles);
conflictResults.forEach(conflictResult => {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
const modifiedFile = results.modifiedFiles.find(file => file.filePath === conflictResult.filePath);
if (!modifiedFile) throw new (_generalError().default)(`unable to find ${conflictResult.filePath} in modified files array`); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
modifiedFile.output = conflictResult.output; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
modifiedFile.conflict = conflictResult.conflict;
if (conflictResult.conflict) results.hasConflicts = true;
});
return results;
});
function threeWayMergeVersions(_x) {
return _threeWayMergeVersions.apply(this, arguments);
}
return threeWayMergeVersions;
}();
exports.default = _default;
function getMergeResults(_x2, _x3) {
return _getMergeResults.apply(this, arguments);
}
function _getMergeResults() {
_getMergeResults = (0, _bluebird().coroutine)(function* (consumer, modifiedFiles) {
const tmp = new (_repositories().Tmp)(consumer.scope);
const conflictResultsP = modifiedFiles.map( /*#__PURE__*/function () {
var _ref = (0, _bluebird().coroutine)(function* (modifiedFile) {
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
const fsFilePathP = tmp.save(modifiedFile.fsFile.contents);
const writeFile = /*#__PURE__*/function () {
var _ref2 = (0, _bluebird().coroutine)(function* (file) {
const content = yield file.file.load(consumer.scope.objects); // @ts-ignore
return tmp.save(content.contents.toString());
});
return function writeFile(_x5) {
return _ref2.apply(this, arguments);
};
}();
const baseFilePathP = writeFile(modifiedFile.baseFile);
const currentFilePathP = writeFile(modifiedFile.currentFile);
const [fsFilePath, baseFilePath, currentFilePath] = yield Promise.all([fsFilePathP, baseFilePathP, currentFilePathP]);
const mergeFilesParams = {
filePath: modifiedFile.filePath,
currentFile: {
// @ts-ignore
label: modifiedFile.currentFile.version,
path: currentFilePath
},
baseFile: {
path: baseFilePath
},
otherFile: {
// @ts-ignore
label: `${modifiedFile.fsFile.version} modified`,
path: fsFilePath
}
};
return (0, _mergeFiles().default)(mergeFilesParams);
});
return function (_x4) {
return _ref.apply(this, arguments);
};
}());
return Promise.all(conflictResultsP);
});
return _getMergeResults.apply(this, arguments);
}
;