Fixture helpers that commit to a repository the product later inspects now pass maintenance.auto=false and gc.auto=0, as the product's own git calls already do, so a detached git maintenance run no longer writes pack temp files mid-walk. inspectGit now refuses a git metadata entry that vanishes between readdir and lstat (or between listing a directory and reading it) with project-repository, 'git metadata changed during inspection', instead of leaking a raw ENOENT. It still refuses rather than skipping or retrying. A missing .git keeps its existing error. A deterministic test removes the named entry from inside a replaced readdirSync, for both a file and a directory.
65 lines
3.4 KiB
JavaScript
65 lines
3.4 KiB
JavaScript
// Row 175 (#1673, mos-0872 Q2): `project init --tester` initializes only a repository under
|
|
// <dataRoot>/projects/<business>/, 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' });
|
|
});
|