From ae123fd20994d649388ed0e297ff0233b534aed0 Mon Sep 17 00:00:00 2001 From: "James R. Barlow" Date: Sat, 28 Oct 2023 01:42:06 -0700 Subject: [PATCH] Try to retain/copy xattrs --- src/ocrmypdf/_pipeline.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/ocrmypdf/_pipeline.py b/src/ocrmypdf/_pipeline.py index 44bd88c9..efb7e20d 100644 --- a/src/ocrmypdf/_pipeline.py +++ b/src/ocrmypdf/_pipeline.py @@ -14,7 +14,7 @@ from collections.abc import Iterable, Iterator, Sequence from contextlib import suppress from datetime import datetime, timezone from pathlib import Path -from shutil import copyfileobj +from shutil import copyfileobj, copystat from typing import Any, BinaryIO, TypeVar, cast import img2pdf @@ -1090,14 +1090,14 @@ def merge_sidecars(txt_files: Iterable[Path | None], context: PdfContext) -> Pat def copy_final( - input_file: Path, output_file: str | Path | BinaryIO, _context: PdfContext + input_file: Path, output_file: str | Path | BinaryIO, context: PdfContext ) -> None: """Copy the final temporary file to the output destination. Args: - input_file (Path): The input file to copy. + input_file (Path): The intermediate input file to copy. output_file (str | Path | BinaryIO): The output file to copy to. - _context (PdfContext): The PDF context. + context (PdfContext): The PDF context. Returns: None @@ -1116,5 +1116,11 @@ def copy_final( # At this point we overwrite the output_file specified by the user # use copyfileobj because then we use open() to create the file and # get the appropriate umask, ownership, etc. - with open(output_file, 'wb') as output_stream: + with open(output_file, 'w+b') as output_stream: copyfileobj(input_stream, output_stream) + # Attempt to copy file attributes from input to output + with suppress(OSError): + # Copy original file's permissions, ownership, etc. if possible + copystat(context.options.input_file, output_file) + # Set output file's modification time to now + Path(output_file).touch(exist_ok=True)