194 lines
5.7 KiB
Python
194 lines
5.7 KiB
Python
|
|
#!/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))
|