Added --main option, for packages containing multiple executables.
[zeroinstall.git] / zeroinstall / injector / run.py
blobca43457ef2ed7867e2da8e58967c226b51ccdba2
1 import os, sys
2 from logging import debug, info
4 from model import Interface, SafeException, EnvironmentBinding
6 def do_env_binding(binding, path):
7 extra = os.path.join(path, binding.insert)
8 if binding.name in os.environ:
9 os.environ[binding.name] = extra + ':' + os.environ[binding.name]
10 else:
11 os.environ[binding.name] = extra
12 info("%s=%s", binding.name, os.environ[binding.name])
14 def execute(policy, prog_args, dry_run = False, main = None):
15 iface = policy.get_interface(policy.root)
16 if main is None and not iface.main:
17 raise SafeException("Interface '%s' cannot be executed directly; it is just a library "
18 "to be used by other programs (or missing 'main' attribute on the "
19 "root <interface> element)." % iface.name)
21 def setup_bindings(i):
22 impl = policy.get_implementation(i)
23 for dep in impl.dependencies.values():
24 dep_iface = policy.get_interface(dep.interface)
25 for b in dep.bindings:
26 if isinstance(b, EnvironmentBinding):
27 dep_impl = policy.get_implementation(dep_iface)
28 do_env_binding(b, policy.get_implementation_path(dep_impl))
29 setup_bindings(dep_iface)
30 setup_bindings(iface)
32 root_impl = policy.get_implementation(iface)
33 if main is None:
34 main = iface.main
35 elif main.startswith('/'):
36 main = main[1:]
37 elif iface.main:
38 main = os.path.join(os.path.dirname(iface.main), main)
39 prog_path = os.path.join(policy.get_implementation_path(root_impl), main)
40 if not os.path.exists(prog_path):
41 raise SafeException("File '%s' does not exist.\n"
42 "(implementation '%s' + program '%s')" %
43 (prog_path, policy.implementation[iface].id, main))
44 if dry_run:
45 print "Would execute:", prog_path
46 else:
47 info("Executing: %s", prog_path)
48 sys.stdout.flush()
49 sys.stderr.flush()
50 os.execl(prog_path, prog_path, *prog_args)