2 Executes a set of implementations as a program.
5 # Copyright (C) 2006, Thomas Leonard
6 # See the README file for details, or visit http://0install.net.
9 from logging
import debug
, info
11 from zeroinstall
.injector
.model
import Interface
, SafeException
, EnvironmentBinding
, DistributionImplementation
, ZeroInstallImplementation
12 from zeroinstall
.injector
.iface_cache
import iface_cache
14 def do_env_binding(binding
, path
):
15 os
.environ
[binding
.name
] = binding
.get_value(path
,
16 os
.environ
.get(binding
.name
, None))
17 info("%s=%s", binding
.name
, os
.environ
[binding
.name
])
19 def execute(policy
, prog_args
, dry_run
= False, main
= None, wrapper
= None):
20 """Execute program. On success, doesn't return. On failure, raises an Exception.
21 Returns normally only for a successful dry run.
23 @precondition: C{policy.ready and policy.get_uncached_implementations() == []}
25 iface
= iface_cache
.get_interface(policy
.root
)
27 for needed_iface
in policy
.implementation
:
28 impl
= policy
.implementation
[needed_iface
]
30 _do_bindings(impl
, impl
.bindings
)
31 for dep
in impl
.requires
:
32 dep_iface
= iface_cache
.get_interface(dep
.interface
)
33 dep_impl
= policy
.get_implementation(dep_iface
)
34 if isinstance(dep_impl
, ZeroInstallImplementation
):
35 _do_bindings(dep_impl
, dep
.bindings
)
37 debug("Implementation %s is native; no bindings needed", dep_impl
)
39 root_impl
= policy
.get_implementation(iface
)
40 _execute(root_impl
, prog_args
, dry_run
, main
, wrapper
)
42 def _do_bindings(impl
, bindings
):
44 if isinstance(b
, EnvironmentBinding
):
45 do_env_binding(b
, _get_implementation_path(impl
.id))
47 def _get_implementation_path(id):
48 if id.startswith('/'): return id
49 return iface_cache
.stores
.lookup(id)
51 def execute_selections(selections
, prog_args
, dry_run
= False, main
= None, wrapper
= None):
52 """Execute program. On success, doesn't return. On failure, raises an Exception.
53 Returns normally only for a successful dry run.
56 @precondition: All implementations are in the cache.
58 sels
= selections
.selections
59 for selection
in sels
.values():
60 _do_bindings(selection
, selection
.bindings
)
61 for dep
in selection
.dependencies
:
62 dep_impl
= sels
[dep
.interface
]
63 if not dep_impl
.id.startswith('package:'):
64 _do_bindings(dep_impl
, dep
.bindings
)
66 root_impl
= sels
[selections
.interface
]
67 _execute(root_impl
, prog_args
, dry_run
, main
, wrapper
)
69 def test_selections(selections
, prog_args
, dry_run
, main
, wrapper
= None):
70 """Run the program in a child process, collecting stdout and stderr.
71 @return: the output produced by the process
76 output
= tempfile
.TemporaryFile(prefix
= '0launch-test')
83 os
.dup2(output
.fileno(), 1)
84 os
.dup2(output
.fileno(), 2)
85 execute_selections(selections
, prog_args
, dry_run
, main
)
94 info("Waiting for test process to finish...")
96 pid
, status
= os
.waitpid(child
, 0)
100 results
= output
.read()
102 results
+= "Error from child process: exit code = %d" % status
108 def _execute(root_impl
, prog_args
, dry_run
, main
, wrapper
):
109 assert root_impl
is not None
111 if root_impl
.id.startswith('package:'):
112 main
= main
or root_impl
.main
116 main
= root_impl
.main
117 elif main
.startswith('/'):
120 main
= os
.path
.join(os
.path
.dirname(root_impl
.main
), main
)
122 prog_path
= os
.path
.join(_get_implementation_path(root_impl
.id), main
)
125 raise SafeException("Implementation '%s' cannot be executed directly; it is just a library "
126 "to be used by other programs (or missing 'main' attribute)" %
129 if not os
.path
.exists(prog_path
):
130 raise SafeException("File '%s' does not exist.\n"
131 "(implementation '%s' + program '%s')" %
132 (prog_path
, root_impl
.id, main
))
134 prog_args
= ['-c', wrapper
+ ' "$@"', '-', prog_path
] + list(prog_args
)
135 prog_path
= '/bin/sh'
138 print "Would execute:", prog_path
, ' '.join(prog_args
)
140 info("Executing: %s", prog_path
)
144 os
.execl(prog_path
, prog_path
, *prog_args
)
146 raise SafeException("Failed to run '%s': %s" % (prog_path
, str(ex
)))