#!/usr/bin/env python import enum import itertools import json import os import re import sys from dataclasses import KW_ONLY, dataclass, field from functools import partial, partialmethod from operator import itemgetter from tabnanny import verbose from time import sleep from traceback import print_list import defl from defl import CLIError, DotDict, Null, Path, Undefined, cl, log from defl._assert_ import Assert from defl._typing_ import * from defl.testing_ import Tester from defl.rsync_ import * tester = Tester(name=__file__) @tester.add() def cli(): r = Rsync('srcPath', 'dstPath').cli() Assert(r) == ['rsync', 'srcPath', 'dstPath'] r = Rsync(srcPath='srcPath', dstPath='dstPath', srcHost='srcHost', dstHost='dstHost').cli() Assert(r) == ['rsync', 'srcHost:srcPath', 'dstHost:dstPath'] r = Rsync(srcPath='srcPath', dstPath='dstPath', srcHost='srcHost', dstHost=None).cli() Assert(r) == ['rsync', 'srcHost:srcPath', 'dstPath'] r = Rsync(srcPath='srcPath', dstPath='dstPath', srcHost='srcHost').cli() Assert(r) == ['rsync', 'srcHost:srcPath', 'dstPath'] @tester.add() def basic(): r = Rsync( srcPath='srcPath', dstPath='dstPath', srcHost='srcHost', options=RsyncOptions( verbose=T, dryRun=T, ), ) Assert(r.base()) == ['rsync', 'srcHost:srcPath', 'dstPath'] Assert(set(r.args())) == set(['--verbose', '--dry-run']) Assert(RsyncOptions(exclude=['a', 'b']) | RsyncOptions(exclude=['c']) | RsyncOptions(include=['d'])) == RsyncOptions(exclude=['a', 'b', 'c'], include=['d']) def test(rsync, src, dst, assOut, assSrc, assDst): res = rsync.run().run(T, T).wait().assSuc().outStr() if '.d..t...... ./' in res: res.pop(res.index('.d..t...... ./')) Assert(res) == assOut Assert([x.name for x in src.ls()]) == assSrc Assert([x.name for x in dst.ls()]) == assDst @tester.add() def mirror(): tmp = Path.Temp().tempFile(direct=T) tmp.chdir() src = tmp / 'src' dst = tmp / 'dst' src.mkdir() dst.mkdir() opt = RsyncOptions.Mirror(RsyncOptions(outFormat='%i %n%L')) rsync = Rsync( srcPath='src/', dstPath='dst/', options=opt, ) Assert(set(rsync.args())) == { '--times', '--recursive', '--atimes', '--delete-before', '--chmod=go=', '--perms', '--out-format=%i %n%L', '--links' } run = rsync.run() log.info('cwd', Path('.').absolute()) log.info('run', lambda r: r.run) # ===================================== for i in ['1', '2', '3']: (src / i).touch() test( rsync, src, dst, assOut=['>f+++++++++ 1', '>f+++++++++ 2', '>f+++++++++ 3'], assSrc=['1', '2', '3'], assDst=['1', '2', '3'] ) # ===================================== Path('src/3').write_text('src1').setAccModTime(1, 1) Path('dst/3').write_text('dst1').setAccModTime(2, 2) src3a = Path('src/3').stat().st_mtime dst3a = Path('dst/3').stat().st_mtime test(rsync, src, dst, assOut=['>f..t...u.. 3'], assSrc=['1', '2', '3'], assDst=['1', '2', '3']) Assert(Path('dst/3').stat().st_mtime) == src3a Assert(Path('dst/3').stat().st_mtime) != dst3a Assert(Path('dst/3').read_text()) == 'src1' # ===================================== Path('src/1').remove() Path('src/2').remove() Path('src/3').write_text('src2').setAccModTime(1, 2) Path('src/4').touch().write_text('src2').setAccModTime(99999999999, 99999999999) src3a = Path('src/3').stat().st_mtime test( rsync, src, dst, assOut=['*deleting 2', '*deleting 1', '>f..t...u.. 3', '>f+++++++++ 4'], assSrc=['3', '4'], assDst=['3', '4'] ) Assert(Path('dst/3').stat().st_mtime) == src3a Assert(Path('dst/3').read_text()) == 'src2' Assert(Path('dst/4').read_text()) == 'src2' @tester.add() def move(): tmp = Path.Temp().tempFile(direct=T) tmp.chdir() src = tmp / 'src' dst = tmp / 'dst' src.mkdir() dst.mkdir() opt = RsyncOptions.Move(RsyncOptions(outFormat='%i %n%L')) rsync = Rsync( srcPath='src/', dstPath='dst/', options=opt, ) Assert(set(rsync.args())) == { '--times', '--chmod=go=', '--perms', '--recursive', '--out-format=%i %n%L', '--links', '--remove-source-files', '--atimes', '--ignore-times' } run = rsync.run() log.info('cwd', Path('.').absolute()) log.info('run', lambda r: r.run) # ===================================== for i in ['1', '2', '3']: (src / i).touch() test( rsync, src, dst, assOut=['>f+++++++++ 1', '>f+++++++++ 2', '>f+++++++++ 3'], assSrc=[], assDst=['1', '2', '3'] ) # ===================================== Path('src/3').write_text('src1').setAccModTime(1, 1) Path('dst/3').write_text('dst1').setAccModTime(2, 2) src3a = Path('src/3').stat().st_mtime dst3a = Path('dst/3').stat().st_mtime test(rsync, src, dst, assOut=['>f..t...u.. 3'], assSrc=[], assDst=['1', '2', '3']) Assert(Path('dst/3').stat().st_mtime) == src3a Assert(Path('dst/3').stat().st_mtime) != dst3a Assert(Path('dst/3').read_text()) == 'src1' # ===================================== Path('src/3').write_text('src2').setAccModTime(1, 2) Path('src/4').touch().write_text('src2').setAccModTime(99999999999, 99999999999) src3a = Path('src/3').stat().st_mtime test(rsync, src, dst, assOut=['>f..t...u.. 3', '>f+++++++++ 4'], assSrc=[], assDst=['1', '2', '3', '4']) Assert(Path('dst/3').stat().st_mtime) == src3a Assert(Path('dst/3').read_text()) == 'src2' Assert(Path('dst/4').read_text()) == 'src2' log.info(tester.run()) tester.exitWithStatus() # for i in ch: # print(defl.printTable([[y for y in x] for x in ch], squareFill=True))