@ghl-ai/aw 0.1.36-beta.91 → 0.1.36-beta.93
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/git.mjs +51 -77
- package/package.json +1 -1
package/git.mjs
CHANGED
|
@@ -230,79 +230,56 @@ export function removeFromSparseCheckout(awHome, removePaths) {
|
|
|
230
230
|
* @param {{ silent?: boolean }} opts
|
|
231
231
|
*/
|
|
232
232
|
export async function fetchAndMerge(awHome, { silent = true } = {}) {
|
|
233
|
-
// ── 1. Branch
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
-
//
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
} catch {
|
|
267
|
-
// Completely broken sparse config — force a safe default
|
|
268
|
-
try {
|
|
269
|
-
await exec(`git -C "${awHome}" sparse-checkout init --no-cone`);
|
|
270
|
-
await exec(
|
|
271
|
-
`git -C "${awHome}" sparse-checkout set "${REGISTRY_DIR}/"`,
|
|
272
|
-
);
|
|
273
|
-
} catch { /* best effort */ }
|
|
233
|
+
// ── 1. Branch classification ──────────────────────────────────────────────
|
|
234
|
+
// There are three possible states for ~/.aw:
|
|
235
|
+
//
|
|
236
|
+
// A. REGISTRY_BASE_BRANCH — normal, fast-forward sync
|
|
237
|
+
// B. Push branch (upload/ sync/ remove/) — intentional, rebase remote
|
|
238
|
+
// changes under our local commits (stacked PR model)
|
|
239
|
+
// C. Anything else (e.g. `main` from a failed initPersistentClone) —
|
|
240
|
+
// drift/broken state; re-enable sparse checkout and switch back to
|
|
241
|
+
// REGISTRY_BASE_BRANCH before syncing. We must NOT rebase here:
|
|
242
|
+
// `main` and REGISTRY_BASE_BRANCH are unrelated trees in platform-docs
|
|
243
|
+
// and rebasing between them on a blob:none clone wipes the working tree.
|
|
244
|
+
|
|
245
|
+
const PUSH_PREFIXES = ['upload/', 'remove/', 'sync/'];
|
|
246
|
+
|
|
247
|
+
let currentBranch = REGISTRY_BASE_BRANCH; // assume good unless detection succeeds
|
|
248
|
+
try {
|
|
249
|
+
const { stdout } = await exec(`git -C "${awHome}" rev-parse --abbrev-ref HEAD`);
|
|
250
|
+
currentBranch = stdout.trim();
|
|
251
|
+
} catch { /* proceed with assumption */ }
|
|
252
|
+
|
|
253
|
+
const isPushBranch = PUSH_PREFIXES.some(p => currentBranch.startsWith(p));
|
|
254
|
+
const isBaseBranch = currentBranch === REGISTRY_BASE_BRANCH;
|
|
255
|
+
const isDrift = !isBaseBranch && !isPushBranch && currentBranch !== 'HEAD';
|
|
256
|
+
|
|
257
|
+
if (isDrift) {
|
|
258
|
+
// Re-enable sparse checkout (may have been disabled by an old --no-edit merge)
|
|
259
|
+
try {
|
|
260
|
+
await exec(`git -C "${awHome}" sparse-checkout init --no-cone`);
|
|
261
|
+
const { stdout: listOut } = await exec(`git -C "${awHome}" sparse-checkout list`);
|
|
262
|
+
if (!listOut.trim()) {
|
|
263
|
+
await exec(`git -C "${awHome}" sparse-checkout set "${REGISTRY_DIR}/"`);
|
|
274
264
|
}
|
|
275
|
-
|
|
276
|
-
// Switch to the correct branch; this materialises files via lazy fetch.
|
|
265
|
+
} catch {
|
|
277
266
|
try {
|
|
278
|
-
await exec(`git -C "${awHome}" checkout
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
// Return without touching anything; the user can run `aw init` to
|
|
282
|
-
// trigger a full re-clone via initPersistentClone.
|
|
283
|
-
return { updated: false, conflicts: [] };
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Branch repaired. Do NOT continue to fetch/rebase on this same run —
|
|
287
|
-
// that combination is what caused the original wipe.
|
|
288
|
-
return { updated: false, conflicts: [] };
|
|
267
|
+
await exec(`git -C "${awHome}" sparse-checkout init --no-cone`);
|
|
268
|
+
await exec(`git -C "${awHome}" sparse-checkout set "${REGISTRY_DIR}/"`);
|
|
269
|
+
} catch { /* best effort */ }
|
|
289
270
|
}
|
|
290
|
-
} catch { /* branch detection failed — proceed with normal sync */ }
|
|
291
271
|
|
|
292
|
-
|
|
293
|
-
// Guard: if something disabled sparse checkout while on the right branch
|
|
294
|
-
// (should be rare), re-enable before fetch so the working tree stays intact.
|
|
295
|
-
try {
|
|
296
|
-
await exec(`git -C "${awHome}" sparse-checkout list`);
|
|
297
|
-
} catch {
|
|
272
|
+
// Switch to the correct branch — materialises files via lazy blob fetch
|
|
298
273
|
try {
|
|
299
|
-
await exec(`git -C "${awHome}" sparse-checkout init --no-cone`);
|
|
300
|
-
// Re-checkout to materialise files according to restored sparse config
|
|
301
274
|
await exec(`git -C "${awHome}" checkout ${REGISTRY_BASE_BRANCH}`);
|
|
302
|
-
} catch {
|
|
275
|
+
} catch {
|
|
276
|
+
return { updated: false, conflicts: [] }; // can't repair; leave for full re-init
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Drift repaired. Continue below to also fetch + fast-forward this run.
|
|
303
280
|
}
|
|
304
281
|
|
|
305
|
-
// ──
|
|
282
|
+
// ── 2. Fetch ──────────────────────────────────────────────────────────────
|
|
306
283
|
try {
|
|
307
284
|
await exec(`git -C "${awHome}" fetch origin ${REGISTRY_BASE_BRANCH}`);
|
|
308
285
|
} catch (e) {
|
|
@@ -312,36 +289,33 @@ export async function fetchAndMerge(awHome, { silent = true } = {}) {
|
|
|
312
289
|
let updated = false;
|
|
313
290
|
const conflicts = [];
|
|
314
291
|
|
|
315
|
-
// ──
|
|
292
|
+
// ── 3. Fast-forward (no local commits ahead of remote) ───────────────────
|
|
316
293
|
try {
|
|
317
294
|
const { stdout } = await exec(
|
|
318
295
|
`git -C "${awHome}" merge origin/${REGISTRY_BASE_BRANCH} --ff-only`,
|
|
319
296
|
);
|
|
320
297
|
updated = !stdout.includes('Already up to date');
|
|
321
298
|
return { updated, conflicts };
|
|
322
|
-
} catch { /*
|
|
299
|
+
} catch { /* local commits exist — fall through to rebase */ }
|
|
323
300
|
|
|
324
|
-
// ──
|
|
325
|
-
//
|
|
301
|
+
// ── 4. Rebase current branch onto remote REGISTRY_BASE_BRANCH ────────────
|
|
302
|
+
// For push branches: stacks our local commits on top of latest remote.
|
|
303
|
+
// For base branch: only reached if local commits exist (unusual).
|
|
304
|
+
// Never uses --no-edit merge — that disables sparse checkout on blob:none.
|
|
326
305
|
try {
|
|
327
306
|
await exec(`git -C "${awHome}" rebase origin/${REGISTRY_BASE_BRANCH}`);
|
|
328
307
|
updated = true;
|
|
329
308
|
} catch {
|
|
330
|
-
// Rebase has conflicts — collect them
|
|
331
309
|
try {
|
|
332
|
-
const { stdout } = await exec(
|
|
333
|
-
`git -C "${awHome}" diff --name-only --diff-filter=U`,
|
|
334
|
-
);
|
|
310
|
+
const { stdout } = await exec(`git -C "${awHome}" diff --name-only --diff-filter=U`);
|
|
335
311
|
conflicts.push(...stdout.trim().split('\n').filter(Boolean));
|
|
336
312
|
} catch { /* best effort */ }
|
|
337
313
|
|
|
338
314
|
if (silent) {
|
|
339
|
-
//
|
|
340
|
-
// usable state. The next explicit `aw init` will surface the conflict.
|
|
315
|
+
// Background: abort so repo stays usable; surface on next explicit aw init
|
|
341
316
|
try { await exec(`git -C "${awHome}" rebase --abort`); } catch { /* best effort */ }
|
|
342
317
|
}
|
|
343
|
-
//
|
|
344
|
-
// resolve them directly in their editor.
|
|
318
|
+
// Interactive: leave conflict markers for the user to resolve
|
|
345
319
|
}
|
|
346
320
|
|
|
347
321
|
return { updated, conflicts };
|