Added missing application/x-xz-compressed-tar menu option
[0publish-gui.git] / implementation.py
blob352fdc2f8bf1d29e8d5e5d0dab81f462217d13b4
1 from xml.dom import Node
3 import os
4 import logging
5 from rox import g
6 import gtk.glade
8 import main
9 from xmltools import *
11 from zeroinstall.injector import model
12 from zeroinstall.zerostore import NotStored
14 RESPONSE_SAVE_AND_TEST = 1
16 class ImplementationProperties:
17 def __init__(self, feed_editor, element = None, is_group = False):
18 self.feed_editor = feed_editor
19 self.element = element
21 widgets = gtk.glade.XML(main.gladefile, 'version')
23 #attributes = g.ListStore(str, str)
24 #attr_view = widgets.get_widget('attributes')
25 #attr_view.set_model(attributes)
27 #attr_view.append_column(g.TreeViewColumn('Name'))
28 #attr_view.append_column(g.TreeViewColumn('Value'))
30 inherit_arch = widgets.get_widget('inherit_arch')
31 def shade_os_cpu():
32 s = not inherit_arch.get_active()
33 widgets.get_widget('cpu').set_sensitive(s)
34 widgets.get_widget('os').set_sensitive(s)
35 if s:
36 cpu = widgets.get_widget('cpu').get_active_text()
37 else:
38 cpu = None
39 if element:
40 parent = element.parentNode
41 while parent.nodeType == Node.ELEMENT_NODE and not cpu:
42 arch = parent.getAttribute('arch')
43 if arch and '-' in arch:
44 cpu = arch.split('-')[1]
45 parent = parent.parentNode
47 if cpu == 'src':
48 widgets.get_widget('source_frame').show()
49 else:
50 widgets.get_widget('source_frame').hide()
51 command = widgets.get_widget('compile_command')
52 if command.get_text() == '':
53 command.set_text('"$SRCDIR/configure" --prefix="$DISTDIR" && make install')
54 inherit_arch.connect('toggled', lambda cb: shade_os_cpu())
55 widgets.get_widget('cpu').connect('changed', lambda cb: shade_os_cpu())
57 main_menu = widgets.get_widget('main_binary')
58 doc_menu = widgets.get_widget('doc_dir')
60 if element:
61 if element.localName == 'group':
62 is_group = True
63 id = None
64 else:
65 id = element.getAttribute('id')
67 version = element.getAttribute('version') + \
68 (element.getAttribute('version-modifier') or '')
69 widgets.get_widget('version_number').set_text(version)
70 widgets.get_widget('released').set_text(element.getAttribute('released'))
72 widgets.get_widget('compile_command').set_text(element.getAttributeNS(XMLNS_COMPILE, 'command'))
73 widgets.get_widget('compile_binary_main').set_text(element.getAttributeNS(XMLNS_COMPILE, 'binary-main'))
74 widgets.get_widget('compile_binary_lib_mappings').set_text(element.getAttributeNS(XMLNS_COMPILE, 'binary-lib-mappings'))
76 main_binary = element.getAttribute('main')
77 doc_dir = element.getAttribute('doc-dir')
79 stability_menu = widgets.get_widget('stability')
80 stability = element.getAttribute('stability')
81 if stability:
82 i = 0
83 for row in stability_menu.get_model():
84 if row[0].lower() == stability:
85 stability_menu.set_active(i)
86 break
87 i += 1
88 else:
89 stability_menu.set_active(0)
91 main.combo_set_text(widgets.get_widget('license'), element.getAttribute('license'))
92 arch = element.getAttribute('arch')
93 if arch:
94 arch_os, arch_cpu = arch.split('-')
95 main.combo_set_text(widgets.get_widget('os'), arch_os)
96 main.combo_set_text(widgets.get_widget('cpu'), arch_cpu)
97 inherit_arch.set_active(False)
98 else:
99 widgets.get_widget('os').set_active(0)
100 widgets.get_widget('cpu').set_active(0)
102 def ok():
103 self.update_impl(element, widgets)
104 else:
105 released = widgets.get_widget('released')
107 id = '.'
108 if is_group:
109 widgets.get_widget('version_number').set_text('')
110 released.set_text('')
111 else:
112 widgets.get_widget('version_number').set_text('0.1-pre')
113 #released.set_text(time.strftime('%Y-%m-%d'))
115 widgets.get_widget('cpu').set_active(0)
116 widgets.get_widget('os').set_active(0)
117 widgets.get_widget('stability').set_active(0)
118 main_binary = None
119 doc_dir = None
121 def ok():
122 if is_group:
123 element_name = 'group'
124 else:
125 element_name = 'implementation'
126 element = create_element(self.feed_editor.doc.documentElement, element_name)
127 if not is_group:
128 element.setAttribute('id', '.')
129 try:
130 self.update_impl(element, widgets)
131 except:
132 remove_element(element)
133 raise
135 shade_os_cpu()
137 self.is_group = is_group
139 id_label = widgets.get_widget('id_label')
141 if is_group:
142 id_label.set_text('(group)')
143 elif id:
144 id_label.set_text(id)
145 if id.startswith('.') or id.startswith('/'):
146 id_label.set_sensitive(True)
147 else:
148 id_label.set_text('-')
150 def resp(dialog, r):
151 if r in (g.RESPONSE_OK, RESPONSE_SAVE_AND_TEST):
152 ok()
153 self.feed_editor.update_version_model()
154 if r == RESPONSE_SAVE_AND_TEST:
155 is_src = bool(widgets.get_widget('source_frame').flags() & gtk.VISIBLE)
156 self.feed_editor.save(lambda: self.test(element, is_src))
157 else:
158 dialog.destroy()
160 if is_group and element:
161 # Find a cached implementation for getting main
162 for x in child_elements(element):
163 if x.localName == 'implementation' and x.namespaceURI == XMLNS_INTERFACE:
164 id = x.getAttribute('id')
165 try:
166 if id and (id.startswith('.') or id.startswith('/') or main.stores.lookup(id)):
167 break
168 except NotStored, ex:
169 pass
171 if element:
172 feed = feed_editor.get_as_feed()
173 impl = feed.implementations.get(id)
174 cached_impl = (impl.local_path or main.stores.lookup_maybe(impl.digests)) if impl else None
175 elif id.startswith('/') or id.startswith('.'):
176 cached_impl = os.path.abspath(os.path.join(os.path.dirname(feed_editor.pathname), id))
177 else:
178 cached_impl = main.stores.lookup_maybe([id])
180 if cached_impl:
181 try:
182 possible_mains = []
183 possible_docs = []
184 for (dirpath, dirnames, filenames) in os.walk(cached_impl):
185 relbasedir = dirpath[len(cached_impl) + 1:]
186 for file in filenames:
187 info = os.lstat(os.path.join(dirpath, file))
188 if info.st_mode & 0111:
189 new = os.path.join(relbasedir, file)
190 possible_mains.append(new)
191 for d in dirnames[:]:
192 if d.startswith('.'):
193 dirnames.remove(d)
194 else:
195 possible_docs.append(os.path.join(relbasedir, d))
196 for option in sorted(possible_mains):
197 main_menu.append_text(option)
198 for option in sorted(possible_docs):
199 doc_menu.append_text(option)
200 except OSError as ex:
201 logging.warning("Failed to scan directory {dir}: {ex}".format(dir = cached_impl, ex = ex))
203 main.combo_set_text(main_menu, main_binary)
204 main.combo_set_text(doc_menu, doc_dir)
206 dialog = widgets.get_widget('version')
207 dialog.connect('response', resp)
209 def update_impl(self, element, widgets):
210 version = widgets.get_widget('version_number').get_text()
211 released = widgets.get_widget('released').get_text()
212 inherit_arch = widgets.get_widget('inherit_arch')
214 def get_combo(name):
215 widget = widgets.get_widget(name)
216 return widget.get_active_text()
218 cpu = get_combo('cpu')
219 os = get_combo('os')
220 license = get_combo('license')
222 widget = widgets.get_widget('stability')
223 if widget.get_active() == 0:
224 stability = None
225 else:
226 stability = get_combo('stability').lower()
228 if inherit_arch.get_active():
229 arch = None
230 else:
231 arch = os + '-' + cpu
233 main = widgets.get_widget('main_binary').get_active_text()
234 docs = widgets.get_widget('doc_dir').get_active_text()
236 old_id = element.getAttribute('id')
237 if old_id.startswith('/') or old_id.startswith('.'):
238 # Local paths are editable
239 new_id = widgets.get_widget('id_label').get_text()
240 if new_id.startswith('.') or new_id.startswith('/'):
241 element.setAttribute('id', new_id)
242 else:
243 raise Exception('Local IDs must start with "." or "/"')
245 version_modifier = None
246 if version:
247 model.parse_version(version)
248 # Was only needed for very old versions of 0launch:
249 #if '-' in version:
250 # version, version_modifier = version.split('-', 1)
251 # version_modifier = '-' + version_modifier
253 for name, value in [('version', version),
254 ('version-modifier', version_modifier),
255 ('arch', arch),
256 ('main', main),
257 ('doc-dir', docs),
258 ('released', released),
259 ('license', license),
260 ('stability', stability)]:
261 if value:
262 element.setAttribute(name, value)
263 elif element.hasAttribute(name):
264 element.removeAttribute(name)
266 # Source packages
267 if widgets.get_widget('source_frame').flags() & gtk.VISIBLE:
268 compile_command = widgets.get_widget('compile_command').get_text()
269 compile_binary_main = widgets.get_widget('compile_binary_main').get_text()
270 compile_binary_lib_mappings = widgets.get_widget('compile_binary_lib_mappings').get_text()
271 self.feed_editor.doc.documentElement.setAttribute('xmlns:compile', XMLNS_COMPILE)
272 else:
273 compile_command = compile_binary_main = compile_binary_lib_mappings = None
275 for name, value in [('command', compile_command),
276 ('binary-main', compile_binary_main),
277 ('binary-lib-mappings', compile_binary_lib_mappings)]:
278 if value:
279 element.setAttributeNS(XMLNS_COMPILE, 'compile:' + name, value)
280 elif element.hasAttributeNS(XMLNS_COMPILE, name):
281 element.removeAttributeNS(XMLNS_COMPILE, name)
283 def test(self, element, compile):
284 version = None
285 while element:
286 if element.hasAttribute('version'):
287 version = element.getAttribute('version')
288 break
289 element = element.parentNode
290 if element.namespaceURI != XMLNS_INTERFACE:
291 break
292 if element.localName != 'group':
293 break
295 if compile:
296 # TODO: 0compile doesn't allow setting the version
297 self.feed_editor.test_compile([])
298 else:
299 if version:
300 args = ['--not-before', version, '--before', version + '-0-pre9999']
301 else:
302 args = []
303 self.feed_editor.test(args)