Added --unsign option to remove signatures.
[0publish.git] / archive.py
blobe39e360b711ee9e5016f68158f1924dce4eef5a7
1 from xml.dom import minidom
2 from zeroinstall.zerostore import Store, manifest, unpack
3 from zeroinstall.injector import namespaces
4 import os, time, re, shutil, tempfile, sha
6 def manifest_for_dir(dir, alg):
7 algorithm = manifest.get_algorithm(alg)
8 digest = algorithm.new_digest()
9 for line in algorithm.generate_manifest(dir):
10 digest.update(line + '\n')
11 return algorithm.getID(digest)
13 def add_archive(data, url, local_file, extract, alg):
14 if local_file is None:
15 local_file = os.path.abspath(os.path.basename(url))
16 if not os.path.exists(local_file):
17 raise Exception("Use --archive-file option to specify a local copy of the archive "
18 "(default file '%s' does not exist)" % local_file)
20 doc = minidom.parseString(data)
22 if alg is None:
23 if local_file.endswith('.deb'):
24 # Debs require 0launch >= 0.20 anyway, so use the new hash to avoid
25 # problems with directory mtimes
26 alg = 'sha1new'
27 else:
28 alg = 'sha1'
30 all_impls = doc.documentElement.getElementsByTagNameNS(namespaces.XMLNS_IFACE, 'implementation')
31 tmpdir = tempfile.mkdtemp('-0publish')
32 try:
33 unpack.unpack_archive(url, file(local_file), tmpdir, extract)
34 if extract:
35 extracted = os.path.join(tmpdir, extract)
36 else:
37 extracted = tmpdir
39 archive_id = manifest_for_dir(extracted, alg)
40 finally:
41 shutil.rmtree(tmpdir)
43 local_ifaces = []
44 for impl in all_impls:
45 this_id = impl.getAttribute('id')
46 if this_id == archive_id:
47 break
48 if this_id.startswith('/') or this_id.startswith('.'):
49 local_ifaces.append(impl)
50 else:
51 if len(local_ifaces) == 0:
52 raise Exception('Nothing with id "%s", and no local implementations' % archive_id)
53 if len(local_ifaces) > 1:
54 raise Exception('Nothing with id "%s", and multiple local implementations!' % archive_id)
55 impl = local_ifaces[0]
56 impl.setAttribute('id', archive_id)
58 assert impl.getAttribute('id') == archive_id
60 nl = doc.createTextNode('\n ')
61 impl.appendChild(nl)
63 archive = doc.createElementNS(namespaces.XMLNS_IFACE, 'archive')
64 impl.appendChild(archive)
65 archive.setAttribute('href', url)
66 archive.setAttribute('size', str(os.stat(local_file).st_size))
67 if extract is not None:
68 archive.setAttribute('extract', extract)
70 nl = doc.createTextNode('\n ')
71 impl.appendChild(nl)
73 return doc.toxml()