// Row 175 (#1673, mos-0872 Q2): `project init --tester` initializes only a repository under // /projects//, and its layout commit names `tester` as author and committer. import test from 'node:test'; import assert from 'node:assert/strict'; import { existsSync, mkdtempSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { execFileSync } from 'node:child_process'; import { initProject, testerProjectArea } from '../src/index.mjs'; const git = (repo, ...args) => execFileSync('git', ['-c', 'core.hooksPath=/dev/null', '-c', 'maintenance.auto=false', '-c', 'gc.auto=0', '-C', repo, ...args], { encoding: 'utf8' }).trim(); function context(t, repo) { const root = mkdtempSync(join(tmpdir(), 'project-tester-')); t.after(() => rmSync(root, { recursive: true, force: true })); const dataRoot = join(root, 'data'); return { root, business: { id: 'acme', human: 'jason', projects: { stack: { root: join(root, 'code'), ...(repo ? { repo: repo(root, dataRoot) } : {}) } } }, project: 'stack', dataRoot }; } test('row 175: init with author tester commits the layout as tester; without it, as the human', async (t) => { const c = context(t); const { repo, commit } = await initProject(c, { author: 'tester' }); assert.equal(repo, join(c.dataRoot, 'projects/acme/stack')); assert.equal(git(repo, 'show', '-s', '--format=%an|%cn', commit), 'tester|tester'); assert.equal(git(repo, 'rev-list', '--count', 'HEAD'), '1'); const h = context(t); const human = await initProject(h); assert.equal(git(human.repo, 'show', '-s', '--format=%an|%cn', human.commit), 'jason|jason'); }); test('row 175: init refuses an author that is no id before it makes any directory', async (t) => { const c = context(t); for (const author of ['', 'two words', '../x', 7]) await assert.rejects(initProject(c, { author }), { code: 'project-id' }, String(author)); assert.equal(existsSync(c.dataRoot), false); }); test('row 175: testerProjectArea passes a repository inside the business area and refuses the area itself and any other, touching nothing', (t) => { const inside = [ null, (root, dataRoot) => join(dataRoot, 'projects', 'acme', 'records'), (root, dataRoot) => join(dataRoot, 'projects', 'acme', 'deep', 'records'), ]; for (const repo of inside) { const c = context(t, repo); assert.equal(testerProjectArea(c), repo ? repo(c.root, c.dataRoot) : join(c.dataRoot, 'projects', 'acme', 'stack')); } const outside = [ (root) => join(root, 'records'), (root, dataRoot) => join(dataRoot, 'records'), (root, dataRoot) => join(dataRoot, 'projects', 'other', 'stack'), // A sibling whose name starts with the business id is not inside it. (root, dataRoot) => join(dataRoot, 'projects', 'acme-2', 'stack'), // The area itself: a repository there would hold the other projects' default repositories. (root, dataRoot) => join(dataRoot, 'projects', 'acme'), ]; for (const repo of outside) { const c = context(t, repo); assert.throws(() => testerProjectArea(c), { code: 'tester-project-area' }, repo(c.root, c.dataRoot)); assert.equal(existsSync(c.dataRoot), false); assert.equal(existsSync(repo(c.root, c.dataRoot)), false); } // projectRepo's own checks still come first. assert.throws(() => testerProjectArea({ ...context(t), project: 'missing' }), { code: 'project-not-declared' }); });