amalgm 0.1.180 → 0.1.181
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/package.json
CHANGED
|
@@ -23,6 +23,7 @@ fs.writeFileSync(
|
|
|
23
23
|
const { closeLocalDb } = require('../state/db');
|
|
24
24
|
const { revisionOf } = require('../workspace/checkpoint');
|
|
25
25
|
const {
|
|
26
|
+
captureIsOnRail,
|
|
26
27
|
hydrateRepo,
|
|
27
28
|
materializeRepo,
|
|
28
29
|
readRepoState,
|
|
@@ -296,6 +297,39 @@ test('one materializer converges to the reduced checkpoint and later removes a r
|
|
|
296
297
|
assert.equal(fs.readFileSync(path.join(repo, 'b.txt'), 'utf8'), 'b1\n');
|
|
297
298
|
});
|
|
298
299
|
|
|
300
|
+
test('once local work is on the rail, a checkpoint conflict materializes exactly without echoing', async () => {
|
|
301
|
+
const { repo, oid } = await makeRepo('materialize-conflict');
|
|
302
|
+
const localPatch = await patchFor(repo, { 'a.txt': 'local answer\n' });
|
|
303
|
+
const remotePatch = await patchFor(repo, { 'a.txt': 'remote answer\n' });
|
|
304
|
+
const localTransition = transition('machine-local', 2, oid, '', localPatch);
|
|
305
|
+
const plan = {
|
|
306
|
+
repoKey: 'root:test',
|
|
307
|
+
card: card(repo, oid, 1),
|
|
308
|
+
transitions: [
|
|
309
|
+
localTransition,
|
|
310
|
+
transition('machine-remote', 3, oid, '', remotePatch),
|
|
311
|
+
],
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
fs.writeFileSync(path.join(repo, 'a.txt'), 'local answer\n');
|
|
315
|
+
await git(repo, 'add', 'a.txt');
|
|
316
|
+
assert.equal(captureIsOnRail(plan, {
|
|
317
|
+
baseOid: oid,
|
|
318
|
+
indexDiff: localPatch,
|
|
319
|
+
worktreeDiff: '',
|
|
320
|
+
}), true);
|
|
321
|
+
|
|
322
|
+
const outcome = await materializeRepo(plan.card, plan);
|
|
323
|
+
assert.equal(outcome.state, 'conflict');
|
|
324
|
+
const first = fs.readFileSync(path.join(repo, 'a.txt'), 'utf8');
|
|
325
|
+
assert.match(first, /local answer/);
|
|
326
|
+
assert.match(first, /remote answer/);
|
|
327
|
+
assert.match(first, /<<<<<<< current/);
|
|
328
|
+
|
|
329
|
+
await materializeRepo(plan.card, plan);
|
|
330
|
+
assert.equal(fs.readFileSync(path.join(repo, 'a.txt'), 'utf8'), first);
|
|
331
|
+
});
|
|
332
|
+
|
|
299
333
|
test('a writer publishing again cannot erase its earlier uncommitted work', async () => {
|
|
300
334
|
const { repo, oid } = await makeRepo('checkpoint-history');
|
|
301
335
|
const patchA = await patchFor(repo, { 'a.txt': 'a1\n' });
|
|
@@ -32,6 +32,7 @@ const {
|
|
|
32
32
|
repoKeyOfCard,
|
|
33
33
|
revisionOf,
|
|
34
34
|
} = require('./checkpoint');
|
|
35
|
+
const { machineId } = require('./identity');
|
|
35
36
|
const merge = require('./merge');
|
|
36
37
|
const transition = require('./transition');
|
|
37
38
|
|
|
@@ -416,6 +417,25 @@ async function reduceCheckpoint(localCard, plan) {
|
|
|
416
417
|
};
|
|
417
418
|
}
|
|
418
419
|
|
|
420
|
+
function captureIsOnRail(plan, captured, localMachine = machineId()) {
|
|
421
|
+
if (
|
|
422
|
+
!captured
|
|
423
|
+
|| captured.indexDiff === null
|
|
424
|
+
|| captured.baseOid !== plan.card.head.oid
|
|
425
|
+
) return false;
|
|
426
|
+
const latest = [...plan.transitions]
|
|
427
|
+
.reverse()
|
|
428
|
+
.find((operation) => operation.machine === localMachine);
|
|
429
|
+
return Boolean(
|
|
430
|
+
latest
|
|
431
|
+
&& latest.to?.revision === revisionOf(
|
|
432
|
+
captured.baseOid,
|
|
433
|
+
captured.indexDiff,
|
|
434
|
+
captured.worktreeDiff,
|
|
435
|
+
),
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
|
|
419
439
|
async function materializeRepo(localCardInput, plan) {
|
|
420
440
|
const refreshed = await refreshRepoCard(localCardInput.replica) || localCardInput;
|
|
421
441
|
const cardResult = await moveToWinningCard(refreshed, plan.card);
|
|
@@ -436,16 +456,28 @@ async function materializeRepo(localCardInput, plan) {
|
|
|
436
456
|
if (reduced.state !== 'ready') return reduced;
|
|
437
457
|
|
|
438
458
|
const baseTree = await merge.treeOf(localCard.path, plan.card.head.oid);
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
?
|
|
443
|
-
:
|
|
444
|
-
const
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
459
|
+
const captured = await captureCheckpoint(localCard.path);
|
|
460
|
+
const represented = captureIsOnRail(plan, captured);
|
|
461
|
+
const capturedIndex = represented
|
|
462
|
+
? await merge.treeOfPatch(localCard.path, plan.card.head.oid, captured.indexDiff)
|
|
463
|
+
: null;
|
|
464
|
+
const capturedWorktree = represented
|
|
465
|
+
? await merge.treeOfPatch(localCard.path, capturedIndex, captured.worktreeDiff)
|
|
466
|
+
: null;
|
|
467
|
+
const heldWorktree = capturedWorktree || (
|
|
468
|
+
previous?.baseOid === plan.card.head.oid
|
|
469
|
+
&& previous.heldTree
|
|
470
|
+
&& await merge.hasTree(localCard.path, previous.heldTree)
|
|
471
|
+
? previous.heldTree
|
|
472
|
+
: baseTree
|
|
473
|
+
);
|
|
474
|
+
const heldIndex = capturedIndex || (
|
|
475
|
+
previous?.baseOid === plan.card.head.oid
|
|
476
|
+
&& previous.heldIndexTree
|
|
477
|
+
&& await merge.hasTree(localCard.path, previous.heldIndexTree)
|
|
478
|
+
? previous.heldIndexTree
|
|
479
|
+
: baseTree
|
|
480
|
+
);
|
|
449
481
|
const currentIndex = await merge.indexTree(localCard.path);
|
|
450
482
|
const reducedLocalIndex = await merge.reduceTree(
|
|
451
483
|
localCard.path,
|
|
@@ -642,6 +674,7 @@ function reducerStats() {
|
|
|
642
674
|
}
|
|
643
675
|
|
|
644
676
|
module.exports = {
|
|
677
|
+
captureIsOnRail,
|
|
645
678
|
hydrateRepo,
|
|
646
679
|
materializeRepo,
|
|
647
680
|
readRepoState,
|