Author: hadess
Update of /cvs/pkgs/rpms/codeina/devel In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv19098
Modified Files: codeina.spec Added Files: codeina-f8-wishlist.patch Removed Files: codeina-python-dirs.patch Log Message: * Mon Oct 01 2007 - Bastien Nocera bnocera@redhat.com - 0.10.1-2 - Big patch from myself (fixes from Thomas) to: - Show a title to the price column (#299251) - Not redownload already downloaded packages, and check whether corrupted (#305421) - Select free matching codecs by default (#305411) - Clearly show an empty list and a warning when no codecs match the required ones, so users don't get confused
codeina-f8-wishlist.patch:
--- NEW FILE codeina-f8-wishlist.patch --- Index: ChangeLog =================================================================== --- ChangeLog (revision 827) +++ ChangeLog (working copy) @@ -1,3 +1,24 @@ +2007-09-29 Thomas Vander Stichele <thomas at apestaart dot org> + + patch by: Bastien Nocera + + * codeina/httpdownload.py: + * codeina/listview.py: + * codeina/main.py: + * codeina/productlist.py: + * codeina/requiredplugin.py: + * data/available-plugins.xml.in: + Add sha1sums to plugins, and use it to verify plugin download. + See https://bugzilla.redhat.com/show_bug.cgi?id=305421 + Add price column header. + See https://bugzilla.redhat.com/show_bug.cgi?id=299251 + Select free and matching codecs by default. + See https://bugzilla.redhat.com/show_bug.cgi?id=305411 + Don't silently switch to the "all available" view when requesting a + plugin that's not available, instead, show an empty list, and + error + message with an explanation on how to see all the plugins + === release 0.10.1 ===
2007-08-27 Thomas Vander Stichele <thomas at apestaart dot org> Index: codeina/requiredplugin.py =================================================================== --- codeina/requiredplugin.py (revision 827) +++ codeina/requiredplugin.py (working copy) @@ -51,6 +51,10 @@ if self.req_type in self.valid_req_types: self.valid = True
+ def __repr__(self): + return "<%s for %s> " % (self.__class__.__name__, self.req_string) + + # currently we're only interested in specialising mp3, we should probably # do something more generic later that covers other common formats too def is_mp3_decoder(self): Index: codeina/listview.py =================================================================== --- codeina/listview.py (revision 827) +++ codeina/listview.py (working copy) @@ -35,6 +35,10 @@
class ListView(gtk.VBox): + """ + @ivar productlist: list of products, set when creating the listview + @type productlist: L{codeina.productlist.ProductList} + """
def __init__(self): gtk.VBox.__init__(self) @@ -53,7 +57,9 @@ self.view = gtk.TreeView() row_height = self.get_estimated_row_height() row_padding = 2 # assumed, random number - self.view.set_size_request(-1, (row_height + row_padding) * 8) + headers_height = 12 # assumed + self.view.set_size_request(-1, + (row_height + row_padding) * 8 + headers_height) self.productlist = None self.store = gtk.ListStore(object) self.store.set_default_sort_func(self.sort_func, self) @@ -61,9 +67,8 @@ self.model = self.store.filter_new() self.model.set_visible_func(self.visible_func, self) self.view.set_model(self.model) - self.view.set_headers_visible(False) self.view.set_rules_hint(True) - column = gtk.TreeViewColumn("product") + column = gtk.TreeViewColumn(_("Product")) text_renderer = gtk.CellRendererText() text_renderer.set_property('xpad', 6) text_renderer.set_property('ypad', 3) @@ -79,7 +84,7 @@ # the expand property to False, so that things behave right if the # user makes the window wider
- column = gtk.TreeViewColumn('install-status') + column = gtk.TreeViewColumn(_('Installed?')) status_renderer = gtk.CellRendererText() column.pack_start(status_renderer, True) status_renderer.set_property('xalign', 0.5) @@ -90,7 +95,7 @@ column.set_expand(False) self.view.append_column(column)
- column = gtk.TreeViewColumn('price') + column = gtk.TreeViewColumn(_('Price')) price_renderer = gtk.CellRendererText() column.pack_end(price_renderer, False) price_renderer.set_property('xalign', 1.0) @@ -102,7 +107,7 @@
# Put check boxes in separate column for nicer activation
- column = gtk.TreeViewColumn("toggle") + column = gtk.TreeViewColumn("") toggle_renderer = gtk.CellRendererToggle() toggle_renderer.set_property('activatable', True) toggle_renderer.connect('toggled', self.cell_toggled_cb, self) @@ -145,13 +150,16 @@ return False flav = product.get_best_flavor_for_current_system() if not flav: + print "product %r does not have flavor" % product product.set_selected(False) return False if not self.required_plugins: return True else: + print "Checking visibility of product %r" % product for req in self.required_plugins: if product.provides_requirement(req): + print "provides requirement %r, showing" % req return True return False
@@ -229,7 +237,7 @@ data): product = tree_model.get_value(tree_iter, 0) if product.price: - renderer.set_property('text', "%.0f€" % product.price) + renderer.set_property('text', "%.0f €" % product.price) else: renderer.set_property('text', _("Free")) return @@ -238,11 +246,16 @@ self.store.clear() if self.productlist: for p in self.productlist.products: + print "appending product %r" % p row = self.store.append() self.store.set_value(row, 0, p) return
def set_product_list(self, product_list): + """ + @ivar productlist: list of products the view should handle + @type productlist: L{codeina.productlist.ProductList} + """ if self.productlist != product_list: self.productlist = product_list self.fill_with_products() Index: codeina/httpdownload.py =================================================================== --- codeina/httpdownload.py (revision 827) +++ codeina/httpdownload.py (working copy) @@ -31,7 +31,9 @@ import thread import urllib2 import xdg.BaseDirectory +import sha
+from codeina.extern.log import log from gettext import gettext as _
# Defaults to ~/.local/share/codeina/downloads/ in most cases @@ -43,7 +45,7 @@ Downloads a HTTP URI to file in a separate thread and iterates the GLib/Gtk main context until either the download is done or an error occurred """ -class HttpDownload: +class HttpDownload(log.Loggable): """ @ivar content_length: size in bytes of the download """ @@ -59,6 +61,7 @@
def __init__ (self): self.url = None + self.sha1sum = None self.directory = None self.fn = None self.done = False @@ -71,7 +74,7 @@ def get_error_msg_from_error(self, err): msg = _("Unexpected error of type %s") % type(err) try: - raise err + raise err except urllib2.HTTPError, e: if e.code == 403: msg = _("Access to this file is forbidden") @@ -105,7 +108,11 @@ return msg
""" Iterates the default GLib main context until the download is done """ - def run(self, url, directory, fn, message=None): + def run(self, url, directory, fn, sha1sum, message=None): + self.debug("Running download for %s (sha1sum=%s)" % (os.path.join(directory, fn), sha1sum)) + if sha1sum and self.verify(os.path.join(directory, fn), sha1sum): + self.debug("Already downloaded %s" % os.path.join(directory, fn)) + return None
if self.url: return _("Download already in progress") @@ -116,6 +123,7 @@ self.url = url self.directory = directory self.fn = fn + self.sha1sum = sha1sum self.done = False self.err = None self.bytes_read = -1 @@ -165,6 +173,23 @@
return not self.done
+ """ Check whether a file matches the SHA1 sum given """ + def verify(self, fn, sha1sum): + if not sha1sum: + self.debug("No sha1sum or filename, can't check (%s), " + "so assuming true" % fn) + return True + + fs = open(fn,'rb').read() + real_sha1sum = sha.new(fs).hexdigest() + if real_sha1sum == sha1sum: + self.debug("%s matched its sha1sum" % fn) + return True + + self.debug("%s didn't match its sha1sum (got %s expected %s)" % ( + fn, real_sha1sum, sha1sum)) + return False + """ Thread where all the downloading and file writing happens """ def thread_func(self):
@@ -191,8 +216,8 @@ pass
# Now create a temp file there - tmpfile_handle, tmpfile_path = tempfile.mkstemp('.incomplete',\ - 'codeina-download',\ + tmpfile_handle, tmpfile_path = tempfile.mkstemp('.incomplete', + 'codeina-download', self.directory)
while not self.cancelled: @@ -211,6 +236,12 @@ os.remove(tmpfile_path) except: pass + elif not self.verify(tmpfile_path, self.sha1sum): + try: + os.remove(tmpfile_path) + except: + pass + err = _("Downloaded file is corrupted") else: os.rename(tmpfile_path, os.path.join(self.directory, self.fn))
@@ -277,11 +308,11 @@ def destroy(self): self.dlg.destroy()
- def run(self, url, directory, fn, message): + def run(self, url, directory, fn, sha1sum, message): if message: self.set_dialog_text(message) self.dlg.present() - err = HttpDownload.run(self, url, directory, fn, None) + err = HttpDownload.run(self, url, directory, fn, sha1sum, None) self.dlg.hide() return err
@@ -310,11 +341,16 @@
if __name__ == "__main__": - # Different URLs for different errors + log.init('CODEINA_DEBUG') + log.setPackageScrubList('codeina') + + # Different URLs for different errors #url='http://shop.fluendo.com/images/mpeg.png' #url='http://shop.fluendo.com/tpm-codeina-test.bz2' #url='http://example.com/gimme-a-404' - url='http://antihost.atari/tpm-codeina-test.bz2' + #url='http://antihost.atari/tpm-codeina-test.bz2' + url="http://shop.fluendo.com/pub/fluendo-mp3-2.i386.tar.bz2" + sha1sum='117f85e118dab2d9f7c9bb10554fbc4e8f7fdf38'
download_dir = DEFAULT_DOWNLOAD_DIR
@@ -322,7 +358,7 @@
# Do the downloading, with dialog d = HttpDownloadDialog() - e = d.run(url, download_dir, fn, "Downloading '%s'" % fn) + e = d.run(url, download_dir, fn, sha1sum, "Downloading '%s'" % fn) if d.cancelled: print "Download cancelled" elif e: Index: codeina/productlist.py =================================================================== --- codeina/productlist.py (revision 827) +++ codeina/productlist.py (working copy) @@ -103,13 +103,19 @@ d['summary'] = self._get_localized(summaries) d['flavors'] = flavors product = Product(**d) + + # Select the free-not-fully-installed plugins by default + if price == 0.0: + product.selected = not product.is_fully_installed() + return product
def _parse_flavor(self, node): d = {} required = ('system', 'arch', 'distro', 'distro-version', 'core-req', 'base-req', 'last-modified', 'uri', 'comment') - attrs = self.parseAttributes(node, required=required) + optional = ('sha1sum',) + attrs = self.parseAttributes(node, required=required, optional=optional) for i in range(0, len(required)): # pesky - -> _ translation for attributes key = '_'.join(required[i].split('-')) @@ -125,7 +131,6 @@ flavor = ProductFlavor(**d) return flavor
- def _parse_name(self, node): # parse a name and its language # return tuple of language, name @@ -204,6 +209,9 @@
selected = False # for list view
+ def __repr__(self): + return "<%s for %s> " % (self.__class__.__name__, self.name) + def get_selected(self): return self.selected
@@ -398,6 +406,7 @@ version = None uri = None comment = None + sha1sum = None
def is_compatible(self, system, arch, distro, core_version, base_version): @@ -418,18 +427,22 @@
if __name__ == "__main__": - plist = ProductList() - try: - plist.read_from_xml(open("available-plugins.xml").read()) - print "done, %d products:" % len(plist.products) - for p in plist.products: - print " * %s (%.2f EUR)" % (p.name, p.price) - for f in p.flavors: - print " - %s %s %s" % (f.system, f.arch, f.distro) - except: - print "oops, couldn't parse products XML list" + xml_data = open("../data/available-plugins.xml") + parser = ProductListParser() + plist = parser.parse(xml_data) + print "done, %d products:" % len(plist.products) + for p in plist.products: + print " * %s (%.2f EUR)" % (p.name, p.price) + for f in p.flavors: + print " - %s %s %s %s %s" % (f.system, f.arch, f.distro, os.path.basename(f.uri), f.sha1sum)
-# flavs = plist.products[0].find_compatible_flavors ("Linux", "ppc64", None, Version("0.10.9"), Version ("0.10.9")) -# print "Matching flavors:" -# for f in flavs: -# print " - %s %s %s %s" % (f.product.name, f.system, f.arch, f.distro) + f = plist.products[9].get_best_flavor_for_current_system() + print "Best flavor:" + print " - %s %s %s %s %s" % (f.system, f.arch, f.distro, os.path.basename(f.uri), f.sha1sum) + + flavs = plist.products[9].find_compatible_flavors ("Linux", "i386", None, check.Version("0.10.4"), check.Version("0.10.4")) +# flavs = plist.products[0].find_compatible_flavors ("Linux", "ppc64", None, Version("0.10.9"), Version ("0.10.9")) + print "Matching flavors:" + for f in flavs: + print " - %s %s %s %s %s" % (f.system, f.arch, f.distro, os.path.basename(f.uri), f.sha1sum) + Index: codeina/main.py =================================================================== --- codeina/main.py (revision 827) +++ codeina/main.py (working copy) @@ -241,6 +241,18 @@
self.vbox.pack_start(self.listview, True)
+ # The label showing we have no matching plugins + + self.no_plugins_box = gtk.HBox() + img = gtk.Image() + img.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) + self.no_plugins_box.pack_start(img, False, 0, 6) + label = gtk.Label( + _("There are no plugins available for the requested functionality.") + + "\n" + _("Please select the full plugins list in the View menu.")) + self.no_plugins_box.pack_start(label, False) + self.vbox.pack_start(self.no_plugins_box, False) + # status bar
self.statusbar = gtk.Statusbar() @@ -248,13 +260,15 @@ self.statusbar.show() self.vbox.pack_end(self.statusbar, False)
- # only show matching plugin packages if there are required plugins (?) + # only show matching plugin packages if there are required plugins
if self.required_plugins and len(self.required_plugins) > 0: + self.debug("Showing the matching plugins list") self.actiongroup.get_action('ViewMatching').set_active(True) else: + self.debug("Showing all the plugins") self.actiongroup.get_action('ViewAllAvailable').set_active(True) - self.actiongroup.get_action('ViewMatching').set_visible(False) + self.actiongroup.get_action('ViewMatching').set_sensitive(False)
# button box
@@ -341,7 +355,7 @@ button.set_property('can-default', True) return button
- def download_uri(self, dialog, name, uri): + def download_uri(self, dialog, name, uri, sha1sum): """ Download the given uri.
@@ -352,7 +366,8 @@ self.debug("Trying to download '%s'" % uri) dl_dir = DEFAULT_DOWNLOAD_DIR fn = os.path.basename(uri) - err_msg = dialog.run(uri, dl_dir, fn, _("Downloading '%s'") % name) + err_msg = dialog.run(uri, dl_dir, fn, sha1sum, + _("Downloading '%s'") % name) if dialog.cancelled: self.debug("Download cancelled") return None @@ -378,7 +393,7 @@
Returns: whether the EULA was accepted. """ - path = self.download_uri(dialog, name, eula_uri) + path = self.download_uri(dialog, name, eula_uri, None) if not path: self.debug('Could not download EULA') return False @@ -412,7 +427,10 @@ continue
flavor = p.get_best_flavor_for_current_system() - path = self.download_uri(d, p.name, flavor.uri) + self.debug("Selected flavour %s %s %s %s %s" % ( + flavor.system, flavor.arch, flavor.distro, + os.path.basename(flavor.uri), flavor.sha1sum)) + path = self.download_uri(d, p.name, flavor.uri, flavor.sha1sum)
if not path: self.debug('User cancelled') @@ -513,8 +531,12 @@ self.listview.show_matching(self.required_plugins) no_rows_txt = _( 'No matching plugins available for your system yet.') + if self.listview.get_visible_rows() == 0: self.set_status_text(no_rows_txt) + self.no_plugins_box.show_all() + else: + self.no_plugins_box.hide()
def do_install(self, filenames): failed_installs = [] Index: data/available-plugins.xml.in =================================================================== --- data/available-plugins.xml.in (revision 827) +++ data/available-plugins.xml.in (working copy) @@ -50,13 +50,15 @@ core-req="0.10.3" base-req="0.10.3" last-modified="2007-05-25" uri="http://shop.fluendo.com/pub/fluendo-mp3-2.i386.tar.bz2" - comment="Tested on FC3, FC4, FC5, and Ubuntu 6.10 (edgy)" + comment="Tested on FC3, FC4, FC5, and Ubuntu 6.10 (edgy)" + sha1sum="117f85e118dab2d9f7c9bb10554fbc4e8f7fdf38" /> <flavor system="Linux" arch="x86_64" distro="generic" distro-version="any" core-req="0.10.3" base-req="0.10.3" last-modified="2007-05-25" uri="http://shop.fluendo.com/pub/fluendo-mp3-2.x86_64.tar.bz2" - comment="" + comment="" + sha1sum="47e2169453c4025e88edd6e4e1b64da26cbf64c6" /> </product>
Index: codeina.spec =================================================================== RCS file: /cvs/pkgs/rpms/codeina/devel/codeina.spec,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- codeina.spec 27 Aug 2007 15:17:49 -0000 1.4 +++ codeina.spec 30 Sep 2007 23:25:40 -0000 1.5 @@ -6,7 +6,7 @@
Name: codeina Version: 0.10.1 -Release: 1%{?dist} +Release: 2%{?dist} Summary: GStreamer Codec Installation Application
Group: Applications/Internet @@ -15,6 +15,7 @@ # Upstream SVN repository is at https://core.fluendo.com/gstreamer/svn/codeina/trunk/ Source: http://www.fluendo.com/downloads/codeina/%%7Bname%7D-%%7Bversion%7D.tar.bz2 Source1: gst-install-plugins-helper.sh +Patch0: codeina-f8-wishlist.patch BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
Requires: python >= 2.3 @@ -35,6 +36,7 @@
%prep %setup -q +%patch0 -p0 -b .old
%build %configure @@ -62,6 +64,15 @@ %{_datadir}/%{name}/
%changelog +* Mon Oct 01 2007 - Bastien Nocera bnocera@redhat.com - 0.10.1-2 +- Big patch from myself (fixes from Thomas) to: +- Show a title to the price column (#299251) +- Not redownload already downloaded packages, and check whether corrupted + (#305421) +- Select free matching codecs by default (#305411) +- Clearly show an empty list and a warning when no codecs match the required + ones, so users don't get confused + * Mon Aug 27 2007 Thomas Vander Stichele <thomas at apestaart dot org> - 0.10.1-1 - New release
--- codeina-python-dirs.patch DELETED ---
scm-commits@lists.fedoraproject.org