sync manager

This commit is contained in:
Amber 2024-05-17 11:53:30 +02:00
parent 2c0a75b466
commit 0090a67c41
5 changed files with 127 additions and 16 deletions

Binary file not shown.

View File

@ -1,46 +1,138 @@
# from tools import parse_conf as _parse_conf
import time
import os
import subprocess
from pathlib import Path
from lib.snapshot.generate import local as _genlocal
from lib.snapshot import dump as _dump
from iface import snap
DEFAULT_MANAGER_CONF = './conf/manager.conf'
class Manager():
def __init__(task: int=0, conf: dict={}):
def __init__(self, task: int=0, local_path: str='', remote_path: str=''):
if task:
## get conf from task table
## usually at ~/.syncdir.sync, a line is a task
## c00092bca01e2b580d84ac04b5dcab05 p2185521 w1693995892 STOPPED /home/luca/sharednotes/ notanamber@myvps:/home/notanamber/notes/
pass
if conf:
self.conf = conf
return
else:
if not local_path or not remote_path:
raise Exception('Please specify a local path and a remote path to sync')
self.local_path = self.normalize_path(local_path)
self.remote_path = self.normalize_path(remote_path)
self.check_conf()
# self.check_conf()
# conf_file = conf_file or DEFAULT_MANAGER_CONF
# self.conf = _parse_conf.read_conf(conf_file)
def check_conf():
local_path = self.conf.get('local_path')
if not local_path:
raise Exception('No local path specified')
remote_path = self.conf.get('remote_path')
if not remote_path:
raise Exception('No remote path specified')
def check_init_conf(self):
local_path = Path(self.local_path)
if not local_path.exists():
create = input('Do you want create the location %s? [Y/n] ' % (local_path))
if create == 'n' or create == 'N':
exit(0)
print('Creating path: %s' % (local_path,))
# if create == 'Y' or create == 'y'
os.mkdir(local_path)
else:
if not local_path.is_dir():
raise Exception('Local path is not a valid folder!')
def mirror(dry_run=True):
def normalize_path(self, path):
if path.endswith(os.sep): return path
return '%s%s' % (path, os.sep)
def mirror(self, dry_run=True):
'''
do an itial rsync
rsync -i -aPu --progress --out-format="%i ${GREEN}%n%L${ENDCOLOR} %''b" --log-file=$logfile -e ssh $otheropts $src $dest
rsync -i -aPu --progress --dry-run -e ssh notanamber@myvps:/home/notanamber/sharednotes_dev /home/luca/sharednotes_dev/
Note:
- if local_path don't exists it is created
- if already exists can be a good idea to report it to user!
'''
local_path = self.conf['local_path']
remote_path = self.conf['remote_path']
local_path = self.local_path
remote_path = self.remote_path
dry_run_flag = ''
def start_sync():
if dry_run:
dry_run_flag = '--dry-run'
cmd = ["rsync"]
cmd.extend(["-i"])
cmd.extend(["-aPu"])
cmd.extend(["--progress"])
cmd.extend(["--delete"])
# cmd.extend(["--out-format=\"%i %n%L$ %''b\""])
cmd.extend(["-e"])
cmd.extend(["ssh"])
remote_path = self.remote_path
cmd.extend(["%s" % (remote_path,)])
local_path = self.local_path
cmd.extend(["%s" % (local_path,)])
subprocess.run(cmd)
def compute_local_hash(self):
local_path = self.local_path
local_hash = _genlocal.generate_tree_hash(local_path)
return local_hash
def get_snapshot_path(self):
local_path = self.local_path
snapshot_dump_path = '%s%s%s%s' % (local_path, '.masy', os.sep, 'snapshot')
snapshot_dump_path = self.normalize_path(snapshot_dump_path)
return snapshot_dump_path
def dump_local_hash(self, hsh):
# local_path = self.local_path
# snapshot_dump_path = '%s%s%s%s' % (local_path, '.masy', os.sep, 'snapshot')
snapshot_dump_path = self.get_snapshot_path()
os.makedirs(snapshot_dump_path)
_dump.dump_snapshot(hsh, path=snapshot_dump_path)
def load_local_hash(self):
# local_path = self.local_path
# snapshot_dump_path = '%s%s%s%s' % (local_path, '.masy', os.sep, 'snapshot')
snapshot_dump_path = self.get_snapshot_path()
snapshot = _dump.load_snapshot(snapshot_dump_path)
return snapshot
def add_sync_to_list(self):
home_dir = os.environ.get('HOME')
home_dir = self.normalize_path(home_dir)
file_name = '.masync.sync'
local_path = self.local_path
remote_path = self.remote_path
last_action = int(time.time())
try:
with open('%s%s' % (home_dir,file_name), 'a') as f:
line = f'{local_path} {remote_path} {last_action} INIT\n'
f.write(line)
except Exception as ss:
raise Exception(f'can\' create file {home_dir}{file_name}')
def init_sync(self):
self.check_init_conf()
self.mirror()
local_hash = self.compute_local_hash()
self.dump_local_hash(local_hash)
self.add_sync_to_list()
def sync(self):
last_tree = self.load_local_hash()
current_tree = self.compute_local_hash()
local_snap_diff = snap.diff_snap(last_tree, current_tree)
return local_snap_diff

View File

@ -18,6 +18,18 @@ def dump_snapshot(snapshot, path=None, dump_file_name=None):
with open(file, "wb") as f:
f.write(dump)
def load_snapshot(path, dump_file_name=None):
dump_file_name = dump_file_name or DUMP_FILE_NAME
file = '%s%s' % (path, dump_file_name)
with open(file, "rb") as f:
dump = f.read()
snapshot = gzip.decompress(dump)
snapshot = json.loads(snapshot)
return snapshot
def decode_snapshot(path=None, dump_file_name=None):
path = path or SNAPSHOT_PATH

7
src/testing/sync.py Normal file
View File

@ -0,0 +1,7 @@
from iface import sync_manager
def test_init_sync():
m = sync_manager.Manager(local_path='/home/luca/sharednotes_dev', remote_path='notanamber@myvps:/home/notanamber/notes_dev')
m.init_sync()