Release 0.12
[0publish-gui.git] / implementation.py
blobcf891014e8134ec19b61c87f867c5d4dcc977b2c
1 from xml.dom import Node, minidom
3 import rox, os, pango, sys, textwrap, traceback, subprocess, time, urlparse
4 from rox import g, tasks, loading
5 import gtk.glade
7 import main
8 from xmltools import *
10 from zeroinstall.injector import model
11 from zeroinstall.zerostore import unpack, NotStored
13 RESPONSE_SAVE_AND_TEST = 1
15 class ImplementationProperties:
16 def __init__(self, feed_editor, element = None, is_group = False):
17 self.feed_editor = feed_editor
18 self.element = element
20 widgets = gtk.glade.XML(main.gladefile, 'version')
22 #attributes = g.ListStore(str, str)
23 #attr_view = widgets.get_widget('attributes')
24 #attr_view.set_model(attributes)
26 #attr_view.append_column(g.TreeViewColumn('Name'))
27 #attr_view.append_column(g.TreeViewColumn('Value'))
29 inherit_arch = widgets.get_widget('inherit_arch')
30 def shade_os_cpu():
31 s = not inherit_arch.get_active()
32 widgets.get_widget('cpu').set_sensitive(s)
33 widgets.get_widget('os').set_sensitive(s)
34 if s:
35 cpu = widgets.get_widget('cpu').get_active_text()
36 else:
37 cpu = None
38 if element:
39 parent = element.parentNode
40 while parent.nodeType == Node.ELEMENT_NODE and not cpu:
41 arch = parent.getAttribute('arch')
42 if arch and '-' in arch:
43 cpu = arch.split('-')[1]
44 parent = parent.parentNode
46 if cpu == 'src':
47 widgets.get_widget('source_frame').show()
48 else:
49 widgets.get_widget('source_frame').hide()
50 command = widgets.get_widget('compile_command')
51 if command.get_text() == '':
52 command.set_text('"$SRCDIR/configure" --prefix="$DISTDIR" && make install')
53 inherit_arch.connect('toggled', lambda cb: shade_os_cpu())
54 widgets.get_widget('cpu').connect('changed', lambda cb: shade_os_cpu())
56 main_menu = widgets.get_widget('main_binary')
57 doc_menu = widgets.get_widget('doc_dir')
59 if element:
60 if element.localName == 'group':
61 is_group = True
62 id = None
63 else:
64 id = element.getAttribute('id')
66 version = element.getAttribute('version') + \
67 (element.getAttribute('version-modifier') or '')
68 widgets.get_widget('version_number').set_text(version)
69 widgets.get_widget('released').set_text(element.getAttribute('released'))
71 widgets.get_widget('compile_command').set_text(element.getAttributeNS(XMLNS_COMPILE, 'command'))
72 widgets.get_widget('compile_binary_main').set_text(element.getAttributeNS(XMLNS_COMPILE, 'binary-main'))
73 widgets.get_widget('compile_binary_lib_mappings').set_text(element.getAttributeNS(XMLNS_COMPILE, 'binary-lib-mappings'))
75 main_binary = element.getAttribute('main')
76 doc_dir = element.getAttribute('doc-dir')
78 stability_menu = widgets.get_widget('stability')
79 stability = element.getAttribute('stability')
80 if stability:
81 i = 0
82 for row in stability_menu.get_model():
83 if row[0].lower() == stability:
84 stability_menu.set_active(i)
85 break
86 i += 1
87 else:
88 stability_menu.set_active(0)
90 main.combo_set_text(widgets.get_widget('license'), element.getAttribute('license'))
91 arch = element.getAttribute('arch')
92 if arch:
93 arch_os, arch_cpu = arch.split('-')
94 main.combo_set_text(widgets.get_widget('os'), arch_os)
95 main.combo_set_text(widgets.get_widget('cpu'), arch_cpu)
96 inherit_arch.set_active(False)
97 else:
98 widgets.get_widget('os').set_active(0)
99 widgets.get_widget('cpu').set_active(0)
101 def ok():
102 self.update_impl(element, widgets)
103 else:
104 released = widgets.get_widget('released')
106 id = '.'
107 if is_group:
108 widgets.get_widget('version_number').set_text('')
109 released.set_text('')
110 else:
111 widgets.get_widget('version_number').set_text('0.1-pre')
112 #released.set_text(time.strftime('%Y-%m-%d'))
114 widgets.get_widget('cpu').set_active(0)
115 widgets.get_widget('os').set_active(0)
116 widgets.get_widget('stability').set_active(0)
117 main_binary = None
118 doc_dir = None
120 def ok():
121 if is_group:
122 element_name = 'group'
123 else:
124 element_name = 'implementation'
125 element = create_element(self.feed_editor.doc.documentElement, element_name)
126 if not is_group:
127 element.setAttribute('id', '.')
128 try:
129 self.update_impl(element, widgets)
130 except:
131 remove_element(element)
132 raise
134 shade_os_cpu()
136 self.is_group = is_group
138 id_label = widgets.get_widget('id_label')
140 if is_group:
141 id_label.set_text('(group)')
142 elif id:
143 id_label.set_text(id)
144 if id.startswith('.') or id.startswith('/'):
145 id_label.set_sensitive(True)
146 else:
147 id_label.set_text('-')
149 def resp(dialog, r):
150 if r in (g.RESPONSE_OK, RESPONSE_SAVE_AND_TEST):
151 ok()
152 self.feed_editor.update_version_model()
153 if r == RESPONSE_SAVE_AND_TEST:
154 is_src = bool(widgets.get_widget('source_frame').flags() & gtk.VISIBLE)
155 self.feed_editor.save(lambda: self.test(element, is_src))
156 else:
157 dialog.destroy()
159 if is_group and element:
160 # Find a cached implementation for getting main
161 for x in child_elements(element):
162 if x.localName == 'implementation' and x.namespaceURI == XMLNS_INTERFACE:
163 id = x.getAttribute('id')
164 try:
165 if id and (id.startswith('.') or id.startswith('/') or main.stores.lookup(id)):
166 break
167 except NotStored, ex:
168 pass
169 if id and (element or id != '.'):
170 # Find possible main settings, if possible
171 if id.startswith('/') or id.startswith('.'):
172 cached_impl = os.path.abspath(os.path.join(os.path.dirname(feed_editor.pathname), id))
173 else:
174 try:
175 cached_impl = main.stores.lookup(id)
176 except NotStored, ex:
177 cached_impl = None
178 if cached_impl:
179 possible_mains = []
180 possible_docs = []
181 for (dirpath, dirnames, filenames) in os.walk(cached_impl):
182 relbasedir = dirpath[len(cached_impl) + 1:]
183 for file in filenames:
184 info = os.lstat(os.path.join(dirpath, file))
185 if info.st_mode & 0111:
186 new = os.path.join(relbasedir, file)
187 possible_mains.append(new)
188 for d in dirnames[:]:
189 if d.startswith('.'):
190 dirnames.remove(d)
191 else:
192 possible_docs.append(os.path.join(relbasedir, d))
193 for option in sorted(possible_mains):
194 main_menu.append_text(option)
195 for option in sorted(possible_docs):
196 doc_menu.append_text(option)
197 main.combo_set_text(main_menu, main_binary)
198 main.combo_set_text(doc_menu, doc_dir)
200 dialog = widgets.get_widget('version')
201 dialog.connect('response', resp)
203 def update_impl(self, element, widgets):
204 version = widgets.get_widget('version_number').get_text()
205 released = widgets.get_widget('released').get_text()
206 inherit_arch = widgets.get_widget('inherit_arch')
208 def get_combo(name):
209 widget = widgets.get_widget(name)
210 return widget.get_active_text()
212 cpu = get_combo('cpu')
213 os = get_combo('os')
214 license = get_combo('license')
216 widget = widgets.get_widget('stability')
217 if widget.get_active() == 0:
218 stability = None
219 else:
220 stability = get_combo('stability').lower()
222 if inherit_arch.get_active():
223 arch = None
224 else:
225 arch = os + '-' + cpu
227 main = widgets.get_widget('main_binary').get_active_text()
228 docs = widgets.get_widget('doc_dir').get_active_text()
230 old_id = element.getAttribute('id')
231 if old_id.startswith('/') or old_id.startswith('.'):
232 # Local paths are editable
233 new_id = widgets.get_widget('id_label').get_text()
234 if new_id.startswith('.') or new_id.startswith('/'):
235 element.setAttribute('id', new_id)
236 else:
237 raise Exception('Local IDs must start with "." or "/"')
239 version_modifier = None
240 if version:
241 model.parse_version(version)
242 # Was only needed for very old versions of 0launch:
243 #if '-' in version:
244 # version, version_modifier = version.split('-', 1)
245 # version_modifier = '-' + version_modifier
247 for name, value in [('version', version),
248 ('version-modifier', version_modifier),
249 ('arch', arch),
250 ('main', main),
251 ('doc-dir', docs),
252 ('released', released),
253 ('license', license),
254 ('stability', stability)]:
255 if value:
256 element.setAttribute(name, value)
257 elif element.hasAttribute(name):
258 element.removeAttribute(name)
260 # Source packages
261 if widgets.get_widget('source_frame').flags() & gtk.VISIBLE:
262 compile_command = widgets.get_widget('compile_command').get_text()
263 compile_binary_main = widgets.get_widget('compile_binary_main').get_text()
264 compile_binary_lib_mappings = widgets.get_widget('compile_binary_lib_mappings').get_text()
265 self.feed_editor.doc.documentElement.setAttribute('xmlns:compile', XMLNS_COMPILE)
266 else:
267 compile_command = compile_binary_main = compile_binary_lib_mappings = None
269 for name, value in [('command', compile_command),
270 ('binary-main', compile_binary_main),
271 ('binary-lib-mappings', compile_binary_lib_mappings)]:
272 if value:
273 element.setAttributeNS(XMLNS_COMPILE, 'compile:' + name, value)
274 elif element.hasAttributeNS(XMLNS_COMPILE, name):
275 element.removeAttributeNS(XMLNS_COMPILE, name)
277 def test(self, element, compile):
278 version = None
279 while element:
280 if element.hasAttribute('version'):
281 version = element.getAttribute('version')
282 break
283 element = element.parentNode
284 if element.namespaceURI != XMLNS_INTERFACE:
285 break
286 if element.localName != 'group':
287 break
289 if compile:
290 # TODO: 0compile doesn't allow setting the version
291 self.feed_editor.test_compile([])
292 else:
293 if version:
294 args = ['--not-before', version, '--before', version + '-0-pre9999']
295 else:
296 args = []
297 self.feed_editor.test(args)