summaryrefslogtreecommitdiffstats
path: root/gamechestcli/rsync.py
diff options
context:
space:
mode:
Diffstat (limited to 'gamechestcli/rsync.py')
-rw-r--r--gamechestcli/rsync.py80
1 files changed, 67 insertions, 13 deletions
diff --git a/gamechestcli/rsync.py b/gamechestcli/rsync.py
index f27c4f3..37330f9 100644
--- a/gamechestcli/rsync.py
+++ b/gamechestcli/rsync.py
@@ -1,28 +1,82 @@
#!/usr/bin/python3
+import os
+import re
import subprocess
+import humanfriendly
+
+from .structures import Progress
+
class Rsync:
+ _rsync_progress_re = re.compile(r'^\s*(\S+)\s+(\d+)%\s+(\S+)\s+(\S+)\s+$')
+
def __init__(self, src, dst):
- pass
+ self.proc = subprocess.Popen(
+ [
+ 'rsync',
+ '--partial',
+ # not human readable, easier to parse (but speed still appears
+ # in human form).
+ '--no-h',
+ '--info=progress2',
+ src,
+ dst,
+ ],
+ stdout=subprocess.PIPE,
+ #stderr=subprocess.DEVNULL,
+ encoding='utf8',
+ env={**os.environ,
+ **{'LC_ALL':'C.UTF-8',
+ 'LANG':'C.UTF-8',
+ 'LANGUAGE':'C.UTF-8',
+ }},
+ )
+ self.last_progress = Progress()
- #def start(src, dst):
+ def select_fd(self):
+ 'useful to use selectors with the process stdout file descriptor'
+ return self.proc.stdout
- def terminate(self):
+ def progress_read(self):
+ line = self.proc.stdout.readline()
+ if match := self._rsync_progress_re.search(line):
+ self.last_progress = Progress(
+ int(match.group(1)),
+ int(match.group(2)),
+ humanfriendly.parse_size(match.group(3), binary=True),
+ match.group(4),
+ )
+ return self.last_progress
- pass
+ def terminate(self):
+ self.proc.terminate()
def poll(self):
- pass
+ 'returns None if not terminated, otherwise return returncode'
+ return self.proc.poll()
+
+ def wait(self, timeout=None):
+ return self.proc.wait(timeout)
+
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, value, traceback):
+ self.terminate()
+ self.wait()
-def rsync(src, dst):
- subprocess.run(
- ['rsync',
- '--partial',
- # format: %l length in bytes, %b bytes actually transferred, %f
- # filename.
- '--out-format=%l %b %f',
- ])
+if __name__ == '__main__':
+ import sys
+ import contextlib
+ with contextlib.suppress(KeyboardInterrupt):
+ with Rsync(sys.argv[1], sys.argv[2]) as rsync:
+ while rsync.poll() is None:
+ progress = rsync.progress_read()
+ print(f'{progress.bytes}b {progress.percent}% '
+ f'{progress.speed}b/s {progress.eta}')
+ rc = rsync.poll()
+ print(f'rsync ended with code: {rc}')
+ print('Rsync test main ended')