Skip to content

fix for ctime and mtime issue #533 and prevents side effect if #532 is implemented - #536

Open
mailinglists35 wants to merge 4 commits into
jmathai:masterfrom
mailinglists35:master
Open

fix for ctime and mtime issue #533 and prevents side effect if #532 is implemented#536
mailinglists35 wants to merge 4 commits into
jmathai:masterfrom
mailinglists35:master

Conversation

@mailinglists35

@mailinglists35 mailinglists35 commented Jul 27, 2026

Copy link
Copy Markdown

note I have no idea what I am doing (Google Gemini/Colab), it works for me, but this needs a real world human programmer review

Google's explanation:


Title: Fix: Prevent source file ctime alteration during import by deferring EXIF writes to destination

Description

Motivation / Root Cause Analysis
During a standard import operation, Elodie was inadvertently violating the read-only assumption of the source payload, leading to an irreversible alteration of the source file's ctime (inode change time) on POSIX systems.

This occurred because media.set_original_name() directly invoked ExifTool to write missing tags into the source file before the copy operation. To mask this mutation, process_file() explicitly called os.utime on the source to restore its original mtime and atime. However, under POSIX semantics, utime is a metadata operation that inherently forces the OS to update the file's inode ctime to the current system time. Restoring the original ctime is impossible via standard unprivileged syscalls, leaving the source file permanently altered at the filesystem level.

Modifications

1. elodie/media/media.py (Architectural Shift):

  • Method Signature Updates: Refactored set_original_name and the internal __set_tags to accept an optional file_path parameter.
  • Targeted Writes: Decoupled the media object's source property from the tag-writing destination. This allows the application to write the original_name tag directly to the destination file after the copy, leaving the source file physically untouched.

2. elodie/filesystem.py (Process Flow Optimization):

  • Deferred Tagging: Removed the premature call to media.set_original_name() that occurred while the source file was being initially processed.
  • Read-Only Copying: Modified the else block (standard copy-on-import) to perform a straight copy without prior EXIF tag injections.
  • Side-Effect Elimination: Completely eradicated the os.utime(_file, ...) cleanup call targeting the source path. Instead, the logic now invokes media.set_original_name(file_path=dest_path), ensuring all metadata modification and timestamp synchronizations are strictly localized to the newly created file in the destination directory.

Outcome
The source media file is now treated as strictly immutable by the importer, ensuring full data integrity and nanosecond-accurate ctime/mtime preservation for archival workflows. Validated via stat and verified against media and filesystem test suites with no regressions.


Title: Fix: Restore original mtime/atime clobbered by deferred EXIF writes (with nanosecond precision)

Description

Motivation / Root Cause Analysis
This patch resolves a critical side-effect introduced by the architectural shift that protects the source file's ctime.

To ensure the source file remains strictly read-only, EXIF tag injections (like original_name) were deferred to the destination file after the copy/move operation. However, invoking ExifTool to write these tags inherently clobbers the destination file's modification time (mtime) and access time (atime), updating them to the exact moment the script is executed. Without explicit restoration, the destination file completely loses its historical modification timestamp.

Modifications

elodie/filesystem.py (Absolute Temporal Restoration):

  • State Snapshot Recovery: Relies strictly on stat_info_original—the absolute baseline state captured at the very entry point of process_file(), before any plugins, reads, or deferred EXIF writes can pollute the temporal attributes.
  • Overriding EXIF Side-Effects: Introduced explicit os.utime syscalls immediately following the copy and move operations to forcibly revert the destination file back to its true historical state, erasing the temporal footprint of the ExifTool execution.
  • Nanosecond Precision (ns=): Leveraged stat_info_original.st_atime_ns and stat_info_original.st_mtime_ns via the ns= keyword argument. This bypasses standard floating-point translation and utilizes the underlying utimensat POSIX syscall for mathematically perfect time replication, preventing the sub-second truncation often seen in standard shutil operations.

Outcome
The destination payload now inherits the exact, unmodified historical timestamps of the original source file. It successfully survives both the massive mtime overwrite caused by deferred metadata writes and the micro-second truncation inherent to standard filesystem I/O operations.

…mathai#532 is implemented

note I have no idea what I am doing (Google Gemini/Colab), it works for me,
but this needs a *real world human programmer* review
@CLAassistant

CLAassistant commented Jul 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

- Treat composite full_path segments as custom masks
- Expand %<name> placeholders from Directory inside location/custom masks
- Add unit tests for month-in-location and custom month+location
…cation masks

- Replace naive .replace() loops with re.sub callbacks to avoid partial overlaps
- Ensure %month expands to full value (02) without leaving 'onth' tail
…e-placeholders

Fix: Expand Directory placeholders inside custom/location masks (handle composite masks like %month, %country, %city) issue jmathai#534
@mailinglists35

Copy link
Copy Markdown
Author

sorry it seems that while I fixed another issue in my fork, it somehow reflected in this PR. they should normally belong in separate PR. the other fixes are for #534 and another bug discovered when %month together with something else becomes [0-9][0-9]onth

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants