@teambit/tracker 1.0.1174 → 1.0.1176
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/add-cmd.d.ts +2 -1
- package/dist/add-cmd.js +5 -3
- package/dist/add-cmd.js.map +1 -1
- package/dist/add-components.d.ts +35 -2
- package/dist/add-components.js +259 -40
- package/dist/add-components.js.map +1 -1
- package/dist/add-components.spec.d.ts +1 -0
- package/dist/add-components.spec.js +205 -0
- package/dist/add-components.spec.js.map +1 -0
- package/dist/determine-main-file.js +10 -1
- package/dist/determine-main-file.js.map +1 -1
- package/dist/determine-main-file.spec.d.ts +1 -0
- package/dist/determine-main-file.spec.js +231 -0
- package/dist/determine-main-file.spec.js.map +1 -0
- package/dist/track-workspace-root.spec.d.ts +1 -0
- package/dist/track-workspace-root.spec.js +377 -0
- package/dist/track-workspace-root.spec.js.map +1 -0
- package/dist/tracker.main.runtime.d.ts +8 -1
- package/dist/tracker.main.runtime.js +2 -1
- package/dist/tracker.main.runtime.js.map +1 -1
- package/package.json +20 -16
- /package/dist/{preview-1789911586102.js → preview-1790183760587.js} +0 -0
package/dist/add-components.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.addMultipleFromResolvedTrackData = addMultipleFromResolvedTrackData;
|
|
7
|
+
exports.configForWorkspaceRoot = configForWorkspaceRoot;
|
|
7
8
|
exports.default = void 0;
|
|
8
9
|
function _arrayDifference() {
|
|
9
10
|
const data = _interopRequireDefault(require("array-difference"));
|
|
@@ -175,6 +176,8 @@ function _determineMainFile() {
|
|
|
175
176
|
}
|
|
176
177
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
177
178
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
179
|
+
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; }
|
|
180
|
+
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; }
|
|
178
181
|
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; }
|
|
179
182
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
180
183
|
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); }
|
|
@@ -183,7 +186,6 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
|
|
|
183
186
|
|
|
184
187
|
const REGEX_DSL_PATTERN = /{([^}]+)}/g;
|
|
185
188
|
class AddComponents {
|
|
186
|
-
// only bit-add (not bit-create/new) should handle out-of-sync scenario
|
|
187
189
|
constructor(context, addProps) {
|
|
188
190
|
_defineProperty(this, "workspace", void 0);
|
|
189
191
|
_defineProperty(this, "consumer", void 0);
|
|
@@ -204,6 +206,8 @@ class AddComponents {
|
|
|
204
206
|
// helpful for out-of-sync
|
|
205
207
|
_defineProperty(this, "config", void 0);
|
|
206
208
|
_defineProperty(this, "shouldHandleOutOfSync", void 0);
|
|
209
|
+
// only bit-add (not bit-create/new) should handle out-of-sync scenario
|
|
210
|
+
_defineProperty(this, "root", void 0);
|
|
207
211
|
this.workspace = context.workspace;
|
|
208
212
|
this.consumer = context.workspace.consumer;
|
|
209
213
|
this.bitMap = this.consumer.bitMap;
|
|
@@ -222,6 +226,40 @@ class AddComponents {
|
|
|
222
226
|
this.defaultScope = addProps.defaultScope;
|
|
223
227
|
this.config = addProps.config;
|
|
224
228
|
this.shouldHandleOutOfSync = addProps.shouldHandleOutOfSync;
|
|
229
|
+
this.root = addProps.root;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* tracking the workspace root turns the workspace itself into a component: it owns every file no
|
|
234
|
+
* other component claims, `.bitmap` included, and every other component becomes a member of it.
|
|
235
|
+
* "bit add ." is one keystroke away from "git add .", which means something else entirely, so the
|
|
236
|
+
* intent is spelled out rather than inferred from the path.
|
|
237
|
+
*
|
|
238
|
+
* only the workspace root needs the flag, and it is the only thing the flag does: "bit add ." from
|
|
239
|
+
* a sub-directory names that directory, not the root, and is tracked like any other path.
|
|
240
|
+
*
|
|
241
|
+
* a workspace that already has a root does not ask again. what the flag guards against is creating
|
|
242
|
+
* one by accident, and there is none to create here - the add either refreshes the root that exists
|
|
243
|
+
* or names a second owner for ".", which has its own message saying who holds it.
|
|
244
|
+
*/
|
|
245
|
+
/**
|
|
246
|
+
* the paths reach here as the user typed them - relative to the cwd, or absolute - so the workspace
|
|
247
|
+
* root arrives as ".", as "", or as the workspace path itself, depending on where the command ran.
|
|
248
|
+
*/
|
|
249
|
+
isWorkspaceRootPath(onePath) {
|
|
250
|
+
return ((0, _legacy5().pathNormalizeToLinux)(this.consumer.getPathRelativeToConsumer(onePath)) || _legacy3().WORKSPACE_ROOT_DIR) === _legacy3().WORKSPACE_ROOT_DIR;
|
|
251
|
+
}
|
|
252
|
+
throwForWorkspaceRootFlagMismatch(resolvedPaths) {
|
|
253
|
+
const tracksRoot = resolvedPaths.some(onePath => this.isWorkspaceRootPath(onePath));
|
|
254
|
+
if (tracksRoot && !this.root && !this.bitMap.getWorkspaceRootMap()) {
|
|
255
|
+
throw new (_bitError().BitError)(`unable to track the workspace root without the --root flag.
|
|
256
|
+
it makes the workspace itself a component - it owns every file no other component claims, .bitmap included, and every other component becomes a member of it.
|
|
257
|
+
if that is what you want, run "bit add . --root". to track a component, pass its directory, e.g. "bit add my-component"`);
|
|
258
|
+
}
|
|
259
|
+
if (!tracksRoot && this.root) {
|
|
260
|
+
throw new (_bitError().BitError)(`the --root flag tracks the workspace root, but none of the given paths is the workspace root.
|
|
261
|
+
run "bit add . --root" from the workspace root, or drop the flag to track the given paths as ordinary components`);
|
|
262
|
+
}
|
|
225
263
|
}
|
|
226
264
|
async add() {
|
|
227
265
|
this.ignoreList = await this.getIgnoreList();
|
|
@@ -246,6 +284,7 @@ class AddComponents {
|
|
|
246
284
|
throw new (_addingIndividualFiles().AddingIndividualFiles)(compPath);
|
|
247
285
|
}
|
|
248
286
|
});
|
|
287
|
+
this.throwForWorkspaceRootFlagMismatch(Object.keys(componentPathsStats));
|
|
249
288
|
if (Object.keys(componentPathsStats).length > 1 && this.id) {
|
|
250
289
|
throw new (_bitError().BitError)(`the --id flag (${this.id}) is used for a single component only, however, got ${this.componentPaths.length} paths`);
|
|
251
290
|
}
|
|
@@ -340,17 +379,32 @@ class AddComponents {
|
|
|
340
379
|
const foundComponentFromBitMap = this.bitMap.getComponentIfExist(component.componentId, {
|
|
341
380
|
ignoreVersion: true
|
|
342
381
|
});
|
|
382
|
+
// the workspace-root component owns every file no other component claims, so it "owns" a file
|
|
383
|
+
// only until a more specific component is added for it: the component being added wins, and the
|
|
384
|
+
// root subtracts the new root-dir from its own file-set on the next scan. the one file it cannot
|
|
385
|
+
// give away is its main file - without it, it fails to load from the next scan on.
|
|
386
|
+
const workspaceRootMap = this.bitMap.getWorkspaceRootMap();
|
|
387
|
+
const isWorkspaceRoot = component.trackDir === _legacy3().WORKSPACE_ROOT_DIR;
|
|
388
|
+
if (workspaceRootMap && !isWorkspaceRoot && !parsedBitId.isEqualWithoutVersion(workspaceRootMap.id)) {
|
|
389
|
+
throwForTakingWorkspaceRootMainFile(workspaceRootMap, parsedBitId, (0, _legacy5().pathNormalizeToLinux)(component.trackDir));
|
|
390
|
+
}
|
|
343
391
|
const componentFilesP = files.map(async file => {
|
|
344
392
|
// $FlowFixMe null is removed later on
|
|
345
393
|
const filePath = path().join(consumerPath, file.relativePath);
|
|
394
|
+
// the workspace map carries the auto-generated banner, but the root component tracks it on
|
|
395
|
+
// purpose (see isWorkspaceMapFile), and the rescan keeps it. the add-time file-set does too.
|
|
346
396
|
const isAutoGenerated = await isAutoGeneratedFile(filePath);
|
|
347
|
-
|
|
397
|
+
// trackAllFiles keeps the files bit generates, and the rescan never looks at the banner at all
|
|
398
|
+
// (see getFilesByDir) - so dropping them here would leave the add-time file-set short of it.
|
|
399
|
+
const keepAutoGenerated = this.consumer.config.trackAllFiles || isWorkspaceRoot && (0, _legacy3().isWorkspaceMapFile)(file.relativePath);
|
|
400
|
+
if (isAutoGenerated && !keepAutoGenerated) {
|
|
348
401
|
return null;
|
|
349
402
|
}
|
|
350
403
|
const caseSensitive = false;
|
|
351
404
|
const existingIdOfFile = this.bitMap.getComponentIdByPath(file.relativePath, caseSensitive);
|
|
352
405
|
const idOfFileIsDifferent = existingIdOfFile && !existingIdOfFile.isEqual(parsedBitId);
|
|
353
|
-
|
|
406
|
+
const ownedByWorkspaceRoot = Boolean(workspaceRootMap && existingIdOfFile?.isEqualWithoutVersion(workspaceRootMap.id));
|
|
407
|
+
if (idOfFileIsDifferent && !ownedByWorkspaceRoot) {
|
|
354
408
|
// not imported component file but exists in bitmap
|
|
355
409
|
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
|
|
356
410
|
if (this.warnings.alreadyUsed[existingIdOfFile]) {
|
|
@@ -389,7 +443,9 @@ class AddComponents {
|
|
|
389
443
|
return foundComponentFromBitMap;
|
|
390
444
|
}
|
|
391
445
|
}
|
|
392
|
-
|
|
446
|
+
// the root's files are whatever the scan says. a component nested since the previous add owns the
|
|
447
|
+
// files the previous entry listed for the root, so they are not merged back.
|
|
448
|
+
if (!this.override && foundComponentFromBitMap && !isWorkspaceRoot) {
|
|
393
449
|
this._updateFilesWithCurrentLetterCases(foundComponentFromBitMap, componentFiles);
|
|
394
450
|
component.files = this._mergeFilesWithExistingComponentMapFiles(componentFiles, foundComponentFromBitMap.files);
|
|
395
451
|
} else {
|
|
@@ -404,7 +460,8 @@ class AddComponents {
|
|
|
404
460
|
if (this.trackDirFeature) throw new Error('track dir should not calculate the rootDir');
|
|
405
461
|
if (foundComponentFromBitMap) return foundComponentFromBitMap.rootDir;
|
|
406
462
|
if (!trackDir) throw new Error(`addOrUpdateComponentInBitMap expect to have trackDir for non-legacy workspace`);
|
|
407
|
-
|
|
463
|
+
// every file in the workspace is inside the workspace root, so there is nothing to check.
|
|
464
|
+
const fileNotInsideTrackDir = trackDir === _legacy3().WORKSPACE_ROOT_DIR ? undefined : componentFiles.find(file => !(0, _legacy5().pathNormalizeToLinux)(file.relativePath).startsWith(`${(0, _legacy5().pathNormalizeToLinux)(trackDir)}/`));
|
|
408
465
|
if (fileNotInsideTrackDir) {
|
|
409
466
|
// we check for this error before. however, it's possible that a user have one trackDir
|
|
410
467
|
// and another dir for the tests.
|
|
@@ -429,7 +486,7 @@ class AddComponents {
|
|
|
429
486
|
componentId: new (_componentId().ComponentID)(componentId._legacy, defaultScope),
|
|
430
487
|
files: component.files,
|
|
431
488
|
defaultScope,
|
|
432
|
-
config: this.config,
|
|
489
|
+
config: rootDir === _legacy3().WORKSPACE_ROOT_DIR ? configForWorkspaceRoot(foundComponentFromBitMap?.config, this.config) : this.config,
|
|
433
490
|
mainFile,
|
|
434
491
|
// @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
|
|
435
492
|
override: this.override
|
|
@@ -450,6 +507,11 @@ class AddComponents {
|
|
|
450
507
|
_updateFilesAccordingToExistingRootDir(foundComponentFromBitMap, componentFiles, component) {
|
|
451
508
|
const existingRootDir = foundComponentFromBitMap.rootDir;
|
|
452
509
|
if (!existingRootDir) return; // nothing to do.
|
|
510
|
+
// every file in the workspace is inside the workspace root, and its paths are already relative
|
|
511
|
+
// to it, so there is nothing to check and nothing to rewrite. without this, re-running
|
|
512
|
+
// "bit add ." would compare "README.md" against a "./" prefix, decide the files are outside the
|
|
513
|
+
// root, and throw.
|
|
514
|
+
if (existingRootDir === _legacy3().WORKSPACE_ROOT_DIR) return;
|
|
453
515
|
const areFilesInsideExistingRootDir = componentFiles.every(file => (0, _legacy5().pathNormalizeToLinux)(file.relativePath).startsWith(`${existingRootDir}/`));
|
|
454
516
|
if (areFilesInsideExistingRootDir) {
|
|
455
517
|
_legacy3().ComponentMap.changeFilesPathAccordingToItsRootDir(existingRootDir, componentFiles);
|
|
@@ -588,21 +650,49 @@ you can add the directory these files are located at and it'll change the root d
|
|
|
588
650
|
* e.g. bar/foo.js, the id would be bar/foo.
|
|
589
651
|
* in case bitmap has already the same id, the complete id is taken from bitmap (see _getIdAccordingToExistingComponent)
|
|
590
652
|
*/
|
|
591
|
-
async addOneComponent(componentPath) {
|
|
653
|
+
async addOneComponent(componentPath, batchRootDirs = []) {
|
|
592
654
|
let finalBitId; // final id to use for bitmap file
|
|
593
655
|
let idFromPath;
|
|
594
656
|
if (this.id) {
|
|
595
657
|
finalBitId = this._getIdAccordingToExistingComponent(this.id);
|
|
596
658
|
}
|
|
597
|
-
|
|
659
|
+
// when the tracked dir is the workspace root itself, the relative path is empty. normalize it
|
|
660
|
+
// to "." so it is a real rootDir rather than a falsy one.
|
|
661
|
+
const relativeComponentPath = this.consumer.getPathRelativeToConsumer(componentPath) || _legacy3().WORKSPACE_ROOT_DIR;
|
|
598
662
|
this._throwForOutsideConsumer(relativeComponentPath);
|
|
599
|
-
|
|
663
|
+
// the component this add is for: the one the user named, tracked already or not, or else the
|
|
664
|
+
// one already tracking this dir. for the workspace root, this is what tells a re-add from a
|
|
665
|
+
// second owner.
|
|
666
|
+
const idOfTrackDir = this._getIdAccordingToTrackDir(relativeComponentPath);
|
|
667
|
+
const idToAdd = this.id ? finalBitId : idOfTrackDir;
|
|
668
|
+
throwForExistingParentDir(this.bitMap, relativeComponentPath, idToAdd || undefined);
|
|
669
|
+
// files of components nested inside this dir belong to them, not to the component being added -
|
|
670
|
+
// whether they are tracked already or added by the same command.
|
|
671
|
+
const nestedRootDirs = (0, _lodash().uniq)([...this.bitMap.getNestedRootDirs(relativeComponentPath), ...batchRootDirs.filter(other => other !== relativeComponentPath && (relativeComponentPath === _legacy3().WORKSPACE_ROOT_DIR || other.startsWith(`${relativeComponentPath}/`)))]);
|
|
600
672
|
const matches = await (0, _glob().glob)((0, _legacy5().pathNormalizeToLinux)(path().join(relativeComponentPath, '**')), {
|
|
601
673
|
cwd: this.consumer.getPath(),
|
|
602
|
-
nodir: true
|
|
674
|
+
nodir: true,
|
|
675
|
+
// dotfiles are component files like any other (the workspace root is full of them: .gitignore,
|
|
676
|
+
// .github/**). the rescan, getFilesByDir(), scans with dot: true, and the add-time file-set has to
|
|
677
|
+
// agree with it rather than be corrected by the next command.
|
|
678
|
+
dot: true,
|
|
679
|
+
// the same exclusions the rescan applies, see getFilesByDir().
|
|
680
|
+
ignore: (0, _legacy3().getScanIgnorePatterns)(relativeComponentPath, nestedRootDirs)
|
|
603
681
|
});
|
|
604
682
|
if (!matches.length) throw new (_exceptions().EmptyDirectory)(componentPath);
|
|
605
|
-
|
|
683
|
+
|
|
684
|
+
// the config files "bit ws-config write" generates are not source - the same rule the rescan
|
|
685
|
+
// applies (see getFilesByDir), so the add-time file-set matches the next rescan.
|
|
686
|
+
const generatedAtRoot = new Set(_legacy2().IGNORE_ROOT_ONLY_LIST.map(file => (0, _legacy5().pathNormalizeToLinux)(path().join(relativeComponentPath, file))));
|
|
687
|
+
const matchesNotIgnored = await (0, _legacy3().filterByIgnoreFiles)(relativeComponentPath, this.consumer.getPath(), this.gitIgnore, matches.map(_legacy5().pathNormalizeToLinux), this.consumer.config.trackAllFiles);
|
|
688
|
+
// and by the component's own ignore file, the rule the rescan applies (see getFilesByDir) - it
|
|
689
|
+
// takes paths relative to the component, the matches are relative to the workspace.
|
|
690
|
+
const relativeToComponent = match => path().posix.relative(relativeComponentPath, match);
|
|
691
|
+
const keptByOwnIgnoreFile = new Set(await (0, _legacy3().filterByOwnIgnoreFile)(relativeComponentPath, this.consumer.getPath(), matchesNotIgnored.map(relativeToComponent)));
|
|
692
|
+
// the rules the rescan applies too (see getFilesByDir), so the add-time file-set matches it. the
|
|
693
|
+
// main file is checked against the same predicate below - it is put back after this filtering.
|
|
694
|
+
const isTrackable = match => keptByOwnIgnoreFile.has(relativeToComponent(match)) && (this.consumer.config.trackAllFiles || !generatedAtRoot.has(match));
|
|
695
|
+
const filteredMatches = matchesNotIgnored.filter(isTrackable);
|
|
606
696
|
if (!filteredMatches.length) {
|
|
607
697
|
throw new (_exceptions().NoFiles)(matches);
|
|
608
698
|
}
|
|
@@ -614,10 +704,29 @@ you can add the directory these files are located at and it'll change the root d
|
|
|
614
704
|
};
|
|
615
705
|
});
|
|
616
706
|
const resolvedMainFile = this._addMainFileToFiles(filteredMatchedFiles);
|
|
707
|
+
// that puts the main file back into the list after the filtering above, and checks it against the
|
|
708
|
+
// workspace ignore rules only. without applying the rest of them here, the add fails further down
|
|
709
|
+
// on a main file the rescan already dropped, saying it was removed - the config files bit treats
|
|
710
|
+
// as generated (tsconfig.json and friends) reach it that way, as does a component ignore file.
|
|
711
|
+
if (resolvedMainFile) {
|
|
712
|
+
const mainNormalized = (0, _legacy5().pathNormalizeToLinux)(resolvedMainFile);
|
|
713
|
+
// it is in the file-set only if it was found on disk. a missing one is reported further down,
|
|
714
|
+
// where the error says so rather than blaming an ignore rule.
|
|
715
|
+
const inFileSet = filteredMatchedFiles.some(file => file.relativePath === mainNormalized);
|
|
716
|
+
// some paths the scan never yields at all - bit's own dirs, a nested workspace map, the
|
|
717
|
+
// root-dir of a component nested in this one - so they never reach `matches` and the ignore
|
|
718
|
+
// rules below have nothing to compare them against. either way an explicit main file is put
|
|
719
|
+
// into the file-set without going through the scan, and the next rescan drops it again: the
|
|
720
|
+
// component then fails to load, saying the main file was removed.
|
|
721
|
+
const excludedFromScan = !(0, _legacy3().filterByScanIgnorePatterns)(relativeComponentPath, [mainNormalized], nestedRootDirs).length;
|
|
722
|
+
const excludedByIgnoreRules = matchesNotIgnored.includes(mainNormalized) && !isTrackable(mainNormalized);
|
|
723
|
+
if (inFileSet && excludedFromScan || excludedByIgnoreRules) {
|
|
724
|
+
throw new (_exceptions().ExcludedMainFile)(relativeToComponent(mainNormalized));
|
|
725
|
+
}
|
|
726
|
+
}
|
|
617
727
|
const absoluteComponentPath = (0, _legacy5().pathNormalizeToLinux)(path().resolve(componentPath));
|
|
618
728
|
const splitPath = absoluteComponentPath.split('/');
|
|
619
729
|
const lastDir = splitPath[splitPath.length - 1];
|
|
620
|
-
const idOfTrackDir = this._getIdAccordingToTrackDir(componentPath);
|
|
621
730
|
if (!finalBitId) {
|
|
622
731
|
if (this.id) {
|
|
623
732
|
const bitId = _legacyBitId().BitId.parse(this.id, false);
|
|
@@ -651,7 +760,7 @@ you can add the directory these files are located at and it'll change the root d
|
|
|
651
760
|
}
|
|
652
761
|
async getIgnoreList() {
|
|
653
762
|
const consumerPath = this.consumer.getPath();
|
|
654
|
-
return (0, _legacy3().getIgnoreListHarmony)(consumerPath, this.consumer.config.ignoredFiles);
|
|
763
|
+
return (0, _legacy3().getIgnoreListHarmony)(consumerPath, this.consumer.config.ignoredFiles, this.consumer.config.trackAllFiles);
|
|
655
764
|
}
|
|
656
765
|
async linkComponents(ids) {
|
|
657
766
|
if (this.trackDirFeature) {
|
|
@@ -678,8 +787,13 @@ you can add the directory these files are located at and it'll change the root d
|
|
|
678
787
|
_removeDirectoriesWhenTheirFilesAreAdded(componentPathsStats) {
|
|
679
788
|
const allPaths = Object.keys(componentPathsStats);
|
|
680
789
|
allPaths.forEach(componentPath => {
|
|
681
|
-
|
|
682
|
-
|
|
790
|
+
// the dirname of "." is "." itself - the workspace root is not a wildcard expansion of itself.
|
|
791
|
+
const foundDir = allPaths.find(p => p !== componentPath && p === path().dirname(componentPath));
|
|
792
|
+
// nor of what sits directly below it. the workspace root contains every other component by
|
|
793
|
+
// design, so a component inside it is no reason to drop it: it was asked for by name, and the
|
|
794
|
+
// --root flag says so in as many words (see throwForWorkspaceRootFlagMismatch). without this,
|
|
795
|
+
// "bit add . comp --root" tracks comp alone and reports success, the root never created.
|
|
796
|
+
if (foundDir && componentPathsStats[foundDir] && !this.isWorkspaceRootPath(foundDir)) {
|
|
683
797
|
_legacy4().logger.debug(`add-components._removeDirectoriesWhenTheirFilesAreAdded, ignoring ${foundDir}`);
|
|
684
798
|
delete componentPathsStats[foundDir];
|
|
685
799
|
}
|
|
@@ -721,9 +835,10 @@ you can add the directory these files are located at and it'll change the root d
|
|
|
721
835
|
}));
|
|
722
836
|
}
|
|
723
837
|
async _tryAddingMultiple(componentPathsStats) {
|
|
838
|
+
const batchRootDirs = Object.keys(componentPathsStats).map(onePath => (0, _legacy5().pathNormalizeToLinux)(this.consumer.getPathRelativeToConsumer(onePath)) || _legacy3().WORKSPACE_ROOT_DIR);
|
|
724
839
|
const addedP = Object.keys(componentPathsStats).map(async onePath => {
|
|
725
840
|
try {
|
|
726
|
-
const addedComponent = await this.addOneComponent(onePath);
|
|
841
|
+
const addedComponent = await this.addOneComponent(onePath, batchRootDirs);
|
|
727
842
|
return addedComponent;
|
|
728
843
|
} catch (err) {
|
|
729
844
|
if (!(err instanceof _exceptions().EmptyDirectory)) throw err;
|
|
@@ -741,13 +856,28 @@ you can add the directory these files are located at and it'll change the root d
|
|
|
741
856
|
}
|
|
742
857
|
}
|
|
743
858
|
exports.default = AddComponents;
|
|
744
|
-
function throwForExistingParentDir(bitMap, relativeToConsumerPath) {
|
|
859
|
+
function throwForExistingParentDir(bitMap, relativeToConsumerPath, addedId) {
|
|
860
|
+
if (relativeToConsumerPath === _legacy3().WORKSPACE_ROOT_DIR) {
|
|
861
|
+
// only one component can own the workspace root. rejected before the (expensive) scan of the
|
|
862
|
+
// whole workspace, with a message that says which component already owns it. re-adding the same
|
|
863
|
+
// component is fine. the root component contains every other component by design, so there is no
|
|
864
|
+
// parent-dir conflict to check for it.
|
|
865
|
+
const currentOwner = bitMap.getComponentIdByRootPath(_legacy3().WORKSPACE_ROOT_DIR);
|
|
866
|
+
if (currentOwner && !addedId?.isEqual(currentOwner, {
|
|
867
|
+
ignoreVersion: true
|
|
868
|
+
})) {
|
|
869
|
+
throw new (_bitError().BitError)(`unable to track the workspace root, it is already tracked by "${currentOwner.toStringWithoutVersion()}"`);
|
|
870
|
+
}
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
745
873
|
const isParentDir = parent => {
|
|
746
874
|
const relative = path().relative(parent, relativeToConsumerPath);
|
|
747
875
|
return relative && !relative.startsWith('..') && !path().isAbsolute(relative);
|
|
748
876
|
};
|
|
749
877
|
bitMap.components.forEach(componentMap => {
|
|
750
|
-
|
|
878
|
+
// the workspace-root component contains every other component by design, and subtracts their
|
|
879
|
+
// root-dirs from its own file-set.
|
|
880
|
+
if (!componentMap.rootDir || componentMap.rootDir === _legacy3().WORKSPACE_ROOT_DIR) return;
|
|
751
881
|
if (isParentDir(componentMap.rootDir)) {
|
|
752
882
|
throw new (_parentDirTracked().ParentDirTracked)(componentMap.rootDir, componentMap.id.toStringWithoutVersion(), relativeToConsumerPath);
|
|
753
883
|
}
|
|
@@ -809,46 +939,135 @@ async function isAutoGeneratedFile(filePath) {
|
|
|
809
939
|
const line = await (0, _firstline().default)(filePath);
|
|
810
940
|
return line.includes(_legacy2().AUTO_GENERATED_STAMP);
|
|
811
941
|
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* the env the workspace-root component is tracked with. hardcoded, the same way the envs aspect
|
|
945
|
+
* names its default env - the tracker does not depend on the env aspects.
|
|
946
|
+
*/
|
|
947
|
+
const WORKSPACE_ROOT_ENV = 'teambit.harmony/empty-env';
|
|
948
|
+
|
|
949
|
+
/**
|
|
950
|
+
* the workspace-root component (rootDir ".") is a bag of config files, not a source component:
|
|
951
|
+
* nothing compiles it, nothing tests it, and nothing imports it as a package. the regular default
|
|
952
|
+
* env would give it a compiler and a dependency policy it can never satisfy, so it is tracked with
|
|
953
|
+
* the empty env - as explicit config, so every path that resolves an env or a dependency policy
|
|
954
|
+
* sees the same answer. an env configured by the caller, or set later with "bit env set", wins.
|
|
955
|
+
*/
|
|
956
|
+
function configForWorkspaceRoot(existingConfig, addedConfig) {
|
|
957
|
+
const configuredEnv = addedConfig?.[_legacy2().Extensions.envs] ?? existingConfig?.[_legacy2().Extensions.envs];
|
|
958
|
+
if (configuredEnv) return _objectSpread(_objectSpread({}, existingConfig), addedConfig);
|
|
959
|
+
// the same two entries "bit env set" writes: the env aspect itself, and the env selection
|
|
960
|
+
return _objectSpread(_objectSpread(_objectSpread({}, existingConfig), addedConfig), {}, {
|
|
961
|
+
[WORKSPACE_ROOT_ENV]: {},
|
|
962
|
+
[_legacy2().Extensions.envs]: {
|
|
963
|
+
env: WORKSPACE_ROOT_ENV
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
}
|
|
812
967
|
async function addMultipleFromResolvedTrackData(workspace, trackData) {
|
|
813
968
|
const bitMap = workspace.consumer.bitMap;
|
|
814
|
-
const
|
|
969
|
+
const {
|
|
970
|
+
ignoredFiles,
|
|
971
|
+
trackAllFiles
|
|
972
|
+
} = workspace.consumer.config;
|
|
973
|
+
const ignoreList = await (0, _legacy3().getIgnoreListHarmony)(workspace.path, ignoredFiles, trackAllFiles);
|
|
815
974
|
const gitIgnore = (0, _ignore().default)().add(ignoreList);
|
|
816
|
-
|
|
975
|
+
// normalized once, the way the map stores it, so "./" is the workspace root here as well as there
|
|
976
|
+
const normalizeRootDir = rootDir => (0, _legacy5().pathNormalizeToLinux)(path().normalize(rootDir));
|
|
977
|
+
const batchRootDirs = trackData.map(data => normalizeRootDir(data.rootDir));
|
|
978
|
+
const componentMaps = [];
|
|
979
|
+
for (const data of trackData) {
|
|
817
980
|
const {
|
|
818
|
-
rootDir,
|
|
819
981
|
files,
|
|
820
982
|
componentName,
|
|
821
983
|
defaultScope,
|
|
822
|
-
mainFile,
|
|
823
984
|
config
|
|
824
985
|
} = data;
|
|
825
|
-
if (path().isAbsolute(rootDir)) throw new (_bitError().BitError)(`path is absolute, got ${rootDir}`);
|
|
826
|
-
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
986
|
+
if (path().isAbsolute(data.rootDir)) throw new (_bitError().BitError)(`path is absolute, got ${data.rootDir}`);
|
|
987
|
+
const rootDir = normalizeRootDir(data.rootDir);
|
|
988
|
+
const componentId = _componentId().ComponentID.fromObject({
|
|
989
|
+
name: componentName
|
|
990
|
+
}, defaultScope);
|
|
991
|
+
// re-tracking the workspace root with the same id is a no-op, not a second owner
|
|
992
|
+
throwForExistingParentDir(bitMap, rootDir, componentId);
|
|
993
|
+
const isWorkspaceRoot = rootDir === _legacy3().WORKSPACE_ROOT_DIR;
|
|
994
|
+
// re-tracking keeps the entry's id, version included, the way "bit add" does: the id built from
|
|
995
|
+
// the name alone would replace it and make a snapped component look newly tracked.
|
|
996
|
+
const existingEntry = bitMap.getComponentIfExist(componentId, {
|
|
997
|
+
ignoreVersion: true
|
|
836
998
|
});
|
|
999
|
+
const idToTrack = existingEntry?.id ?? componentId;
|
|
1000
|
+
// the workspace root has no entry point of its own, workspace.jsonc stands in for it, the way
|
|
1001
|
+
// "bit add ." resolves it (see determine-main-file). re-tracking keeps the entry's main file.
|
|
1002
|
+
const mainFile = data.mainFile ?? existingEntry?.mainFile ?? (isWorkspaceRoot ? _legacy2().WORKSPACE_JSONC : undefined);
|
|
1003
|
+
if (!mainFile) throw new (_bitError().BitError)(`unable to track "${rootDir}" as "${componentName}", no main file was given`);
|
|
1004
|
+
const existingConfig = isWorkspaceRoot ? existingEntry?.config : undefined;
|
|
1005
|
+
const componentFiles = isWorkspaceRoot ? await scanWorkspaceRootFiles(workspace, gitIgnore, batchRootDirs) : await filterResolvedFiles(rootDir, workspace.path, files, gitIgnore, trackAllFiles);
|
|
1006
|
+
// a nested component may take any file from a tracked workspace root but its main file, the
|
|
1007
|
+
// rule "bit add" applies. a root tracked later in the same call scans around this component.
|
|
1008
|
+
const workspaceRootMap = bitMap.getWorkspaceRootMap();
|
|
1009
|
+
if (!isWorkspaceRoot && workspaceRootMap) throwForTakingWorkspaceRootMainFile(workspaceRootMap, idToTrack, rootDir);
|
|
837
1010
|
const componentMap = bitMap.addComponent({
|
|
838
|
-
componentId:
|
|
839
|
-
name: componentName
|
|
840
|
-
}, defaultScope),
|
|
1011
|
+
componentId: idToTrack,
|
|
841
1012
|
files: componentFiles,
|
|
842
|
-
defaultScope,
|
|
843
|
-
config,
|
|
1013
|
+
defaultScope: idToTrack.hasScope() ? undefined : defaultScope,
|
|
1014
|
+
config: isWorkspaceRoot ? configForWorkspaceRoot(existingConfig, config) : config,
|
|
844
1015
|
mainFile,
|
|
845
1016
|
rootDir
|
|
846
1017
|
});
|
|
847
|
-
|
|
848
|
-
}
|
|
1018
|
+
componentMaps.push(componentMap);
|
|
1019
|
+
}
|
|
849
1020
|
const allIds = componentMaps.map(c => c.id);
|
|
850
1021
|
await (0, _workspaceModules().linkToNodeModulesByIds)(workspace, allIds);
|
|
851
1022
|
return allIds;
|
|
852
1023
|
}
|
|
853
1024
|
|
|
1025
|
+
/**
|
|
1026
|
+
* the workspace-root component owns every file no other component claims, so it gives a file away to
|
|
1027
|
+
* a more specific component - all but its main file: without it, it fails to load from the next scan on.
|
|
1028
|
+
*/
|
|
1029
|
+
function throwForTakingWorkspaceRootMainFile(workspaceRootMap, componentId, rootDir) {
|
|
1030
|
+
// checked on the directory rather than on the files the component keeps: the root's next scan
|
|
1031
|
+
// subtracts the whole directory, whether or not the component itself tracks that file. the
|
|
1032
|
+
// ownership lookups are case-insensitive, so this comparison is too.
|
|
1033
|
+
if (!workspaceRootMap.mainFile.toLowerCase().startsWith(`${rootDir.toLowerCase()}/`)) return;
|
|
1034
|
+
throw new (_bitError().BitError)(`unable to add "${rootDir}" as "${componentId.toString()}", it contains "${workspaceRootMap.mainFile}", the main file of the workspace-root component "${workspaceRootMap.id.toStringWithoutVersion()}". set a different main file for it first: bit add . --main ${_legacy2().WORKSPACE_JSONC}`);
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* the workspace-root's file-set is derived by scanning, the way every load derives it, rather than
|
|
1039
|
+
* taken from the caller: the scan is what knows the nested components (tracked already, or by the same
|
|
1040
|
+
* call), the ignore files below the root and bit's own exclusions. a main file the scan leaves out
|
|
1041
|
+
* fails the map validation before the map is written, not on the next load.
|
|
1042
|
+
*/
|
|
1043
|
+
async function scanWorkspaceRootFiles(workspace, gitIgnore, batchRootDirs) {
|
|
1044
|
+
const nestedRootDirs = (0, _lodash().uniq)([...workspace.consumer.bitMap.getNestedRootDirs(_legacy3().WORKSPACE_ROOT_DIR), ...batchRootDirs.filter(dir => dir !== _legacy3().WORKSPACE_ROOT_DIR)]);
|
|
1045
|
+
const {
|
|
1046
|
+
trackAllFiles
|
|
1047
|
+
} = workspace.consumer.config;
|
|
1048
|
+
return (0, _legacy3().getFilesByDir)(_legacy3().WORKSPACE_ROOT_DIR, workspace.path, gitIgnore, nestedRootDirs, trackAllFiles);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* the files the caller resolved for a component, minus the config files "bit ws-config write"
|
|
1053
|
+
* generates and the ignored ones - the rules the rescan applies, see getFilesByDir. the workspace
|
|
1054
|
+
* ignore rules are written against the workspace root, so a file is matched by its workspace-relative
|
|
1055
|
+
* path and mapped back to the component-relative one the map stores; the component's own ignore file
|
|
1056
|
+
* is applied to the latter.
|
|
1057
|
+
*/
|
|
1058
|
+
async function filterResolvedFiles(rootDir, consumerPath, files, gitIgnore, trackAllFiles) {
|
|
1059
|
+
const notGenerated = files.map(_legacy5().pathNormalizeToLinux).filter(file => trackAllFiles || !_legacy2().IGNORE_ROOT_ONLY_LIST.includes(file));
|
|
1060
|
+
// what a scan never yields (bit's and git's own dirs, a nested workspace map) is not tracked here either,
|
|
1061
|
+
// or the next rescan would drop it
|
|
1062
|
+
const workspaceRelative = (0, _legacy3().filterByScanIgnorePatterns)(rootDir, notGenerated.map(file => path().posix.join(rootDir, file)));
|
|
1063
|
+
const filteredByWorkspaceRules = gitIgnore.filter(workspaceRelative).map(file => path().posix.relative(rootDir, file));
|
|
1064
|
+
const filtered = await (0, _legacy3().filterByOwnIgnoreFile)(rootDir, consumerPath, filteredByWorkspaceRules);
|
|
1065
|
+
if (!filtered.length) throw new (_exceptions().NoFiles)(files);
|
|
1066
|
+
return filtered.map(relativePath => ({
|
|
1067
|
+
relativePath,
|
|
1068
|
+
name: path().basename(relativePath),
|
|
1069
|
+
test: false
|
|
1070
|
+
}));
|
|
1071
|
+
}
|
|
1072
|
+
|
|
854
1073
|
//# sourceMappingURL=add-components.js.map
|