Skip to content

fix: keep attribute preservation best-effort when os.utime fails#180

Open
seonghobae wants to merge 1 commit into
mainfrom
fix/metadata-preservation
Open

fix: keep attribute preservation best-effort when os.utime fails#180
seonghobae wants to merge 1 commit into
mainfrom
fix/metadata-preservation

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Problem

preserve_file_attributes promises best-effort semantics in its docstring — "Non-critical metadata copy failures are ignored so a completed conversion is not lost" — and guards os.chmod and the extended-attribute copy accordingly.

But the two os.utime calls that restore nanosecond atime/mtime were unguarded. On a destination that rejects utime (a read-only filesystem, or one without timestamp support) os.utime raises OSError, which propagates up through convert_file at the preserve_file_attributes(source, first_result) call site — discarding an otherwise completed conversion, and skipping the macOS creation-time restore that runs afterward.

Fix

Extract the timestamp restore into a _restore_timestamps helper that swallows OSError, matching the best-effort guards already used for chmod and xattrs. Both restore points now use it.

Test

Added test_preserve_file_attributes_ignores_utime_error, which patches os.utime to raise OSError and asserts that preserve_file_attributes:

  • does not raise, and
  • still invokes the macOS creation-time step (best-effort continues).

The test fails on the current code (OSError propagates) and passes with the fix.

Gates

  • coverage report --include=media_shrinker.py: 100%
  • interrogate media_shrinker.py: 100%
  • Full suite: 5 pre-existing macOS os.listxattr errors unchanged (all in _copy_extended_attributes tests, untouched here); no new failures.

🤖 Generated with Claude Code

preserve_file_attributes documents best-effort semantics ("failures are
ignored so a completed conversion is not lost"), and guards chmod and the
xattr copy accordingly. The two os.utime calls that restore nanosecond
atime/mtime were unguarded, so an OSError (read-only destination, a
filesystem without timestamp support) propagated up through convert_file
and discarded an otherwise completed conversion — and skipped the macOS
creation-time restore.

Extract the utime restore into a _restore_timestamps helper that swallows
OSError, matching the surrounding best-effort guards. Add a regression
test that patches os.utime to raise and asserts the copy neither raises
nor skips the creation-time step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJRVbDrp1vGYkJgNHMGPpG
@seonghobae seonghobae enabled auto-merge (squash) July 6, 2026 14:26
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.

1 participant