|
|
@@ -18,7 +18,7 @@ import wcmatch.glob # type: ignore |
|
|
|
import humanfriendly # type: ignore |
|
|
|
|
|
|
|
class Config: |
|
|
|
root: str |
|
|
|
root: bytes |
|
|
|
max_file_size: typing.Optional[int] |
|
|
|
one_file_system: bool |
|
|
|
exclude: list[bytes] |
|
|
@@ -91,9 +91,8 @@ class Config: |
|
|
|
return yaml.dump(d, default_flow_style=False) |
|
|
|
|
|
|
|
class Backup: |
|
|
|
def __init__(self, config: Config, dry_run: bool, out: typing.BinaryIO): |
|
|
|
def __init__(self, config: Config, dry_run: bool): |
|
|
|
self.config = config |
|
|
|
self.outfile = out |
|
|
|
self.dry_run = dry_run |
|
|
|
|
|
|
|
# All logged messages, with severity |
|
|
@@ -111,7 +110,8 @@ class Backup: |
|
|
|
sys.stderr.write(f"\033[1;{c}m{letter}:\033[22m {msg}\033[0m\n") |
|
|
|
self.logs.append((letter, msg)) |
|
|
|
|
|
|
|
def run(self): |
|
|
|
def run(self, outfile: typing.BinaryIO): |
|
|
|
self.outfile = outfile |
|
|
|
self.scan(self.config.root) |
|
|
|
|
|
|
|
def scan(self, path: bytes, parent_st: os.stat_result=None): |
|
|
@@ -140,16 +140,16 @@ class Backup: |
|
|
|
# Config file says to exclude |
|
|
|
exclude_reason = ('I', f"skipping, excluded by config file") |
|
|
|
|
|
|
|
elif (stat.S_ISDIR(st().st_mode) |
|
|
|
and self.config.one_file_system |
|
|
|
elif (self.config.one_file_system |
|
|
|
and parent_st is not None |
|
|
|
and stat.S_ISDIR(st().st_mode) |
|
|
|
and st().st_dev != parent_st.st_dev): |
|
|
|
# Crosses a mount point |
|
|
|
exclude_reason = ('I', "skipping, on different filesystem") |
|
|
|
|
|
|
|
elif (stat.S_ISREG(st().st_mode) |
|
|
|
and self.config.max_file_size |
|
|
|
and st().st_size > self.config.max_file_size): |
|
|
|
elif (self.config.max_file_size |
|
|
|
and stat.S_ISREG(st().st_mode) |
|
|
|
and (st().st_blocks * 512) > self.config.max_file_size): |
|
|
|
# Too big |
|
|
|
def format_size(n): |
|
|
|
return humanfriendly.format_size( |
|
|
@@ -199,8 +199,13 @@ def main(argv: list[str]): |
|
|
|
|
|
|
|
args = parser.parse_args() |
|
|
|
config = Config(args.config) |
|
|
|
backup = Backup(config, args.dry_run, sys.stdout.buffer) |
|
|
|
backup.run() |
|
|
|
|
|
|
|
backup = Backup(config, args.dry_run) |
|
|
|
if args.dry_run: |
|
|
|
with open(os.devnull, "wb") as out: |
|
|
|
backup.run(out) |
|
|
|
else: |
|
|
|
backup.run(sys.stdout.buffer) |
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
import sys |
|
|
|