mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-14 00:49:00 +02:00
fix(make-pdf): pdftotext version and flavor probe returns unknown on poppler
describeBinary reports version="unknown" flavor="unknown" for every poppler
install, so logDiagnostics prints nothing useful on the most common
implementation. Two independent causes:
1. poppler writes the -v banner to stderr and exits 0. execFileSync returns
stdout (empty) and does not throw on a zero exit, so the stderr fallback in
the catch block is unreachable. The in-code comment already notes poppler
exits 0, but only the throwing path reads stderr.
2. flavor is matched against the version line alone. poppler prints
"pdftotext version 26.06.0" on line 1 and names itself on line 2,
"Copyright ... The Poppler Developers", so even a working stderr read
yields "unknown".
Switch the probe to spawnSync, which returns both streams regardless of exit
status, match the version banner rather than assuming line 0, and derive the
flavor from the full output.
Measured on poppler 26.06.0 (Homebrew, macOS), same machine and binary:
before: { version: "unknown", flavor: "unknown" }
after: { version: "pdftotext version 26.06.0", flavor: "poppler" }
xpdf is unaffected: it exits non-zero and names itself on line 1, so it
resolved correctly before and still does.
Tests use shell shims reproducing each vendor's banner, stream and exit status,
since a real pdftotext cannot be assumed present in CI. Two of the four fail on
this commit's parent; the xpdf and no-banner cases pass there and are included
as regression guards rather than red-proofs.
This commit is contained in:
+20
-14
@@ -26,7 +26,7 @@
|
||||
* Only the CI gate and unit tests invoke pdftotext.
|
||||
*/
|
||||
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { execFileSync, spawnSync } from "node:child_process";
|
||||
import * as fs from "node:fs";
|
||||
import * as os from "node:os";
|
||||
import * as path from "node:path";
|
||||
@@ -154,19 +154,25 @@ function isExecutable(p: string): boolean {
|
||||
function describeBinary(bin: string): PdftotextInfo {
|
||||
let version = "unknown";
|
||||
let flavor: PdftotextInfo["flavor"] = "unknown";
|
||||
try {
|
||||
// pdftotext -v writes to stderr and exits 0 on poppler, 99 on some xpdf builds.
|
||||
const result = execFileSync(bin, ["-v"], {
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
version = (result || "").trim().split("\n")[0] || "unknown";
|
||||
} catch (err: any) {
|
||||
// Many pdftotext builds exit non-zero on -v but still write to stderr.
|
||||
const stderr = err?.stderr?.toString?.() ?? "";
|
||||
version = stderr.trim().split("\n")[0] || "unknown";
|
||||
}
|
||||
const v = version.toLowerCase();
|
||||
|
||||
// spawnSync, not execFileSync: poppler writes -v output to STDERR and exits 0,
|
||||
// so execFileSync neither returns it (it returns stdout, which is empty) nor
|
||||
// throws (which is what made the stderr fallback below reachable). The result
|
||||
// was version="unknown" flavor="unknown" on every poppler install. spawnSync
|
||||
// hands back both streams regardless of exit status, which also covers the
|
||||
// xpdf builds that exit 99.
|
||||
const res = spawnSync(bin, ["-v"], { encoding: "utf8" });
|
||||
const raw = `${res.stdout ?? ""}\n${res.stderr ?? ""}`;
|
||||
|
||||
// The version banner is not reliably the first line once both streams are in
|
||||
// play, so match it rather than taking line 0.
|
||||
const lines = raw.split("\n").map(l => l.trim()).filter(Boolean);
|
||||
version = lines.find(l => /pdftotext\s+version/i.test(l)) ?? lines[0] ?? "unknown";
|
||||
|
||||
// Flavor comes from the WHOLE banner, never the version line alone: poppler
|
||||
// prints "pdftotext version 26.06.0" on line 1 and only identifies itself on
|
||||
// line 2, "Copyright ... The Poppler Developers".
|
||||
const v = raw.toLowerCase();
|
||||
if (v.includes("poppler")) flavor = "poppler";
|
||||
else if (v.includes("xpdf")) flavor = "xpdf";
|
||||
return { bin, version, flavor };
|
||||
|
||||
Reference in New Issue
Block a user