Skip to content

Commit cd22421

Browse files
committed
Merge branch 'mr/fs' into 'master'
Adjust timestamp handling in sync_tree ficlone method See merge request it/e3-core!416
2 parents b526dda + 93e3eb9 commit cd22421

2 files changed

Lines changed: 47 additions & 15 deletions

File tree

src/e3/fs.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,10 +1203,8 @@ def safe_copy_ficlone(src: FileInfo, dst: FileInfo) -> None:
12031203
# If dst was already a file open does not adjust the mode
12041204
os.fchmod(dst_fd, src.stat.st_mode)
12051205

1206-
if not preserve_timestamps and os_utime:
1207-
# By default FICLONE preserve timestamps. So adjust timestamp to now
1208-
# only if preserve_timestamps is False.
1209-
os_utime(dst_fd, None)
1206+
if preserve_timestamps and os_utime:
1207+
os_utime(dst_fd, ns=(src.stat.st_atime_ns, src.stat.st_mtime_ns))
12101208

12111209
except OSError:
12121210
# We will probably have the same issue with all files

tests/tests_e3/fs/main_test.py

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -419,28 +419,62 @@ def test_sync_tree_case_insensitive() -> None:
419419

420420
def test_sync_tree_preserve_timestamps() -> None:
421421
"""Run sync_tree without preserving timestamps."""
422+
# Some filesystem might require some tolerance on
423+
# timestamps
424+
timestamp_tolerance = 2.0
425+
422426
e3.fs.mkdir("a")
423427
e3.fs.mkdir("b")
424-
a_content = Path("a/content")
425-
a_content.write_text("content1")
426-
b_content = Path("b/content")
427-
b_content.write_text("content2")
428-
429428
now = time.time()
430-
os.utime(a_content, (now - 10, now - 10))
431-
os.utime(b_content, (now - 5, now - 5))
432429

430+
# Ensure to do the test on a few files as the sync method
431+
# may change while synchronizing the first files
432+
basenames = ("content1", "content2", "content3", "content4")
433+
for b in basenames:
434+
a_content = Path("a") / b
435+
a_content.write_text("content1")
436+
b_content = Path("b") / b
437+
b_content.write_text("content2")
438+
os.utime(a_content, (now - 10, now - 10))
439+
os.utime(b_content, (now - 7, now - 7))
440+
441+
# First sync should not update b directory as timestamps
442+
# for files in b are newer and size is equal
433443
e3.fs.sync_tree("a", "b", preserve_timestamps=False)
434444

435-
with b_content.open() as f:
436-
assert f.read() == "content2"
445+
for b in basenames:
446+
b_content = Path("b") / b
447+
with b_content.open() as f:
448+
assert f.read() == "content2"
449+
450+
# Update timestamps in a/ to now - 4s
451+
for b in basenames:
452+
a_content = Path("a") / b
453+
os.utime(a_content, (now - 4, now - 4))
437454

438-
os.utime(a_content, (now, now))
455+
# Sync should sync all files and set timestamp to now
439456
e3.fs.sync_tree("a", "b", preserve_timestamps=False)
457+
458+
for b in basenames:
459+
b_content = Path("b") / b
460+
with b_content.open() as f:
461+
assert f.read() == "content1"
462+
assert abs(b_content.stat().st_mtime - time.time()) < timestamp_tolerance
463+
464+
# Reset timestamp to original value and re-run sync with
465+
# timestamp preservation
466+
for b in basenames:
467+
a_content = Path("a") / b
468+
os.utime(a_content, (now - 10.0, now - 10.0))
469+
470+
e3.fs.sync_tree("a", "b", preserve_timestamps=True)
440471
with b_content.open() as f:
441472
assert f.read() == "content1"
442473

443-
assert b_content.stat().st_mtime - now < 2 # noqa: PLR2004
474+
# Check that timestamp is preserved
475+
for b in basenames:
476+
b_content = Path("b") / b
477+
assert abs(b_content.stat().st_mtime - now + 10) < timestamp_tolerance
444478

445479

446480
@pytest.mark.skipif(sys.platform == "win32", reason="win32 does not support full mode")

0 commit comments

Comments
 (0)