1 # Copyright (C) 2006, Thomas Leonard
2 # See http://0install.net/0compile.html
4 import sys
, os
, __main__
5 from logging
import info
6 from xml
.dom
import minidom
, XMLNS_NAMESPACE
8 from zeroinstall
.injector
import model
9 from zeroinstall
.injector
.policy
import Policy
10 from zeroinstall
import SafeException
15 "setup [ SOURCE-URI [ DIR ] ]"
17 if not os
.path
.isfile(ENV_FILE
):
18 raise SafeException("Run 0compile from a directory containing a '%s' file, or "
19 "specify a source URI as an argument." % ENV_FILE
)
21 interface
= doc
.documentElement
.getAttributeNS(None, 'interface')
26 dir = os
.path
.basename(interface
)
27 if dir.endswith('.xml'):
33 raise __main__
.UsageError()
35 interface
= model
.canonical_iface_uri(args
[0])
37 if os
.path
.exists(dir):
38 raise SafeException("Directory '%s' already exists." % dir)
40 setup(interface
, dir, prompt
= True, create_dir
= len(args
) > 0)
42 def setup(interface
, dir, prompt
, create_dir
):
46 gui_options
= '--offline'
48 # Prompt user to choose versions
49 if os
.spawnvp(os
.P_WAIT
, '0launch', ['0launch', gui_options
, '--source', '--download-only', interface
]):
50 raise SafeException('Failed to select source files.')
52 # Get the chosen versions
53 policy
= Policy(interface
, src
= True)
58 raise Exception('Internal error: required source components not found!')
60 root_iface
= policy
.get_interface(policy
.root
)
61 impl
= policy
.implementation
[root_iface
]
62 min_version
= parse_version(impl
.metadata
.get(XMLNS_0COMPILE
+ ' min-version', None))
63 if min_version
and min_version
> parse_version(__main__
.version
):
64 raise SafeException("%s-%s requires 0compile >= %s, but we are only version %s" %
65 (root_iface
.get_name(), impl
.get_version(), format_version(min_version
), __main__
.version
))
68 if os
.path
.exists(dir):
69 raise SafeException("Directory '%s' already exists." % dir)
74 save_environment(policy
)
76 def save_environment(policy
):
77 impl
= minidom
.getDOMImplementation()
79 doc
= impl
.createDocument(XMLNS_0COMPILE
, "build-environment", None)
81 root
= doc
.documentElement
82 root
.setAttributeNS(XMLNS_NAMESPACE
, 'xmlns', XMLNS_0COMPILE
)
84 root
.setAttributeNS(None, 'interface', policy
.root
)
86 for needed_iface
in policy
.implementation
:
87 iface_elem
= doc
.createElementNS(XMLNS_0COMPILE
, 'interface')
88 iface_elem
.setAttributeNS(None, 'uri', needed_iface
.uri
)
89 root
.appendChild(iface_elem
)
91 impl
= policy
.implementation
[needed_iface
]
94 impl_elem
= doc
.createElementNS(XMLNS_0COMPILE
, 'implementation')
95 impl_elem
.setAttributeNS(None, 'id', impl
.id)
96 impl_elem
.setAttributeNS(None, 'version', impl
.get_version())
97 if impl
.interface
is not needed_iface
:
98 impl_elem
.setAttributeNS(None, 'from-feed', impl
.interface
.uri
)
100 if needed_iface
.uri
== policy
.root
:
101 command
= impl
.metadata
.get(XMLNS_0COMPILE
+ ' command', None)
102 if not command
: raise SafeException("Missing 'compile:command' attribute on <implementation>.")
103 impl_elem
.setAttributeNS(XMLNS_0COMPILE
, 'command', command
)
104 binary_main
= impl
.metadata
.get(XMLNS_0COMPILE
+ ' binary-main', None)
106 impl_elem
.setAttributeNS(XMLNS_0COMPILE
, 'binary-main', binary_main
)
107 metadir
= impl
.metadata
.get(XMLNS_0COMPILE
+ ' metadir', None)
109 impl_elem
.setAttributeNS(XMLNS_0COMPILE
, 'metadir', metadir
)
111 iface_elem
.appendChild(impl_elem
)
113 for dep
in impl
.dependencies
.values():
115 dep_iface
= policy
.get_interface(dep
.interface
)
116 dep_impl
= policy
.get_implementation(dep_iface
)
118 dep_elem
= doc
.createElementNS(XMLNS_0COMPILE
, 'requires')
119 dep_elem
.setAttributeNS(None, 'interface', dep
.interface
)
120 impl_elem
.appendChild(dep_elem
)
122 for m
in dep
.metadata
:
123 if m
.startswith(XMLNS_0COMPILE
+ ' '):
124 dep_elem
.setAttributeNS(None, m
.split(' ', 1)[1], dep
.metadata
[m
])
126 for b
in dep
.bindings
:
127 if isinstance(b
, model
.EnvironmentBinding
):
128 env_elem
= doc
.createElementNS(XMLNS_0COMPILE
, 'environment')
129 env_elem
.setAttributeNS(None, 'name', b
.name
)
130 env_elem
.setAttributeNS(None, 'insert', b
.insert
)
132 env_elem
.setAttributeNS(None, 'default', b
.default
)
133 dep_elem
.appendChild(env_elem
)
135 raise Exception('Unknown binding type ' + b
)
137 doc
.writexml(file(ENV_FILE
, 'w'), addindent
= ' ', newl
= '\n')
139 __main__
.commands
.append(do_setup
)