28 lines
1.6 KiB
TypeScript
28 lines
1.6 KiB
TypeScript
// Keep a folder out of the app's git repo: store art pulled from the stores (and renders) is never committed.
|
|
import { appendFileSync, existsSync, readFileSync, realpathSync, writeFileSync } from 'node:fs';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { join, relative, sep } from 'node:path';
|
|
|
|
const git = (cwd: string, args: string[]) => spawnSync('git', args, { cwd, encoding: 'utf8', timeout: 15_000 });
|
|
|
|
/** When `dir` is inside a git repo and not ignored yet, adds `/<dir relative to the repo root>/` to the repo root's
|
|
* .gitignore. Returns the line added, or null (no repo, no git, already ignored). `dry`: only says what it would add. */
|
|
export function ignoreInRepo(dir: string, comment: string, dry = false): string | null {
|
|
let probe = dir;
|
|
while (!existsSync(probe)) { const up = join(probe, '..'); if (up === probe) return null; probe = up; }
|
|
const top = git(probe, ['rev-parse', '--show-toplevel']);
|
|
if (top.status !== 0) return null;
|
|
const root = realpathSync(top.stdout.trim());
|
|
let real: string;
|
|
try { real = realpathSync(probe) + dir.slice(probe.length); } catch { return null; }
|
|
const rel = relative(root, real).split(sep).join('/');
|
|
if (!rel || rel.startsWith('..')) return null;
|
|
if (git(root, ['check-ignore', '-q', `${rel}/`]).status === 0) return null;
|
|
const line = `/${rel}/`;
|
|
if (dry) return line;
|
|
const gi = join(root, '.gitignore');
|
|
const cur = existsSync(gi) ? readFileSync(gi, 'utf8') : '';
|
|
const add = `# ${comment}\n${line}\n`;
|
|
if (cur) appendFileSync(gi, `${cur.endsWith('\n') ? '' : '\n'}${add}`); else writeFileSync(gi, add);
|
|
return line;
|
|
}
|