-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmirror.py
152 lines (126 loc) · 5.65 KB
/
mirror.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# coding=utf-8
__author__ = 'Vladimir'
import argparse
import os
import sys
import shutil
import locale
lang, default_locale = locale.getdefaultlocale()
def is_close(a, b, rel_tol=1e-09, abs_tol=0.0):
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
class FolderInfo:
def __init__(self, root, rel_path, name):
self.root = root
self.rel_path = rel_path
self.name = name
def is_equals(self, to):
if self.rel_path == to.rel_path and self.name == to.name:
return True
return False
def get_full_name(self):
return os.path.join(self.root, self.rel_path, self.name)
def delete(self):
full_name = self.get_full_name()
try:
shutil.rmtree(full_name, ignore_errors=True)
except Exception as ex:
print('Error delete folder {}: {}'.format(full_name.encode(default_locale), ex))
class FileInfo(FolderInfo):
def __init__(self, root, rel_path, name, size, change_time, crc):
FolderInfo.__init__(self, root, rel_path, name)
self.size = size
self.change_time = change_time
self.crc = crc
def is_equals(self, to):
if self.rel_path == to.rel_path and self.name == to.name and self.size == to.size and is_close(
self.change_time, to.change_time) and self.crc == to.crc:
return True
return False
def delete(self):
full_name = self.get_full_name()
try:
os.remove(full_name)
except Exception as ex:
print('Error delete file {}: {}'.format(full_name.encode(default_locale), ex))
def copy_to(self, folder):
source_file = self.get_full_name()
destination_file = os.path.join(folder, self.name)
try:
shutil.copy2(source_file, destination_file)
except Exception as ex:
print('Error copy {} to {}: {}'.format(source_file.encode(default_locale),
destination_file.encode(default_locale), ex))
def list_dir(folder):
result_files = {}
result_folders = {}
for root, folders, files in os.walk(unicode(folder)):
for current_file in files:
relative_path = os.path.relpath(root, folder)
if relative_path == '.':
relative_path = ''
full_file = os.path.join(root, current_file)
stat = os.stat(full_file.encode(sys.getfilesystemencoding()))
key = os.path.join(relative_path, current_file)
result_files[key] = FileInfo(folder, relative_path, current_file, stat.st_size, stat.st_mtime, None)
for current_folder in folders:
relative_path = os.path.relpath(root, folder)
if relative_path == '.':
relative_path = ''
key = os.path.join(relative_path, current_folder)
result_folders[key] = FolderInfo(folder, relative_path, current_folder)
return result_folders, result_files
parser = argparse.ArgumentParser(description='Mirroring folder', add_help=True)
parser.add_argument('source', nargs=1, help='Source folder')
parser.add_argument('destination', nargs=1, help='Destination folder')
parser.add_argument('--test', dest='test', action='store_true', help='Only test')
parser.add_argument('--quiet', dest='quiet', action='store_true', help='Quiet mode - do not display any messages')
args = parser.parse_args()
source_dir = args.source[0]
dest_dir = args.destination[0]
is_test = args.test
is_quiet = args.quiet
if not os.path.isdir(source_dir):
print('Directory {} not exists'.format(source_dir.encode(default_locale)))
sys.exit(0)
if os.path.exists(dest_dir) and not os.path.isdir(dest_dir):
print('{} is nod directory'.format(dest_dir.encode(default_locale)))
sys.exit(0)
source_folder_list, source_file_list = list_dir(source_dir)
dest_folder_list, dest_file_list = list_dir(dest_dir)
# Deleting files from destination folder
for file_name, dest_object in dest_file_list.items():
if file_name not in source_file_list or not dest_object.is_equals(source_file_list[file_name]):
if not is_quiet:
print('Delete file {}'.format(dest_object.get_full_name().encode(default_locale)))
if not is_test:
dest_object.delete()
del dest_file_list[file_name]
# Deleting folders from destination folder
for folder_name, dest_object in dest_folder_list.items():
if folder_name not in source_folder_list:
if not is_quiet:
print('Delete folder {}'.format(dest_object.get_full_name().encode(default_locale)))
if not is_test:
dest_object.delete()
del dest_folder_list[folder_name]
# Create folders in destination folder
for folder_name, source_object in source_folder_list.items():
if folder_name not in dest_folder_list:
full_folder = os.path.join(dest_dir, folder_name)
if not is_quiet:
print('Create folder {}'.format(full_folder.encode(default_locale)))
if not is_test:
if not os.path.isdir(full_folder):
try:
os.makedirs(full_folder)
except Exception as e:
print('Error create directory {}: {}'.format(full_folder.encode(default_locale), e))
# Copy files
for file_name, source_object in source_file_list.items():
if file_name not in dest_file_list:
dest_folder = os.path.join(dest_dir, source_object.rel_path)
if not is_quiet:
print('Copy file {} to {}'.format(source_object.get_full_name().encode(default_locale),
dest_folder.encode(default_locale)))
if not is_test:
source_object.copy_to(dest_folder)