@enbox/gitd 0.1.0 → 0.3.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.
@@ -6,6 +6,9 @@
6
6
  * the existing vault and return a ready-to-use `TypedWeb5` instance for
7
7
  * each protocol.
8
8
  *
9
+ * Agent data is stored under the resolved profile path:
10
+ * `~/.enbox/profiles/<profile>/DATA/AGENT/`
11
+ *
9
12
  * @module
10
13
  */
11
14
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
@@ -18,6 +21,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
18
21
  });
19
22
  };
20
23
  import { Web5 } from '@enbox/api';
24
+ import { Web5UserAgent } from '@enbox/agent';
21
25
  import { ForgeCiProtocol } from '../ci.js';
22
26
  import { ForgeIssuesProtocol } from '../issues.js';
23
27
  import { ForgeNotificationsProtocol } from '../notifications.js';
@@ -35,23 +39,73 @@ import { ForgeWikiProtocol } from '../wiki.js';
35
39
  /**
36
40
  * Connect to the local Web5 agent, initializing on first launch.
37
41
  *
38
- * The agent's persistent data lives under `dataPath` (default:
39
- * `~/.gitd/agent`). Sync is disabled the CLI operates against
40
- * the local DWN only.
42
+ * When `dataPath` is provided, the agent's persistent data lives there.
43
+ * Otherwise, it falls back to `DATA/AGENT` relative to CWD (legacy).
44
+ *
45
+ * Sync is disabled — the CLI operates against the local DWN only.
41
46
  */
42
- export function connectAgent(password) {
47
+ export function connectAgent(options) {
43
48
  return __awaiter(this, void 0, void 0, function* () {
44
- const { web5, did, recoveryPhrase } = yield Web5.connect({
45
- password,
46
- sync: 'off',
47
- });
48
- if (recoveryPhrase) {
49
+ const { password, dataPath, recoveryPhrase: inputPhrase } = options;
50
+ let agent;
51
+ let recoveryPhrase;
52
+ if (dataPath) {
53
+ // Profile-based: create agent with explicit data path.
54
+ agent = yield Web5UserAgent.create({ dataPath });
55
+ if (yield agent.firstLaunch()) {
56
+ recoveryPhrase = yield agent.initialize({
57
+ password,
58
+ recoveryPhrase: inputPhrase,
59
+ dwnEndpoints: ['https://enbox-dwn.fly.dev'],
60
+ });
61
+ }
62
+ yield agent.start({ password });
63
+ // Ensure at least one identity exists.
64
+ const identities = yield agent.identity.list();
65
+ let identity = identities[0];
66
+ if (!identity) {
67
+ identity = yield agent.identity.create({
68
+ didMethod: 'dht',
69
+ metadata: { name: 'Default' },
70
+ didOptions: {
71
+ services: [{
72
+ id: 'dwn',
73
+ type: 'DecentralizedWebNode',
74
+ serviceEndpoint: ['https://enbox-dwn.fly.dev'],
75
+ enc: '#enc',
76
+ sig: '#sig',
77
+ }],
78
+ verificationMethods: [
79
+ { algorithm: 'Ed25519', id: 'sig', purposes: ['assertionMethod', 'authentication'] },
80
+ { algorithm: 'X25519', id: 'enc', purposes: ['keyAgreement'] },
81
+ ],
82
+ },
83
+ });
84
+ }
85
+ const result = yield Web5.connect({
86
+ agent,
87
+ connectedDid: identity.did.uri,
88
+ sync: 'off',
89
+ });
90
+ return bindProtocols(result.web5, result.did, recoveryPhrase);
91
+ }
92
+ // Legacy: let Web5.connect() manage the agent (uses CWD-relative path).
93
+ const result = yield Web5.connect({ password, sync: 'off' });
94
+ if (result.recoveryPhrase) {
49
95
  console.log('');
50
96
  console.log(' Recovery phrase (save this — it cannot be shown again):');
51
- console.log(` ${recoveryPhrase}`);
97
+ console.log(` ${result.recoveryPhrase}`);
52
98
  console.log('');
53
99
  }
54
- // Bind typed protocol handles.
100
+ return bindProtocols(result.web5, result.did, result.recoveryPhrase);
101
+ });
102
+ }
103
+ // ---------------------------------------------------------------------------
104
+ // Internal helpers
105
+ // ---------------------------------------------------------------------------
106
+ /** Bind typed protocol handles and configure all protocols. */
107
+ function bindProtocols(web5, did, recoveryPhrase) {
108
+ return __awaiter(this, void 0, void 0, function* () {
55
109
  const repo = web5.using(ForgeRepoProtocol);
56
110
  const refs = web5.using(ForgeRefsProtocol);
57
111
  const issues = web5.using(ForgeIssuesProtocol);
@@ -80,6 +134,7 @@ export function connectAgent(password) {
80
134
  return {
81
135
  did, repo, refs, issues, patches, ci, releases,
82
136
  registry, social, notifications, wiki, org, web5,
137
+ recoveryPhrase,
83
138
  };
84
139
  });
85
140
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/cli/agent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/cli/agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * `gitd auth` — identity and profile management.
3
+ *
4
+ * Usage:
5
+ * gitd auth Show current identity info
6
+ * gitd auth login Create or import an identity
7
+ * gitd auth list List all profiles
8
+ * gitd auth use <profile> Set profile for current repo
9
+ * gitd auth use <profile> --global Set default profile
10
+ * gitd auth export [profile] Export portable identity
11
+ * gitd auth import Import from recovery phrase
12
+ * gitd auth logout [profile] Remove a profile
13
+ *
14
+ * @module
15
+ */
16
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
17
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
18
+ return new (P || (P = Promise))(function (resolve, reject) {
19
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
20
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
21
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
22
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
23
+ });
24
+ };
25
+ import * as p from '@clack/prompts';
26
+ import { connectAgent } from '../agent.js';
27
+ import { enboxHome, listProfiles, profileDataPath, readConfig, resolveProfile, setGitConfigProfile, upsertProfile, writeConfig, } from '../../profiles/config.js';
28
+ // ---------------------------------------------------------------------------
29
+ // Sub-command dispatch
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * The auth command can run without a pre-existing AgentContext (for `login`,
33
+ * `list`), but some sub-commands need one (for `export`). We accept
34
+ * ctx as optional and connect lazily when needed.
35
+ */
36
+ export function authCommand(ctx, args) {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ const sub = args[0];
39
+ switch (sub) {
40
+ case 'login': return authLogin();
41
+ case 'list': return authList();
42
+ case 'use': return authUse(args.slice(1));
43
+ case 'logout': return authLogout(args.slice(1));
44
+ default: return authInfo(ctx);
45
+ }
46
+ });
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // auth (no subcommand) — show current identity
50
+ // ---------------------------------------------------------------------------
51
+ function authInfo(ctx) {
52
+ return __awaiter(this, void 0, void 0, function* () {
53
+ const config = readConfig();
54
+ const profileName = resolveProfile();
55
+ if (!profileName || !config.profiles[profileName]) {
56
+ p.log.warn('No identity configured. Run `gitd auth login` to get started.');
57
+ return;
58
+ }
59
+ const entry = config.profiles[profileName];
60
+ p.log.info(`Profile: ${profileName}${config.defaultProfile === profileName ? ' (default)' : ''}`);
61
+ p.log.info(`DID: ${entry.did}`);
62
+ p.log.info(`Created: ${entry.createdAt}`);
63
+ p.log.info(`Data: ${profileDataPath(profileName)}`);
64
+ if (ctx) {
65
+ p.log.info(`Connected: ${ctx.did}`);
66
+ }
67
+ });
68
+ }
69
+ // ---------------------------------------------------------------------------
70
+ // auth login — create or import identity
71
+ // ---------------------------------------------------------------------------
72
+ function authLogin() {
73
+ return __awaiter(this, void 0, void 0, function* () {
74
+ p.intro('Identity setup');
75
+ const action = yield p.select({
76
+ message: 'What would you like to do?',
77
+ options: [
78
+ { value: 'create', label: 'Create a new identity' },
79
+ { value: 'import', label: 'Import from recovery phrase' },
80
+ ],
81
+ });
82
+ if (p.isCancel(action)) {
83
+ p.cancel('Cancelled.');
84
+ return;
85
+ }
86
+ const name = yield p.text({
87
+ message: 'Name this profile:',
88
+ placeholder: 'personal',
89
+ validate(val) {
90
+ if (!(val === null || val === void 0 ? void 0 : val.trim())) {
91
+ return 'Profile name is required.';
92
+ }
93
+ if (!/^[a-zA-Z0-9_-]+$/.test(val)) {
94
+ return 'Only letters, numbers, hyphens, and underscores.';
95
+ }
96
+ const existing = listProfiles();
97
+ if (existing.includes(val)) {
98
+ return `Profile "${val}" already exists.`;
99
+ }
100
+ },
101
+ });
102
+ if (p.isCancel(name)) {
103
+ p.cancel('Cancelled.');
104
+ return;
105
+ }
106
+ const profileName = name.trim();
107
+ const password = yield p.password({
108
+ message: 'Choose a password for your vault:',
109
+ validate(val) {
110
+ if (!val || val.length < 4) {
111
+ return 'Password must be at least 4 characters.';
112
+ }
113
+ },
114
+ });
115
+ if (p.isCancel(password)) {
116
+ p.cancel('Cancelled.');
117
+ return;
118
+ }
119
+ let recoveryInput;
120
+ if (action === 'import') {
121
+ const phrase = yield p.text({
122
+ message: 'Enter your 12-word recovery phrase:',
123
+ placeholder: 'abandon ability able about above absent ...',
124
+ validate(val) {
125
+ if (!val) {
126
+ return 'Recovery phrase is required.';
127
+ }
128
+ const words = val.trim().split(/\s+/);
129
+ if (words.length !== 12) {
130
+ return 'Recovery phrase must be exactly 12 words.';
131
+ }
132
+ },
133
+ });
134
+ if (p.isCancel(phrase)) {
135
+ p.cancel('Cancelled.');
136
+ return;
137
+ }
138
+ recoveryInput = phrase.trim();
139
+ }
140
+ const spin = p.spinner();
141
+ spin.start('Creating identity...');
142
+ try {
143
+ const dataPath = profileDataPath(profileName);
144
+ const result = yield connectAgent({
145
+ password: password,
146
+ dataPath,
147
+ recoveryPhrase: recoveryInput,
148
+ });
149
+ // Save profile metadata.
150
+ upsertProfile(profileName, {
151
+ name: profileName,
152
+ did: result.did,
153
+ createdAt: new Date().toISOString(),
154
+ });
155
+ spin.stop('Identity created!');
156
+ p.log.success(`DID: ${result.did}`);
157
+ p.log.success(`Profile: ${profileName} (${dataPath})`);
158
+ if (result.recoveryPhrase) {
159
+ p.log.warn('');
160
+ p.log.warn('Your recovery phrase (write this down!):');
161
+ p.log.warn(` ${result.recoveryPhrase}`);
162
+ p.log.warn('');
163
+ p.log.warn('This phrase can recover your identity if you lose your password.');
164
+ p.log.warn('Store it securely — it will NOT be shown again.');
165
+ }
166
+ }
167
+ catch (err) {
168
+ spin.stop('Failed.');
169
+ p.log.error(`Failed to create identity: ${err.message}`);
170
+ process.exit(1);
171
+ }
172
+ p.outro('You\'re all set! Run `gitd whoami` to verify.');
173
+ });
174
+ }
175
+ // ---------------------------------------------------------------------------
176
+ // auth list — list all profiles
177
+ // ---------------------------------------------------------------------------
178
+ function authList() {
179
+ const config = readConfig();
180
+ const names = Object.keys(config.profiles);
181
+ if (names.length === 0) {
182
+ p.log.warn('No profiles found. Run `gitd auth login` to create one.');
183
+ return;
184
+ }
185
+ p.log.info(`Profiles (${enboxHome()}):\n`);
186
+ for (const name of names) {
187
+ const entry = config.profiles[name];
188
+ const isDefault = config.defaultProfile === name ? ' (default)' : '';
189
+ p.log.info(` ${name}${isDefault}`);
190
+ p.log.info(` DID: ${entry.did}`);
191
+ p.log.info(` Created: ${entry.createdAt}`);
192
+ }
193
+ }
194
+ // ---------------------------------------------------------------------------
195
+ // auth use — set active profile
196
+ // ---------------------------------------------------------------------------
197
+ function authUse(args) {
198
+ return __awaiter(this, void 0, void 0, function* () {
199
+ const name = args[0];
200
+ const isGlobal = args.includes('--global');
201
+ if (!name) {
202
+ p.log.error('Usage: gitd auth use <profile> [--global]');
203
+ process.exit(1);
204
+ }
205
+ const config = readConfig();
206
+ if (!config.profiles[name]) {
207
+ p.log.error(`Profile "${name}" not found. Run \`gitd auth list\` to see available profiles.`);
208
+ process.exit(1);
209
+ }
210
+ if (isGlobal) {
211
+ config.defaultProfile = name;
212
+ writeConfig(config);
213
+ p.log.success(`Default profile set to "${name}".`);
214
+ }
215
+ else {
216
+ try {
217
+ setGitConfigProfile(name);
218
+ p.log.success(`Profile "${name}" set for this repository.`);
219
+ }
220
+ catch (_a) {
221
+ p.log.error('Not in a git repository. Use --global to set the default profile.');
222
+ process.exit(1);
223
+ }
224
+ }
225
+ });
226
+ }
227
+ // ---------------------------------------------------------------------------
228
+ // auth logout — remove a profile
229
+ // ---------------------------------------------------------------------------
230
+ function authLogout(args) {
231
+ return __awaiter(this, void 0, void 0, function* () {
232
+ var _a, _b;
233
+ let name = args[0];
234
+ if (!name) {
235
+ name = (_a = resolveProfile()) !== null && _a !== void 0 ? _a : '';
236
+ }
237
+ if (!name) {
238
+ p.log.error('No profile specified and no default profile found.');
239
+ process.exit(1);
240
+ }
241
+ const config = readConfig();
242
+ if (!config.profiles[name]) {
243
+ p.log.error(`Profile "${name}" not found.`);
244
+ process.exit(1);
245
+ }
246
+ const confirm = yield p.confirm({
247
+ message: `Remove profile "${name}"? This will delete all local data for this identity.`,
248
+ });
249
+ if (p.isCancel(confirm) || !confirm) {
250
+ p.cancel('Cancelled.');
251
+ return;
252
+ }
253
+ // Remove from config (we don't delete the data directory — user can do that).
254
+ delete config.profiles[name];
255
+ if (config.defaultProfile === name) {
256
+ const remaining = Object.keys(config.profiles);
257
+ config.defaultProfile = (_b = remaining[0]) !== null && _b !== void 0 ? _b : '';
258
+ }
259
+ writeConfig(config);
260
+ p.log.success(`Profile "${name}" removed.`);
261
+ p.log.info(`Data directory preserved at: ${profileDataPath(name)}`);
262
+ p.log.info('Delete it manually if you want to free disk space.');
263
+ });
264
+ }
265
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../../src/cli/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -29,8 +29,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
29
29
  step((generator = generator.apply(thisArg, _arguments || [])).next());
30
30
  });
