Added --select-version option to say which implementations you want to change
[0publish.git] / digest.py
blobd2777ecaec9890c4dbd2fdc78c3843350e928989
1 from xml.dom import minidom
2 from zeroinstall.injector import namespaces
3 from zeroinstall.zerostore import manifest, Stores, NotStored
4 import xmltools
5 from logging import info
7 stores = Stores()
9 def digests(impl):
10 yield impl.getAttribute('id').split('=', 1)
11 for x in xmltools.children(impl, 'manifest-digest'):
12 for name, value in x.attributes.itemsNS():
13 if name[0] is None:
14 yield name[1], value
16 def get_version(impl):
17 while impl:
18 v = impl.getAttribute('version')
19 if v: return v
20 impl = impl.parentNode
22 def add_digest(impl, alg_name):
23 alg = manifest.get_algorithm(alg_name)
25 # Scan through the existing digests
26 # - If we've already got the one we need, return
27 # - Otherwise, find a cached implementation we can use
28 existing_path = None
29 for a, value in digests(impl):
30 digest = '%s=%s' % (a, value)
31 if a == alg_name:
32 return False # Already signed with this algorithm
33 if not existing_path:
34 try:
35 existing_path = stores.lookup(digest)
36 if existing_path:
37 existing_digest = digest
38 except NotStored:
39 pass # OK
41 if existing_path is None:
42 print "No implementations of %s cached; can't calculate new digest" % get_version(impl)
43 return False
45 info("Verifying %s", existing_path)
46 manifest.verify(existing_path, existing_digest)
48 print "Adding new digest to version %s" % get_version(impl)
50 new_digest = alg.new_digest()
51 for line in alg.generate_manifest(existing_path):
52 new_digest.update(line + '\n')
54 for md in xmltools.children(impl, 'manifest-digest'):
55 break
56 else:
57 md = xmltools.create_element(impl, 'manifest-digest')
58 md.setAttribute(alg_name, new_digest.hexdigest())
60 return True
62 def add_digests(data, alg = None):
63 doc = minidom.parseString(data)
65 if alg is None:
66 alg = 'sha1new'
68 changed = False
69 for impl in doc.documentElement.getElementsByTagNameNS(namespaces.XMLNS_IFACE, 'implementation'):
70 if impl.getAttribute('id') in "./":
71 continue # Local implementation
73 if add_digest(impl, alg):
74 changed = True
76 if changed:
77 return doc.toxml()
78 else:
79 return data