hippocamp 0.2.9 → 0.2.10
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 +1 -1
- package/scripts/hippocamp-memory.cjs +26 -22
- package/test/sync-memory.test.cjs +54 -0
package/package.json
CHANGED
|
@@ -510,12 +510,19 @@ async function syncMemory({ scope, projectRoot, paths, message }) {
|
|
|
510
510
|
}
|
|
511
511
|
|
|
512
512
|
if (!diffResult.stdout) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
513
|
+
// Commits left behind by an earlier failed push still need to go up.
|
|
514
|
+
const aheadResult = await runGit(["rev-list", "--count", "@{u}..HEAD"], repoRoot);
|
|
515
|
+
|
|
516
|
+
if (!aheadResult.ok || aheadResult.stdout === "0") {
|
|
517
|
+
return {
|
|
518
|
+
attempted: true,
|
|
519
|
+
skipped: true,
|
|
520
|
+
reason: "no_changes_to_commit",
|
|
521
|
+
repoRoot,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return pushToUpstream(repoRoot, { attempted: true, committed: false, repoRoot });
|
|
519
526
|
}
|
|
520
527
|
|
|
521
528
|
const commitResult = await runGit(["commit", "-m", message, "--", ...repoRelativePaths], repoRoot);
|
|
@@ -524,16 +531,22 @@ async function syncMemory({ scope, projectRoot, paths, message }) {
|
|
|
524
531
|
throw new Error(commitResult.stderr || "git commit failed.");
|
|
525
532
|
}
|
|
526
533
|
|
|
534
|
+
return pushToUpstream(repoRoot, {
|
|
535
|
+
attempted: true,
|
|
536
|
+
committed: true,
|
|
537
|
+
repoRoot,
|
|
538
|
+
commitSummary: commitResult.stdout,
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
async function pushToUpstream(repoRoot, result) {
|
|
527
543
|
const upstreamResult = await runGit(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], repoRoot);
|
|
528
544
|
|
|
529
545
|
if (!upstreamResult.ok) {
|
|
530
546
|
return {
|
|
531
|
-
|
|
532
|
-
committed: true,
|
|
547
|
+
...result,
|
|
533
548
|
pushed: false,
|
|
534
549
|
reason: "no_upstream",
|
|
535
|
-
repoRoot,
|
|
536
|
-
commitSummary: commitResult.stdout,
|
|
537
550
|
};
|
|
538
551
|
}
|
|
539
552
|
|
|
@@ -544,12 +557,9 @@ async function syncMemory({ scope, projectRoot, paths, message }) {
|
|
|
544
557
|
|
|
545
558
|
if (!pullResult.ok) {
|
|
546
559
|
return {
|
|
547
|
-
|
|
548
|
-
committed: true,
|
|
560
|
+
...result,
|
|
549
561
|
pushed: false,
|
|
550
562
|
reason: "pull_rebase_failed",
|
|
551
|
-
repoRoot,
|
|
552
|
-
commitSummary: commitResult.stdout,
|
|
553
563
|
pushError: pushResult.stderr,
|
|
554
564
|
pullError: pullResult.stderr,
|
|
555
565
|
};
|
|
@@ -559,23 +569,17 @@ async function syncMemory({ scope, projectRoot, paths, message }) {
|
|
|
559
569
|
|
|
560
570
|
if (!pushResult.ok) {
|
|
561
571
|
return {
|
|
562
|
-
|
|
563
|
-
committed: true,
|
|
572
|
+
...result,
|
|
564
573
|
pushed: false,
|
|
565
574
|
reason: "push_failed",
|
|
566
|
-
repoRoot,
|
|
567
|
-
commitSummary: commitResult.stdout,
|
|
568
575
|
pushError: pushResult.stderr,
|
|
569
576
|
};
|
|
570
577
|
}
|
|
571
578
|
}
|
|
572
579
|
|
|
573
580
|
return {
|
|
574
|
-
|
|
575
|
-
committed: true,
|
|
581
|
+
...result,
|
|
576
582
|
pushed: true,
|
|
577
|
-
repoRoot,
|
|
578
|
-
commitSummary: commitResult.stdout,
|
|
579
583
|
pushSummary: pushResult.stdout || pushResult.stderr,
|
|
580
584
|
};
|
|
581
585
|
}
|
|
@@ -63,3 +63,57 @@ test("sync commits when the Lagoon path goes through a symlink", async (t) => {
|
|
|
63
63
|
/escapes the memory root/,
|
|
64
64
|
);
|
|
65
65
|
});
|
|
66
|
+
|
|
67
|
+
test("sync pushes commits left behind by an earlier failed push", async (t) => {
|
|
68
|
+
const originalRoot = process.env.HIPPOCAMP_GLOBAL_ROOT;
|
|
69
|
+
const tempRoot = await fs.mkdtemp(path.join(os.tmpdir(), "hippocamp-backlog-"));
|
|
70
|
+
const remote = path.join(tempRoot, "remote.git");
|
|
71
|
+
const lagoon = path.join(tempRoot, "lagoon");
|
|
72
|
+
const projectRoot = path.join(tempRoot, "project");
|
|
73
|
+
const git = (args, cwd = lagoon) => execFileSync("git", args, { cwd }).toString().trim();
|
|
74
|
+
|
|
75
|
+
const identity = { GIT_AUTHOR_NAME: "Test", GIT_AUTHOR_EMAIL: "test@example.com", GIT_COMMITTER_NAME: "Test", GIT_COMMITTER_EMAIL: "test@example.com" };
|
|
76
|
+
const saved = Object.fromEntries(Object.keys(identity).map((key) => [key, process.env[key]]));
|
|
77
|
+
Object.assign(process.env, identity);
|
|
78
|
+
t.after(() => {
|
|
79
|
+
for (const [key, value] of Object.entries(saved)) {
|
|
80
|
+
if (value === undefined) {
|
|
81
|
+
delete process.env[key];
|
|
82
|
+
} else {
|
|
83
|
+
process.env[key] = value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
git(["init", "-q", "--bare", "-b", "main", remote], tempRoot);
|
|
89
|
+
git(["clone", "-q", remote, lagoon], tempRoot);
|
|
90
|
+
git(["commit", "-q", "--allow-empty", "-m", "init"]);
|
|
91
|
+
git(["push", "-q", "-u", "origin", "main"]);
|
|
92
|
+
process.env.HIPPOCAMP_GLOBAL_ROOT = lagoon;
|
|
93
|
+
t.after(async () => {
|
|
94
|
+
if (originalRoot === undefined) {
|
|
95
|
+
delete process.env.HIPPOCAMP_GLOBAL_ROOT;
|
|
96
|
+
} else {
|
|
97
|
+
process.env.HIPPOCAMP_GLOBAL_ROOT = originalRoot;
|
|
98
|
+
}
|
|
99
|
+
await fs.rm(tempRoot, { recursive: true, force: true, maxRetries: 5 });
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Simulate an unreachable remote for the first write.
|
|
103
|
+
git(["remote", "set-url", "origin", path.join(tempRoot, "missing.git")]);
|
|
104
|
+
const write = await memory.appendEvent({ content: "Use HTTPS.", keywords: ["sync"], projectRoot, scope: "project", title: "Remote" });
|
|
105
|
+
assert.equal(write.sync.committed, true);
|
|
106
|
+
assert.equal(write.sync.pushed, false);
|
|
107
|
+
|
|
108
|
+
git(["remote", "set-url", "origin", remote]);
|
|
109
|
+
const result = await memory.syncMemory({
|
|
110
|
+
scope: "project",
|
|
111
|
+
projectRoot,
|
|
112
|
+
paths: await memory.getDefaultSyncPaths("project", projectRoot),
|
|
113
|
+
message: "sync",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
assert.equal(result.committed, false);
|
|
117
|
+
assert.equal(result.pushed, true);
|
|
118
|
+
assert.equal(git(["rev-parse", "main"], remote), git(["rev-parse", "HEAD"]));
|
|
119
|
+
});
|