'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _regenerator;

function _load_regenerator() {
  return _regenerator = _interopRequireDefault(require('babel-runtime/regenerator'));
}

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _path;

function _load_path() {
  return _path = _interopRequireDefault(require('path'));
}

var _fsExtra;

function _load_fsExtra() {
  return _fsExtra = _interopRequireDefault(require('fs-extra'));
}

var _ramda;

function _load_ramda() {
  return _ramda = _interopRequireDefault(require('ramda'));
}

var _stringFormat;

function _load_stringFormat() {
  return _stringFormat = _interopRequireDefault(require('string-format'));
}

var _lodash;

function _load_lodash() {
  return _lodash = _interopRequireDefault(require('lodash.assignwith'));
}

var _lodash2;

function _load_lodash2() {
  return _lodash2 = _interopRequireDefault(require('lodash.groupby'));
}

var _lodash3;

function _load_lodash3() {
  return _lodash3 = _interopRequireDefault(require('lodash.unionby'));
}

var _ignore;

function _load_ignore() {
  return _ignore = _interopRequireDefault(require('ignore'));
}

var _arrayDifference;

function _load_arrayDifference() {
  return _arrayDifference = _interopRequireDefault(require('array-difference'));
}

var _analytics;

function _load_analytics() {
  return _analytics = require('../../../analytics/analytics');
}

var _utils;

function _load_utils() {
  return _utils = require('../../../utils');
}

var _consumer;

function _load_consumer() {
  return _consumer = require('../../../consumer');
}

var _bitMap;

function _load_bitMap() {
  return _bitMap = _interopRequireDefault(require('../../../consumer/bit-map'));
}

var _bitId;

function _load_bitId() {
  return _bitId = require('../../../bit-id');
}

var _constants;

function _load_constants() {
  return _constants = require('../../../constants');
}

var _logger;

function _load_logger() {
  return _logger = _interopRequireDefault(require('../../../logger/logger'));
}

var _exceptions;

function _load_exceptions() {
  return _exceptions = require('./exceptions');
}

var _componentMap;

function _load_componentMap() {
  return _componentMap = _interopRequireDefault(require('../../bit-map/component-map'));
}

var _generalError;

function _load_generalError() {
  return _generalError = _interopRequireDefault(require('../../../error/general-error'));
}

var _versionShouldBeRemoved;

function _load_versionShouldBeRemoved() {
  return _versionShouldBeRemoved = _interopRequireDefault(require('./exceptions/version-should-be-removed'));
}

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// can be a path or a DSL, e.g: tests/{PARENT}/{FILE_NAME}
var REGEX_DSL_PATTERN = /{([^}]+)}/g;

/**
 * validatePaths - validate if paths entered by user exist and if not throw an error
 *
 * @param {string[]} fileArray - array of paths
 * @returns {PathsStats} componentPathsStats
 */
function validatePaths(fileArray) {
  var componentPathsStats = {};
  fileArray.forEach(function (componentPath) {
    if (!(0, (_utils || _load_utils()).existsSync)(componentPath)) {
      throw new (_exceptions || _load_exceptions()).PathsNotExist([componentPath]);
    }
    componentPathsStats[componentPath] = {
      isDir: (0, (_utils || _load_utils()).isDir)(componentPath)
    };
  });
  return componentPathsStats;
}

/**
 * validate that no two files where added with the same id in the same bit add command
 */
var validateNoDuplicateIds = function validateNoDuplicateIds(addComponents) {
  var duplicateIds = {};
  var newGroupedComponents = (0, (_lodash2 || _load_lodash2()).default)(addComponents, 'componentId');
  Object.keys(newGroupedComponents).forEach(function (key) {
    if (newGroupedComponents[key].length > 1) duplicateIds[key] = newGroupedComponents[key];
  });
  if (!(_ramda || _load_ramda()).default.isEmpty(duplicateIds) && !(_ramda || _load_ramda()).default.isNil(duplicateIds)) throw new (_exceptions || _load_exceptions()).DuplicateIds(duplicateIds);
};

