node as Class
This commit is contained in:
parent
b552ccd298
commit
bdba95d9c2
@ -4,6 +4,7 @@ import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from lib.repr.node import node_factory
|
||||
from lib.snapshot.generate import local as _genlocal
|
||||
from lib.snapshot import dump as _dump
|
||||
# from lib.snapshot.generate.remote import RHAgent
|
||||
@ -18,6 +19,7 @@ from lib.utils import node as _node_utils
|
||||
from tools import colors
|
||||
|
||||
from iface import snap
|
||||
# from iface import Node
|
||||
|
||||
DEFAULT_MANAGER_CONF = './conf/manager.conf'
|
||||
|
||||
@ -154,20 +156,6 @@ class Manager():
|
||||
unmerged_file_path = unmerged_local_file_path.replace('.%s' % (os.sep), self.get_unmerged_path())
|
||||
return unmerged_file_path
|
||||
|
||||
def get_absolute_local_path(self, node):
|
||||
node_path = self.normalize_path(node['rel_path'])
|
||||
node_name = node['name']
|
||||
local_file_path = '%s%s' % (node_path, node_name)
|
||||
local_file_path = local_file_path.replace('.%s' % (os.sep), self.local_path)
|
||||
return local_file_path
|
||||
|
||||
def get_absolute_remote_path(self, node):
|
||||
node_path = self.normalize_path(node['rel_path'])
|
||||
node_name = node['name']
|
||||
remote_file_path = '%s%s' % (node_path, node_name)
|
||||
remote_file_path = remote_file_path.replace('.%s' % (os.sep), self.remote_path)
|
||||
return remote_file_path
|
||||
|
||||
def get_remote_mount_point(self, node):
|
||||
node_path = node['rel_path']
|
||||
remote_mount_point = node_path.replace('.%s' % (os.sep), self.remote_path)
|
||||
@ -229,7 +217,8 @@ class Manager():
|
||||
store in file diff path `.masy/diff` the tree with diffs
|
||||
file is containing the diff between local and remote
|
||||
'''
|
||||
node_local_path = self.get_absolute_local_path(node)
|
||||
LNode = node_factory(self.local_path, node)
|
||||
node_local_path = LNode.absolute_path()
|
||||
filea_block_tag = '%s %s (local)' % (node['name'], node['cur_hash'])
|
||||
fileb_block_tag = '%s %s (remote)' % (node['name'], node['remote_hash'])
|
||||
# rfile_buf = ''
|
||||
@ -284,11 +273,15 @@ class Manager():
|
||||
|
||||
def get_rnode_status(self, node):
|
||||
'''
|
||||
we start from a local node
|
||||
gived a node check the remote status
|
||||
- node exists in remote
|
||||
- hash changed
|
||||
'''
|
||||
absolute_remote_path = self.get_absolute_remote_path(node)
|
||||
LNode = node_factory(self.local_path, node)
|
||||
RNode = node_factory(self.remote_path, node)
|
||||
absolute_remote_path = RNode.absolute_path()
|
||||
|
||||
agent = self.get_agent()
|
||||
## if node not exist in the local tree there is not last_type
|
||||
## we use cur_type (is this correct?)
|
||||
@ -303,8 +296,12 @@ class Manager():
|
||||
use put of sftp client
|
||||
put(localpath, remotepath, callback=None, confirm=True)
|
||||
'''
|
||||
absolute_local_path = self.get_absolute_local_path(node)
|
||||
absolute_remote_path = self.get_absolute_remote_path(node)
|
||||
LNode = node_factory(self.local_path, node)
|
||||
RNode = node_factory(self.remote_path, node)
|
||||
|
||||
absolute_local_path = LNode.absolute_path()
|
||||
absolute_remote_path = RNode.absolute_path()
|
||||
|
||||
agent = self.get_agent()
|
||||
if node['cur_type'] == 'f':
|
||||
## simply put
|
||||
@ -316,86 +313,39 @@ class Manager():
|
||||
return agent.copy_dir(absolute_local_path, remote_mount_point)
|
||||
|
||||
def remove_node_remotely(self, node):
|
||||
absolute_remote_path = self.get_absolute_remote_path(node)
|
||||
RNode = node_factory(self.remote_path, node)
|
||||
absolute_remote_path = RNode.absolute_path()
|
||||
|
||||
agent = self.get_agent()
|
||||
if node['last_type'] == 'f':
|
||||
if RNode.is_file():
|
||||
## simply put
|
||||
return agent.remove_file(absolute_remote_path)
|
||||
elif node['last_type'] == 'd':
|
||||
elif RNode.is_dir():
|
||||
#cur_hash contains the entire subtree to recreate on remote
|
||||
## it is better to remove the root node if already exists on remote
|
||||
# remote_mount_point = self.get_remote_mount_point(node)
|
||||
return agent.remove_dir(absolute_remote_path)
|
||||
|
||||
#maybe useless
|
||||
# def precheck_remote_unode(self, node):
|
||||
# '''
|
||||
# Check the unmerged node on remote before solve conflict
|
||||
# Consideration about unode:
|
||||
# 1. We have generated `cur_hash` starting from `last_hash` version of node on local tree
|
||||
# 2. We are aware on remote the hash is changed at the moment we `sync`, the value is stored in `remote_hash`
|
||||
#
|
||||
# we expect
|
||||
# `remote_hash` is unchanged, then we can proceed with solving the conflict
|
||||
# `remote_hash` is changed, then we can generate a new conflict with `remote_hash` equals to the new remote hash
|
||||
#
|
||||
# '''
|
||||
# rstatus = self.get_rnode_status(node)
|
||||
# rfile_buf, rhash, rexists = map(rstatus.get, ['iobuffer', 'hash', 'exists'])
|
||||
#
|
||||
# remote_hash = node['remote_hash']
|
||||
#
|
||||
# if not (remote_hash == rhash):
|
||||
# unmerged = self.load_unmerged_diff()
|
||||
# name = node['name']
|
||||
# path = node['rel_path']
|
||||
#
|
||||
# unmerged = self.load_unmerged_diff()
|
||||
#
|
||||
# found = {}
|
||||
# for n, unode in enumerate(unmerged):
|
||||
# if unode['name'] == name and unode['rel_path'] == path:
|
||||
# found = unode
|
||||
# break
|
||||
# else:
|
||||
# n = -1
|
||||
#
|
||||
# if n == -1:
|
||||
# raise Exception('No node conflicting found!!')
|
||||
#
|
||||
# print(f'remote hash changed you...generate a new conflict')
|
||||
# ## update the conflicting node by index
|
||||
# # (cur_hash, cur_buf) = _genlocal.generate_file_hash(self.get_absolute_local_path(found))
|
||||
# found['cur_hash'] = cur_hash
|
||||
# found['last_hash'] = found['remote_hash']
|
||||
# found['remote_hash'] = rhash
|
||||
# found['remote_file_buf'] = rfile_buf
|
||||
# self.store_unmerged_diff(unmerged)
|
||||
# ## store diff in diffs path
|
||||
# self.store_fdiff(found)
|
||||
# return False, 'Generate conflict'
|
||||
#
|
||||
# return True, 'You can proceed'
|
||||
|
||||
|
||||
|
||||
def show_conflicts(self):
|
||||
unmerged = self.load_unmerged_diff()
|
||||
for n, unode in enumerate(unmerged):
|
||||
i = n+1
|
||||
absolute_local_path = colors.CYAN(self.get_absolute_local_path(unode))
|
||||
name = unode['name']
|
||||
remote_hash = unode['remote_hash']
|
||||
last_type = unode.get('last_type')
|
||||
local_hash = unode['cur_hash']
|
||||
cur_type = unode['cur_type']
|
||||
last_hash = unode['last_hash']
|
||||
if remote_hash is None:
|
||||
remote_hash = colors.RED('file not present in remote')
|
||||
elif local_hash is None:
|
||||
local_hash = colors.RED('file not present local')
|
||||
LNode = node_factory(self.local_path, unode)
|
||||
absolute_local_path = colors.CYAN(LNode.absolute_path())
|
||||
name = LNode.name
|
||||
remote_hash = LNode.remote_hash
|
||||
node_type = LNode.get_type()
|
||||
node_action = LNode.get_action()
|
||||
local_hash = LNode.cur_hash
|
||||
last_hash = LNode.last_hash if LNode.last_hash is not None else 'File was not present'
|
||||
|
||||
print(f'{i}- path: \'{absolute_local_path}\' ({cur_type}) \n local_hash: \'{last_hash}\' \u21E8 \'{local_hash}\', \n remote_hash: \'{last_hash}\' \u21E8 \'{remote_hash}\'')
|
||||
if remote_hash is None:
|
||||
remote_hash = colors.RED('File not present in remote')
|
||||
elif local_hash is None:
|
||||
local_hash = colors.RED('File not present local')
|
||||
|
||||
print(f'{i}- path: \'{absolute_local_path}\' ({node_type} - {node_action}) \n local: \'{last_hash}\' \u21E8 \'{local_hash}\',\
|
||||
\n remote: \'{last_hash}\' \u21E8 \'{remote_hash}\'')
|
||||
|
||||
def manual_solve_conflict(self, n, version_kept):
|
||||
i = n-1
|
||||
@ -414,8 +364,10 @@ class Manager():
|
||||
self.store_unmerged_diff(unmerged)
|
||||
return
|
||||
|
||||
absolute_local_path = colors.CYAN(self.get_absolute_local_path(node))
|
||||
absolute_remote_path = colors.CYAN(self.get_absolute_remote_path(node))
|
||||
LNode = node_factory(self.local_path, node)
|
||||
RNode = node_factory(self.remote_path, node)
|
||||
absolute_local_path = colors.CYAN(LNode.absolute_path())
|
||||
absolute_remote_path = colors.CYAN(RNode.absolute_path())
|
||||
|
||||
if version_kept == 'keep_local':
|
||||
# before copy check the remote
|
||||
@ -628,24 +580,28 @@ class Manager():
|
||||
|
||||
def compute_local_node_hash(self, n):
|
||||
## we must compute n['cur_hash']
|
||||
path = self.get_absolute_local_path(n)
|
||||
LNode = node_factory(self.local_path, n)
|
||||
absolute_local_path = LNode.absolute_path()
|
||||
if n['last_type'] == 'd':
|
||||
cur_hash = _genlocal.generate_tree_hash(path)
|
||||
cur_hash = _genlocal.generate_tree_hash(absolute_local_path)
|
||||
else:
|
||||
cur_hash = _genlocal.generate_file_hash(path)
|
||||
cur_hash = _genlocal.generate_file_hash(absolute_local_path)
|
||||
|
||||
return cur_hash
|
||||
|
||||
def copy_node_from_remote(self, n):
|
||||
a = self.get_agent()
|
||||
last_type = n['last_type']
|
||||
absolute_remote_path = self.get_absolute_remote_path(n)
|
||||
# absolute_remote_path = self.get_absolute_remote_path(n)
|
||||
RNode = node_factory(self.remote_path, n)
|
||||
absolute_remote_path = RNode.absolute_path()
|
||||
|
||||
if last_type == 'd':
|
||||
local_mount_point = self.get_local_mount_point(n)
|
||||
return a.get_dir(absolute_remote_path, local_mount_point)
|
||||
|
||||
absolute_local_path = self.get_absolute_local_path(n)
|
||||
LNode = node_factory(self.local_path, n)
|
||||
absolute_local_path = LNode.absolute_path()
|
||||
return a.get_file(absolute_remote_path, absolute_local_path)
|
||||
|
||||
|
||||
|
@ -1,18 +1,25 @@
|
||||
import os
|
||||
|
||||
from dataclasses import dataclass
|
||||
from lib.utils import path_utils as _path_utils
|
||||
|
||||
@dataclass
|
||||
class Node:
|
||||
base_path: str
|
||||
name: str
|
||||
rel_path: str
|
||||
last_type: str
|
||||
cur_type:str
|
||||
last_hash: str
|
||||
cur_hash: str
|
||||
last_type: str = None
|
||||
cur_type:str = None
|
||||
last_hash: str = None
|
||||
cur_hash: str = None
|
||||
remote_hash: str = None
|
||||
|
||||
'''
|
||||
A node is a representation of a node within the tree
|
||||
that we wish to keep synchronised with remote source
|
||||
|
||||
@param base_path base_path of node: NOTE can be local or remote
|
||||
|
||||
@param name name of node
|
||||
@param rel_path relative path of node respect of root of shared folder
|
||||
@param last_type is the last type received from server
|
||||
@ -23,3 +30,61 @@ class Node:
|
||||
no conflict -> `remote_hash` == `last_hash`
|
||||
conflict -> `remote_hash` != `last_hash` this means we have lost a version of node
|
||||
'''
|
||||
|
||||
'''
|
||||
compute the action actually binded to node
|
||||
can be -> deletion | addition | change
|
||||
'''
|
||||
|
||||
def is_node_added(self):
|
||||
return self.last_hash is None and self.cur_hash is not None
|
||||
|
||||
def is_node_deleted(self):
|
||||
return self.cur_hash is None and self.last_hash is not None
|
||||
|
||||
def is_node_changed(self):
|
||||
return self.cur_hash is not None and self.last_hash is not None
|
||||
|
||||
def get_action(self):
|
||||
if self.is_node_added():
|
||||
return 'addition'
|
||||
elif self.is_node_deleted():
|
||||
return 'deletion'
|
||||
elif self.is_node_changed():
|
||||
return 'changed'
|
||||
|
||||
def absolute_path(self):
|
||||
rel_path = self.rel_path
|
||||
name = self.name
|
||||
file_path = '%s%s' % (rel_path, name)
|
||||
file_path = file_path.replace('.%s' % (os.sep), self.base_path)
|
||||
return file_path
|
||||
|
||||
def is_file(self):
|
||||
if self.is_node_deleted():
|
||||
return self.last_type == 'f'
|
||||
## if is_node_added or is_node_changed
|
||||
return self.cur_type == 'f'
|
||||
|
||||
def is_dir(self):
|
||||
if self.is_node_deleted():
|
||||
return self.last_type == 'd'
|
||||
## if is_node_added or is_node_changed
|
||||
return self.cur_type == 'd'
|
||||
|
||||
def get_type(self):
|
||||
if self.is_file: return 'f'
|
||||
return 'd'
|
||||
|
||||
def node_factory(base_path, d):
|
||||
base_path = _path_utils.normalize_path(base_path)
|
||||
name = d['name']
|
||||
rel_path = _path_utils.normalize_path(d['rel_path'])
|
||||
last_type = d.get('last_type')
|
||||
cur_type = d.get('cur_type')
|
||||
last_hash = d.get('last_hash')
|
||||
cur_hash = d.get('cur_hash')
|
||||
remote_hash = d.get('remote_hash')
|
||||
# action = d.get('action')
|
||||
return Node(base_path, name, rel_path, last_type, cur_type, last_hash, cur_hash, remote_hash)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user