Skip to content

Commit 1c688ce

Browse files
committed
refactor: handle GHJK_CLEANUP_POSIX edgecases
1 parent dbfec67 commit 1c688ce

File tree

22 files changed

+904
-272
lines changed

22 files changed

+904
-272
lines changed

.ghjk/deno.lock

Lines changed: 452 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.ghjk/lock.json

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,72 @@
44
"moduleEntries": {
55
"ports": {
66
"version": "0",
7-
"configResolutions": {}
7+
"configResolutions": {
8+
"bciqjlw6cxddajjmznoemlmnu7mgbbm7a3hfmnd2x5oivwajmiqui5ey": {
9+
"version": "v0.2.63",
10+
"buildDepConfigs": {},
11+
"portRef": "[email protected]",
12+
"specifiedVersion": false
13+
},
14+
"bciqao2s3r3r33ruox4qknfrxqrmemuccxn64dze2ylojrzp2bwvt4ji": {
15+
"version": "3.7.1",
16+
"buildDepConfigs": {
17+
"cpy_bs_ghrel": {
18+
"version": "3.12.3",
19+
"buildDepConfigs": {
20+
"tar_aa": {
21+
"version": "1.34",
22+
"buildDepConfigs": {},
23+
"portRef": "[email protected]",
24+
"specifiedVersion": false
25+
},
26+
"zstd_aa": {
27+
"version": "v1.4.8,",
28+
"buildDepConfigs": {},
29+
"portRef": "[email protected]",
30+
"specifiedVersion": false
31+
}
32+
},
33+
"portRef": "[email protected]",
34+
"specifiedVersion": false
35+
}
36+
},
37+
"portRef": "[email protected]",
38+
"packageName": "pre-commit",
39+
"specifiedVersion": false
40+
},
41+
"bciqij3g6mmbjn4a6ps4eipcy2fmw2zumgv5a3gbxycthroffihwquoi": {
42+
"version": "3.12.3",
43+
"buildDepConfigs": {
44+
"tar_aa": {
45+
"version": "1.34",
46+
"buildDepConfigs": {},
47+
"portRef": "[email protected]",
48+
"specifiedVersion": false
49+
},
50+
"zstd_aa": {
51+
"version": "v1.4.8,",
52+
"buildDepConfigs": {},
53+
"portRef": "[email protected]",
54+
"specifiedVersion": false
55+
}
56+
},
57+
"portRef": "[email protected]",
58+
"specifiedVersion": false
59+
},
60+
"bciqj4p5hoqweghbuvz52rupja7sqze34z63dd62nz632c5zxikv6ezy": {
61+
"version": "1.34",
62+
"buildDepConfigs": {},
63+
"portRef": "[email protected]",
64+
"specifiedVersion": false
65+
},
66+
"bciqe6fwheayositrdk7rkr2ngdr4wizldakex23tgivss7w6z7g3q3y": {
67+
"version": "v1.4.8,",
68+
"buildDepConfigs": {},
69+
"portRef": "[email protected]",
70+
"specifiedVersion": false
71+
}
72+
}
873
},
974
"tasks": {
1075
"version": "0"
@@ -33,7 +98,6 @@
3398
{
3499
"id": "tasks",
35100
"config": {
36-
"envs": {},
37101
"tasks": {},
38102
"tasksNamed": []
39103
}
@@ -55,7 +119,11 @@
55119
]
56120
}
57121
},
58-
"defaultEnv": "main"
122+
"defaultEnv": "main",
123+
"envsNamed": [
124+
"test",
125+
"main"
126+
]
59127
}
60128
}
61129
],

files/mod.ts

Lines changed: 123 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// here to make the resulting config reasonably stable
55
// across serializaiton. No random identifiers.
66

7-
import { deep_eql, multibase32, multibase64 } from "../deps/common.ts";
7+
import { deep_eql, multibase32, multibase64, zod } from "../deps/common.ts";
88

99
// ports specific imports
1010
import portsValidators from "../modules/ports/types.ts";
@@ -43,8 +43,16 @@ import type {
4343
Provision,
4444
WellKnownProvision,
4545
} from "../modules/envs/types.ts";
46+
import modulesValidators from "../modules/types.ts";
4647

47-
export type EnvParent = string | string[] | boolean;
48+
const validators = {
49+
envVars: zod.record(
50+
modulesValidators.envVarName,
51+
zod.union([zod.string(), zod.number()]),
52+
),
53+
};
54+
55+
export type EnvParent = string | string[] | boolean | undefined;
4856