var AddComponents = function () {
  // id entered by the user
  function AddComponents(consumer, addProps) {
    _classCallCheck(this, AddComponents);

    this.consumer = consumer;
    this.bitMap = consumer.bitMap;
    this.componentPaths = addProps.componentPaths;
    this.id = addProps.id;
    this.main = addProps.main;
    this.namespace = addProps.namespace;
    this.tests = addProps.tests || [];
    this.exclude = addProps.exclude || [];
    this.override = addProps.override;
    this.trackDirFeature = addProps.trackDirFeature;
    this.origin = addProps.origin || (_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED;
    this.warnings = {};
  }

  /**
   * @param {string[]} files - array of file-paths from which it should search for the dsl patterns.
   * @param {*} filesWithPotentialDsl - array of file-path which may have DSL patterns
   *
   * @returns array of file-paths from 'files' parameter that match the patterns from 'filesWithPotentialDsl' parameter
   */
  // (default = false) replace the files array or only add files.


  _createClass(AddComponents, [{
    key: 'getFilesAccordingToDsl',
    value: function () {
      var _ref = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(files, filesWithPotentialDsl) {
        var _this = this;

        var filesListAllMatches, filesListFlatten, filesListUnique;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                filesListAllMatches = filesWithPotentialDsl.map(function () {
                  var _ref2 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(dsl) {
                    var filesListMatch;
                    return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
                      while (1) {
                        switch (_context2.prev = _context2.next) {
                          case 0:
                            filesListMatch = files.map(function () {
                              var _ref3 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(file) {
                                var fileInfo, generatedFile, matches, matchesAfterGitIgnore;
                                return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
                                  while (1) {
                                    switch (_context.prev = _context.next) {
                                      case 0:
                                        fileInfo = (0, (_utils || _load_utils()).calculateFileInfo)(file);
                                        generatedFile = (0, (_stringFormat || _load_stringFormat()).default)(dsl, fileInfo);
                                        _context.next = 4;
                                        return (0, (_utils || _load_utils()).glob)(generatedFile);

                                      case 4:
                                        matches = _context.sent;
                                        matchesAfterGitIgnore = _this.gitIgnore.filter(matches);
                                        return _context.abrupt('return', matchesAfterGitIgnore.filter(function (match) {
                                          return (_fsExtra || _load_fsExtra()).default.existsSync(match);
                                        }));

                                      case 7:
                                      case 'end':
                                        return _context.stop();
                                    }
                                  }
                                }, _callee, _this);
                              }));

                              return function (_x4) {
                                return _ref3.apply(this, arguments);
                              };
                            }());
                            return _context2.abrupt('return', Promise.all(filesListMatch));

                          case 2:
                          case 'end':
                            return _context2.stop();
                        }
                      }
                    }, _callee2, _this);
                  }));

                  return function (_x3) {
                    return _ref2.apply(this, arguments);
                  };
                }());
                _context3.t0 = (_ramda || _load_ramda()).default;
                _context3.next = 4;
                return Promise.all(filesListAllMatches);

              case 4:
                _context3.t1 = _context3.sent;
                filesListFlatten = _context3.t0.flatten.call(_context3.t0, _context3.t1);
                filesListUnique = (_ramda || _load_ramda()).default.uniq(filesListFlatten);
                return _context3.abrupt('return', filesListUnique.map(function (file) {
                  var relativeToConsumer = _this.consumer.getPathRelativeToConsumer(file);
                  return (0, (_utils || _load_utils()).pathNormalizeToLinux)(relativeToConsumer);
                }));

              case 8:
              case 'end':
                return _context3.stop();
            }
          }
        }, _callee3, this);
      }));

      function getFilesAccordingToDsl(_x, _x2) {
        return _ref.apply(this, arguments);
      }

      return getFilesAccordingToDsl;
    }()
  }, {
    key: 'addToBitMap',
    value: function addToBitMap(_ref4) {
      var _this2 = this;

      var componentId = _ref4.componentId,
          files = _ref4.files,
          mainFile = _ref4.mainFile,
          trackDir = _ref4.trackDir;

      var getComponentMap = function getComponentMap() {
        if (_this2.trackDirFeature) {
          return _this2.bitMap.addFilesToComponent({ componentId, files });
        }
        return _this2.bitMap.addComponent({
          componentId,
          files,
          mainFile,
          trackDir,
          origin: (_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED,
          override: _this2.override
        });
      };
      var componentMap = getComponentMap();
      return { id: componentId.toString(), files: componentMap.files };
    }

    /**
     * Add or update existing (imported and new) component according to bitmap
     * there are 3 options:
     * 1. a user is adding a new component. there is no record for this component in bit.map
     * 2. a user is updating an existing component. there is a record for this component in bit.map
     * 3. some or all the files of this component were previously added as another component-id.
     */

  }, {
    key: 'addOrUpdateComponentInBitMap',
    value: function addOrUpdateComponentInBitMap(component) {
      var _this3 = this;

      var consumerPath = this.consumer.getPath();
      var parsedBitId = component.componentId;
      var files = component.files;
      var foundComponentFromBitMap = this.bitMap.getComponentIfExist(component.componentId, {
        ignoreScopeAndVersion: true
      });
      component.files = files.map(function (file) {
        // $FlowFixMe null is removed later on
        if ((0, (_utils || _load_utils()).isAutoGeneratedFile)((_path || _load_path()).default.join(consumerPath, file.relativePath))) return null;
        var caseSensitive = false;
        var existingIdOfFile = _this3.bitMap.getComponentIdByPath(file.relativePath, caseSensitive);
        var idOfFileIsDifferent = existingIdOfFile && !existingIdOfFile.isEqual(parsedBitId);
        var existingComponentOfFile = existingIdOfFile ? _this3.bitMap.getComponent(existingIdOfFile) : undefined;
        var isImported = foundComponentFromBitMap && foundComponentFromBitMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED || existingComponentOfFile && existingComponentOfFile.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED;
        if (isImported) {
          // throw error in case user didn't add id to imported component or the id is incorrect
          if (!_this3.id) throw new (_exceptions || _load_exceptions()).MissingComponentIdForImportedComponent(parsedBitId.toStringWithoutVersion());
          if (idOfFileIsDifferent) {
            var existingIdWithoutVersion = existingIdOfFile.toStringWithoutVersion();
            // $FlowFixMe $this.id is not null at this point
            throw new (_exceptions || _load_exceptions()).IncorrectIdForImportedComponent(existingIdWithoutVersion, _this3.id, file.relativePath);
          }
          delete component.trackDir;
        } else if (idOfFileIsDifferent) {
          // not imported component file but exists in bitmap
          if (_this3.warnings[existingIdOfFile]) _this3.warnings[existingIdOfFile].push(file.relativePath);else _this3.warnings[existingIdOfFile] = [file.relativePath];
          // $FlowFixMe null is removed later on
          return null;
        }
        return file;
      }).filter(function (file) {
        return file;
      });
      if ((_ramda || _load_ramda()).default.isEmpty(component.files)) return null;
      return this.addToBitMap(component);
    }

    // remove excluded files from file list

  }, {
    key: 'removeExcludedFiles',
    value: function () {
      var _ref5 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(componentsWithFiles) {
        var files, resolvedExcludedFiles;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                files = (_ramda || _load_ramda()).default.flatten(componentsWithFiles.map(function (x) {
                  return x.files.map(function (i) {
                    return i.relativePath;
                  });
                }));
                _context4.next = 3;
                return this.getFilesAccordingToDsl(files, this.exclude);

              case 3:
                resolvedExcludedFiles = _context4.sent;

                componentsWithFiles.forEach(function (componentWithFiles) {
                  var mainFile = componentWithFiles.mainFile ? (0, (_utils || _load_utils()).pathNormalizeToLinux)(componentWithFiles.mainFile) : undefined;
                  if (resolvedExcludedFiles.includes(mainFile)) {
                    componentWithFiles.files = [];
                  } else {
                    // if mainFile is excluded, exclude all files
                    componentWithFiles.files = componentWithFiles.files.filter(function (key) {
                      return !resolvedExcludedFiles.includes(key.relativePath);
                    });
                  }
                });

              case 5:
              case 'end':
                return _context4.stop();
            }
          }
        }, _callee4, this);
      }));

      function removeExcludedFiles(_x5) {
        return _ref5.apply(this, arguments);
      }

      return removeExcludedFiles;
    }()

    /**
     * if the id is already saved in bitmap file, it might have more data (such as scope, version)
     * use that id instead.
     */

  }, {
    key: '_getIdAccordingToExistingComponent',
    value: function _getIdAccordingToExistingComponent(currentId) {
      var existingComponentId = this.bitMap.getExistingBitId(currentId, false);
      var componentExists = Boolean(existingComponentId);
      if (componentExists && this.bitMap.getComponent(existingComponentId).origin === (_constants || _load_constants()).COMPONENT_ORIGINS.NESTED) {
        throw new (_generalError || _load_generalError()).default(`One of your dependencies (${existingComponentId}) has already the same namespace and name.
    If you're trying to add a new component, please choose a new namespace or name.
    If you're trying to update a dependency component, please re-import it individually`);
      }
      if (currentId.includes((_constants || _load_constants()).VERSION_DELIMITER)) {
        if (!existingComponentId || // this id is new, it shouldn't have a version
        !existingComponentId.hasVersion() || // this component is new, it shouldn't have a version
        // user shouldn't add files to a an existing component with different version
        // $FlowFixMe this function gets called only when this.id is set
        existingComponentId.version !== (_bitId || _load_bitId()).BitId.getVersionOnlyFromString(this.id)) {
          // $FlowFixMe this.id is defined here
          throw new (_versionShouldBeRemoved || _load_versionShouldBeRemoved()).default(this.id);
        }
      }
      return existingComponentId || (_bitId || _load_bitId()).BitId.parse(currentId, false);
    }

    /**
     * used for updating main file if exists or doesn't exists
     */

  }, {
    key: '_addMainFileToFiles',
    value: function _addMainFileToFiles(files) {
      var _this4 = this;

      var mainFile = this.main;
      if (mainFile && mainFile.match(REGEX_DSL_PATTERN)) {
        // it's a DSL
        files.forEach(function (file) {
          var fileInfo = (0, (_utils || _load_utils()).calculateFileInfo)(file.relativePath);
          var generatedFile = (0, (_stringFormat || _load_stringFormat()).default)(mainFile, fileInfo);
          var foundFile = (_ramda || _load_ramda()).default.find((_ramda || _load_ramda()).default.propEq('relativePath', (0, (_utils || _load_utils()).pathNormalizeToLinux)(generatedFile)))(files);
          if (foundFile) {
            mainFile = foundFile.relativePath;
          }
          if ((_fsExtra || _load_fsExtra()).default.existsSync(generatedFile) && !foundFile) {
            var shouldIgnore = _this4.gitIgnore.ignores(generatedFile);
            if (shouldIgnore) {
              // check if file is in exclude list
              throw new (_exceptions || _load_exceptions()).ExcludedMainFile(generatedFile);
            }
            files.push({
              relativePath: (0, (_utils || _load_utils()).pathNormalizeToLinux)(generatedFile),
              test: false,
              name: (_path || _load_path()).default.basename(generatedFile)
            });
            mainFile = generatedFile;
          }
        });
      }
      if (!mainFile) return undefined;
      var mainFileRelativeToConsumer = this.consumer.getPathRelativeToConsumer(mainFile);
      var mainPath = this.consumer.toAbsolutePath(mainFileRelativeToConsumer);
      if ((_fsExtra || _load_fsExtra()).default.existsSync(mainPath)) {
        var shouldIgnore = this.gitIgnore.ignores(mainFileRelativeToConsumer);
        if (shouldIgnore) throw new (_exceptions || _load_exceptions()).ExcludedMainFile(mainFileRelativeToConsumer);
        if ((0, (_utils || _load_utils()).isDir)(mainPath)) {
          throw new (_exceptions || _load_exceptions()).MainFileIsDir(mainPath);
        }
        var foundFile = (_ramda || _load_ramda()).default.find((_ramda || _load_ramda()).default.propEq('relativePath', (0, (_utils || _load_utils()).pathNormalizeToLinux)(mainFileRelativeToConsumer)))(files);
        if (!foundFile) {
          files.push({
            relativePath: (0, (_utils || _load_utils()).pathNormalizeToLinux)(mainFileRelativeToConsumer),
            test: false,
            name: (_path || _load_path()).default.basename(mainFileRelativeToConsumer)
          });
        }
        return mainFileRelativeToConsumer;
      }
      return mainFile;
    }
  }, {
    key: '_mergeTestFilesWithFiles',
    value: function () {
      var _ref6 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee5(files) {
        var _this5 = this;

        var testFiles, resolvedTestFiles;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                if ((_ramda || _load_ramda()).default.isEmpty(this.tests)) {
                  _context5.next = 6;
                  break;
                }

                _context5.next = 3;
                return this.getFilesAccordingToDsl(files.map(function (file) {
                  return file.relativePath;
                }), this.tests);

              case 3:
                _context5.t0 = _context5.sent;
                _context5.next = 7;
                break;

              case 6:
                _context5.t0 = [];

              case 7:
                testFiles = _context5.t0;
                resolvedTestFiles = testFiles.map(function (testFile) {
                  if ((0, (_utils || _load_utils()).isDir)((_path || _load_path()).default.join(_this5.consumer.getPath(), testFile))) throw new (_exceptions || _load_exceptions()).TestIsDirectory(testFile);
                  return {
                    relativePath: testFile,
                    test: true,
                    name: (_path || _load_path()).default.basename(testFile)
                  };
                });
                return _context5.abrupt('return', (0, (_lodash3 || _load_lodash3()).default)(resolvedTestFiles, files, 'relativePath'));

              case 10:
              case 'end':
                return _context5.stop();
            }
          }
        }, _callee5, this);
      }));

      function _mergeTestFilesWithFiles(_x6) {
        return _ref6.apply(this, arguments);
      }

      return _mergeTestFilesWithFiles;
    }()

    /**
     * given the component paths, prepare the id, mainFile and files to be added later on to bitmap
     * the id of the component is either entered by the user or, if not entered, concluded by the path.
     * e.g. bar/foo.js, the id would be bar/foo.
     * in case bitmap has already the same id, the complete id is taken from bitmap (see _getIdAccordingToExistingComponent)
     */

  }, {
    key: 'addOneComponent',
    value: function () {
      var _ref7 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee7(componentPathsStats) {
        var _this6 = this;

        var finalBitId, componentsWithFilesP, componentsWithFiles, componentId, files, groupedComponents, uniqComponents;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee7$(_context7) {
          while (1) {
            switch (_context7.prev = _context7.next) {
              case 0:
                finalBitId = void 0; // final id to use for bitmap file

                if (this.id) {
                  finalBitId = this._getIdAccordingToExistingComponent(this.id);
                }

                componentsWithFilesP = Object.keys(componentPathsStats).map(function () {
                  var _ref8 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee6(componentPath) {
                    var relativeComponentPath, matches, filteredMatches, filteredMatchedFiles, _resolvedMainFile, absoluteComponentPath, splitPath, lastDir, nameSpaceOrDir, idFromPath, _trackDir, absolutePath, pathParsed, relativeFilePath, dirName, nameSpaceOrLastDir, _idFromPath, files, resolvedMainFile;

                    return (_regenerator || _load_regenerator()).default.wrap(function _callee6$(_context6) {
                      while (1) {
                        switch (_context6.prev = _context6.next) {
                          case 0:
                            if (!componentPathsStats[componentPath].isDir) {
                              _context6.next = 16;
                              break;
                            }

                            relativeComponentPath = _this6.consumer.getPathRelativeToConsumer(componentPath);
                            _context6.next = 4;
                            return (0, (_utils || _load_utils()).glob)((_path || _load_path()).default.join(relativeComponentPath, '**'), {
                              cwd: _this6.consumer.getPath(),
                              nodir: true
                            });

                          case 4:
                            matches = _context6.sent;
                            filteredMatches = _this6.gitIgnore.filter(matches);

                            if (filteredMatches.length) {
                              _context6.next = 8;
                              break;
                            }

                            throw new (_exceptions || _load_exceptions()).EmptyDirectory();

                          case 8:
                            filteredMatchedFiles = filteredMatches.map(function (match) {
                              return { relativePath: (0, (_utils || _load_utils()).pathNormalizeToLinux)(match), test: false, name: (_path || _load_path()).default.basename(match) };
                            });

                            // merge test files with files

                            _context6.next = 11;
                            return _this6._mergeTestFilesWithFiles(filteredMatchedFiles);

                          case 11:
                            filteredMatchedFiles = _context6.sent;
                            _resolvedMainFile = _this6._addMainFileToFiles(filteredMatchedFiles);


                            if (!finalBitId) {
                              absoluteComponentPath = (_path || _load_path()).default.resolve(componentPath);
                              splitPath = absoluteComponentPath.split((_path || _load_path()).default.sep);
                              lastDir = splitPath[splitPath.length - 1];
                              nameSpaceOrDir = _this6.namespace || splitPath[splitPath.length - 2];
                              idFromPath = (_bitId || _load_bitId()).BitId.getValidBitId(nameSpaceOrDir, lastDir);

                              finalBitId = _this6._getIdAccordingToExistingComponent(idFromPath.toString());
                            }

                            _trackDir = Object.keys(componentPathsStats).length === 1 && !_this6.exclude.length && _this6.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED ? relativeComponentPath : undefined;
                            return _context6.abrupt('return', { componentId: finalBitId, files: filteredMatchedFiles, mainFile: _resolvedMainFile, trackDir: _trackDir });

                          case 16:
                            // is file
                            absolutePath = (_path || _load_path()).default.resolve(componentPath);
                            pathParsed = (_path || _load_path()).default.parse(absolutePath);
                            relativeFilePath = _this6.consumer.getPathRelativeToConsumer(componentPath);

                            if (!finalBitId) {
                              dirName = pathParsed.dir;

                              if (!dirName) {
                                dirName = (_path || _load_path()).default.dirname(absolutePath);
                              }
                              nameSpaceOrLastDir = _this6.namespace || (_ramda || _load_ramda()).default.last(dirName.split((_path || _load_path()).default.sep));
                              _idFromPath = (_bitId || _load_bitId()).BitId.getValidBitId(nameSpaceOrLastDir, pathParsed.name);

                              finalBitId = _this6._getIdAccordingToExistingComponent(_idFromPath.toString());
                            }

                            files = [{ relativePath: (0, (_utils || _load_utils()).pathNormalizeToLinux)(relativeFilePath), test: false, name: (_path || _load_path()).default.basename(relativeFilePath) }];
                            _context6.next = 23;
                            return _this6._mergeTestFilesWithFiles(files);

                          case 23:
                            files = _context6.sent;
                            resolvedMainFile = _this6._addMainFileToFiles(files);
                            return _context6.abrupt('return', { componentId: finalBitId, files, mainFile: resolvedMainFile });

                          case 26:
                          case 'end':
                            return _context6.stop();
                        }
                      }
                    }, _callee6, _this6);
                  }));

                  return function (_x8) {
                    return _ref8.apply(this, arguments);
                  };
                }());
                _context7.next = 5;
                return Promise.all(componentsWithFilesP);

              case 5:
                componentsWithFiles = _context7.sent;

                if ((_ramda || _load_ramda()).default.isEmpty(this.exclude)) {
                  _context7.next = 9;
                  break;
                }

                _context7.next = 9;
                return this.removeExcludedFiles(componentsWithFiles);

              case 9:
                componentId = finalBitId;

                componentsWithFiles = componentsWithFiles.filter(function (componentWithFiles) {
                  return componentWithFiles.files.length;
                });

                // $FlowFixMe

                if (!(componentsWithFiles.length === 0)) {
                  _context7.next = 13;
                  break;
                }

                return _context7.abrupt('return', { componentId, files: [] });

              case 13:
                if (!(componentsWithFiles.length === 1)) {
                  _context7.next = 15;
                  break;
                }

                return _context7.abrupt('return', componentsWithFiles[0]);

              case 15:
                files = componentsWithFiles.reduce(function (a, b) {
                  return a.concat(b.files);
                }, []);
                groupedComponents = (0, (_lodash2 || _load_lodash2()).default)(files, 'relativePath');
                uniqComponents = Object.keys(groupedComponents).map(function (key) {
                  return (_lodash || _load_lodash()).default.apply(undefined, [{}].concat(_toConsumableArray(groupedComponents[key]), [function (val1, val2) {
                    return val1 || val2;
                  }]));
                });
                // $FlowFixMe

                return _context7.abrupt('return', {
                  componentId,
                  files: uniqComponents,
                  mainFile: (_ramda || _load_ramda()).default.head(componentsWithFiles).mainFile,
                  trackDir: (_ramda || _load_ramda()).default.head(componentsWithFiles).trackDir
                });

              case 19:
              case 'end':
                return _context7.stop();
            }
          }
        }, _callee7, this);
      }));

      function addOneComponent(_x7) {
        return _ref7.apply(this, arguments);
      }

      return addOneComponent;
    }()
  }, {
    key: 'getIgnoreList',
    value: function getIgnoreList() {
      var ignoreList = (0, (_utils || _load_utils()).retrieveIgnoreList)(this.consumer.getPath());
      var importedComponents = this.bitMap.getAllComponents((_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED);
      var distDirsOfImportedComponents = Object.keys(importedComponents).map(function (key) {
        return (0, (_utils || _load_utils()).pathJoinLinux)(importedComponents[key].rootDir, (_constants || _load_constants()).DEFAULT_DIST_DIRNAME, '**');
      });
      var configsToIgnore = this.bitMap.getConfigDirsAndFilesToIgnore(this.consumer.getPath());
      var configDirs = configsToIgnore.dirs.map(function (dir) {
        return (0, (_utils || _load_utils()).pathJoinLinux)(dir, '**');
      });
      ignoreList = ignoreList.concat(distDirsOfImportedComponents);
      ignoreList = ignoreList.concat(configsToIgnore.files);
      ignoreList = ignoreList.concat(configDirs);
      return ignoreList;
    }
  }, {
    key: 'add',
    value: function () {
      var _ref9 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee8() {
        var _this7 = this;

        var missingFiles, componentPathsStats, resolvedComponentPathsWithoutGitIgnore, resolvedExcludedFiles, resolvedComponentPathsWithGitIgnore, diff, resolvedTestFiles, isMultipleComponents, addedComponents, testToRemove, addedP, added, addedOne, addedResult;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee8$(_context8) {
          while (1) {
            switch (_context8.prev = _context8.next) {
              case 0:
                this.ignoreList = this.getIgnoreList();
                this.gitIgnore = (0, (_ignore || _load_ignore()).default)().add(this.ignoreList); // add ignore list

                // check unknown test files
                missingFiles = (0, (_utils || _load_utils()).getMissingTestFiles)(this.tests);

                if ((_ramda || _load_ramda()).default.isEmpty(missingFiles)) {
                  _context8.next = 5;
                  break;
                }

                throw new (_exceptions || _load_exceptions()).PathsNotExist(missingFiles);

              case 5:
                componentPathsStats = {};
                _context8.t0 = (_ramda || _load_ramda()).default;
                _context8.next = 9;
                return Promise.all(this.componentPaths.map(function (componentPath) {
                  return (0, (_utils || _load_utils()).glob)(componentPath);
                }));

              case 9:
                _context8.t1 = _context8.sent;
                resolvedComponentPathsWithoutGitIgnore = _context8.t0.flatten.call(_context8.t0, _context8.t1);
                _context8.next = 13;
                return this.getFilesAccordingToDsl(resolvedComponentPathsWithoutGitIgnore, this.exclude);

              case 13:
                resolvedExcludedFiles = _context8.sent;

                this.ignoreList = [].concat(_toConsumableArray(this.ignoreList), _toConsumableArray(resolvedExcludedFiles));
                this.gitIgnore = (0, (_ignore || _load_ignore()).default)().add(this.ignoreList); // add ignore list

                resolvedComponentPathsWithGitIgnore = this.gitIgnore.filter(resolvedComponentPathsWithoutGitIgnore);

                // Run diff on both arrays to see what was filtered out because of the gitignore file

                diff = (0, (_arrayDifference || _load_arrayDifference()).default)(resolvedComponentPathsWithGitIgnore, resolvedComponentPathsWithoutGitIgnore);

                if (!(!(_ramda || _load_ramda()).default.isEmpty(this.tests) && this.id && (_ramda || _load_ramda()).default.isEmpty(resolvedComponentPathsWithoutGitIgnore))) {
                  _context8.next = 27;
                  break;
                }

                _context8.t2 = (_ramda || _load_ramda()).default;
                _context8.next = 22;
                return Promise.all(this.tests.map(function (componentPath) {
                  return (0, (_utils || _load_utils()).glob)(componentPath);
                }));

              case 22:
                _context8.t3 = _context8.sent;
                resolvedTestFiles = _context8.t2.flatten.call(_context8.t2, _context8.t3);

                componentPathsStats = validatePaths(resolvedTestFiles);
                _context8.next = 34;
                break;

              case 27:
                if (!(_ramda || _load_ramda()).default.isEmpty(resolvedComponentPathsWithoutGitIgnore)) {
                  _context8.next = 29;
                  break;
                }

                throw new (_exceptions || _load_exceptions()).PathsNotExist(this.componentPaths);

              case 29:
                if ((_ramda || _load_ramda()).default.isEmpty(resolvedComponentPathsWithGitIgnore)) {
                  _context8.next = 33;
                  break;
                }

                componentPathsStats = validatePaths(resolvedComponentPathsWithGitIgnore);
                _context8.next = 34;
                break;

              case 33:
                throw new (_exceptions || _load_exceptions()).NoFiles(diff);

              case 34:
                // if a user entered multiple paths and entered an id, he wants all these paths to be one component
                // conversely, if a user entered multiple paths without id, he wants each dir as an individual component
                isMultipleComponents = Object.keys(componentPathsStats).length > 1 && !this.id;
                addedComponents = [];

                if (!isMultipleComponents) {
                  _context8.next = 55;
                  break;
                }

                (_logger || _load_logger()).default.debug('bit add - multiple components');

                if ((_ramda || _load_ramda()).default.isEmpty(this.tests)) {
                  _context8.next = 44;
                  break;
                }

                _context8.next = 41;
                return this.getFilesAccordingToDsl(Object.keys(componentPathsStats), this.tests);

              case 41:
                _context8.t4 = _context8.sent;
                _context8.next = 45;
                break;

              case 44:
                _context8.t4 = [];

              case 45:
                testToRemove = _context8.t4;

                testToRemove.forEach(function (test) {
                  return delete componentPathsStats[(_path || _load_path()).default.normalize(test)];
                });
                addedP = Object.keys(componentPathsStats).map(function (onePath) {
                  var oneComponentPathStat = { [onePath]: componentPathsStats[onePath] };
                  return _this7.addOneComponent(oneComponentPathStat);
                });
                _context8.next = 50;
                return Promise.all(addedP);

              case 50:
                added = _context8.sent;

                validateNoDuplicateIds(added);
                added.forEach(function (component) {
                  if (!(_ramda || _load_ramda()).default.isEmpty(component.files)) {
                    var addedComponent = _this7.addOrUpdateComponentInBitMap(component);
                    if (addedComponent) addedComponents.push(addedComponent);
                  }
                });
                _context8.next = 60;
                break;

              case 55:
                (_logger || _load_logger()).default.debug('bit add - one component');
                // when a user enters more than one directory, he would like to keep the directories names
                // so then when a component is imported, it will write the files into the original directories
                _context8.next = 58;
                return this.addOneComponent(componentPathsStats);

              case 58:
                addedOne = _context8.sent;

                if (!(_ramda || _load_ramda()).default.isEmpty(addedOne.files)) {
                  addedResult = this.addOrUpdateComponentInBitMap(addedOne);

                  if (addedResult) addedComponents.push(addedResult);
                }

              case 60:
                (_analytics || _load_analytics()).Analytics.setExtraData('num_components', addedComponents.length);
                return _context8.abrupt('return', { addedComponents, warnings: this.warnings });

              case 62:
              case 'end':
                return _context8.stop();
            }
          }
        }, _callee8, this);
      }));

      function add() {
        return _ref9.apply(this, arguments);
      }

      return add;
    }()
  }]);

  return AddComponents;
}();

exports.default = AddComponents;