// Row 288: real bare-repository plumbing and remote effects. All text and credentials are fixtures. import test from 'node:test'; import assert from 'node:assert/strict'; import { writeFileSync, existsSync, renameSync, mkdirSync, rmSync } from 'node:fs'; import { join } from 'node:path'; import { git } from './helpers.mjs'; import { sync, push, withLibraryWriteGuard } from '../src/sync.mjs'; import { servedCommit, withLibraryLock, readSyncState, SYNC_STATE_FILE } from '../src/mirror.mjs'; import { publishLibraryWrite } from '../src/sync.mjs'; import { checkMapping } from '../src/mapping.mjs'; import { writeLibraryDoc, saveLibraryFile, revertLibraryCommit } from '../src/write.mjs'; import { world, PATH, EDITOR } from './write-fixture.mjs'; test('C2-02: write/delete each publish one parent, seat ident, fixed trailer, index and lastPush', async t => { const f = await world(t), parent = f.remoteHead(); const saved = await writeLibraryDoc(f.args(), f.opts); assert.deepEqual(saved, { project: 'books', path: PATH, commit: f.remoteHead() }); assert.equal(git(f.remote, 'show', `${saved.commit}:${PATH}`), 'after'); assert.equal(git(f.remote, 'show', '-s', '--format=%P', saved.commit), parent); assert.equal(git(f.remote, 'show', '-s', '--format=%an <%ae>|%cn <%ce>', saved.commit), 'Bean Fixture |Bean Fixture '); assert.equal(git(f.remote, 'show', '-s', '--format=%B', saved.commit), `Mosaic: write ${PATH}\n\nMosaic-Agent: acme/bean`); assert.equal(await servedCommit(f.mirror), saved.commit); assert.equal((await f.state()).lastPush.commit, saved.commit); assert.equal(existsSync(join(f.mirror, 'index')), false); const gone = await writeLibraryDoc(f.args({ content: undefined }), { ...f.opts, op: 'delete' }); assert.equal(git(f.remote, 'show', '-s', '--format=%P', gone.commit), saved.commit); assert.equal(git(f.remote, 'ls-tree', '-r', gone.commit, '--', PATH), ''); assert.equal(git(f.remote, 'show', '-s', '--format=%B', gone.commit), `Mosaic: delete ${PATH}\n\nMosaic-Agent: acme/bean`); }); test('C2-02 M12: each path refusal leaves every ref and remote unchanged', async t => { const f = await world(t); const paths = ['Book One/Chapters/Chapter 01.md', 'Book One/Playground/What If.md', 'Inbox Note.md', 'Book One/Notes/X.canvas', 'Book One/Notes/X.base', 'Book One/Notes/X.png', 'Second World/Chapters/01.md', '/Book One/Notes/X.md', 'Book One/Notes/../X.md', 'Book One/./Notes/X.md', 'Book One//Notes/X.md', 'Book One/Notes/X\\Y.md', 'Book One/Notes/X\nY.md', 'Book One/Notes/Link.md', 'Book One/Notes/agent.md', `Book One/Notes/${'é'.repeat(512)}.md`]; for (const path of paths) { const before = f.refs(), head = f.remoteHead(); await assert.rejects(writeLibraryDoc(f.args({ path, base: null }), f.opts), { code: 'library-write-story-path' }, path); assert.equal(f.refs(), before); assert.equal(f.remoteHead(), head); } }); test('C2-02 Q4: delete requires an existing 100644 blob; null base never deletes a missing path', async t => { const f = await world(t); for (const path of ['Book One/Notes/Missing.md', 'Book One/Notes/Executable.md', 'Book One/Notes/Link.md', 'Book One/Notes/Submodule.md']) { const before = f.refs(); await assert.rejects(writeLibraryDoc(f.args({ path, base: null, content: undefined }), { ...f.opts, op: 'delete' }), { code: 'library-write-story-path' }); assert.equal(f.refs(), before); } }); test('C2-02: stale base and failed push keep remote/served/tracking refs unchanged', async t => { const f = await world(t), refs = f.refs(), head = f.remoteHead(); await assert.rejects(writeLibraryDoc(f.args({ base: 'a'.repeat(40) }), f.opts), { code: 'stale-base' }); assert.equal(f.refs(), refs); assert.equal(f.remoteHead(), head); f.reject(); await assert.rejects(writeLibraryDoc(f.args(), f.opts), { code: 'library-push-failed' }); assert.equal(f.refs(), refs); assert.equal(f.remoteHead(), head); }); test('C2-02: a moved unrelated blob retries once on the new parent, changed target refuses', async t => { const f = await world(t); const args = f.args(); let raced; f.race(() => { f.external('Inbox Note.md', 'another\n'); raced = f.remoteHead(); }); const saved = await writeLibraryDoc(args, f.opts); assert.equal(git(f.remote, 'show', '-s', '--format=%P', saved.commit), raced); assert.equal(git(f.remote, 'show', `${saved.commit}:Inbox Note.md`), 'another'); const g = await world(t), before = g.refs(); g.race(() => g.external(PATH, 'raced target\n')); await assert.rejects(writeLibraryDoc(g.args(), g.opts), { code: 'stale-base' }); assert.equal(g.refs(), before); assert.equal(git(g.remote, 'show', `main:${PATH}`), 'raced target'); }); test('C2-02: create with null base; human revert restores parent and does not require seat credentials', async t => { const f = await world(t); const made = await writeLibraryDoc(f.args({ path: 'Book One/Notes/New.md', base: null, content: 'new\n' }), f.opts); const options = { credential: { ...f.credential, kind: 'human' }, command: f.command }; const reverted = await revertLibraryCommit({ ...f.context, commit: made.commit }, options); assert.deepEqual(reverted, { project: 'books', path: 'Book One/Notes/New.md', reverted: made.commit, commit: f.remoteHead() }); assert.equal(git(f.remote, 'ls-tree', '-r', reverted.commit, '--', reverted.path), ''); assert.equal(git(f.remote, 'show', '-s', '--format=%an <%ae>|%cn <%ce>', reverted.commit), 'Human Fixture |Human Fixture '); assert.equal(git(f.remote, 'show', '-s', '--format=%(trailers:key=Mosaic-Agent,valueonly)', reverted.commit), ''); }); test('C2-02: revert requires reachable business trailer and refuses a later path change', async t => { const f = await world(t), options = { credential: { ...f.credential, kind: 'human' }, command: f.command }; await assert.rejects(revertLibraryCommit({ ...f.context, commit: f.commit }, options), { code: 'library-revert-not-agent' }); const saved = await writeLibraryDoc(f.args(), f.opts); await saveLibraryFile({ ...f.context, path: PATH, base: git(f.mirror, 'rev-parse', `served:${PATH}`), content: 'human later\n' }, options); await assert.rejects(revertLibraryCommit({ ...f.context, commit: saved.commit }, options), { code: 'stale-base' }); }); test('C2-02: human save reaches story, preserves UTF-8 bytes and uses editor without a trailer', async t => { const f = await world(t), path = 'Book One/Chapters/Chapter 01.md'; const content = '# Her text\n' + 'é'.repeat(40000) + '\n\n'; const saved = await saveLibraryFile({ ...f.context, path, base: git(f.mirror, 'rev-parse', `served:${path}`), content }, { credential: { ...f.credential, kind: 'human' }, command: f.command }); assert.equal(git(f.remote, 'show', '-s', '--format=%an <%ae>', saved.commit), 'Human Fixture '); // git helper trims; compare the stored blob byte count separately. assert.equal(Number(git(f.remote, 'cat-file', '-s', `${saved.commit}:${path}`)), Buffer.byteLength(content)); }); test('C2-02: invalid content/editor/human credential refuse before any git command', async t => { const f = await world(t), before = f.refs(); for (const content of ['nul\0', '\ud800', 'x'.repeat(1024 * 1024 + 1)]) await assert.rejects(writeLibraryDoc(f.args({ content }), f.opts), { code: 'invalid-request' }); const args = { ...f.context, path: PATH, base: null, content: 'x' }; writeFileSync(join(f.mirror, 'unexpected'), 'any local git inspection must refuse\n'); delete f.entry.editor; await assert.rejects(saveLibraryFile(args, { credential: { ...f.credential, kind: 'human' }, command: f.command }), { code: 'library-mapping-invalid' }); await assert.rejects(revertLibraryCommit({ ...f.context, commit: f.commit }, { credential: { ...f.credential, kind: 'human' }, command: f.command }), { code: 'library-mapping-invalid' }); f.entry.editor = EDITOR; const n = f.commands.length; await assert.rejects(saveLibraryFile(args, { credential: { kind: 'human', user: 'human', file: '/absent' }, command: f.command }), { code: 'library-human-missing' }); await assert.rejects(revertLibraryCommit({ ...f.context, commit: f.commit }, { credential: { kind: 'human', user: 'human', file: '/absent' }, command: f.command }), { code: 'library-human-missing' }); assert.equal(f.commands.length, n); assert.equal(f.refs(), before); }); test('C2-02 guard: only the exact owning token permits a push race fetch; sync refuses busy', async t => { const f = await world(t), commit = f.remoteHead(); f.external('Inbox Note.md', 'remote moved\n'); await withLibraryWriteGuard(f.mirror, async token => { await assert.rejects(sync(f.context, { credential: f.credential, command: f.command }), { code: 'library-sync-busy' }); for (const writeToken of [null, {}, Object.freeze({})]) await assert.rejects(push(f.context, { commit, credential: f.credential, command: f.command, writeToken }), { code: 'library-sync-busy' }); const raced = await push(f.context, { commit, credential: f.credential, command: f.command, writeToken: token }); assert.equal(raced.raced, true); assert.equal(raced.tip, f.remoteHead()); }); }); test('C2-02 publication F1: failed state rename restores served to match prior state', async t => { const f = await world(t), previous = await servedCommit(f.mirror); const commit = git(f.mirror, 'commit-tree', git(f.mirror, 'rev-parse', `${previous}^{tree}`), '-p', previous, '-m', 'candidate'); const statePath = join(f.mirror, SYNC_STATE_FILE), backup = join(f.root, 'state-backup'); await withLibraryLock(f.mirror, async lock => { // A filesystem failure after the locked state read, before state publication. The original // state is saved outside the mirror and restored after the failed rename. const read = async options => { const state = await lock.readSyncState(options); renameSync(statePath, backup); mkdirSync(statePath, { mode: 0o700 }); return state; }; try { await assert.rejects(publishLibraryWrite(f.mirror, { mapping: checkMapping(f.entry), commit, previous, readSyncState: read }), { code: 'outcome-unknown' }); assert.equal(git(f.mirror, 'rev-parse', 'served'), previous); } finally { rmSync(statePath, { recursive: true, force: true }); renameSync(backup, statePath); } }); assert.equal((await readSyncState(f.mirror, { branch: 'main' })).served, previous); }); test('C2-02 E1: a dotted business id never matches another business trailer', async t => { const f = await world(t, { business: 'acme.co' }); writeFileSync(join(f.repo, PATH), 'foreign seat change\n'); git(f.repo, 'add', '-A'); git(f.repo, 'commit', '-qm', 'Foreign\n\nMosaic-Agent: acme-co/bean'); const foreign = git(f.repo, 'rev-parse', 'HEAD'); git(f.repo, 'push', '-q', f.remote, 'HEAD:main'); await sync(f.context, { credential: f.credential, command: f.command }); const before = f.refs(); await assert.rejects(revertLibraryCommit({ ...f.context, commit: foreign }, { credential: { ...f.credential, kind: 'human' }, command: f.command }), { code: 'library-revert-not-agent' }); assert.equal(f.refs(), before); assert.equal(f.remoteHead(), foreign); });