|
@@ -1,12 +1,20 @@
|
|
|
import json
|
|
|
import os
|
|
|
+from pathlib import Path
|
|
|
import stat
|
|
|
import time
|
|
|
|
|
|
from ...constants import * # NOQA
|
|
|
from .. import are_symlinks_supported, are_hardlinks_supported
|
|
|
from ...platformflags import is_win32, is_darwin
|
|
|
-from . import cmd, create_regular_file, RK_ENCRYPTION, assert_line_exists, generate_archiver_tests
|
|
|
+from . import (
|
|
|
+ cmd,
|
|
|
+ create_regular_file,
|
|
|
+ RK_ENCRYPTION,
|
|
|
+ assert_line_exists,
|
|
|
+ generate_archiver_tests,
|
|
|
+ assert_line_not_exists,
|
|
|
+)
|
|
|
|
|
|
pytest_generate_tests = lambda metafunc: generate_archiver_tests(metafunc, kinds="local,remote,binary") # NOQA
|
|
|
|
|
@@ -19,6 +27,7 @@ def test_basic_functionality(archivers, request):
|
|
|
create_regular_file(archiver.input_path, "file_removed", size=256)
|
|
|
create_regular_file(archiver.input_path, "file_removed2", size=512)
|
|
|
create_regular_file(archiver.input_path, "file_replaced", size=1024)
|
|
|
+ create_regular_file(archiver.input_path, "file_touched", size=128)
|
|
|
os.mkdir("input/dir_replaced_with_file")
|
|
|
os.chmod("input/dir_replaced_with_file", stat.S_IFDIR | 0o755)
|
|
|
os.mkdir("input/dir_removed")
|
|
@@ -44,6 +53,7 @@ def test_basic_functionality(archivers, request):
|
|
|
create_regular_file(archiver.input_path, "file_replaced", contents=b"0" * 4096)
|
|
|
os.unlink("input/file_removed")
|
|
|
os.unlink("input/file_removed2")
|
|
|
+ Path("input/file_touched").touch()
|
|
|
os.rmdir("input/dir_replaced_with_file")
|
|
|
create_regular_file(archiver.input_path, "dir_replaced_with_file", size=8192)
|
|
|
os.chmod("input/dir_replaced_with_file", stat.S_IFREG | 0o755)
|
|
@@ -102,6 +112,15 @@ def test_basic_functionality(archivers, request):
|
|
|
# pointing to the file is not changed.
|
|
|
change = "modified.*0 B" if can_compare_ids else r"modified: \(can't get size\)"
|
|
|
assert_line_exists(lines, f"{change}.*input/empty")
|
|
|
+
|
|
|
+ # Do not show a 0 byte change for a file whose contents weren't modified.
|
|
|
+ assert_line_not_exists(lines, "0 B.*input/file_touched")
|
|
|
+ if not content_only:
|
|
|
+ assert_line_exists(lines, "[cm]time:.*input/file_touched")
|
|
|
+ else:
|
|
|
+ # And if we're doing content-only, don't show the file at all.
|
|
|
+ assert "input/file_touched" not in output
|
|
|
+
|
|
|
if are_hardlinks_supported():
|
|
|
assert_line_exists(lines, f"{change}.*input/hardlink_contents_changed")
|
|
|
if are_symlinks_supported():
|
|
@@ -150,6 +169,17 @@ def test_basic_functionality(archivers, request):
|
|
|
# File unchanged
|
|
|
assert not any(get_changes("input/file_unchanged", joutput))
|
|
|
|
|
|
+ # Do not show a 0 byte change for a file whose contents weren't modified.
|
|
|
+ unexpected = {"type": "modified", "added": 0, "removed": 0}
|
|
|
+ assert unexpected not in get_changes("input/file_touched", joutput)
|
|
|
+ if not content_only:
|
|
|
+ # on win32, ctime is the file creation time and does not change.
|
|
|
+ expected = {"mtime"} if is_win32 else {"mtime", "ctime"}
|
|
|
+ assert expected.issubset({c["type"] for c in get_changes("input/file_touched", joutput)})
|
|
|
+ else:
|
|
|
+ # And if we're doing content-only, don't show the file at all.
|
|
|
+ assert not any(get_changes("input/file_touched", joutput))
|
|
|
+
|
|
|
# Directory replaced with a regular file
|
|
|
if "BORG_TESTS_IGNORE_MODES" not in os.environ and not is_win32 and not content_only:
|
|
|
assert {"type": "changed mode", "item1": "drwxr-xr-x", "item2": "-rwxr-xr-x"} in get_changes(
|