UNPKG

diffjam

Version:
94 lines (78 loc) 2.59 kB
/* Calls back a single listener with all non-gitignored files in the current working directory. Uses git ls-tree by default, falling back to fdir if git is not available or this isn't a git repo. We maintain a queue for if files are available before the listener is ready. */ import { equal } from "node:assert"; import { spawn } from "child_process" import { createInterface } from "node:readline"; import { fdir } from "fdir"; import { join } from "path"; import { GitIgnore } from "./GitIgnore" export class CurrentWorkingDirectory { private queue: string[] = []; private closed = false; private listener: undefined | { onFile: (path: string) => void; onClose: () => void; } constructor(public cwd: string, gitIgnoreFileName?: string) { if (gitIgnoreFileName) { this.manualDirCrawl(gitIgnoreFileName); } else { const gitLsTree = spawn("git", ["ls-tree", "-r", "HEAD", "--name-only"]); gitLsTree.on("error", () => this.manualDirCrawl()); const nonGitIgnoredFiles = createInterface({ input: gitLsTree.stdout, }); nonGitIgnoredFiles.on("line", this.onFile.bind(this)); nonGitIgnoredFiles.on("close", this.onClose.bind(this)); } } private async manualDirCrawl(gitIgnoreFileName?: string) { // git is not installed or this isn't a git repo, falling back to fdir const gitignore = new GitIgnore(join(this.cwd, gitIgnoreFileName || ".gitignore")); const gettingFiles = new fdir() .withRelativePaths() .withErrors() .filter((_, isDirectory) => !isDirectory) .crawl(this.cwd) .withPromise() as Promise<string[]> await gitignore.ready; const files = await gettingFiles; files.forEach(file => { if (!gitignore.isIgnored(file) && file !== gitIgnoreFileName) { this.onFile(file); } }); this.onClose(); } private onFile(path: string) { if (this.listener) { this.listener.onFile(path); } else { this.queue.push(path); } } private onClose() { equal(this.closed, false, "CurrentWorkingDirectory.onClose() should only be called once"); this.closed = true; if (this.listener) { this.listener.onClose(); } } allNonGitIgnoredFiles( onFile: (path: string) => void, onClose: () => void ) { if (this.listener) throw new Error("Already listening"); this.listener = { onFile, onClose }; if (this.queue.length) { this.queue.forEach(onFile); this.queue = []; } if (this.closed) { this.listener.onClose(); } } }