Updated version.
[0publish.git] / archive.py
blob609b71e744c0e11eb31d6170e0759bda34192371
1 from xml.dom import minidom
2 from zeroinstall.zerostore import Store, manifest
3 from zeroinstall.injector import namespaces
4 import os, time, re, shutil, tempfile, sha
5 import unpack
7 def manifest_for_dir(dir):
8 digest = sha.new()
9 for line in manifest.generate_manifest(dir):
10 digest.update(line + '\n')
11 return 'sha1=' + digest.hexdigest()
13 def add_archive(data, url, local_file, extract):
14 if local_file is None:
15 raise Exception('Use --archive-file option to specify a local copy')
17 doc = minidom.parseString(data)
19 all_impls = doc.documentElement.getElementsByTagNameNS(namespaces.XMLNS_IFACE, 'implementation')
20 tmpdir = tempfile.mkdtemp('-0publish')
21 try:
22 unpack.unpack_archive(url, file(local_file), tmpdir, extract)
23 if extract:
24 extracted = os.path.join(tmpdir, extract)
25 else:
26 extracted = tmpdir
28 archive_id = manifest_for_dir(extracted)
29 finally:
30 shutil.rmtree(tmpdir)
32 local_ifaces = []
33 for impl in all_impls:
34 this_id = impl.getAttribute('id')
35 if this_id == archive_id:
36 break
37 if this_id.startswith('/') or this_id.startswith('.'):
38 local_ifaces.append(impl)
39 else:
40 if len(local_ifaces) == 0:
41 raise Exception('Nothing with id "%s", and no local implementations' % archive_id)
42 if len(local_ifaces) > 1:
43 raise Exception('Nothing with id "%s", and multiple local implementations!' % archive_id)
44 impl = local_ifaces[0]
45 impl.setAttribute('id', archive_id)
47 assert impl.getAttribute('id') == archive_id
49 nl = doc.createTextNode('\n ')
50 impl.appendChild(nl)
52 archive = doc.createElementNS(namespaces.XMLNS_IFACE, 'archive')
53 impl.appendChild(archive)
54 archive.setAttribute('href', url)
55 archive.setAttribute('size', str(os.stat(local_file).st_size))
56 if extract is not None:
57 archive.setAttribute('extract', extract)
59 nl = doc.createTextNode('\n ')
60 impl.appendChild(nl)
62 return doc.toxml()