-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmanifest
executable file
·153 lines (133 loc) · 5.17 KB
/
manifest
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
153
#!/bin/env python
from common import *
from treecomp import TreeComparer
import sys
import codecs
# Avoid problems with unicode chars when piping the output of this program
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
class ManifestTree:
def __init__(self, path):
self.old_dict = {}
for md5, fn in read_md5sum(os.path.join(path, mff)):
old_dict[fn] = md5
self.new_dict = load_tree(path)
for fn in self.new_dict:
if is_manifest_fn(fn):
del self.new_dict[fn]
self.tc = TreeComparer(self.old_dict, self.new_dict)
def is_manifest_fn(fn):
return fn.startswith("manifest-") and fn.endswith("md5")
def list_manifests(d):
return [fn for fn in os.listdir(d)
if is_manifest_fn(fn)]
def get_manifest_fn(root):
manifests = list_manifests(root)
if not manifests:
return None
assert len(manifests) == 1
return manifests[0]
def write_manifest(manifest_contents, root):
assert type(manifest_contents) == unicode
assert not list_manifests(root)
manifest_contents = manifest_contents.encode("utf8")
manifest_fn = "manifest-%s.md5" % md5sum(manifest_contents)
create_file(os.path.join(root, manifest_fn), manifest_contents)
def replace_manifest(manifest_contents, root):
old_manifests = list_manifests(root)
assert len(old_manifests) == 1
new_manifest_tmp = os.path.join(root, "manifest-%s.new" % md5sum(manifest_contents.encode("utf8")))
new_manifest = os.path.join(root, "manifest-%s.md5" % md5sum(manifest_contents.encode("utf8")))
create_file(new_manifest_tmp, manifest_contents.encode("utf8"))
old_manifest = os.path.join(root, old_manifests[0])
old_manifest_bak = os.path.join(root, old_manifests[0].replace("manifest-", "oldmanifest-"))
os.rename(old_manifest, old_manifest_bak)
os.rename(new_manifest_tmp, new_manifest)
os.unlink(old_manifest_bak)
def load_tree(path):
"""Return the current tree as a dict on the form { fn -> md5 }"""
tree = get_tree(path)
new_dict = {}
for t in tree:
if not os.path.isfile(t):
continue
if is_manifest_fn(t):
continue
new_dict[t] = md5sum_file(t)
return new_dict
def mkmanifest(tree):
"""Returns the manifest as a utf-8 encoded string"""
manifest = u""
for fn, md5 in sorted(tree.items()):
manifest += u"%s *%s\n" % (md5, fn)
assert type(manifest) == unicode
return manifest
def ugetcwd():
return os.getcwd().decode(locale.getpreferredencoding())
def cmd_init():
import locale
cwd = ugetcwd()
tree = load_tree(cwd)
manifest = mkmanifest(tree)
write_manifest(manifest, cwd)
def cmd_accept():
expected_md5 = None
if len(sys.argv) > 2:
assert len(sys.argv) == 3
expected_md5 = sys.argv[2]
tree = load_tree(ugetcwd())
manifest = mkmanifest(tree)
if expected_md5 and expected_md5 != md5sum(manifest.encode("utf8")):
print "Current tree status does not match given checksum", expected_md5, md5sum(manifest)
sys.exit(1)
replace_manifest(manifest, ugetcwd())
def cmd_diff():
old_dict = {}
manifest_fn = get_manifest_fn(".")
for md5, fn in read_md5sum(manifest_fn):
old_dict[fn] = md5
new_dict = load_tree(ugetcwd())
print "# Comparing with manifest", manifest_fn
number_of_unchanged_files, number_of_new_files, number_of_deleted_files = print_diff(old_dict, new_dict)
#print number_of_unchanged_files, "unchanged files"
print "# Set summary:", number_of_new_files, "new files,", number_of_deleted_files, "deleted files, ", len(set(new_dict.values())), "files in total"
print "# Current tree manifest md5:", md5sum(mkmanifest(new_dict).encode("utf8"))
def print_diff(old_dict, new_dict):
old_set = set(old_dict.values())
new_set = set(new_dict.values())
tc = TreeComparer(old_dict, new_dict)
for fn in sorted(tc.all_changed_filenames()):
old_md5 = old_dict.get(fn, None)
new_md5 = new_dict.get(fn, None)
set_change = " "
if tc.is_deleted(fn):
assert old_md5 and not new_md5
if old_md5 not in new_set:
set_change = " -"
print "D %s %s" % (set_change, fn)
elif tc.is_new(fn):
assert new_md5 and not old_md5
if new_md5 not in old_set:
set_change = "+ "
print "N %s %s" % (set_change, fn)
elif tc.is_modified(fn):
assert old_md5 and new_md5
a = " "
r = " "
if old_md5 not in new_set:
# Old file overwritten and lost in new set
r = "-"
if new_md5 not in old_set:
# A new file is introduced in the set
a = "+"
print "M %s %s" % (a+r, fn)
else:
assert False
number_of_unchanged_files = len(old_set & new_set)
number_of_new_files = len(new_set - old_set)
number_of_deleted_files = len(old_set - new_set)
return number_of_unchanged_files, number_of_new_files, number_of_deleted_files
def main():
cmd = sys.argv[1]
assert cmd in ("diff", "init", "accept")
eval("cmd_" + cmd + "()")
main()