[Merge] lp:~marcustomlinson/update-manager/update-manager into lp:update-manager

Marcus Tomlinson marcus.tomlinson at canonical.com
Thu Apr 2 11:54:10 UTC 2020


Alright, changes made:

- I've split the large update_snaps() function into smaller parts.
- Snap updates now occur _after_ the user has opted in to the updates.
- snapd-glib for (un)installs means just one polkit prompt now for the all snap updates.
- debs with a snap replacement that were not installed manually get marked for deletion.
- The thread is still there, sorry, though I'm not sure why it's a bad idea really.

Diff comments:

> === modified file 'UpdateManager/backend/__init__.py'
> --- UpdateManager/backend/__init__.py	2019-04-08 17:00:30 +0000
> +++ UpdateManager/backend/__init__.py	2020-03-02 11:23:45 +0000
> @@ -67,6 +74,154 @@
>          """Commit the cache changes """
>          raise NotImplementedError
>  
> +    def update_snaps(self):
> +        # update status and progress bar
> +        def update_status(status):
> +            GLib.idle_add(self.label_details.set_label, status)
> +
> +        def update_progress(progress_bar):
> +            progress_bar.pulse()
> +            return True
> +
> +        update_status(_("Updating snaps"))
> +
> +        progress_timer = None
> +        progress_bars = self.progressbar_slot.get_children()
> +        if progress_bars and isinstance(progress_bars[0], Gtk.ProgressBar):
> +            progress_timer = GLib.timeout_add(100, update_progress, progress_bars[0])
> +
> +        # update and grab the latest cache
> +        try:
> +            if self.window_main.cache is None:
> +                self.window_main.cache = MyCache(None)
> +            else:
> +                self.window_main.cache.open(None)
> +                self.window_main.cache._initDepCache()
> +            cache = self.window_main.cache
> +        except:
> +            cache = None
> +
> +        # populate snap_list with deb2snap transitions
> +        snap_list = {}
> +        seeded_snaps = {}
> +        unseeded_snaps = {}
> +
> +        release = subprocess.Popen(["lsb_release", "-r", "-s"],
> +                                    universal_newlines=True,
> +                                    stdout=subprocess.PIPE).communicate()
> +        release = release[0].split()[0]
> +        curr_channel = "stable/ubuntu-" + release
> +
> +        try:
> +            d2s_file = open('/usr/share/ubuntu-release-upgrader/deb2snap.json', 'r')
> +            d2s = json.load(d2s_file)
> +            d2s_file.close()
> +
> +            for snap in d2s["seeded"]:
> +                seed = d2s["seeded"][snap]
> +                deb = seed.get("deb", None)
> +                to_channel = seed.get("to_channel", curr_channel)
> +                seeded_snaps[snap] = (deb, to_channel)
> +
> +            for snap in d2s["unseeded"]:
> +                unseed = d2s["unseeded"][snap]
> +                from_channel = unseed.get("from_channel", curr_channel)
> +                unseeded_snaps[snap] = (from_channel)
> +        except Exception as e:
> +            logging.debug("error reading deb2snap.json file (%s)" % e)
> +
> +        for snap, (deb, to_channel) in seeded_snaps.items():
> +            snap_object = {}
> +            # check if the snap is already installed
> +            snap_info = subprocess.Popen(["snap", "info", snap],

Apologies, a major advantage to using snapd-glib at least for the (un)installs is that you only get one polk it prompt for all updates. I've updated this logic.

> +                                         universal_newlines=True,
> +                                         stdout=subprocess.PIPE).communicate()
> +            if re.search("^installed: ", snap_info[0], re.MULTILINE):
> +                logging.debug("Snap %s is installed" % snap)
> +                continue
> +            elif deb and cache:
> +                # Do not replace packages not marked for deletion
> +                if (deb not in cache or not cache[deb].marked_delete):
> +                    logging.debug("Deb package %s is not marked for deletion. "
> +                                  "Skipping %s installation" % (deb, snap))
> +                    continue
> +
> +                snap_object['command'] = 'install'
> +                snap_object['channel'] = to_channel
> +                snap_list[snap] = snap_object
> +            else:
> +                logging.debug("Could not determine which deb %s replaces" % snap)
> +                continue
> +        for snap, (from_channel) in unseeded_snaps.items():
> +            snap_object = {}
> +            # check if the snap is already installed
> +            snap_info = subprocess.Popen(["snap", "info", snap],
> +                                         universal_newlines=True,
> +                                         stdout=subprocess.PIPE).communicate()
> +            if re.search("^installed: ", snap_info[0], re.MULTILINE):
> +                logging.debug("Snap %s is installed" % snap)
> +                # its not tracking the release channel so don't remove
> +                if not re.search(r"^tracking:.*%s" % from_channel,
> +                                 snap_info[0], re.MULTILINE):
> +                    logging.debug("Snap %s is not tracking the release channel"
> +                                  % snap)
> +                    continue
> +
> +                snap_object['command'] = 'remove'
> +
> +                # check if this snap is being used by any other snaps
> +                conns = subprocess.Popen(["snap", "connections", snap],
> +                                         universal_newlines=True,
> +                                         stdout=subprocess.PIPE).communicate()
> +
> +                for conn in conns[0].split('\n'):
> +                    conn_cols = conn.split()
> +                    if len(conn_cols) != 4:
> +                        continue
> +                    plug = conn_cols[1]
> +                    slot = conn_cols[2]
> +
> +                    if slot.startswith(snap + ':'):
> +                        plug_snap = plug.split(':')[0]
> +                        if plug_snap != '-' and \
> +                           plug_snap not in unseeded_snaps:
> +                            logging.debug("Snap %s is being used by %s. "
> +                                          "Switching it to stable track"
> +                                          % (snap, plug_snap))
> +                            snap_object['command'] = 'refresh'
> +                            snap_object['channel'] = 'stable'
> +                            break
> +
> +                snap_list[snap] = snap_object
> +
> +        # (un)install (un)seeded snap(s)
> +        for snap, snap_object in snap_list.items():
> +            command = snap_object['command']
> +            if command == 'refresh':
> +                update_status(_("Refreshing %s snap" % snap))
> +                popenargs = ["snap", command,
> +                             "--channel", snap_object['channel'], snap]
> +            elif command == 'remove':
> +                update_status(_("Removing %s snap" % snap))
> +                popenargs = ["snap", command, snap]
> +            else:
> +                update_status(_("Installing %s snap" % snap))
> +                popenargs = ["snap", command,
> +                             "--channel", snap_object['channel'], snap]
> +            try:
> +                proc = subprocess.run(popenargs,
> +                                      stdout=subprocess.PIPE,
> +                                      check=True)
> +            except subprocess.CalledProcessError:
> +                logging.debug("%s of snap %s failed" % (command, snap))
> +                continue
> +            if proc.returncode == 0:
> +                logging.debug("%s of snap %s succeeded" % (command, snap))
> +
> +        # continue with the rest of the updates
> +        if progress_timer: GLib.source_remove(progress_timer)
> +        GLib.idle_add(self.window_main.start_available)
> +
>      def _action_done(self, action, authorized, success, error_string,
>                       error_desc, trans_failed=False):
>  


-- 
https://code.launchpad.net/~marcustomlinson/update-manager/update-manager/+merge/380060
Your team Ubuntu Core Development Team is requested to review the proposed merge of lp:~marcustomlinson/update-manager/update-manager into lp:update-manager.



More information about the Ubuntu-reviews mailing list