UNPKG

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

715 lines (550 loc) 23.5 kB
"use strict"; 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 _defineProperty2() { const data = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); _defineProperty2 = function () { return data; }; return data; } function _ramda() { const data = _interopRequireDefault(require("ramda")); _ramda = function () { return data; }; return data; } function _semver() { const data = _interopRequireDefault(require("semver")); _semver = function () { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function () { return data; }; return data; } function _exceptions() { const data = require("../exceptions"); _exceptions = function () { return data; }; return data; } function _bitId() { const data = require("../../bit-id"); _bitId = function () { return data; }; return data; } function _loader() { const data = _interopRequireDefault(require("../../cli/loader")); _loader = function () { return data; }; return data; } function _loaderMessages() { const data = require("../../cli/loader/loader-messages"); _loaderMessages = function () { return data; }; return data; } function _logger() { const data = _interopRequireDefault(require("../../logger/logger")); _logger = function () { return data; }; return data; } function _utils() { const data = require("../../utils"); _utils = function () { return data; }; return data; } function _generalError() { const data = _interopRequireDefault(require("../../error/general-error")); _generalError = function () { return data; }; return data; } function _checkoutVersion() { const data = require("../versions-ops/checkout-version"); _checkoutVersion = function () { return data; }; return data; } function _mergeVersion() { const data = require("../versions-ops/merge-version"); _mergeVersion = function () { return data; }; return data; } function _manyComponentsWriter() { const data = _interopRequireDefault(require("./many-components-writer")); _manyComponentsWriter = function () { return data; }; return data; } function _constants() { const data = require("../../constants"); _constants = function () { return data; }; return data; } function _hasWildcard() { const data = _interopRequireDefault(require("../../utils/string/has-wildcard")); _hasWildcard = function () { return data; }; return data; } function _listScope() { const data = require("../../api/consumer/lib/list-scope"); _listScope = function () { return data; }; return data; } function _scopeRemotes() { const data = require("../../scope/scope-remotes"); _scopeRemotes = function () { return data; }; return data; } function _showDoctorError() { const data = _interopRequireDefault(require("../../error/show-doctor-error")); _showDoctorError = function () { return data; }; return data; } class ImportComponents { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! constructor(consumer, options) { (0, _defineProperty2().default)(this, "consumer", void 0); (0, _defineProperty2().default)(this, "scope", void 0); (0, _defineProperty2().default)(this, "options", void 0); (0, _defineProperty2().default)(this, "mergeStatus", void 0); this.consumer = consumer; this.scope = consumer.scope; this.options = options; } importComponents() { _loader().default.start(_loaderMessages().BEFORE_IMPORT_ACTION); this.options.saveDependenciesAsComponents = this.consumer.config._saveDependenciesAsComponents; if (!this.options.writePackageJson) { // if package.json is not written, it's impossible to install the packages and dependencies as npm packages this.options.installNpmPackages = false; this.options.saveDependenciesAsComponents = true; } if (!this.options.ids || _ramda().default.isEmpty(this.options.ids)) { return this.importAccordingToBitMap(); } return this.importSpecificComponents(); } // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! importSpecificComponents() { var _this = this; return (0, _bluebird().coroutine)(function* () { _logger().default.debug(`importSpecificComponents, Ids: ${_this.options.ids.join(', ')}`); const bitIds = yield _this._getBitIds(); const beforeImportVersions = yield _this._getCurrentVersions(bitIds); yield _this._throwForPotentialIssues(bitIds); const componentsWithDependencies = yield _this.consumer.importComponents(bitIds, true, _this.options.saveDependenciesAsComponents); yield _this._throwForModifiedOrNewDependencies(componentsWithDependencies); const componentsWithDependenciesFiltered = _this._filterComponentsWithLowerVersions(componentsWithDependencies); yield _this._writeToFileSystem(componentsWithDependenciesFiltered); const importDetails = yield _this._getImportDetails(beforeImportVersions, componentsWithDependencies); return { dependencies: componentsWithDependenciesFiltered, importDetails }; })(); } /** * it can happen for example when importing a component with `--dependent` flag and the component has * the same dependent with different versions. we only want the one with the higher version */ _filterComponentsWithLowerVersions(componentsWithDependencies) { return componentsWithDependencies.filter(comp => { const sameIdHigherVersion = componentsWithDependencies.find(c => !c.component.id.isEqual(comp.component.id) && c.component.id.isEqualWithoutVersion(comp.component.id) && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion _semver().default.gt(c.component.id.version, comp.component.id.version)); return !sameIdHigherVersion; }); } _getBitIds() { var _this2 = this; return (0, _bluebird().coroutine)(function* () { const bitIds = []; yield Promise.all(_this2.options.ids.map( /*#__PURE__*/function () { var _ref = (0, _bluebird().coroutine)(function* (idStr) { if ((0, _hasWildcard().default)(idStr)) { const ids = yield (0, _listScope().getRemoteBitIdsByWildcards)(idStr); _loader().default.start(_loaderMessages().BEFORE_IMPORT_ACTION); // it stops the previous loader of BEFORE_REMOTE_LIST bitIds.push(...ids); } else { bitIds.push(_bitId().BitId.parse(idStr, true)); // we don't support importing without a scope name } }); return function (_x) { return _ref.apply(this, arguments); }; }())); if (_this2.options.importDependenciesDirectly || _this2.options.importDependents) { const graphs = yield _this2._getComponentsGraphs(bitIds); if (_this2.options.importDependenciesDirectly) { const dependenciesIds = _this2._getDependenciesFromGraph(bitIds, graphs); bitIds.push(...dependenciesIds); } if (_this2.options.importDependents) { const dependentsIds = _this2._getDependentsFromGraph(bitIds, graphs); bitIds.push(...dependentsIds); } } return _bitId().BitIds.uniqFromArray(bitIds); })(); } _getDependenciesFromGraph(bitIds, graphs) { const dependencies = bitIds.map(bitId => { const componentGraph = graphs.find(graph => graph.scopeName === bitId.scope); if (!componentGraph) { throw new Error(`unable to find a graph for ${bitId.toString()}`); } const dependenciesInfo = componentGraph.getDependenciesInfo(bitId); return dependenciesInfo.map(d => d.id); }); return _ramda().default.flatten(dependencies); } _getDependentsFromGraph(bitIds, graphs) { const dependents = bitIds.map(bitId => { const componentGraph = graphs.find(graph => graph.scopeName === bitId.scope); if (!componentGraph) { throw new Error(`unable to find a graph for ${bitId.toString()}`); } const dependentsInfo = componentGraph.getDependentsInfo(bitId); return dependentsInfo.map(d => d.id); }); return _ramda().default.flatten(dependents); } _getComponentsGraphs(bitIds) { var _this3 = this; return (0, _bluebird().coroutine)(function* () { const remotes = yield (0, _scopeRemotes().getScopeRemotes)(_this3.consumer.scope); return remotes.scopeGraphs(bitIds, _this3.consumer.scope); })(); } // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! importAccordingToBitMap() { var _this4 = this; return (0, _bluebird().coroutine)(function* () { _this4.options.objectsOnly = !_this4.options.merge && !_this4.options.override; const authoredExportedComponents = _this4.consumer.bitMap.getAuthoredExportedComponents(); const importedComponents = _this4.consumer.bitMap.getAllBitIds([_constants().COMPONENT_ORIGINS.IMPORTED]); const componentsIdsToImport = [...authoredExportedComponents, ...importedComponents]; let compiler; let tester; if (_ramda().default.isEmpty(componentsIdsToImport)) { if (!_this4.options.withEnvironments) { throw new (_exceptions().NothingToImport)(); } compiler = yield _this4.consumer.compiler; tester = yield _this4.consumer.tester; if (!tester && !compiler) { throw new (_exceptions().NothingToImport)(); } } // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! yield _this4._throwForModifiedOrNewComponents(componentsIdsToImport); // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! const beforeImportVersions = yield _this4._getCurrentVersions(componentsIdsToImport); let componentsAndDependencies = []; if (componentsIdsToImport.length) { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! componentsAndDependencies = yield _this4.consumer.importComponents(componentsIdsToImport, true); yield _this4._throwForModifiedOrNewDependencies(componentsAndDependencies); yield _this4._writeToFileSystem(componentsAndDependencies); } const importDetails = yield _this4._getImportDetails(beforeImportVersions, componentsAndDependencies); if (_this4.options.withEnvironments) { compiler = compiler || (yield _this4.consumer.compiler); tester = tester || (yield _this4.consumer.tester); const context = { workspaceDir: _this4.consumer.getPath() }; const envsArgs = [_this4.consumer.scope, { verbose: _this4.options.verbose }, context]; const envComponents = []; if (compiler) { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! envComponents.push(yield compiler.install(...envsArgs)); } if (tester) { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! envComponents.push(yield tester.install(...envsArgs)); } return { dependencies: componentsAndDependencies, envComponents: _ramda().default.flatten(envComponents), importDetails }; } return { dependencies: componentsAndDependencies, importDetails }; })(); } // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! _getCurrentVersions(ids) { var _this5 = this; return (0, _bluebird().coroutine)(function* () { const versionsP = ids.map( /*#__PURE__*/function () { var _ref2 = (0, _bluebird().coroutine)(function* (id) { const modelComponent = yield _this5.consumer.scope.getModelComponentIfExist(id); const idStr = id.toStringWithoutVersion(); if (!modelComponent) return [idStr, []]; return [idStr, modelComponent.listVersions()]; }); return function (_x2) { return _ref2.apply(this, arguments); }; }()); const versions = yield Promise.all(versionsP); return _ramda().default.fromPairs(versions); })(); } /** * get import details, includes the diff between the versions array before import and after import */ _getImportDetails(currentVersions, components) { var _this6 = this; return (0, _bluebird().coroutine)(function* () { const detailsP = components.map( /*#__PURE__*/function () { var _ref3 = (0, _bluebird().coroutine)(function* (component) { const id = component.component.id; const idStr = id.toStringWithoutVersion(); const beforeImportVersions = currentVersions[idStr]; if (!beforeImportVersions) { throw new Error(`_getImportDetails failed finding ${idStr} in currentVersions, which has ${Object.keys(currentVersions).join(', ')}`); } const modelComponent = yield _this6.consumer.scope.getModelComponentIfExist(id); if (!modelComponent) throw new (_showDoctorError().default)(`imported component ${idStr} was not found in the model`); const afterImportVersions = modelComponent.listVersions(); const versionDifference = _ramda().default.difference(afterImportVersions, beforeImportVersions); const getStatus = () => { if (!versionDifference.length) return 'up to date'; if (!beforeImportVersions.length) return 'added'; return 'updated'; }; const filesStatus = _this6.mergeStatus && _this6.mergeStatus[idStr] ? _this6.mergeStatus[idStr] : null; return { id: idStr, versions: versionDifference, status: getStatus(), filesStatus }; }); return function (_x3) { return _ref3.apply(this, arguments); }; }()); return Promise.all(detailsP); })(); } _throwForPotentialIssues(ids) { var _this7 = this; return (0, _bluebird().coroutine)(function* () { yield _this7._throwForModifiedOrNewComponents(ids); _this7._throwForDifferentComponentWithSameName(ids); })(); } _throwForModifiedOrNewComponents(ids) { var _this8 = this; return (0, _bluebird().coroutine)(function* () { // the typical objectsOnly option is when a user cloned a project with components tagged to the source code, but // doesn't have the model objects. in that case, calling getComponentStatusById() may return an error as it relies // on the model objects when there are dependencies if (_this8.options.override || _this8.options.objectsOnly || _this8.options.merge) return; const componentsStatuses = yield _this8.consumer.getManyComponentsStatuses(ids); const modifiedComponents = componentsStatuses.filter(({ status }) => status.modified || status.newlyCreated).map(c => c.id); if (modifiedComponents.length) { throw new (_generalError().default)(_chalk().default.yellow(`unable to import the following components due to local changes, use --merge flag to merge your local changes or --override to override them\n${modifiedComponents.join('\n')} `)); } })(); } _throwForModifiedOrNewDependencies(componentsAndDependencies) { var _this9 = this; return (0, _bluebird().coroutine)(function* () { const allDependenciesIds = _ramda().default.flatten(componentsAndDependencies.map(componentAndDependencies => componentAndDependencies.component.dependencies.getAllIds())); yield _this9._throwForModifiedOrNewComponents(allDependenciesIds); })(); } /** * Model Component id() calculation uses id.toString() for the hash. * If an imported component has scopereadonly name equals to a local name, both will have the exact same * hash and they'll override each other. */ _throwForDifferentComponentWithSameName(ids) { ids.forEach(id => { const existingId = this.consumer.getParsedIdIfExist(id.toStringWithoutVersion()); if (existingId && !existingId.hasScope()) { throw new (_generalError().default)(`unable to import ${id.toString()}. the component name conflicted with your local component with the same name. it's fine to have components with the same name as long as their scope names are different. Make sure to export your component first to get a scope and then try importing again`); } }); } _getMergeStatus(componentWithDependencies) { var _this10 = this; return (0, _bluebird().coroutine)(function* () { const component = componentWithDependencies.component; const componentStatus = yield _this10.consumer.getComponentStatusById(component.id); const mergeStatus = { componentWithDependencies, mergeResults: null }; if (!componentStatus.modified) return mergeStatus; const componentModel = yield _this10.consumer.scope.sources.get(component.id); if (!componentModel) { throw new (_showDoctorError().default)(`component ${component.id.toString()} wasn't found in the model`); } const existingBitMapBitId = _this10.consumer.bitMap.getBitId(component.id, { ignoreVersion: true }); const fsComponent = yield _this10.consumer.loadComponent(existingBitMapBitId); const currentlyUsedVersion = existingBitMapBitId.version; // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! const baseComponent = yield componentModel.loadVersion(currentlyUsedVersion, _this10.consumer.scope.objects); const currentComponent = yield componentModel.loadVersion( // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! component.id.version, _this10.consumer.scope.objects); const mergeResults = yield (0, _mergeVersion().threeWayMerge)({ consumer: _this10.consumer, otherComponent: fsComponent, // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! otherVersion: currentlyUsedVersion, currentComponent, // $FlowFixMe // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! currentVersion: component.id.version, baseComponent }); mergeStatus.mergeResults = mergeResults; return mergeStatus; })(); } /** * 1) when there are conflicts and the strategy is "ours", don't write the imported component to * the filesystem, only update bitmap. * * 2) when there are conflicts and the strategy is "theirs", override the local changes by the * imported component. (similar to --override) * * 3) when there is no conflict or there are conflicts and the strategy is manual, write the files * according to the merge result. (done by applyModifiedVersion()) */ _updateComponentFilesPerMergeStrategy(componentMergeStatus) { const mergeResults = componentMergeStatus.mergeResults; if (!mergeResults) return null; const component = componentMergeStatus.componentWithDependencies.component; const files = component.files; const filesStatus = {}; if (mergeResults.hasConflicts && this.options.mergeStrategy === _mergeVersion().MergeOptions.ours) { // don't write the files to the filesystem, only bump the bitmap version. files.forEach(file => { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! filesStatus[(0, _utils().pathNormalizeToLinux)(file.relative)] = _mergeVersion().FileStatus.unchanged; }); this.consumer.bitMap.updateComponentId(component.id); this.consumer.bitMap.hasChanged = true; return filesStatus; } if (mergeResults.hasConflicts && this.options.mergeStrategy === _mergeVersion().MergeOptions.theirs) { // the local changes will be overridden (as if the user entered --override flag for this component) files.forEach(file => { // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! filesStatus[(0, _utils().pathNormalizeToLinux)(file.relative)] = _mergeVersion().FileStatus.updated; }); return filesStatus; } return (0, _checkoutVersion().applyModifiedVersion)(component.files, mergeResults, this.options.mergeStrategy, // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX! component.originallySharedDir); } /** * update the component files if they are modified and there is a merge strategy. * returns only the components that need to be written to the filesystem */ updateAllComponentsAccordingToMergeStrategy(componentsWithDependencies) { var _this11 = this; return (0, _bluebird().coroutine)(function* () { if (!_this11.options.merge) return componentsWithDependencies; const componentsStatusP = componentsWithDependencies.map(componentWithDependencies => { return _this11._getMergeStatus(componentWithDependencies); }); const componentsStatus = yield Promise.all(componentsStatusP); const componentWithConflict = componentsStatus.find(component => component.mergeResults && component.mergeResults.hasConflicts); if (componentWithConflict && !_this11.options.mergeStrategy) { _this11.options.mergeStrategy = yield (0, _mergeVersion().getMergeStrategyInteractive)(); } _this11.mergeStatus = {}; const componentsToWrite = componentsStatus.map(componentStatus => { const filesStatus = _this11._updateComponentFilesPerMergeStrategy(componentStatus); const componentWithDependencies = componentStatus.componentWithDependencies; if (!filesStatus) return componentWithDependencies; _this11.mergeStatus[componentWithDependencies.component.id.toStringWithoutVersion()] = filesStatus; const unchangedFiles = Object.keys(filesStatus).filter(file => filesStatus[file] === _mergeVersion().FileStatus.unchanged); if (unchangedFiles.length === Object.keys(filesStatus).length) { // all files are unchanged return null; } return componentWithDependencies; }); const removeNulls = _ramda().default.reject(_ramda().default.isNil); return removeNulls(componentsToWrite); })(); } _writeToFileSystem(componentsWithDependencies) { var _this12 = this; return (0, _bluebird().coroutine)(function* () { if (_this12.options.objectsOnly) return; const componentsToWrite = yield _this12.updateAllComponentsAccordingToMergeStrategy(componentsWithDependencies); const manyComponentsWriter = new (_manyComponentsWriter().default)({ consumer: _this12.consumer, componentsWithDependencies: componentsToWrite, writeToPath: _this12.options.writeToPath, writePackageJson: _this12.options.writePackageJson, addToRootPackageJson: _this12.options.writePackageJson, // no point to add to root if it doesn't have package.json writeConfig: _this12.options.writeConfig, writeDists: _this12.options.writeDists, installNpmPackages: _this12.options.installNpmPackages, verbose: _this12.options.verbose, override: _this12.options.override }); yield manyComponentsWriter.writeAll(); })(); } } exports.default = ImportComponents;