OpenMiInk/scripts/krita-patch.ts
Hellings b8c8ff98e2 Hi
2026-10-16 09:05:56 -04:00

111 lines
3.7 KiB
TypeScript

import fs from "node:fs";
import path from "node:path";
import { spawnSync } from "node:child_process";
const root = path.resolve(import.meta.dir, "..");
const krita = path.join(root, "krita");
const patchDir = path.join(root, "krita-patches");
const patchFile = path.join(patchDir, "xiaomi-eink.patch");
// Keep generated patches limited to this project. The nested Krita checkout may carry
// line-ending or formatter changes that are not part of the E Ink product patch.
const patchPaths = [
"CMakeLists.txt",
"libs/ui/KisApplication.cpp",
"libs/ui/KisMainWindow.cpp",
"libs/ui/thememanager.cpp",
"packaging/android/apk/AndroidManifest.xml",
"packaging/android/apk/build.gradle",
"packaging/android/apk/proguard-rules.pro",
"packaging/android/apk/src/org/krita/android/MainActivity.java",
"plugins/CMakeLists.txt",
"plugins/dockers/CMakeLists.txt",
"plugins/filters/CMakeLists.txt",
"plugins/impex/CMakeLists.txt",
"plugins/paintops/CMakeLists.txt",
"plugins/tools/CMakeLists.txt",
];
const untrackedPatchPaths = [
"EINK_SLIM.md",
"packaging/android/apk/.gitignore",
"packaging/android/apk/settings.gradle",
"packaging/android/apk/lib/arm64-v8a/libfakeRKEpdUtils.so",
"packaging/android/apk/src/com/moan/fakerkepdlib/EpdUtil.java",
"packaging/android/apk/src/org/krita/android/XiaomiEinkController.java",
"plugins/dockers/einkmonochromeselector/CMakeLists.txt",
"plugins/dockers/einkmonochromeselector/einkmonochromeselector.cpp",
"plugins/dockers/einkmonochromeselector/krita_einkmonochromeselector.json",
"plugins/extensions/einksync/CMakeLists.txt",
"plugins/extensions/einksync/EinkSyncPlugin.action",
"plugins/extensions/einksync/EinkSyncPlugin.cpp",
"plugins/extensions/einksync/kritaeinksync.json",
];
function git(args: string[], allowDifference = false): string {
const result = spawnSync("git", ["-C", krita, ...args], {
encoding: "utf8",
maxBuffer: 128 * 1024 * 1024,
});
if (result.error) throw result.error;
if (result.status !== 0 && !(allowDifference && result.status === 1)) {
throw new Error(result.stderr || `git ${args.join(" ")} failed`);
}
return result.stdout;
}
function generate(): void {
fs.mkdirSync(patchDir, { recursive: true });
let output = git([
"diff",
"--binary",
"--ignore-space-at-eol",
"--",
...patchPaths,
]);
const available = new Set(
git(["ls-files", "--others", "--exclude-standard"])
.split("\n")
.filter(Boolean),
);
const untracked = untrackedPatchPaths.filter((file) => available.has(file));
for (const file of untracked) {
output += git(
["diff", "--no-index", "--binary", "--", "/dev/null", file],
true,
);
}
if (!output.trim()) throw new Error("Krita has no changes to package");
fs.writeFileSync(patchFile, output);
console.log(`[ok] Generated ${patchFile} with ${untracked.length} new files`);
}
function apply(): void {
if (!fs.existsSync(path.join(krita, ".git")))
throw new Error("Initialize the Krita submodule first");
if (!fs.existsSync(patchFile)) throw new Error(`Missing ${patchFile}`);
const applyArgs = ["apply", "--ignore-space-change", "--recount"];
const check = spawnSync(
"git",
["-C", krita, ...applyArgs, "--check", patchFile],
{
encoding: "utf8",
},
);
if (check.status === 0) {
git([...applyArgs, "--whitespace=nowarn", patchFile]);
console.log("[ok] Applied E Ink Krita patch set");
return;
}
const reverse = spawnSync(
"git",
["-C", krita, ...applyArgs, "--reverse", "--check", patchFile],
{ encoding: "utf8" },
);
if (reverse.status === 0) {
console.log("[ok] E Ink Krita patch set is already applied");
return;
}
throw new Error(`Patch does not apply cleanly\n${check.stderr}`);
}
if (process.argv.includes("--generate")) generate();
else apply();