Last active
May 28, 2025 11:23
-
-
Save fsubal/4d663c9fad65724c57993d2da1873605 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { resolve } from 'node:path' | |
| import { readFile } from 'node:fs/promises' | |
| import { exec } from 'node:child_process' | |
| import { promisify } from 'node:util' | |
| const execp = promisify(exec) | |
| /** | |
| * @see https://git-scm.com/docs/git-status#_porcelain_format_version_1 | |
| */ | |
| const PATTERN = /( M| D|\?\?)\s*(.+)/ | |
| function parseGitStatus(line: string) { | |
| const [, status, path] = line.match(PATTERN) ?? [] | |
| switch (status) { | |
| case ' M': { | |
| return [path, 'modified'] as const | |
| } | |
| case ' D': { | |
| return [path, 'deleted'] as const | |
| } | |
| case '??': { | |
| return [path, 'added'] as const | |
| } | |
| default: { | |
| throw new TypeError(`Could not parse git status result: (${line})`) | |
| } | |
| } | |
| } | |
| async function loadGitStatus(dirname = process.cwd()) { | |
| const lines = await execp('git status --porcelain').then(({ stdout }) => stdout.trim().split('\n')) | |
| const parsedStatus = new Map(lines.map(parseGitStatus)) | |
| return { | |
| async *[Symbol.asyncIterator]() { | |
| for (const [relativePath, status] of parsedStatus) { | |
| const fullpath = resolve(dirname, relativePath) | |
| const content = await readFile(fullpath, { encoding: 'utf8' }) | |
| yield { fullpath, status, content } | |
| } | |
| } | |
| } | |
| } | |
| const gitStatus = await loadGitStatus() | |
| for await (const changedFile of gitStatus) { | |
| console.log(changedFile.status, changedFile.fullpath, changedFile.content) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment