Beispiel #1
0
    def do_transfer_progress(self, stats):
        # Ignore callbacks after we finish progress
        if self.done:
            return

        # Start tracking after first call to transfer_progress
        if not self.started_at:
            self.started_at = time.time()

        fraction = stats.get_received_objects() / float(max(1, stats.get_total_objects()))

        duration = time.time() - self.started_at
        hours = duration / (60 * 60)
        minutes = (duration % (60 * 60)) / 60
        seconds = duration % 60
        prefix = "%02u:%02u:%02u" % (hours, minutes, seconds)

        rate = stats.get_received_bytes() / max(1, duration)
        ratestr = GLib.format_size(rate)
        if len(ratestr) < 8:
            ratestr = (' ' * (8 - len(ratestr))) + ratestr

        if fraction == 1.0:
            transfered = GLib.format_size(stats.get_received_bytes())
            self.tool.clear_line()
            self.tool.write_progress(fraction, prefix, transfered)
            self.tool.write_line("")
            self.done = True
        else:
            self.tool.clear_line()
            self.tool.write_progress(fraction, prefix, ratestr)
Beispiel #2
0
    def do_transfer_progress(self, stats):
        # Ignore callbacks after we finish progress
        if self.done:
            return

        # Start tracking after first call to transfer_progress
        if not self.started_at:
            self.started_at = time.time()

        fraction = stats.get_received_objects() / float(
            max(1, stats.get_total_objects()))

        duration = time.time() - self.started_at
        hours = duration / (60 * 60)
        minutes = (duration % (60 * 60)) / 60
        seconds = duration % 60
        prefix = "%02u:%02u:%02u" % (hours, minutes, seconds)

        rate = stats.get_received_bytes() / max(1, duration)
        ratestr = GLib.format_size(rate)
        if len(ratestr) < 8:
            ratestr = (' ' * (8 - len(ratestr))) + ratestr

        if fraction == 1.0:
            transfered = GLib.format_size(stats.get_received_bytes())
            self.tool.clear_line()
            self.tool.write_progress(fraction, prefix, transfered)
            self.tool.write_line("")
            self.done = True
        else:
            self.tool.clear_line()
            self.tool.write_progress(fraction, prefix, ratestr)
Beispiel #3
0
 def _on_speed_refresh(self, *args):
     subtitle = ''
     down = self.client.props.download_speed
     up = self.client.props.upload_speed
     if down:
         subtitle += '↓ {}/s'.format(GLib.format_size(down))
     if down and up:
         subtitle += ' — '
     if up:
         subtitle += '↑ {}/s'.format(GLib.format_size(up))
     self.header_bar.props.subtitle = subtitle
 def _on_speed_refresh(self, *args):
     subtitle = ''
     down = self.client.props.download_speed
     up = self.client.props.upload_speed
     if down:
         subtitle += '↓ {}/s'.format(GLib.format_size(down))
     if down and up:
         subtitle += ' — '
     if up:
         subtitle += '↑ {}/s'.format(GLib.format_size(up))
     self.header_bar.props.subtitle = subtitle
    def _log_installation_free_space(self):
        """Write a log entry with the available installation space

        Use os.statvfs to get the free and blocks at the installation's
        path and then print a log message with the information.
        """
        stats = os.statvfs(self.installation_path)
        free = stats.f_bsize * stats.f_bfree
        total = stats.f_bsize * stats.f_blocks
        percent = (100.0 * stats.f_bfree) / stats.f_blocks
        logger.info('%s free space: %s / %s (%.1f%%)', self.installation_path,
                    GLib.format_size(free), GLib.format_size(total), percent)
Beispiel #6
0
 def _on_progress_details_changed(self, trans, current_items, total_items,
                                  current_bytes, total_bytes, current_cps,
                                  eta):
     #print "_on_progress_details_changed: ", trans, progress
     for row in self:
         if row[self.COL_TID] == trans.tid:
             if trans.is_downloading():
                 name = row[self.COL_NAME]
                 current_bytes_str = GLib.format_size(current_bytes)
                 total_bytes_str = GLib.format_size(total_bytes)
                 status = _("Downloaded %s of %s") % \
                          (current_bytes_str, total_bytes_str)
                 row[self.COL_STATUS] = self._render_status_text(name,
                     status)
 def _on_progress_details_changed(self, trans, current_items, total_items,
                                  current_bytes, total_bytes, current_cps,
                                  eta):
     #print "_on_progress_details_changed: ", trans, progress
     for row in self:
         if row[self.COL_TID] == trans.tid:
             if trans.is_downloading():
                 name = row[self.COL_NAME]
                 current_bytes_str = GLib.format_size(current_bytes)
                 total_bytes_str = GLib.format_size(total_bytes)
                 status = _("Downloaded %s of %s") % \
                          (current_bytes_str, total_bytes_str)
                 row[self.COL_STATUS] = self._render_status_text(
                     name, status)
Beispiel #8
0
    def update_progress(self, size_read):
        self.total_transferred += size_read

        now = GLib.get_monotonic_time()

        if ((now - self.last_update_time) > util.PROGRESS_UPDATE_FREQ):
            self.last_update_time = now

            progress = self.total_transferred / self.total_size
            elapsed = now - self.transfer_start_time

            bytes_per_micro = self.total_transferred / elapsed
            bytes_per_sec = int(bytes_per_micro * 1000 * 1000)

            if bytes_per_sec == 0:
                bytes_per_sec = 1  # no a/0

            time_left_sec = (self.total_size -
                             self.total_transferred) / bytes_per_sec

            print("%s time left, %s/s" % (util.format_time_span(time_left_sec),
                                          GLib.format_size(bytes_per_sec)))

            progress_report = Progress(progress, time_left_sec, bytes_per_sec)
            self.op.progress_report(progress_report)
Beispiel #9
0
    def update_ui_info(self, error):
        if error == None:
            self.size_string = GLib.format_size(self.total_size)
            print("Calculated %d files, with a size of %s" %
                  (self.total_count, self.size_string))

            if self.total_count > 1:
                # Translators: Don't need to translate singular, we show the filename if there's only one
                self.description = gettext.ngettext(
                    "%d file", "%d files",
                    self.total_count) % (self.total_count, )
                self.gicon = Gio.ThemedIcon.new("edit-copy-symbolic")
            else:
                self.description = self.resolved_files[0].basename
                self.gicon = Gio.content_type_get_symbolic_icon(
                    self.mime_if_single)

            self.set_status(OpStatus.WAITING_PERMISSION)
        else:
            if isinstance(
                    error,
                    GLib.Error) and error.code == Gio.IOErrorEnum.NOT_FOUND:
                self.status = OpStatus.FILE_NOT_FOUND
                self.description = ""
                self.error_msg = ""
                self.first_missing_file = self.top_dir_basenames[-1]
                self.gicon = Gio.ThemedIcon.new("dialog-error-symbolic")
            else:
                self.status = OpStatus.FAILED_UNRECOVERABLE
                self.description = ""
                self.set_error(error)

        self.emit_initial_setup_complete()
        self.emit_status_changed()
Beispiel #10
0
    def ask_my_permission(self, request):
        self.active_receive_request = request

        markup = gettext.ngettext("<b>%s</b> wants to send you %d file (%s)",
                                  "<b>%s</b> wants to send you %d files (%s)", request.count) \
                                  % (self.proxy_nick, request.count, GLib.format_size(request.size))

        self.widget.get_toplevel().present()
        dialog = Gtk.MessageDialog(
            title=_("Incoming file"),
            # parent=self.widget.get_toplevel(),
            destroy_with_parent=True,
            message_type=Gtk.MessageType.QUESTION,
            use_markup=True,
            modal=True,
            text=markup)
        dialog.add_buttons(_("Refuse"), Gtk.ResponseType.CANCEL, _("Accept"),
                           Gtk.ResponseType.ACCEPT)

        self.active_receive_request.permission_dialog = dialog

        res = dialog.run()
        dialog.destroy()

        # request may have been cancelled.  Destroying the dialog elsewhere will still return a code,
        # quit early if we're no longer tracking the request (see self.receive_request_withdrawn)
        if not self.active_receive_request:
            return

        if res == Gtk.ResponseType.ACCEPT:
            self.active_receive_request.permission = util.TRANSFER_REQUEST_GRANTED
        else:
            self.active_receive_request.permission = util.TRANSFER_REQUEST_REFUSED

        self.active_receive_request = None
Beispiel #11
0
    def __init__(self, package):
        super().__init__()

        text_view = TextViewWithLinks()
        text_view.set_editable(False)
        text_view.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
        self.add(text_view)

        # TODO: Handle multiple versions.
        version = package.candidate
        text_buffer = text_view.get_buffer()
        it = text_buffer.get_start_iter()
        text_buffer.insert_markup(
            it,
            # I18N This is the format of the first line of the package
            # view.
            _('<span size="x-large" weight="bold">{name}</span>'
              '        version <span size="large">{version}</span>\n'
              ).format(name=package.name, version=version.version),
            -1)
        summary = re.sub(r' --? ', ' — ', version.summary)
        text_buffer.insert_markup(it, f'<big>{summary}</big>\n', -1)

        description = get_description(version)
        description = format_package_description(description)

        text_buffer.insert_markup(it, description, -1)
        text_buffer.insert_markup(it, '\n<span size="xx-small">\n</span>', -1)
        text_buffer.insert(it, _("Homepage:"))
        text_buffer.insert(it, ' ')
        text_view.insert_link(it, version.homepage, version.homepage)
        text_buffer.insert(it, '\n')
        # FIXME: I don’t think this formats according to the current
        # locale.
        text_buffer.insert(
            it,
            _("Download size: {}").format(GLib.format_size(version.size)))
        text_buffer.insert(it, '\n')
        text_buffer.insert(
            it,
            _("Installed size: {}").format(
                GLib.format_size(version.installed_size)))
        text_buffer.insert(it, '\n')
        text_buffer.insert(it,
                           _("Source package: {}").format(version.source_name))
        text_buffer.insert(it, '\n')
        text_buffer.insert(it, _("Section: {}").format(version.section))
Beispiel #12
0
    def prepare_receive_info(self):
        self.size_string = GLib.format_size(self.total_size)
        logging.debug("Op: details: %d files, with a size of %s" %
                      (self.total_count, self.size_string))

        self.have_space = util.have_free_space(self.total_size)
        self.existing = util.files_exist(self.top_dir_basenames)
        self.update_ui_info()
Beispiel #13
0
def have_free_space(size):
    save_file = Gio.File.new_for_path(prefs.get_save_path())

    try:
        info = save_file.query_filesystem_info(Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE, None)
    except GLib.Error:
        print("Unable to check free space in save location (%s), but proceeding anyhow" % prefs.get_save_path())
        return True

    free = info.get_attribute_uint64(Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE)

    # I guess we could have exactly 0 bytes free, but I think you'd have larger problems.  I want to make sure
    # here that we don't fail because we didn't get a valid number.
    if free == 0:
        return True
    print("Need: %s, have %s" % (GLib.format_size(size), GLib.format_size(free)))
    return size < free
 def query_info_cb(gfile, result):
     try:
         file_info = gfile.query_info_finish(result)
     except GLib.Error as err:
         logging.error("Could not query file info: %s", err.message)
     else:
         size = file_info.get_size()  # In bytes.
         self.size_row.props.subtitle = GLib.format_size(size)
Beispiel #15
0
    def start_transfer_op(self, op):
        logging.debug("Remote RPC: calling StartTransfer on '%s'" %
                      (self.display_hostname))

        start_time = GLib.get_monotonic_time()

        op.progress_tracker = transfers.OpProgressTracker(op)
        op.current_progress_report = None
        receiver = transfers.FileReceiver(op)
        op.set_status(OpStatus.TRANSFERRING)

        op.file_iterator = self.stub.StartTransfer(
            warp_pb2.OpInfo(timestamp=op.start_time,
                            ident=self.local_ident,
                            readable_name=util.get_hostname(),
                            use_compression=op.use_compression
                            and prefs.use_compression()))

        def report_receive_error(error):
            op.set_error(error)

            try:
                # If we leave an io stream open, it locks the location.  For instance,
                # if this was a mounted location, we wouldn't be able to terminate until
                # we closed warp.
                if receiver.current_stream != None:
                    receiver.current_stream.close()
            except GLib.Error:
                pass

            logging.critical("An error occurred receiving data from %s: %s" %
                             (op.sender, op.error_msg))
            op.set_status(OpStatus.FAILED)
            op.stop_transfer()

        try:
            for data in op.file_iterator:
                receiver.receive_data(data)
        except grpc.RpcError:
            if op.file_iterator.code() == grpc.StatusCode.CANCELLED:
                op.file_iterator = None
                return
            else:
                report_receive_error(op.file_iterator)
                return
        except Exception as e:
            report_receive_error(e)
            return

        op.file_iterator = None
        receiver.receive_finished()

        logging.debug("Remote: receipt of %s files (%s) finished in %s" % \
              (op.total_count, GLib.format_size(op.total_size),\
               util.precise_format_time_span(GLib.get_monotonic_time() - start_time)))

        op.set_status(OpStatus.FINISHED)
Beispiel #16
0
    def prepare_receive_info(self):
        self.size_string = GLib.format_size(self.total_size)
        print("Transfer request received for %d files, with a size of %s" %
              (self.total_count, self.size_string))

        self.have_space = util.have_free_space(self.total_size)
        self.existing = util.files_exist(
            self.top_dir_basenames) and prefs.prevent_overwriting()
        self.update_ui_info()
    def _write_table(self, stream, title, refs, display_branch=False):
        if not refs:
            return

        stream.write('== {} ==\n\n'.format(title))
        stream.write(self.header)

        for ref in refs:
            row = [
                ref.remote.name,
                self._describe_ref(ref),
                GLib.format_size(ref.installed_size),
                GLib.format_size(ref.download_size),
            ]
            if self.verdicts:
                row.append(self.verdicts.get(ref.name, ''))
            stream.write(self.format_string.format(*row))

        stream.write('\n')
Beispiel #18
0
 def transfer_done():
     if sender.error != None:
         op.set_error(sender.error)
         op.stop_transfer()
         op.set_status(OpStatus.FAILED_UNRECOVERABLE)
     elif op.file_send_cancellable.is_set():
         print("File send cancelled")
     else:
         print("Transfer of %s files (%s) finished in %s" % \
             (op.total_count, GLib.format_size(op.total_size),\
              util.precise_format_time_span(GLib.get_monotonic_time() - start_time)))
 def set_free_space_label(self):
     self.details_label = None
     if self.current_uri.startswith("file://"):
         file = Gio.File.new_for_uri(self.current_uri)
         fileinfo = file.query_filesystem_info(
             Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE, None)
         if fileinfo != None:
             volume_free = fileinfo.get_attribute_uint64(
                 Gio.FILE_ATTRIBUTE_FILESYSTEM_FREE)
             if volume_free != 0:
                 self.details_label = GLib.format_size(volume_free)
     self.space_bar.set_property("details_label", self.details_label)
Beispiel #20
0
    def progress_report(self, report):
        self.current_progress_report = report
        report.progress_text = _("%(time_left)s (%(bytes_per_sec)s/s)") \
                                   % ({
                                         "time_left": util.format_time_span(report.time_left_sec),
                                         "bytes_per_sec": GLib.format_size(report.bytes_per_sec)
                                     })

        if report.progress == 1.0:
            self.status = OpStatus.FINISHED
            self.emit_status_changed()
            return

        self.emit("progress-changed")
Beispiel #21
0
    def get_ram_memory(self):
        self.__ram_memory = ""
        try:
            self.__memory = os.popen(
                "sed -n 's/^MemTotal[ \t]*: *//p' /proc/meminfo").readlines()

            self.__ram_memory = str(self.__memory[0].replace(" kB", ""))
        except Exception as err:
            print("ORG.GCLEANER.APP.SPECS: [ERROR::RAM Memory Not found [ " +
                  str(err) + " ]]")
            self.__ram_memory = "0"

        self.__memory = GLib.format_size((int(self.__ram_memory) * 1024))
        return self.__memory
Beispiel #22
0
    def _update_progress(self, cb_info):
        if cb_info.finished:
            with self.proxy.lock:
                # Don't send NeverStartedSending errors to the other end.
                if cb_info.error and isinstance(cb_info.error, Aborted):
                    e_str = str(cb_info.error)
                else:
                    e_str = None
                self.proxy.update_progress(self.app_name, 0, "", "",
                                           cb_info.finished, e_str)
            GLib.idle_add(self.progress_callback,
                          cb_info,
                          priority=GLib.PRIORITY_DEFAULT)
            print("finished: %s" %
                  util.precise_format_time_span(GLib.get_monotonic_time() -
                                                self.start_time))
            return

        if cb_info.is_informational():
            GLib.idle_add(self.progress_callback,
                          cb_info,
                          priority=GLib.PRIORITY_DEFAULT)
            return

        cb_info.progress = self.current_transfer_size / self.total_transfer_size

        cur_time = GLib.get_monotonic_time()
        total_elapsed = cur_time - self.start_time

        if (cur_time - self.interval_start_time) > self.PROGRESS_INTERVAL:
            self.interval_start_time = cur_time
            bytes_per_micro = self.current_transfer_size / total_elapsed
            bytes_per_sec = int(bytes_per_micro * 1000 * 1000)

            bytes_left = self.total_transfer_size - self.current_transfer_size
            time_left_sec = bytes_left / bytes_per_sec

            cb_info.speed = _("%s/s") % GLib.format_size(bytes_per_sec)
            cb_info.time_left = util.format_time_span(time_left_sec)
            with self.proxy.lock:
                self.proxy.update_progress(self.app_name, cb_info.progress,
                                           cb_info.speed, cb_info.time_left,
                                           cb_info.finished, None)

            GLib.idle_add(self.progress_callback,
                          cb_info,
                          priority=GLib.PRIORITY_DEFAULT)
Beispiel #23
0
    def __init__(self, file: Gio.File, info: Gio.FileInfo):
        if info.get_file_type() == Gio.FileType.DIRECTORY:
            name_attrs = ('folder', 'folder focused')
        else:
            name_attrs = (None, None)
        columns = urwid.Columns([
            urwid.AttrMap(urwid.Text(info.get_display_name()), *name_attrs),
            ('pack', urwid.Text(GLib.format_size(info.get_size()), 'right')),
            (8, urwid.Text(get_basic_content_type(info.get_content_type()))),
            (11, urwid.Text(format_time(info.get_modification_time())))
        ], dividechars=3)

        super().__init__(columns, None, 'focused')
        self._file = file
        self._info = info
        self._name_key = GLib.utf8_collate_key_for_filename(
            info.get_display_name(), -1)
Beispiel #24
0
    def show_diskfull_message(self, size):
        self.widget.get_toplevel().present()

        text = _("The target machine (<b>%s</b>) does not have enough disk space to complete the transfer (approximately %s required)" \
                 % (self.proxy_nick, GLib.format_size(size)))

        dialog = Gtk.MessageDialog(
            title=_("Insufficient Disk Space"),
            # parent=self.widget.get_toplevel(),
            destroy_with_parent=True,
            message_type=Gtk.MessageType.WARNING,
            use_markup=True,
            text=text)
        dialog.add_buttons(_("Dismiss"), Gtk.ResponseType.CLOSE)

        res = dialog.run()
        dialog.destroy()
Beispiel #25
0
    def send_notification(self):
        if prefs.get_show_notifications():
            notification = Gio.Notification.new(_("Transfer complete"))

            body =gettext.ngettext(
                _("%s (%s) received from %s."),
                _("%s files (%s) received from %s"), self.op.total_count) \
                    % (self.op.top_dir_basenames[0] if self.op.total_count == 1 else str(self.op.total_count),
                       GLib.format_size(self.op.total_size),
                       self.op.sender_name)

            notification.set_body(body)
            notification.set_icon(Gio.ThemedIcon(name="emblem-ok-symbolic"))

            notification.set_priority(Gio.NotificationPriority.NORMAL)

            Gio.Application.get_default().send_notification(
                self.op.sender, notification)
    def _read_bytes_async_cb(self, inputstream: Gio.InputStream,
                             result: Gio.AsyncResult, *user_data):
        with self._pause_lock:
            if self._should_pause:
                self._pause_main_loop = GLib.MainLoop.new(None, False)
                self._should_pause = False
                self._paused = True
                self.notify("paused")

        # this has to be done outside the mutex as it will start a blocking loop
        if self._pause_main_loop:
            self._pause_main_loop.run()

        try:
            gbytes: GLib.Bytes = inputstream.read_bytes_finish(result)
        except GLib.Error as e:
            self._error_message = e.message
            self._abort()
            return

        if gbytes.get_size() == 0:
            # EOF -> download complete
            logger.info(f"No bytes returned for {self._filename}")
            self._progress = 1.0
            filesize_str = GLib.format_size(self._filesize)
            self._status_message = f"{filesize_str} of {filesize_str}"
            self.notify("progress")
            self._abort()
            return
        else:
            # write bytes to file
            self._outputstream.write_bytes_async(
                bytes=gbytes,
                io_priority=GLib.PRIORITY_DEFAULT,
                cancellable=self._cancellable,
                callback=self._write_bytes_async_cb,
            )
Beispiel #27
0
 def _on_size_change(self, prop, param):
     self.set_property('text', GLib.format_size(self.size))
Beispiel #28
0
def sizeof_fmt(num):
    return GLib.format_size(num)
 def _on_speed_change(self, prop, param):
     if self.speed:
         self.props.text = GLib.format_size(self.speed) + '/s'
     else:
         self.props.text = ''
Beispiel #30
0
    def _show_changes(self):
        """Show a message and the dependencies in the dialog."""
        self.treestore.clear()

        # Run parent method for apt
        if self.task.pkginfo.pkg_hash.startswith("a"):
            super(ChangesConfirmDialog, self)._show_changes()
        else:
            # flatpak
            self.set_title(_("Flatpaks"))

            if len(self.task.to_install) > 0:
                piter = self.treestore.append(None, ["<b>%s</b>" % _("Install")])

                for ref in self.task.to_install:
                    if self.task.pkginfo.refid == ref.format_ref():
                        continue

                    self.treestore.append(piter, [ref.get_name()])

            if len(self.task.to_remove) > 0:
                piter = self.treestore.append(None, ["<b>%s</b>" % _("Remove")])

                for ref in self.task.to_remove:
                    if self.task.pkginfo.refid == ref.format_ref():
                        continue

                    self.treestore.append(piter, [ref.get_name()])

            if len(self.task.to_update) > 0:
                piter = self.treestore.append(None, ["<b>%s</b>" % _("Upgrade")])

                for ref in self.task.to_update:
                    if self.task.pkginfo.refid == ref.format_ref():
                        continue

                    self.treestore.append(piter, [ref.get_name()])

            msg = _("Please take a look at the list of changes below.")

            if len(self.treestore) == 1:
                filtered_store = self.treestore.filter_new(
                    Gtk.TreePath.new_first())
                self.treeview.expand_all()
                self.treeview.set_model(filtered_store)
                self.treeview.set_show_expanders(False)

                if len(self.task.to_install) > 0:
                    title = _("Additional software has to be installed")
                elif len(self.task.to_remove) > 0:
                    title = _("Additional software has to be removed")
                elif len(self.task.to_update) > 0:
                    title = _("Additional software has to be upgraded")

                if len(filtered_store) < 6:
                    self.set_resizable(False)
                    self.scrolled.set_policy(Gtk.PolicyType.AUTOMATIC,
                                             Gtk.PolicyType.NEVER)
                else:
                    self.treeview.set_size_request(350, 200)
            else:
                title = _("Additional changes are required")
                self.treeview.set_size_request(350, 200)
                self.treeview.collapse_all()

            if self.task.download_size > 0:
                msg += "\n"
                msg += (_("%s will be downloaded in total.") %
                        GLib.format_size(self.task.download_size))
            if self.task.freed_size > 0:
                msg += "\n"
                msg += (_("%s of disk space will be freed.") %
                        GLib.format_size(self.task.freed_size))
            elif self.task.install_size > 0:
                msg += "\n"
                msg += (_("%s more disk space will be used.") %
                        GLib.format_size(self.task.install_size))
            self.label.set_markup("<b><big>%s</big></b>\n\n%s" % (title, msg))
Beispiel #31
0
 def __init__(self, progress, time_left_sec, bytes_per_sec):
     self.progress = progress
     self.time_left_sec = time_left_sec
     self.bytes_per_sec = bytes_per_sec
     self.progress_text = _("%s (%s/s)") % (util.format_time_span(
         time_left_sec), GLib.format_size(bytes_per_sec))
 def _on_size_change(self, prop, param):
     self.set_property('text', GLib.format_size(self.size))
def show_apps(config, split, excess, by, stream):
    '''Lists apps that will be installed for this image, with their installed
    (uncompressed) and download (compressed) sizes.

    If excess > 0, we also suggest which apps to remove to save that amount of
    space in the compressed image.  We use the compressed download size
    according to Flatpak as an approximation for how the uncompressed app will
    affect the compressed size in the image.

    Args:
        config (ConfigParser): the image config
        split (bool): true to consider the split image configuration
        excess (int): bytes that need to be saved to fit within the size, or 0
                      if there's no size limit and you just want the list of
                      apps
        by (str): 'nature' or 'runtime'
        stream (file): stream to which to write the lists
    '''
    # Use a temporary repo in the image builder tmpdir where it will be
    # cleaned up later
    tmpdir = config['build']['tmpdir']
    installation_path = os.path.join(tmpdir, 'applist')
    os.makedirs(installation_path, exist_ok=True)
    installation_file = Gio.File.new_for_path(installation_path)
    installation = Flatpak.Installation.new_for_path(installation_file,
                                                     user=False)

    # Enumerate remotes and resolve all refs needed for installation
    manager = eibflatpak.FlatpakManager(installation, config)
    manager.add_remotes()
    manager.enumerate_remotes()
    manager.resolve_refs(split=split)

    # Make a simple list of FlatpakFullRefs sorted by descending
    # download size order, then by app name
    # TODO: .Locale extensions will appear to be enormous, but in fact their
    # size is normally much smaller due to being only partially installed.
    # TODO: sort later, after bundling extensions together with the app(s) that
    # use them. Without this com.endlessm.extra.pt_BR.Content (421 MB) sorts
    # below com.endlessm.math.pt (25.5 MB) because the app size (3.2 MB) is the
    # effective sort key (
    refs = sorted([
        install_ref.full_ref for install_ref in manager.install_refs.values()
    ],
                  key=lambda ref: (-ref.download_size, ref.name))
    total_installed = sum(ref.installed_size for ref in refs)
    total = sum(ref.download_size for ref in refs)

    excess_after_removals = excess
    verdicts = {}

    if excess > 0:
        for name in MUST_KEEP_APPS:
            verdicts[name] = 'No'

        # Remove any app which we're happy to sacrifice
        for ref in refs:
            if excess_after_removals <= 0:
                break

            if ref.name in verdicts:
                continue

            if (ref.name in PREFER_REMOVE_APPS or any(
                    ref.name.startswith(prefix)
                    for prefix in PREFER_REMOVE_NS)):
                verdicts[ref.name] = 'Yes'
                excess_after_removals -= ref.download_size

        # Propose removing the largest n apps until we're under budget.
        # TODO: prefer to remove generic apps?
        # TODO: some non-greedy algorithm that prefers to remove smaller apps
        # to minimize free excess_after_removals
        for ref in refs:
            if excess_after_removals <= 0:
                break

            if ref.name in verdicts:
                continue

            verdicts[ref.name] = 'Maybe'
            excess_after_removals -= ref.download_size

    stream.write('\n')
    stream.write('Estimated installed size of apps: {}\n'.format(
        GLib.format_size(total_installed)))
    stream.write('Estimated compressed size of apps: {}\n'.format(
        GLib.format_size(total)))
    if excess > 0:
        stream.write('Over budget: {}\n'.format(GLib.format_size(excess)))
        if excess_after_removals > 0:
            stream.write('Over budget after proposed removals: {}\n'.format(
                GLib.format_size(excess_after_removals)))
        else:
            stream.write('Free space after proposed removals: {}\n'.format(
                GLib.format_size(-excess_after_removals)))
    stream.write('\n')

    personality = config['build']['personality']
    formatter = AppListFormatter(refs, personality, verdicts)
    formatter.write_by(by)(stream)
Beispiel #34
0
    def _process_files(self, uri_list):
        self.current_send_request = request = TransferRequest()

        # These are the first-level base names (no path, just the filename) that we'll send to the server
        # to check for pre-existence.  We know that if these files/folders don't exist, none of their children
        # will.  This is a bit simple, but until we need more, it's fine.
        top_dir_basenames = []

        # Recursive function for processing folders and their contents.
        def process_folder(folder_uri, top_dir):
            folder_file = Gio.File.new_for_uri(folder_uri)

            try:
                enumerator = folder_file.enumerate_children(
                    FILE_INFOS, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, None)
                info = enumerator.next_file(None)
            except GLib.Error as e:
                raise NeverStartedSending(e.message)

            while info:
                child = enumerator.get_child(info)
                child_uri = child.get_uri()
                child_basename = child.get_basename()

                file_type = info.get_file_type()

                if file_type == Gio.FileType.DIRECTORY:
                    if uri not in self.file_to_size_map.keys():
                        request.add_file(child_basename, child_uri, top_dir,
                                         info)
                    process_folder(child_uri, top_dir)
                else:
                    if child_uri not in self.file_to_size_map.keys():
                        size = info.get_size()
                        request.add_file(child_basename, child_uri, top_dir,
                                         info)

                try:
                    info = enumerator.next_file(None)
                except GLib.Error as e:
                    raise NeverStartedSending(e.message)

        try:
            # Process the initial list.
            for uri in uri_list:
                file = Gio.File.new_for_uri(uri)
                top_dir_basenames.append(file.get_basename())

                try:
                    info = file.query_info(FILE_INFOS,
                                           Gio.FileQueryInfoFlags.NONE, None)
                except GLib.Error as e:
                    raise NeverStartedSending(e.message)

                basename = file.get_basename()

                if info and info.get_file_type() == Gio.FileType.DIRECTORY:
                    top_dir = file.get_parent().get_uri()
                    if uri not in self.file_to_size_map.keys():
                        request.add_file(basename, uri, None, info)
                    process_folder(uri, top_dir)
                    continue
                else:
                    size = info.get_size()
                    if uri not in self.file_to_size_map.keys():
                        request.add_file(basename, uri, None, info)

            if request.transfer_count == 0:
                #what?
                exit()
        except NeverStartedSending as e:
            self._update_progress(
                util.ProgressCallbackInfo(transfer_cancelled=True, error=e))
            exit()

        with self.proxy.lock:
            if self.proxy.prevent_overwriting() and self.proxy.files_exist(
                    top_dir_basenames):
                self._update_progress(
                    util.ProgressCallbackInfo(transfer_exists=True,
                                              count=request.transfer_count))
                exit()

        permission = False

        with self.proxy.lock:
            need = self.proxy.permission_needed()

        if need:
            self._update_progress(
                util.ProgressCallbackInfo(sender_awaiting_approval=True,
                                          count=request.transfer_count))
            request.stamp = GLib.get_monotonic_time()

            while True:
                with self.proxy.lock:
                    response = self.proxy.get_permission(
                        self.app_name,
                        self.proxy_nick,
                        str(request.transfer_size
                            ),  # XML RPC can't handle longs
                        str(request.transfer_count),
                        str(request.stamp))

                if response == util.TRANSFER_REQUEST_PENDING:
                    time.sleep(1)
                    continue
                elif response == util.TRANSFER_REQUEST_CANCELLED:
                    break
                elif response == util.TRANSFER_REQUEST_REFUSED:
                    self._update_progress(
                        util.ProgressCallbackInfo(transfer_refused=True))
                    break
                elif response == util.TRANSFER_REQUEST_DISKFULL:
                    self._update_progress(
                        util.ProgressCallbackInfo(transfer_diskfull=True,
                                                  size=request.transfer_size))
                    break
                else:
                    permission = response == util.TRANSFER_REQUEST_GRANTED
                    break
        else:
            permission = True

        if permission:
            new_total = 0
            self.file_to_size_map.update(request.transfer_file_to_size_map)

            for size in self.file_to_size_map.values():
                new_total += size

            self.total_transfer_size = new_total

            self._update_progress(
                util.ProgressCallbackInfo(transfer_starting=True))

            print("Starting send: %d files (%s)" %
                  (request.transfer_count,
                   GLib.format_size(request.transfer_size)))
            GLib.idle_add(self._queue_files,
                          request,
                          priority=GLib.PRIORITY_DEFAULT)
        else:
            self._update_progress(
                util.ProgressCallbackInfo(transfer_cancelled=True))
        exit()
Beispiel #35
0
 def _on_speed_change(self, prop, param):
     if self.speed:
         self.props.text = GLib.format_size(self.speed) + '/s'
     else:
         self.props.text = ''
Beispiel #36
0
    def _show_changes(self):
        """Show a message and the dependencies in the dialog."""
        self.treestore.clear()

        # Run parent method for apt
        if self.task.pkginfo.pkg_hash.startswith("a"):
            super(ChangesConfirmDialog, self)._show_changes()
        else:
            # flatpak
            self.set_title(_("Flatpaks"))

            if len(self.task.to_install) > 0:
                piter = self.treestore.append(None, ["<b>%s</b>" % _("Install")])

                for ref in self.task.to_install:
                    if self.task.pkginfo.refid == ref.format_ref():
                        continue

                    self.treestore.append(piter, [ref.get_name()])

            if len(self.task.to_remove) > 0:
                piter = self.treestore.append(None, ["<b>%s</b>" % _("Remove")])

                for ref in self.task.to_remove:
                    if self.task.pkginfo.refid == ref.format_ref():
                        continue

                    self.treestore.append(piter, [ref.get_name()])

            if len(self.task.to_update) > 0:
                piter = self.treestore.append(None, ["<b>%s</b>" % _("Upgrade")])

                for ref in self.task.to_update:
                    if self.task.pkginfo.refid == ref.format_ref():
                        continue

                    self.treestore.append(piter, [ref.get_name()])

            msg = _("Please take a look at the list of changes below.")

            if len(self.treestore) == 1:
                filtered_store = self.treestore.filter_new(
                    Gtk.TreePath.new_first())
                self.treeview.expand_all()
                self.treeview.set_model(filtered_store)
                self.treeview.set_show_expanders(False)

                if len(self.task.to_install) > 0:
                    title = _("Additional software has to be installed")
                elif len(self.task.to_remove) > 0:
                    title = _("Additional software has to be removed")
                elif len(self.task.to_update) > 0:
                    title = _("Additional software has to be upgraded")

                if len(filtered_store) < 6:
                    self.set_resizable(False)
                    self.scrolled.set_policy(Gtk.PolicyType.AUTOMATIC,
                                             Gtk.PolicyType.NEVER)
                else:
                    self.treeview.set_size_request(350, 200)
            else:
                title = _("Additional changes are required")
                self.treeview.set_size_request(350, 200)
                self.treeview.collapse_all()

            if self.task.download_size > 0:
                msg += "\n"
                msg += (_("%s will be downloaded in total.") %
                        GLib.format_size(self.task.download_size))
            if self.task.freed_size > 0:
                msg += "\n"
                msg += (_("%s of disk space will be freed.") %
                        GLib.format_size(self.task.freed_size))
            elif self.task.install_size > 0:
                msg += "\n"
                msg += (_("%s more disk space will be used.") %
                        GLib.format_size(self.task.install_size))
            self.label.set_markup("<b><big>%s</big></b>\n\n%s" % (title, msg))