1313import subprocess
1414import threading
1515import time
16+ from datetime import datetime , timedelta
1617from enum import Enum
1718from pathlib import Path
1819from typing import Awaitable , Callable , List , NamedTuple
@@ -63,6 +64,8 @@ def __init__(
6364 remove_files : bool = False ,
6465 required_substrings_for_removal : List [str ] = [],
6566 notify : bool = True ,
67+ end_time : datetime | None = None ,
68+ grace_period : int = 0 ,
6669 ):
6770 super ().__init__ ()
6871 self ._basepath = basepath_local .absolute ()
@@ -76,6 +79,10 @@ def __init__(
7679 self ._server_url = server_url
7780 self ._notify = notify
7881 self ._finalised = False
82+ self ._end_time = end_time
83+ self ._grace_period = grace_period
84+
85+ self ._skipped_files : List [Path ] = []
7986
8087 # Set rsync destination
8188 if local :
@@ -304,14 +311,25 @@ def _fake_transfer(self, files: list[Path]) -> bool:
304311
305312 return True
306313
307- def _transfer (self , files : list [Path ]) -> bool :
314+ def _transfer (self , infiles : list [Path ]) -> bool :
308315 """
309316 Transfer files via an rsync sub-process, and parses the rsync stdout to verify
310317 the success of the transfer.
311318 """
312319
313320 # Set up initial variables
314- files = [f for f in files if f .is_file ()]
321+ if self ._end_time :
322+ files = [
323+ f
324+ for f in infiles
325+ if f .is_file ()
326+ and f .stat ().st_ctime
327+ < (self ._end_time + timedelta (seconds = self ._grace_period )).timestamp ()
328+ ]
329+ self ._skipped_files .extend (set (infiles ).difference (set (files )))
330+ else :
331+ files = [f for f in infiles if f .is_file ()]
332+
315333 previously_transferred = self ._files_transferred
316334 transfer_success : set [Path ] = set ()
317335 successful_updates : list [RSyncerUpdate ] = []
0 commit comments