UNPKG

rigjs

Version:

A multi-repos dev tool based on yarn and git.Rigjs is intended to be the simplest way to develop,share and deliver codes between different developers or different projects.

105 lines (96 loc) 3.32 kB
// Shared guards for rig wiki — refuse to operate on hidden paths, // .gitignored content, or .wikiignored content. The user must explicitly // copy such files into a visible, tracked, non-wikiignored location // before they can become wiki sources. import path from 'path'; import { spawnSync } from 'child_process'; import { batchWikiIgnored } from './wikiignore'; export interface PathGuardResult { ok: boolean; reason?: 'hidden' | 'gitignored' | 'wikiignored'; segment?: string; // for hidden: the offending segment detail?: string; // human-readable detail } /** True if any path segment (except `.` / `..`) starts with `.`. */ export function isHiddenPath(p: string): boolean { for (const seg of segmentsOf(p)) { if (seg.startsWith('.')) return true; } return false; } /** First hidden segment, or null. */ export function hiddenSegment(p: string): string | null { for (const seg of segmentsOf(p)) { if (seg.startsWith('.')) return seg; } return null; } function segmentsOf(p: string): string[] { return p.split(path.sep).filter(s => s && s !== '.' && s !== '..'); } /** * Returns true if the path is ignored by git in `repoCwd`'s repo. * Returns false if tracked/non-ignored. Returns null if not in a git repo * (so callers can pass the check transparently outside git contexts). */ export function isGitignored(p: string, repoCwd: string): boolean | null { const r = spawnSync('git', ['check-ignore', '-q', '--', p], { cwd: repoCwd, encoding: 'utf8', }); if (r.status === 0) return true; // ignored if (r.status === 1) return false; // not ignored return null; // exit 128 (not a repo) or git missing } /** * Validate a path as a wiki source / target. Returns ok if visible AND * not gitignored AND not wikiignored. Use for `init` target and `ingest` * source. * * `vaultRoot` (optional) enables the `.wikiignore` check; pass the * project root so layered `.wikiignore` files are consulted. Omit for * pre-vault callers (e.g. `init` deciding where the vault dir lives). */ export function guardPath(absPath: string, repoCwd: string, vaultRoot?: string): PathGuardResult { const seg = hiddenSegment(absPath); if (seg) { return { ok: false, reason: 'hidden', segment: seg, detail: `path contains a hidden segment "${seg}"`, }; } const gi = isGitignored(absPath, repoCwd); if (gi === true) { return { ok: false, reason: 'gitignored', detail: '.gitignore matches this path', }; } if (vaultRoot) { const wk = batchWikiIgnored([absPath], vaultRoot); if (wk.has(absPath)) { return { ok: false, reason: 'wikiignored', detail: '.wikiignore matches this path', }; } } return { ok: true }; } export function refusalMessage(target: string, r: PathGuardResult): string { const lines = [ `refused: ${target}`, ` reason: ${r.reason}${r.detail}`, '', ' rig wiki refuses to operate on hidden files/dirs, .gitignored, or .wikiignored content.', ' If you really need this content, copy it to a visible, tracked location first:', '', ' cp -R <hidden-or-ignored> <wiki>/raw/manual-copy/ # then `rig wiki ingest`', '', ]; return lines.join('\n'); }