@sous-io/sous 0.1.1 → 0.2.0
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/README.md +115 -35
- package/bin/run.js +10 -1
- package/docs/markdown/README.md +27 -0
- package/docs/markdown/_sidebar.md +18 -0
- package/docs/markdown/commands.md +308 -0
- package/docs/markdown/config-discovery.md +74 -0
- package/docs/markdown/config-inspection.md +69 -0
- package/docs/markdown/config-layers.md +92 -0
- package/docs/markdown/config-variables.md +79 -0
- package/docs/markdown/configuration.md +71 -0
- package/docs/markdown/design-principles.md +59 -0
- package/docs/markdown/repositories-authoring.md +408 -0
- package/docs/markdown/repositories-consuming.md +580 -0
- package/docs/markdown/repositories-file-formats.md +1084 -0
- package/docs/markdown/repositories-variables.md +387 -0
- package/docs/markdown/repositories.md +303 -0
- package/docs/markdown/skill-categories.md +58 -0
- package/package.json +72 -8
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/SKILL.tpl.md +20 -20
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/examples/about-something.md +2 -2
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/examples/do-something.md +1 -1
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/advanced-patterns.md +6 -6
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/commands.md +5 -5
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/frontmatter.md +3 -3
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-liquid-templates/SKILL.tpl.md +40 -25
- package/recipes/core/sous-skills/skills/about-sous/SKILL.tpl.md +70 -0
- package/recipes/core/sous-skills/skills/about-sous-configuration/SKILL.tpl.md +75 -0
- package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/create-skill/SKILL.tpl.md +8 -9
- package/recipes/core/sous-skills/sous.recipe.yaml +45 -0
- package/sous.config.schema.json +337 -0
- package/src/base-command.ts +220 -67
- package/src/commands/build.ts +150 -73
- package/src/commands/clear.ts +23 -15
- package/src/commands/compile.ts +74 -16
- package/src/commands/config/get.ts +110 -0
- package/src/commands/config/show.ts +32 -0
- package/src/commands/config/validate.ts +53 -0
- package/src/commands/help.ts +46 -0
- package/src/commands/launch.ts +36 -14
- package/src/commands/lock/rebuild.ts +241 -0
- package/src/commands/lock/show.ts +115 -0
- package/src/commands/namespace/list.ts +117 -0
- package/src/commands/namespace/show.ts +110 -0
- package/src/commands/prune.ts +3 -11
- package/src/commands/recipe/list.ts +95 -0
- package/src/commands/recipe/show.ts +301 -0
- package/src/commands/repo/add.ts +145 -0
- package/src/commands/repo/gc.ts +172 -0
- package/src/commands/repo/init.ts +136 -0
- package/src/commands/repo/link.ts +500 -0
- package/src/commands/repo/list.ts +179 -0
- package/src/commands/repo/release.ts +619 -0
- package/src/commands/repo/remove.ts +193 -0
- package/src/commands/repo/search.ts +189 -0
- package/src/commands/repo/submit.ts +133 -0
- package/src/commands/repo/unlink.ts +147 -0
- package/src/commands/subscription/add.ts +285 -0
- package/src/commands/subscription/list.ts +129 -0
- package/src/commands/subscription/remove.ts +181 -0
- package/src/commands/vars/ask.ts +374 -0
- package/src/commands/vars/index.ts +79 -0
- package/src/commands/vars/list.ts +67 -0
- package/src/commands/vars/show.ts +77 -0
- package/src/config-command.ts +30 -0
- package/src/lib/build-service.ts +206 -54
- package/src/lib/config-discovery.ts +220 -27
- package/src/lib/config-inspect.ts +145 -0
- package/src/lib/config-kernel.mjs +377 -0
- package/src/lib/config-schema.ts +361 -0
- package/src/lib/env-file.ts +328 -0
- package/src/lib/env-local.ts +18 -1
- package/src/lib/errors.ts +32 -0
- package/src/lib/include-resolver.ts +108 -15
- package/src/lib/interactive.ts +165 -0
- package/src/lib/markdown-compiler.ts +118 -37
- package/src/lib/package-info.ts +25 -0
- package/src/lib/pid-service.ts +32 -21
- package/src/lib/refs/find.ts +589 -0
- package/src/lib/refs/index.ts +12 -0
- package/src/lib/refs/pick.ts +147 -0
- package/src/lib/refs/scopes.ts +61 -0
- package/src/lib/repos/catalog-display.ts +116 -0
- package/src/lib/repos/catalog-inputs.ts +160 -0
- package/src/lib/repos/catalog.ts +722 -0
- package/src/lib/repos/core-recipe.ts +105 -0
- package/src/lib/repos/defaults.ts +175 -0
- package/src/lib/repos/formats/common.ts +389 -0
- package/src/lib/repos/formats/index-file.ts +215 -0
- package/src/lib/repos/formats/links-map.ts +96 -0
- package/src/lib/repos/formats/lockfile.ts +167 -0
- package/src/lib/repos/formats/patterns.ts +57 -0
- package/src/lib/repos/formats/recipe-manifest.ts +395 -0
- package/src/lib/repos/formats/repo-manifest.ts +88 -0
- package/src/lib/repos/formats/store-entry.ts +84 -0
- package/src/lib/repos/freshness.ts +208 -0
- package/src/lib/repos/git-clone.ts +312 -0
- package/src/lib/repos/identity.ts +89 -0
- package/src/lib/repos/index.ts +58 -0
- package/src/lib/repos/links.ts +353 -0
- package/src/lib/repos/load-manifest.ts +236 -0
- package/src/lib/repos/lock-service.ts +453 -0
- package/src/lib/repos/locked-namespace-resolver.ts +90 -0
- package/src/lib/repos/locked-recipes.ts +254 -0
- package/src/lib/repos/managed-layer.ts +422 -0
- package/src/lib/repos/namespace-resolver.ts +370 -0
- package/src/lib/repos/providers/base.ts +206 -0
- package/src/lib/repos/providers/git.ts +233 -0
- package/src/lib/repos/providers/github.ts +294 -0
- package/src/lib/repos/providers/gitlab.ts +263 -0
- package/src/lib/repos/providers/http.ts +102 -0
- package/src/lib/repos/providers/index-cache.ts +382 -0
- package/src/lib/repos/providers/index.ts +106 -0
- package/src/lib/repos/providers/local.ts +391 -0
- package/src/lib/repos/providers/provider.ts +401 -0
- package/src/lib/repos/recipe-config-layers.ts +287 -0
- package/src/lib/repos/recipe-targets.ts +223 -0
- package/src/lib/repos/ref-search.ts +46 -0
- package/src/lib/repos/ref.ts +513 -0
- package/src/lib/repos/reference-report.ts +122 -0
- package/src/lib/repos/release/bump.ts +161 -0
- package/src/lib/repos/release/git-state.ts +305 -0
- package/src/lib/repos/release/index-builder.ts +635 -0
- package/src/lib/repos/release/index.ts +16 -0
- package/src/lib/repos/release/plan.ts +512 -0
- package/src/lib/repos/release/submit-service.ts +496 -0
- package/src/lib/repos/release/tags.ts +243 -0
- package/src/lib/repos/release/validate.ts +463 -0
- package/src/lib/repos/resolver.ts +789 -0
- package/src/lib/repos/scaffold/index.ts +238 -0
- package/src/lib/repos/scaffold/templates.ts +413 -0
- package/src/lib/repos/seed.ts +414 -0
- package/src/lib/repos/store/contract.ts +64 -0
- package/src/lib/repos/store/hash.ts +114 -0
- package/src/lib/repos/store/recipe-store.ts +599 -0
- package/src/lib/repos/store/settings.ts +58 -0
- package/src/lib/repos/subscription-service.ts +2678 -0
- package/src/lib/repos/trust.ts +447 -0
- package/src/lib/settings.ts +546 -189
- package/src/lib/sous-home.ts +104 -0
- package/src/lib/state.ts +52 -20
- package/src/lib/vars/ask.ts +1152 -0
- package/src/lib/vars/definition-source.ts +252 -0
- package/src/lib/vars/display.ts +233 -0
- package/src/lib/vars/index.ts +18 -0
- package/src/lib/vars/ladder.ts +282 -0
- package/src/lib/vars/mappings.ts +265 -0
- package/src/lib/vars/names.ts +94 -0
- package/src/lib/vars/preanswers.ts +395 -0
- package/src/lib/vars/question-plan.ts +218 -0
- package/src/lib/vars/report.ts +228 -0
- package/src/lib/vars/safe-regex.ts +235 -0
- package/src/lib/vars/validate.ts +312 -0
- package/src/lib/watch-loop.ts +148 -0
- package/src/templating/init-liquid-engine.ts +58 -16
- package/src/utils/choice-prompt.ts +143 -0
- package/src/utils/command-errors.ts +186 -0
- package/src/utils/command-help.ts +45 -0
- package/src/utils/confirm-prompt.ts +110 -0
- package/src/utils/flags.ts +153 -0
- package/src/utils/formatting.ts +540 -55
- package/src/utils/prompts.ts +35 -1
- package/src/utils/sous-directory.ts +245 -0
- package/src/utils/table.ts +603 -0
- package/src/utils/value-prompt.ts +119 -0
- package/shared-prompts/_partials/resume-task.md +0 -51
- package/shared-prompts/_partials/sub-agent-delegation.md +0 -32
- package/shared-prompts/_partials/update-task-file.md +0 -52
- package/shared-prompts/memories/automated-browser-tasks/INDEX.tpl.md +0 -52
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/SKILL.tpl.md +0 -102
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/auth-failure-handling.mjs +0 -81
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/chained-workflow.mjs +0 -126
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/simple-fetch.mjs +0 -92
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/architecture.md +0 -61
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/auth-and-sessions.md +0 -65
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/ctx-api.md +0 -96
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/installation.md +0 -104
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/script-conventions.md +0 -243
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/chrome-state.mjs +0 -148
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.mjs +0 -383
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.spec.mjs +0 -267
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/eslint.config.mjs +0 -56
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/harness.mjs +0 -169
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/keyring.mjs +0 -59
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/logger.mjs +0 -25
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/params.mjs +0 -140
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/run.mjs +0 -140
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/settings.tpl.mjs +0 -1
- package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/utils.mjs +0 -185
- package/shared-prompts/skills/automated-browser-tasks/create-automated-browser-task/SKILL.tpl.md +0 -52
- package/shared-prompts/skills/automated-browser-tasks/running-automated-browser-tasks/SKILL.tpl.md +0 -59
- package/shared-prompts/skills/automated-browser-tasks/update-automated-browser-task/SKILL.tpl.md +0 -47
- package/shared-prompts/skills/control-flow/approve/SKILL.tpl.md +0 -26
- package/shared-prompts/skills/control-flow/opine/SKILL.tpl.md +0 -58
- package/shared-prompts/skills/control-flow/repeat/SKILL.tpl.md +0 -27
- package/shared-prompts/skills/control-flow/research/SKILL.tpl.md +0 -34
- package/shared-prompts/skills/sous-skills/about-sous/SKILL.tpl.md +0 -51
- package/shared-prompts/skills/task-files/about-task-files/SKILL.tpl.md +0 -122
- package/shared-prompts/skills/task-files/continue-task-in-new-branch/SKILL.tpl.md +0 -80
- package/shared-prompts/skills/task-files/go/SKILL.tpl.md +0 -14
- package/shared-prompts/skills/task-files/resume-task/SKILL.tpl.md +0 -13
- package/shared-prompts/skills/task-files/start-task/SKILL.tpl.md +0 -93
- package/shared-prompts/skills/task-files/update/SKILL.tpl.md +0 -14
- package/shared-prompts/skills/task-files/update-task-file/SKILL.tpl.md +0 -13
- /package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/substitutions.md +0 -0
- /package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-liquid-templates/references/liquid-filters.md +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `sous repo gc`.
|
|
3
|
+
*
|
|
4
|
+
* Collects the machine-wide recipe store back down to its size cap, evicting the
|
|
5
|
+
* least recently used entries first. Everything this project's lockfile still
|
|
6
|
+
* pins is protected, whatever that does to the total, because a cache that is
|
|
7
|
+
* too large is a nuisance while evicting a pinned entry breaks a build.
|
|
8
|
+
*
|
|
9
|
+
* The store is disposable by design: everything in it is re-fetchable from the
|
|
10
|
+
* pins in a lockfile, so an entry evicted here comes back on the next build that
|
|
11
|
+
* needs it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Flags } from "@oclif/core";
|
|
15
|
+
import { BaseCommand } from "../../base-command.js";
|
|
16
|
+
import { subscriptionServiceFor } from "../../lib/repos/subscription-service.js";
|
|
17
|
+
import { resolveStoreSettings } from "../../lib/repos/store/settings.js";
|
|
18
|
+
import type { StoreKey } from "../../lib/repos/store/contract.js";
|
|
19
|
+
import { renderTable, type TableColumn } from "../../utils/table.js";
|
|
20
|
+
import {
|
|
21
|
+
blankLine,
|
|
22
|
+
dryRunNotice,
|
|
23
|
+
footer,
|
|
24
|
+
indent,
|
|
25
|
+
log,
|
|
26
|
+
paragraph,
|
|
27
|
+
section,
|
|
28
|
+
showCommandVars,
|
|
29
|
+
showVariables,
|
|
30
|
+
} from "../../utils/formatting.js";
|
|
31
|
+
|
|
32
|
+
/** How far every line of this command's output is indented. */
|
|
33
|
+
const INDENT = 2;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The columns the eviction report shows: what was removed, and how much room it
|
|
37
|
+
* was taking. Which repository it came from and when it was last read are the
|
|
38
|
+
* details that step aside on a narrow terminal.
|
|
39
|
+
*/
|
|
40
|
+
const EVICTED_COLUMNS: TableColumn[] = [
|
|
41
|
+
{ key: "recipe", header: "Recipe", kind: "path", overflow: "truncate", minWidth: 12 },
|
|
42
|
+
{ key: "version", header: "Version", overflow: "truncate" },
|
|
43
|
+
{ key: "size", header: "Size", kind: "number" },
|
|
44
|
+
{ key: "repo", header: "Repository", overflow: "truncate", priority: "medium" },
|
|
45
|
+
{ key: "lastUsed", header: "Last used", priority: "low", flex: 1 },
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/** Renders a byte count the way a person reads one. */
|
|
49
|
+
function describeSize(bytes: number): string {
|
|
50
|
+
if (bytes < 1024) return `${bytes} bytes`;
|
|
51
|
+
const units = ["KB", "MB", "GB", "TB"];
|
|
52
|
+
let value = bytes / 1024;
|
|
53
|
+
let unit = 0;
|
|
54
|
+
while (value >= 1024 && unit < units.length - 1) {
|
|
55
|
+
value /= 1024;
|
|
56
|
+
unit += 1;
|
|
57
|
+
}
|
|
58
|
+
return `${value.toFixed(1)} ${units[unit]}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default class RepoGc extends BaseCommand {
|
|
62
|
+
static description =
|
|
63
|
+
"Collect the machine-wide recipe store back down to its size cap";
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The other spelling of the topic. It lives under a hidden topic, so it is
|
|
67
|
+
* typable everywhere without ever reaching the top-level listing.
|
|
68
|
+
*/
|
|
69
|
+
static aliases = ["repos:gc"];
|
|
70
|
+
|
|
71
|
+
static examples = [
|
|
72
|
+
"<%= config.bin %> repo gc",
|
|
73
|
+
"<%= config.bin %> repo gc --dry-run",
|
|
74
|
+
"<%= config.bin %> repo gc --max-bytes 268435456",
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
static flags = {
|
|
78
|
+
...BaseCommand.baseFlags,
|
|
79
|
+
"max-bytes": Flags.integer({
|
|
80
|
+
description:
|
|
81
|
+
"The size cap to collect down to, instead of the one this project's config sets",
|
|
82
|
+
}),
|
|
83
|
+
"dry-run": Flags.boolean({
|
|
84
|
+
description: "Print what would be evicted without removing anything",
|
|
85
|
+
default: false,
|
|
86
|
+
}),
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
async run(): Promise<void> {
|
|
90
|
+
const { flags } = await this.parse(RepoGc);
|
|
91
|
+
const dryRun = flags["dry-run"];
|
|
92
|
+
|
|
93
|
+
const service = subscriptionServiceFor({
|
|
94
|
+
configContext: this.configContext,
|
|
95
|
+
settings: this.settings,
|
|
96
|
+
shellEnv: this.shellEnv,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const storeSettings = resolveStoreSettings(this.settings);
|
|
100
|
+
const maxBytes = flags["max-bytes"] ?? storeSettings.maxBytes;
|
|
101
|
+
|
|
102
|
+
showCommandVars({
|
|
103
|
+
Project: this.projectLabel,
|
|
104
|
+
Store: service.store.root,
|
|
105
|
+
"Size cap": describeSize(maxBytes),
|
|
106
|
+
"Dry Run": dryRun,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
section("Collecting the recipe store");
|
|
110
|
+
|
|
111
|
+
if (dryRun) {
|
|
112
|
+
dryRunNotice("Nothing will be removed.");
|
|
113
|
+
blankLine();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Everything this project pins is protected. Other projects on this machine
|
|
117
|
+
// pin things too, and their entries are re-fetchable, so this pass may evict
|
|
118
|
+
// them; that is what makes the store disposable.
|
|
119
|
+
const lock = service.lockService.read();
|
|
120
|
+
const keep: StoreKey[] = Object.entries(lock.recipes).flatMap(([key, entry]) => {
|
|
121
|
+
const identity = lock.repos[entry.repo]?.identity;
|
|
122
|
+
if (identity === undefined) return [];
|
|
123
|
+
const namespace = key.slice(0, key.indexOf("/"));
|
|
124
|
+
return [
|
|
125
|
+
{
|
|
126
|
+
identity,
|
|
127
|
+
namespace,
|
|
128
|
+
name: key.slice(namespace.length + 1),
|
|
129
|
+
version: entry.version,
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
const report = await service.store.gc({ maxBytes, keep, dryRun });
|
|
135
|
+
|
|
136
|
+
showVariables({
|
|
137
|
+
"Entries before": String(report.evicted.length + report.kept.length),
|
|
138
|
+
"Entries kept": String(report.kept.length),
|
|
139
|
+
"Entries evicted": String(report.evicted.length),
|
|
140
|
+
"Size before": describeSize(report.bytesBefore),
|
|
141
|
+
"Size after": describeSize(report.bytesAfter),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (report.evicted.length > 0) {
|
|
145
|
+
blankLine();
|
|
146
|
+
const rows = report.evicted.map((entry) => ({
|
|
147
|
+
repo: entry.repo,
|
|
148
|
+
recipe: `${entry.namespace}/${entry.name}`,
|
|
149
|
+
version: entry.version,
|
|
150
|
+
size: describeSize(entry.sizeBytes),
|
|
151
|
+
lastUsed: entry.lastAccessAt,
|
|
152
|
+
}));
|
|
153
|
+
|
|
154
|
+
for (const line of renderTable(EVICTED_COLUMNS, rows, { indent: INDENT })) {
|
|
155
|
+
log(indent(line, INDENT));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
blankLine();
|
|
160
|
+
paragraph(
|
|
161
|
+
report.evicted.length === 0
|
|
162
|
+
? "The store is already inside its size cap, so nothing was removed."
|
|
163
|
+
: dryRun
|
|
164
|
+
? "Nothing was removed. Everything listed above is re-fetchable from the " +
|
|
165
|
+
"lockfile that pins it."
|
|
166
|
+
: "Everything removed is re-fetchable from the lockfile that pins it; the " +
|
|
167
|
+
"next build that needs one will download it again."
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
footer();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
3
|
+
import { SOUS_VERSION } from "../../lib/settings.js";
|
|
4
|
+
import { scaffoldRepo } from "../../lib/repos/scaffold/index.js";
|
|
5
|
+
import { reportCommandError } from "../../utils/command-errors.js";
|
|
6
|
+
import { nonInteractiveFlag } from "../../utils/flags.js";
|
|
7
|
+
import {
|
|
8
|
+
dryRunNotice,
|
|
9
|
+
blankLine,
|
|
10
|
+
footer,
|
|
11
|
+
header,
|
|
12
|
+
log,
|
|
13
|
+
section,
|
|
14
|
+
showCommandVars,
|
|
15
|
+
showVariables,
|
|
16
|
+
} from "../../utils/formatting.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* `sous repo init` scaffolds a new recipe repository.
|
|
20
|
+
*
|
|
21
|
+
* This is the one repo command that does NOT extend BaseCommand. Every other
|
|
22
|
+
* command needs a discovered project config; this one creates a repository,
|
|
23
|
+
* which by definition is not a sous project and usually has no `.sous/`
|
|
24
|
+
* directory anywhere above it. Requiring discovery here would mean the command
|
|
25
|
+
* could only run inside an unrelated project, which is exactly backwards.
|
|
26
|
+
*/
|
|
27
|
+
export default class RepoInit extends Command {
|
|
28
|
+
static description = "Create a new sous recipe repository in a directory";
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The other spelling of the topic. It lives under a hidden topic, so it is
|
|
32
|
+
* typable everywhere without ever reaching the top-level listing.
|
|
33
|
+
*/
|
|
34
|
+
static aliases = ["repos:init"];
|
|
35
|
+
|
|
36
|
+
static examples = [
|
|
37
|
+
"<%= config.bin %> repo init",
|
|
38
|
+
"<%= config.bin %> repo init ./my-recipes",
|
|
39
|
+
"<%= config.bin %> repo init ./my-recipes --name team-recipes --namespace workflow",
|
|
40
|
+
"<%= config.bin %> repo init ./my-recipes --dry-run",
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
static args = {
|
|
44
|
+
directory: Args.string({
|
|
45
|
+
description: "Directory to create the repository in (defaults to the current one)",
|
|
46
|
+
required: false,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
static flags = {
|
|
51
|
+
name: Flags.string({
|
|
52
|
+
description:
|
|
53
|
+
"Short name for the repository (defaults to the directory's own name)",
|
|
54
|
+
}),
|
|
55
|
+
namespace: Flags.string({
|
|
56
|
+
description:
|
|
57
|
+
"Name of the one namespace to declare (defaults to the repository's name)",
|
|
58
|
+
}),
|
|
59
|
+
force: Flags.boolean({
|
|
60
|
+
description: "Write the scaffold over a repository that already exists",
|
|
61
|
+
default: false,
|
|
62
|
+
}),
|
|
63
|
+
"dry-run": Flags.boolean({
|
|
64
|
+
description: "Print the files that would be written without writing them",
|
|
65
|
+
default: false,
|
|
66
|
+
}),
|
|
67
|
+
// This command does not extend BaseCommand, so it declares the global
|
|
68
|
+
// non-interactive flag itself; the rule is the same everywhere.
|
|
69
|
+
"non-interactive": nonInteractiveFlag(),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
async init(): Promise<void> {
|
|
73
|
+
await super.init();
|
|
74
|
+
header();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async run(): Promise<void> {
|
|
78
|
+
const { args, flags } = await this.parse(RepoInit);
|
|
79
|
+
const directory = path.resolve(process.cwd(), args.directory ?? ".");
|
|
80
|
+
|
|
81
|
+
showCommandVars({
|
|
82
|
+
Directory: directory,
|
|
83
|
+
Name: flags.name ?? "(from the directory name)",
|
|
84
|
+
Namespace: flags.namespace ?? "(same as the repository name)",
|
|
85
|
+
"Dry Run": flags["dry-run"],
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
section("Creating a recipe repository");
|
|
89
|
+
|
|
90
|
+
const result = scaffoldRepo({
|
|
91
|
+
directory,
|
|
92
|
+
name: flags.name,
|
|
93
|
+
namespace: flags.namespace,
|
|
94
|
+
force: flags.force,
|
|
95
|
+
dryRun: flags["dry-run"],
|
|
96
|
+
sousVersion: SOUS_VERSION,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
for (const file of result.files) {
|
|
100
|
+
if (result.dryRun) dryRunNotice(`would write ${file}`);
|
|
101
|
+
else log(` wrote ${file}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
section("What to do next");
|
|
105
|
+
showVariables({
|
|
106
|
+
Repository: result.name,
|
|
107
|
+
Namespace: result.namespace,
|
|
108
|
+
"Example recipe": path.join(
|
|
109
|
+
"recipes",
|
|
110
|
+
result.namespace,
|
|
111
|
+
"example",
|
|
112
|
+
"sous.recipe.yaml"
|
|
113
|
+
),
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
blankLine();
|
|
117
|
+
log(" Edit the example recipe, or copy its folder to start another one.");
|
|
118
|
+
log(" Every recipe folder must also be listed under 'recipes' in sous.repo.yaml.");
|
|
119
|
+
log(" Commit the repository and push it, then add it to a project with");
|
|
120
|
+
log(" 'sous repo add <url>'. Adding a repository is what trusts it.");
|
|
121
|
+
|
|
122
|
+
footer();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Reports a failure the way every other sous command reports one: the message
|
|
127
|
+
* on its own, this command's help underneath it when the command line was the
|
|
128
|
+
* problem or a question could not be asked, and a stack trace only when
|
|
129
|
+
* `SOUS_DEBUG` asks for one. The rules live in `utils/command-errors.ts`.
|
|
130
|
+
*/
|
|
131
|
+
protected async catch(error: Error & { exitCode?: number }): Promise<unknown> {
|
|
132
|
+
const exitCode = await reportCommandError(this, error);
|
|
133
|
+
if (exitCode === undefined) return super.catch(error);
|
|
134
|
+
return this.exit(exitCode);
|
|
135
|
+
}
|
|
136
|
+
}
|