node as Class
This commit is contained in:
parent
b552ccd298
commit
bdba95d9c2
@ -4,6 +4,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from lib.repr.node import node_factory
|
||||||
from lib.snapshot.generate import local as _genlocal
|
from lib.snapshot.generate import local as _genlocal
|
||||||
from lib.snapshot import dump as _dump
|
from lib.snapshot import dump as _dump
|
||||||
# from lib.snapshot.generate.remote import RHAgent
|
# from lib.snapshot.generate.remote import RHAgent
|
||||||
@ -18,6 +19,7 @@ from lib.utils import node as _node_utils
|
|||||||
from tools import colors
|
from tools import colors
|
||||||
|
|
||||||
from iface import snap
|
from iface import snap
|
||||||
|
# from iface import Node
|
||||||
|
|
||||||
DEFAULT_MANAGER_CONF = './conf/manager.conf'
|
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())
|
unmerged_file_path = unmerged_local_file_path.replace('.%s' % (os.sep), self.get_unmerged_path())
|
||||||
return unmerged_file_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):
|
def get_remote_mount_point(self, node):
|
||||||
node_path = node['rel_path']
|
node_path = node['rel_path']
|
||||||
remote_mount_point = node_path.replace('.%s' % (os.sep), self.remote_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
|
store in file diff path `.masy/diff` the tree with diffs
|
||||||
file is containing the diff between local and remote
|
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'])
|
filea_block_tag = '%s %s (local)' % (node['name'], node['cur_hash'])
|
||||||
fileb_block_tag = '%s %s (remote)' % (node['name'], node['remote_hash'])
|
fileb_block_tag = '%s %s (remote)' % (node['name'], node['remote_hash'])
|
||||||
# rfile_buf = ''
|
# rfile_buf = ''
|
||||||
@ -284,11 +273,15 @@ class Manager():
|
|||||||
|
|
||||||
def get_rnode_status(self, node):
|
def get_rnode_status(self, node):
|
||||||
'''
|
'''
|
||||||
|
we start from a local node
|
||||||
gived a node check the remote status
|
gived a node check the remote status
|
||||||
- node exists in remote
|
- node exists in remote
|
||||||
- hash changed
|
- 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()
|
agent = self.get_agent()
|
||||||
## if node not exist in the local tree there is not last_type
|
## if node not exist in the local tree there is not last_type
|
||||||
## we use cur_type (is this correct?)
|
## we use cur_type (is this correct?)
|
||||||
@ -303,8 +296,12 @@ class Manager():
|
|||||||
use put of sftp client
|
use put of sftp client
|
||||||
put(localpath, remotepath, callback=None, confirm=True)
|
put(localpath, remotepath, callback=None, confirm=True)
|
||||||
'''
|
'''
|
||||||
absolute_local_path = self.get_absolute_local_path(node)
|
LNode = node_factory(self.local_path, node)
|
||||||
absolute_remote_path = self.get_absolute_remote_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()
|
agent = self.get_agent()
|
||||||
if node['cur_type'] == 'f':
|
if node['cur_type'] == 'f':
|
||||||
## simply put
|
## simply put
|
||||||
@ -316,86 +313,39 @@ class Manager():
|
|||||||
return agent.copy_dir(absolute_local_path, remote_mount_point)
|
return agent.copy_dir(absolute_local_path, remote_mount_point)
|
||||||
|
|
||||||
def remove_node_remotely(self, node):
|
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()
|
agent = self.get_agent()
|
||||||
if node['last_type'] == 'f':
|
if RNode.is_file():
|
||||||
## simply put
|
## simply put
|
||||||
return agent.remove_file(absolute_remote_path)
|
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
|
#cur_hash contains the entire subtree to recreate on remote
|
||||||
## it is better to remove the root node if already exists on remote
|
## it is better to remove the root node if already exists on remote
|
||||||
# remote_mount_point = self.get_remote_mount_point(node)
|
# remote_mount_point = self.get_remote_mount_point(node)
|
||||||
return agent.remove_dir(absolute_remote_path)
|
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):
|
def show_conflicts(self):
|
||||||
unmerged = self.load_unmerged_diff()
|
unmerged = self.load_unmerged_diff()
|
||||||
for n, unode in enumerate(unmerged):
|
for n, unode in enumerate(unmerged):
|
||||||
i = n+1
|
i = n+1
|
||||||
absolute_local_path = colors.CYAN(self.get_absolute_local_path(unode))
|
LNode = node_factory(self.local_path, unode)
|
||||||
name = unode['name']
|
absolute_local_path = colors.CYAN(LNode.absolute_path())
|
||||||
remote_hash = unode['remote_hash']
|
name = LNode.name
|
||||||
last_type = unode.get('last_type')
|
remote_hash = LNode.remote_hash
|
||||||
local_hash = unode['cur_hash']
|
node_type = LNode.get_type()
|
||||||
cur_type = unode['cur_type']
|
node_action = LNode.get_action()
|
||||||
last_hash = unode['last_hash']
|
local_hash = LNode.cur_hash
|
||||||
if remote_hash is None:
|
last_hash = LNode.last_hash if LNode.last_hash is not None else 'File was not present'
|
||||||
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}\' ({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):
|
def manual_solve_conflict(self, n, version_kept):
|
||||||
i = n-1
|
i = n-1
|
||||||
@ -414,8 +364,10 @@ class Manager():
|
|||||||
self.store_unmerged_diff(unmerged)
|
self.store_unmerged_diff(unmerged)
|
||||||
return
|
return
|
||||||
|
|
||||||
absolute_local_path = colors.CYAN(self.get_absolute_local_path(node))
|
LNode = node_factory(self.local_path, node)
|
||||||
absolute_remote_path = colors.CYAN(self.get_absolute_remote_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':
|
if version_kept == 'keep_local':
|
||||||
# before copy check the remote
|
# before copy check the remote
|
||||||
@ -628,24 +580,28 @@ class Manager():
|
|||||||
|
|
||||||
def compute_local_node_hash(self, n):
|
def compute_local_node_hash(self, n):
|
||||||
## we must compute n['cur_hash']
|
## 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':
|
if n['last_type'] == 'd':
|
||||||
cur_hash = _genlocal.generate_tree_hash(path)
|
cur_hash = _genlocal.generate_tree_hash(absolute_local_path)
|
||||||
else:
|
else:
|
||||||
cur_hash = _genlocal.generate_file_hash(path)
|
cur_hash = _genlocal.generate_file_hash(absolute_local_path)
|
||||||
|
|
||||||
return cur_hash
|
return cur_hash
|
||||||
|
|
||||||
def copy_node_from_remote(self, n):
|
def copy_node_from_remote(self, n):
|
||||||
a = self.get_agent()
|
a = self.get_agent()
|
||||||
last_type = n['last_type']
|
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':
|
if last_type == 'd':
|
||||||
local_mount_point = self.get_local_mount_point(n)
|
local_mount_point = self.get_local_mount_point(n)
|
||||||
return a.get_dir(absolute_remote_path, local_mount_point)
|
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)
|
return a.get_file(absolute_remote_path, absolute_local_path)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,18 +1,25 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from lib.utils import path_utils as _path_utils
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Node:
|
class Node:
|
||||||
|
base_path: str
|
||||||
name: str
|
name: str
|
||||||
rel_path: str
|
rel_path: str
|
||||||
last_type: str
|
last_type: str = None
|
||||||
cur_type:str
|
cur_type:str = None
|
||||||
last_hash: str
|
last_hash: str = None
|
||||||
cur_hash: str
|
cur_hash: str = None
|
||||||
remote_hash: str = None
|
remote_hash: str = None
|
||||||
|
|
||||||
'''
|
'''
|
||||||
A node is a representation of a node within the tree
|
A node is a representation of a node within the tree
|
||||||
that we wish to keep synchronised with remote source
|
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 name name of node
|
||||||
@param rel_path relative path of node respect of root of shared folder
|
@param rel_path relative path of node respect of root of shared folder
|
||||||
@param last_type is the last type received from server
|
@param last_type is the last type received from server
|
||||||
@ -23,3 +30,61 @@ class Node:
|
|||||||
no conflict -> `remote_hash` == `last_hash`
|
no conflict -> `remote_hash` == `last_hash`
|
||||||
conflict -> `remote_hash` != `last_hash` this means we have lost a version of node
|
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