Removed special case of running Zero2Bundle without an argument to create
[AddApp.git] / Zero2Bundle / bundle.py
blob97af9f9e16d3111dda76982ca96f0e11449d97f6
1 import os, shutil, sys
2 import rox
3 from rox import saving
4 from xml.dom import minidom
5 import urllib2
6 import tempfile, shutil
7 from zeroinstall.injector.model import EnvironmentBinding
8 from zeroinstall.injector.iface_cache import iface_cache
9 import __main__
11 def iface_to_dir_name(iface):
12 """Pick a directory name for this interface's implementation."""
13 return iface.get_name().replace(' ', '_').replace('/', '-')
15 class BundleMaker(saving.Saveable):
16 def __init__(self, policy):
17 assert policy.ready
19 self.policy = policy
20 iface = self.policy.get_interface(policy.root)
21 self.icon = iface_cache.get_icon_path(iface)
23 self.impl = self.policy.implementation[iface]
24 if hasattr(self.impl, 'main'):
25 self.main = self.impl.main
26 else:
27 self.main = iface.main
28 if not self.main:
29 rox.alert("Interface '%s' cannot be executed directly; it is just a library "
30 "to be used by other programs (or missing 'main' attribute on the "
31 "root <interface> element)." % iface.name)
33 def save_to_file(self, path):
34 os.mkdir(path)
35 assert "'" not in self.policy.root
37 apprun = os.fdopen(os.open(os.path.join(path, 'AppRun'), os.O_CREAT | os.O_WRONLY, 0777), 'w')
38 apprun.write("""#!/bin/sh
39 # This script was created automatically by Zero2Bundle
40 APP_DIR=`dirname "$0"`
41 """)
43 iface = self.policy.get_interface(self.policy.root)
45 # Copy each implementation into the bundle and set any
46 # environment variables required to find it
47 bindings = []
48 for needed_iface in self.policy.implementation:
49 impl = self.policy.implementation[needed_iface]
50 impl_copy = os.path.join(path, iface_to_dir_name(needed_iface))
51 assert impl
52 shutil.copytree(self.policy.get_implementation_path(impl), impl_copy)
54 for dep in impl.dependencies.values():
55 for b in dep.bindings:
56 bindings.append((dep, b))
58 for (dep, binding) in bindings:
59 dep_iface = self.policy.get_interface(dep.interface)
60 if isinstance(b, EnvironmentBinding):
61 dep_name = os.path.join(iface_to_dir_name(dep_iface), b.insert)
62 apprun.write("""
63 if [ "x$%s" = x ]; then
64 %s="$APP_DIR/%s"
65 else
66 %s="$APP_DIR/%s:$%s"
68 export %s
69 """ % (b.name, b.name, dep_name, b.name, dep_name, b.name, b.name))
70 dep_impl = self.policy.get_implementation(dep_iface)
71 else:
72 print >>sys.stderr, "Warning: unknown binding type " + b
74 root_iface = self.policy.get_interface(self.policy.root)
75 root_impl = self.policy.get_implementation(root_iface)
77 impl_apprun = os.path.join(iface_to_dir_name(root_iface), root_impl.main)
78 apprun.write('exec "$APP_DIR/%s" "$@"\n' % impl_apprun)
80 apprun.close()
82 if self.icon:
83 shutil.copyfile(self.icon, os.path.join(path, '.DirIcon'))
85 if self.is_applet(root_iface):
86 os.symlink('AppRun', os.path.join(path, 'AppletRun'))
88 appinfo = os.path.join(os.path.dirname(impl_apprun), 'AppInfo.xml')
89 if os.path.exists(os.path.join(path, appinfo)):
90 os.symlink(appinfo, os.path.join(path, 'AppInfo.xml'))
92 help = os.path.join(os.path.dirname(impl_apprun), 'Help')
93 if os.path.exists(os.path.join(path, help)):
94 os.symlink(help, os.path.join(path, 'Help'))
96 def add_item(self, menu, option, labels):
97 doc = menu.ownerDocument
98 item = doc.createElement('Item')
99 kids = menu.childNodes
100 if kids:
101 menu.insertBefore(item, kids[0])
102 else:
103 menu.appendChild(item)
104 item.setAttribute('option', option)
106 for lang in labels:
107 label = doc.createElement('Label')
108 item.appendChild(label)
109 label.setAttribute('xml:lang', lang)
110 label.appendChild(doc.createTextNode(labels[lang]))
112 def get_item(self, parent, name):
113 items = parent.getElementsByTagName(name)
114 if items:
115 return items[0]
116 item = parent.ownerDocument.createElement(name)
117 parent.appendChild(item)
118 return item
120 def is_applet(self, iface):
121 impl_path = self.policy.get_implementation_path(self.impl)
122 assert impl_path
124 applet_run = os.path.join(impl_path, os.path.dirname(self.main), 'AppletRun')
125 return os.path.exists(applet_run)