4957
export type EnvDefArgs = {
5058
name: string;
@@ -91,7 +99,7 @@ export type TaskDefArgs = {
9199
workingDir?: string | Path;
92100
vars?: Record<string, string | number>;
93101
allowedBuildDeps?: (InstallConfigFat | AllowedPortDep)[];
94-
installs?: InstallConfigFat[];
102+
installs?: InstallConfigFat | InstallConfigFat[];
95103
inherit?: EnvParent;
96104
};
97105

@@ -191,12 +199,20 @@ export class Ghjkfile {
191199
// brittle.
192200
if (typeof args.inherit == "string") {
193201
this.addEnv({ name: args.inherit });
194-
}
195-
if (Array.isArray(args.inherit)) {
202+
} else if (Array.isArray(args.inherit)) {
196203
for (const name of args.inherit) {
197204
this.addEnv({ name });
198205
}
199206
}
207+
// FIXME: combine the task env processing
208+
// with normal env processing
209+
// we currrently process task envs at once in the end
210+
// to do env deduplication
211+
if (args.vars) {
212+
args.vars = unwrapParseRes(validators.envVars.safeParse(args.vars), {
213+
vars: args.vars,
214+
});
215+
}
200216
let key = args.name;
201217
if (!key) {
202218
switch (args.ty) {
@@ -413,7 +429,7 @@ export class Ghjkfile {
413429
: null;
414430
}
415431

416-
/** this processes the defined envs, normalizing dependency (i.e. "envBase")
432+
/** this processes the defined envs, resolving inherit
417433
* relationships to produce the standard EnvsModuleConfig
418434
*/
419435
#processEnvs(
@@ -450,7 +466,11 @@ export class Ghjkfile {
450466
}
451467
}
452468

453-
const moduleConfig: EnvsModuleConfig = { envs: {}, defaultEnv };
469+
const moduleConfig: EnvsModuleConfig = {
470+
envs: {},
471+
defaultEnv,
472+
envsNamed: [],
473+
};
454474
const workingSet = indie;
455475
while (workingSet.length > 0) {
456476
const item = workingSet.pop()!;
@@ -559,6 +579,12 @@ export class Ghjkfile {
559579
moduleConfig.envs[final.name].provides.push(prov);
560580
}
561581

582+
// envs that have names which start with underscors
583+
// don't show up in the cli list
584+
if (!final.name.startsWith("_")) {
585+
moduleConfig.envsNamed.push(final.name);
586+
}
587+
562588
const curRevDeps = revDeps.get(final.name);
563589
if (curRevDeps) {
564590
workingSet.push(...curRevDeps);
@@ -609,8 +635,8 @@ export class Ghjkfile {
609635
}
610636
const workingSet = indie;
611637
const localToFinalKey = {} as Record<string, string>;
638+
const gatheredEnvs = {} as Record<string, EnvRecipe>;
612639
const moduleConfig: TasksModuleConfig = {
613-
envs: {},
614640
tasks: {},
615641
tasksNamed: [],
616642
};
@@ -620,80 +646,95 @@ export class Ghjkfile {
620646
const { workingDir, desc, dependsOn, inherit } = args;
621647

622648
const envBaseResolved = this.#resolveEnvBases(
623-
inherit ?? [],
649+
inherit,
624650
defaultBaseEnv,
625651
);
626-
627-
const base = envBaseResolved
628-
? this.#mergeEnvs(envBaseResolved, `task_${args.name ?? key}`)
629-
: null;
630-
631-
let installSetId: string | undefined;
632-
if (
652+
const needsSeparateSet =
633653
// if task has installs itself
634654
args.installs?.length ||
635655
// task inherits from more than one parent
636-
(envBaseResolved && envBaseResolved.length > 1)
637-
) {
638-
// we need to create a new install set
639-
const taskInstallSet: InstallSet = {
640-
installs: [...args.installs ?? []],
641-
allowedBuildDeps: Object.fromEntries(
642-
reduceAllowedDeps(args.allowedBuildDeps ?? []).map((
643-
dep,
644-
) => [dep.manifest.name, dep]),
645-
),
646-
};
647-
if (base) {
648-
taskInstallSet.installs.push(...base.installSet.installs);
649-
for (
650-
const [key, val] of Object.entries(
651-
base.installSet.allowedBuildDeps,
652-
)
653-
) {
654-
// prefer the port dep config of the child over any
655-
// similar deps in the base
656-
if (!taskInstallSet.allowedBuildDeps[key]) {
657-
taskInstallSet.allowedBuildDeps[key] = val;
656+
(envBaseResolved && envBaseResolved.length > 1);
657+
658+
// task only needs decalre a separate env
659+
// if it's overriding/adding something
660+
const needsSeparateEnv = needsSeparateSet || args.vars;
661+
662+
let envKey: string | undefined;
663+
if (needsSeparateEnv) {
664+
const base = envBaseResolved
665+
? this.#mergeEnvs(envBaseResolved, `____task_${args.name ?? key}`)
666+
: null;
667+
668+
let installSetId: string | undefined;
669+
if (needsSeparateSet) {
670+
// we need to create a new install set
671+
const taskInstallSet: InstallSet = {
672+
installs: Array.isArray(args.installs)
673+
? [...args.installs]
674+
: args.installs
675+
? [args.installs]
676+
: [],
677+
allowedBuildDeps: Object.fromEntries(
678+
reduceAllowedDeps(args.allowedBuildDeps ?? []).map((
679+
dep,
680+
) => [dep.manifest.name, dep]),
681+
),
682+
};
683+
if (base) {
684+
taskInstallSet.installs.push(...base.installSet.installs);
685+
for (
686+
const [key, val] of Object.entries(
687+
base.installSet.allowedBuildDeps,
688+
)
689+
) {
690+
// prefer the port dep config of the child over any
691+
// similar deps in the base
692+
if (!taskInstallSet.allowedBuildDeps[key]) {
693+
taskInstallSet.allowedBuildDeps[key] = val;
694+
}
658695
}
659696
}
697+
installSetId = `ghjkTaskInstSet___${
698+
objectHash(JSON.parse(JSON.stringify(taskInstallSet)))
699+
}`;
700+
this.#installSets.set(installSetId, taskInstallSet);
701+
} else if (envBaseResolved?.length == 1) {
702+
installSetId = this.finalizedEnvs[envBaseResolved[0]].installSetId;
660703
}
661-
installSetId = `ghjkTaskInstSet___${
662-
objectHash(JSON.parse(JSON.stringify(taskInstallSet)))
663-
}`;
664-
this.#installSets.set(installSetId, taskInstallSet);
665-
} else if (envBaseResolved?.length == 1) {
666-
installSetId = this.finalizedEnvs[envBaseResolved[0]].installSetId;
667-
}
668704

669-
const mergedEnvVars = {
670-
...base?.vars,
671-
...args.vars,
672-
};
673-
const taskEnvRecipe: EnvRecipe = {
674-
provides: [
675-
...Object.entries(mergedEnvVars).map((
676-
[key, val],
677-
) => {
678-
const prov: WellKnownProvision = {
679-
ty: "posix.envVar",
680-
key,
681-
val: val.toString(),
682-
};
683-
return prov;
684-
}),
685-
],
686-
};
687-
if (installSetId) {
688-
const prov: InstallSetRefProvision = {
689-
ty: "ghjk.ports.InstallSetRef",
690-
setId: installSetId,
705+
const mergedEnvVars = {
706+
...base?.vars,
707+
...args.vars,
691708
};
692-
taskEnvRecipe.provides.push(prov);
693-
}
694709

695-
const envHash = objectHash(JSON.parse(JSON.stringify(taskEnvRecipe)));
696-
moduleConfig.envs[envHash] = taskEnvRecipe;
710+
const taskEnvRecipe: EnvRecipe = {
711+
provides: [
712+
...Object.entries(mergedEnvVars).map((
713+
[key, val],
714+
) => {
715+
const prov: WellKnownProvision = {
716+
ty: "posix.envVar",
717+
key,
718+
val: val.toString(),
719+
};
720+
return prov;
721+
}),
722+
],
723+
};
724+
if (installSetId) {
725+
const prov: InstallSetRefProvision = {
726+
ty: "ghjk.ports.InstallSetRef",
727+
setId: installSetId,
728+
};
729+
taskEnvRecipe.provides.push(prov);
730+
}
731+
732+
const envHash = objectHash(JSON.parse(JSON.stringify(taskEnvRecipe)));
733+
gatheredEnvs[envHash] = taskEnvRecipe;
734+
envKey = envHash;
735+
} else if (envBaseResolved?.length == 1) {
736+
envKey = envBaseResolved[0];
737+
}
697738

698739
const def: TaskDefHashed = {
699740
ty: args.ty,
@@ -710,7 +751,7 @@ export class Ghjkfile {
710751
),
711752
}
712753
: {},
713-
envHash,
754+
envKey,
714755
};
715756
const taskHash = objectHash(def);
716757
// we prefer the name as a key if present
@@ -767,6 +808,12 @@ export class Ghjkfile {
767808
});
768809
}
769810

811+
// add the task envs to the envsModuleConfig
812+
for (const [hash, env] of Object.entries(gatheredEnvs)) {
813+
envsConfig.envs[hash] = env;
814+
}
815+
816+
// reduce task based env hooks
770817
for (const [_name, env] of Object.entries(envsConfig.envs)) {
771818
env.provides = env.provides.map(
772819
(prov) => {
@@ -891,7 +938,10 @@ export class EnvBuilder {
891938
* Add multiple environment variable.
892939
*/
893940
vars(envVars: Record<string, string | number>) {
894-
Object.assign(this.#vars, envVars);
941+
Object.assign(
942+
this.#vars,
943+
unwrapParseRes(validators.envVars.safeParse(envVars), { envVars }),
944+
);
895945
return this;
896946
}
897947

@@ -963,7 +1013,6 @@ type InlineTaskHookProvision = Provision & {
9631013
export function reduceAllowedDeps(
9641014
deps: (AllowedPortDep | InstallConfigFat)[],
9651015
): AllowedPortDep[] {
966-
console.log(deps);
9671016
return deps.map(
9681017
(dep: any) => {
9691018
{

0 commit comments

Comments
 (0)