import {execCommand} from "https://script.hatter.ink/@29/deno-commons-mod.ts"; import {existsSync} from "node:fs"; export async function getGitRemoteRev(): Promise { const currentBranch = await getGitCurrentBranch(); const lsGitRemoteOrigin = await execCommand("git", [ "ls-remote", "origin", currentBranch, ]); lsGitRemoteOrigin.assertSuccess(); return lsGitRemoteOrigin.stdout.trim().split(/\s+/)[0].trim(); } export async function getGitCurrentBranch(): Promise { const gitCurrentBranch = await execCommand("git", [ "branch", "--show-current", ]); gitCurrentBranch.assertSuccess(); return gitCurrentBranch.stdout.trim(); } export async function getGitLocalRev(): Promise { const gitLocalRev = await execCommand("git", [ "rev-parse", "HEAD", ]); gitLocalRev.assertSuccess(); return gitLocalRev.stdout.trim(); } export class GitStatusResult { newfile: string[]; modified: string[]; deleted: string[]; untracked: string[]; constructor( newfile: string[], modified: string[], deleted: string[], untracked: string[], ) { this.newfile = newfile; this.modified = modified; this.deleted = deleted; this.untracked = untracked; } } // On branch main // Your branch is up to date with 'origin/main'. // // nothing to commit, working tree clean // ---------------------------------------------------------------------- // On branch main // Your branch is up to date with 'origin/main'. // // Changes to be committed: // (use "git restore --staged ..." to unstage) // new file: single-scripts/commit.ts // ---------------------------------------------------------------------- // On branch main // Your branch is up to date with 'origin/main'. // // Changes not staged for commit: // (use "git add/rm ..." to update what will be committed) // (use "git restore ..." to discard changes in working directory) // modified: README.md // deleted: script-config.json // // Untracked files: // (use "git add ..." to include in what will be committed) // single-scripts/commit.ts // // no changes added to commit (use "git add" and/or "git commit -a") export async function getGitStatus(): Promise { const newfile: string[] = []; const modified: string[] = []; const deleted: string[] = []; const untracked: string[] = []; const gitStatus = await execCommand("git", ["status"]); gitStatus.assertSuccess(); const gitStatusStdout = gitStatus.stdout.trim(); if (gitStatusStdout.includes("nothing to commit, working tree clean")) { return null; } let inChangesNotStaged = false; let inUntrackedFiles = false; gitStatusStdout.split("\n").forEach((line) => { if ( line.startsWith("Changes to be committed:") || line.startsWith("Changes not staged for commit:") ) { inChangesNotStaged = true; inUntrackedFiles = false; return; } if (line.startsWith("Untracked files:")) { inChangesNotStaged = false; inUntrackedFiles = true; return; } if (inChangesNotStaged) { const modifiedOrDeletedLine = line.trim(); if (modifiedOrDeletedLine.startsWith("new file:")) { const newFile = modifiedOrDeletedLine.substring( "new file:".length, ).trim(); newfile.push(newFile); } else if (modifiedOrDeletedLine.startsWith("modified:")) { const modifiedFile = modifiedOrDeletedLine.substring( "modified:".length, ).trim(); modified.push(modifiedFile); } else if (modifiedOrDeletedLine.startsWith("deleted:")) { const deletedFile = modifiedOrDeletedLine.substring( "deleted:".length, ).trim(); deleted.push(deletedFile); } } if (inUntrackedFiles) { const newFile = line.trim(); if (newFile && existsSync(newFile)) { untracked.push(newFile); } } }); if ( newfile.length === 0 && modified.length === 0 && deleted.length === 0 && untracked.length === 0 ) { // WILL THIS HAPPEN? return null; } return new GitStatusResult(newfile, modified, deleted, untracked); }