@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.
- package/dist/esm/cli/agent.js +66 -11
- package/dist/esm/cli/agent.js.map +1 -1
- package/dist/esm/cli/commands/auth.js +265 -0
- package/dist/esm/cli/commands/auth.js.map +1 -0
- package/dist/esm/cli/commands/migrate.js +151 -6
- package/dist/esm/cli/commands/migrate.js.map +1 -1
- package/dist/esm/cli/main.js +72 -2
- package/dist/esm/cli/main.js.map +1 -1
- package/dist/esm/git-remote/credential-main.js +34 -8
- package/dist/esm/git-remote/credential-main.js.map +1 -1
- package/dist/esm/profiles/config.js +156 -0
- package/dist/esm/profiles/config.js.map +1 -0
- package/dist/types/cli/agent.d.ts +27 -4
- package/dist/types/cli/agent.d.ts.map +1 -1
- package/dist/types/cli/commands/auth.d.ts +23 -0
- package/dist/types/cli/commands/auth.d.ts.map +1 -0
- package/dist/types/cli/commands/migrate.d.ts.map +1 -1
- package/dist/types/git-remote/credential-main.d.ts +2 -1
- package/dist/types/git-remote/credential-main.d.ts.map +1 -1
- package/dist/types/profiles/config.d.ts +69 -0
- package/dist/types/profiles/config.d.ts.map +1 -0
- package/package.json +2 -1
- package/src/cli/agent.ts +95 -11
- package/src/cli/commands/auth.ts +290 -0
- package/src/cli/commands/migrate.ts +166 -6
- package/src/cli/main.ts +78 -2
- package/src/git-remote/credential-main.ts +41 -8
- package/src/profiles/config.ts +188 -0
package/dist/esm/cli/agent.js
CHANGED
|
@@ -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
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
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(
|
|
47
|
+
export function connectAgent(options) {
|
|
43
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
-
const {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
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":"AAAA
|
|
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 {
|
|
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:
|
|
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>
|
|
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:
|
|
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
|
|
304
|
+
// Step 4: pull requests + reviews.
|
|
275
305
|
const pullCount = yield migratePullsInner(ctx, owner, repo);
|
|
276
|
-
// Step
|
|
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) {
|