31
31
  };
32
+ import { createFullBundle } from '../../git-server/bundle-sync.js';
33
+ import { flagValue } from '../flags.js';
34
+ import { getRepoContext } from '../repo-context.js';
32
35
  import { getRepoContextId } from '../repo-context.js';
33
- import { spawnSync } from 'node:child_process';
36
+ import { GitBackend } from '../../git-server/git-backend.js';
37
+ import { readGitRefs } from '../../git-server/ref-sync.js';
38
+ import { readFile, unlink } from 'node:fs/promises';
39
+ import { spawn, spawnSync } from 'node:child_process';
34
40
  // ---------------------------------------------------------------------------
35
41
  // GitHub auth — resolve a token from env or the gh CLI
36
42
  // ---------------------------------------------------------------------------
@@ -65,7 +71,7 @@ export function resolveGitHubToken() {
65
71
  try {
66
72
  const result = spawnSync('gh', ['auth', 'token'], {
67
73
  stdio: ['pipe', 'pipe', 'pipe'],
68
- timeout: 5000,
74
+ timeout: 2000,
69
75
  });
70
76
  const token = (_a = result.stdout) === null || _a === void 0 ? void 0 : _a.toString().trim();
71
77
  if (result.status === 0 && token) {
@@ -163,7 +169,7 @@ export function migrateCommand(ctx, args) {
163
169
  case 'pulls': return migratePulls(ctx, rest);
164
170
  case 'releases': return migrateReleases(ctx, rest);
165
171
  default:
166
- console.error('Usage: gitd migrate <all|repo|issues|pulls|releases> <owner/repo>');
172
+ console.error('Usage: gitd migrate <all|repo|issues|pulls|releases> [owner/repo] [--repos <path>]');
167
173
  process.exit(1);
168
174
  }
169
175
  });
@@ -256,9 +262,19 @@ function prependAuthor(body, ghLogin) {
256
262
  // ---------------------------------------------------------------------------
257
263
  // migrate all
258
264
  // ---------------------------------------------------------------------------
265
+ /**
266
+ * Resolve the repos base path from CLI flags or environment.
267
+ * Returns `null` when no explicit path was provided, so callers can
268
+ * decide whether to skip git content migration.
269
+ */
270
+ function resolveReposPath(args) {
271
+ var _a, _b;
272
+ return (_b = (_a = flagValue(args, '--repos')) !== null && _a !== void 0 ? _a : process.env.GITD_REPOS) !== null && _b !== void 0 ? _b : null;
273
+ }
259
274
  function migrateAll(ctx, args) {
260
275
  return __awaiter(this, void 0, void 0, function* () {
261
276
  const { owner, repo } = resolveGhRepo(args);
277
+ const reposPath = resolveReposPath(args);
262
278
  const slug = `${owner}/${repo}`;
263
279
  const token = resolveGitHubToken();
264
280
  if (!token) {
@@ -269,11 +285,25 @@ function migrateAll(ctx, args) {
269
285
  try {
270
286
  // Step 1: repo metadata.
271
287
  yield migrateRepoInner(ctx, owner, repo);
272
- // Step 2: issues + comments.
288
+ // Step 2: git content (clone, bundle, refs).
289
+ if (reposPath) {
290
+ try {
291
+ yield migrateGitContent(ctx, owner, repo, reposPath);
292
+ }
293
+ catch (err) {
294
+ console.error(` Warning: git content migration failed: ${err.message}`);
295
+ console.error(' Metadata, issues, PRs, and releases will still be imported.');
296
+ console.error(' Re-run with a valid --repos path to retry git content migration.\n');
297
+ }
298
+ }
299
+ else {
300
+ console.log(' Skipping git content — pass --repos <path> or set GITD_REPOS to include git data.');
301
+ }
302
+ // Step 3: issues + comments.
273
303
  const issueCount = yield migrateIssuesInner(ctx, owner, repo);
274
- // Step 3: pull requests + reviews.
304
+ // Step 4: pull requests + reviews.
275
305
  const pullCount = yield migratePullsInner(ctx, owner, repo);
276
- // Step 4: releases.
306
+ // Step 5: releases.
277
307
  const releaseCount = yield migrateReleasesInner(ctx, owner, repo);
278
308
  console.log(`\nMigration complete: ${slug}`);
279
309
  console.log(` Issues: ${issueCount}`);
@@ -292,8 +322,15 @@ function migrateAll(ctx, args) {
292
322
  function migrateRepo(ctx, args) {
293
323
  return __awaiter(this, void 0, void 0, function* () {
294
324
  const { owner, repo } = resolveGhRepo(args);
325
+ const reposPath = resolveReposPath(args);
295
326
  try {
296
327
  yield migrateRepoInner(ctx, owner, repo);
328
+ if (reposPath) {
329
+ yield migrateGitContent(ctx, owner, repo, reposPath);
330
+ }
331
+ else {
332
+ console.log(' Skipping git content — pass --repos <path> or set GITD_REPOS to include git data.');
333
+ }
297
334
  }
298
335
  catch (err) {
299
336
  console.error(`Failed to migrate repo: ${err.message}`);
@@ -336,6 +373,114 @@ function migrateRepoInner(ctx, owner, repo) {
336
373
  });
337
374
  }
338
375
  // ---------------------------------------------------------------------------
376
+ // migrate git content (clone + bundle + refs)
377
+ // ---------------------------------------------------------------------------
378
+ /**
379
+ * Clone the GitHub repository as a bare repo, create a full git bundle,
380
+ * upload it to DWN, and sync all refs to DWN records.
381
+ *
382
+ * This is the "git content" migration step that turns the metadata-only
383
+ * repo record into a fully cloneable repo.
384
+ */
385
+ function migrateGitContent(ctx, owner, repo, reposPath) {
386
+ return __awaiter(this, void 0, void 0, function* () {
387
+ const slug = `${owner}/${repo}`;
388
+ console.log(`Importing git content from ${slug}...`);
389
+ const backend = new GitBackend({ basePath: reposPath });
390
+ const repoPath = backend.repoPath(ctx.did, repo);
391
+ // Step 1: Clone bare repo from GitHub (or skip if already on disk).
392
+ if (backend.exists(ctx.did, repo)) {
393
+ console.log(` Bare repo already exists at ${repoPath} — skipping clone.`);
394
+ }
395
+ else {
396
+ const cloneUrl = buildCloneUrl(owner, repo);
397
+ console.log(` Cloning ${cloneUrl} → ${repoPath}`);
398
+ yield cloneBare(cloneUrl, repoPath);
399
+ console.log(' Clone complete.');
400
+ }
401
+ // Step 2: Create full git bundle.
402
+ console.log(' Creating git bundle...');
403
+ const bundleInfo = yield createFullBundle(repoPath);
404
+ console.log(` Bundle: ${bundleInfo.size} bytes, ${bundleInfo.refCount} ref(s), tip: ${bundleInfo.tipCommit.slice(0, 8)}`);
405
+ // Step 3: Upload bundle to DWN.
406
+ const { contextId: repoContextId, visibility } = yield getRepoContext(ctx);
407
+ const encrypt = visibility === 'private';
408
+ try {
409
+ const bundleData = new Uint8Array(yield readFile(bundleInfo.path));
410
+ const { status } = yield ctx.repo.records.create('repo/bundle', {
411
+ data: bundleData,
412
+ dataFormat: 'application/x-git-bundle',
413
+ tags: {
414
+ tipCommit: bundleInfo.tipCommit,
415
+ isFull: true,
416
+ refCount: bundleInfo.refCount,
417
+ size: bundleInfo.size,
418
+ },
419
+ parentContextId: repoContextId,
420
+ encryption: encrypt,
421
+ });
422
+ if (status.code >= 300) {
423
+ throw new Error(`Failed to create bundle record: ${status.code} ${status.detail}`);
424
+ }
425
+ console.log(' Bundle uploaded to DWN.');
426
+ }
427
+ finally {
428
+ yield unlink(bundleInfo.path).catch(() => { });
429
+ }
430
+ // Step 4: Sync git refs to DWN.
431
+ console.log(' Syncing refs to DWN...');
432
+ const gitRefs = yield readGitRefs(repoPath);
433
+ let refCount = 0;
434
+ for (const ref of gitRefs) {
435
+ const { status } = yield ctx.refs.records.create('repo/ref', {
436
+ data: { name: ref.name, target: ref.target, type: ref.type },
437
+ tags: { name: ref.name, type: ref.type, target: ref.target },
438
+ parentContextId: repoContextId,
439
+ });
440
+ if (status.code >= 300) {
441
+ console.error(` Failed to sync ref ${ref.name}: ${status.code} ${status.detail}`);
442
+ continue;
443
+ }
444
+ refCount++;
445
+ }
446
+ console.log(` Synced ${refCount} ref(s) to DWN.`);
447
+ console.log(` Git content migration complete.`);
448
+ });
449
+ }
450
+ /**
451
+ * Build the clone URL for a GitHub repository.
452
+ * Uses the token (if available) for authenticated HTTPS clone.
453
+ */
454
+ function buildCloneUrl(owner, repo) {
455
+ const token = resolveGitHubToken();
456
+ if (token) {
457
+ return `https://${token}@github.com/${owner}/${repo}.git`;
458
+ }
459
+ return `https://github.com/${owner}/${repo}.git`;
460
+ }
461
+ /**
462
+ * Clone a git repository as a bare repo using `git clone --bare`.
463
+ */
464
+ function cloneBare(url, destPath) {
465
+ return new Promise((resolve, reject) => {
466
+ const child = spawn('git', ['clone', '--bare', url, destPath], {
467
+ stdio: ['pipe', 'pipe', 'pipe'],
468
+ });
469
+ const stderrChunks = [];
470
+ child.stderr.on('data', (chunk) => stderrChunks.push(chunk));
471
+ child.on('error', reject);
472
+ child.on('exit', (code) => {
473
+ if (code !== 0) {
474
+ const stderr = Buffer.concat(stderrChunks).toString('utf-8');
475
+ reject(new Error(`git clone --bare failed (exit ${code}): ${stderr}`));
476
+ }
477
+ else {
478
+ resolve();
479
+ }
480
+ });
481
+ });
482
+ }
483
+ // ---------------------------------------------------------------------------
339
484
  // migrate issues
340
485
  // ---------------------------------------------------------------------------
341
486
  function migrateIssues(ctx, args) {