@h-rig/repos-plugin 0.0.6-alpha.156
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 +1 -0
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.js +491 -0
- package/dist/src/layout.d.ts +10 -0
- package/dist/src/layout.js +83 -0
- package/dist/src/mirror/bootstrap.d.ts +2 -0
- package/dist/src/mirror/bootstrap.js +192 -0
- package/dist/src/mirror/refresh.d.ts +3 -0
- package/dist/src/mirror/refresh.js +322 -0
- package/dist/src/mirror/state.d.ts +3 -0
- package/dist/src/mirror/state.js +93 -0
- package/dist/src/plugin.d.ts +4 -0
- package/dist/src/plugin.js +457 -0
- package/dist/src/registry.d.ts +21 -0
- package/dist/src/registry.js +77 -0
- package/dist/src/service.d.ts +13 -0
- package/dist/src/service.js +391 -0
- package/package.json +36 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, {
|
|
10
|
+
get: all[name],
|
|
11
|
+
enumerable: true,
|
|
12
|
+
configurable: true,
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
|
+
|
|
18
|
+
// packages/repos-plugin/src/registry.ts
|
|
19
|
+
function createRepoRegistry(entries) {
|
|
20
|
+
const map = new Map;
|
|
21
|
+
for (const e of entries) {
|
|
22
|
+
if (map.has(e.id))
|
|
23
|
+
throw new Error(`repo already registered: ${e.id}`);
|
|
24
|
+
map.set(e.id, { ...e });
|
|
25
|
+
}
|
|
26
|
+
const ordered = Array.from(map.values());
|
|
27
|
+
return {
|
|
28
|
+
getById: (id) => map.get(id),
|
|
29
|
+
list: () => ordered
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function setManagedRepos(entries) {
|
|
33
|
+
const next = new Map;
|
|
34
|
+
for (const e of entries) {
|
|
35
|
+
if (next.has(e.id)) {
|
|
36
|
+
throw new Error(`managed repo already registered: ${e.id}`);
|
|
37
|
+
}
|
|
38
|
+
next.set(e.id, e);
|
|
39
|
+
}
|
|
40
|
+
MANAGED_REPOS = next;
|
|
41
|
+
}
|
|
42
|
+
function getManagedRepoEntry(repoId) {
|
|
43
|
+
const entry = MANAGED_REPOS.get(repoId);
|
|
44
|
+
if (!entry) {
|
|
45
|
+
throw new Error(`managed repo not registered: ${repoId}. Plugins contribute repos via RigPlugin.contributes.repoSources; ` + `make sure a plugin declares this id and the plugin host has been initialized.`);
|
|
46
|
+
}
|
|
47
|
+
return entry;
|
|
48
|
+
}
|
|
49
|
+
function listManagedRepoEntries() {
|
|
50
|
+
return Array.from(MANAGED_REPOS.values());
|
|
51
|
+
}
|
|
52
|
+
function resolveManagedRepoIdByAlias(alias) {
|
|
53
|
+
for (const entry of MANAGED_REPOS.values()) {
|
|
54
|
+
if (entry.alias === alias) {
|
|
55
|
+
return entry.id;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
function repoRegistrationToManagedEntry(reg) {
|
|
61
|
+
if (!reg.defaultBranch) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
id: reg.id,
|
|
66
|
+
alias: reg.defaultPath ?? reg.id,
|
|
67
|
+
defaultBranch: reg.defaultBranch,
|
|
68
|
+
defaultRemoteUrl: reg.url,
|
|
69
|
+
remoteEnvVar: reg.remoteEnvVar,
|
|
70
|
+
checkoutEnvVar: reg.checkoutEnvVar
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
var MANAGED_REPOS;
|
|
74
|
+
var init_registry = __esm(() => {
|
|
75
|
+
MANAGED_REPOS = new Map;
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// packages/repos-plugin/src/layout.ts
|
|
79
|
+
import { existsSync } from "fs";
|
|
80
|
+
import { basename, dirname, join, resolve } from "path";
|
|
81
|
+
import { resolveMonorepoRoot } from "@rig/runtime/layout";
|
|
82
|
+
function resolveRepoStateDir(projectRoot) {
|
|
83
|
+
const normalizedProjectRoot = resolve(projectRoot);
|
|
84
|
+
const projectParent = dirname(normalizedProjectRoot);
|
|
85
|
+
if (basename(projectParent) === ".worktrees") {
|
|
86
|
+
const ownerRoot = dirname(projectParent);
|
|
87
|
+
const ownerHasRepoMarkers = existsSync(resolve(ownerRoot, ".git")) || existsSync(resolve(ownerRoot, ".rig", "state"));
|
|
88
|
+
if (ownerHasRepoMarkers) {
|
|
89
|
+
return resolve(ownerRoot, ".rig", "state");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return resolve(projectRoot, ".rig", "state");
|
|
93
|
+
}
|
|
94
|
+
function resolveManagedRepoLayout(projectRoot, repoId) {
|
|
95
|
+
const normalizedProjectRoot = resolve(projectRoot);
|
|
96
|
+
const entry = getManagedRepoEntry(repoId);
|
|
97
|
+
const stateDir = resolveRepoStateDir(normalizedProjectRoot);
|
|
98
|
+
const metadataRelativePath = join("repos", entry.id);
|
|
99
|
+
const metadataRoot = resolve(stateDir, metadataRelativePath);
|
|
100
|
+
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
101
|
+
const runsInsideTaskWorktree = runtimeWorkspace && resolve(runtimeWorkspace) === normalizedProjectRoot || basename(dirname(normalizedProjectRoot)) === ".worktrees";
|
|
102
|
+
const isPrimaryManagedRepo = listManagedRepoEntries()[0]?.id === repoId;
|
|
103
|
+
const checkoutRoot = isPrimaryManagedRepo && runsInsideTaskWorktree ? resolveMonorepoRoot(normalizedProjectRoot) : entry.checkoutEnvVar && process.env[entry.checkoutEnvVar]?.trim() ? resolve(process.env[entry.checkoutEnvVar].trim()) : resolve(normalizedProjectRoot, entry.alias);
|
|
104
|
+
return {
|
|
105
|
+
projectRoot: normalizedProjectRoot,
|
|
106
|
+
repoId: entry.id,
|
|
107
|
+
alias: entry.alias,
|
|
108
|
+
defaultBranch: entry.defaultBranch,
|
|
109
|
+
remoteUrl: entry.remoteEnvVar && process.env[entry.remoteEnvVar]?.trim() ? process.env[entry.remoteEnvVar].trim() : entry.defaultRemoteUrl,
|
|
110
|
+
checkoutRoot,
|
|
111
|
+
worktreesRoot: resolve(checkoutRoot, ".worktrees"),
|
|
112
|
+
stateDir,
|
|
113
|
+
metadataRoot,
|
|
114
|
+
metadataRelativePath,
|
|
115
|
+
mirrorRoot: resolve(metadataRoot, "mirror.git"),
|
|
116
|
+
mirrorStatePath: resolve(metadataRoot, "mirror-state.json"),
|
|
117
|
+
mirrorStateRelativePath: join(metadataRelativePath, "mirror-state.json")
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function resolveManagedRepoLayoutByAlias(projectRoot, alias) {
|
|
121
|
+
const repoId = resolveManagedRepoIdByAlias(alias);
|
|
122
|
+
return repoId ? resolveManagedRepoLayout(projectRoot, repoId) : null;
|
|
123
|
+
}
|
|
124
|
+
function resolveMonorepoRepoLayout(projectRoot) {
|
|
125
|
+
const entries = listManagedRepoEntries();
|
|
126
|
+
if (entries.length === 0) {
|
|
127
|
+
throw new Error("resolveMonorepoRepoLayout: no managed repos registered. Either contribute one via " + "RigPlugin.contributes.repoSources (with defaultBranch set), or avoid calling this " + "function for projects where the project root IS the monorepo.");
|
|
128
|
+
}
|
|
129
|
+
const primary = entries[0];
|
|
130
|
+
return resolveManagedRepoLayout(projectRoot, primary.id);
|
|
131
|
+
}
|
|
132
|
+
var init_layout = __esm(() => {
|
|
133
|
+
init_registry();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// packages/repos-plugin/src/mirror/state.ts
|
|
137
|
+
import { readAuthorityProjectStateJson, writeAuthorityProjectStateJson } from "@rig/runtime/control-plane/json-files";
|
|
138
|
+
function defaultMirrorState(projectRoot, repoId) {
|
|
139
|
+
const layout = resolveManagedRepoLayout(projectRoot, repoId);
|
|
140
|
+
return {
|
|
141
|
+
version: STATE_VERSION,
|
|
142
|
+
repoId,
|
|
143
|
+
remoteUrl: layout.remoteUrl,
|
|
144
|
+
defaultBranch: layout.defaultBranch
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function readManagedRepoMirrorState(projectRoot, repoId) {
|
|
148
|
+
const layout = resolveManagedRepoLayout(projectRoot, repoId);
|
|
149
|
+
return readAuthorityProjectStateJson(projectRoot, layout.mirrorStateRelativePath, null);
|
|
150
|
+
}
|
|
151
|
+
function writeManagedRepoMirrorState(projectRoot, repoId, patch) {
|
|
152
|
+
const current = readManagedRepoMirrorState(projectRoot, repoId) || defaultMirrorState(projectRoot, repoId);
|
|
153
|
+
const next = {
|
|
154
|
+
...current,
|
|
155
|
+
...patch,
|
|
156
|
+
version: STATE_VERSION,
|
|
157
|
+
repoId
|
|
158
|
+
};
|
|
159
|
+
const layout = resolveManagedRepoLayout(projectRoot, repoId);
|
|
160
|
+
writeAuthorityProjectStateJson(projectRoot, layout.mirrorStateRelativePath, next);
|
|
161
|
+
return next;
|
|
162
|
+
}
|
|
163
|
+
var STATE_VERSION = 1;
|
|
164
|
+
var init_state = __esm(() => {
|
|
165
|
+
init_layout();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// packages/repos-plugin/src/mirror/bootstrap.ts
|
|
169
|
+
import { existsSync as existsSync2, mkdirSync, realpathSync } from "fs";
|
|
170
|
+
import { resolve as resolve2 } from "path";
|
|
171
|
+
function nowIso() {
|
|
172
|
+
return new Date().toISOString();
|
|
173
|
+
}
|
|
174
|
+
function runGit(command, cwd) {
|
|
175
|
+
const result = Bun.spawnSync(command, {
|
|
176
|
+
cwd,
|
|
177
|
+
stdout: "pipe",
|
|
178
|
+
stderr: "pipe",
|
|
179
|
+
env: process.env
|
|
180
|
+
});
|
|
181
|
+
return {
|
|
182
|
+
exitCode: result.exitCode,
|
|
183
|
+
stdout: result.stdout.toString(),
|
|
184
|
+
stderr: result.stderr.toString()
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function ensureGitSuccess(result, command) {
|
|
188
|
+
if (result.exitCode !== 0) {
|
|
189
|
+
throw new Error(result.stderr || result.stdout || `git command failed: ${command.join(" ")}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function isUsableRemoteUrl(candidate, layout) {
|
|
193
|
+
return candidate.length > 0 && candidate !== layout.mirrorRoot && candidate !== layout.checkoutRoot;
|
|
194
|
+
}
|
|
195
|
+
function sameExistingPath(left, right) {
|
|
196
|
+
try {
|
|
197
|
+
return realpathSync(left) === realpathSync(right);
|
|
198
|
+
} catch {
|
|
199
|
+
return resolve2(left) === resolve2(right);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function repoLooksUsable(repoRoot, projectRoot) {
|
|
203
|
+
const probe = runGit(["git", "-C", repoRoot, "rev-parse", "--show-toplevel"], projectRoot);
|
|
204
|
+
return probe.exitCode === 0 && sameExistingPath(probe.stdout.trim(), repoRoot);
|
|
205
|
+
}
|
|
206
|
+
function checkoutLooksUsable(layout) {
|
|
207
|
+
return repoLooksUsable(layout.checkoutRoot, layout.projectRoot);
|
|
208
|
+
}
|
|
209
|
+
function resolveMirrorRemoteUrl(layout) {
|
|
210
|
+
const entry = getManagedRepoEntry(layout.repoId);
|
|
211
|
+
const explicit = entry.remoteEnvVar ? process.env[entry.remoteEnvVar]?.trim() : "";
|
|
212
|
+
if (explicit) {
|
|
213
|
+
return explicit;
|
|
214
|
+
}
|
|
215
|
+
const persisted = readManagedRepoMirrorState(layout.projectRoot, layout.repoId)?.remoteUrl?.trim();
|
|
216
|
+
if (persisted && isUsableRemoteUrl(persisted, layout)) {
|
|
217
|
+
return persisted;
|
|
218
|
+
}
|
|
219
|
+
const mirrorOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
220
|
+
if (mirrorOrigin.exitCode === 0) {
|
|
221
|
+
const currentOrigin = mirrorOrigin.stdout.trim();
|
|
222
|
+
if (isUsableRemoteUrl(currentOrigin, layout)) {
|
|
223
|
+
return currentOrigin;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (repoLooksUsable(layout.projectRoot, layout.projectRoot)) {
|
|
227
|
+
const projectOrigin = runGit(["git", "-C", layout.projectRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
228
|
+
if (projectOrigin.exitCode === 0) {
|
|
229
|
+
const currentOrigin = projectOrigin.stdout.trim();
|
|
230
|
+
if (isUsableRemoteUrl(currentOrigin, layout)) {
|
|
231
|
+
return currentOrigin;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (existsSync2(resolve2(layout.checkoutRoot, ".git")) && checkoutLooksUsable(layout)) {
|
|
236
|
+
const checkoutOrigin = runGit(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
237
|
+
if (checkoutOrigin.exitCode === 0) {
|
|
238
|
+
const currentOrigin = checkoutOrigin.stdout.trim();
|
|
239
|
+
if (isUsableRemoteUrl(currentOrigin, layout)) {
|
|
240
|
+
return currentOrigin;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return layout.remoteUrl;
|
|
245
|
+
}
|
|
246
|
+
function ensureManagedRepoMirror(projectRoot, repoId) {
|
|
247
|
+
const layout = resolveManagedRepoLayout(projectRoot, repoId);
|
|
248
|
+
mkdirSync(layout.metadataRoot, { recursive: true });
|
|
249
|
+
const remoteUrl = resolveMirrorRemoteUrl(layout);
|
|
250
|
+
if (!existsSync2(resolve2(layout.mirrorRoot, "HEAD"))) {
|
|
251
|
+
ensureGitSuccess(runGit(["git", "init", "--bare", layout.mirrorRoot], layout.projectRoot), ["git", "init", "--bare", layout.mirrorRoot]);
|
|
252
|
+
}
|
|
253
|
+
const getOrigin = runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
254
|
+
if (getOrigin.exitCode === 0) {
|
|
255
|
+
const currentOrigin = getOrigin.stdout.trim();
|
|
256
|
+
if (currentOrigin !== remoteUrl) {
|
|
257
|
+
ensureGitSuccess(runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "set-url", "origin", remoteUrl], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "set-url", "origin", remoteUrl]);
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
ensureGitSuccess(runGit(["git", "--git-dir", layout.mirrorRoot, "remote", "add", "origin", remoteUrl], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "add", "origin", remoteUrl]);
|
|
261
|
+
}
|
|
262
|
+
writeManagedRepoMirrorState(projectRoot, repoId, {
|
|
263
|
+
remoteUrl,
|
|
264
|
+
defaultBranch: layout.defaultBranch,
|
|
265
|
+
initializedAt: nowIso()
|
|
266
|
+
});
|
|
267
|
+
return layout;
|
|
268
|
+
}
|
|
269
|
+
var init_bootstrap = __esm(() => {
|
|
270
|
+
init_registry();
|
|
271
|
+
init_layout();
|
|
272
|
+
init_state();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// packages/repos-plugin/src/mirror/refresh.ts
|
|
276
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, realpathSync as realpathSync2, rmSync } from "fs";
|
|
277
|
+
import { resolve as resolve3 } from "path";
|
|
278
|
+
function nowIso2() {
|
|
279
|
+
return new Date().toISOString();
|
|
280
|
+
}
|
|
281
|
+
function runGit2(command, cwd) {
|
|
282
|
+
const result = Bun.spawnSync(command, {
|
|
283
|
+
cwd,
|
|
284
|
+
stdout: "pipe",
|
|
285
|
+
stderr: "pipe",
|
|
286
|
+
env: process.env
|
|
287
|
+
});
|
|
288
|
+
return {
|
|
289
|
+
exitCode: result.exitCode,
|
|
290
|
+
stdout: result.stdout.toString(),
|
|
291
|
+
stderr: result.stderr.toString()
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function ensureGitSuccess2(result, command) {
|
|
295
|
+
if (result.exitCode !== 0) {
|
|
296
|
+
throw new Error(result.stderr || result.stdout || `git command failed: ${command.join(" ")}`);
|
|
297
|
+
}
|
|
298
|
+
return result.stdout.trim();
|
|
299
|
+
}
|
|
300
|
+
function sameExistingPath2(left, right) {
|
|
301
|
+
try {
|
|
302
|
+
return realpathSync2(left) === realpathSync2(right);
|
|
303
|
+
} catch {
|
|
304
|
+
return resolve3(left) === resolve3(right);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function ensureMirrorHead(layout) {
|
|
308
|
+
ensureGitSuccess2(runGit2([
|
|
309
|
+
"git",
|
|
310
|
+
"--git-dir",
|
|
311
|
+
layout.mirrorRoot,
|
|
312
|
+
"fetch",
|
|
313
|
+
"--prune",
|
|
314
|
+
"origin",
|
|
315
|
+
"+refs/heads/*:refs/heads/*",
|
|
316
|
+
"+refs/tags/*:refs/tags/*"
|
|
317
|
+
], layout.projectRoot), [
|
|
318
|
+
"git",
|
|
319
|
+
"--git-dir",
|
|
320
|
+
layout.mirrorRoot,
|
|
321
|
+
"fetch",
|
|
322
|
+
"--prune",
|
|
323
|
+
"origin",
|
|
324
|
+
"+refs/heads/*:refs/heads/*",
|
|
325
|
+
"+refs/tags/*:refs/tags/*"
|
|
326
|
+
]);
|
|
327
|
+
const headRef = `refs/heads/${layout.defaultBranch}`;
|
|
328
|
+
const headCommit = ensureGitSuccess2(runGit2(["git", "--git-dir", layout.mirrorRoot, "rev-parse", headRef], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "rev-parse", headRef]);
|
|
329
|
+
const remoteUrl = ensureGitSuccess2(runGit2(["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "remote", "get-url", "origin"]);
|
|
330
|
+
ensureGitSuccess2(runGit2(["git", "--git-dir", layout.mirrorRoot, "symbolic-ref", "HEAD", headRef], layout.projectRoot), ["git", "--git-dir", layout.mirrorRoot, "symbolic-ref", "HEAD", headRef]);
|
|
331
|
+
writeManagedRepoMirrorState(layout.projectRoot, layout.repoId, {
|
|
332
|
+
remoteUrl,
|
|
333
|
+
defaultBranch: layout.defaultBranch,
|
|
334
|
+
lastSyncedAt: nowIso2(),
|
|
335
|
+
headRef,
|
|
336
|
+
headCommit
|
|
337
|
+
});
|
|
338
|
+
return headCommit;
|
|
339
|
+
}
|
|
340
|
+
function refreshManagedRepoMirror(projectRoot, repoId) {
|
|
341
|
+
const layout = ensureManagedRepoMirror(projectRoot, repoId);
|
|
342
|
+
const headCommit = ensureMirrorHead(layout);
|
|
343
|
+
return { layout, headCommit };
|
|
344
|
+
}
|
|
345
|
+
function checkoutLooksUsable2(layout) {
|
|
346
|
+
const probe = runGit2(["git", "-C", layout.checkoutRoot, "rev-parse", "--show-toplevel"], layout.projectRoot);
|
|
347
|
+
return probe.exitCode === 0 && sameExistingPath2(probe.stdout.trim(), layout.checkoutRoot);
|
|
348
|
+
}
|
|
349
|
+
function ensureCheckoutFromMirror(layout) {
|
|
350
|
+
mkdirSync2(resolve3(layout.checkoutRoot, ".."), { recursive: true });
|
|
351
|
+
const gitPath = resolve3(layout.checkoutRoot, ".git");
|
|
352
|
+
if (existsSync3(layout.checkoutRoot) && (!existsSync3(gitPath) || !checkoutLooksUsable2(layout))) {
|
|
353
|
+
rmSync(layout.checkoutRoot, { recursive: true, force: true });
|
|
354
|
+
}
|
|
355
|
+
if (!existsSync3(gitPath)) {
|
|
356
|
+
ensureGitSuccess2(runGit2(["git", "clone", layout.mirrorRoot, layout.checkoutRoot], layout.projectRoot), ["git", "clone", layout.mirrorRoot, layout.checkoutRoot]);
|
|
357
|
+
}
|
|
358
|
+
const getOrigin = runGit2(["git", "-C", layout.checkoutRoot, "remote", "get-url", "origin"], layout.projectRoot);
|
|
359
|
+
if (getOrigin.exitCode === 0) {
|
|
360
|
+
const currentOrigin = getOrigin.stdout.trim();
|
|
361
|
+
if (currentOrigin !== layout.mirrorRoot) {
|
|
362
|
+
ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "remote", "set-url", "origin", layout.mirrorRoot], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "remote", "set-url", "origin", layout.mirrorRoot]);
|
|
363
|
+
}
|
|
364
|
+
} else {
|
|
365
|
+
ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "remote", "add", "origin", layout.mirrorRoot], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "remote", "add", "origin", layout.mirrorRoot]);
|
|
366
|
+
}
|
|
367
|
+
ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "fetch", "origin", layout.defaultBranch], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "fetch", "origin", layout.defaultBranch]);
|
|
368
|
+
ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "reset", "--hard"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "reset", "--hard"]);
|
|
369
|
+
ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "clean", "-fd"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "clean", "-fd"]);
|
|
370
|
+
ensureGitSuccess2(runGit2([
|
|
371
|
+
"git",
|
|
372
|
+
"-C",
|
|
373
|
+
layout.checkoutRoot,
|
|
374
|
+
"checkout",
|
|
375
|
+
"--force",
|
|
376
|
+
"-B",
|
|
377
|
+
layout.defaultBranch,
|
|
378
|
+
`origin/${layout.defaultBranch}`
|
|
379
|
+
], layout.projectRoot), [
|
|
380
|
+
"git",
|
|
381
|
+
"-C",
|
|
382
|
+
layout.checkoutRoot,
|
|
383
|
+
"checkout",
|
|
384
|
+
"--force",
|
|
385
|
+
"-B",
|
|
386
|
+
layout.defaultBranch,
|
|
387
|
+
`origin/${layout.defaultBranch}`
|
|
388
|
+
]);
|
|
389
|
+
ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "reset", "--hard", `origin/${layout.defaultBranch}`], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "reset", "--hard", `origin/${layout.defaultBranch}`]);
|
|
390
|
+
ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "clean", "-fd"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "clean", "-fd"]);
|
|
391
|
+
return ensureGitSuccess2(runGit2(["git", "-C", layout.checkoutRoot, "rev-parse", "HEAD"], layout.projectRoot), ["git", "-C", layout.checkoutRoot, "rev-parse", "HEAD"]);
|
|
392
|
+
}
|
|
393
|
+
function syncManagedRepo(projectRoot, repoId) {
|
|
394
|
+
const { layout, headCommit } = refreshManagedRepoMirror(projectRoot, repoId);
|
|
395
|
+
const checkoutCommit = ensureCheckoutFromMirror(layout);
|
|
396
|
+
if (checkoutCommit !== headCommit) {
|
|
397
|
+
throw new Error(`Managed repo checkout ${layout.alias} is out of sync with mirror: expected ${headCommit}, got ${checkoutCommit}.`);
|
|
398
|
+
}
|
|
399
|
+
return { layout, headCommit };
|
|
400
|
+
}
|
|
401
|
+
var init_refresh = __esm(() => {
|
|
402
|
+
init_bootstrap();
|
|
403
|
+
init_state();
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// packages/repos-plugin/src/service.ts
|
|
407
|
+
var exports_service = {};
|
|
408
|
+
__export(exports_service, {
|
|
409
|
+
svc: () => svc,
|
|
410
|
+
managedRepoService: () => managedRepoService
|
|
411
|
+
});
|
|
412
|
+
var managedRepoService, svc;
|
|
413
|
+
var init_service = __esm(() => {
|
|
414
|
+
init_registry();
|
|
415
|
+
init_layout();
|
|
416
|
+
init_refresh();
|
|
417
|
+
managedRepoService = {
|
|
418
|
+
setManagedRepos,
|
|
419
|
+
listManagedRepoEntries,
|
|
420
|
+
resolveManagedRepoIdByAlias,
|
|
421
|
+
repoRegistrationToManagedEntry,
|
|
422
|
+
createRepoRegistry,
|
|
423
|
+
resolveManagedRepoLayoutByAlias,
|
|
424
|
+
resolveMonorepoRepoLayout,
|
|
425
|
+
syncManagedRepo
|
|
426
|
+
};
|
|
427
|
+
svc = managedRepoService;
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// packages/repos-plugin/src/plugin.ts
|
|
431
|
+
import { definePlugin } from "@rig/core/config";
|
|
432
|
+
import { MANAGED_REPO_SERVICE_CAPABILITY_ID } from "@rig/contracts";
|
|
433
|
+
var REPOS_PLUGIN_NAME = "@rig/repos-plugin";
|
|
434
|
+
var reposPlugin = definePlugin({
|
|
435
|
+
name: REPOS_PLUGIN_NAME,
|
|
436
|
+
version: "0.0.0-alpha.1",
|
|
437
|
+
contributes: {
|
|
438
|
+
capabilities: [
|
|
439
|
+
{
|
|
440
|
+
id: MANAGED_REPO_SERVICE_CAPABILITY_ID,
|
|
441
|
+
title: "Managed repositories",
|
|
442
|
+
description: "Registry, on-disk layout, and mirror/sync for plugin-contributed managed repos.",
|
|
443
|
+
run: async () => (await Promise.resolve().then(() => (init_service(), exports_service))).svc
|
|
444
|
+
}
|
|
445
|
+
]
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
function createReposPlugin() {
|
|
449
|
+
return reposPlugin;
|
|
450
|
+
}
|
|
451
|
+
var plugin_default = reposPlugin;
|
|
452
|
+
export {
|
|
453
|
+
reposPlugin,
|
|
454
|
+
plugin_default as default,
|
|
455
|
+
createReposPlugin,
|
|
456
|
+
REPOS_PLUGIN_NAME
|
|
457
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ManagedRepoAlias, ManagedRepoId, ManagedRepoRegistryEntry, RepoRegistry, RepoSourceRegistration } from "@rig/contracts";
|
|
2
|
+
/**
|
|
3
|
+
* Build a pluggable repo registry from an injected list of entries.
|
|
4
|
+
*
|
|
5
|
+
* Throws on duplicate `id` values. The registry is immutable after creation.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createRepoRegistry(entries: readonly RepoSourceRegistration[]): RepoRegistry;
|
|
8
|
+
export declare function setManagedRepos(entries: readonly ManagedRepoRegistryEntry[]): void;
|
|
9
|
+
export declare function clearManagedRepos(): void;
|
|
10
|
+
export declare function getManagedRepoEntry(repoId: ManagedRepoId): ManagedRepoRegistryEntry;
|
|
11
|
+
export declare function tryGetManagedRepoEntry(repoId: ManagedRepoId): ManagedRepoRegistryEntry | undefined;
|
|
12
|
+
export declare function listManagedRepoEntries(): ManagedRepoRegistryEntry[];
|
|
13
|
+
export declare function resolveManagedRepoIdByAlias(alias: string): ManagedRepoId | null;
|
|
14
|
+
export declare function isManagedRepoAlias(alias: string): alias is ManagedRepoAlias;
|
|
15
|
+
/**
|
|
16
|
+
* Convert a plugin-contributed RepoSourceRegistration into the managed-repo
|
|
17
|
+
* shape required by the legacy mirror/sync layer. Returns null if the
|
|
18
|
+
* registration is a pure listing (no `defaultBranch`), in which case it has
|
|
19
|
+
* no managed-repo behavior — only display.
|
|
20
|
+
*/
|
|
21
|
+
export declare function repoRegistrationToManagedEntry(reg: RepoSourceRegistration): ManagedRepoRegistryEntry | null;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/repos-plugin/src/registry.ts
|
|
3
|
+
function createRepoRegistry(entries) {
|
|
4
|
+
const map = new Map;
|
|
5
|
+
for (const e of entries) {
|
|
6
|
+
if (map.has(e.id))
|
|
7
|
+
throw new Error(`repo already registered: ${e.id}`);
|
|
8
|
+
map.set(e.id, { ...e });
|
|
9
|
+
}
|
|
10
|
+
const ordered = Array.from(map.values());
|
|
11
|
+
return {
|
|
12
|
+
getById: (id) => map.get(id),
|
|
13
|
+
list: () => ordered
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
var MANAGED_REPOS = new Map;
|
|
17
|
+
function setManagedRepos(entries) {
|
|
18
|
+
const next = new Map;
|
|
19
|
+
for (const e of entries) {
|
|
20
|
+
if (next.has(e.id)) {
|
|
21
|
+
throw new Error(`managed repo already registered: ${e.id}`);
|
|
22
|
+
}
|
|
23
|
+
next.set(e.id, e);
|
|
24
|
+
}
|
|
25
|
+
MANAGED_REPOS = next;
|
|
26
|
+
}
|
|
27
|
+
function clearManagedRepos() {
|
|
28
|
+
MANAGED_REPOS = new Map;
|
|
29
|
+
}
|
|
30
|
+
function getManagedRepoEntry(repoId) {
|
|
31
|
+
const entry = MANAGED_REPOS.get(repoId);
|
|
32
|
+
if (!entry) {
|
|
33
|
+
throw new Error(`managed repo not registered: ${repoId}. Plugins contribute repos via RigPlugin.contributes.repoSources; ` + `make sure a plugin declares this id and the plugin host has been initialized.`);
|
|
34
|
+
}
|
|
35
|
+
return entry;
|
|
36
|
+
}
|
|
37
|
+
function tryGetManagedRepoEntry(repoId) {
|
|
38
|
+
return MANAGED_REPOS.get(repoId);
|
|
39
|
+
}
|
|
40
|
+
function listManagedRepoEntries() {
|
|
41
|
+
return Array.from(MANAGED_REPOS.values());
|
|
42
|
+
}
|
|
43
|
+
function resolveManagedRepoIdByAlias(alias) {
|
|
44
|
+
for (const entry of MANAGED_REPOS.values()) {
|
|
45
|
+
if (entry.alias === alias) {
|
|
46
|
+
return entry.id;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function isManagedRepoAlias(alias) {
|
|
52
|
+
return resolveManagedRepoIdByAlias(alias) !== null;
|
|
53
|
+
}
|
|
54
|
+
function repoRegistrationToManagedEntry(reg) {
|
|
55
|
+
if (!reg.defaultBranch) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
id: reg.id,
|
|
60
|
+
alias: reg.defaultPath ?? reg.id,
|
|
61
|
+
defaultBranch: reg.defaultBranch,
|
|
62
|
+
defaultRemoteUrl: reg.url,
|
|
63
|
+
remoteEnvVar: reg.remoteEnvVar,
|
|
64
|
+
checkoutEnvVar: reg.checkoutEnvVar
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
tryGetManagedRepoEntry,
|
|
69
|
+
setManagedRepos,
|
|
70
|
+
resolveManagedRepoIdByAlias,
|
|
71
|
+
repoRegistrationToManagedEntry,
|
|
72
|
+
listManagedRepoEntries,
|
|
73
|
+
isManagedRepoAlias,
|
|
74
|
+
getManagedRepoEntry,
|
|
75
|
+
createRepoRegistry,
|
|
76
|
+
clearManagedRepos
|
|
77
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The concrete `ManagedRepoService` the runtime port resolves and consumes.
|
|
3
|
+
*
|
|
4
|
+
* The managed-repo set is a module-level singleton inside `./registry` — the
|
|
5
|
+
* service object below is a thin facade over the registry / layout / mirror
|
|
6
|
+
* functions. Because the singleton lives in module scope, every resolution of
|
|
7
|
+
* this service shares the same state, matching the pre-extraction behaviour
|
|
8
|
+
* where these functions operated on a single runtime-global map.
|
|
9
|
+
*/
|
|
10
|
+
import type { ManagedRepoService } from "@rig/runtime/control-plane/managed-repo-service-port";
|
|
11
|
+
export declare const managedRepoService: ManagedRepoService;
|
|
12
|
+
/** Lazy-import handle for the config-light capability `run()` in plugin.ts. */
|
|
13
|
+
export declare const svc: ManagedRepoService;
|