#!/usr/bin/env runts -- --allow-all import { execCommand, formatHumanTime, log, ProcessBar, readFileToString, writeStringToFile, } from "https://script.hatter.ink/@29/deno-commons-mod.ts"; import {getGitLocalRev, getGitRemoteRev,} from "https://script.hatter.ink/@0/deno-git-mod.ts"; async function sha256OfString(input: string): Promise { const data = new TextEncoder().encode(input); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map((b) => b.toString(16).padStart(2, "0")).join( "", ); } async function getPwd(): Promise { const pwd = await execCommand("pwd"); pwd.assertSuccess(); return pwd.stdout.trim(); } interface GitCheckCache { path: string; lastCheckTime: number; } async function main() { const pwd = await getPwd(); const pwdHash = await sha256OfString(pwd); const gitCheckCacheFile = `~/.cache/git-check-${ pwdHash.substring(0, 20) }.json`; log.debug(`Check git cache file: ${gitCheckCacheFile}`); const gitCheckCacheContent = await readFileToString(gitCheckCacheFile); const gitCheckCache = gitCheckCacheContent ? JSON.parse(gitCheckCacheContent) as GitCheckCache : null; if (gitCheckCache) { const timeBefore = Date.now() - gitCheckCache.lastCheckTime; if (timeBefore < 60 * 60 * 1000) { log.info( `Last check at ${new Date( gitCheckCache.lastCheckTime, )}, in ${ formatHumanTime(timeBefore) }, skip check git remote rev`, ); return; } } const localRev = await getGitLocalRev(); const remoteRev = await new ProcessBar("Checking rev").call( async (): Promise => { return await getGitRemoteRev(); }, ); if (localRev === remoteRev) { log.success(`Check rev successfully, rev: ${localRev}`); await writeStringToFile( gitCheckCacheFile, JSON.stringify( { path: pwd, lastCheckTime: Date.now(), } as GitCheckCache, null, 2, ), ); } else { log.error( `Check rev failed, local rev: ${localRev} vs remote rev: ${remoteRev}`, ); Deno.exit(1); } } await main(); // @SCRIPT-SIGNATURE-V1: yk-r1.ES256.20260208T171322+08:00.MEYCIQDvczD6qSfdlDkZCiN+ // 9VKrEX6Fqd7/yZQLXjuWpOOX9AIhAIF/bVRRxFcawTy8DIt6G5Zxv3UqB82KgM0aQIAESMM5