diff options
Diffstat (limited to 'UpdateManager')
| -rw-r--r-- | UpdateManager/Common/DistInfo.py | 32 | ||||
| -rw-r--r-- | UpdateManager/Common/aptsources.py | 53 | ||||
| -rw-r--r-- | UpdateManager/DistUpgradeFetcher.py | 2 | ||||
| -rw-r--r-- | UpdateManager/UpdateManager.py | 112 |
4 files changed, 81 insertions, 118 deletions
diff --git a/UpdateManager/Common/DistInfo.py b/UpdateManager/Common/DistInfo.py index 81f08200..8153f04b 100644 --- a/UpdateManager/Common/DistInfo.py +++ b/UpdateManager/Common/DistInfo.py @@ -48,7 +48,6 @@ class Component: self.name = "" self.description = "" self.description_long = "" - self.enabled = None class DistInfo: def __init__(self, @@ -85,7 +84,7 @@ class DistInfo: if suite: if component: suite.components["%s" % component.name] = \ - (component.description, component.enabled, + (component.description, component.description_long) component = None self.suites.append (suite) @@ -100,6 +99,13 @@ class DistInfo: for nanny in self.suites: if nanny.name == value: nanny.children.append(suite) + # reuse some properties of the parent suite + if suite.match_uri == None: + suite.match_uri = nanny.match_uri + if suite.valid_mirrors == None: + suite.valid_mirrors = nanny.valid_mirrors + if suite.base_uri == None: + suite.base_uri = nanny.base_uri elif field == 'Available': suite.available = value elif field == 'RepositoryType': @@ -110,22 +116,23 @@ class DistInfo: elif field == 'MatchURI': suite.match_uri = value elif field == 'MirrorsFile': - suite.valid_mirrors = filter(lambda s: - ((s != "") and - (not s.startswith("#"))), - map(string.strip, - open(value))) + if os.path.exists(value): + suite.valid_mirrors = filter(lambda s: + ((s != "") and + (not s.startswith("#"))), + map(string.strip, + open(value))) + else: + print "WARNING: can't read '%s'" % value elif field == 'Description': suite.description = _(value) elif field == 'Component': if component: suite.components["%s" % component.name] = \ - (component.description, component.enabled, + (component.description, component.description_long) component = Component () component.name = value - elif field == 'Enabled': - component.enabled = bool(int(value)) elif field == 'CompDescription': component.description = _(value) elif field == 'CompDescriptionLong': @@ -133,7 +140,7 @@ class DistInfo: if suite: if component: suite.components["%s" % component.name] = \ - (component.description, component.enabled, + (component.description, component.description_long) component = None self.suites.append (suite) @@ -152,7 +159,6 @@ if __name__ == "__main__": for component in suite.components: print " %s - %s - %s - %s" % (component, suite.components[component][0], - suite.components[component][1], - suite.components[component][2]) + suite.components[component][1]) for child in suite.children: print " %s" % child.description diff --git a/UpdateManager/Common/aptsources.py b/UpdateManager/Common/aptsources.py index bc6886d9..836b8fae 100644 --- a/UpdateManager/Common/aptsources.py +++ b/UpdateManager/Common/aptsources.py @@ -87,7 +87,6 @@ class SourceEntry: file = apt_pkg.Config.FindDir("Dir::Etc")+apt_pkg.Config.Find("Dir::Etc::sourcelist") self.file = file # the file that the entry is located in self.parse(line) - # FIXME: this name is really misleading and already overloaded self.template = None # type DistInfo.Suite self.children = [] @@ -373,56 +372,6 @@ class SourcesList: #print self.parents return (parents, used_child_templates) -# templates for the add dialog -class SourceEntryTemplate(SourceEntry): - def __init__(self,a_type,uri,dist,description,comps): - self.comps_descriptions = [] - self.type = a_type - self.uri = uri - self.dist = dist - self.description = description - self.comps = comps - - def matches(self,source_entry): - """ check if a given source_entry matches this one """ - if (self.type != source_entry.type): - return False - if (self.dist != source_entry.dist): - return False - if not is_mirror(self.uri,source_entry.uri): - return False - for e_comp in source_entry.comps: - for t_comp in self.comps: - if e_comp == t_comp.name: break - else: - return False - return True - -class SourceCompTemplate: - def __init__(self, name, description, on_by_default): - self.name = name - self.description = description - self.on_by_default = on_by_default - -class SourceEntryTemplates: - - def __init__(self,datadir): - _ = gettext.gettext - self.templates = [] - - dinfo = DistInfo (base_dir=datadir+"channels/") - - for suite in dinfo.suites: - comps = [] - for comp in suite.components: - comps.append(SourceCompTemplate(comp.name, _(comp.description), - comp.enabled)) - self.templates.append (SourceEntryTemplate(suite.repository_type, - suite.base_uri, - suite.name, - suite.description, - comps)) - # matcher class to make a source entry look nice # lots of predefined matchers to make it i18n/gettext friendly class SourceEntryMatcher: @@ -447,7 +396,7 @@ class SourceEntryMatcher: f = os.path.basename(f) i = f.find(".info") f = f[0:i] - dist = DistInfo(f) + dist = DistInfo(f,base_dir=matcherPath) for suite in dist.suites: if suite.match_uri != None: self.templates.append(suite) diff --git a/UpdateManager/DistUpgradeFetcher.py b/UpdateManager/DistUpgradeFetcher.py index af07cfb4..cda27e2f 100644 --- a/UpdateManager/DistUpgradeFetcher.py +++ b/UpdateManager/DistUpgradeFetcher.py @@ -219,7 +219,7 @@ class DistUpgradeFetcher(object): if not self.verifyDistUprader(): error(self.window_main, _("Verfication failed"), - _("Verfing the upgrade failed. There may be a problem " + _("Verifying the upgrade failed. There may be a problem " "with the network or with the server. ")) self.cleanup() return diff --git a/UpdateManager/UpdateManager.py b/UpdateManager/UpdateManager.py index 343dcd85..63d0eab9 100644 --- a/UpdateManager/UpdateManager.py +++ b/UpdateManager/UpdateManager.py @@ -33,8 +33,11 @@ try: except: import fakegconf as gconf import gobject +import warnings +warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) import apt import apt_pkg + import gettext import copy import string @@ -120,7 +123,7 @@ class MyCache(apt.Cache): # don't touch the gui in this function, it needs to be thread-safe pkg = self[name] - # get the src package name + # get the src package name srcpkg = pkg.sourcePackageName # assume "main" section @@ -130,6 +133,7 @@ class MyCache(apt.Cache): # get the source version, start with the binaries version binver = pkg.candidateVersion + srcver = pkg.candidateVersion #print "bin: %s" % binver try: # try to get the source version of the pkg, this differs @@ -146,6 +150,9 @@ class MyCache(apt.Cache): #print "srcver: %s" % srcver section = srcrecords.Section #print "srcsect: %s" % section + else: + # fail into the error handler + raise SystemError except SystemError, e: srcver = binver @@ -219,38 +226,40 @@ class UpdateList: self.importance = importance self.description = desc - def __init__(self, parent_window): + def __init__(self): # a map of packages under their origin pipe = os.popen("lsb_release -c -s") dist = pipe.read().strip() del pipe - templates = [("%s-security" % dist, "Ubuntu", _("Important security updates" - " of Ubuntu"), 10), - ("%s-updates" % dist, "Ubuntu", _("Recommended updates of " - "Ubuntu"), 9), - ("%s-proposed" % dist, "Ubuntu", _("Proposed updates for Ubuntu"), 8), - ("%s-backports" % dist, "Ubuntu", _("Backports of Ubuntu"), 7), - (dist, "Ubuntu", _("Updates of Ubuntu"), 6)] + templates = [("%s-security" % dist, "Ubuntu", _("Important security updates") + , 10), + ("%s-updates" % dist, "Ubuntu", _("Recommended updates"), 9), + ("%s-proposed" % dist, "Ubuntu", _("Proposed updates"), 8), + ("%s-backports" % dist, "Ubuntu", _("Backports"), 7), + (dist, "Ubuntu", _("Normal updates"), 6)] self.pkgs = {} self.matcher = {} self.num_updates = 0 - self.parent_window = parent_window for (origin, archive, desc, importance) in templates: self.matcher[(origin, archive)] = self.UpdateOrigin(desc, importance) self.unknown_origin = self.UpdateOrigin(_("Other updates"), -1) def update(self, cache): - held_back = [] - broken = [] + self.held_back = [] # do the upgrade cache.saveDistUpgrade() # sort by origin for pkg in cache: - if pkg.markedUpgrade or pkg.markedInstall: + if pkg.isUpgradable: + if pkg.candidateOrigin == None: + # can happen for e.g. loged packages + # FIXME: do something more sensible here (but what?) + print "WARNING: upgradable but no canidateOrigin?!?: ", pkg.name + continue # TRANSLATORS: updates from an 'unknown' origin originstr = _("Other updates") for aorigin in pkg.candidateOrigin: @@ -264,38 +273,11 @@ class UpdateList: self.pkgs[origin_node] = [] self.pkgs[origin_node].append(pkg) self.num_updates = self.num_updates + 1 - elif pkg.isUpgradable: - held_back.append(pkg.name) + if pkg.isUpgradable and not (pkg.markedUpgrade or pkg.markedInstall): + self.held_back.append(pkg.name) for l in self.pkgs.keys(): self.pkgs[l].sort(lambda x,y: cmp(x.name,y.name)) - - # check if we have held-back something - if cache._depcache.KeepCount > 0: - keepcount = cache._depcache.KeepCount - msg = ("<big><b>%s</b></big>\n\n%s" % \ - (_("Cannot install all available updates"), - _("Some of the updates require more extensive changes " - "than expected.\n\n" - "This usually means that you have enabled unoffical " - "repositories, that it is not " - "fully upgraded from the last distribution release or " - "that you run a development release " - "of the distribution.\n\n" - "Would you like to perform a full distribution upgrade " - "now?"))) - dialog = gtk.MessageDialog(self.parent_window, 0, - gtk.MESSAGE_QUESTION, - gtk.BUTTONS_YES_NO,"") - dialog.set_default_response(gtk.RESPONSE_NO) - dialog.set_markup(msg) - dialog.set_title("") - dialog.vbox.set_spacing(6) - res = dialog.run() - if res == gtk.RESPONSE_YES: - os.execl("/usr/bin/gksu", - "/usr/bin/gksu", - "/usr/bin/update-manager --dist-upgrade") - dialog.destroy() + self.keepcount = cache._depcache.KeepCount class UpdateManagerDbusControler(dbus.service.Object): @@ -419,7 +401,11 @@ class UpdateManager(SimpleGladeApp): return to_install = pkg.markedInstall or pkg.markedUpgrade renderer.set_property("active", to_install) - + if pkg.name in self.list.held_back: + renderer.set_property("activatable", False) + else: + renderer.set_property("activatable", True) + def package_column_view_func(self, cell_layout, renderer, model, iter): self.header_column_func(cell_layout, renderer, model, iter) @@ -532,8 +518,11 @@ class UpdateManager(SimpleGladeApp): lock = thread.allocate_lock() lock.acquire() t=thread.start_new_thread(self.cache.get_changelog,(name,lock)) - changes_buffer.set_text(_("Downloading the list of changes...")) - button = self.button_cancel_dl_changelog + changes_buffer.set_text("%s\n" % _("Downloading list of changes...")) + iter = changes_buffer.get_iter_at_line(1) + anchor = changes_buffer.create_child_anchor(iter) + button = gtk.Button(stock="gtk-cancel") + self.textview_changes.add_child_at_anchor(button, anchor) button.show() id = button.connect("clicked", lambda w,lock: lock.release(), lock) @@ -556,13 +545,13 @@ class UpdateManager(SimpleGladeApp): """ if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: menu = gtk.Menu() - item_select_none = gtk.MenuItem(_("Select _None")) + item_select_none = gtk.MenuItem(_("_Uncheck All")) item_select_none.connect("activate", self.select_none_updgrades) menu.add(item_select_none) num_updates = self.cache.installCount if num_updates == 0: item_select_none.set_property("sensitive", False) - item_select_all = gtk.MenuItem(_("Select _All")) + item_select_all = gtk.MenuItem(_("_Check All")) item_select_all.connect("activate", self.select_all_updgrades) menu.add(item_select_all) menu.popup(None, None, None, 0, event.time) @@ -668,7 +657,7 @@ class UpdateManager(SimpleGladeApp): apt_pkg.PkgSystemUnLock() except SystemError: pass - cmd = ["gksu", "--desktop", "/usr/share/applications/synaptic.desktop", + cmd = ["gksu", "--desktop", "/usr/share/applications/update-manager.desktop", "--", "/usr/sbin/synaptic", "--hide-main-window", "--non-interactive", "--parent-window-id", "%s" % (id) ] if action == INSTALL: @@ -726,6 +715,7 @@ class UpdateManager(SimpleGladeApp): time.sleep(0.05) while gtk.events_pending(): gtk.main_iteration() + self.label_cache_progress_title.set_label("<b><big>%s</big></b>" % _("Checking for updates")) self.fillstore() # Allow suspend after synaptic is finished @@ -734,6 +724,7 @@ class UpdateManager(SimpleGladeApp): self.window_main.set_sensitive(True) self.window_main.window.set_cursor(None) + def inhibit_sleep(self): """Send a dbus signal to gnome-power-manager to not suspend the system""" @@ -755,9 +746,13 @@ class UpdateManager(SimpleGladeApp): def toggled(self, renderer, path): """ a toggle button in the listview was toggled """ - self.setBusy(True) iter = self.store.get_iter(path) pkg = self.store.get_value(iter, LIST_PKG) + # make sure that we don't allow to toggle deactivated updates + # this is needed for the call by the row activation callback + if pkg.name in self.list.held_back: + return False + self.setBusy(True) # update the cache if pkg.markedInstall or pkg.markedUpgrade: pkg.markKeep() @@ -809,9 +804,9 @@ class UpdateManager(SimpleGladeApp): # clean most objects self.dl_size = 0 - self.store.clear() self.initCache() - self.list = UpdateList(self.window_main) + self.store.clear() + self.list = UpdateList() # fill them again self.list.update(self.cache) @@ -839,6 +834,7 @@ class UpdateManager(SimpleGladeApp): self.store.append([contents, pkg.name, pkg]) self.update_count() self.setBusy(False) + self.check_all_updates_installable() return False def dist_no_longer_supported(self, meta_release): @@ -929,6 +925,18 @@ class UpdateManager(SimpleGladeApp): if res == gtk.RESPONSE_YES: self.on_button_reload_clicked(None) + def check_all_updates_installable(self): + """ Check if all available updates can be installed and suggest + to run a distribution upgrade if not """ + if self.list.keepcount > 0: + self.dialog_dist_upgrade.set_transient_for(self.window_main) + res = self.dialog_dist_upgrade.run() + self.dialog_dist_upgrade.hide() + if res == gtk.RESPONSE_YES: + os.execl("/usr/bin/gksu", + "/usr/bin/gksu", "--desktop", + "/usr/share/applications/update-manager.desktop", + "--", "/usr/bin/update-manager", "--dist-upgrade") def main(self, options): gconfclient = gconf.client_get_default() |
