Skip to content

Commit

Permalink
feature(capsules) - support setting exact folder for scope aspects ca…
Browse files Browse the repository at this point in the history
…psule base dir (#7531)
  • Loading branch information
GiladShoham authored Jun 14, 2023
1 parent b79ad22 commit 6cde6b9
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 13 deletions.
14 changes: 10 additions & 4 deletions scopes/component/isolator/isolator.main.runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ export type IsolateComponentsOptions = CreateGraphOptions & {
*/
baseDir?: string;

/**
* Whether to use hash function (of base dir) as capsules root dir name
*/
useHash?: boolean;

/**
* create a new capsule with a random string attached to the path suffix
*/
Expand Down Expand Up @@ -247,7 +252,7 @@ export class IsolatorMain {
});
opts.baseDir = opts.baseDir || host.path;
const capsuleList = await this.createCapsules(componentsToIsolate, opts, legacyScope);
const capsuleDir = this.getCapsulesRootDir(opts.baseDir, opts.rootBaseDir);
const capsuleDir = this.getCapsulesRootDir(opts.baseDir, opts.rootBaseDir, opts.useHash);
this.logger.debug(
`creating network with base dir: ${opts.baseDir}, rootBaseDir: ${opts.rootBaseDir}. final capsule-dir: ${capsuleDir}. capsuleList: ${capsuleList.length}`
);
Expand Down Expand Up @@ -305,7 +310,7 @@ export class IsolatorMain {
legacyScope?: Scope
): Promise<CapsuleList> {
this.logger.debug(`createCapsules, ${components.length} components`);
const capsulesDir = this.getCapsulesRootDir(opts.baseDir as string, opts.rootBaseDir);
const capsulesDir = this.getCapsulesRootDir(opts.baseDir as string, opts.rootBaseDir, opts.useHash);

let longProcessLogger;
if (opts.context?.aspects) {
Expand Down Expand Up @@ -594,9 +599,10 @@ export class IsolatorMain {
}
}

getCapsulesRootDir(baseDir: string, rootBaseDir?: string): PathOsBasedAbsolute {
getCapsulesRootDir(baseDir: string, rootBaseDir?: string, useHash = true): PathOsBasedAbsolute {
const capsulesRootBaseDir = rootBaseDir || this.getRootDirOfAllCapsules();
return path.join(capsulesRootBaseDir, hash(baseDir));
const dir = useHash ? hash(baseDir) : baseDir;
return path.join(capsulesRootBaseDir, dir);
}

async deleteCapsules(capsuleBaseDir: string | null): Promise<string> {
Expand Down
27 changes: 24 additions & 3 deletions scopes/scope/scope/scope-aspects-loader.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { GlobalConfigMain } from '@teambit/global-config';
import mapSeries from 'p-map-series';
import { Lane } from '@teambit/legacy/dist/scope/models';
import { readdirSync, existsSync } from 'fs-extra';
import { resolve, join } from 'path';
import { DEFAULT_DIST_DIRNAME } from '@teambit/legacy/dist/constants';
import {
DEFAULT_DIST_DIRNAME,
CFG_CAPSULES_SCOPES_ASPECTS_BASE_DIR,
CFG_CAPSULES_GLOBAL_SCOPE_ASPECTS_BASE_DIR,
} from '@teambit/legacy/dist/constants';
import { Compiler } from '@teambit/compiler';
import { Capsule, IsolatorMain } from '@teambit/isolator';
import { AspectLoaderMain, AspectDefinition } from '@teambit/aspect-loader';
Expand Down Expand Up @@ -31,7 +36,8 @@ export class ScopeAspectsLoader {
private aspectLoader: AspectLoaderMain,
private envs: EnvsMain,
private isolator: IsolatorMain,
private logger: Logger
private logger: Logger,
private globalConfig: GlobalConfigMain
) {}
private parseLocalAspect(localAspects: string[]) {
const dirPaths = localAspects.map((localAspect) => resolve(localAspect.replace('file://', '')));
Expand Down Expand Up @@ -234,11 +240,13 @@ needed-for: ${neededFor || '<unknown>'}`);
opts?: { skipIfExists?: boolean; packageManagerConfigRootDir?: string; workspaceName?: string }
): Promise<RequireableComponent[]> {
if (!components || !components.length) return [];
const useHash = this.shouldUseHashForCapsules();
const network = await this.isolator.isolateComponents(
components.map((c) => c.id),
// includeFromNestedHosts - to support case when you are in a workspace, trying to load aspect defined in the workspace.jsonc but not part of the workspace
{
baseDir: this.getAspectCapsulePath(),
useHash,
skipIfExists: opts?.skipIfExists ?? true,
seedersOnly: true,
includeFromNestedHosts: true,
Expand Down Expand Up @@ -384,7 +392,18 @@ needed-for: ${neededFor || '<unknown>'}`);
}

getAspectCapsulePath() {
return `${this.scope.path}-aspects`;
const defaultPath = `${this.scope.path}-aspects`;
if (this.scope.isGlobalScope) {
return this.globalConfig.getSync(CFG_CAPSULES_GLOBAL_SCOPE_ASPECTS_BASE_DIR) || defaultPath;
}
return this.globalConfig.getSync(CFG_CAPSULES_SCOPES_ASPECTS_BASE_DIR) || defaultPath;
}

shouldUseHashForCapsules(): boolean {
if (this.scope.isGlobalScope) {
return !this.globalConfig.getSync(CFG_CAPSULES_GLOBAL_SCOPE_ASPECTS_BASE_DIR);
}
return !this.globalConfig.getSync(CFG_CAPSULES_SCOPES_ASPECTS_BASE_DIR);
}

private async resolveUserAspects(
Expand All @@ -394,10 +413,12 @@ needed-for: ${neededFor || '<unknown>'}`);
): Promise<AspectDefinition[]> {
if (!userAspectsIds || !userAspectsIds.length) return [];
const components = await this.scope.getMany(userAspectsIds);
const useHash = this.shouldUseHashForCapsules();
const network = await this.isolator.isolateComponents(
userAspectsIds,
{
baseDir: this.getAspectCapsulePath(),
useHash,
skipIfExists: true,
// for some reason this needs to be false, otherwise tagging components in some workspaces
// result in error during Preview task:
Expand Down
33 changes: 28 additions & 5 deletions scopes/scope/scope/scope.main.runtime.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import GlobalConfigAspect, { GlobalConfigMain } from '@teambit/global-config';
import mapSeries from 'p-map-series';
import { Graph, Node, Edge } from '@teambit/graph.cleargraph';
import semver from 'semver';
Expand Down Expand Up @@ -49,6 +50,7 @@ import { remove } from '@teambit/legacy/dist/api/scope';
import { BitError } from '@teambit/bit-error';
import ConsumerComponent from '@teambit/legacy/dist/consumer/component';
import { resumeExport } from '@teambit/legacy/dist/scope/component-ops/export-scope-components';
import { GLOBAL_SCOPE } from '@teambit/legacy/dist/constants';
import { ExtensionDataEntry, ExtensionDataList } from '@teambit/legacy/dist/consumer/config';
import EnvsAspect, { EnvsMain } from '@teambit/envs';
import { compact, slice, difference } from 'lodash';
Expand Down Expand Up @@ -129,7 +131,9 @@ export class ScopeMain implements ComponentFactory {

private envs: EnvsMain,

private dependencyResolver: DependencyResolverMain
private dependencyResolver: DependencyResolverMain,

private globalConfig: GlobalConfigMain
) {
this.componentLoader = new ScopeComponentLoader(this, this.logger);
}
Expand Down Expand Up @@ -165,6 +169,10 @@ export class ScopeMain implements ComponentFactory {
return this.legacyScope.isLegacy;
}

get isGlobalScope(): boolean {
return this.path === GLOBAL_SCOPE;
}

// We need to reload the aspects with their new version since:
// during get many by legacy, we go load component which in turn go to getEnv
// get env validates that the env written on the component is really exist by checking the envs slot registry
Expand Down Expand Up @@ -240,12 +248,24 @@ export class ScopeMain implements ComponentFactory {
return scopeAspectsLoader.getAspectCapsulePath();
}

shouldUseHashForCapsules() {
const scopeAspectsLoader = this.getScopeAspectsLoader();
return scopeAspectsLoader.shouldUseHashForCapsules();
}

getManyByLegacy(components: ConsumerComponent[]): Promise<Component[]> {
return mapSeries(components, async (component) => this.getFromConsumerComponent(component));
}

getScopeAspectsLoader(): ScopeAspectsLoader {
const scopeAspectsLoader = new ScopeAspectsLoader(this, this.aspectLoader, this.envs, this.isolator, this.logger);
const scopeAspectsLoader = new ScopeAspectsLoader(
this,
this.aspectLoader,
this.envs,
this.isolator,
this.logger,
this.globalConfig
);
return scopeAspectsLoader;
}

Expand Down Expand Up @@ -898,14 +918,15 @@ export class ScopeMain implements ComponentFactory {
LoggerAspect,
EnvsAspect,
DependencyResolverAspect,
GlobalConfigAspect,
];

static defaultConfig: ScopeConfig = {
httpTimeOut: 600000,
};

static async provider(
[componentExt, ui, graphql, cli, isolator, aspectLoader, express, loggerMain, envs, depsResolver]: [
[componentExt, ui, graphql, cli, isolator, aspectLoader, express, loggerMain, envs, depsResolver, globalConfig]: [
ComponentMain,
UiMain,
GraphqlMain,
Expand All @@ -915,7 +936,8 @@ export class ScopeMain implements ComponentFactory {
ExpressMain,
LoggerMain,
EnvsMain,
DependencyResolverMain
DependencyResolverMain,
GlobalConfigMain
],
config: ScopeConfig,
[postPutSlot, postDeleteSlot, postExportSlot, postObjectsPersistSlot, preFetchObjectsSlot]: [
Expand Down Expand Up @@ -948,7 +970,8 @@ export class ScopeMain implements ComponentFactory {
aspectLoader,
logger,
envs,
depsResolver
depsResolver,
globalConfig
);
cli.registerOnStart(async (hasWorkspace: boolean) => {
if (hasWorkspace) return;
Expand Down
6 changes: 5 additions & 1 deletion scopes/workspace/workspace/capsule.cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,11 @@ use --json to get the list of all workspace capsules`);

private getCapsulesRootDirs() {
const workspaceCapsulesRootDir = this.isolator.getCapsulesRootDir(this.workspace.path);
const scopeAspectsCapsulesRootDir = this.isolator.getCapsulesRootDir(this.workspace.scope.getAspectCapsulePath());
const scopeAspectsCapsulesRootDir = this.isolator.getCapsulesRootDir(
this.workspace.scope.getAspectCapsulePath(),
undefined,
this.workspace.scope.shouldUseHashForCapsules()
);

return { workspaceCapsulesRootDir, scopeAspectsCapsulesRootDir };
}
Expand Down
10 changes: 10 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,16 @@ export const CFG_FEATURE_TOGGLE = 'features';
export const CFG_PACKAGE_MANAGER_CACHE = 'package-manager.cache';

export const CFG_CAPSULES_ROOT_BASE_DIR = 'capsules_root_base_dir';
/**
* Name of the directory where the capsules for aspects for regular scope are stored
* This directory is relative to the capsules root directory
*/
export const CFG_CAPSULES_SCOPES_ASPECTS_BASE_DIR = 'capsules_scopes_aspects_base_dir';
/**
* Name of the directory where the capsules for aspects for the global scope are stored
* This directory is relative to the capsules root directory
*/
export const CFG_CAPSULES_GLOBAL_SCOPE_ASPECTS_BASE_DIR = 'capsules_global_scope_aspects_base_dir';

export const CFG_DEFAULT_RESOLVE_ENVS_FROM_ROOTS = 'default_resolve_envs_from_roots';

Expand Down

0 comments on commit 6cde6b9

Please sign in to comment.