PyHardLinkBackup 1.4.0__tar.gz → 1.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PKG-INFO +6 -4
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/__init__.py +1 -1
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/backup.py +2 -1
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_backup.py +93 -61
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/README.md +5 -3
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.editorconfig +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.github/workflows/tests.yml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.gitignore +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.idea/.gitignore +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.pre-commit-config.yaml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.pre-commit-hooks.yaml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.run/Template Python tests.run.xml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.run/Unittests - __all__.run.xml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.run/cli.py --help.run.xml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.run/dev-cli update.run.xml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.run/only DocTests.run.xml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.run/only DocWrite.run.xml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/.venv-app/lib/python3.12/site-packages/cli_base/tests/shell_complete_snapshots/.gitignore +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/__main__.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_app/__init__.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_app/phlb.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/__init__.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/benchmark.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/code_style.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/packaging.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/shell_completion.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/testing.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/update_readme_history.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/constants.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/logging_setup.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/rebuild_databases.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/__init__.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_doc_write.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_doctests.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_project_setup.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_readme.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_readme_history.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_rebuild_database.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/__init__.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/file_hash_database.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/file_size_database.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/filesystem.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/humanize.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/rich_utils.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/sha256sums.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tee.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tests/__init__.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tests/test_file_hash_database.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tests/test_file_size_database.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tests/test_filesystem.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tyro_cli_shared_args.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/cli.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/dev-cli.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/dist/.gitignore +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/docs/README.md +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/docs/about-docs.md +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/noxfile.py +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/pyproject.toml +0 -0
- {pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyHardLinkBackup
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: HardLink/Deduplication Backups with Python
|
|
5
5
|
Project-URL: Documentation, https://github.com/jedie/PyHardLinkBackup
|
|
6
6
|
Project-URL: Source, https://github.com/jedie/PyHardLinkBackup
|
|
@@ -231,6 +231,8 @@ Overview of main changes:
|
|
|
231
231
|
|
|
232
232
|
[comment]: <> (✂✂✂ auto generated history start ✂✂✂)
|
|
233
233
|
|
|
234
|
+
* [v1.4.1](https://github.com/jedie/PyHardLinkBackup/compare/v1.4.0...v1.4.1)
|
|
235
|
+
* 2026-01-16 - Bugfix large file handling
|
|
234
236
|
* [v1.4.0](https://github.com/jedie/PyHardLinkBackup/compare/v1.3.0...v1.4.0)
|
|
235
237
|
* 2026-01-16 - Create log file in backup and a summary.txt
|
|
236
238
|
* 2026-01-16 - Run CI tests on macos, too.
|
|
@@ -247,12 +249,12 @@ Overview of main changes:
|
|
|
247
249
|
* 2026-01-14 - Enhance progress bars
|
|
248
250
|
* 2026-01-14 - A a note to rsync --link-dest
|
|
249
251
|
* 2026-01-14 - Use cli_base.cli_tools.test_utils.base_testcases
|
|
250
|
-
* [v1.1.0](https://github.com/jedie/PyHardLinkBackup/compare/v1.0.1...v1.1.0)
|
|
251
|
-
* 2026-01-14 - Change backup timestamp directory to old schema: '%Y-%m-%d-%H%M%S'
|
|
252
|
-
* 2026-01-14 - Add "Overview of main changes" to README
|
|
253
252
|
|
|
254
253
|
<details><summary>Expand older history entries ...</summary>
|
|
255
254
|
|
|
255
|
+
* [v1.1.0](https://github.com/jedie/PyHardLinkBackup/compare/v1.0.1...v1.1.0)
|
|
256
|
+
* 2026-01-14 - Change backup timestamp directory to old schema: '%Y-%m-%d-%H%M%S'
|
|
257
|
+
* 2026-01-14 - Add "Overview of main changes" to README
|
|
256
258
|
* [v1.0.1](https://github.com/jedie/PyHardLinkBackup/compare/v1.0.0...v1.0.1)
|
|
257
259
|
* 2026-01-13 - Store SHA256SUMS files in backup directories
|
|
258
260
|
* [v1.0.0](https://github.com/jedie/PyHardLinkBackup/compare/v0.13.0...v1.0.0)
|
|
@@ -138,12 +138,13 @@ def backup_one_file(
|
|
|
138
138
|
backup_result.hardlinked_size += size
|
|
139
139
|
else:
|
|
140
140
|
logger.info('Copy unique file: %s to %s', src_path, dst_path)
|
|
141
|
+
file_hash = copy_and_hash(src_path, dst_path)
|
|
141
142
|
hash_db[file_hash] = dst_path
|
|
142
143
|
backup_result.copied_files += 1
|
|
143
144
|
backup_result.copied_size += size
|
|
144
145
|
|
|
145
146
|
# Keep original file metadata (permission bits, time stamps, and flags)
|
|
146
|
-
shutil.
|
|
147
|
+
shutil.copystat(src_path, dst_path)
|
|
147
148
|
else:
|
|
148
149
|
# A file with this size not backuped before -> Can't be duplicate -> copy and hash
|
|
149
150
|
file_hash = copy_and_hash(src_path, dst_path)
|
|
@@ -144,16 +144,13 @@ class BackupTreeTestCase(
|
|
|
144
144
|
(sub_dir / 'file.txt').write_text('This is file in subdir')
|
|
145
145
|
|
|
146
146
|
# Only files bigger than MIN_SIZE will be considered for hardlinking:
|
|
147
|
-
|
|
148
|
-
size_db_min_file.write_bytes(b'X' * FileSizeDatabase.MIN_SIZE)
|
|
147
|
+
(src_root / 'min_sized_file1.bin').write_bytes(b'X' * FileSizeDatabase.MIN_SIZE)
|
|
149
148
|
|
|
150
149
|
# Same content and big enough to be considered for hardlinking:
|
|
151
|
-
|
|
152
|
-
size_db_min_file.write_bytes(b'X' * FileSizeDatabase.MIN_SIZE)
|
|
150
|
+
(src_root / 'min_sized_file2.bin').write_bytes(b'X' * FileSizeDatabase.MIN_SIZE)
|
|
153
151
|
|
|
154
152
|
# Larger then CHUNK_SIZE file will be handled differently:
|
|
155
|
-
|
|
156
|
-
large_file.write_bytes(b'Y' * (CHUNK_SIZE + 1))
|
|
153
|
+
(src_root / 'large_file1.bin').write_bytes(b'Y' * (CHUNK_SIZE + 1))
|
|
157
154
|
|
|
158
155
|
excluded_dir = src_root / '.cache'
|
|
159
156
|
excluded_dir.mkdir()
|
|
@@ -176,7 +173,7 @@ class BackupTreeTestCase(
|
|
|
176
173
|
backup_root=backup_root,
|
|
177
174
|
excludes=('.cache',),
|
|
178
175
|
log_manager=LoggingManager(
|
|
179
|
-
console_level=
|
|
176
|
+
console_level='info',
|
|
180
177
|
file_level=DEFAULT_LOG_FILE_LEVEL,
|
|
181
178
|
),
|
|
182
179
|
)
|
|
@@ -208,6 +205,7 @@ class BackupTreeTestCase(
|
|
|
208
205
|
copied_small_size=50,
|
|
209
206
|
error_count=0,
|
|
210
207
|
),
|
|
208
|
+
redirected_out.stdout,
|
|
211
209
|
)
|
|
212
210
|
|
|
213
211
|
# The sources:
|
|
@@ -219,7 +217,7 @@ class BackupTreeTestCase(
|
|
|
219
217
|
.cache/tempfile.tmp 12:00:00 file 1 38 41d7a2c9
|
|
220
218
|
file2.txt 12:00:00 hardlink 2 14 8a11514a
|
|
221
219
|
hardlink2file1 12:00:00 hardlink 2 14 8a11514a
|
|
222
|
-
|
|
220
|
+
large_file1.bin 12:00:00 file 1 67108865 9671eaac
|
|
223
221
|
min_sized_file1.bin 12:00:00 file 1 1000 f0d93de4
|
|
224
222
|
min_sized_file2.bin 12:00:00 file 1 1000 f0d93de4
|
|
225
223
|
subdir/file.txt 12:00:00 file 1 22 c0167e63
|
|
@@ -234,10 +232,10 @@ class BackupTreeTestCase(
|
|
|
234
232
|
root=backup_dir,
|
|
235
233
|
expected_overview="""
|
|
236
234
|
path birthtime type nlink size CRC32
|
|
237
|
-
SHA256SUMS <mock> file 1
|
|
235
|
+
SHA256SUMS <mock> file 1 411 b02da51e
|
|
238
236
|
file2.txt 12:00:00 file 1 14 8a11514a
|
|
239
237
|
hardlink2file1 12:00:00 file 1 14 8a11514a
|
|
240
|
-
|
|
238
|
+
large_file1.bin 12:00:00 file 1 67108865 9671eaac
|
|
241
239
|
min_sized_file1.bin 12:00:00 hardlink 2 1000 f0d93de4
|
|
242
240
|
min_sized_file2.bin 12:00:00 hardlink 2 1000 f0d93de4
|
|
243
241
|
subdir/SHA256SUMS <mock> file 1 75 1af5ecc7
|
|
@@ -252,12 +250,31 @@ class BackupTreeTestCase(
|
|
|
252
250
|
backup_root=backup_root,
|
|
253
251
|
expected="""
|
|
254
252
|
bb/c4/bbc4de2ca238d1… -> source/2026-01-01-123456/min_sized_file1.bin
|
|
255
|
-
e6/37/e6374ac11d9049… -> source/2026-01-01-123456/
|
|
253
|
+
e6/37/e6374ac11d9049… -> source/2026-01-01-123456/large_file1.bin
|
|
256
254
|
""",
|
|
257
255
|
)
|
|
258
256
|
|
|
259
257
|
#######################################################################################
|
|
260
|
-
#
|
|
258
|
+
# Backup again with new added files:
|
|
259
|
+
|
|
260
|
+
# New small file with different size and different content:
|
|
261
|
+
(src_root / 'small_file_newA.txt').write_text('A new file')
|
|
262
|
+
|
|
263
|
+
# Add small file that size exists, but has different content:
|
|
264
|
+
(src_root / 'small_file_newB.txt').write_text('This is file 2')
|
|
265
|
+
|
|
266
|
+
# Bigger file with new size and new content:
|
|
267
|
+
(src_root / 'min_sized_file_newA.bin').write_bytes(b'A' * (FileSizeDatabase.MIN_SIZE + 1))
|
|
268
|
+
|
|
269
|
+
# Bigger file with existing size, but different content:
|
|
270
|
+
(src_root / 'min_sized_file_newB.bin').write_bytes(b'B' * FileSizeDatabase.MIN_SIZE)
|
|
271
|
+
|
|
272
|
+
# Add a larger then CHUNK_SIZE file with same existing size, but different content:
|
|
273
|
+
(src_root / 'large_file2.bin').write_bytes(b'Y' * (CHUNK_SIZE + 1))
|
|
274
|
+
|
|
275
|
+
# FIXME: freezegun doesn't handle this, see: https://github.com/spulec/freezegun/issues/392
|
|
276
|
+
# Set modification times to a fixed time for easier testing:
|
|
277
|
+
set_file_times(src_root, dt=parse_dt('2026-01-01T12:00:00+0000'))
|
|
261
278
|
|
|
262
279
|
with (
|
|
263
280
|
patch('PyHardLinkBackup.backup.iter_scandir_files', SortedIterScandirFiles),
|
|
@@ -269,7 +286,7 @@ class BackupTreeTestCase(
|
|
|
269
286
|
backup_root=backup_root,
|
|
270
287
|
excludes=('.cache',),
|
|
271
288
|
log_manager=LoggingManager(
|
|
272
|
-
console_level=
|
|
289
|
+
console_level='info',
|
|
273
290
|
file_level=DEFAULT_LOG_FILE_LEVEL,
|
|
274
291
|
),
|
|
275
292
|
)
|
|
@@ -280,23 +297,6 @@ class BackupTreeTestCase(
|
|
|
280
297
|
str(Path(backup_dir).relative_to(temp_path)),
|
|
281
298
|
'backup/source/2026-01-02-123456',
|
|
282
299
|
)
|
|
283
|
-
self.assertEqual(
|
|
284
|
-
result,
|
|
285
|
-
BackupResult(
|
|
286
|
-
backup_dir=backup_dir,
|
|
287
|
-
log_file=result.log_file,
|
|
288
|
-
backup_count=7,
|
|
289
|
-
backup_size=67110929,
|
|
290
|
-
symlink_files=1,
|
|
291
|
-
hardlinked_files=3, # <<< More hardlinks this time!
|
|
292
|
-
hardlinked_size=67110865,
|
|
293
|
-
copied_files=3,
|
|
294
|
-
copied_size=50,
|
|
295
|
-
copied_small_files=3,
|
|
296
|
-
copied_small_size=50,
|
|
297
|
-
error_count=0,
|
|
298
|
-
),
|
|
299
|
-
)
|
|
300
300
|
# The second backup:
|
|
301
301
|
# * /.cache/ -> excluded
|
|
302
302
|
# * min_sized_file1.bin and min_sized_file2.bin -> hardlinked
|
|
@@ -304,26 +304,51 @@ class BackupTreeTestCase(
|
|
|
304
304
|
assert_fs_tree_overview(
|
|
305
305
|
root=backup_dir,
|
|
306
306
|
expected_overview="""
|
|
307
|
-
path
|
|
308
|
-
SHA256SUMS
|
|
309
|
-
file2.txt
|
|
310
|
-
hardlink2file1
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
307
|
+
path birthtime type nlink size CRC32
|
|
308
|
+
SHA256SUMS <mock> file 1 845 6596856a
|
|
309
|
+
file2.txt 12:00:00 file 1 14 8a11514a
|
|
310
|
+
hardlink2file1 12:00:00 file 1 14 8a11514a
|
|
311
|
+
large_file1.bin 12:00:00 hardlink 3 67108865 9671eaac
|
|
312
|
+
large_file2.bin 12:00:00 hardlink 3 67108865 9671eaac
|
|
313
|
+
min_sized_file1.bin 12:00:00 hardlink 4 1000 f0d93de4
|
|
314
|
+
min_sized_file2.bin 12:00:00 hardlink 4 1000 f0d93de4
|
|
315
|
+
min_sized_file_newA.bin 12:00:00 file 1 1001 a48f0e33
|
|
316
|
+
min_sized_file_newB.bin 12:00:00 file 1 1000 7d9c564d
|
|
317
|
+
small_file_newA.txt 12:00:00 file 1 10 76d1acf1
|
|
318
|
+
small_file_newB.txt 12:00:00 file 1 14 131800f0
|
|
319
|
+
subdir/SHA256SUMS <mock> file 1 75 1af5ecc7
|
|
320
|
+
subdir/file.txt 12:00:00 file 1 22 c0167e63
|
|
321
|
+
symlink2file1 12:00:00 symlink 2 14 8a11514a
|
|
317
322
|
""",
|
|
318
323
|
)
|
|
324
|
+
self.assertEqual(
|
|
325
|
+
result,
|
|
326
|
+
BackupResult(
|
|
327
|
+
backup_dir=backup_dir,
|
|
328
|
+
log_file=result.log_file,
|
|
329
|
+
backup_count=12,
|
|
330
|
+
backup_size=134221819,
|
|
331
|
+
symlink_files=1,
|
|
332
|
+
hardlinked_files=4,
|
|
333
|
+
hardlinked_size=134219730,
|
|
334
|
+
copied_files=7,
|
|
335
|
+
copied_size=2075,
|
|
336
|
+
copied_small_files=5,
|
|
337
|
+
copied_small_size=74,
|
|
338
|
+
error_count=0,
|
|
339
|
+
),
|
|
340
|
+
redirected_out.stdout,
|
|
341
|
+
)
|
|
319
342
|
|
|
320
343
|
# The FileHashDatabase remains the same:
|
|
321
344
|
with self.assertLogs('PyHardLinkBackup', level=logging.DEBUG):
|
|
322
345
|
assert_hash_db_info(
|
|
323
346
|
backup_root=backup_root,
|
|
324
347
|
expected="""
|
|
348
|
+
23/d2/23d2ce40d26211… -> source/2026-01-02-123456/min_sized_file_newA.bin
|
|
349
|
+
9a/56/9a567077114134… -> source/2026-01-02-123456/min_sized_file_newB.bin
|
|
325
350
|
bb/c4/bbc4de2ca238d1… -> source/2026-01-01-123456/min_sized_file1.bin
|
|
326
|
-
e6/37/e6374ac11d9049… -> source/2026-01-01-123456/
|
|
351
|
+
e6/37/e6374ac11d9049… -> source/2026-01-01-123456/large_file1.bin
|
|
327
352
|
""",
|
|
328
353
|
)
|
|
329
354
|
|
|
@@ -365,16 +390,21 @@ class BackupTreeTestCase(
|
|
|
365
390
|
assert_fs_tree_overview(
|
|
366
391
|
root=backup_dir,
|
|
367
392
|
expected_overview="""
|
|
368
|
-
path
|
|
369
|
-
SHA256SUMS
|
|
370
|
-
file2.txt
|
|
371
|
-
hardlink2file1
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
393
|
+
path birthtime type nlink size CRC32
|
|
394
|
+
SHA256SUMS <mock> file 1 845 6596856a
|
|
395
|
+
file2.txt 12:00:00 file 1 14 8a11514a
|
|
396
|
+
hardlink2file1 12:00:00 file 1 14 8a11514a
|
|
397
|
+
large_file1.bin 12:00:00 hardlink 5 67108865 9671eaac
|
|
398
|
+
large_file2.bin 12:00:00 hardlink 5 67108865 9671eaac
|
|
399
|
+
min_sized_file1.bin 12:00:00 hardlink 2 1000 f0d93de4
|
|
400
|
+
min_sized_file2.bin 12:00:00 hardlink 2 1000 f0d93de4
|
|
401
|
+
min_sized_file_newA.bin 12:00:00 hardlink 2 1001 a48f0e33
|
|
402
|
+
min_sized_file_newB.bin 12:00:00 hardlink 2 1000 7d9c564d
|
|
403
|
+
small_file_newA.txt 12:00:00 file 1 10 76d1acf1
|
|
404
|
+
small_file_newB.txt 12:00:00 file 1 14 131800f0
|
|
405
|
+
subdir/SHA256SUMS <mock> file 1 75 1af5ecc7
|
|
406
|
+
subdir/file.txt 12:00:00 file 1 22 c0167e63
|
|
407
|
+
symlink2file1 12:00:00 symlink 2 14 8a11514a
|
|
378
408
|
""",
|
|
379
409
|
)
|
|
380
410
|
|
|
@@ -383,16 +413,16 @@ class BackupTreeTestCase(
|
|
|
383
413
|
BackupResult(
|
|
384
414
|
backup_dir=backup_dir,
|
|
385
415
|
log_file=result.log_file,
|
|
386
|
-
backup_count=
|
|
387
|
-
backup_size=
|
|
416
|
+
backup_count=12,
|
|
417
|
+
backup_size=134221819,
|
|
388
418
|
symlink_files=1,
|
|
389
|
-
hardlinked_files=
|
|
390
|
-
hardlinked_size=
|
|
391
|
-
copied_files=
|
|
392
|
-
copied_size=
|
|
393
|
-
copied_small_files=
|
|
394
|
-
copied_small_size=
|
|
395
|
-
error_count=0
|
|
419
|
+
hardlinked_files=5,
|
|
420
|
+
hardlinked_size=134220731,
|
|
421
|
+
copied_files=6,
|
|
422
|
+
copied_size=1074,
|
|
423
|
+
copied_small_files=5,
|
|
424
|
+
copied_small_size=74,
|
|
425
|
+
error_count=0
|
|
396
426
|
),
|
|
397
427
|
)
|
|
398
428
|
|
|
@@ -402,8 +432,10 @@ class BackupTreeTestCase(
|
|
|
402
432
|
assert_hash_db_info(
|
|
403
433
|
backup_root=backup_root,
|
|
404
434
|
expected="""
|
|
435
|
+
23/d2/23d2ce40d26211… -> source/2026-01-02-123456/min_sized_file_newA.bin
|
|
436
|
+
9a/56/9a567077114134… -> source/2026-01-02-123456/min_sized_file_newB.bin
|
|
405
437
|
bb/c4/bbc4de2ca238d1… -> source/2026-01-03-123456/min_sized_file1.bin
|
|
406
|
-
e6/37/e6374ac11d9049… -> source/2026-01-01-123456/
|
|
438
|
+
e6/37/e6374ac11d9049… -> source/2026-01-01-123456/large_file1.bin
|
|
407
439
|
""",
|
|
408
440
|
)
|
|
409
441
|
|
|
@@ -216,6 +216,8 @@ Overview of main changes:
|
|
|
216
216
|
|
|
217
217
|
[comment]: <> (✂✂✂ auto generated history start ✂✂✂)
|
|
218
218
|
|
|
219
|
+
* [v1.4.1](https://github.com/jedie/PyHardLinkBackup/compare/v1.4.0...v1.4.1)
|
|
220
|
+
* 2026-01-16 - Bugfix large file handling
|
|
219
221
|
* [v1.4.0](https://github.com/jedie/PyHardLinkBackup/compare/v1.3.0...v1.4.0)
|
|
220
222
|
* 2026-01-16 - Create log file in backup and a summary.txt
|
|
221
223
|
* 2026-01-16 - Run CI tests on macos, too.
|
|
@@ -232,12 +234,12 @@ Overview of main changes:
|
|
|
232
234
|
* 2026-01-14 - Enhance progress bars
|
|
233
235
|
* 2026-01-14 - A a note to rsync --link-dest
|
|
234
236
|
* 2026-01-14 - Use cli_base.cli_tools.test_utils.base_testcases
|
|
235
|
-
* [v1.1.0](https://github.com/jedie/PyHardLinkBackup/compare/v1.0.1...v1.1.0)
|
|
236
|
-
* 2026-01-14 - Change backup timestamp directory to old schema: '%Y-%m-%d-%H%M%S'
|
|
237
|
-
* 2026-01-14 - Add "Overview of main changes" to README
|
|
238
237
|
|
|
239
238
|
<details><summary>Expand older history entries ...</summary>
|
|
240
239
|
|
|
240
|
+
* [v1.1.0](https://github.com/jedie/PyHardLinkBackup/compare/v1.0.1...v1.1.0)
|
|
241
|
+
* 2026-01-14 - Change backup timestamp directory to old schema: '%Y-%m-%d-%H%M%S'
|
|
242
|
+
* 2026-01-14 - Add "Overview of main changes" to README
|
|
241
243
|
* [v1.0.1](https://github.com/jedie/PyHardLinkBackup/compare/v1.0.0...v1.0.1)
|
|
242
244
|
* 2026-01-13 - Store SHA256SUMS files in backup directories
|
|
243
245
|
* [v1.0.0](https://github.com/jedie/PyHardLinkBackup/compare/v0.13.0...v1.0.0)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/shell_completion.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/cli_dev/update_readme_history.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_project_setup.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_readme_history.py
RENAMED
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/tests/test_rebuild_database.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/file_hash_database.py
RENAMED
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/file_size_database.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tests/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyhardlinkbackup-1.4.0 → pyhardlinkbackup-1.4.1}/PyHardLinkBackup/utilities/tyro_cli_shared_args.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|