Module: Metaclean::Qpdf
- Defined in:
- lib/metaclean/qpdf.rb
Class Method Summary collapse
- .available? ⇒ Boolean
-
.rebuild!(path) ⇒ Object
Rebuilds a PDF in place.
- .version ⇒ Object
Class Method Details
.available? ⇒ Boolean
20 21 22 23 24 25 26 27 |
# File 'lib/metaclean/qpdf.rb', line 20 def available? return @available if defined?(@available) _out, _err, status = Open3.capture3('qpdf', '--version') @available = status.success? rescue Errno::ENOENT @available = false end |
.rebuild!(path) ⇒ Object
Rebuilds a PDF in place. The qpdf flags here:
--linearize → optimize for streaming/web
--object-streams=generate → bundle objects efficiently
--remove-unreferenced-resources=yes → drop unused content (the
privacy-relevant part!)
qpdf can’t write back to the same file, so we use the standard “atomic write” pattern: write to a temp file, then rename it on top of the original. ‘File.rename` (used internally by `FileUtils.mv` for same-filesystem moves) is atomic on POSIX — either the swap completes or nothing changes. No “half-written” state is ever visible.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/metaclean/qpdf.rb', line 51 def rebuild!(path) raise Error, 'qpdf not available' unless available? # Including `Process.pid` in the temp name avoids collisions if two # metaclean processes happen to run at the same time on shared storage. tmp = "#{path}.qpdf.tmp.#{Process.pid}" _out, err, status = Open3.capture3( 'qpdf', '--linearize', '--object-streams=generate', '--remove-unreferenced-resources=yes', path.to_s, tmp ) # qpdf has a quirk: exit code 3 means "succeeded with warnings" (output # is still produced and valid). We treat that the same as success. success = status.success? || status.exitstatus == 3 unless success File.delete(tmp) if File.exist?(tmp) raise Error, "qpdf failed: #{err.strip}" end FileUtils.mv(tmp, path.to_s) true end |
.version ⇒ Object
29 30 31 32 33 34 35 36 37 38 |
# File 'lib/metaclean/qpdf.rb', line 29 def version return nil unless available? out, _err, status = Open3.capture3('qpdf', '--version') # `qpdf --version` prints multiple lines starting with the version line. # `.lines.first` grabs only that line. status.success? ? out.lines.first.to_s.strip : nil rescue Errno::ENOENT nil end |