diff --git a/SystemUpdater/Core/UpdateList.py b/SystemUpdater/Core/UpdateList.py index 3c43b53..5bf91e0 100644 --- a/SystemUpdater/Core/UpdateList.py +++ b/SystemUpdater/Core/UpdateList.py @@ -505,8 +505,9 @@ class UpdateList(): pkg_obj = cache[pkg_name] #在可升级的列表当中 此步骤为了排除已安装不需要升级的 if pkg_obj.is_installed: - if pkg_name in pkgs_upgrade: - pkg_important_list.append(pkg_name) + if pkg_obj in pkgs_upgrade: + pkg_important_list.append(pkg_obj.name) + pkgs_upgrade.remove(pkg_obj) else: pkg_important_list.append(pkg_name) else: @@ -517,7 +518,7 @@ class UpdateList(): except Exception as e: header = _("read important list failed") desc = ("%s",str(e)) - logging.info(header + desc) + logging.error(header + desc) return False,[],[] def _make_pkg_info_json(self,cache,pkgs_list): @@ -561,7 +562,7 @@ class UpdateList(): # logging.info("this package(%s) not in list ",pkg_name) return new_pkgs_list - def _make_output_json(self,data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list): + def _make_group_output_json(self,data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list): groups_base_info = {} output_json = {} @@ -587,7 +588,7 @@ class UpdateList(): json.dump(output_json, f, ensure_ascii=False, indent=4) logging.info("Generate Jsonfile(%s) to complete... ",output_config_name) - def _make_groups_upgrade(self,cache,group_list,pkgs_install = [], pkgs_upgrade = [], pkgs_remove = []): + def _make_groups_upgrade(self,cache,group_list, pkgs_upgrade = []): try: files = os.listdir(self.INPUT_CONFIG_PATH) #获得文件夹中所有文件的名称列表 upgrade_groups_list = [] @@ -630,7 +631,7 @@ class UpdateList(): install_pkgs_json = self._make_pkg_info_json(cache,new_install_pkgs_list) #输出JSON配置文件 - self._make_output_json(data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list) + self._make_group_output_json(data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list) upgrade_groups_list.append(group_name) @@ -645,8 +646,23 @@ class UpdateList(): logging.warning("Generate Jsonfile to failed... ") logging.error(e) + def _make_single_upgrade(self,cache,pkg_list): + try: + for pkg in pkg_list: + pkgs_json = self._make_pkg_info_json(cache,[pkg]) + + #FIXME: 确定输出文件的文件名 以及放置位置 + output_config_name = self.OUTPUT_CONFIG_PATH + '/' + pkg + '.json' + + #产生JSON文件 + with open(output_config_name, 'w', encoding='utf-8') as f: + json.dump(pkgs_json, f, ensure_ascii=False, indent=4) + logging.info("Generate Jsonfile(%s) to complete... ",output_config_name) + except Exception as e: + logging.warning("Generate Jsonfile to failed... ") + logging.error(e) - def update(self, cache, eventloop_callback=None): + def update(self,cache): pkgs_upgrade = [] header = '' @@ -661,8 +677,12 @@ class UpdateList(): logging.error(e) logging.info("System all upgradeable packages:upgrade:%d ",len(pkgs_upgrade)) + + #源过滤 + # fu = filter.UpdateListFilterCache() + # allowed_origin_upgrade_pkgs = fu.check_in_allowed_origin(pkgs_upgrade) - success,group_important_list,pkg_important_list=self._read_important_list(cache,[pkg.name for pkg in pkgs_upgrade]) + success,group_important_list,pkg_important_list = self._read_important_list(cache,pkgs_upgrade) #important_list 为空时此次不需要升级 if not group_important_list and not pkg_important_list: @@ -671,17 +691,13 @@ class UpdateList(): desc = _('important_list is Empty') return True,header,desc - #源过滤 - # fu = filter.UpdateListFilterCache() - # allowed_origin_upgrade_pkgs = fu.check_in_allowed_origin(pkgs_upgrade) - self._make_groups_upgrade(cache,group_list = group_important_list,pkgs_upgrade = ([pkg.name for pkg in pkgs_upgrade])) - + self._make_single_upgrade(cache,pkg_important_list) + #是否存在可升级的组 if self.local_upgrade_list.get('upgrade_groups_list',[]) or pkg_important_list: #增加需要移除的包列表 - # self.local_upgrade_list.update({"pkgs_remove":[pkg.name for pkg in pkgs_remove]}) - self.local_upgrade_list.update({"pkg_important_list":[pkg for pkg in pkg_important_list]}) + self.local_upgrade_list.update({"pkg_important_list":pkg_important_list}) return True,header,desc else: #不需要升级 全部的软件都是新的 diff --git a/SystemUpdater/UpdateManagerDbus.py b/SystemUpdater/UpdateManagerDbus.py index 120aa4d..9433e9c 100755 --- a/SystemUpdater/UpdateManagerDbus.py +++ b/SystemUpdater/UpdateManagerDbus.py @@ -134,9 +134,7 @@ class UpdateManagerDbusController(dbus.service.Object): @dbus.service.method(INTERFACE, out_signature='bs') def DistUpgradeSystem(self): pkgs_install = [] - pkgs_upgrade = ['ghostscript','adduser','anacron', 'apng2gif', 'apparmor', 'acpid', 'atril',\ - 'at', 'bash', 'bash-completion', 'bc', 'binutils', 'biometric-auth', 'biometric-driver-a210',\ - 'bluez'] + pkgs_upgrade = [] pkgs_remove = [] try: #处于更新和升级中的话 不进行升级 @@ -171,9 +169,7 @@ class UpdateManagerDbusController(dbus.service.Object): else: logging.info('pkgs list is empty.') return False,'upgrade_list is empty' - else: - logging.info('Cancel repair') - return False,'Cancel repair' + except Exception as e: logging.error(False, str(e)) return (False, str(e)) diff --git a/SystemUpdater/backend/InstallBackendAptdaemon.py b/SystemUpdater/backend/InstallBackendAptdaemon.py index 1f37bae..3f1dbfc 100644 --- a/SystemUpdater/backend/InstallBackendAptdaemon.py +++ b/SystemUpdater/backend/InstallBackendAptdaemon.py @@ -2,12 +2,10 @@ from __future__ import print_function -from apt.debfile import DebPackage from aptdaemon import client, errors from defer import inline_callbacks from aptdaemon.enums import (EXIT_SUCCESS, EXIT_FAILED, - EXIT_CANCELLED, get_error_description_from_enum, get_error_string_from_enum, get_status_string_from_enum @@ -68,9 +66,6 @@ class InstallBackendAptdaemon(InstallBackend): authorized=False, success=False, error_string=None, error_desc=None) except errors.TransactionFailed as e: - # if e.code == 'error-dep-resolution-failed': - # logging.error("依赖错误: %s", str(e)) - self.errors = e self.trans_failed_msg = str(e) except dbus.DBusException as e: if e.get_dbus_name() != "org.freedesktop.DBus.Error.NoReply": @@ -88,7 +83,6 @@ class InstallBackendAptdaemon(InstallBackend): def _on_progress_changed(self, trans,progress,action): if progress == 101: return - self.trans_progress = progress if action == self.ACTION_UPDATE: self.window_main.dbusController.UpdateDetectStatusChanged(self.trans_progress,self.trans_status) @@ -154,17 +148,11 @@ class InstallBackendAptdaemon(InstallBackend): trans_failed = False if status == EXIT_FAILED: - # error_string = get_error_string_from_enum(trans.error.code) - # error_desc = get_error_description_from_enum(trans.error.code) - if self.errors: - error_string = self.errors.code - error_string = get_error_string_from_enum(trans.error.code) - error_desc = get_error_description_from_enum(trans.error.code) + error_string = get_error_string_from_enum(trans.error.code) + error_desc = get_error_description_from_enum(trans.error.code) if self.trans_failed_msg: trans_failed = True error_desc = error_desc + "\n" + self.trans_failed_msg - elif status == EXIT_CANCELLED: - error_desc = 'cancel download' is_success = (status == EXIT_SUCCESS) try: @@ -172,8 +160,6 @@ class InstallBackendAptdaemon(InstallBackend): authorized=True, success=is_success, error_string=error_string, error_desc=error_desc, trans_failed=trans_failed) - # - # if self.errors.code == 'error-dep-resolution-failed': except TypeError: # this module used to be be lazily imported and in older code # trans_failed= is not accepted diff --git a/SystemUpdater/backend/__init__.py b/SystemUpdater/backend/__init__.py index 8eb2994..0456da9 100644 --- a/SystemUpdater/backend/__init__.py +++ b/SystemUpdater/backend/__init__.py @@ -23,7 +23,7 @@ class InstallBackend(): #记录当前正在升级的组或者单包 self.now_upgrade_list = [] - def _make_commit_list(self,partial_upgrade_list): + def _make_problem_resolver(self,partial_upgrade_list): pkgs_install = [] pkgs_upgrade = [] @@ -114,7 +114,7 @@ class InstallBackend(): pkgs_remove = [] pkgs_purge = [] - pkgs_install,pkgs_upgrade,pkgs_remove = self._make_commit_list(partial_upgrade_list) + pkgs_install,pkgs_upgrade,pkgs_remove = self._make_problem_resolver(partial_upgrade_list) try: logging.info("commit install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) diff --git a/debian/kylin-system-updater/DEBIAN/conffiles b/debian/kylin-system-updater/DEBIAN/conffiles deleted file mode 100644 index 861c759..0000000 --- a/debian/kylin-system-updater/DEBIAN/conffiles +++ /dev/null @@ -1,2 +0,0 @@ -/etc/apt/apt.conf.d/30kylin-system-updater -/etc/dbus-1/system.d/com.kylin.systemupgrade.conf diff --git a/debian/kylin-system-updater/DEBIAN/control b/debian/kylin-system-updater/DEBIAN/control deleted file mode 100644 index ee45733..0000000 --- a/debian/kylin-system-updater/DEBIAN/control +++ /dev/null @@ -1,13 +0,0 @@ -Package: kylin-system-updater -Version: 1.0.4kord -Architecture: all -Maintainer: Kylin Development Team -Installed-Size: 826 -Depends: python3:any (>= 3.2~), policykit-1, python3-dbus, python3-gi (>= 3.8), python3-yaml -Recommends: python3-launchpadlib -Suggests: gir1.2-dbusmenu-glib-0.4, gir1.2-unity-5.0 -Section: misc -Priority: optional -Homepage: https://www.kylinos.cn -Description: dbus daemon that manages apt updates. - dbus daemon that manages apt updates. Provides DBUS interfaces to UKCC. diff --git a/debian/kylin-system-updater/DEBIAN/md5sums b/debian/kylin-system-updater/DEBIAN/md5sums deleted file mode 100644 index ffd10f6..0000000 --- a/debian/kylin-system-updater/DEBIAN/md5sums +++ /dev/null @@ -1,48 +0,0 @@ -7aa78bd3b35c4249395e6a134b1b2763 debian/kylin-system-updater/usr/bin/kylin-system-updater -4a69f46c22f712a8d9639bc3af4b08c9 debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/AlertWatcher.py -11673e0d6ad9a97ff151f4a851504cec debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/Database.py -876c981f05893045d941af6ac28a486e debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/DistUpgradeCache.py -87fc857cc6e778143b3edb183ea7c2d6 debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/MyCache.py -d024c71b076d685e3d797686b358a65d debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/UpdateList.py -d41d8cd98f00b204e9800998ecf8427e debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/__init__.py -f645c71978cd69e48d09bc5258cc0efe debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/filter.py -6023d761ec73fcb1bb570fed416b185b debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/roam.py -c1e87e6ccff788db537df67e156eebb8 debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/utils.py -7089737368f78098bfbe2465c35e296e debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManager.py -5f8e3e7c4837aaf4f12bd9e2b5d3d05b debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerDbus.py -9e6fc6234ce58a64c484547688f1b6eb debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerVersion.py -d41d8cd98f00b204e9800998ecf8427e debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/__init__.py -efbf7d17f9a58c4bd46171bd1cdc2f73 debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py -fe5d272f0d4155836257cd354511a9ff debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/__init__.py -190f09f0171f56cc355086689030cd69 debian/kylin-system-updater/usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo -f5cbdda16e026bc0d8d0c9a80e694063 debian/kylin-system-updater/usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo -7f78cbf3fc4fc5a1de01e57004e0b717 debian/kylin-system-updater/usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo -7aa78bd3b35c4249395e6a134b1b2763 usr/bin/kylin-system-updater -4a69f46c22f712a8d9639bc3af4b08c9 usr/lib/python3/dist-packages/SystemUpdater/Core/AlertWatcher.py -11673e0d6ad9a97ff151f4a851504cec usr/lib/python3/dist-packages/SystemUpdater/Core/Database.py -876c981f05893045d941af6ac28a486e usr/lib/python3/dist-packages/SystemUpdater/Core/DistUpgradeCache.py -87fc857cc6e778143b3edb183ea7c2d6 usr/lib/python3/dist-packages/SystemUpdater/Core/MyCache.py -d024c71b076d685e3d797686b358a65d usr/lib/python3/dist-packages/SystemUpdater/Core/UpdateList.py -d41d8cd98f00b204e9800998ecf8427e usr/lib/python3/dist-packages/SystemUpdater/Core/__init__.py -f645c71978cd69e48d09bc5258cc0efe usr/lib/python3/dist-packages/SystemUpdater/Core/filter.py -6023d761ec73fcb1bb570fed416b185b usr/lib/python3/dist-packages/SystemUpdater/Core/roam.py -c1e87e6ccff788db537df67e156eebb8 usr/lib/python3/dist-packages/SystemUpdater/Core/utils.py -7089737368f78098bfbe2465c35e296e usr/lib/python3/dist-packages/SystemUpdater/UpdateManager.py -5f8e3e7c4837aaf4f12bd9e2b5d3d05b usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerDbus.py -9e6fc6234ce58a64c484547688f1b6eb usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerVersion.py -d41d8cd98f00b204e9800998ecf8427e usr/lib/python3/dist-packages/SystemUpdater/__init__.py -efbf7d17f9a58c4bd46171bd1cdc2f73 usr/lib/python3/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py -fe5d272f0d4155836257cd354511a9ff usr/lib/python3/dist-packages/SystemUpdater/backend/__init__.py -c13dcab9f5a17bd97b6348a365c4f5df usr/lib/python3/dist-packages/kylin_system_updater-1.0.4kord.egg-info -3f0a4348b0a23600b349da44d54089e6 usr/lib/systemd/system/kylin-system-updater.service -d452acfcbbca9f831a00db7deb82bbab usr/share/doc/kylin-system-updater/AUTHORS -582421dbc6d2d14b1042225ae685b0cb usr/share/doc/kylin-system-updater/README.MD -e5522a184d5e57ab4cbe77b55313f3eb usr/share/doc/kylin-system-updater/TODO -93452eaf7f1114185550ee6cbb1887df usr/share/doc/kylin-system-updater/changelog.gz -91ad613244decccbbfe88d9d6f93cdc3 usr/share/doc/kylin-system-updater/copyright -d1826028b77ced3beb24afec7d26d1ca usr/share/doc/kylin-system-updater/interface.md -1c0ec04ef5901e22a7c9fe1c35533552 usr/share/kylin-system-updater/kylin-system-updater.db -190f09f0171f56cc355086689030cd69 usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo -f5cbdda16e026bc0d8d0c9a80e694063 usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo -7f78cbf3fc4fc5a1de01e57004e0b717 usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo -699e946534eb70f8386a48070efcc203 usr/share/man/man8/kylin-system-updater.8.gz diff --git a/debian/kylin-system-updater/DEBIAN/postinst b/debian/kylin-system-updater/DEBIAN/postinst deleted file mode 100755 index 92c083a..0000000 --- a/debian/kylin-system-updater/DEBIAN/postinst +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -if [ ! -d /var/cache/kylin-system-updater ];then - mkdir -p /var/cache/kylin-system-updater -fi -if [ ! -f /var/cache/kylin-system-updater/kylin-system-updater.db ];then - echo "Copying database to the specified path ..." - cp -r /usr/share/kylin-system-updater/kylin-system-updater.db /var/cache/kylin-system-updater/ -fi - -systemctl enable kylin-system-updater -systemctl start kylin-system-updater diff --git a/debian/kylin-system-updater/DEBIAN/prerm b/debian/kylin-system-updater/DEBIAN/prerm deleted file mode 100755 index b36e5c5..0000000 --- a/debian/kylin-system-updater/DEBIAN/prerm +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -set -e - -# Automatically added by dh_python3: -if which py3clean >/dev/null 2>&1; then - py3clean -p kylin-system-updater -else - dpkg -L kylin-system-updater | perl -ne 's,/([^/]*)\.py$,/__pycache__/\1.*, or next; unlink $_ or die $! foreach glob($_)' - find /usr/lib/python3/dist-packages/ -type d -name __pycache__ -empty -print0 | xargs --null --no-run-if-empty rmdir -fi - -# End automatically added section diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/bin/kylin-system-updater b/debian/kylin-system-updater/debian/kylin-system-updater/usr/bin/kylin-system-updater deleted file mode 100755 index 417f5c9..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/bin/kylin-system-updater +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python3 - -from __future__ import print_function - -from SystemUpdater.UpdateManager import UpdateManager -from gettext import gettext as _ -# import -import logging -from optparse import OptionParser -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib - -#定义日志的格式 -FORMAT = '%(asctime)-15s %(levelname)s:%(message)s' - -FORMAT_DEBUG = '%(asctime)-15s %(levelname)s(%(filename)s:%(lineno)d):%(message)s' - -if __name__ == "__main__": - - # Begin parsing of options - parser = OptionParser() - parser.add_option ("--no-update", action="store_true", - dest="no_update", default=False, - help=_("Do not check for updates when starting")) - parser.add_option ("", "--debug", action="store_true", default=False, - help=_("Show debug messages")) - - (options, args) = parser.parse_args() - - if options.debug: - logging.basicConfig(format=FORMAT,level=logging.INFO) - else: - logging.basicConfig(format=FORMAT,level=logging.INFO) - - logging.info('kylin-update-manager starting ...') - bus_loop = DBusGMainLoop(set_as_default=True) - - app = UpdateManager(options) - # app.start_update() - - loop = GLib.MainLoop() - loop.run() - \ No newline at end of file diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/AlertWatcher.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/AlertWatcher.py deleted file mode 100644 index 83e8ba7..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/AlertWatcher.py +++ /dev/null @@ -1,101 +0,0 @@ -# AlertWatcher.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2010 Mohamed Amine IL Idrissi -# -# Author: Mohamed Amine IL Idrissi -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import absolute_import - -from gi.repository import GObject -import dbus -from dbus.mainloop.glib import DBusGMainLoop - - -class AlertWatcher(GObject.GObject): - """ a class that checks for alerts and reports them, like a battery - or network warning """ - - __gsignals__ = {"network-alert": (GObject.SignalFlags.RUN_FIRST, - None, - (GObject.TYPE_INT,)), - "battery-alert": (GObject.SignalFlags.RUN_FIRST, - None, - (GObject.TYPE_BOOLEAN,)), - "network-3g-alert": (GObject.SignalFlags.RUN_FIRST, - None, - (GObject.TYPE_BOOLEAN, - GObject.TYPE_BOOLEAN,)), - } - - def __init__(self): - GObject.GObject.__init__(self) - DBusGMainLoop(set_as_default=True) - self.bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - # make it always connected if NM isn't available - self.network_state = 3 - - def check_alert_state(self): - try: - #network - obj = self.bus.get_object("org.freedesktop.NetworkManager", - "/org/freedesktop/NetworkManager") - obj.connect_to_signal( - "StateChanged", - self._on_network_state_changed, - dbus_interface="org.freedesktop.NetworkManager") - interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties") - self.network_state = interface.Get( - "org.freedesktop.NetworkManager", "State") - self._network_alert(self.network_state) - - # power - # obj = self.bus.get_object('org.freedesktop.UPower', - # '/org/freedesktop/UPower') - # obj.connect_to_signal("Changed", self._power_changed, - # dbus_interface="org.freedesktop.UPower") - # self._power_changed() - # 3g - # self._update_3g_state() - except dbus.exceptions.DBusException: - pass - - def _on_network_state_changed(self, state): - self._network_alert(state) - # self._update_3g_state() - - # def _update_3g_state(self): - # from .roam import NetworkManagerHelper - # nm = NetworkManagerHelper() - # on_3g = nm.is_active_connection_gsm_or_cdma() - # is_roaming = nm.is_active_connection_gsm_or_cdma_roaming() - # self._network_3g_alert(on_3g, is_roaming) - - # def _network_3g_alert(self, on_3g, is_roaming): - # self.emit("network-3g-alert", on_3g, is_roaming) - - def _network_alert(self, state): - self.network_state = state - self.emit("network-alert", state) - - # def _power_changed(self): - # obj = self.bus.get_object("org.freedesktop.UPower", - # "/org/freedesktop/UPower") - # interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties") - # on_battery = interface.Get("org.freedesktop.UPower", "OnBattery") - # self.emit("battery-alert", on_battery) diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/Database.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/Database.py deleted file mode 100644 index 94e1f69..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/Database.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -import os -import re -import shutil -import sqlite3 -import logging -from gettext import gettext as _ - -DB_FILE = os.path.join("/var/cache/kylin-system-updater/kylin-system-updater.db") -INSTALLED_LIST = [{"item": "errorcode", "type": "int", "default": "0"}] -DISPALY_LIST = [] - -class Sqlite3Server(object): - def __init__(self): - self.connect = None - logging.info("init Sqlite3Server running...") - self.init_sqlit() - - # 初始化连接数据库 - def init_sqlit(self): - logging.info(_("初始化连接数据库 ...")) - try: - if os.path.isfile(DB_FILE): - self.connect = sqlite3.connect(DB_FILE, check_same_thread=False) - self.cursor = self.connect.cursor() - self.insert_new_field() - else: - if not os.path.isdir(os.path.dirname(DB_FILE)): - os.makedirs(os.path.dirname(DB_FILE)) - shutil.copy("/usr/share/kylin-system-updater/kylin-system-updater.db", os.path.dirname(DB_FILE)) - self.connect = sqlite3.connect(DB_FILE, check_same_thread=False) - self.cursor = self.connect.cursor() - self.insert_new_field() - except Exception as e: - logging.error(_("初始化数据库失败: %s"), str(e)) - return False - logging.info(_("成功连接数据库.")) - return True - - # 数据库表格中动态增加新的字段用于扩展 - def insert_new_field(self): - if len(INSTALLED_LIST) == 0 and len(DISPALY_LIST) == 0: - return - self.cursor.execute("select sql from sqlite_master where name='installed'") - installed_sql = self.cursor.fetchone()[0] - pattern = re.compile(r'\"\w+\"') - installed_sql_list = pattern.findall(installed_sql) - for value in INSTALLED_LIST: - for field in installed_sql_list: - if value["item"] == str(field).strip("\""): - break - elif field == installed_sql_list[len(installed_sql_list) - 1]: - try: - if value["default"] != "": - sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"] \ - + ' default ' + str(value["default"]) - else: - sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"] - self.cursor.execute(sql) - logging.info(_("installed表插入新字段: %s"), value["item"]) - except: - logging.error(_("installed表插入新字段失败:"), value["item"], exc_info=True) - - self.cursor.execute("select sql from sqlite_master where name='display'") - display_sql = self.cursor.fetchone()[0] - pattern = re.compile(r'\"\w+\"') - display_sql_list = pattern.findall(display_sql) - for value in DISPALY_LIST: - for field in display_sql_list: - if value["item"] == str(field).strip("\""): - break - elif field == display_sql_list[len(display_sql_list) - 1]: - try: - if value["default"] != "": - sql = 'alter table display add column "' + value["item"] + '" ' + value["type"] \ - + ' default ' + str(value["default"]) - else: - sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"] - self.cursor.execute(sql) - logging.info(_("display表插入新字段: %s"), value["item"]) - except: - logging.error(_("display表插入新字段失败: %s"), value["item"], exc_info=True) - - # 写入数据到installed表中 - def insert_into_installed(self, *args, **kwargs): - self.cursor.execute( - "insert into installed (appname, version, time, description, icon, statue, keyword, errorcode) values(?," - "?,?,?,?,?,?,?)", - (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7])) - self.connect.commit() - - # 写入数据到display表中 - def insert_into_display(self, *args, **kwargs): - sql = "update display set " + args[0] + "='" + args[1] + "' where id = 1" - self.cursor.execute(sql) - self.connect.commit() - - diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/DistUpgradeCache.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/DistUpgradeCache.py deleted file mode 100644 index a3971e5..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/DistUpgradeCache.py +++ /dev/null @@ -1,1251 +0,0 @@ -# DistUpgradeCache.py -# -# Copyright (c) 2004-2008 Canonical -# -# Author: Michael Vogt -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -import apt -import apt_pkg -import glob -import locale -import os -import re -import logging -import time -import datetime -import threading -import configparser -from subprocess import Popen, PIPE - -from gettext import gettext as _ - -from .utils import inside_chroot - -class CacheException(Exception): - pass - - -class CacheExceptionLockingFailed(CacheException): - pass - - -class CacheExceptionDpkgInterrupted(CacheException): - pass - - -def estimate_kernel_initrd_size_in_boot(): - """estimate the amount of space used by the kernel and initramfs in /boot, - including a safety margin - """ - kernel = 0 - initrd = 0 - kver = os.uname()[2] - for f in glob.glob("/boot/*%s*" % kver): - if f == '/boot/initrd.img-%s' % kver: - initrd += os.path.getsize(f) - # don't include in the estimate any files that are left behind by - # an interrupted package manager run - elif (f.find('initrd.img') >= 0 or f.find('.bak') >= 0 - or f.find('.dpkg-') >= 0): - continue - else: - kernel += os.path.getsize(f) - if kernel == 0: - logging.warning( - "estimate_kernel_initrd_size_in_boot() returned '0' for kernel?") - kernel = 16*1024*1024 - if initrd == 0: - logging.warning( - "estimate_kernel_initrd_size_in_boot() returned '0' for initrd?") - initrd = 100*1024*1024 - # add small safety buffer - kernel += 1*1024*1024 - # safety buffer as a percentage of the existing initrd's size - initrd_buffer = 1*1024*1024 - if initrd * 0.05 > initrd_buffer: - initrd_buffer = initrd * 0.05 - initrd += initrd_buffer - return kernel,initrd -KERNEL_SIZE, INITRD_SIZE = estimate_kernel_initrd_size_in_boot() - - -class FreeSpaceRequired(object): - """ FreeSpaceRequired object: - - This exposes: - - the total size required (size_total) - - the dir that requires the space (dir) - - the additional space that is needed (size_needed) - """ - def __init__(self, size_total, dir, size_needed): - self.size_total = size_total - self.dir = dir - self.size_needed = size_needed - def __str__(self): - return "FreeSpaceRequired Object: Dir: %s size_total: %s size_needed: %s" % (self.dir, self.size_total, self.size_needed) - - -class NotEnoughFreeSpaceError(CacheException): - """ - Exception if there is not enough free space for this operation - - """ - def __init__(self, free_space_required_list): - self.free_space_required_list = free_space_required_list - - -class MyCache(apt.Cache): - ReInstReq = 1 - HoldReInstReq = 3 - - # init - def __init__(self, config, view, quirks, progress=None, lock=True): - self.to_install = [] - self.to_remove = [] - self.view = view - self.quirks = quirks - self.lock = False - self.partialUpgrade = False - self.config = config - self.metapkgs = self.config.getlist("Distro", "MetaPkgs") - # acquire lock - self._listsLock = -1 - if lock: - try: - apt_pkg.pkgsystem_lock() - self.lock_lists_dir() - self.lock = True - except SystemError as e: - # checking for this is ok, its not translatable - if "dpkg --configure -a" in str(e): - raise CacheExceptionDpkgInterrupted(e) - raise CacheExceptionLockingFailed(e) - # Do not create the cache until we know it is not locked - apt.Cache.__init__(self, progress) - # a list of regexp that are not allowed to be removed - self.removal_blacklist = config.getListFromFile("Distro", "RemovalBlacklistFile") - # the linux metapackage should not be removed - self.linux_metapackage = self.quirks._get_linux_metapackage(self, False) - self.uname = Popen(["uname", "-r"], stdout=PIPE, - universal_newlines=True).communicate()[0].strip() - self._initAptLog() - # from hardy on we use recommends by default, so for the - # transition to the new dist we need to enable them now - if (config.get("Sources", "From") == "hardy" and - not "RELEASE_UPGRADE_NO_RECOMMENDS" in os.environ): - apt_pkg.config.set("APT::Install-Recommends", "true") - - - apt_pkg.config.set("APT::AutoRemove::SuggestsImportant", "false") - - def _apply_dselect_upgrade(self): - """ honor the dselect install state """ - for pkg in self: - if pkg.is_installed: - continue - if pkg._pkg.selected_state == apt_pkg.SELSTATE_INSTALL: - # upgrade() will take care of this - pkg.mark_install(auto_inst=False, auto_fix=False) - - @property - def req_reinstall_pkgs(self): - " return the packages not downloadable packages in reqreinst state " - reqreinst = set() - for pkg in self: - if ((not pkg.candidate or not pkg.candidate.downloadable) - and - (pkg._pkg.inst_state == self.ReInstReq or - pkg._pkg.inst_state == self.HoldReInstReq)): - reqreinst.add(pkg.name) - return reqreinst - - def fix_req_reinst(self, view): - " check for reqreinst state and offer to fix it " - reqreinst = self.req_reinstall_pkgs - if len(reqreinst) > 0: - header = _("Remove package in bad state", - "Remove packages in bad state", - len(reqreinst)) - summary = _("The package '%s' is in an inconsistent " - "state and needs to be reinstalled, but " - "no archive can be found for it. " - "Do you want to remove this package " - "now to continue?", - "The packages '%s' are in an inconsistent " - "state and need to be reinstalled, but " - "no archives can be found for them. Do you " - "want to remove these packages now to " - "continue?", - len(reqreinst)) % ", ".join(reqreinst) - if view.askYesNoQuestion(header, summary): - self.release_lock() - cmd = ["/usr/bin/dpkg", "--remove", "--force-remove-reinstreq"] + list(reqreinst) - view.getTerminal().call(cmd) - self.get_lock() - return True - return False - - # logging stuff - def _initAptLog(self): - " init logging, create log file" - logdir = self.config.getWithDefault("Files", "LogDir", - "/var/log/dist-upgrade") - if not os.path.exists(logdir): - os.makedirs(logdir) - apt_pkg.config.set("Dir::Log", logdir) - apt_pkg.config.set("Dir::Log::Terminal", "apt-term.log") - self.logfd = os.open(os.path.join(logdir, "apt.log"), - os.O_RDWR | os.O_CREAT | os.O_APPEND, 0o644) - now = datetime.datetime.now() - header = "Log time: %s\n" % now - os.write(self.logfd, header.encode("utf-8")) - - # turn on debugging in the cache - apt_pkg.config.set("Debug::pkgProblemResolver", "true") - apt_pkg.config.set("Debug::pkgDepCache::Marker", "true") - apt_pkg.config.set("Debug::pkgDepCache::AutoInstall", "true") - def _startAptResolverLog(self): - if hasattr(self, "old_stdout"): - os.close(self.old_stdout) - os.close(self.old_stderr) - self.old_stdout = os.dup(1) - self.old_stderr = os.dup(2) - os.dup2(self.logfd, 1) - os.dup2(self.logfd, 2) - def _stopAptResolverLog(self): - os.fsync(1) - os.fsync(2) - os.dup2(self.old_stdout, 1) - os.dup2(self.old_stderr, 2) - # use this decorator instead of the _start/_stop stuff directly - # FIXME: this should probably be a decorator class where all - # logging is moved into? - def withResolverLog(f): - " decorator to ensure that the apt output is logged " - def wrapper(*args, **kwargs): - args[0]._startAptResolverLog() - res = f(*args, **kwargs) - args[0]._stopAptResolverLog() - return res - return wrapper - - # properties - @property - def required_download(self): - """ get the size of the packages that are required to download """ - pm = apt_pkg.PackageManager(self._depcache) - fetcher = apt_pkg.Acquire() - pm.get_archives(fetcher, self._list, self._records) - return fetcher.fetch_needed - @property - def additional_required_space(self): - """ get the size of the additional required space on the fs """ - return self._depcache.usr_size - @property - def additional_required_space_for_snaps(self): - """ get the extra size needed to install the snap replacements """ - try: - # update-manager uses DistUpgradeCache.MyCache as the base class - # of its own MyCache version - but without actually calling our - # constructor at all. This causes that the MyCache version from - # update-manager has no self.quirks attribute while still calling - # our default version of checkFreeSpace(). Since extra_snap_space - # is only used on dist-upgrades, let's just not care and return 0 - # in this weird, undocumented case. - return self.quirks.extra_snap_space - except AttributeError: - return 0 - @property - def is_broken(self): - """ is the cache broken """ - return self._depcache.broken_count > 0 - - # methods - def lock_lists_dir(self): - name = apt_pkg.config.find_dir("Dir::State::Lists") + "lock" - self._listsLock = apt_pkg.get_lock(name) - if self._listsLock < 0: - e = "Can not lock '%s' " % name - raise CacheExceptionLockingFailed(e) - def unlock_lists_dir(self): - if self._listsLock > 0: - os.close(self._listsLock) - self._listsLock = -1 - def update(self, fprogress=None): - """ - our own update implementation is required because we keep the lists - dir lock - """ - self.unlock_lists_dir() - res = apt.Cache.update(self, fprogress) - self.lock_lists_dir() - if fprogress and fprogress.release_file_download_error: - # FIXME: not ideal error message, but we just reuse a - # existing one here to avoid a new string - raise IOError(_("The server may be overloaded")) - if res == False: - raise IOError("apt.cache.update() returned False, but did not raise exception?!?") - - def commit(self, fprogress, iprogress): - logging.info("cache.commit()") - if self.lock: - self.release_lock() - apt.Cache.commit(self, fprogress, iprogress) - - def release_lock(self, pkgSystemOnly=True): - if self.lock: - try: - apt_pkg.pkgsystem_unlock() - self.lock = False - except SystemError as e: - logging.debug("failed to SystemUnLock() (%s) " % e) - - def get_lock(self, pkgSystemOnly=True): - if not self.lock: - try: - apt_pkg.pkgsystem_lock() - self.lock = True - except SystemError as e: - logging.debug("failed to SystemLock() (%s) " % e) - - def downloadable(self, pkg, useCandidate=True): - " check if the given pkg can be downloaded " - if useCandidate: - ver = self._depcache.get_candidate_ver(pkg._pkg) - else: - ver = pkg._pkg.current_ver - if ver == None: - logging.warning("no version information for '%s' (useCandidate=%s)" % (pkg.name, useCandidate)) - return False - return ver.downloadable - - def pkg_auto_removable(self, pkg): - """ check if the pkg is auto-removable """ - return (pkg.is_installed and - self._depcache.is_garbage(pkg._pkg)) - - def fix_broken(self): - """ try to fix broken dependencies on the system, may throw - SystemError when it can't""" - return self._depcache.fix_broken() - - def create_snapshot(self): - """ create a snapshot of the current changes """ - self.to_install = [] - self.to_remove = [] - for pkg in self.get_changes(): - if pkg.marked_install or pkg.marked_upgrade: - self.to_install.append(pkg.name) - if pkg.marked_delete: - self.to_remove.append(pkg.name) - - def clear(self): - self._depcache.init() - - def restore_snapshot(self): - """ restore a snapshot """ - actiongroup = apt_pkg.ActionGroup(self._depcache) - # just make pyflakes shut up, later we need to use - # with self.actiongroup(): - actiongroup - self.clear() - for name in self.to_remove: - pkg = self[name] - pkg.mark_delete() - for name in self.to_install: - pkg = self[name] - pkg.mark_install(auto_fix=False, auto_inst=False) - - def need_server_mode(self): - """ - This checks if we run on a desktop or a server install. - - A server install has more freedoms, for a desktop install - we force a desktop meta package to be install on the upgrade. - - We look for a installed desktop meta pkg and for key - dependencies, if none of those are installed we assume - server mode - """ - #logging.debug("need_server_mode() run") - # check for the MetaPkgs (e.g. ubuntu-desktop) - metapkgs = self.config.getlist("Distro", "MetaPkgs") - for key in metapkgs: - # if it is installed we are done - if key in self and self[key].is_installed: - logging.debug("need_server_mode(): run in 'desktop' mode, (because of pkg '%s')" % key) - return False - # if it is not installed, but its key depends are installed - # we are done too (we auto-select the package later) - deps_found = True - for pkg in self.config.getlist(key, "KeyDependencies"): - deps_found &= pkg in self and self[pkg].is_installed - if deps_found: - logging.debug("need_server_mode(): run in 'desktop' mode, (because of key deps for '%s')" % key) - return False - logging.debug("need_server_mode(): can not find a desktop meta package or key deps, running in server mode") - return True - - def sanity_check(self, view): - """ check if the cache is ok and if the required metapkgs - are installed - """ - if self.is_broken: - try: - logging.debug("Have broken pkgs, trying to fix them") - self.fix_broken() - except SystemError: - view.error(_("Broken packages"), - _("Your system contains broken packages " - "that couldn't be fixed with this " - "software. " - "Please fix them first using synaptic or " - "apt-get before proceeding.")) - return False - return True - - def mark_install(self, pkg, reason="", **flags): - logging.debug("Installing '%s' (%s)" % (pkg, reason)) - if pkg in self: - self[pkg].mark_install(**flags) - if not (self[pkg].marked_install or self[pkg].marked_upgrade): - logging.error("Installing/upgrading '%s' failed" % pkg) - #raise SystemError("Installing '%s' failed" % pkg) - return False - return True - - def mark_upgrade(self, pkg, reason=""): - logging.debug("Upgrading '%s' (%s)" % (pkg, reason)) - if pkg in self and self[pkg].is_installed: - self[pkg].mark_upgrade() - if not self[pkg].marked_upgrade: - logging.error("Upgrading '%s' failed" % pkg) - return False - return True - - def mark_remove(self, pkg, reason="", **flags): - logging.debug("Removing '%s' (%s)" % (pkg, reason)) - if pkg in self: - self[pkg].mark_delete(**flags) - - def mark_purge(self, pkg, reason=""): - logging.debug("Purging '%s' (%s)" % (pkg, reason)) - if pkg in self: - self._depcache.mark_delete(self[pkg]._pkg, True) - - def _keep_installed(self, pkgname, reason): - if (pkgname in self - and self[pkgname].is_installed - and self[pkgname].marked_delete): - self.mark_install(pkgname, reason) - - def keep_installed_rule(self): - """ run after the dist-upgrade to ensure that certain - packages are kept installed """ - # first the global list - for pkgname in self.config.getlist("Distro", "KeepInstalledPkgs"): - self._keep_installed(pkgname, "Distro KeepInstalledPkgs rule") - # the the per-metapkg rules - for key in self.metapkgs: - if key in self and (self[key].is_installed or - self[key].marked_install): - for pkgname in self.config.getlist(key, "KeepInstalledPkgs"): - self._keep_installed(pkgname, "%s KeepInstalledPkgs rule" % key) - - # only enforce section if we have a network. Otherwise we run - # into CD upgrade issues for installed language packs etc - if self.config.get("Options", "withNetwork") == "True": - logging.debug("Running KeepInstalledSection rules") - # now the KeepInstalledSection code - for section in self.config.getlist("Distro", "KeepInstalledSection"): - for pkg in self: - if (pkg.candidate and pkg.candidate.downloadable - and pkg.marked_delete - and pkg.candidate.section == section): - self._keep_installed(pkg.name, "Distro KeepInstalledSection rule: %s" % section) - for key in self.metapkgs: - if key in self and (self[key].is_installed or - self[key].marked_install): - for section in self.config.getlist(key, "KeepInstalledSection"): - for pkg in self: - if (pkg.candidate and pkg.candidate.downloadable - and pkg.marked_delete and - pkg.candidate.section == section): - self._keep_installed(pkg.name, "%s KeepInstalledSection rule: %s" % (key, section)) - - - def pre_upgrade_rule(self): - " run before the upgrade was done in the cache " - # run the quirks handlers - if not self.partialUpgrade: - self.quirks.run("PreDistUpgradeCache") - - def post_upgrade_rule(self): - " run after the upgrade was done in the cache " - for (rule, action) in [("Install", self.mark_install), - ("Upgrade", self.mark_upgrade), - ("Remove", self.mark_remove), - ("Purge", self.mark_purge)]: - # first the global list - for pkg in self.config.getlist("Distro", "PostUpgrade%s" % rule): - action(pkg, "Distro PostUpgrade%s rule" % rule) - for key in self.metapkgs: - if key in self and (self[key].is_installed or - self[key].marked_install): - for pkg in self.config.getlist(key, "PostUpgrade%s" % rule): - action(pkg, "%s PostUpgrade%s rule" % (key, rule)) - # run the quirks handlers - if not self.partialUpgrade: - self.quirks.run("PostDistUpgradeCache") - - def checkForNvidia(self): - """ - this checks for nvidia hardware and checks what driver is needed - """ - logging.debug("nvidiaUpdate()") - # if the free drivers would give us a equally hard time, we would - # never be able to release - try: - from NvidiaDetector.nvidiadetector import NvidiaDetection - except (ImportError, SyntaxError) as e: - # SyntaxError is temporary until the port of NvidiaDetector to - # Python 3 is in the archive. - logging.error("NvidiaDetector can not be imported %s" % e) - return False - try: - # get new detection module and use the modalises files - # from within the release-upgrader - nv = NvidiaDetection(obsolete="./ubuntu-drivers-obsolete.pkgs") - #nv = NvidiaDetection() - # check if a binary driver is installed now - for oldDriver in nv.oldPackages: - if oldDriver in self and self[oldDriver].is_installed: - self.mark_remove(oldDriver, "old nvidia driver") - break - else: - logging.info("no old nvidia driver installed, installing no new") - return False - # check which one to use - driver = nv.selectDriver() - logging.debug("nv.selectDriver() returned '%s'" % driver) - if not driver in self: - logging.warning("no '%s' found" % driver) - return False - if not (self[driver].marked_install or self[driver].marked_upgrade): - self[driver].mark_install() - logging.info("installing %s as suggested by NvidiaDetector" % driver) - return True - except Exception as e: - logging.error("NvidiaDetection returned a error: %s" % e) - return False - - - def _has_kernel_headers_installed(self): - for pkg in self: - if (pkg.name.startswith("linux-headers-") and - pkg.is_installed): - return True - return False - - def checkForKernel(self): - """ check for the running kernel and try to ensure that we have - an updated version - """ - logging.debug("Kernel uname: '%s' " % self.uname) - try: - (version, build, flavour) = self.uname.split("-") - except Exception as e: - logging.warning("Can't parse kernel uname: '%s' (self compiled?)" % e) - return False - # now check if we have a SMP system - dmesg = Popen(["dmesg"], stdout=PIPE).communicate()[0] - if b"WARNING: NR_CPUS limit" in dmesg: - logging.debug("UP kernel on SMP system!?!") - return True - - def checkPriority(self): - # tuple of priorities we require to be installed - need = ('required', ) - # stuff that its ok not to have - removeEssentialOk = self.config.getlist("Distro", "RemoveEssentialOk") - # check now - for pkg in self: - # WORKAROUND bug on the CD/python-apt #253255 - ver = pkg._pcache._depcache.get_candidate_ver(pkg._pkg) - if ver and ver.priority == 0: - logging.error("Package %s has no priority set" % pkg.name) - continue - if (pkg.candidate and pkg.candidate.downloadable and - not (pkg.is_installed or pkg.marked_install) and - not pkg.name in removeEssentialOk and - # ignore multiarch priority required packages - not ":" in pkg.name and - pkg.candidate.priority in need): - self.mark_install(pkg.name, "priority in required set '%s' but not scheduled for install" % need) - - # FIXME: make this a decorator (just like the withResolverLog()) - def updateGUI(self, view, lock): - i = 0 - while lock.locked(): - if i % 15 == 0: - view.pulseProgress() - view.processEvents() - time.sleep(0.02) - i += 1 - view.pulseProgress(finished=True) - view.processEvents() - - @withResolverLog - def distUpgrade(self, view, serverMode, partialUpgrade): - # keep the GUI alive - lock = threading.Lock() - lock.acquire() - t = threading.Thread(target=self.updateGUI, args=(self.view, lock,)) - t.start() - try: - # mvo: disabled as it casues to many errornous installs - #self._apply_dselect_upgrade() - - # run PreDistUpgradeCache quirks - self.pre_upgrade_rule() - - # upgrade (and make sure this way that the cache is ok) - self.upgrade(True) - - # check that everything in priority required is installed - self.checkPriority() - - # see if our KeepInstalled rules are honored - self.keep_installed_rule() - - # check if we got a new kernel (if we are not inside a - # chroot) - if inside_chroot(): - logging.warning("skipping kernel checks because we run inside a chroot") - else: - self.checkForKernel() - - # check for nvidia stuff - self.checkForNvidia() - - # and if we have some special rules - self.post_upgrade_rule() - - # install missing meta-packages (if not in server upgrade mode) - self._keepBaseMetaPkgsInstalled(view) - if not serverMode: - # if this fails, a system error is raised - self._installMetaPkgs(view) - - # see if it all makes sense, if not this function raises - self._verifyChanges() - - if self.is_broken: - raise SystemError(_("Broken packages after upgrade: %s") % ", ".join(p.name for p in self if p.is_inst_broken or p.is_now_broken)) - - except SystemError as e: - # the most likely problem is the 3rd party pkgs so don't address - # foreignPkgs and devRelease being True - details = _("An unresolvable problem occurred while " - "calculating the upgrade.\n\n ") - if self.config.get("Options", "foreignPkgs") == "True": - details += _("This was likely caused by:\n" - " * Unofficial software packages not provided by Ubuntu\n" - "Please use the tool 'ppa-purge' from the ppa-purge \n" - "package to remove software from a Launchpad PPA and \n" - "try the upgrade again.\n" - "\n") - elif self.config.get("Options", "foreignPkgs") == "False" and \ - self.config.get("Options", "devRelease") == "True": - details += _("This was caused by:\n" - " * Upgrading to a pre-release version of Ubuntu\n" - "This is most likely a transient problem, \n" - "please try again later.\n") - # we never have partialUpgrades (including removes) on a stable system - # with only ubuntu sources so we do not recommend reporting a bug - if partialUpgrade: - details += _("This is most likely a transient problem, " - "please try again later.") - else: - details += _("If none of this applies, then please report this bug using " - "the command 'ubuntu-bug ubuntu-release-upgrader-core' in a terminal. ") - details += _("If you want to investigate this yourself the log files in " - "'/var/log/dist-upgrade' will contain details about the upgrade. " - "Specifically, look at 'main.log' and 'apt.log'.") - # make the error text available again on stdout for the - # text frontend - self._stopAptResolverLog() - view.error(_("Could not calculate the upgrade"), details) - # may contain utf-8 (LP: #1310053) - error_msg = str(e) - logging.error("Dist-upgrade failed: '%s'", error_msg) - # start the resolver log again because this is run with - # the withResolverLog decorator - self._startAptResolverLog() - return False - finally: - # wait for the gui-update thread to exit - lock.release() - t.join() - - # check the trust of the packages that are going to change - untrusted = [] - downgrade = [] - for pkg in self.get_changes(): - if pkg.marked_delete: - continue - # special case because of a bug in pkg.candidate.origins - if pkg.marked_downgrade: - downgrade.append(pkg.name) - for ver in pkg._pkg.version_list: - # version is lower than installed one - if apt_pkg.version_compare( - ver.ver_str, pkg.installed.version) < 0: - for (verFileIter, index) in ver.file_list: - indexfile = pkg._pcache._list.find_index(verFileIter) - if indexfile and not indexfile.is_trusted: - untrusted.append(pkg.name) - break - continue - origins = pkg.candidate.origins - trusted = False - for origin in origins: - #print(origin) - trusted |= origin.trusted - if not trusted: - untrusted.append(pkg.name) - # check if the user overwrote the unauthenticated warning - try: - b = self.config.getboolean("Distro", "AllowUnauthenticated") - if b: - logging.warning("AllowUnauthenticated set!") - return True - except configparser.NoOptionError: - pass - if len(downgrade) > 0: - downgrade.sort() - logging.error("Packages to downgrade found: '%s'" % - " ".join(downgrade)) - if len(untrusted) > 0: - untrusted.sort() - logging.error("Unauthenticated packages found: '%s'" % - " ".join(untrusted)) - # FIXME: maybe ask a question here? instead of failing? - self._stopAptResolverLog() - view.error(_("Error authenticating some packages"), - _("It was not possible to authenticate some " - "packages. This may be a transient network problem. " - "You may want to try again later. See below for a " - "list of unauthenticated packages."), - "\n".join(untrusted)) - # start the resolver log again because this is run with - # the withResolverLog decorator - self._startAptResolverLog() - return False - return True - - def _verifyChanges(self): - """ this function tests if the current changes don't violate - our constrains (blacklisted removals etc) - """ - main_arch = apt_pkg.config.find("APT::Architecture") - removeEssentialOk = self.config.getlist("Distro", "RemoveEssentialOk") - # check changes - for pkg in self.get_changes(): - if pkg.marked_delete and self._inRemovalBlacklist(pkg.name): - logging.debug("The package '%s' is marked for removal but it's in the removal blacklist", pkg.name) - raise SystemError(_("The package '%s' is marked for removal but it is in the removal blacklist.") % pkg.name) - if pkg.marked_delete and ( - pkg._pkg.essential == True and - pkg.installed.architecture in (main_arch, "all") and - not pkg.name in removeEssentialOk): - logging.debug("The package '%s' is marked for removal but it's an ESSENTIAL package", pkg.name) - raise SystemError(_("The essential package '%s' is marked for removal.") % pkg.name) - # check bad-versions blacklist - badVersions = self.config.getlist("Distro", "BadVersions") - for bv in badVersions: - (pkgname, ver) = bv.split("_") - if (pkgname in self and self[pkgname].candidate and - self[pkgname].candidate.version == ver and - (self[pkgname].marked_install or - self[pkgname].marked_upgrade)): - raise SystemError(_("Trying to install blacklisted version '%s'") % bv) - return True - - def _lookupPkgRecord(self, pkg): - """ - helper to make sure that the pkg._records is pointing to the right - location - needed because python-apt 0.7.9 dropped the python-apt - version but we can not yet use the new version because on upgrade - the old version is still installed - """ - ver = pkg._pcache._depcache.get_candidate_ver(pkg._pkg) - if ver is None: - print("No candidate ver: ", pkg.name) - return False - if ver.file_list is None: - print("No file_list for: %s " % self._pkg.name()) - return False - f, index = ver.file_list.pop(0) - pkg._pcache._records.lookup((f, index)) - return True - - @property - def installedTasks(self): - tasks = {} - installed_tasks = set() - for pkg in self: - if not self._lookupPkgRecord(pkg): - logging.debug("no PkgRecord found for '%s', skipping " % pkg.name) - continue - for line in pkg._pcache._records.record.split("\n"): - if line.startswith("Task:"): - for task in (line[len("Task:"):]).split(","): - task = task.strip() - if task not in tasks: - tasks[task] = set() - tasks[task].add(pkg.name) - for task in tasks: - installed = True - ignored_tasks = self.config.getlist("Distro", "IgnoredTasks") - if task in ignored_tasks: - installed = False - for pkgname in tasks[task]: - if not self[pkgname].is_installed: - installed = False - break - if installed: - installed_tasks.add(task) - return installed_tasks - - def installTasks(self, tasks): - logging.debug("running installTasks") - for pkg in self: - if pkg.marked_install or pkg.is_installed: - continue - self._lookupPkgRecord(pkg) - if not (hasattr(pkg._pcache._records, "record") and pkg._pcache._records.record): - logging.warning("can not find Record for '%s'" % pkg.name) - continue - for line in pkg._pcache._records.record.split("\n"): - if line.startswith("Task:"): - for task in (line[len("Task:"):]).split(","): - task = task.strip() - if task in tasks: - pkg.mark_install() - return True - - def _keepBaseMetaPkgsInstalled(self, view): - for pkg in self.config.getlist("Distro", "BaseMetaPkgs"): - self._keep_installed(pkg, "base meta package keep installed rule") - - def _installMetaPkgs(self, view): - - def metaPkgInstalled(): - """ - internal helper that checks if at least one meta-pkg is - installed or marked install - """ - for key in metapkgs: - if key in self: - pkg = self[key] - if pkg.is_installed and pkg.marked_delete: - logging.debug("metapkg '%s' installed but marked_delete" % pkg.name) - if ((pkg.is_installed and not pkg.marked_delete) - or self[key].marked_install): - return True - return False - - # now check for ubuntu-desktop, kubuntu-desktop, edubuntu-desktop - metapkgs = self.config.getlist("Distro", "MetaPkgs") - - # we never go without ubuntu-base - for pkg in self.config.getlist("Distro", "BaseMetaPkgs"): - self[pkg].mark_install() - - # every meta-pkg that is installed currently, will be marked - # install (that result in a upgrade and removes a mark_delete) - for key in metapkgs: - try: - if (key in self and - self[key].is_installed and - self[key].is_upgradable): - logging.debug("Marking '%s' for upgrade" % key) - self[key].mark_upgrade() - except SystemError as e: - # warn here, but don't fail, its possible that meta-packages - # conflict (like ubuntu-desktop vs xubuntu-desktop) LP: #775411 - logging.warning("Can't mark '%s' for upgrade (%s)" % (key, e)) - - # check if we have a meta-pkg, if not, try to guess which one to pick - if not metaPkgInstalled(): - logging.debug("none of the '%s' meta-pkgs installed" % metapkgs) - for key in metapkgs: - deps_found = True - for pkg in self.config.getlist(key, "KeyDependencies"): - deps_found &= pkg in self and self[pkg].is_installed - if deps_found: - logging.debug("guessing '%s' as missing meta-pkg" % key) - try: - self[key].mark_install() - except (SystemError, KeyError) as e: - logging.error("failed to mark '%s' for install (%s)" % - (key, e)) - view.error(_("Can't install '%s'") % key, - _("It was impossible to install a " - "required package. Please report " - "this as a bug using " - "'ubuntu-bug ubuntu-release-upgrader-core' in " - "a terminal.")) - return False - logging.debug("marked_install: '%s' -> '%s'" % (key, self[key].marked_install)) - break - # check if we actually found one - if not metaPkgInstalled(): - meta_pkgs = ', '.join(metapkgs[0:-1]) - view.error(_("Can't guess meta-package"), - _("Your system does not contain a " - "%s or %s package and it was not " - "possible to detect which version of " - "Ubuntu you are running.\n " - "Please install one of the packages " - "above first using synaptic or " - "apt-get before proceeding.") % - (meta_pkgs, metapkgs[-1])) - return False - return True - - def _inRemovalBlacklist(self, pkgname): - for expr in self.removal_blacklist: - if re.compile(expr).match(pkgname): - logging.debug("blacklist expr '%s' matches '%s'" % (expr, pkgname)) - return True - return False - - @withResolverLog - def tryMarkObsoleteForRemoval(self, pkgname, remove_candidates, forced_obsoletes, foreign_pkgs): - #logging.debug("tryMarkObsoleteForRemoval(): %s" % pkgname) - # sanity check, first see if it looks like a running kernel pkg - if pkgname.endswith(self.uname): - logging.debug("skipping running kernel pkg '%s'" % pkgname) - return False - if pkgname == self.linux_metapackage: - logging.debug("skipping kernel metapackage '%s'" % pkgname) - return False - if self._inRemovalBlacklist(pkgname): - logging.debug("skipping '%s' (in removalBlacklist)" % pkgname) - return False - # ensure we honor KeepInstalledSection here as well - for section in self.config.getlist("Distro", "KeepInstalledSection"): - if (pkgname in self and self[pkgname].installed and - self[pkgname].installed.section == section): - logging.debug("skipping '%s' (in KeepInstalledSection)" % pkgname) - return False - # if we don't have the package anyway, we are fine (this can - # happen when forced_obsoletes are specified in the config file) - if pkgname not in self: - #logging.debug("package '%s' not in cache" % pkgname) - return True - # check if we want to purge - try: - purge = self.config.getboolean("Distro", "PurgeObsoletes") - except configparser.NoOptionError: - purge = False - - # if this package has not been forced obsolete, only - # delete it if it doesn't remove other dependents - # that are not obsolete as well - actiongroup = apt_pkg.ActionGroup(self._depcache) - # just make pyflakes shut up, later we should use - # with self.actiongroup(): - actiongroup - self.create_snapshot() - try: - self[pkgname].mark_delete(purge=purge) - self.view.processEvents() - if pkgname in forced_obsoletes: - return True - #logging.debug("marking '%s' for removal" % pkgname) - for pkg in self.get_changes(): - if (pkg.name not in remove_candidates or - pkg.name in foreign_pkgs or - self._inRemovalBlacklist(pkg.name) or - pkg.name == self.linux_metapackage): - logging.debug("package '%s' produces an unwanted removal '%s', skipping" % (pkgname, pkg.name)) - self.restore_snapshot() - return False - except (SystemError, KeyError) as e: - logging.warning("_tryMarkObsoleteForRemoval failed for '%s' (%s: %s)" % (pkgname, repr(e), e)) - self.restore_snapshot() - return False - return True - - def _getObsoletesPkgs(self): - " get all package names that are not downloadable " - obsolete_pkgs = set() - for pkg in self: - if pkg.is_installed: - # check if any version is downloadable. we need to check - # for older ones too, because there might be - # cases where e.g. firefox in gutsy-updates is newer - # than hardy - if not self.anyVersionDownloadable(pkg): - obsolete_pkgs.add(pkg.name) - return obsolete_pkgs - - def anyVersionDownloadable(self, pkg): - " helper that checks if any of the version of pkg is downloadable " - for ver in pkg._pkg.version_list: - if ver.downloadable: - return True - return False - - def _getUnusedDependencies(self): - " get all package names that are not downloadable " - unused_dependencies = set() - for pkg in self: - if pkg.is_installed and self._depcache.is_garbage(pkg._pkg): - unused_dependencies.add(pkg.name) - return unused_dependencies - - def get_installed_demoted_packages(self): - """ return list of installed and demoted packages - - If a demoted package is a automatic install it will be skipped - """ - demotions = set() - demotions_file = self.config.get("Distro", "Demotions") - if os.path.exists(demotions_file): - with open(demotions_file) as demotions_f: - for line in demotions_f: - if not line.startswith("#"): - demotions.add(line.strip()) - installed_demotions = set() - for demoted_pkgname in demotions: - if demoted_pkgname not in self: - continue - pkg = self[demoted_pkgname] - if (not pkg.is_installed or - self._depcache.is_auto_installed(pkg._pkg) or - pkg.marked_delete): - continue - installed_demotions.add(pkg) - return list(installed_demotions) - - def _getForeignPkgs(self, allowed_origin, fromDist, toDist): - """ get all packages that are installed from a foreign repo - (and are actually downloadable) - """ - foreign_pkgs = set() - for pkg in self: - if pkg.is_installed and self.downloadable(pkg): - if not pkg.candidate: - continue - # assume it is foreign and see if it is from the - # official archive - foreign = True - for origin in pkg.candidate.origins: - # FIXME: use some better metric here - if fromDist in origin.archive and \ - origin.origin == allowed_origin: - foreign = False - if toDist in origin.archive and \ - origin.origin == allowed_origin: - foreign = False - if foreign: - foreign_pkgs.add(pkg.name) - return foreign_pkgs - - def checkFreeSpace(self, snapshots_in_use=False): - """ - this checks if we have enough free space on /var, /boot and /usr - with the given cache - - Note: this can not be fully accurate if there are multiple - mountpoints for /usr, /var, /boot - """ - - class FreeSpace(object): - " helper class that represents the free space on each mounted fs " - def __init__(self, initialFree): - self.free = initialFree - self.need = 0 - - def make_fs_id(d): - """ return 'id' of a directory so that directories on the - same filesystem get the same id (simply the mount_point) - """ - for mount_point in mounted: - if d.startswith(mount_point): - return mount_point - return "/" - - # this is all a bit complicated - # 1) check what is mounted (in mounted) - # 2) create FreeSpace objects for the dirs we are interested in - # (mnt_map) - # 3) use the mnt_map to check if we have enough free space and - # if not tell the user how much is missing - mounted = [] - mnt_map = {} - fs_free = {} - with open("/proc/mounts") as mounts: - for line in mounts: - try: - (what, where, fs, options, a, b) = line.split() - except ValueError as e: - logging.debug("line '%s' in /proc/mounts not understood (%s)" % (line, e)) - continue - if not where in mounted: - mounted.append(where) - # make sure mounted is sorted by longest path - mounted.sort(key=len, reverse=True) - archivedir = apt_pkg.config.find_dir("Dir::Cache::archives") - aufs_rw_dir = "/tmp/" - if (hasattr(self, "config") and - self.config.getWithDefault("Aufs", "Enabled", False)): - aufs_rw_dir = self.config.get("Aufs", "RWDir") - if not os.path.exists(aufs_rw_dir): - os.makedirs(aufs_rw_dir) - logging.debug("cache aufs_rw_dir: %s" % aufs_rw_dir) - for d in ["/", "/usr", "/var", "/boot", archivedir, aufs_rw_dir, "/home", "/tmp/"]: - d = os.path.realpath(d) - fs_id = make_fs_id(d) - if os.path.exists(d): - st = os.statvfs(d) - free = st.f_bavail * st.f_frsize - else: - logging.warning("directory '%s' does not exists" % d) - free = 0 - if fs_id in mnt_map: - logging.debug("Dir %s mounted on %s" % - (d, mnt_map[fs_id])) - fs_free[d] = fs_free[mnt_map[fs_id]] - else: - logging.debug("Free space on %s: %s" % - (d, free)) - mnt_map[fs_id] = d - fs_free[d] = FreeSpace(free) - del mnt_map - logging.debug("fs_free contains: '%s'" % fs_free) - - # now calculate the space that is required on /boot - # we do this by checking how many linux-image-$ver packages - # are installed or going to be installed - kernel_count = 0 - for pkg in self: - # we match against everything that looks like a kernel - # and add space check to filter out metapackages - if re.match("^linux-(image|image-debug)-[0-9.]*-.*", pkg.name): - # upgrade because early in the release cycle the major version - # may be the same or they might be -lts- kernels - if pkg.marked_install or pkg.marked_upgrade: - logging.debug("%s (new-install) added with %s to boot space" % (pkg.name, KERNEL_SIZE)) - kernel_count += 1 - # space calculated per LP: #1646222 - space_in_boot = (kernel_count * KERNEL_SIZE - + (kernel_count + 1) * INITRD_SIZE) - - # we check for various sizes: - # archivedir is where we download the debs - # /usr is assumed to get *all* of the install space (incorrect, - # but as good as we can do currently + safety buffer - # / has a small safety buffer as well - required_for_aufs = 0.0 - if (hasattr(self, "config") and - self.config.getWithDefault("Aufs", "Enabled", False)): - logging.debug("taking aufs overlay into space calculation") - aufs_rw_dir = self.config.get("Aufs", "RWDir") - # if we use the aufs rw overlay all the space is consumed - # the overlay dir - for pkg in self: - if pkg.marked_upgrade or pkg.marked_install: - required_for_aufs += pkg.candidate.installed_size - - # add old size of the package if we use snapshots - required_for_snapshots = 0.0 - if snapshots_in_use: - for pkg in self: - if (pkg.is_installed and - (pkg.marked_upgrade or pkg.marked_delete)): - required_for_snapshots += pkg.installed.installed_size - logging.debug("additional space for the snapshots: %s" % required_for_snapshots) - - # sum up space requirements - for (dir, size) in [(archivedir, self.required_download), - ("/usr", self.additional_required_space), - # this is only >0 for the deb-to-snap quirks - ("/var", self.additional_required_space_for_snaps), - # plus 50M safety buffer in /usr - ("/usr", 50*1024*1024), - ("/boot", space_in_boot), - ("/tmp", 5*1024*1024), # /tmp for dkms LP: #427035 - ("/", 10*1024*1024), # small safety buffer / - (aufs_rw_dir, required_for_aufs), - # if snapshots are in use - ("/usr", required_for_snapshots), - ]: - # we are ensuring we have more than enough free space not less - if size < 0: - continue - dir = os.path.realpath(dir) - logging.debug("dir '%s' needs '%s' of '%s' (%f)" % (dir, size, fs_free[dir], fs_free[dir].free)) - fs_free[dir].free -= size - fs_free[dir].need += size - - # check for space required violations - required_list = {} - for dir in fs_free: - if fs_free[dir].free < 0: - # ensure unicode here (LP: #1172740) - free_at_least = apt_pkg.size_to_str(float(abs(fs_free[dir].free)+1)) - if isinstance(free_at_least, bytes): - free_at_least = free_at_least.decode( - locale.getpreferredencoding()) - free_needed = apt_pkg.size_to_str(fs_free[dir].need) - if isinstance(free_needed, bytes): - free_needed = free_needed.decode( - locale.getpreferredencoding()) - # make_fs_id ensures we only get stuff on the same - # mountpoint, so we report the requirements only once - # per mountpoint - required_list[make_fs_id(dir)] = FreeSpaceRequired(free_needed, make_fs_id(dir), free_at_least) - # raise exception if free space check fails - if len(required_list) > 0: - logging.error("Not enough free space: %s" % [str(i) for i in required_list]) - raise NotEnoughFreeSpaceError(list(required_list.values())) - return True - - -if __name__ == "__main__": - import sys - # from .DistUpgradeConfigParser import DistUpgradeConfig - # from .DistUpgradeView import DistUpgradeView - # print("foo") - # c = MyCache(DistUpgradeConfig("."), DistUpgradeView(), None) - # #c.checkForNvidia() - # #print(c._identifyObsoleteKernels()) - # print(c.checkFreeSpace()) - sys.exit() - - # c.clear() - # c.create_snapshot() - # c.installedTasks - # c.installTasks(["ubuntu-desktop"]) - # print(c.get_changes()) - # c.restore_snapshot() diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/MyCache.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/MyCache.py deleted file mode 100644 index fec5960..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/MyCache.py +++ /dev/null @@ -1,433 +0,0 @@ -# MyCache.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2004-2008 Canonical -# -# Author: Michael Vogt -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import absolute_import, print_function - -import warnings -warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) -import apt -import apt_pkg -import logging -import os -from urllib.error import HTTPError -from urllib.request import urlopen -from urllib.parse import urlsplit -from http.client import BadStatusLine -import socket -import re -import SystemUpdater.Core.DistUpgradeCache -from gettext import gettext as _ -try: - from launchpadlib.launchpad import Launchpad -except ImportError: - Launchpad = None - -CHANGELOGS_POOL = "https://changelogs.ubuntu.com/changelogs/pool/" -CHANGELOGS_URI = CHANGELOGS_POOL + "%s/%s/%s/%s_%s/%s" - - -class HttpsChangelogsUnsupportedError(Exception): - """ https changelogs with credentials are unsupported because of the - lack of certitifcation validation in urllib2 which allows MITM - attacks to steal the credentials - """ - pass - - -class MyCache(SystemUpdater.Core.DistUpgradeCache.MyCache): - - CHANGELOG_ORIGIN = "Ubuntu" - - def __init__(self, progress, rootdir=None): - apt.Cache.__init__(self, progress, rootdir) - # save for later - self.rootdir = rootdir - # raise if we have packages in reqreinst state - # and let the caller deal with that (runs partial upgrade) - assert len(self.req_reinstall_pkgs) == 0 - # check if the dpkg journal is ok (we need to do that here - # too because libapt will only do it when it tries to lock - # the packaging system) - assert(not self._dpkgJournalDirty()) - # init the regular cache - self._initDepCache() - self.all_changes = {} - self.all_news = {} - # on broken packages, try to fix via saveDistUpgrade() - if self._depcache.broken_count > 0: - self.saveDistUpgrade() - assert (self._depcache.broken_count == 0 - and self._depcache.del_count == 0) - self.launchpad = None - - def _dpkgJournalDirty(self): - """ - test if the dpkg journal is dirty - (similar to debSystem::CheckUpdates) - """ - d = os.path.dirname( - apt_pkg.config.find_file("Dir::State::status")) + "/updates" - for f in os.listdir(d): - if re.match("[0-9]+", f): - return True - return False - - def _initDepCache(self): - self._depcache.read_pinfile() - self._depcache.init() - - def clear(self): - self._initDepCache() - - @property - def required_download(self): - """ get the size of the packages that are required to download """ - pm = apt_pkg.PackageManager(self._depcache) - fetcher = apt_pkg.Acquire() - pm.get_archives(fetcher, self._list, self._records) - return fetcher.fetch_needed - - @property - def install_count(self): - return self._depcache.inst_count - - def keep_count(self): - return self._depcache.keep_count - - @property - def del_count(self): - return self._depcache.del_count - - def _check_dependencies(self, target, deps): - """Return True if any of the dependencies in deps match target.""" - # TODO: handle virtual packages - for dep_or in deps: - if not dep_or: - continue - match = True - for base_dep in dep_or: - if (base_dep.name != target.package.shortname - or not apt_pkg.check_dep( - target.version, base_dep.relation, base_dep.version)): - match = False - if match: - return True - return False - - def find_removal_justification(self, pkg): - target = pkg.installed - if not target: - return False - for cpkg in self: - candidate = cpkg.candidate - if candidate is not None: - if (self._check_dependencies( - target, candidate.get_dependencies("Conflicts")) - and self._check_dependencies( - target, candidate.get_dependencies("Replaces"))): - logging.info( - "%s Conflicts/Replaces %s; allowing removal" % ( - candidate.package.shortname, pkg.shortname)) - return True - return False - - def saveDistUpgrade(self): - """ this functions mimics a upgrade but will never remove anything """ - #upgrade(True) 为True时使用dist-upgrade进行升级 - self._depcache.upgrade(True) - wouldDelete = self._depcache.del_count - wouldDelete = 0 - if wouldDelete > 0: - deleted_pkgs = [pkg for pkg in self if pkg.marked_delete] - assert wouldDelete == len(deleted_pkgs) - for pkg in deleted_pkgs: - if self.find_removal_justification(pkg): - wouldDelete -= 1 - if wouldDelete > 0: - self.clear() - assert (self._depcache.broken_count == 0 - and self._depcache.del_count == 0) - # else: - # assert self._depcache.broken_count == 0 - self._depcache.upgrade() - return wouldDelete - - def _strip_epoch(self, verstr): - " strip of the epoch " - vers_no_epoch = verstr.split(":") - if len(vers_no_epoch) > 1: - verstr = "".join(vers_no_epoch[1:]) - return verstr - - def _get_changelog_or_news(self, name, fname, strict_versioning=False, - changelogs_uri=None): - " helper that fetches the file in question " - # don't touch the gui in this function, it needs to be thread-safe - pkg = self[name] - - # get the src package name - srcpkg = pkg.candidate.source_name - - # assume "main" section - src_section = "main" - # use the section of the candidate as a starting point - section = pkg._pcache._depcache.get_candidate_ver(pkg._pkg).section - - # get the source version - srcver_epoch = pkg.candidate.source_version - srcver = self._strip_epoch(srcver_epoch) - - split_section = section.split("/") - if len(split_section) > 1: - src_section = split_section[0] - - # lib is handled special - prefix = srcpkg[0] - if srcpkg.startswith("lib"): - prefix = "lib" + srcpkg[3] - - # the changelogs_uri argument overrides the default changelogs_uri, - # this is useful for e.g. PPAs where we construct the changelogs - # path differently - if changelogs_uri: - uri = changelogs_uri - else: - uri = CHANGELOGS_URI % (src_section, prefix, srcpkg, srcpkg, - srcver, fname) - - # https uris are not supported when they contain a username/password - # because the urllib2 https implementation will not check certificates - # and so its possible to do a man-in-the-middle attack to steal the - # credentials - res = urlsplit(uri) - if res.scheme == "https" and res.username: - raise HttpsChangelogsUnsupportedError( - "https locations with username/password are not" - "supported to fetch changelogs") - - # print("Trying: %s " % uri) - changelog = urlopen(uri) - #print(changelog.read()) - # do only get the lines that are new - alllines = "" - regexp = "^%s \\((.*)\\)(.*)$" % (re.escape(srcpkg)) - - while True: - line = changelog.readline().decode("UTF-8", "replace") - if line == "": - break - match = re.match(regexp, line) - if match: - # strip epoch from installed version - # and from changelog too - installed = getattr(pkg.installed, "version", None) - if installed and ":" in installed: - installed = installed.split(":", 1)[1] - changelogver = match.group(1) - if changelogver and ":" in changelogver: - changelogver = changelogver.split(":", 1)[1] - # we test for "==" here for changelogs - # to ensure that the version - # is actually really in the changelog - if not - # just display it all, this catches cases like: - # gcc-defaults with "binver=4.3.1" and srcver=1.76 - # - # for NEWS.Debian we do require the changelogver > installed - if strict_versioning: - if (installed - and apt_pkg.version_compare(changelogver, - installed) < 0): - break - else: - if (installed - and apt_pkg.version_compare(changelogver, - installed) == 0): - break - alllines = alllines + line - return alllines - - def _extract_ppa_changelog_uri(self, name): - """Return the changelog URI from the Launchpad API - - Return None in case of an error. - """ - if not Launchpad: - logging.warning("Launchpadlib not available, cannot retrieve PPA " - "changelog") - return None - - cdt = self[name].candidate - for uri in cdt.uris: - if urlsplit(uri).hostname != 'ppa.launchpad.net': - continue - match = re.search('http.*/(.*)/(.*)/ubuntu/.*', uri) - if match is not None: - user, ppa = match.group(1), match.group(2) - break - else: - logging.error("Unable to find a valid PPA candidate URL.") - return - - # Login on launchpad if we are not already - if self.launchpad is None: - self.launchpad = Launchpad.login_anonymously('update-manager', - 'production', - version='devel') - - archive = self.launchpad.archives.getByReference( - reference='~%s/ubuntu/%s' % (user, ppa) - ) - if archive is None: - logging.error("Unable to retrieve the archive from the Launchpad " - "API.") - return - - spphs = archive.getPublishedSources(source_name=cdt.source_name, - exact_match=True, - version=cdt.source_version) - if not spphs: - logging.error("No published sources were retrieved from the " - "Launchpad API.") - return - - return spphs[0].changelogUrl() - - def _guess_third_party_changelogs_uri_by_source(self, name): - pkg = self[name] - deb_uri = pkg.candidate.uri - if deb_uri is None: - return None - srcrec = pkg.candidate.record.get("Source") - if not srcrec: - return None - # srcpkg can be "apt" or "gcc-default (1.0)" - srcpkg = srcrec.split("(")[0].strip() - if "(" in srcrec: - srcver = srcrec.split("(")[1].rstrip(")") - else: - srcver = pkg.candidate.source_version - base_uri = deb_uri.rpartition("/")[0] - return base_uri + "/%s_%s.changelog" % (srcpkg, srcver) - - def _guess_third_party_changelogs_uri_by_binary(self, name): - """ guess changelogs uri based on ArchiveURI by replacing .deb - with .changelog - """ - # there is always a pkg and a pkg.candidate, no need to add - # check here - pkg = self[name] - deb_uri = pkg.candidate.uri - if deb_uri: - return "%s.changelog" % deb_uri.rsplit(".", 1)[0] - return None - - def get_news_and_changelog(self, name, lock): - self.get_news(name) - self.get_changelog(name) - try: - lock.release() - except Exception: - pass - - def get_news(self, name): - " get the NEWS.Debian file from the changelogs location " - try: - news = self._get_changelog_or_news(name, "NEWS.Debian", True) - except Exception: - return - if news: - self.all_news[name] = news - - def _fetch_changelog_for_third_party_package(self, name, origins): - # Special case for PPAs - changelogs_uri_ppa = None - for origin in origins: - if origin.origin.startswith('LP-PPA-'): - try: - changelogs_uri_ppa = self._extract_ppa_changelog_uri(name) - break - except Exception: - logging.exception("Unable to connect to the Launchpad " - "API.") - # Try non official changelog location - changelogs_uri_binary = \ - self._guess_third_party_changelogs_uri_by_binary(name) - changelogs_uri_source = \ - self._guess_third_party_changelogs_uri_by_source(name) - error_message = "" - for changelogs_uri in [changelogs_uri_ppa, - changelogs_uri_binary, - changelogs_uri_source]: - if changelogs_uri: - try: - changelog = self._get_changelog_or_news( - name, "changelog", False, changelogs_uri) - self.all_changes[name] += changelog - except (HTTPError, HttpsChangelogsUnsupportedError): - # no changelogs_uri or 404 - error_message = _( - "This update does not come from a " - "source that supports changelogs.") - except (IOError, BadStatusLine, socket.error): - # network errors and others - logging.exception("error on changelog fetching") - error_message = _( - "Failed to download the list of changes. \n" - "Please check your Internet connection.") - self.all_changes[name] += error_message - - def get_changelog(self, name): - " get the changelog file from the changelog location " - origins = self[name].candidate.origins - self.all_changes[name] = _("Changes for %s versions:\n" - "Installed version: %s\n" - "Available version: %s\n\n") % \ - (name, getattr(self[name].installed, "version", None), - self[name].candidate.version) - if self.CHANGELOG_ORIGIN not in [o.origin for o in origins]: - self._fetch_changelog_for_third_party_package(name, origins) - return - # fixup epoch handling version - srcpkg = self[name].candidate.source_name - srcver_epoch = self[name].candidate.source_version.replace(':', '%3A') - try: - changelog = self._get_changelog_or_news(name, "changelog") - if len(changelog) == 0: - changelog = _("The changelog does not contain any relevant " - "changes.\n\n" - "Please use http://launchpad.net/ubuntu/+source/" - "%s/%s/+changelog\n" - "until the changes become available or try " - "again later.") % (srcpkg, srcver_epoch) - except HTTPError: - changelog = _("The list of changes is not available yet.\n\n" - "Please use http://launchpad.net/ubuntu/+source/" - "%s/%s/+changelog\n" - "until the changes become available or try again " - "later.") % (srcpkg, srcver_epoch) - except (IOError, BadStatusLine, socket.error) as e: - print("caught exception: ", e) - changelog = _("Failed to download the list " - "of changes. \nPlease " - "check your Internet " - "connection.") - self.all_changes[name] += changelog diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/UpdateList.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/UpdateList.py deleted file mode 100644 index a53d2c1..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/UpdateList.py +++ /dev/null @@ -1,675 +0,0 @@ -# UpdateList.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2004-2013 Canonical -# -# Author: Michael Vogt -# Dylan McCall -# Michael Terry -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import print_function - -import warnings -warnings.filterwarnings("ignore", "Accessed deprecated property", - DeprecationWarning) - -from gettext import gettext as _, install -import apt -import logging -import itertools -import os -import random -import glob -import json -from gi.repository import Gio - -import shutil -from .utils import humanize_size -from SystemUpdater.Core import utils -from SystemUpdater.Core import filter - -class UpdateItem(): - def __init__(self, pkg, name, icon, to_remove): - self.icon = icon - self.name = name - self.pkg = pkg - self.to_remove = to_remove - - def is_selected(self): - if not self.to_remove: - return self.pkg.marked_install or self.pkg.marked_upgrade - else: - return self.pkg.marked_delete - - -class UpdateGroup(UpdateItem): - _depcache = {} - - def __init__(self, pkg, name, icon, to_remove): - UpdateItem.__init__(self, pkg, name, icon, to_remove) - self._items = set() - self._deps = set() - self.core_item = None - if pkg is not None: - self.core_item = UpdateItem(pkg, name, icon, to_remove) - self._items.add(self.core_item) - - @property - def items(self): - all_items = [] - all_items.extend(self._items) - return sorted(all_items, key=lambda a: a.name.lower()) - - def add(self, pkg, cache=None, eventloop_callback=None, to_remove=False): - name = utils.get_package_label(pkg) - icon = Gio.ThemedIcon.new("package") - self._items.add(UpdateItem(pkg, name, icon, to_remove)) - # If the pkg is in self._deps, stop here. We have already calculated - # the recursive dependencies for this package, no need to do it again. - if cache and pkg.name in cache and pkg.name not in self._deps: - if not self._deps: - # Initial deps haven't been calculated. As we're checking - # whether _deps is empty in is_dependency, we must init now or - # it won't be done at all. - self._init_deps(cache, eventloop_callback) - self._add_deps(pkg, cache, eventloop_callback) - - def contains(self, item): - return item in self._items - - def _init_deps(self, cache, eventloop_callback): - for item in self._items: - if item.pkg and item.pkg.name not in self._deps: - self._add_deps(item.pkg, cache, eventloop_callback) - - def _add_deps(self, pkg, cache, eventloop_callback): - """Adds pkg and dependencies of pkg to the dependency list.""" - if pkg is None or pkg.candidate is None or pkg.name in self._deps: - # This shouldn't really happen. If we land here often, it's a sign - # that something has gone wrong. Unless all pkgs are None it's not - # a critical issue - a hit to the performance at most. - reason = ((not pkg or not pkg.candidate) - and "Package was None or didn't have a candidate." - or "%s already in _deps." % pkg.name) - logging.debug("Useless call to _add_deps. %s" % reason) - return - if len(self._deps) % 200 == 0 and callable(eventloop_callback): - # Don't spin the loop every time _add_deps is called. - eventloop_callback() - - self._deps.add(pkg.name) - - if pkg.name in self._depcache: - for dep in self._depcache[pkg.name]: - if dep not in self._deps and dep in cache: - self._add_deps(cache[dep], cache, eventloop_callback) - else: - candidate = pkg.candidate - dependencies = candidate.get_dependencies('Depends', 'Recommends') - for dependency_pkg in itertools.chain.from_iterable(dependencies): - name = dependency_pkg.name - if name not in self._deps and name in cache: - self._depcache.setdefault(pkg.name, []).append(name) - self._add_deps(cache[name], cache, eventloop_callback) - - def is_dependency(self, maybe_dep, cache=None, eventloop_callback=None): - if not self._deps and cache: - self._init_deps(cache, eventloop_callback) - - return maybe_dep.name in self._deps - - def packages_are_selected(self): - for item in self.items: - if item.is_selected(): - return True - return False - - def selection_is_inconsistent(self): - pkgs_installing = [item for item in self.items if item.is_selected()] - return (len(pkgs_installing) > 0 - and len(pkgs_installing) < len(self.items)) - - def get_total_size(self): - if self.to_remove: - return 0 - size = 0 - for item in self.items: - size += getattr(item.pkg.candidate, "size", 0) - return size - - -class UpdateApplicationGroup(UpdateGroup): - def __init__(self, pkg, application, to_remove): - name = application.get_display_name() - icon = application.get_icon() - super(UpdateApplicationGroup, self).__init__(pkg, name, icon, - to_remove) - - -class UpdatePackageGroup(UpdateGroup): - def __init__(self, pkg, to_remove): - name = utils.get_package_label(pkg) - icon = Gio.ThemedIcon.new("package") - super(UpdatePackageGroup, self).__init__(pkg, name, icon, to_remove) - - -class UpdateSystemGroup(UpdateGroup): - def __init__(self, cache, to_remove): - # Translators: the %s is a distro name, like 'Ubuntu' and 'base' as in - # the core components and packages. - name = _("%s base") % utils.get_ubuntu_flavor_name(cache=cache) - icon = Gio.ThemedIcon.new("distributor-logo") - super(UpdateSystemGroup, self).__init__(None, name, icon, to_remove) - - -class UpdateOrigin(): - def __init__(self, desc, importance): - self.packages = [] - self.importance = importance - self.description = desc - - -class UpdateList(): - """ - class that contains the list of available updates in - self.pkgs[origin] where origin is the user readable string - """ - - # the key in the debian/control file used to add the phased - # updates percentage - PHASED_UPDATES_KEY = "Phased-Update-Percentage" - - # the file that contains the uniq machine id - UNIQ_MACHINE_ID_FILE = "/etc/machine-id" - # use the dbus one as a fallback - UNIQ_MACHINE_ID_FILE_FALLBACK = "/var/lib/dbus/machine-id" - - APP_INSTALL_PATTERN = "/usr/share/app-install/desktop/%s:*.desktop" - - # the configuration key to turn phased-updates always on - ALWAYS_INCLUDE_PHASED_UPDATES = ( - "Update-Manager::Always-Include-Phased-Updates") - # ... or always off - NEVER_INCLUDE_PHASED_UPDATES = ( - "Update-Manager::Never-Include-Phased-Updates") - - def __init__(self, parent, dist=None): - self.dist = (dist if dist else utils.get_dist()) - self.distUpgradeWouldDelete = 0 - self.update_groups = [] - self.random = random.Random() - - #FIXME: 最好将这个常量通过配置文件读 - self.GROUPS_JSON_PKG = 'kylin-update-desktop-config' - - self.INPUT_CONFIG_PATH = '/usr/share/kylin-update-desktop-config/data' - self.OUTPUT_CONFIG_PATH = os.getenv('HOME') + '/.config' +'/update_manager_config' - - self.IMPORTANT_LIST_PATH="/var/lib/kylin-software-properties/template/important.list" - - # important推送列表 - self.important_list = [] - - #所有的组升级安装列表 - self.local_upgrade_list = {} - # a stable machine uniq id - try: - with open(self.UNIQ_MACHINE_ID_FILE) as f: - self.machine_uniq_id = f.read() - except FileNotFoundError: - with open(self.UNIQ_MACHINE_ID_FILE_FALLBACK) as f: - self.machine_uniq_id = f.read() - - if 'XDG_DATA_DIRS' in os.environ and os.environ['XDG_DATA_DIRS']: - data_dirs = os.environ['XDG_DATA_DIRS'] - else: - data_dirs = '/usr/local/share/:/usr/share/' - - #FIX 此处需要修复 application_dirs 包含正确的desktop文件的目录 - self.application_dirs = [os.path.join(base, 'applications') - for base in data_dirs.split(':')] - - if 'XDG_CURRENT_DESKTOP' in os.environ: - self.current_desktop = os.environ.get('XDG_CURRENT_DESKTOP') - else: - self.current_desktop = '' - self.desktop_cache = {} - - def _file_is_application(self, file_path): - # WARNING: This is called often if there's a lot of updates. A poor - # performing call here has a huge impact on the overall performance! - #通过判断包的配置文件是否存在.desktop - if not file_path.endswith(".desktop"): - # First the obvious case: If the path doesn't end in a .desktop - # extension, this isn't a desktop file. - return False - - #通过判断.desktop 文件是否在/usr/share/applications 里面 表示属于应用 - file_path = os.path.abspath(file_path) - for app_dir in self.application_dirs: - if file_path.startswith(app_dir): - return True - return False - - def _rate_application_for_package(self, application, pkg): - score = 0 - desktop_file = os.path.basename(application.get_filename()) - application_id = os.path.splitext(desktop_file)[0] - - if application.should_show(): - score += 1 - - if application_id == pkg.name: - score += 5 - - return score - - def _get_application_for_package(self, pkg): - desktop_files = [] - rated_applications = [] - - #拿到应用的desktop文件判断为一个应用 - for installed_file in pkg.installed_files: - if self._file_is_application(installed_file): - desktop_files.append(installed_file) - #此部分强制进行添加应用 - if pkg.name in self.desktop_cache: - desktop_files += self.desktop_cache[pkg.name] - - for desktop_file in desktop_files: - try: - application = Gio.DesktopAppInfo.new_from_filename( - desktop_file) - application.set_desktop_env(self.current_desktop) - except Exception as e: - logging.warning("Error loading .desktop file %s: %s" % - (desktop_file, e)) - continue - score = self._rate_application_for_package(application, pkg) - if score > 0: - rated_applications.append((score, application)) - - rated_applications.sort(key=lambda app: app[0], reverse=True) - if len(rated_applications) > 0: - return rated_applications[0][1] - else: - return None - - def _populate_desktop_cache(self, pkg_names): - if not pkg_names: - # No updates; This shouldn't have happened. - logging.warning("_populate_desktop_cache called with empty list " - "of packages.") - return - elif len(pkg_names) == 1: - # One update; Let glob do the matching. - pattern = self.APP_INSTALL_PATTERN % pkg_names[0] - else: - # More than one update available. Glob all desktop files and store - # those that match an upgradeable package. - pattern = self.APP_INSTALL_PATTERN % "*" - - for desktop_file in glob.iglob(pattern): - try: - pkg = desktop_file.split('/')[-1].split(":")[0] - except IndexError: - # app-install-data desktop file had an unexpected naming - # convention. As we can't extract the package name from - # the path, just ignore it. - logging.error("Could not extract package name from '%s'. " - "File ignored." % desktop_file) - continue - - if pkg in pkg_names: - self.desktop_cache.setdefault(pkg, []).append(desktop_file) - logging.debug("App candidate for %s: %s" % - (pkg, desktop_file)) - - def _is_security_update(self, pkg): - """ This will test if the pkg is a security update. - This includes if there is a newer version in -updates, but also - an older update available in -security. For example, if - installed pkg A v1.0 is available in both -updates (as v1.2) and - -security (v1.1). we want to display it as a security update. - - :return: True if the update comes from the security pocket - """ - if not self.dist: - return False - inst_ver = pkg._pkg.current_ver - for ver in pkg._pkg.version_list: - # discard is < than installed ver - if (inst_ver - and apt.apt_pkg.version_compare(ver.ver_str, - inst_ver.ver_str) <= 0): - continue - # check if we have a match - for (verFileIter, index) in ver.file_list: - if verFileIter.archive == "%s-security" % self.dist and \ - verFileIter.origin == "Ubuntu": - indexfile = pkg._pcache._list.find_index(verFileIter) - if indexfile: # and indexfile.IsTrusted: - return True - return False - - def _is_ignored_phased_update(self, pkg): - """ This will test if the pkg is a phased update and if - it needs to get installed or ignored. - - :return: True if the updates should be ignored - """ - # allow the admin to override this - if apt.apt_pkg.config.find_b( - self.ALWAYS_INCLUDE_PHASED_UPDATES, False): - return False - - if self.PHASED_UPDATES_KEY in pkg.candidate.record: - if apt.apt_pkg.config.find_b( - self.NEVER_INCLUDE_PHASED_UPDATES, False): - logging.info("holding back phased update per configuration") - return True - - # its important that we always get the same result on - # multiple runs of the update-manager, so we need to - # feed a seed that is a combination of the pkg/ver/machine - self.random.seed("%s-%s-%s" % ( - pkg.candidate.source_name, pkg.candidate.version, - self.machine_uniq_id)) - threshold = pkg.candidate.record[self.PHASED_UPDATES_KEY] - percentage = self.random.randint(0, 100) - if percentage > int(threshold): - logging.info("holding back phased update %s (%s < %s)" % ( - pkg.name, threshold, percentage)) - return True - return False - - def _get_linux_packages(self): - "Return all binary packages made by the linux-meta source package" - # Hard code this rather than generate from source info in cache because - # that might only be available if we have deb-src lines. I think we - # could also generate it by iterating over all the binary package info - # we have, but that is costly. These don't change often. - return ['linux', - 'linux-cloud-tools-generic', - 'linux-cloud-tools-lowlatency', - 'linux-cloud-tools-virtual', - 'linux-crashdump', - 'linux-generic', - 'linux-generic-lpae', - 'linux-headers-generic', - 'linux-headers-generic-lpae', - 'linux-headers-lowlatency', - 'linux-headers-lowlatency-lpae', - 'linux-headers-server', - 'linux-headers-virtual', - 'linux-image', - 'linux-image-extra-virtual', - 'linux-image-generic', - 'linux-image-generic-lpae', - 'linux-image-lowlatency', - 'linux-image-virtual', - 'linux-lowlatency', - 'linux-signed-generic', - 'linux-signed-image-generic', - 'linux-signed-image-lowlatency', - 'linux-signed-lowlatency', - 'linux-source', - 'linux-tools-generic', - 'linux-tools-generic-lpae', - 'linux-tools-lowlatency', - 'linux-tools-virtual', - 'linux-virtual'] - - def _make_groups(self, cache, pkgs, eventloop_callback, to_remove=False): - if not pkgs: - return [] - ungrouped_pkgs = [] - app_groups = [] - pkg_groups = [] - - for pkg in pkgs: - #查看这个包属于那个应用的 并获取这个应用的一些属性 例如 应用名称和图标的等等 - app = self._get_application_for_package(pkg) - if app is not None: - #包含 应用名称和图标 - app_group = UpdateApplicationGroup(pkg, app, to_remove) - app_groups.append(app_group) - else: - ungrouped_pkgs.append(pkg) - - # Stick together applications and their immediate dependencies - #将应用和它们的依赖关系 结合在一起 - for pkg in list(ungrouped_pkgs): - dep_groups = [] - for group in app_groups: - if group.is_dependency(pkg, cache, eventloop_callback): - dep_groups.append(group) - if len(dep_groups) > 1: - break - #此来决定是这一个包所独有的依赖 如果一个依赖存在2个以上的就不 - if len(dep_groups) == 1: - dep_groups[0].add(pkg, cache, eventloop_callback, to_remove) - ungrouped_pkgs.remove(pkg) - - system_group = None - if ungrouped_pkgs: - # Separate out system base packages. If we have already found an - # application for all updates, don't bother. - meta_group = UpdateGroup(None, None, None, to_remove) - flavor_package = utils.get_ubuntu_flavor_package(cache=cache) - meta_pkgs = [flavor_package, "ubuntu-standard", "ubuntu-minimal"] - meta_pkgs.extend(self._get_linux_packages()) - for pkg in meta_pkgs: - if pkg in cache: - meta_group.add(cache[pkg]) - for pkg in ungrouped_pkgs: - if meta_group.is_dependency(pkg, cache, eventloop_callback): - if system_group is None: - system_group = UpdateSystemGroup(cache, to_remove) - system_group.add(pkg) - else: - pkg_groups.append(UpdatePackageGroup(pkg, to_remove)) - - app_groups.sort(key=lambda a: a.name.lower()) - pkg_groups.sort(key=lambda a: a.name.lower()) - if system_group: - pkg_groups.append(system_group) - - return app_groups + pkg_groups - - def _read_important_list(self): - header = '' - desc = '' - # 获取importantlist 本次更新推送 - try: - with open(self.IMPORTANT_LIST_PATH, 'r') as f: - data = f.read() - self.important_list = data.split() - logging.info("importantList: %s",self.important_list) - return True - except Exception as e: - header = _("read important list failed") - desc = ("%s",str(e)) - logging.info(header + desc) - return False,header,desc - - def _make_pkg_info_json(self,cache,pkgs_list): - size = 0 - total_size = 0 - pkgs_info_json = {} - for pkg_name in pkgs_list: - try: - pkg = cache[pkg_name] - - #获取下载大小 - size = getattr(pkg.candidate, "size", 0) - total_size = total_size + size - pkgs_info_json.update({pkg_name:{"size":size}}) - except Exception as e: - logging.info("this package(%s) not in list and error mes:%s",pkg_name,e) - pass - pkgs_info_json.update({"total_size":humanize_size(total_size)}) - return pkgs_info_json - - #检查包是否在cache中 返回新得列表 - def _check_pkg_in_cache(self,cache,pkgs_list): - new_pkgs_list = [] - for pkg_name in pkgs_list: - #检查是否在cache 以及 是否安装检查 - if pkg_name in cache and not cache[pkg_name].is_installed: - new_pkgs_list.append(pkg_name) - else: - pass - # logging.info("this package(%s) not in list ",pkg_name) - return new_pkgs_list - - def _make_output_json(self,data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list): - groups_base_info = {} - output_json = {} - - #FIXME: 确定输出文件的文件名 以及放置位置 - output_config_name = self.OUTPUT_CONFIG_PATH + '/' + data['package'] + '_output.json' - - #4、添加一些基础信息 - groups_base_info.update({"package":data['package']}) - groups_base_info.update({"version":data['version']}) - groups_base_info.update({"name":data['name']}) - groups_base_info.update({"description":data['description']}) - groups_base_info.update({"icon":data['icon']}) - - #5、添加升级的内容 - output_json.update(groups_base_info) - output_json.update({"upgrade_list":upgrade_pkgs_json}) - output_json.update({"install_list":install_pkgs_json}) - output_json.update({"hold_list":hold_pkgs_list}) - output_json.update({"remove_list":remove_pkgs_list}) - - #6 产生JSON文件 - with open(output_config_name, 'w', encoding='utf-8') as f: - json.dump(output_json, f, ensure_ascii=False, indent=4) - logging.info("Generate Jsonfile(%s) to complete... ",output_config_name) - - def _make_groups_upgrade(self,cache,pkgs_install = [], pkgs_upgrade = [], pkgs_remove = []): - try: - files = os.listdir(self.INPUT_CONFIG_PATH) #获得文件夹中所有文件的名称列表 - upgrade_groups_list = [] - - for file in files: - #判是否是目录以及是否以JSON结尾 - if file.endswith('.json'): - with open(self.INPUT_CONFIG_PATH+"/"+file,'r') as f: - data = json.load(f) - group_name = data['package'] - - #过滤没有推送的配置文件 - if not group_name in self.important_list: - continue - - upgrade_pkgs_list = data['upgrade_list'] - hold_pkgs_list = data['hold_list'] - - #这个安装升级列表中包含当前系统的cache中没有的包 需要过滤 - remove_pkgs_list = data['remove_list'] - - #检查包是否在cache中 以及是否已经安装 - new_install_pkgs_list = self._check_pkg_in_cache(cache,data['install_list']) - - #进行交集 升级列表 - upgrade_intersection_pkgs = list(set(pkgs_upgrade) & set(upgrade_pkgs_list)) - - #判断当前是否可升级或者新装的包 - if len(new_install_pkgs_list) == 0 and len(upgrade_intersection_pkgs) == 0: - continue - - #在总升级列表中移除这些包 - for pkg in upgrade_intersection_pkgs: - pkgs_upgrade.remove(pkg) - - #3、生成升级的包列表JSON - upgrade_pkgs_json = self._make_pkg_info_json(cache,upgrade_intersection_pkgs) - - #2、生成安装的软件列表 - install_pkgs_json = self._make_pkg_info_json(cache,new_install_pkgs_list) - - #输出JSON配置文件 - self._make_output_json(data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list) - - upgrade_groups_list.append(group_name) - - #添加到字典维护的升级列表 - self.local_upgrade_list.update({group_name:{"pkgs_upgrade":upgrade_intersection_pkgs,"pkgs_install":new_install_pkgs_list}}) - logging.info("group(%s) upgrade:%d install:%d",group_name,len(upgrade_intersection_pkgs),len(new_install_pkgs_list)) - else: - pass - #添加所有可升级的组列表 - self.local_upgrade_list.update({"upgrade_groups_list":upgrade_groups_list}) - except Exception as e: - logging.warning("Generate Jsonfile to failed... ") - logging.error(e) - - - def update(self, cache, eventloop_callback=None): - pkgs_install = [] - pkgs_upgrade = [] - pkgs_remove = [] - - header = '' - desc = '' - - self._read_important_list() - - #important_list 为空时此次不需要升级 - if not self.important_list: - #不需要升级 全部的软件都是新的 - header = _("No software updates are available.") - desc = _('important_list is Empty') - return True,header,desc - - #查找所有可升级的包 - for pkg in cache: - try: - if pkg.marked_install: - pkgs_install.append(pkg) - elif pkg.marked_upgrade: - pkgs_upgrade.append(pkg) - elif pkg.marked_delete: - pkgs_remove.append(pkg) - except Exception as e: - logging.error(e) - logging.info("System all upgradeable packages:new_install:%d upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) - - #源过滤 - # fu = filter.UpdateListFilterCache() - # allowed_origin_upgrade_pkgs = fu.check_in_allowed_origin(pkgs_upgrade) - - self._make_groups_upgrade(cache,pkgs_upgrade = ([pkg.name for pkg in pkgs_upgrade])) - - #是否存在可升级的组 - if self.local_upgrade_list.get('upgrade_groups_list',[]): - #增加需要移除的包列表 - self.local_upgrade_list.update({"pkgs_remove":[pkg.name for pkg in pkgs_remove]}) - return True,header,desc - else: - #不需要升级 全部的软件都是新的 - header = _("The software on this computer is up to date.") - desc = '' - return True,header,desc - - #FIXME: 目前此功能不使用 但是以此按应用进行分组是更好的展示升级列表的方式 - # self.update_groups = self._make_groups(cache, self.pkgs_upgrade, - # eventloop_callback) \ No newline at end of file diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/__init__.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/filter.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/filter.py deleted file mode 100644 index a2c1671..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/filter.py +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/python3 - -import apt -import apt_pkg -import fnmatch -import logging -import logging.handlers -import re -import os -import string -import subprocess -import sys -import json -import dbus -import threading - -try: - from typing import AbstractSet, cast, DefaultDict, Dict, Iterable, List - AbstractSet # pyflakes - DefaultDict # pyflakes - Dict # pyflakes - Iterable # pyflakes - List # pyflakes - from typing import Set, Tuple, Union - Set # pyflakes - Tuple # pyflakes - Union # pyflakes -except ImportError: - pass - -from email.message import Message -from gettext import gettext as _ - -import apt -import apt_pkg - - -ImportantListPath="/var/lib/kylin-software-properties/template/important.list" -DesktopSystemPath="/usr/share/kylin-update-desktop-config/data/" - - -# no py3 lsb_release in debian :/ -DISTRO_CODENAME = subprocess.check_output( - ["lsb_release", "-c", "-s"], universal_newlines=True).strip() # type: str -DISTRO_DESC = subprocess.check_output( - ["lsb_release", "-d", "-s"], universal_newlines=True).strip() # type: str -DISTRO_ID = subprocess.check_output( - ["lsb_release", "-i", "-s"], universal_newlines=True).strip() # type: str - - -class UpdateListFilterCache(apt.Cache): - - def __init__(self): - # whitelist - self.upgradeList = [] - # 必须升级的包 - self.installList = [] - # self._cached_candidate_pkgnames = set() # type: Set[str] - - self.allowed_origins = get_allowed_origins() - self.allowed_origins = deleteDuplicatedElementFromList(self.allowed_origins) - logging.info("Allowed origins are: %s", - self.allowed_origins) - - self.blacklist = apt_pkg.config.value_list( - "Kylin-update-manager::Package-Blacklist") - self.blacklist = deleteDuplicatedElementFromList(self.blacklist) - # print("Initial blacklist: ", " ".join(self.blacklist)) - - self.whitelist = apt_pkg.config.value_list( - "Kylin-update-manager::Package-Whitelist") - self.whitelist = deleteDuplicatedElementFromList(self.whitelist) - # print("Initial whitelist: ", " ".join(self.whitelist)) - - self.strict_whitelist = apt_pkg.config.find_b( - "Kylin-update-manager::Package-Whitelist-Strict", False) - # print("Initial whitelist (%s): %s"%( - # "strict" if self.strict_whitelist else "not strict", - # " ".join(self.whitelist))) - - # update importantlist - # initUpdateImportantList() - - # 获取list - # self.initLocalPackagesList() - - #除掉不在cache中的包 - # self.checkInCache() - - def checkInCache(self): - logging.info("start Check in cache") - tmplist = [] - cache = apt.Cache() - for i in self.upgradeList: - try: - cache[i] - tmplist.append(i) - except Exception as e: - # print("not found pkg: ", str(e)) - pass - self.upgradeList = tmplist - - def initLocalPackagesList(self): - jsonfiles = [] - tmplist = [] - - # 获取importantlist 本次更新推送 - with open(ImportantListPath, 'r') as f: - text = f.read() - importantList = text.split() - logging.info("importantList: %s",importantList) - f.close() - - if not importantList: - logging.error("importantList is empty") - exit(-1) - - # 获取/usr/share/kylin-update-desktop-config/data/下所有json文件 - for root,dirs,files in os.walk(DesktopSystemPath): - pass - for i in files: - if ".json" in i: - jsonfiles.append(i.split('.')[0]) - # logging.info("all files: %s", jsonfiles) - - # 找到importantlist中对应的json文件 - for i in importantList: - if i not in jsonfiles: - # 说明这个是单独的包,不在分组中 - # 加入更新列表 - if i not in self.upgradeList: - self.upgradeList.append(i) - else: - # 在分组中 - # 获取每个对应json文件中的upgrade_list - if i in jsonfiles: - filepath = os.path.join(DesktopSystemPath, i) - filepath = filepath+".json" - with open(filepath, 'r') as f: - pkgdict = f.read() - jsonfile = json.loads(pkgdict) - tmplist = jsonfile['install_list'] - # print("\ntmplist: ", tmplist) - for j in tmplist: - if j not in self.upgradeList: - self.upgradeList.append(j) - f.close() - # logging.info("self.upgradeList: %s", self.upgradeList) - - - def check_in_allowed_origin(self, pkgs): - new_upgrade_pkgs = [] - for pkg in pkgs: - # print("checking %d pkgname: %s"%(i, pkg)) - for v in pkg.versions: - if is_in_allowed_origin(v, self.allowed_origins) and not pkg in new_upgrade_pkgs: - new_upgrade_pkgs.append(pkg) - # else: - # pkg.mark_keep() - return new_upgrade_pkgs - - def is_pkgname_in_blacklist(self, pkgs): - blacklist_filter_pkgs = [] - for pkg in pkgs: - if pkg.name in self.blacklist: - pass - # print("skipping blacklisted package %s" % pkg.name) - else : - blacklist_filter_pkgs.append(pkg) - - return blacklist_filter_pkgs - - def is_pkgname_in_whitelist(self, pkgs): - whitelist_filter_upgrade_pkgs = [] - for pkg in pkgs: - if pkg.name in self.upgradeList: - whitelist_filter_upgrade_pkgs.append(pkg) - else : - pkg.mark_keep() - pass - # print("skipping whitelist package %s" % pkg.name) - - return whitelist_filter_upgrade_pkgs - - -def get_allowed_origins(): - # type: () -> List[str] - """ return a list of allowed origins from apt.conf - - This will take substitutions (like distro_id) into account. - """ - allowed_origins = get_allowed_origins_legacy() - key = "Kylin-update-manager::Origins-Pattern" - try: - for s in apt_pkg.config.value_list(key): - allowed_origins.append(substitute(s)) - except ValueError: - print("Unable to parse %s." % key) - raise - return allowed_origins - -def get_allowed_origins_legacy(): - # type: () -> List[str] - """ legacy support for old Allowed-Origins var """ - allowed_origins = [] # type: List[str] - key = "Kylin-update-manager::Allowed-Origins" - try: - for s in apt_pkg.config.value_list(key): - # if there is a ":" use that as seperator, else use spaces - if re.findall(r'(? str - """ substitude known mappings and return a new string - - Currently supported ${distro-release} - """ - mapping = {"distro_codename": get_distro_codename(), - "distro_id": get_distro_id()} - return string.Template(line).substitute(mapping) - - -def get_distro_codename(): - # type: () -> str - return DISTRO_CODENAME - - -def get_distro_id(): - # type: () -> str - return DISTRO_ID - -def is_in_allowed_origin(ver, allowed_origins): - # type: (apt.package.Version, List[str]) -> bool - if not ver: - return False - for origin in ver.origins: - if is_allowed_origin(origin, allowed_origins): - return True - return False - -def is_allowed_origin(origin, allowed_origins): - # type: (Union[apt.package.Origin, apt_pkg.PackageFile], List[str]) -> bool - - # local origin is allowed by default - # if origin.component == 'now' and origin.archive == 'now' and \ - # not origin.label and not origin.site: - # return True - for allowed in allowed_origins: - if match_whitelist_string(allowed, origin): - return True - return False - -def match_whitelist_string(whitelist, origin): - # type: (str, Union[apt.package.Origin, apt_pkg.PackageFile]) -> bool - """ - take a whitelist string in the form "origin=Debian,label=Debian-Security" - and match against the given python-apt origin. A empty whitelist string - never matches anything. - """ - whitelist = whitelist.strip() - if whitelist == "": - logging.warning("empty match string matches nothing") - return False - res = True - # make "\," the html quote equivalent - whitelist = whitelist.replace("\\,", "%2C") - for token in whitelist.split(","): - # strip and unquote the "," back - (what, value) = [s.strip().replace("%2C", ",") - for s in token.split("=")] - # logging.debug("matching %s=%s against %s" % ( - # what, value, origin)) - # support substitution here as well - value = substitute(value) - # first char is apt-cache policy output, send is the name - # in the Release file - if what in ("o", "origin"): - match = fnmatch.fnmatch(origin.origin, value) - elif what in ("l", "label"): - match = fnmatch.fnmatch(origin.label, value) - elif what in ("a", "suite", "archive"): - match = fnmatch.fnmatch(origin.archive, value) - elif what in ("c", "component"): - match = fnmatch.fnmatch(origin.component, value) - elif what in ("site",): - match = fnmatch.fnmatch(origin.site, value) - elif what in ("n", "codename",): - match = fnmatch.fnmatch(origin.codename, value) - else: - raise UnknownMatcherError( - "Unknown whitelist entry for matcher %s (token %s)" % ( - what, token)) - # update res - res = res and match - # logging.debug("matching %s=%s against %s" % ( - # what, value, origin)) - return res - -def deleteDuplicatedElementFromList(list): - resultList = [] - for item in list: - if not item in resultList: - resultList.append(item) - return resultList - - -class UnknownMatcherError(ValueError): - pass \ No newline at end of file diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/roam.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/roam.py deleted file mode 100644 index 0714d89..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/roam.py +++ /dev/null @@ -1,212 +0,0 @@ -# utils.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2011 Canonical -# -# Author: Alex Chiang -# Michael Vogt -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - - -from __future__ import print_function - -import dbus -import sys - - -class ModemManagerHelper(object): - - # data taken from - # http://projects.gnome.org/NetworkManager/developers/mm-spec-04.html - MM_DBUS_IFACE = "org.freedesktop.ModemManager" - MM_DBUS_IFACE_MODEM = MM_DBUS_IFACE + ".Modem" - - # MM_MODEM_TYPE - MM_MODEM_TYPE_GSM = 1 - MM_MODEM_TYPE_CDMA = 2 - - # GSM - # Not registered, not searching for new operator to register. - MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE = 0 - # Registered on home network. - MM_MODEM_GSM_NETWORK_REG_STATUS_HOME = 1 - # Not registered, searching for new operator to register with. - MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING = 2 - # Registration denied. - MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED = 3 - # Unknown registration status. - MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN = 4 - # Registered on a roaming network. - MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING = 5 - - # CDMA - # Registration status is unknown or the device is not registered. - MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN = 0 - # Registered, but roaming status is unknown or cannot be provided - # by the device. The device may or may not be roaming. - MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED = 1 - # Currently registered on the home network. - MM_MODEM_CDMA_REGISTRATION_STATE_HOME = 2 - # Currently registered on a roaming network. - MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING = 3 - - def __init__(self): - self.bus = dbus.SystemBus() - self.proxy = self.bus.get_object("org.freedesktop.ModemManager", - "/org/freedesktop/ModemManager") - modem_manager = dbus.Interface(self.proxy, self.MM_DBUS_IFACE) - self.modems = modem_manager.EnumerateDevices() - - @staticmethod - def get_dbus_property(proxy, interface, property): - props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties") - property = props.Get(interface, property) - return property - - def is_gsm_roaming(self): - for m in self.modems: - dev = self.bus.get_object(self.MM_DBUS_IFACE, m) - type = self.get_dbus_property(dev, self.MM_DBUS_IFACE_MODEM, - "Type") - if type != self.MM_MODEM_TYPE_GSM: - continue - net = dbus.Interface(dev, - self.MM_DBUS_IFACE_MODEM + ".Gsm.Network") - reg = net.GetRegistrationInfo() - # Be conservative about roaming. If registration unknown, - # assume yes. - # MM_MODEM_GSM_NETWORK_REG_STATUS - if reg[0] in (self.MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN, - self.MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING): - return True - return False - - def is_cdma_roaming(self): - for m in self.modems: - dev = self.bus.get_object(self.MM_DBUS_IFACE, m) - type = self.get_dbus_property(dev, self.MM_DBUS_IFACE_MODEM, - "Type") - if type != self.MM_MODEM_TYPE_CDMA: - continue - cdma = dbus.Interface(dev, self.MM_DBUS_IFACE_MODEM + ".Cdma") - (cmda_1x, evdo) = cdma.GetRegistrationState() - # Be conservative about roaming. If registration unknown, - # assume yes. - # MM_MODEM_CDMA_REGISTRATION_STATE - roaming_states = (self.MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED, - self.MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING) - # evdo trumps cmda_1x (thanks to Mathieu Trudel-Lapierre) - if evdo in roaming_states: - return True - elif cmda_1x in roaming_states: - return True - return False - - -class NetworkManagerHelper(object): - NM_DBUS_IFACE = "org.freedesktop.NetworkManager" - - # connection states - # Old enum values are for NM 0.7 - - # The NetworkManager daemon is in an unknown state. - NM_STATE_UNKNOWN = 0 - # The NetworkManager daemon is connecting a device. - NM_STATE_CONNECTING_OLD = 2 - NM_STATE_CONNECTING = 40 - NM_STATE_CONNECTING_LIST = [NM_STATE_CONNECTING_OLD, - NM_STATE_CONNECTING] - # The NetworkManager daemon is connected. - NM_STATE_CONNECTED_OLD = 3 - NM_STATE_CONNECTED_LOCAL = 50 - NM_STATE_CONNECTED_SITE = 60 - NM_STATE_CONNECTED_GLOBAL = 70 - NM_STATE_CONNECTED_LIST = [NM_STATE_CONNECTED_OLD, - NM_STATE_CONNECTED_LOCAL, - NM_STATE_CONNECTED_SITE, - NM_STATE_CONNECTED_GLOBAL] - - # The device type is unknown. - NM_DEVICE_TYPE_UNKNOWN = 0 - # The device is wired Ethernet device. - NM_DEVICE_TYPE_ETHERNET = 1 - # The device is an 802.11 WiFi device. - NM_DEVICE_TYPE_WIFI = 2 - # The device is a GSM-based cellular WAN device. - NM_DEVICE_TYPE_GSM = 3 - # The device is a CDMA/IS-95-based cellular WAN device. - NM_DEVICE_TYPE_CDMA = 4 - - def __init__(self): - self.bus = dbus.SystemBus() - self.proxy = self.bus.get_object("org.freedesktop.NetworkManager", - "/org/freedesktop/NetworkManager") - - @staticmethod - def get_dbus_property(proxy, interface, property): - props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties") - property = props.Get(interface, property) - return property - - def is_active_connection_gsm_or_cdma(self): - res = False - actives = self.get_dbus_property( - self.proxy, self.NM_DBUS_IFACE, 'ActiveConnections') - for a in actives: - active = self.bus.get_object(self.NM_DBUS_IFACE, a) - default_route = self.get_dbus_property( - active, self.NM_DBUS_IFACE + ".Connection.Active", 'Default') - if not default_route: - continue - devs = self.get_dbus_property( - active, self.NM_DBUS_IFACE + ".Connection.Active", 'Devices') - for d in devs: - dev = self.bus.get_object(self.NM_DBUS_IFACE, d) - type = self.get_dbus_property( - dev, self.NM_DBUS_IFACE + ".Device", 'DeviceType') - if type == self.NM_DEVICE_TYPE_GSM: - return True - elif type == self.NM_DEVICE_TYPE_CDMA: - return True - else: - continue - return res - - def is_active_connection_gsm_or_cdma_roaming(self): - res = False - if self.is_active_connection_gsm_or_cdma(): - mmhelper = ModemManagerHelper() - res |= mmhelper.is_gsm_roaming() - res |= mmhelper.is_cdma_roaming() - return res - - -if __name__ == "__main__": - - # test code - if sys.argv[1:] and sys.argv[1] == "--test": - mmhelper = ModemManagerHelper() - print("is_gsm_roaming", mmhelper.is_gsm_roaming()) - print("is_cdma_romaing", mmhelper.is_cdma_roaming()) - - # roaming? - nmhelper = NetworkManagerHelper() - is_roaming = nmhelper.is_active_connection_gsm_or_cdma_roaming() - print("roam: ", is_roaming) - if is_roaming: - sys.exit(1) - sys.exit(0) diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/utils.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/utils.py deleted file mode 100644 index 103f8bf..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/Core/utils.py +++ /dev/null @@ -1,557 +0,0 @@ -# utils.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2004-2013 Canonical -# -# Authors: Michael Vogt -# Michael Terry -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import print_function - -from gettext import gettext as _ -from gettext import ngettext -from stat import (S_IMODE, ST_MODE, S_IXUSR) -from math import ceil - -import apt -import apt_pkg -apt_pkg.init_config() - -import locale -import logging -import re -import os -import subprocess -import sys -import time -from urllib.request import ( - ProxyHandler, - Request, - build_opener, - install_opener, - urlopen, -) -from urllib.parse import urlsplit - -from copy import copy - - -class ExecutionTime(object): - """ - Helper that can be used in with statements to have a simple - measure of the timing of a particular block of code, e.g. - with ExecutionTime("db flush"): - db.flush() - """ - def __init__(self, info=""): - self.info = info - - def __enter__(self): - self.now = time.time() - - def __exit__(self, type, value, stack): - print("%s: %s" % (self.info, time.time() - self.now)) - - -def get_string_with_no_auth_from_source_entry(entry): - tmp = copy(entry) - url_parts = urlsplit(tmp.uri) - if url_parts.username: - tmp.uri = tmp.uri.replace(url_parts.username, "hidden-u") - if url_parts.password: - tmp.uri = tmp.uri.replace(url_parts.password, "hidden-p") - return str(tmp) - - -def is_unity_running(): - """ return True if Unity is currently running """ - unity_running = False - try: - import dbus - bus = dbus.SessionBus() - unity_running = bus.name_has_owner("com.canonical.Unity") - except Exception: - logging.exception("could not check for Unity dbus service") - return unity_running - - -def is_child_of_process_name(processname, pid=None): - if not pid: - pid = os.getpid() - while pid > 0: - stat_file = "/proc/%s/stat" % pid - with open(stat_file) as stat_f: - stat = stat_f.read() - # extract command (inside ()) - command = stat.partition("(")[2].rpartition(")")[0] - if command == processname: - return True - # get parent (second to the right of command) and check that next - pid = int(stat.rpartition(")")[2].split()[1]) - return False - - -def inside_chroot(): - """ returns True if we are inside a chroot - """ - # if there is no proc or no pid 1 we are very likely inside a chroot - if not os.path.exists("/proc") or not os.path.exists("/proc/1"): - return True - # if the inode is differnt for pid 1 "/" and our "/" - return os.stat("/") != os.stat("/proc/1/root") - - -def wrap(t, width=70, subsequent_indent=""): - """ helpers inspired after textwrap - unfortunately - we can not use textwrap directly because it break - packagenames with "-" in them into new lines - """ - out = "" - for s in t.split(): - if (len(out) - out.rfind("\n")) + len(s) > width: - out += "\n" + subsequent_indent - out += s + " " - return out - - -def twrap(s, **kwargs): - msg = "" - paras = s.split("\n") - for par in paras: - s = wrap(par, **kwargs) - msg += s + "\n" - return msg - - -def lsmod(): - " return list of loaded modules (or [] if lsmod is not found) " - modules = [] - # FIXME raise? - if not os.path.exists("/sbin/lsmod"): - return [] - p = subprocess.Popen(["/sbin/lsmod"], stdout=subprocess.PIPE, - universal_newlines=True) - lines = p.communicate()[0].split("\n") - # remove heading line: "Modules Size Used by" - del lines[0] - # add lines to list, skip empty lines - for line in lines: - if line: - modules.append(line.split()[0]) - return modules - - -def check_and_fix_xbit(path): - " check if a given binary has the executable bit and if not, add it" - if not os.path.exists(path): - return - mode = S_IMODE(os.stat(path)[ST_MODE]) - if not ((mode & S_IXUSR) == S_IXUSR): - os.chmod(path, mode | S_IXUSR) - - -def country_mirror(): - " helper to get the country mirror from the current locale " - # special cases go here - lang_mirror = {'c': ''} - # no lang, no mirror - if 'LANG' not in os.environ: - return '' - lang = os.environ['LANG'].lower() - # check if it is a special case - if lang[:5] in lang_mirror: - return lang_mirror[lang[:5]] - # now check for the most comon form (en_US.UTF-8) - if "_" in lang: - country = lang.split(".")[0].split("_")[1] - if "@" in country: - country = country.split("@")[0] - return country + "." - else: - return lang[:2] + "." - return '' - - -def get_dist(): - " return the codename of the current runing distro " - # support debug overwrite - dist = os.environ.get("META_RELEASE_FAKE_CODENAME") - if dist: - logging.warning("using fake release name '%s' (because of " - "META_RELEASE_FAKE_CODENAME environment) " % dist) - return dist - # then check the real one - from subprocess import Popen, PIPE - p = Popen(["lsb_release", "-c", "-s"], stdout=PIPE, - universal_newlines=True) - res = p.wait() - if res != 0: - sys.stderr.write("lsb_release returned exitcode: %i\n" % res) - return "unknown distribution" - dist = p.stdout.readline().strip() - p.stdout.close() - return dist - - -def get_dist_version(): - " return the version of the current running distro " - # support debug overwrite - desc = os.environ.get("META_RELEASE_FAKE_VERSION") - if desc: - logging.warning("using fake release version '%s' (because of " - "META_RELEASE_FAKE_VERSION environment) " % desc) - return desc - # then check the real one - from subprocess import Popen, PIPE - p = Popen(["lsb_release", "-r", "-s"], stdout=PIPE, - universal_newlines=True) - res = p.wait() - if res != 0: - sys.stderr.write("lsb_release returned exitcode: %i\n" % res) - return "unknown distribution" - desc = p.stdout.readline().strip() - p.stdout.close() - return desc - - -class HeadRequest(Request): - def get_method(self): - return "HEAD" - - -def url_downloadable(uri, debug_func=None): - """ - helper that checks if the given uri exists and is downloadable - (supports optional debug_func function handler to support - e.g. logging) - - Supports http (via HEAD) and ftp (via size request) - """ - if not debug_func: - lambda x: True - debug_func("url_downloadable: %s" % uri) - (scheme, netloc, path, querry, fragment) = urlsplit(uri) - debug_func("s='%s' n='%s' p='%s' q='%s' f='%s'" % (scheme, netloc, path, - querry, fragment)) - if scheme in ("http", "https"): - try: - http_file = urlopen(HeadRequest(uri)) - http_file.close() - if http_file.code == 200: - return True - return False - except Exception as e: - debug_func("error from httplib: '%s'" % e) - return False - elif scheme == "ftp": - import ftplib - try: - f = ftplib.FTP(netloc) - f.login() - f.cwd(os.path.dirname(path)) - size = f.size(os.path.basename(path)) - f.quit() - if debug_func: - debug_func("ftplib.size() returned: %s" % size) - if size != 0: - return True - except Exception as e: - if debug_func: - debug_func("error from ftplib: '%s'" % e) - return False - return False - - -def init_proxy(gsettings=None): - """ init proxy settings - - * use apt.conf http proxy if present, - * otherwise look into synaptics config file, - * otherwise the default behavior will use http_proxy environment - if present - """ - SYNAPTIC_CONF_FILE = "/root/.synaptic/synaptic.conf" - proxies = {} - # generic apt config wins - if apt_pkg.config.find("Acquire::http::Proxy") != '': - proxies["http"] = apt_pkg.config.find("Acquire::http::Proxy") - # then synaptic - elif os.path.exists(SYNAPTIC_CONF_FILE): - cnf = apt_pkg.Configuration() - apt_pkg.read_config_file(cnf, SYNAPTIC_CONF_FILE) - use_proxy = cnf.find_b("Synaptic::useProxy", False) - if use_proxy: - proxy_host = cnf.find("Synaptic::httpProxy") - proxy_port = str(cnf.find_i("Synaptic::httpProxyPort")) - if proxy_host and proxy_port: - proxies["http"] = "http://%s:%s/" % (proxy_host, proxy_port) - if apt_pkg.config.find("Acquire::https::Proxy") != '': - proxies["https"] = apt_pkg.config.find("Acquire::https::Proxy") - elif "http" in proxies: - proxies["https"] = proxies["http"] - # if we have a proxy, set it - if proxies: - # basic verification - for proxy in proxies.values(): - if not re.match("https?://\\w+", proxy): - print("proxy '%s' looks invalid" % proxy, file=sys.stderr) - return - proxy_support = ProxyHandler(proxies) - opener = build_opener(proxy_support) - install_opener(opener) - if "http" in proxies: - os.putenv("http_proxy", proxies["http"]) - if "https" in proxies: - os.putenv("https_proxy", proxies["https"]) - return proxies - - -def on_battery(): - """ - Check via dbus if the system is running on battery. - This function is using UPower per default, if UPower is not - available it falls-back to DeviceKit.Power. - """ - try: - import dbus - bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - try: - devobj = bus.get_object('org.freedesktop.UPower', - '/org/freedesktop/UPower') - dev = dbus.Interface(devobj, 'org.freedesktop.DBus.Properties') - return dev.Get('org.freedesktop.UPower', 'OnBattery') - except dbus.exceptions.DBusException as e: - error_unknown = 'org.freedesktop.DBus.Error.ServiceUnknown' - if e._dbus_error_name != error_unknown: - raise - devobj = bus.get_object('org.freedesktop.DeviceKit.Power', - '/org/freedesktop/DeviceKit/Power') - dev = dbus.Interface(devobj, "org.freedesktop.DBus.Properties") - return dev.Get("org.freedesktop.DeviceKit.Power", "on_battery") - except Exception: - #import sys - #print("on_battery returned error: ", e, file=sys.stderr) - return False - - -def inhibit_sleep(): - """ - Send a dbus signal to logind to not suspend the system, it will be - released when the return value drops out of scope - """ - try: - from gi.repository import Gio, GLib - connection = Gio.bus_get_sync(Gio.BusType.SYSTEM) - - var, fdlist = connection.call_with_unix_fd_list_sync( - 'org.freedesktop.login1', '/org/freedesktop/login1', - 'org.freedesktop.login1.Manager', 'Inhibit', - GLib.Variant('(ssss)', - ('shutdown:sleep', - 'UpdateManager', 'Updating System', - 'block')), - None, 0, -1, None, None) - inhibitor = Gio.UnixInputStream(fd=fdlist.steal_fds()[var[0]]) - - return inhibitor - except Exception: - #print("could not send the dbus Inhibit signal: %s" % e) - return False - - -def str_to_bool(str): - if str == "0" or str.upper() == "FALSE": - return False - return True - - -def get_lang(): - import logging - try: - (locale_s, encoding) = locale.getdefaultlocale() - return locale_s - except Exception: - logging.exception("gedefaultlocale() failed") - return None - - -def get_ubuntu_flavor(cache=None): - """ try to guess the flavor based on the running desktop """ - # this will (of course) not work in a server environment, - # but the main use case for this is to show the right - # release notes. - pkg = get_ubuntu_flavor_package(cache=cache) - return pkg.split('-', 1)[0] - - -def _load_meta_pkg_list(): - # This could potentially introduce a circular dependency, but the config - # parser logic is simple, and doesn't rely on any UpdateManager code. - from DistUpgrade.DistUpgradeConfigParser import DistUpgradeConfig - parser = DistUpgradeConfig('/usr/share/ubuntu-release-upgrader') - return parser.getlist('Distro', 'MetaPkgs') - - -def get_ubuntu_flavor_package(cache=None): - """ try to guess the flavor metapackage based on the running desktop """ - # From spec, first if ubuntu-desktop is installed, use that. - # Second, grab first installed one from DistUpgrade.cfg. - # Lastly, fallback to ubuntu-desktop again. - meta_pkgs = ['ubuntu-desktop'] - - try: - meta_pkgs.extend(sorted(_load_meta_pkg_list())) - except Exception as e: - print('Could not load list of meta packages:', e) - - if cache is None: - cache = apt.Cache() - for meta_pkg in meta_pkgs: - cache_pkg = cache[meta_pkg] if meta_pkg in cache else None - if cache_pkg and cache_pkg.is_installed: - return meta_pkg - return 'ubuntu-desktop' - - -def get_ubuntu_flavor_name(cache=None): - """ try to guess the flavor name based on the running desktop """ - pkg = get_ubuntu_flavor_package(cache=cache) - lookup = {'ubuntustudio-desktop': 'Ubuntu Studio'} - if pkg in lookup: - return lookup[pkg] - elif pkg.endswith('-desktop'): - return capitalize_first_word(pkg.rsplit('-desktop', 1)[0]) - elif pkg.endswith('-netbook'): - return capitalize_first_word(pkg.rsplit('-netbook', 1)[0]) - else: - return 'Ubuntu' - - -# Unused by update-manager, but still used by ubuntu-release-upgrader -def error(parent, summary, message): - import gi - gi.require_version("Gtk", "3.0") - from gi.repository import Gtk, Gdk - d = Gtk.MessageDialog(parent=parent, - flags=Gtk.DialogFlags.MODAL, - type=Gtk.MessageType.ERROR, - buttons=Gtk.ButtonsType.CLOSE) - d.set_markup("%s\n\n%s" % (summary, message)) - d.realize() - d.get_window().set_functions(Gdk.WMFunction.MOVE) - d.set_title("") - d.run() - d.destroy() - return False - - -def humanize_size(bytes): - """ - Convert a given size in bytes to a nicer better readable unit - """ - - if bytes < 1000 * 1000: - # to have 0 for 0 bytes, 1 for 0-1000 bytes and for 1 and above - # round up - size_in_kb = int(ceil(bytes / float(1000))) - # TRANSLATORS: download size of small updates, e.g. "250 kB" - return ngettext("%(size).0f kB", "%(size).0f kB", size_in_kb) % { - "size": size_in_kb} - else: - # TRANSLATORS: download size of updates, e.g. "2.3 MB" - return locale.format_string(_("%.1f MB"), bytes / 1000.0 / 1000.0) - - -def get_arch(): - return apt_pkg.config.find("APT::Architecture") - - -def is_port_already_listening(port): - """ check if the current system is listening on the given tcp port """ - # index in the line - INDEX_LOCAL_ADDR = 1 - #INDEX_REMOTE_ADDR = 2 - INDEX_STATE = 3 - # state (st) that we care about - STATE_LISTENING = '0A' - # read the data - with open("/proc/net/tcp") as net_tcp: - for line in net_tcp.readlines(): - line = line.strip() - if not line: - continue - # split, values are: - # sl local_address rem_address st tx_queue rx_queue tr - # tm->when retrnsmt uid timeout inode - values = line.split() - state = values[INDEX_STATE] - if state != STATE_LISTENING: - continue - local_port_str = values[INDEX_LOCAL_ADDR].split(":")[1] - local_port = int(local_port_str, 16) - if local_port == port: - return True - return False - - -def iptables_active(): - """ Return True if iptables is active """ - # FIXME: is there a better way? - iptables_empty = """Chain INPUT (policy ACCEPT) -target prot opt source destination - -Chain FORWARD (policy ACCEPT) -target prot opt source destination - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination -""" - if os.getuid() != 0: - raise OSError("Need root to check the iptables state") - if not os.path.exists("/sbin/iptables"): - return False - out = subprocess.Popen(["iptables", "-nL"], - stdout=subprocess.PIPE, - universal_newlines=True).communicate()[0] - if out == iptables_empty: - return False - return True - - -def capitalize_first_word(string): - """ this uppercases the first word's first letter - """ - if len(string) > 1 and string[0].isalpha() and not string[0].isupper(): - return string[0].capitalize() + string[1:] - return string - - -def get_package_label(pkg): - """ this takes a package synopsis and uppercases the first word's - first letter - """ - name = getattr(pkg.candidate, "summary", "") - return capitalize_first_word(name) - - -if __name__ == "__main__": - #print(mirror_from_sources_list()) - #print(on_battery()) - #print(inside_chroot()) - #print(iptables_active()) - error(None, "bar", "baz") diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManager.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManager.py deleted file mode 100644 index 3fc695b..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManager.py +++ /dev/null @@ -1,286 +0,0 @@ -# UpdateManager.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- - -from __future__ import absolute_import, print_function - -import os -import sys -import dbus -import shutil -import apt_pkg -import logging -import datetime -import warnings -import dbus.service -from dbus.mainloop.glib import DBusGMainLoop -DBusGMainLoop(set_as_default=True) - -from .Core.DistUpgradeCache import NotEnoughFreeSpaceError -from .Core.MyCache import MyCache -from .UpdateManagerDbus import UpdateManagerDbusController -from .Core.UpdateList import UpdateList -from .backend import (InstallBackend, - get_backend) -from .Core.Database import Sqlite3Server - - -from gettext import gettext as _ -warnings.filterwarnings("ignore", "Accessed deprecated property", - DeprecationWarning) - -#安装完成之后是否有请求需要重启 -REBOOT_REQUIRED_FILE = "/var/run/reboot-required" - -INSTALL_ALONE_PROGRESS = "alone" - -class UpdateManager(): - - def __init__(self,options): - self.options = options - self.cache = None - self.update_list = None - - #表示是否处于更新和安装的状态 - self.is_updating = False - self.is_upgrading = False - - #建立dbus - self.dbusController = self._setup_dbus() - - #连接数据库 - time = datetime.datetime.now() - timestr = datetime.datetime.strftime(time, "%Y-%m-%d %H:%M:%S") - self.sqlite3_server = Sqlite3Server() - - - # # FIXME: 目前此功能没有进行测试不知道是否可以进行检查 安装的时进行检查磁盘空间 - def check_free_space(self,cache): - err_sum = _("Not enough free disk space") - err_msg = _("The upgrade needs a total of %s free space on " - "disk '%s'. " - "Please free at least an additional %s of disk " - "space on '%s'. %s") - # specific ways to resolve lack of free space - remedy_archivedir = _("Remove temporary packages of former " - "installations using 'sudo apt clean'.") - remedy_boot = _("You can remove old kernels using " - "'sudo apt autoremove', and you could also " - "set COMPRESS=xz in " - "/etc/initramfs-tools/initramfs.conf to " - "reduce the size of your initramfs.") - remedy_root = _("Empty your trash and remove temporary " - "packages of former installations using " - "'sudo apt clean'.") - remedy_tmp = _("Reboot to clean up files in /tmp.") - remedy_usr = _("") - # check free space and error if its not enough - try: - cache.checkFreeSpace() - except NotEnoughFreeSpaceError as e: - # CheckFreeSpace examines where packages are cached - archivedir = apt_pkg.config.find_dir("Dir::Cache::archives") - err_long = "" - for req in e.free_space_required_list: - if err_long != "": - err_long += " " - if req.dir == archivedir: - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_archivedir) - elif req.dir == "/boot": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_boot) - elif req.dir == "/": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_root) - elif req.dir == "/tmp": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_tmp) - elif req.dir == "/usr": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_usr) - #在此抛出异常 - # self.window_main.start_error(False, err_sum, err_long) - return False - except SystemError: - logging.exception("free space check failed") - - return True - - #进行更新的操作 - def start_update(self): - try: - self.is_updating = True - update_backend = get_backend(self, InstallBackend.ACTION_UPDATE) - update_backend.start() - except Exception as e: - logging.error(e) - - #进行升级的操作 - def start_install(self,partial_upgrade_list = []): - #检查磁盘的状态 - if self.check_free_space(self.cache) == False: - return - logging.info("Disk Check finished...") - try: - self.is_upgrading = True - install_backend = get_backend(self, InstallBackend.ACTION_INSTALL) - install_backend.start(partial_upgrade_list=partial_upgrade_list) - except Exception as e: - logging.error(e) - - #进行升级的操作-传入包列表 - def start_install_alone(self,pkgs_install = [], pkgs_upgrade = [], pkgs_remove = [],pkgs_purge = []): - #检查磁盘的状态 - if self.check_free_space(self.cache) == False: - return - logging.info("Disk Check finished...") - self.is_upgrading = True - install_backend = get_backend(self, InstallBackend.ACTION_INSTALL) - install_backend.start_alone(pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_purge) - - #更新结束之后会调到此获取要升级的列表 and 更新cache 生成升级组列表JSON - def start_available(self, cancelled_update=False): - _success,header,desc = self.refresh_cache() - - #特殊情况的处理 单独安装包需要直接退出 安装or卸载执行完毕后 还会调到start_available - if _success == True and header == INSTALL_ALONE_PROGRESS: - return - else: - #发送更新升级列表完成的标志 - self.dbusController.UpdateDetectFinished(_success,self.update_list.local_upgrade_list.get('upgrade_groups_list',[]),header,desc) - - #检查安装完成之后需要重启吗 - if os.path.exists(REBOOT_REQUIRED_FILE): - logging.error("REBOOT_REQUIRED_FILE") - - def refresh_cache(self): - _success = True - header = None - desc = None - try: - #第一次进入 之后update不进入 - if self.cache is None: - self.cache = MyCache(None) - else: - self.cache.open(None) - self.cache._initDepCache() - except AssertionError: - header = _("Software index is broken") - desc = _("It is impossible to install or remove any software. " - "Please use the package manager \"Synaptic\" or run " - "\"sudo apt-get install -f\" in a terminal to fix " - "this issue at first.") - _success = False - return _success,header,desc - - except SystemError as e: - header = _("Could not initialize the package information") - desc = _("An unresolvable problem occurred while " - "initializing the package information.\n\n" - "Please report this bug against the 'update-manager' " - "package and include the following error " - "message:\n") + str(e) - _success = False - return _success,header,desc - - self.update_list = UpdateList(self) - - '''1、 - dist-upgrade 标记在此处进行 - 来判断将要删除的包 如果存在要删除的break的包的话 会从dist-upgrade切换到upgrade 目前此功能不使用 默认使用dist-upgrade - ''' - self.distUpgradeWouldDelete = self.cache.saveDistUpgrade() - - #2、 安装JSON分组配置文件包 安装完毕会重新调start_available --> here 安装失败就直接退出不会进行下面的操作 - try: - pkg_json = self.cache[self.update_list.GROUPS_JSON_PKG] - #是否安装 - if pkg_json.is_installed: - #是否可升级 - if pkg_json.is_upgradable: - logging.info("groups JSON ConfigPkgs(%s) start upgrading...",self.GROUPS_JSON_PKG) - self.start_install_alone(pkgs_upgrade = [self.update_list.GROUPS_JSON_PKG]) - #直接退出 - _success = True - header = INSTALL_ALONE_PROGRESS - return _success,header,desc - else: - logging.info("ConfigPkgs(%s) No need to upgrade...",self.update_list.GROUPS_JSON_PKG) - else: - logging.info("groups JSON ConfigPkgs(%s) start new installing...",self.update_list.GROUPS_JSON_PKG) - self.start_install_alone(pkgs_install = [self.update_list.GROUPS_JSON_PKG]) - #直接退出 - _success = True - header = INSTALL_ALONE_PROGRESS - return _success,header,desc - - #FIXME: 错误处理未做 报告到控制面板 - except Exception as e: - logging.warning("groups JSON ConfigPkgs(%s) install failed...",self.update_list.GROUPS_JSON_PKG) - logging.error(e) - _success = False - - #3、 判断目录是JSON配置文件夹是否缺失 缺失后进行修复 卸载重新安装步骤 - if not os.path.exists(self.update_list.INPUT_CONFIG_PATH): - logging.info("groups JSON Config Path(%s) Missing and Trying to fix...",self.update_list.INPUT_CONFIG_PATH) - #将软件包卸载 之后进行重新安装here --> purge --> start_available 进行判断是否安装未安装重新安装 - self.start_install_alone(pkgs_purge = [self.update_list.GROUPS_JSON_PKG]) - #直接退出 - _success = True - header = INSTALL_ALONE_PROGRESS - return _success,header,desc - - #4、 清空上次输出的分组JSON文件 - try: - if not os.path.exists(self.update_list.OUTPUT_CONFIG_PATH): - os.makedirs(self.update_list.OUTPUT_CONFIG_PATH) - logging.info('making the configuration file is complete...') - else: - shutil.rmtree(self.update_list.OUTPUT_CONFIG_PATH) - os.makedirs(self.update_list.OUTPUT_CONFIG_PATH) - logging.info('Emptying the configuration file is complete...') - except Exception as e: - logging.warning(e) - - #FIXME: 5、 待开发功能 根据监测存在配置文件 不存在进行重新安装包 再检测还是未存在的话 就判断此次没有可升级的 - - #FIXME: 6、 出错后未进行处理 更新important.list 文件错误的话 - self.dbusController._on_update_important_list() - - try: - _success,header,desc = self.update_list.update(self.cache) - except SystemError as e: - header = _("Could not calculate the upgrade") - desc = _("An unresolvable problem occurred while " - "calculating the upgrade.\n\n" - "Please report this bug against the 'update-manager' " - "package and include the following error " - "message:\n") + str(e) - _success = False - - return _success,header,desc - - def _setup_dbus(self): - # check if there is another g-a-i already and if not setup one - # listening on dbus - try: - bus = dbus.SystemBus() - except Exception: - logging.error("warning: could not initiate dbus") - return - try: - proxy_obj = bus.get_object('com.kylin.systemupgrade', - '/com/kylin/systemupgrade') - - logging.warning("kylin-update-manager have started...") - sys.exit(0) - except dbus.DBusException: - bus_name = dbus.service.BusName('com.kylin.systemupgrade', - bus) - logging.info('initiate dbus success ...') - return UpdateManagerDbusController(self, bus_name) \ No newline at end of file diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerDbus.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerDbus.py deleted file mode 100644 index 53c8124..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerDbus.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/python3 -import dbus -import dbus.service -import logging -import threading - -from .Core.AlertWatcher import AlertWatcher -from .Core.roam import NetworkManagerHelper - -#dbus 建立 -class UpdateManagerDbusController(dbus.service.Object): - """ this is a helper to provide the UpdateManagerIFace """ - - INTERFACE = 'com.kylin.systemupgrade.interface' - - def __init__(self, parent, bus_name, - object_path='/com/kylin/systemupgrade'): - dbus.service.Object.__init__(self, bus_name, object_path) - self.parent = parent - - #网络检测 电池检测等等的启动检查 - self.alert_watcher = AlertWatcher() - self.alert_watcher.check_alert_state() - self.alert_watcher.connect("network-alert", self._on_network_alert) - self.connected = False - self.transaction = None - - #更新important.list的本次升级的列表 - def _on_update_important_list(self): - lock = threading.Lock() - bus = dbus.SystemBus() - try: - obj = bus.get_object('com.kylin.software.properties', '/com/kylin/software/properties') - interface = dbus.Interface(obj, dbus_interface='com.kylin.software.properties.interface') - lock.acquire() - retval = interface.updateSourceTemplate() - lock.release() - except Exception as e: - logging.error("update sourceTemplate Failed and Error mes:%s"%str(e)) - return False - - if retval == False: - logging.warning("update SourceTemplate failed") - return False - else: - logging.info("update sourceTemplate successed...") - return True - - #检测网络的状态 - def _on_network_alert(self, watcher, state): - if state in NetworkManagerHelper.NM_STATE_CONNECTED_LIST: - self.connected = True - logging.info('Network Connected ...') - else: - self.connected = False - logging.info('Network Disconnected ...') - - #更新的dbus - @dbus.service.method(INTERFACE,out_signature='b') - def UpdateDetect(self): - try: - #处于更新和升级中的话 不进行更新 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - self.parent.start_update() - logging.info('method dbus updating ...') - return True - except Exception: - return False - - #全部升级 - @dbus.service.method(INTERFACE,out_signature='bs') - def DistUpgradeSystem(self): - try: - if not self.parent.update_list: - logging.info('Perform \"UpdateDetect\" first') - return False,'Perform \"UpdateDetect\" first' - #处于更新和升级中的话 不进行升级 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - upgrade_groups_list = self.parent.update_list.local_upgrade_list.get('upgrade_groups_list',[]) - if upgrade_groups_list: - logging.info('method dbus upgrading ...') - self.parent.start_install() - return True,'success' - else: - return False,'False' - except Exception as e: - return False,str(e) - - #部分升级 - @dbus.service.method(INTERFACE,in_signature='as',out_signature='bs') - def DistUpgradePartial(self,_partial_upgrade_list): - try: - if not self.parent.update_list: - logging.info('Perform \"UpdateDetect\" first') - return False,'Perform \"UpdateDetect\" first' - #处于更新和升级中的话 不进行升级 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - partial_upgrade_list = [str(i) for i in _partial_upgrade_list] - #本地维护的可升级的组 - upgrade_groups_list = self.parent.update_list.local_upgrade_list.get('upgrade_groups_list',[]) - upgrade_list = list(set(partial_upgrade_list) & set(upgrade_groups_list)) - - if upgrade_list: - logging.info('dbus partial_upgrade(%s)',upgrade_list) - self.parent.start_install(upgrade_list) - return True,'dbus upgrading' - else: - logging.info('input upgrade list(%s) not in local upgrade_list(%s)',partial_upgrade_list,upgrade_groups_list) - return False,'upgrade_list is empty' - except Exception as e: - return False,e - - # 取消transaction - @dbus.service.method(INTERFACE, out_signature='bs') - def CancelDownload(self): - status = False - message = "" - try: - if self.transaction.cancellable == True: - self.transaction.cancel() - status = True - message = "Success" - logging.info("dbus-mothod cancel task Success") - elif self.transaction == None or self.transaction.cancellable == False: - message = "Can not Cancel" - except Exception as e: - return (status,str(e)) - return (status, message) - - # 依赖错误时调用的接口 - @dbus.service.method(INTERFACE, in_signature='b', out_signature='bs') - def Here_is_a_handsome_pot(self, repair): - pkgs_install = [] - pkgs_upgrade = [] - pkgs_remove = [] - try: - #处于更新和升级中的话 不进行升级 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - if repair: - #查找所有可升级的包 - for pkg in self.parent.cache: - try: - if pkg.marked_install: - pkgs_install.append(pkg.name) - elif pkg.marked_upgrade: - pkgs_upgrade.append(pkg.name) - elif pkg.marked_delete: - pkgs_remove.append(pkg.name) - except Exception as e: - logging.error(e) - if pkgs_install or pkgs_upgrade or pkgs_remove: - logging.info('total: install pkgs num(%d) | upgrade pkgs num(%d) | remove pkgs num(%d) |', \ - len(pkgs_install), \ - len(pkgs_upgrade), \ - len(pkgs_remove)) - #开始安装 - self.parent.start_install_alone( \ - pkgs_install = pkgs_install, \ - pkgs_upgrade = pkgs_upgrade, \ - pkgs_remove = pkgs_remove) - return True,'dbus upgrading' - else: - logging.info('pkgs list is empty.') - return False,'upgrade_list is empty' - - else: - logging.info('Cancel repair') - return False,'Cancel repair' - except Exception as e: - return (False, str(e)) - - #更新进度信息 0~100 进度信息 101为非预期的信号 - @dbus.service.signal(INTERFACE,signature='is') - def UpdateDetectStatusChanged(self,progress,status): - logging.info("emit progress = %d , status = %s",progress,status) - - #更新完成的信号 - @dbus.service.signal(INTERFACE,signature='basss') - def UpdateDetectFinished(self, success, upgrade_group,error_string='',error_desc='',): - logging.info("emit update success = %r , upgrade_group = %a, error_string = %s , error_desc = %s ",\ - success,upgrade_group, error_string,error_desc) - - #升级的进度信息 0~100 进度信息 101为非预期的信号 - @dbus.service.signal(INTERFACE,signature='asis') - def UpdateDloadAndInstStaChanged(self,groups_list,progress,status): - logging.info("emit upgrade groups_list = %s progress = %d , status = %s",groups_list,progress,status) - - #升级完成的信号 - @dbus.service.signal(INTERFACE,signature='basss') - def UpdateDownloadFinished(self, success, upgrade_group,error_string='',error_desc='',): - logging.info("emit success = %r , upgrade_group = %a, error_string = %s , error_desc = %s ",\ - success,upgrade_group, error_string,error_desc) - - #发送下载包信息 - @dbus.service.signal(INTERFACE, signature='iiiii') - def UpdateDownloadInfo(self, current_items, total_items, currenty_bytes, total_bytes, current_cps): - logging.info("emit current_items = %d, total_items = %d, currenty_bytes = %d, total_bytes = %d, current_cps = %d .",\ - current_items, total_items, \ - currenty_bytes, total_bytes,\ - current_cps) - - # 信号是否可取消 - @dbus.service.signal(INTERFACE, signature='b') - def Cancelable(self, Cancelable): - logging.info("emit Cancelable: %r",\ - Cancelable) diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerVersion.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerVersion.py deleted file mode 100644 index 4224770..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/UpdateManagerVersion.py +++ /dev/null @@ -1 +0,0 @@ -VERSION = '1.0.4kord' diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/__init__.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py deleted file mode 100644 index e135fba..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python - -from __future__ import print_function - -from apt.debfile import DebPackage -from aptdaemon import client, errors -from defer import inline_callbacks -from aptdaemon.enums import (EXIT_SUCCESS, - EXIT_FAILED, - EXIT_CANCELLED, - get_error_description_from_enum, - get_error_string_from_enum, - get_status_string_from_enum - ) - -from SystemUpdater.backend import InstallBackend -import logging -from gettext import gettext as _ -import dbus - -class InstallBackendAptdaemon(InstallBackend): - """Makes use of aptdaemon to refresh the cache and to install updates.""" - - def __init__(self, window_main, action): - InstallBackend.__init__(self, window_main, action) - self.window_main = window_main - #客户端连接aptdeamon的dbus接口 - self.client = client.AptClient() - self.trans_failed_msg = None - - self.trans_progress = 0 - self.trans_status = '' - - @inline_callbacks - def update(self): - """刷新包cache""" - try: - trans = yield self.client.update_cache(defer=True) - self.window_main.dbusController.transaction = trans - #注册回调函数 接收更新的状态 - yield self._show_transaction(trans, self.ACTION_UPDATE, - _("Checking for updates…"), False) - except errors.NotAuthorizedError: - self._action_done(self.ACTION_UPDATE, - authorized=False, success=False, - error_string=None, error_desc=None) - except Exception: - self._action_done(self.ACTION_UPDATE, - authorized=True, success=False, - error_string=None, error_desc=None) - raise - - @inline_callbacks - def commit(self, pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge): - """Commit a list of package adds and removes""" - try: - reinstall = downgrade = [] - trans = yield self.client.commit_packages( - pkgs_install, reinstall, pkgs_remove, purge = pkgs_purge, upgrade = pkgs_upgrade, - downgrade = downgrade, defer=True) - self.window_main.dbusController.transaction = trans - - yield self._show_transaction(trans, self.ACTION_INSTALL, - _("Installing updates…"), True) - except errors.NotAuthorizedError: - self._action_done(self.ACTION_INSTALL, - authorized=False, success=False, - error_string=None, error_desc=None) - except errors.TransactionFailed as e: - # if e.code == 'error-dep-resolution-failed': - # logging.error("依赖错误: %s", str(e)) - self.errors = e - self.trans_failed_msg = str(e) - except dbus.DBusException as e: - if e.get_dbus_name() != "org.freedesktop.DBus.Error.NoReply": - raise - self._action_done(self.ACTION_INSTALL, - authorized=False, success=False, - error_string=None, error_desc=None) - except Exception: - self._action_done(self.ACTION_INSTALL, - authorized=True, success=False, - error_string=None, error_desc=None) - raise - - #进度回调 - def _on_progress_changed(self, trans,progress,action): - self.trans_progress = progress - if action == self.ACTION_UPDATE: - self.window_main.dbusController.UpdateDetectStatusChanged(self.trans_progress,self.trans_status) - else: - self.window_main.dbusController.UpdateDloadAndInstStaChanged(self.upgrade_groups_list,self.trans_progress,self.trans_status) - - #同步状态回调 - def _on_status_changed(self, trans, status,action): - #转化词条 - self.trans_status = get_status_string_from_enum(status) - - if action == self.ACTION_UPDATE: - self.window_main.dbusController.UpdateDetectStatusChanged(self.trans_progress,self.trans_status) - else: - #升级的时候发送状态信号时需要上传更新组信息self.upgrade_groups_list - self.window_main.dbusController.UpdateDloadAndInstStaChanged(self.upgrade_groups_list,self.trans_progress,self.trans_status) - - def _on_details_changed(self, trans, details): - logging.info(details) - - def _on_download_changed(self, trans, details): - logging.info(details) - - # eta 下载速度不正确,取消掉 - def _on_progress_download_changed(self,trans,current_items, total_items, currenty_bytes, total_bytes, current_cps, eta): - if self.action == self.ACTION_INSTALL: - self.window_main.dbusController.UpdateDownloadInfo(\ - current_items, total_items, \ - currenty_bytes, total_bytes, \ - current_cps) - - def _on_cancellable_changed(self, trans, Cancelable): - self.window_main.dbusController.Cancelable(Cancelable) - - @inline_callbacks - def _show_transaction(self, trans, action, header, show_details): - - #更新和升级最后完成和失败都会走此在此进行完成之后的处理 - trans.connect("finished", self._on_finished, action) - - #升级和更新的状态信息和进度 - trans.connect("status-changed", self._on_status_changed,action) - trans.connect("progress-changed", self._on_progress_changed,action) - - #取消升级 - trans.connect("cancellable-changed", self._on_cancellable_changed) - - #下载的进度信息 - trans.connect("progress-details-changed", self._on_progress_download_changed) - - # trans.connect("medium-required", self._on_medium_required) - # trans.connect("status-details-changed", self._on_details_changed) - #状态改变的时候的回调函数 - # trans.connect("download-changed", self._on_download_changed) - # trans.connect("config-file-conflict", self._on_config_file_conflict) - # yield trans.set_debconf_frontend("ukui") - yield trans.run() - - def _on_finished(self, trans, status, action): - error_string = '' - error_desc = '' - trans_failed = False - - if status == EXIT_FAILED: - # error_string = get_error_string_from_enum(trans.error.code) - # error_desc = get_error_description_from_enum(trans.error.code) - if self.errors: - error_string = self.errors.code - error_string = get_error_string_from_enum(trans.error.code) - error_desc = get_error_description_from_enum(trans.error.code) - if self.trans_failed_msg: - trans_failed = True - error_desc = error_desc + "\n" + self.trans_failed_msg - elif status == EXIT_CANCELLED: - error_desc = 'cancel download' - is_success = (status == EXIT_SUCCESS) - - try: - self._action_done(action, - authorized=True, success=is_success, - error_string=error_string, error_desc=error_desc, - trans_failed=trans_failed) - # - # if self.errors.code == 'error-dep-resolution-failed': - except TypeError: - # this module used to be be lazily imported and in older code - # trans_failed= is not accepted - # TODO: this workaround can be dropped in Ubuntu 20.10 - self._action_done(action, - authorized=True, success=is_success, - error_string=error_string, error_desc=error_desc) diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/__init__.py b/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/__init__.py deleted file mode 100644 index b695ebe..0000000 --- a/debian/kylin-system-updater/debian/kylin-system-updater/usr/lib/python3.8/dist-packages/SystemUpdater/backend/__init__.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- - -"""Integration of package managers into SystemUpdater""" -# (c) 2005-2009 Canonical, GPL - -from __future__ import absolute_import - -import logging -import os -from gettext import gettext as _ - - -class InstallBackend(): - ACTION_UPDATE = 0 - ACTION_INSTALL = 1 - - def __init__(self, window_main, action): - self.window_main = window_main - self.action = action - self.upgrade_groups_list = [] - - def start(self,partial_upgrade_list = []): - - #FIXME: 在下载升级的能抑制系统关闭或者睡眠 参考ubuntu此部分代码 - - if self.action == self.ACTION_INSTALL: - pkgs_install = [] - pkgs_upgrade = ['code', 'cpio', 'distro-info-data', 'ghostscript'] - pkgs_remove = [] - pkgs_purge = [] - try: - # #可选升级不为空 - # if partial_upgrade_list: - # self.upgrade_groups_list = partial_upgrade_list - # #全部升级列表 - # else: - # self.upgrade_groups_list = self.window_main.update_list.local_upgrade_list.get('upgrade_groups_list',[]) - - # #遍历升级组列表 - # if self.upgrade_groups_list: - # for group_name in self.upgrade_groups_list: - # pkgs_install += self.window_main.update_list.local_upgrade_list.get(group_name,[]).get('pkgs_install',[]) - # pkgs_upgrade += self.window_main.update_list.local_upgrade_list.get(group_name,[]).get('pkgs_upgrade',[]) - - # pkgs_remove = self.window_main.update_list.local_upgrade_list.get("pkgs_remove",[]) - # else: - # logging.info("no upgradeable packages") - # return - - # #目前不确定#auto含义 大概是自动安装新包 类似加-y ubuntu这样做 - # new_pkgs_install = [] - # for pkgname in pkgs_install: - # pkgname += "#auto" - # new_pkgs_install.append(pkgname) - - logging.info("commit install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) - self.commit(pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge) - except Exception as e: - logging.error(e) - else: - self.update() - - def start_alone(self,pkgs_install = [], pkgs_upgrade = [], pkgs_remove = [],pkgs_purge = []): - os.environ["APT_LISTCHANGES_FRONTEND"] = "none" - - if self.action == self.ACTION_INSTALL: - # Get the packages which should be installed and update - self.commit(pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge) - else: - self.update() - - def update(self): - """Run a update to refresh the package list""" - raise NotImplementedError - - def commit(self, pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge): - """Commit the cache changes """ - raise NotImplementedError - - #出现错误和更新升级完成都会调到此方法 进行处理 - def _action_done(self, action, authorized, success, error_string, - error_desc, trans_failed=False): - - #升级完成后走的分支 - if action == self.ACTION_INSTALL: - self.window_main.is_upgrading = False - if success: - #当组列表为空时 表示现在的单独进行安装某些包或卸载,不发信号到控制面板 - if self.upgrade_groups_list: - self.window_main.dbusController.UpdateDownloadFinished(success,self.upgrade_groups_list,'','') - else: - self.window_main.start_available() - elif error_string or error_desc: - logging.warning(error_string + error_desc) - if error_string.startswith('error-dep-resolution-failed'): - self.window_main.dbusController.UpdateDownloadFinished(success,self.upgrade_groups_list,error_string,error_desc) - else: - self.window_main.dbusController.UpdateDownloadFinished(success,self.upgrade_groups_list,'','') - else: - self.window_main.is_updating = False - if success: - self.window_main.start_available() - elif error_string or error_desc: - logging.warning(error_string + error_desc) - self.window_main.dbusController.UpdateDetectFinished(success,[],error_string,error_desc) - else: - self.window_main.dbusController.UpdateDetectFinished(success,[],'','') - -# try aptdaemon -if os.path.exists("/usr/sbin/aptd") \ - and "UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC" not in os.environ: - # check if the gtkwidgets are installed as well - try: - from .InstallBackendAptdaemon import InstallBackendAptdaemon - except ImportError: - logging.exception("importing aptdaemon") - - -def get_backend(*args, **kwargs): - """Select and return a package manager backend.""" - # try aptdaemon - if (os.path.exists("/usr/sbin/aptd") - and "UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC" not in os.environ): - # check if the gtkwidgets are installed as well - try: - return InstallBackendAptdaemon(*args, **kwargs) - except NameError: - logging.exception("using aptdaemon failed") - - # nothing found, raise - raise Exception("No working backend found, please try installing " - "aptdaemon or synaptic") diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo b/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo deleted file mode 100644 index 9ad85ac..0000000 Binary files a/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo and /dev/null differ diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo b/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo deleted file mode 100644 index 4b58ea2..0000000 Binary files a/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo and /dev/null differ diff --git a/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo b/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo deleted file mode 100644 index 8a70c9b..0000000 Binary files a/debian/kylin-system-updater/debian/kylin-system-updater/usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo and /dev/null differ diff --git a/debian/kylin-system-updater/etc/apt/apt.conf.d/30kylin-system-updater b/debian/kylin-system-updater/etc/apt/apt.conf.d/30kylin-system-updater deleted file mode 100644 index 459b1b6..0000000 --- a/debian/kylin-system-updater/etc/apt/apt.conf.d/30kylin-system-updater +++ /dev/null @@ -1,17 +0,0 @@ -//reference 50uu -Kylin-update-manager::Allowed-Origins { - //"Ubuntu:trusty"; - //"Kylin:10.1"; - ":default"; -}; - -Kylin-update-manager::Package-Blacklist { -}; - -Kylin-update-manager::Package-Whitelist { -}; - -Kylin-update-manager::Package-Whitelist-Strict { -}; - -Kylin-update-manager::DevRelease "auto"; diff --git a/debian/kylin-system-updater/etc/dbus-1/system.d/com.kylin.systemupgrade.conf b/debian/kylin-system-updater/etc/dbus-1/system.d/com.kylin.systemupgrade.conf deleted file mode 100644 index 0408835..0000000 --- a/debian/kylin-system-updater/etc/dbus-1/system.d/com.kylin.systemupgrade.conf +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/debian/kylin-system-updater/usr/bin/kylin-system-updater b/debian/kylin-system-updater/usr/bin/kylin-system-updater deleted file mode 100755 index 417f5c9..0000000 --- a/debian/kylin-system-updater/usr/bin/kylin-system-updater +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python3 - -from __future__ import print_function - -from SystemUpdater.UpdateManager import UpdateManager -from gettext import gettext as _ -# import -import logging -from optparse import OptionParser -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib - -#定义日志的格式 -FORMAT = '%(asctime)-15s %(levelname)s:%(message)s' - -FORMAT_DEBUG = '%(asctime)-15s %(levelname)s(%(filename)s:%(lineno)d):%(message)s' - -if __name__ == "__main__": - - # Begin parsing of options - parser = OptionParser() - parser.add_option ("--no-update", action="store_true", - dest="no_update", default=False, - help=_("Do not check for updates when starting")) - parser.add_option ("", "--debug", action="store_true", default=False, - help=_("Show debug messages")) - - (options, args) = parser.parse_args() - - if options.debug: - logging.basicConfig(format=FORMAT,level=logging.INFO) - else: - logging.basicConfig(format=FORMAT,level=logging.INFO) - - logging.info('kylin-update-manager starting ...') - bus_loop = DBusGMainLoop(set_as_default=True) - - app = UpdateManager(options) - # app.start_update() - - loop = GLib.MainLoop() - loop.run() - \ No newline at end of file diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/AlertWatcher.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/AlertWatcher.py deleted file mode 100644 index 83e8ba7..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/AlertWatcher.py +++ /dev/null @@ -1,101 +0,0 @@ -# AlertWatcher.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2010 Mohamed Amine IL Idrissi -# -# Author: Mohamed Amine IL Idrissi -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import absolute_import - -from gi.repository import GObject -import dbus -from dbus.mainloop.glib import DBusGMainLoop - - -class AlertWatcher(GObject.GObject): - """ a class that checks for alerts and reports them, like a battery - or network warning """ - - __gsignals__ = {"network-alert": (GObject.SignalFlags.RUN_FIRST, - None, - (GObject.TYPE_INT,)), - "battery-alert": (GObject.SignalFlags.RUN_FIRST, - None, - (GObject.TYPE_BOOLEAN,)), - "network-3g-alert": (GObject.SignalFlags.RUN_FIRST, - None, - (GObject.TYPE_BOOLEAN, - GObject.TYPE_BOOLEAN,)), - } - - def __init__(self): - GObject.GObject.__init__(self) - DBusGMainLoop(set_as_default=True) - self.bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - # make it always connected if NM isn't available - self.network_state = 3 - - def check_alert_state(self): - try: - #network - obj = self.bus.get_object("org.freedesktop.NetworkManager", - "/org/freedesktop/NetworkManager") - obj.connect_to_signal( - "StateChanged", - self._on_network_state_changed, - dbus_interface="org.freedesktop.NetworkManager") - interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties") - self.network_state = interface.Get( - "org.freedesktop.NetworkManager", "State") - self._network_alert(self.network_state) - - # power - # obj = self.bus.get_object('org.freedesktop.UPower', - # '/org/freedesktop/UPower') - # obj.connect_to_signal("Changed", self._power_changed, - # dbus_interface="org.freedesktop.UPower") - # self._power_changed() - # 3g - # self._update_3g_state() - except dbus.exceptions.DBusException: - pass - - def _on_network_state_changed(self, state): - self._network_alert(state) - # self._update_3g_state() - - # def _update_3g_state(self): - # from .roam import NetworkManagerHelper - # nm = NetworkManagerHelper() - # on_3g = nm.is_active_connection_gsm_or_cdma() - # is_roaming = nm.is_active_connection_gsm_or_cdma_roaming() - # self._network_3g_alert(on_3g, is_roaming) - - # def _network_3g_alert(self, on_3g, is_roaming): - # self.emit("network-3g-alert", on_3g, is_roaming) - - def _network_alert(self, state): - self.network_state = state - self.emit("network-alert", state) - - # def _power_changed(self): - # obj = self.bus.get_object("org.freedesktop.UPower", - # "/org/freedesktop/UPower") - # interface = dbus.Interface(obj, "org.freedesktop.DBus.Properties") - # on_battery = interface.Get("org.freedesktop.UPower", "OnBattery") - # self.emit("battery-alert", on_battery) diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/Database.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/Database.py deleted file mode 100644 index 94e1f69..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/Database.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -import os -import re -import shutil -import sqlite3 -import logging -from gettext import gettext as _ - -DB_FILE = os.path.join("/var/cache/kylin-system-updater/kylin-system-updater.db") -INSTALLED_LIST = [{"item": "errorcode", "type": "int", "default": "0"}] -DISPALY_LIST = [] - -class Sqlite3Server(object): - def __init__(self): - self.connect = None - logging.info("init Sqlite3Server running...") - self.init_sqlit() - - # 初始化连接数据库 - def init_sqlit(self): - logging.info(_("初始化连接数据库 ...")) - try: - if os.path.isfile(DB_FILE): - self.connect = sqlite3.connect(DB_FILE, check_same_thread=False) - self.cursor = self.connect.cursor() - self.insert_new_field() - else: - if not os.path.isdir(os.path.dirname(DB_FILE)): - os.makedirs(os.path.dirname(DB_FILE)) - shutil.copy("/usr/share/kylin-system-updater/kylin-system-updater.db", os.path.dirname(DB_FILE)) - self.connect = sqlite3.connect(DB_FILE, check_same_thread=False) - self.cursor = self.connect.cursor() - self.insert_new_field() - except Exception as e: - logging.error(_("初始化数据库失败: %s"), str(e)) - return False - logging.info(_("成功连接数据库.")) - return True - - # 数据库表格中动态增加新的字段用于扩展 - def insert_new_field(self): - if len(INSTALLED_LIST) == 0 and len(DISPALY_LIST) == 0: - return - self.cursor.execute("select sql from sqlite_master where name='installed'") - installed_sql = self.cursor.fetchone()[0] - pattern = re.compile(r'\"\w+\"') - installed_sql_list = pattern.findall(installed_sql) - for value in INSTALLED_LIST: - for field in installed_sql_list: - if value["item"] == str(field).strip("\""): - break - elif field == installed_sql_list[len(installed_sql_list) - 1]: - try: - if value["default"] != "": - sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"] \ - + ' default ' + str(value["default"]) - else: - sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"] - self.cursor.execute(sql) - logging.info(_("installed表插入新字段: %s"), value["item"]) - except: - logging.error(_("installed表插入新字段失败:"), value["item"], exc_info=True) - - self.cursor.execute("select sql from sqlite_master where name='display'") - display_sql = self.cursor.fetchone()[0] - pattern = re.compile(r'\"\w+\"') - display_sql_list = pattern.findall(display_sql) - for value in DISPALY_LIST: - for field in display_sql_list: - if value["item"] == str(field).strip("\""): - break - elif field == display_sql_list[len(display_sql_list) - 1]: - try: - if value["default"] != "": - sql = 'alter table display add column "' + value["item"] + '" ' + value["type"] \ - + ' default ' + str(value["default"]) - else: - sql = 'alter table installed add column "' + value["item"] + '" ' + value["type"] - self.cursor.execute(sql) - logging.info(_("display表插入新字段: %s"), value["item"]) - except: - logging.error(_("display表插入新字段失败: %s"), value["item"], exc_info=True) - - # 写入数据到installed表中 - def insert_into_installed(self, *args, **kwargs): - self.cursor.execute( - "insert into installed (appname, version, time, description, icon, statue, keyword, errorcode) values(?," - "?,?,?,?,?,?,?)", - (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7])) - self.connect.commit() - - # 写入数据到display表中 - def insert_into_display(self, *args, **kwargs): - sql = "update display set " + args[0] + "='" + args[1] + "' where id = 1" - self.cursor.execute(sql) - self.connect.commit() - - diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/DistUpgradeCache.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/DistUpgradeCache.py deleted file mode 100644 index a3971e5..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/DistUpgradeCache.py +++ /dev/null @@ -1,1251 +0,0 @@ -# DistUpgradeCache.py -# -# Copyright (c) 2004-2008 Canonical -# -# Author: Michael Vogt -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -import apt -import apt_pkg -import glob -import locale -import os -import re -import logging -import time -import datetime -import threading -import configparser -from subprocess import Popen, PIPE - -from gettext import gettext as _ - -from .utils import inside_chroot - -class CacheException(Exception): - pass - - -class CacheExceptionLockingFailed(CacheException): - pass - - -class CacheExceptionDpkgInterrupted(CacheException): - pass - - -def estimate_kernel_initrd_size_in_boot(): - """estimate the amount of space used by the kernel and initramfs in /boot, - including a safety margin - """ - kernel = 0 - initrd = 0 - kver = os.uname()[2] - for f in glob.glob("/boot/*%s*" % kver): - if f == '/boot/initrd.img-%s' % kver: - initrd += os.path.getsize(f) - # don't include in the estimate any files that are left behind by - # an interrupted package manager run - elif (f.find('initrd.img') >= 0 or f.find('.bak') >= 0 - or f.find('.dpkg-') >= 0): - continue - else: - kernel += os.path.getsize(f) - if kernel == 0: - logging.warning( - "estimate_kernel_initrd_size_in_boot() returned '0' for kernel?") - kernel = 16*1024*1024 - if initrd == 0: - logging.warning( - "estimate_kernel_initrd_size_in_boot() returned '0' for initrd?") - initrd = 100*1024*1024 - # add small safety buffer - kernel += 1*1024*1024 - # safety buffer as a percentage of the existing initrd's size - initrd_buffer = 1*1024*1024 - if initrd * 0.05 > initrd_buffer: - initrd_buffer = initrd * 0.05 - initrd += initrd_buffer - return kernel,initrd -KERNEL_SIZE, INITRD_SIZE = estimate_kernel_initrd_size_in_boot() - - -class FreeSpaceRequired(object): - """ FreeSpaceRequired object: - - This exposes: - - the total size required (size_total) - - the dir that requires the space (dir) - - the additional space that is needed (size_needed) - """ - def __init__(self, size_total, dir, size_needed): - self.size_total = size_total - self.dir = dir - self.size_needed = size_needed - def __str__(self): - return "FreeSpaceRequired Object: Dir: %s size_total: %s size_needed: %s" % (self.dir, self.size_total, self.size_needed) - - -class NotEnoughFreeSpaceError(CacheException): - """ - Exception if there is not enough free space for this operation - - """ - def __init__(self, free_space_required_list): - self.free_space_required_list = free_space_required_list - - -class MyCache(apt.Cache): - ReInstReq = 1 - HoldReInstReq = 3 - - # init - def __init__(self, config, view, quirks, progress=None, lock=True): - self.to_install = [] - self.to_remove = [] - self.view = view - self.quirks = quirks - self.lock = False - self.partialUpgrade = False - self.config = config - self.metapkgs = self.config.getlist("Distro", "MetaPkgs") - # acquire lock - self._listsLock = -1 - if lock: - try: - apt_pkg.pkgsystem_lock() - self.lock_lists_dir() - self.lock = True - except SystemError as e: - # checking for this is ok, its not translatable - if "dpkg --configure -a" in str(e): - raise CacheExceptionDpkgInterrupted(e) - raise CacheExceptionLockingFailed(e) - # Do not create the cache until we know it is not locked - apt.Cache.__init__(self, progress) - # a list of regexp that are not allowed to be removed - self.removal_blacklist = config.getListFromFile("Distro", "RemovalBlacklistFile") - # the linux metapackage should not be removed - self.linux_metapackage = self.quirks._get_linux_metapackage(self, False) - self.uname = Popen(["uname", "-r"], stdout=PIPE, - universal_newlines=True).communicate()[0].strip() - self._initAptLog() - # from hardy on we use recommends by default, so for the - # transition to the new dist we need to enable them now - if (config.get("Sources", "From") == "hardy" and - not "RELEASE_UPGRADE_NO_RECOMMENDS" in os.environ): - apt_pkg.config.set("APT::Install-Recommends", "true") - - - apt_pkg.config.set("APT::AutoRemove::SuggestsImportant", "false") - - def _apply_dselect_upgrade(self): - """ honor the dselect install state """ - for pkg in self: - if pkg.is_installed: - continue - if pkg._pkg.selected_state == apt_pkg.SELSTATE_INSTALL: - # upgrade() will take care of this - pkg.mark_install(auto_inst=False, auto_fix=False) - - @property - def req_reinstall_pkgs(self): - " return the packages not downloadable packages in reqreinst state " - reqreinst = set() - for pkg in self: - if ((not pkg.candidate or not pkg.candidate.downloadable) - and - (pkg._pkg.inst_state == self.ReInstReq or - pkg._pkg.inst_state == self.HoldReInstReq)): - reqreinst.add(pkg.name) - return reqreinst - - def fix_req_reinst(self, view): - " check for reqreinst state and offer to fix it " - reqreinst = self.req_reinstall_pkgs - if len(reqreinst) > 0: - header = _("Remove package in bad state", - "Remove packages in bad state", - len(reqreinst)) - summary = _("The package '%s' is in an inconsistent " - "state and needs to be reinstalled, but " - "no archive can be found for it. " - "Do you want to remove this package " - "now to continue?", - "The packages '%s' are in an inconsistent " - "state and need to be reinstalled, but " - "no archives can be found for them. Do you " - "want to remove these packages now to " - "continue?", - len(reqreinst)) % ", ".join(reqreinst) - if view.askYesNoQuestion(header, summary): - self.release_lock() - cmd = ["/usr/bin/dpkg", "--remove", "--force-remove-reinstreq"] + list(reqreinst) - view.getTerminal().call(cmd) - self.get_lock() - return True - return False - - # logging stuff - def _initAptLog(self): - " init logging, create log file" - logdir = self.config.getWithDefault("Files", "LogDir", - "/var/log/dist-upgrade") - if not os.path.exists(logdir): - os.makedirs(logdir) - apt_pkg.config.set("Dir::Log", logdir) - apt_pkg.config.set("Dir::Log::Terminal", "apt-term.log") - self.logfd = os.open(os.path.join(logdir, "apt.log"), - os.O_RDWR | os.O_CREAT | os.O_APPEND, 0o644) - now = datetime.datetime.now() - header = "Log time: %s\n" % now - os.write(self.logfd, header.encode("utf-8")) - - # turn on debugging in the cache - apt_pkg.config.set("Debug::pkgProblemResolver", "true") - apt_pkg.config.set("Debug::pkgDepCache::Marker", "true") - apt_pkg.config.set("Debug::pkgDepCache::AutoInstall", "true") - def _startAptResolverLog(self): - if hasattr(self, "old_stdout"): - os.close(self.old_stdout) - os.close(self.old_stderr) - self.old_stdout = os.dup(1) - self.old_stderr = os.dup(2) - os.dup2(self.logfd, 1) - os.dup2(self.logfd, 2) - def _stopAptResolverLog(self): - os.fsync(1) - os.fsync(2) - os.dup2(self.old_stdout, 1) - os.dup2(self.old_stderr, 2) - # use this decorator instead of the _start/_stop stuff directly - # FIXME: this should probably be a decorator class where all - # logging is moved into? - def withResolverLog(f): - " decorator to ensure that the apt output is logged " - def wrapper(*args, **kwargs): - args[0]._startAptResolverLog() - res = f(*args, **kwargs) - args[0]._stopAptResolverLog() - return res - return wrapper - - # properties - @property - def required_download(self): - """ get the size of the packages that are required to download """ - pm = apt_pkg.PackageManager(self._depcache) - fetcher = apt_pkg.Acquire() - pm.get_archives(fetcher, self._list, self._records) - return fetcher.fetch_needed - @property - def additional_required_space(self): - """ get the size of the additional required space on the fs """ - return self._depcache.usr_size - @property - def additional_required_space_for_snaps(self): - """ get the extra size needed to install the snap replacements """ - try: - # update-manager uses DistUpgradeCache.MyCache as the base class - # of its own MyCache version - but without actually calling our - # constructor at all. This causes that the MyCache version from - # update-manager has no self.quirks attribute while still calling - # our default version of checkFreeSpace(). Since extra_snap_space - # is only used on dist-upgrades, let's just not care and return 0 - # in this weird, undocumented case. - return self.quirks.extra_snap_space - except AttributeError: - return 0 - @property - def is_broken(self): - """ is the cache broken """ - return self._depcache.broken_count > 0 - - # methods - def lock_lists_dir(self): - name = apt_pkg.config.find_dir("Dir::State::Lists") + "lock" - self._listsLock = apt_pkg.get_lock(name) - if self._listsLock < 0: - e = "Can not lock '%s' " % name - raise CacheExceptionLockingFailed(e) - def unlock_lists_dir(self): - if self._listsLock > 0: - os.close(self._listsLock) - self._listsLock = -1 - def update(self, fprogress=None): - """ - our own update implementation is required because we keep the lists - dir lock - """ - self.unlock_lists_dir() - res = apt.Cache.update(self, fprogress) - self.lock_lists_dir() - if fprogress and fprogress.release_file_download_error: - # FIXME: not ideal error message, but we just reuse a - # existing one here to avoid a new string - raise IOError(_("The server may be overloaded")) - if res == False: - raise IOError("apt.cache.update() returned False, but did not raise exception?!?") - - def commit(self, fprogress, iprogress): - logging.info("cache.commit()") - if self.lock: - self.release_lock() - apt.Cache.commit(self, fprogress, iprogress) - - def release_lock(self, pkgSystemOnly=True): - if self.lock: - try: - apt_pkg.pkgsystem_unlock() - self.lock = False - except SystemError as e: - logging.debug("failed to SystemUnLock() (%s) " % e) - - def get_lock(self, pkgSystemOnly=True): - if not self.lock: - try: - apt_pkg.pkgsystem_lock() - self.lock = True - except SystemError as e: - logging.debug("failed to SystemLock() (%s) " % e) - - def downloadable(self, pkg, useCandidate=True): - " check if the given pkg can be downloaded " - if useCandidate: - ver = self._depcache.get_candidate_ver(pkg._pkg) - else: - ver = pkg._pkg.current_ver - if ver == None: - logging.warning("no version information for '%s' (useCandidate=%s)" % (pkg.name, useCandidate)) - return False - return ver.downloadable - - def pkg_auto_removable(self, pkg): - """ check if the pkg is auto-removable """ - return (pkg.is_installed and - self._depcache.is_garbage(pkg._pkg)) - - def fix_broken(self): - """ try to fix broken dependencies on the system, may throw - SystemError when it can't""" - return self._depcache.fix_broken() - - def create_snapshot(self): - """ create a snapshot of the current changes """ - self.to_install = [] - self.to_remove = [] - for pkg in self.get_changes(): - if pkg.marked_install or pkg.marked_upgrade: - self.to_install.append(pkg.name) - if pkg.marked_delete: - self.to_remove.append(pkg.name) - - def clear(self): - self._depcache.init() - - def restore_snapshot(self): - """ restore a snapshot """ - actiongroup = apt_pkg.ActionGroup(self._depcache) - # just make pyflakes shut up, later we need to use - # with self.actiongroup(): - actiongroup - self.clear() - for name in self.to_remove: - pkg = self[name] - pkg.mark_delete() - for name in self.to_install: - pkg = self[name] - pkg.mark_install(auto_fix=False, auto_inst=False) - - def need_server_mode(self): - """ - This checks if we run on a desktop or a server install. - - A server install has more freedoms, for a desktop install - we force a desktop meta package to be install on the upgrade. - - We look for a installed desktop meta pkg and for key - dependencies, if none of those are installed we assume - server mode - """ - #logging.debug("need_server_mode() run") - # check for the MetaPkgs (e.g. ubuntu-desktop) - metapkgs = self.config.getlist("Distro", "MetaPkgs") - for key in metapkgs: - # if it is installed we are done - if key in self and self[key].is_installed: - logging.debug("need_server_mode(): run in 'desktop' mode, (because of pkg '%s')" % key) - return False - # if it is not installed, but its key depends are installed - # we are done too (we auto-select the package later) - deps_found = True - for pkg in self.config.getlist(key, "KeyDependencies"): - deps_found &= pkg in self and self[pkg].is_installed - if deps_found: - logging.debug("need_server_mode(): run in 'desktop' mode, (because of key deps for '%s')" % key) - return False - logging.debug("need_server_mode(): can not find a desktop meta package or key deps, running in server mode") - return True - - def sanity_check(self, view): - """ check if the cache is ok and if the required metapkgs - are installed - """ - if self.is_broken: - try: - logging.debug("Have broken pkgs, trying to fix them") - self.fix_broken() - except SystemError: - view.error(_("Broken packages"), - _("Your system contains broken packages " - "that couldn't be fixed with this " - "software. " - "Please fix them first using synaptic or " - "apt-get before proceeding.")) - return False - return True - - def mark_install(self, pkg, reason="", **flags): - logging.debug("Installing '%s' (%s)" % (pkg, reason)) - if pkg in self: - self[pkg].mark_install(**flags) - if not (self[pkg].marked_install or self[pkg].marked_upgrade): - logging.error("Installing/upgrading '%s' failed" % pkg) - #raise SystemError("Installing '%s' failed" % pkg) - return False - return True - - def mark_upgrade(self, pkg, reason=""): - logging.debug("Upgrading '%s' (%s)" % (pkg, reason)) - if pkg in self and self[pkg].is_installed: - self[pkg].mark_upgrade() - if not self[pkg].marked_upgrade: - logging.error("Upgrading '%s' failed" % pkg) - return False - return True - - def mark_remove(self, pkg, reason="", **flags): - logging.debug("Removing '%s' (%s)" % (pkg, reason)) - if pkg in self: - self[pkg].mark_delete(**flags) - - def mark_purge(self, pkg, reason=""): - logging.debug("Purging '%s' (%s)" % (pkg, reason)) - if pkg in self: - self._depcache.mark_delete(self[pkg]._pkg, True) - - def _keep_installed(self, pkgname, reason): - if (pkgname in self - and self[pkgname].is_installed - and self[pkgname].marked_delete): - self.mark_install(pkgname, reason) - - def keep_installed_rule(self): - """ run after the dist-upgrade to ensure that certain - packages are kept installed """ - # first the global list - for pkgname in self.config.getlist("Distro", "KeepInstalledPkgs"): - self._keep_installed(pkgname, "Distro KeepInstalledPkgs rule") - # the the per-metapkg rules - for key in self.metapkgs: - if key in self and (self[key].is_installed or - self[key].marked_install): - for pkgname in self.config.getlist(key, "KeepInstalledPkgs"): - self._keep_installed(pkgname, "%s KeepInstalledPkgs rule" % key) - - # only enforce section if we have a network. Otherwise we run - # into CD upgrade issues for installed language packs etc - if self.config.get("Options", "withNetwork") == "True": - logging.debug("Running KeepInstalledSection rules") - # now the KeepInstalledSection code - for section in self.config.getlist("Distro", "KeepInstalledSection"): - for pkg in self: - if (pkg.candidate and pkg.candidate.downloadable - and pkg.marked_delete - and pkg.candidate.section == section): - self._keep_installed(pkg.name, "Distro KeepInstalledSection rule: %s" % section) - for key in self.metapkgs: - if key in self and (self[key].is_installed or - self[key].marked_install): - for section in self.config.getlist(key, "KeepInstalledSection"): - for pkg in self: - if (pkg.candidate and pkg.candidate.downloadable - and pkg.marked_delete and - pkg.candidate.section == section): - self._keep_installed(pkg.name, "%s KeepInstalledSection rule: %s" % (key, section)) - - - def pre_upgrade_rule(self): - " run before the upgrade was done in the cache " - # run the quirks handlers - if not self.partialUpgrade: - self.quirks.run("PreDistUpgradeCache") - - def post_upgrade_rule(self): - " run after the upgrade was done in the cache " - for (rule, action) in [("Install", self.mark_install), - ("Upgrade", self.mark_upgrade), - ("Remove", self.mark_remove), - ("Purge", self.mark_purge)]: - # first the global list - for pkg in self.config.getlist("Distro", "PostUpgrade%s" % rule): - action(pkg, "Distro PostUpgrade%s rule" % rule) - for key in self.metapkgs: - if key in self and (self[key].is_installed or - self[key].marked_install): - for pkg in self.config.getlist(key, "PostUpgrade%s" % rule): - action(pkg, "%s PostUpgrade%s rule" % (key, rule)) - # run the quirks handlers - if not self.partialUpgrade: - self.quirks.run("PostDistUpgradeCache") - - def checkForNvidia(self): - """ - this checks for nvidia hardware and checks what driver is needed - """ - logging.debug("nvidiaUpdate()") - # if the free drivers would give us a equally hard time, we would - # never be able to release - try: - from NvidiaDetector.nvidiadetector import NvidiaDetection - except (ImportError, SyntaxError) as e: - # SyntaxError is temporary until the port of NvidiaDetector to - # Python 3 is in the archive. - logging.error("NvidiaDetector can not be imported %s" % e) - return False - try: - # get new detection module and use the modalises files - # from within the release-upgrader - nv = NvidiaDetection(obsolete="./ubuntu-drivers-obsolete.pkgs") - #nv = NvidiaDetection() - # check if a binary driver is installed now - for oldDriver in nv.oldPackages: - if oldDriver in self and self[oldDriver].is_installed: - self.mark_remove(oldDriver, "old nvidia driver") - break - else: - logging.info("no old nvidia driver installed, installing no new") - return False - # check which one to use - driver = nv.selectDriver() - logging.debug("nv.selectDriver() returned '%s'" % driver) - if not driver in self: - logging.warning("no '%s' found" % driver) - return False - if not (self[driver].marked_install or self[driver].marked_upgrade): - self[driver].mark_install() - logging.info("installing %s as suggested by NvidiaDetector" % driver) - return True - except Exception as e: - logging.error("NvidiaDetection returned a error: %s" % e) - return False - - - def _has_kernel_headers_installed(self): - for pkg in self: - if (pkg.name.startswith("linux-headers-") and - pkg.is_installed): - return True - return False - - def checkForKernel(self): - """ check for the running kernel and try to ensure that we have - an updated version - """ - logging.debug("Kernel uname: '%s' " % self.uname) - try: - (version, build, flavour) = self.uname.split("-") - except Exception as e: - logging.warning("Can't parse kernel uname: '%s' (self compiled?)" % e) - return False - # now check if we have a SMP system - dmesg = Popen(["dmesg"], stdout=PIPE).communicate()[0] - if b"WARNING: NR_CPUS limit" in dmesg: - logging.debug("UP kernel on SMP system!?!") - return True - - def checkPriority(self): - # tuple of priorities we require to be installed - need = ('required', ) - # stuff that its ok not to have - removeEssentialOk = self.config.getlist("Distro", "RemoveEssentialOk") - # check now - for pkg in self: - # WORKAROUND bug on the CD/python-apt #253255 - ver = pkg._pcache._depcache.get_candidate_ver(pkg._pkg) - if ver and ver.priority == 0: - logging.error("Package %s has no priority set" % pkg.name) - continue - if (pkg.candidate and pkg.candidate.downloadable and - not (pkg.is_installed or pkg.marked_install) and - not pkg.name in removeEssentialOk and - # ignore multiarch priority required packages - not ":" in pkg.name and - pkg.candidate.priority in need): - self.mark_install(pkg.name, "priority in required set '%s' but not scheduled for install" % need) - - # FIXME: make this a decorator (just like the withResolverLog()) - def updateGUI(self, view, lock): - i = 0 - while lock.locked(): - if i % 15 == 0: - view.pulseProgress() - view.processEvents() - time.sleep(0.02) - i += 1 - view.pulseProgress(finished=True) - view.processEvents() - - @withResolverLog - def distUpgrade(self, view, serverMode, partialUpgrade): - # keep the GUI alive - lock = threading.Lock() - lock.acquire() - t = threading.Thread(target=self.updateGUI, args=(self.view, lock,)) - t.start() - try: - # mvo: disabled as it casues to many errornous installs - #self._apply_dselect_upgrade() - - # run PreDistUpgradeCache quirks - self.pre_upgrade_rule() - - # upgrade (and make sure this way that the cache is ok) - self.upgrade(True) - - # check that everything in priority required is installed - self.checkPriority() - - # see if our KeepInstalled rules are honored - self.keep_installed_rule() - - # check if we got a new kernel (if we are not inside a - # chroot) - if inside_chroot(): - logging.warning("skipping kernel checks because we run inside a chroot") - else: - self.checkForKernel() - - # check for nvidia stuff - self.checkForNvidia() - - # and if we have some special rules - self.post_upgrade_rule() - - # install missing meta-packages (if not in server upgrade mode) - self._keepBaseMetaPkgsInstalled(view) - if not serverMode: - # if this fails, a system error is raised - self._installMetaPkgs(view) - - # see if it all makes sense, if not this function raises - self._verifyChanges() - - if self.is_broken: - raise SystemError(_("Broken packages after upgrade: %s") % ", ".join(p.name for p in self if p.is_inst_broken or p.is_now_broken)) - - except SystemError as e: - # the most likely problem is the 3rd party pkgs so don't address - # foreignPkgs and devRelease being True - details = _("An unresolvable problem occurred while " - "calculating the upgrade.\n\n ") - if self.config.get("Options", "foreignPkgs") == "True": - details += _("This was likely caused by:\n" - " * Unofficial software packages not provided by Ubuntu\n" - "Please use the tool 'ppa-purge' from the ppa-purge \n" - "package to remove software from a Launchpad PPA and \n" - "try the upgrade again.\n" - "\n") - elif self.config.get("Options", "foreignPkgs") == "False" and \ - self.config.get("Options", "devRelease") == "True": - details += _("This was caused by:\n" - " * Upgrading to a pre-release version of Ubuntu\n" - "This is most likely a transient problem, \n" - "please try again later.\n") - # we never have partialUpgrades (including removes) on a stable system - # with only ubuntu sources so we do not recommend reporting a bug - if partialUpgrade: - details += _("This is most likely a transient problem, " - "please try again later.") - else: - details += _("If none of this applies, then please report this bug using " - "the command 'ubuntu-bug ubuntu-release-upgrader-core' in a terminal. ") - details += _("If you want to investigate this yourself the log files in " - "'/var/log/dist-upgrade' will contain details about the upgrade. " - "Specifically, look at 'main.log' and 'apt.log'.") - # make the error text available again on stdout for the - # text frontend - self._stopAptResolverLog() - view.error(_("Could not calculate the upgrade"), details) - # may contain utf-8 (LP: #1310053) - error_msg = str(e) - logging.error("Dist-upgrade failed: '%s'", error_msg) - # start the resolver log again because this is run with - # the withResolverLog decorator - self._startAptResolverLog() - return False - finally: - # wait for the gui-update thread to exit - lock.release() - t.join() - - # check the trust of the packages that are going to change - untrusted = [] - downgrade = [] - for pkg in self.get_changes(): - if pkg.marked_delete: - continue - # special case because of a bug in pkg.candidate.origins - if pkg.marked_downgrade: - downgrade.append(pkg.name) - for ver in pkg._pkg.version_list: - # version is lower than installed one - if apt_pkg.version_compare( - ver.ver_str, pkg.installed.version) < 0: - for (verFileIter, index) in ver.file_list: - indexfile = pkg._pcache._list.find_index(verFileIter) - if indexfile and not indexfile.is_trusted: - untrusted.append(pkg.name) - break - continue - origins = pkg.candidate.origins - trusted = False - for origin in origins: - #print(origin) - trusted |= origin.trusted - if not trusted: - untrusted.append(pkg.name) - # check if the user overwrote the unauthenticated warning - try: - b = self.config.getboolean("Distro", "AllowUnauthenticated") - if b: - logging.warning("AllowUnauthenticated set!") - return True - except configparser.NoOptionError: - pass - if len(downgrade) > 0: - downgrade.sort() - logging.error("Packages to downgrade found: '%s'" % - " ".join(downgrade)) - if len(untrusted) > 0: - untrusted.sort() - logging.error("Unauthenticated packages found: '%s'" % - " ".join(untrusted)) - # FIXME: maybe ask a question here? instead of failing? - self._stopAptResolverLog() - view.error(_("Error authenticating some packages"), - _("It was not possible to authenticate some " - "packages. This may be a transient network problem. " - "You may want to try again later. See below for a " - "list of unauthenticated packages."), - "\n".join(untrusted)) - # start the resolver log again because this is run with - # the withResolverLog decorator - self._startAptResolverLog() - return False - return True - - def _verifyChanges(self): - """ this function tests if the current changes don't violate - our constrains (blacklisted removals etc) - """ - main_arch = apt_pkg.config.find("APT::Architecture") - removeEssentialOk = self.config.getlist("Distro", "RemoveEssentialOk") - # check changes - for pkg in self.get_changes(): - if pkg.marked_delete and self._inRemovalBlacklist(pkg.name): - logging.debug("The package '%s' is marked for removal but it's in the removal blacklist", pkg.name) - raise SystemError(_("The package '%s' is marked for removal but it is in the removal blacklist.") % pkg.name) - if pkg.marked_delete and ( - pkg._pkg.essential == True and - pkg.installed.architecture in (main_arch, "all") and - not pkg.name in removeEssentialOk): - logging.debug("The package '%s' is marked for removal but it's an ESSENTIAL package", pkg.name) - raise SystemError(_("The essential package '%s' is marked for removal.") % pkg.name) - # check bad-versions blacklist - badVersions = self.config.getlist("Distro", "BadVersions") - for bv in badVersions: - (pkgname, ver) = bv.split("_") - if (pkgname in self and self[pkgname].candidate and - self[pkgname].candidate.version == ver and - (self[pkgname].marked_install or - self[pkgname].marked_upgrade)): - raise SystemError(_("Trying to install blacklisted version '%s'") % bv) - return True - - def _lookupPkgRecord(self, pkg): - """ - helper to make sure that the pkg._records is pointing to the right - location - needed because python-apt 0.7.9 dropped the python-apt - version but we can not yet use the new version because on upgrade - the old version is still installed - """ - ver = pkg._pcache._depcache.get_candidate_ver(pkg._pkg) - if ver is None: - print("No candidate ver: ", pkg.name) - return False - if ver.file_list is None: - print("No file_list for: %s " % self._pkg.name()) - return False - f, index = ver.file_list.pop(0) - pkg._pcache._records.lookup((f, index)) - return True - - @property - def installedTasks(self): - tasks = {} - installed_tasks = set() - for pkg in self: - if not self._lookupPkgRecord(pkg): - logging.debug("no PkgRecord found for '%s', skipping " % pkg.name) - continue - for line in pkg._pcache._records.record.split("\n"): - if line.startswith("Task:"): - for task in (line[len("Task:"):]).split(","): - task = task.strip() - if task not in tasks: - tasks[task] = set() - tasks[task].add(pkg.name) - for task in tasks: - installed = True - ignored_tasks = self.config.getlist("Distro", "IgnoredTasks") - if task in ignored_tasks: - installed = False - for pkgname in tasks[task]: - if not self[pkgname].is_installed: - installed = False - break - if installed: - installed_tasks.add(task) - return installed_tasks - - def installTasks(self, tasks): - logging.debug("running installTasks") - for pkg in self: - if pkg.marked_install or pkg.is_installed: - continue - self._lookupPkgRecord(pkg) - if not (hasattr(pkg._pcache._records, "record") and pkg._pcache._records.record): - logging.warning("can not find Record for '%s'" % pkg.name) - continue - for line in pkg._pcache._records.record.split("\n"): - if line.startswith("Task:"): - for task in (line[len("Task:"):]).split(","): - task = task.strip() - if task in tasks: - pkg.mark_install() - return True - - def _keepBaseMetaPkgsInstalled(self, view): - for pkg in self.config.getlist("Distro", "BaseMetaPkgs"): - self._keep_installed(pkg, "base meta package keep installed rule") - - def _installMetaPkgs(self, view): - - def metaPkgInstalled(): - """ - internal helper that checks if at least one meta-pkg is - installed or marked install - """ - for key in metapkgs: - if key in self: - pkg = self[key] - if pkg.is_installed and pkg.marked_delete: - logging.debug("metapkg '%s' installed but marked_delete" % pkg.name) - if ((pkg.is_installed and not pkg.marked_delete) - or self[key].marked_install): - return True - return False - - # now check for ubuntu-desktop, kubuntu-desktop, edubuntu-desktop - metapkgs = self.config.getlist("Distro", "MetaPkgs") - - # we never go without ubuntu-base - for pkg in self.config.getlist("Distro", "BaseMetaPkgs"): - self[pkg].mark_install() - - # every meta-pkg that is installed currently, will be marked - # install (that result in a upgrade and removes a mark_delete) - for key in metapkgs: - try: - if (key in self and - self[key].is_installed and - self[key].is_upgradable): - logging.debug("Marking '%s' for upgrade" % key) - self[key].mark_upgrade() - except SystemError as e: - # warn here, but don't fail, its possible that meta-packages - # conflict (like ubuntu-desktop vs xubuntu-desktop) LP: #775411 - logging.warning("Can't mark '%s' for upgrade (%s)" % (key, e)) - - # check if we have a meta-pkg, if not, try to guess which one to pick - if not metaPkgInstalled(): - logging.debug("none of the '%s' meta-pkgs installed" % metapkgs) - for key in metapkgs: - deps_found = True - for pkg in self.config.getlist(key, "KeyDependencies"): - deps_found &= pkg in self and self[pkg].is_installed - if deps_found: - logging.debug("guessing '%s' as missing meta-pkg" % key) - try: - self[key].mark_install() - except (SystemError, KeyError) as e: - logging.error("failed to mark '%s' for install (%s)" % - (key, e)) - view.error(_("Can't install '%s'") % key, - _("It was impossible to install a " - "required package. Please report " - "this as a bug using " - "'ubuntu-bug ubuntu-release-upgrader-core' in " - "a terminal.")) - return False - logging.debug("marked_install: '%s' -> '%s'" % (key, self[key].marked_install)) - break - # check if we actually found one - if not metaPkgInstalled(): - meta_pkgs = ', '.join(metapkgs[0:-1]) - view.error(_("Can't guess meta-package"), - _("Your system does not contain a " - "%s or %s package and it was not " - "possible to detect which version of " - "Ubuntu you are running.\n " - "Please install one of the packages " - "above first using synaptic or " - "apt-get before proceeding.") % - (meta_pkgs, metapkgs[-1])) - return False - return True - - def _inRemovalBlacklist(self, pkgname): - for expr in self.removal_blacklist: - if re.compile(expr).match(pkgname): - logging.debug("blacklist expr '%s' matches '%s'" % (expr, pkgname)) - return True - return False - - @withResolverLog - def tryMarkObsoleteForRemoval(self, pkgname, remove_candidates, forced_obsoletes, foreign_pkgs): - #logging.debug("tryMarkObsoleteForRemoval(): %s" % pkgname) - # sanity check, first see if it looks like a running kernel pkg - if pkgname.endswith(self.uname): - logging.debug("skipping running kernel pkg '%s'" % pkgname) - return False - if pkgname == self.linux_metapackage: - logging.debug("skipping kernel metapackage '%s'" % pkgname) - return False - if self._inRemovalBlacklist(pkgname): - logging.debug("skipping '%s' (in removalBlacklist)" % pkgname) - return False - # ensure we honor KeepInstalledSection here as well - for section in self.config.getlist("Distro", "KeepInstalledSection"): - if (pkgname in self and self[pkgname].installed and - self[pkgname].installed.section == section): - logging.debug("skipping '%s' (in KeepInstalledSection)" % pkgname) - return False - # if we don't have the package anyway, we are fine (this can - # happen when forced_obsoletes are specified in the config file) - if pkgname not in self: - #logging.debug("package '%s' not in cache" % pkgname) - return True - # check if we want to purge - try: - purge = self.config.getboolean("Distro", "PurgeObsoletes") - except configparser.NoOptionError: - purge = False - - # if this package has not been forced obsolete, only - # delete it if it doesn't remove other dependents - # that are not obsolete as well - actiongroup = apt_pkg.ActionGroup(self._depcache) - # just make pyflakes shut up, later we should use - # with self.actiongroup(): - actiongroup - self.create_snapshot() - try: - self[pkgname].mark_delete(purge=purge) - self.view.processEvents() - if pkgname in forced_obsoletes: - return True - #logging.debug("marking '%s' for removal" % pkgname) - for pkg in self.get_changes(): - if (pkg.name not in remove_candidates or - pkg.name in foreign_pkgs or - self._inRemovalBlacklist(pkg.name) or - pkg.name == self.linux_metapackage): - logging.debug("package '%s' produces an unwanted removal '%s', skipping" % (pkgname, pkg.name)) - self.restore_snapshot() - return False - except (SystemError, KeyError) as e: - logging.warning("_tryMarkObsoleteForRemoval failed for '%s' (%s: %s)" % (pkgname, repr(e), e)) - self.restore_snapshot() - return False - return True - - def _getObsoletesPkgs(self): - " get all package names that are not downloadable " - obsolete_pkgs = set() - for pkg in self: - if pkg.is_installed: - # check if any version is downloadable. we need to check - # for older ones too, because there might be - # cases where e.g. firefox in gutsy-updates is newer - # than hardy - if not self.anyVersionDownloadable(pkg): - obsolete_pkgs.add(pkg.name) - return obsolete_pkgs - - def anyVersionDownloadable(self, pkg): - " helper that checks if any of the version of pkg is downloadable " - for ver in pkg._pkg.version_list: - if ver.downloadable: - return True - return False - - def _getUnusedDependencies(self): - " get all package names that are not downloadable " - unused_dependencies = set() - for pkg in self: - if pkg.is_installed and self._depcache.is_garbage(pkg._pkg): - unused_dependencies.add(pkg.name) - return unused_dependencies - - def get_installed_demoted_packages(self): - """ return list of installed and demoted packages - - If a demoted package is a automatic install it will be skipped - """ - demotions = set() - demotions_file = self.config.get("Distro", "Demotions") - if os.path.exists(demotions_file): - with open(demotions_file) as demotions_f: - for line in demotions_f: - if not line.startswith("#"): - demotions.add(line.strip()) - installed_demotions = set() - for demoted_pkgname in demotions: - if demoted_pkgname not in self: - continue - pkg = self[demoted_pkgname] - if (not pkg.is_installed or - self._depcache.is_auto_installed(pkg._pkg) or - pkg.marked_delete): - continue - installed_demotions.add(pkg) - return list(installed_demotions) - - def _getForeignPkgs(self, allowed_origin, fromDist, toDist): - """ get all packages that are installed from a foreign repo - (and are actually downloadable) - """ - foreign_pkgs = set() - for pkg in self: - if pkg.is_installed and self.downloadable(pkg): - if not pkg.candidate: - continue - # assume it is foreign and see if it is from the - # official archive - foreign = True - for origin in pkg.candidate.origins: - # FIXME: use some better metric here - if fromDist in origin.archive and \ - origin.origin == allowed_origin: - foreign = False - if toDist in origin.archive and \ - origin.origin == allowed_origin: - foreign = False - if foreign: - foreign_pkgs.add(pkg.name) - return foreign_pkgs - - def checkFreeSpace(self, snapshots_in_use=False): - """ - this checks if we have enough free space on /var, /boot and /usr - with the given cache - - Note: this can not be fully accurate if there are multiple - mountpoints for /usr, /var, /boot - """ - - class FreeSpace(object): - " helper class that represents the free space on each mounted fs " - def __init__(self, initialFree): - self.free = initialFree - self.need = 0 - - def make_fs_id(d): - """ return 'id' of a directory so that directories on the - same filesystem get the same id (simply the mount_point) - """ - for mount_point in mounted: - if d.startswith(mount_point): - return mount_point - return "/" - - # this is all a bit complicated - # 1) check what is mounted (in mounted) - # 2) create FreeSpace objects for the dirs we are interested in - # (mnt_map) - # 3) use the mnt_map to check if we have enough free space and - # if not tell the user how much is missing - mounted = [] - mnt_map = {} - fs_free = {} - with open("/proc/mounts") as mounts: - for line in mounts: - try: - (what, where, fs, options, a, b) = line.split() - except ValueError as e: - logging.debug("line '%s' in /proc/mounts not understood (%s)" % (line, e)) - continue - if not where in mounted: - mounted.append(where) - # make sure mounted is sorted by longest path - mounted.sort(key=len, reverse=True) - archivedir = apt_pkg.config.find_dir("Dir::Cache::archives") - aufs_rw_dir = "/tmp/" - if (hasattr(self, "config") and - self.config.getWithDefault("Aufs", "Enabled", False)): - aufs_rw_dir = self.config.get("Aufs", "RWDir") - if not os.path.exists(aufs_rw_dir): - os.makedirs(aufs_rw_dir) - logging.debug("cache aufs_rw_dir: %s" % aufs_rw_dir) - for d in ["/", "/usr", "/var", "/boot", archivedir, aufs_rw_dir, "/home", "/tmp/"]: - d = os.path.realpath(d) - fs_id = make_fs_id(d) - if os.path.exists(d): - st = os.statvfs(d) - free = st.f_bavail * st.f_frsize - else: - logging.warning("directory '%s' does not exists" % d) - free = 0 - if fs_id in mnt_map: - logging.debug("Dir %s mounted on %s" % - (d, mnt_map[fs_id])) - fs_free[d] = fs_free[mnt_map[fs_id]] - else: - logging.debug("Free space on %s: %s" % - (d, free)) - mnt_map[fs_id] = d - fs_free[d] = FreeSpace(free) - del mnt_map - logging.debug("fs_free contains: '%s'" % fs_free) - - # now calculate the space that is required on /boot - # we do this by checking how many linux-image-$ver packages - # are installed or going to be installed - kernel_count = 0 - for pkg in self: - # we match against everything that looks like a kernel - # and add space check to filter out metapackages - if re.match("^linux-(image|image-debug)-[0-9.]*-.*", pkg.name): - # upgrade because early in the release cycle the major version - # may be the same or they might be -lts- kernels - if pkg.marked_install or pkg.marked_upgrade: - logging.debug("%s (new-install) added with %s to boot space" % (pkg.name, KERNEL_SIZE)) - kernel_count += 1 - # space calculated per LP: #1646222 - space_in_boot = (kernel_count * KERNEL_SIZE - + (kernel_count + 1) * INITRD_SIZE) - - # we check for various sizes: - # archivedir is where we download the debs - # /usr is assumed to get *all* of the install space (incorrect, - # but as good as we can do currently + safety buffer - # / has a small safety buffer as well - required_for_aufs = 0.0 - if (hasattr(self, "config") and - self.config.getWithDefault("Aufs", "Enabled", False)): - logging.debug("taking aufs overlay into space calculation") - aufs_rw_dir = self.config.get("Aufs", "RWDir") - # if we use the aufs rw overlay all the space is consumed - # the overlay dir - for pkg in self: - if pkg.marked_upgrade or pkg.marked_install: - required_for_aufs += pkg.candidate.installed_size - - # add old size of the package if we use snapshots - required_for_snapshots = 0.0 - if snapshots_in_use: - for pkg in self: - if (pkg.is_installed and - (pkg.marked_upgrade or pkg.marked_delete)): - required_for_snapshots += pkg.installed.installed_size - logging.debug("additional space for the snapshots: %s" % required_for_snapshots) - - # sum up space requirements - for (dir, size) in [(archivedir, self.required_download), - ("/usr", self.additional_required_space), - # this is only >0 for the deb-to-snap quirks - ("/var", self.additional_required_space_for_snaps), - # plus 50M safety buffer in /usr - ("/usr", 50*1024*1024), - ("/boot", space_in_boot), - ("/tmp", 5*1024*1024), # /tmp for dkms LP: #427035 - ("/", 10*1024*1024), # small safety buffer / - (aufs_rw_dir, required_for_aufs), - # if snapshots are in use - ("/usr", required_for_snapshots), - ]: - # we are ensuring we have more than enough free space not less - if size < 0: - continue - dir = os.path.realpath(dir) - logging.debug("dir '%s' needs '%s' of '%s' (%f)" % (dir, size, fs_free[dir], fs_free[dir].free)) - fs_free[dir].free -= size - fs_free[dir].need += size - - # check for space required violations - required_list = {} - for dir in fs_free: - if fs_free[dir].free < 0: - # ensure unicode here (LP: #1172740) - free_at_least = apt_pkg.size_to_str(float(abs(fs_free[dir].free)+1)) - if isinstance(free_at_least, bytes): - free_at_least = free_at_least.decode( - locale.getpreferredencoding()) - free_needed = apt_pkg.size_to_str(fs_free[dir].need) - if isinstance(free_needed, bytes): - free_needed = free_needed.decode( - locale.getpreferredencoding()) - # make_fs_id ensures we only get stuff on the same - # mountpoint, so we report the requirements only once - # per mountpoint - required_list[make_fs_id(dir)] = FreeSpaceRequired(free_needed, make_fs_id(dir), free_at_least) - # raise exception if free space check fails - if len(required_list) > 0: - logging.error("Not enough free space: %s" % [str(i) for i in required_list]) - raise NotEnoughFreeSpaceError(list(required_list.values())) - return True - - -if __name__ == "__main__": - import sys - # from .DistUpgradeConfigParser import DistUpgradeConfig - # from .DistUpgradeView import DistUpgradeView - # print("foo") - # c = MyCache(DistUpgradeConfig("."), DistUpgradeView(), None) - # #c.checkForNvidia() - # #print(c._identifyObsoleteKernels()) - # print(c.checkFreeSpace()) - sys.exit() - - # c.clear() - # c.create_snapshot() - # c.installedTasks - # c.installTasks(["ubuntu-desktop"]) - # print(c.get_changes()) - # c.restore_snapshot() diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/MyCache.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/MyCache.py deleted file mode 100644 index fec5960..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/MyCache.py +++ /dev/null @@ -1,433 +0,0 @@ -# MyCache.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2004-2008 Canonical -# -# Author: Michael Vogt -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import absolute_import, print_function - -import warnings -warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) -import apt -import apt_pkg -import logging -import os -from urllib.error import HTTPError -from urllib.request import urlopen -from urllib.parse import urlsplit -from http.client import BadStatusLine -import socket -import re -import SystemUpdater.Core.DistUpgradeCache -from gettext import gettext as _ -try: - from launchpadlib.launchpad import Launchpad -except ImportError: - Launchpad = None - -CHANGELOGS_POOL = "https://changelogs.ubuntu.com/changelogs/pool/" -CHANGELOGS_URI = CHANGELOGS_POOL + "%s/%s/%s/%s_%s/%s" - - -class HttpsChangelogsUnsupportedError(Exception): - """ https changelogs with credentials are unsupported because of the - lack of certitifcation validation in urllib2 which allows MITM - attacks to steal the credentials - """ - pass - - -class MyCache(SystemUpdater.Core.DistUpgradeCache.MyCache): - - CHANGELOG_ORIGIN = "Ubuntu" - - def __init__(self, progress, rootdir=None): - apt.Cache.__init__(self, progress, rootdir) - # save for later - self.rootdir = rootdir - # raise if we have packages in reqreinst state - # and let the caller deal with that (runs partial upgrade) - assert len(self.req_reinstall_pkgs) == 0 - # check if the dpkg journal is ok (we need to do that here - # too because libapt will only do it when it tries to lock - # the packaging system) - assert(not self._dpkgJournalDirty()) - # init the regular cache - self._initDepCache() - self.all_changes = {} - self.all_news = {} - # on broken packages, try to fix via saveDistUpgrade() - if self._depcache.broken_count > 0: - self.saveDistUpgrade() - assert (self._depcache.broken_count == 0 - and self._depcache.del_count == 0) - self.launchpad = None - - def _dpkgJournalDirty(self): - """ - test if the dpkg journal is dirty - (similar to debSystem::CheckUpdates) - """ - d = os.path.dirname( - apt_pkg.config.find_file("Dir::State::status")) + "/updates" - for f in os.listdir(d): - if re.match("[0-9]+", f): - return True - return False - - def _initDepCache(self): - self._depcache.read_pinfile() - self._depcache.init() - - def clear(self): - self._initDepCache() - - @property - def required_download(self): - """ get the size of the packages that are required to download """ - pm = apt_pkg.PackageManager(self._depcache) - fetcher = apt_pkg.Acquire() - pm.get_archives(fetcher, self._list, self._records) - return fetcher.fetch_needed - - @property - def install_count(self): - return self._depcache.inst_count - - def keep_count(self): - return self._depcache.keep_count - - @property - def del_count(self): - return self._depcache.del_count - - def _check_dependencies(self, target, deps): - """Return True if any of the dependencies in deps match target.""" - # TODO: handle virtual packages - for dep_or in deps: - if not dep_or: - continue - match = True - for base_dep in dep_or: - if (base_dep.name != target.package.shortname - or not apt_pkg.check_dep( - target.version, base_dep.relation, base_dep.version)): - match = False - if match: - return True - return False - - def find_removal_justification(self, pkg): - target = pkg.installed - if not target: - return False - for cpkg in self: - candidate = cpkg.candidate - if candidate is not None: - if (self._check_dependencies( - target, candidate.get_dependencies("Conflicts")) - and self._check_dependencies( - target, candidate.get_dependencies("Replaces"))): - logging.info( - "%s Conflicts/Replaces %s; allowing removal" % ( - candidate.package.shortname, pkg.shortname)) - return True - return False - - def saveDistUpgrade(self): - """ this functions mimics a upgrade but will never remove anything """ - #upgrade(True) 为True时使用dist-upgrade进行升级 - self._depcache.upgrade(True) - wouldDelete = self._depcache.del_count - wouldDelete = 0 - if wouldDelete > 0: - deleted_pkgs = [pkg for pkg in self if pkg.marked_delete] - assert wouldDelete == len(deleted_pkgs) - for pkg in deleted_pkgs: - if self.find_removal_justification(pkg): - wouldDelete -= 1 - if wouldDelete > 0: - self.clear() - assert (self._depcache.broken_count == 0 - and self._depcache.del_count == 0) - # else: - # assert self._depcache.broken_count == 0 - self._depcache.upgrade() - return wouldDelete - - def _strip_epoch(self, verstr): - " strip of the epoch " - vers_no_epoch = verstr.split(":") - if len(vers_no_epoch) > 1: - verstr = "".join(vers_no_epoch[1:]) - return verstr - - def _get_changelog_or_news(self, name, fname, strict_versioning=False, - changelogs_uri=None): - " helper that fetches the file in question " - # don't touch the gui in this function, it needs to be thread-safe - pkg = self[name] - - # get the src package name - srcpkg = pkg.candidate.source_name - - # assume "main" section - src_section = "main" - # use the section of the candidate as a starting point - section = pkg._pcache._depcache.get_candidate_ver(pkg._pkg).section - - # get the source version - srcver_epoch = pkg.candidate.source_version - srcver = self._strip_epoch(srcver_epoch) - - split_section = section.split("/") - if len(split_section) > 1: - src_section = split_section[0] - - # lib is handled special - prefix = srcpkg[0] - if srcpkg.startswith("lib"): - prefix = "lib" + srcpkg[3] - - # the changelogs_uri argument overrides the default changelogs_uri, - # this is useful for e.g. PPAs where we construct the changelogs - # path differently - if changelogs_uri: - uri = changelogs_uri - else: - uri = CHANGELOGS_URI % (src_section, prefix, srcpkg, srcpkg, - srcver, fname) - - # https uris are not supported when they contain a username/password - # because the urllib2 https implementation will not check certificates - # and so its possible to do a man-in-the-middle attack to steal the - # credentials - res = urlsplit(uri) - if res.scheme == "https" and res.username: - raise HttpsChangelogsUnsupportedError( - "https locations with username/password are not" - "supported to fetch changelogs") - - # print("Trying: %s " % uri) - changelog = urlopen(uri) - #print(changelog.read()) - # do only get the lines that are new - alllines = "" - regexp = "^%s \\((.*)\\)(.*)$" % (re.escape(srcpkg)) - - while True: - line = changelog.readline().decode("UTF-8", "replace") - if line == "": - break - match = re.match(regexp, line) - if match: - # strip epoch from installed version - # and from changelog too - installed = getattr(pkg.installed, "version", None) - if installed and ":" in installed: - installed = installed.split(":", 1)[1] - changelogver = match.group(1) - if changelogver and ":" in changelogver: - changelogver = changelogver.split(":", 1)[1] - # we test for "==" here for changelogs - # to ensure that the version - # is actually really in the changelog - if not - # just display it all, this catches cases like: - # gcc-defaults with "binver=4.3.1" and srcver=1.76 - # - # for NEWS.Debian we do require the changelogver > installed - if strict_versioning: - if (installed - and apt_pkg.version_compare(changelogver, - installed) < 0): - break - else: - if (installed - and apt_pkg.version_compare(changelogver, - installed) == 0): - break - alllines = alllines + line - return alllines - - def _extract_ppa_changelog_uri(self, name): - """Return the changelog URI from the Launchpad API - - Return None in case of an error. - """ - if not Launchpad: - logging.warning("Launchpadlib not available, cannot retrieve PPA " - "changelog") - return None - - cdt = self[name].candidate - for uri in cdt.uris: - if urlsplit(uri).hostname != 'ppa.launchpad.net': - continue - match = re.search('http.*/(.*)/(.*)/ubuntu/.*', uri) - if match is not None: - user, ppa = match.group(1), match.group(2) - break - else: - logging.error("Unable to find a valid PPA candidate URL.") - return - - # Login on launchpad if we are not already - if self.launchpad is None: - self.launchpad = Launchpad.login_anonymously('update-manager', - 'production', - version='devel') - - archive = self.launchpad.archives.getByReference( - reference='~%s/ubuntu/%s' % (user, ppa) - ) - if archive is None: - logging.error("Unable to retrieve the archive from the Launchpad " - "API.") - return - - spphs = archive.getPublishedSources(source_name=cdt.source_name, - exact_match=True, - version=cdt.source_version) - if not spphs: - logging.error("No published sources were retrieved from the " - "Launchpad API.") - return - - return spphs[0].changelogUrl() - - def _guess_third_party_changelogs_uri_by_source(self, name): - pkg = self[name] - deb_uri = pkg.candidate.uri - if deb_uri is None: - return None - srcrec = pkg.candidate.record.get("Source") - if not srcrec: - return None - # srcpkg can be "apt" or "gcc-default (1.0)" - srcpkg = srcrec.split("(")[0].strip() - if "(" in srcrec: - srcver = srcrec.split("(")[1].rstrip(")") - else: - srcver = pkg.candidate.source_version - base_uri = deb_uri.rpartition("/")[0] - return base_uri + "/%s_%s.changelog" % (srcpkg, srcver) - - def _guess_third_party_changelogs_uri_by_binary(self, name): - """ guess changelogs uri based on ArchiveURI by replacing .deb - with .changelog - """ - # there is always a pkg and a pkg.candidate, no need to add - # check here - pkg = self[name] - deb_uri = pkg.candidate.uri - if deb_uri: - return "%s.changelog" % deb_uri.rsplit(".", 1)[0] - return None - - def get_news_and_changelog(self, name, lock): - self.get_news(name) - self.get_changelog(name) - try: - lock.release() - except Exception: - pass - - def get_news(self, name): - " get the NEWS.Debian file from the changelogs location " - try: - news = self._get_changelog_or_news(name, "NEWS.Debian", True) - except Exception: - return - if news: - self.all_news[name] = news - - def _fetch_changelog_for_third_party_package(self, name, origins): - # Special case for PPAs - changelogs_uri_ppa = None - for origin in origins: - if origin.origin.startswith('LP-PPA-'): - try: - changelogs_uri_ppa = self._extract_ppa_changelog_uri(name) - break - except Exception: - logging.exception("Unable to connect to the Launchpad " - "API.") - # Try non official changelog location - changelogs_uri_binary = \ - self._guess_third_party_changelogs_uri_by_binary(name) - changelogs_uri_source = \ - self._guess_third_party_changelogs_uri_by_source(name) - error_message = "" - for changelogs_uri in [changelogs_uri_ppa, - changelogs_uri_binary, - changelogs_uri_source]: - if changelogs_uri: - try: - changelog = self._get_changelog_or_news( - name, "changelog", False, changelogs_uri) - self.all_changes[name] += changelog - except (HTTPError, HttpsChangelogsUnsupportedError): - # no changelogs_uri or 404 - error_message = _( - "This update does not come from a " - "source that supports changelogs.") - except (IOError, BadStatusLine, socket.error): - # network errors and others - logging.exception("error on changelog fetching") - error_message = _( - "Failed to download the list of changes. \n" - "Please check your Internet connection.") - self.all_changes[name] += error_message - - def get_changelog(self, name): - " get the changelog file from the changelog location " - origins = self[name].candidate.origins - self.all_changes[name] = _("Changes for %s versions:\n" - "Installed version: %s\n" - "Available version: %s\n\n") % \ - (name, getattr(self[name].installed, "version", None), - self[name].candidate.version) - if self.CHANGELOG_ORIGIN not in [o.origin for o in origins]: - self._fetch_changelog_for_third_party_package(name, origins) - return - # fixup epoch handling version - srcpkg = self[name].candidate.source_name - srcver_epoch = self[name].candidate.source_version.replace(':', '%3A') - try: - changelog = self._get_changelog_or_news(name, "changelog") - if len(changelog) == 0: - changelog = _("The changelog does not contain any relevant " - "changes.\n\n" - "Please use http://launchpad.net/ubuntu/+source/" - "%s/%s/+changelog\n" - "until the changes become available or try " - "again later.") % (srcpkg, srcver_epoch) - except HTTPError: - changelog = _("The list of changes is not available yet.\n\n" - "Please use http://launchpad.net/ubuntu/+source/" - "%s/%s/+changelog\n" - "until the changes become available or try again " - "later.") % (srcpkg, srcver_epoch) - except (IOError, BadStatusLine, socket.error) as e: - print("caught exception: ", e) - changelog = _("Failed to download the list " - "of changes. \nPlease " - "check your Internet " - "connection.") - self.all_changes[name] += changelog diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/UpdateList.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/UpdateList.py deleted file mode 100644 index a53d2c1..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/UpdateList.py +++ /dev/null @@ -1,675 +0,0 @@ -# UpdateList.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2004-2013 Canonical -# -# Author: Michael Vogt -# Dylan McCall -# Michael Terry -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import print_function - -import warnings -warnings.filterwarnings("ignore", "Accessed deprecated property", - DeprecationWarning) - -from gettext import gettext as _, install -import apt -import logging -import itertools -import os -import random -import glob -import json -from gi.repository import Gio - -import shutil -from .utils import humanize_size -from SystemUpdater.Core import utils -from SystemUpdater.Core import filter - -class UpdateItem(): - def __init__(self, pkg, name, icon, to_remove): - self.icon = icon - self.name = name - self.pkg = pkg - self.to_remove = to_remove - - def is_selected(self): - if not self.to_remove: - return self.pkg.marked_install or self.pkg.marked_upgrade - else: - return self.pkg.marked_delete - - -class UpdateGroup(UpdateItem): - _depcache = {} - - def __init__(self, pkg, name, icon, to_remove): - UpdateItem.__init__(self, pkg, name, icon, to_remove) - self._items = set() - self._deps = set() - self.core_item = None - if pkg is not None: - self.core_item = UpdateItem(pkg, name, icon, to_remove) - self._items.add(self.core_item) - - @property - def items(self): - all_items = [] - all_items.extend(self._items) - return sorted(all_items, key=lambda a: a.name.lower()) - - def add(self, pkg, cache=None, eventloop_callback=None, to_remove=False): - name = utils.get_package_label(pkg) - icon = Gio.ThemedIcon.new("package") - self._items.add(UpdateItem(pkg, name, icon, to_remove)) - # If the pkg is in self._deps, stop here. We have already calculated - # the recursive dependencies for this package, no need to do it again. - if cache and pkg.name in cache and pkg.name not in self._deps: - if not self._deps: - # Initial deps haven't been calculated. As we're checking - # whether _deps is empty in is_dependency, we must init now or - # it won't be done at all. - self._init_deps(cache, eventloop_callback) - self._add_deps(pkg, cache, eventloop_callback) - - def contains(self, item): - return item in self._items - - def _init_deps(self, cache, eventloop_callback): - for item in self._items: - if item.pkg and item.pkg.name not in self._deps: - self._add_deps(item.pkg, cache, eventloop_callback) - - def _add_deps(self, pkg, cache, eventloop_callback): - """Adds pkg and dependencies of pkg to the dependency list.""" - if pkg is None or pkg.candidate is None or pkg.name in self._deps: - # This shouldn't really happen. If we land here often, it's a sign - # that something has gone wrong. Unless all pkgs are None it's not - # a critical issue - a hit to the performance at most. - reason = ((not pkg or not pkg.candidate) - and "Package was None or didn't have a candidate." - or "%s already in _deps." % pkg.name) - logging.debug("Useless call to _add_deps. %s" % reason) - return - if len(self._deps) % 200 == 0 and callable(eventloop_callback): - # Don't spin the loop every time _add_deps is called. - eventloop_callback() - - self._deps.add(pkg.name) - - if pkg.name in self._depcache: - for dep in self._depcache[pkg.name]: - if dep not in self._deps and dep in cache: - self._add_deps(cache[dep], cache, eventloop_callback) - else: - candidate = pkg.candidate - dependencies = candidate.get_dependencies('Depends', 'Recommends') - for dependency_pkg in itertools.chain.from_iterable(dependencies): - name = dependency_pkg.name - if name not in self._deps and name in cache: - self._depcache.setdefault(pkg.name, []).append(name) - self._add_deps(cache[name], cache, eventloop_callback) - - def is_dependency(self, maybe_dep, cache=None, eventloop_callback=None): - if not self._deps and cache: - self._init_deps(cache, eventloop_callback) - - return maybe_dep.name in self._deps - - def packages_are_selected(self): - for item in self.items: - if item.is_selected(): - return True - return False - - def selection_is_inconsistent(self): - pkgs_installing = [item for item in self.items if item.is_selected()] - return (len(pkgs_installing) > 0 - and len(pkgs_installing) < len(self.items)) - - def get_total_size(self): - if self.to_remove: - return 0 - size = 0 - for item in self.items: - size += getattr(item.pkg.candidate, "size", 0) - return size - - -class UpdateApplicationGroup(UpdateGroup): - def __init__(self, pkg, application, to_remove): - name = application.get_display_name() - icon = application.get_icon() - super(UpdateApplicationGroup, self).__init__(pkg, name, icon, - to_remove) - - -class UpdatePackageGroup(UpdateGroup): - def __init__(self, pkg, to_remove): - name = utils.get_package_label(pkg) - icon = Gio.ThemedIcon.new("package") - super(UpdatePackageGroup, self).__init__(pkg, name, icon, to_remove) - - -class UpdateSystemGroup(UpdateGroup): - def __init__(self, cache, to_remove): - # Translators: the %s is a distro name, like 'Ubuntu' and 'base' as in - # the core components and packages. - name = _("%s base") % utils.get_ubuntu_flavor_name(cache=cache) - icon = Gio.ThemedIcon.new("distributor-logo") - super(UpdateSystemGroup, self).__init__(None, name, icon, to_remove) - - -class UpdateOrigin(): - def __init__(self, desc, importance): - self.packages = [] - self.importance = importance - self.description = desc - - -class UpdateList(): - """ - class that contains the list of available updates in - self.pkgs[origin] where origin is the user readable string - """ - - # the key in the debian/control file used to add the phased - # updates percentage - PHASED_UPDATES_KEY = "Phased-Update-Percentage" - - # the file that contains the uniq machine id - UNIQ_MACHINE_ID_FILE = "/etc/machine-id" - # use the dbus one as a fallback - UNIQ_MACHINE_ID_FILE_FALLBACK = "/var/lib/dbus/machine-id" - - APP_INSTALL_PATTERN = "/usr/share/app-install/desktop/%s:*.desktop" - - # the configuration key to turn phased-updates always on - ALWAYS_INCLUDE_PHASED_UPDATES = ( - "Update-Manager::Always-Include-Phased-Updates") - # ... or always off - NEVER_INCLUDE_PHASED_UPDATES = ( - "Update-Manager::Never-Include-Phased-Updates") - - def __init__(self, parent, dist=None): - self.dist = (dist if dist else utils.get_dist()) - self.distUpgradeWouldDelete = 0 - self.update_groups = [] - self.random = random.Random() - - #FIXME: 最好将这个常量通过配置文件读 - self.GROUPS_JSON_PKG = 'kylin-update-desktop-config' - - self.INPUT_CONFIG_PATH = '/usr/share/kylin-update-desktop-config/data' - self.OUTPUT_CONFIG_PATH = os.getenv('HOME') + '/.config' +'/update_manager_config' - - self.IMPORTANT_LIST_PATH="/var/lib/kylin-software-properties/template/important.list" - - # important推送列表 - self.important_list = [] - - #所有的组升级安装列表 - self.local_upgrade_list = {} - # a stable machine uniq id - try: - with open(self.UNIQ_MACHINE_ID_FILE) as f: - self.machine_uniq_id = f.read() - except FileNotFoundError: - with open(self.UNIQ_MACHINE_ID_FILE_FALLBACK) as f: - self.machine_uniq_id = f.read() - - if 'XDG_DATA_DIRS' in os.environ and os.environ['XDG_DATA_DIRS']: - data_dirs = os.environ['XDG_DATA_DIRS'] - else: - data_dirs = '/usr/local/share/:/usr/share/' - - #FIX 此处需要修复 application_dirs 包含正确的desktop文件的目录 - self.application_dirs = [os.path.join(base, 'applications') - for base in data_dirs.split(':')] - - if 'XDG_CURRENT_DESKTOP' in os.environ: - self.current_desktop = os.environ.get('XDG_CURRENT_DESKTOP') - else: - self.current_desktop = '' - self.desktop_cache = {} - - def _file_is_application(self, file_path): - # WARNING: This is called often if there's a lot of updates. A poor - # performing call here has a huge impact on the overall performance! - #通过判断包的配置文件是否存在.desktop - if not file_path.endswith(".desktop"): - # First the obvious case: If the path doesn't end in a .desktop - # extension, this isn't a desktop file. - return False - - #通过判断.desktop 文件是否在/usr/share/applications 里面 表示属于应用 - file_path = os.path.abspath(file_path) - for app_dir in self.application_dirs: - if file_path.startswith(app_dir): - return True - return False - - def _rate_application_for_package(self, application, pkg): - score = 0 - desktop_file = os.path.basename(application.get_filename()) - application_id = os.path.splitext(desktop_file)[0] - - if application.should_show(): - score += 1 - - if application_id == pkg.name: - score += 5 - - return score - - def _get_application_for_package(self, pkg): - desktop_files = [] - rated_applications = [] - - #拿到应用的desktop文件判断为一个应用 - for installed_file in pkg.installed_files: - if self._file_is_application(installed_file): - desktop_files.append(installed_file) - #此部分强制进行添加应用 - if pkg.name in self.desktop_cache: - desktop_files += self.desktop_cache[pkg.name] - - for desktop_file in desktop_files: - try: - application = Gio.DesktopAppInfo.new_from_filename( - desktop_file) - application.set_desktop_env(self.current_desktop) - except Exception as e: - logging.warning("Error loading .desktop file %s: %s" % - (desktop_file, e)) - continue - score = self._rate_application_for_package(application, pkg) - if score > 0: - rated_applications.append((score, application)) - - rated_applications.sort(key=lambda app: app[0], reverse=True) - if len(rated_applications) > 0: - return rated_applications[0][1] - else: - return None - - def _populate_desktop_cache(self, pkg_names): - if not pkg_names: - # No updates; This shouldn't have happened. - logging.warning("_populate_desktop_cache called with empty list " - "of packages.") - return - elif len(pkg_names) == 1: - # One update; Let glob do the matching. - pattern = self.APP_INSTALL_PATTERN % pkg_names[0] - else: - # More than one update available. Glob all desktop files and store - # those that match an upgradeable package. - pattern = self.APP_INSTALL_PATTERN % "*" - - for desktop_file in glob.iglob(pattern): - try: - pkg = desktop_file.split('/')[-1].split(":")[0] - except IndexError: - # app-install-data desktop file had an unexpected naming - # convention. As we can't extract the package name from - # the path, just ignore it. - logging.error("Could not extract package name from '%s'. " - "File ignored." % desktop_file) - continue - - if pkg in pkg_names: - self.desktop_cache.setdefault(pkg, []).append(desktop_file) - logging.debug("App candidate for %s: %s" % - (pkg, desktop_file)) - - def _is_security_update(self, pkg): - """ This will test if the pkg is a security update. - This includes if there is a newer version in -updates, but also - an older update available in -security. For example, if - installed pkg A v1.0 is available in both -updates (as v1.2) and - -security (v1.1). we want to display it as a security update. - - :return: True if the update comes from the security pocket - """ - if not self.dist: - return False - inst_ver = pkg._pkg.current_ver - for ver in pkg._pkg.version_list: - # discard is < than installed ver - if (inst_ver - and apt.apt_pkg.version_compare(ver.ver_str, - inst_ver.ver_str) <= 0): - continue - # check if we have a match - for (verFileIter, index) in ver.file_list: - if verFileIter.archive == "%s-security" % self.dist and \ - verFileIter.origin == "Ubuntu": - indexfile = pkg._pcache._list.find_index(verFileIter) - if indexfile: # and indexfile.IsTrusted: - return True - return False - - def _is_ignored_phased_update(self, pkg): - """ This will test if the pkg is a phased update and if - it needs to get installed or ignored. - - :return: True if the updates should be ignored - """ - # allow the admin to override this - if apt.apt_pkg.config.find_b( - self.ALWAYS_INCLUDE_PHASED_UPDATES, False): - return False - - if self.PHASED_UPDATES_KEY in pkg.candidate.record: - if apt.apt_pkg.config.find_b( - self.NEVER_INCLUDE_PHASED_UPDATES, False): - logging.info("holding back phased update per configuration") - return True - - # its important that we always get the same result on - # multiple runs of the update-manager, so we need to - # feed a seed that is a combination of the pkg/ver/machine - self.random.seed("%s-%s-%s" % ( - pkg.candidate.source_name, pkg.candidate.version, - self.machine_uniq_id)) - threshold = pkg.candidate.record[self.PHASED_UPDATES_KEY] - percentage = self.random.randint(0, 100) - if percentage > int(threshold): - logging.info("holding back phased update %s (%s < %s)" % ( - pkg.name, threshold, percentage)) - return True - return False - - def _get_linux_packages(self): - "Return all binary packages made by the linux-meta source package" - # Hard code this rather than generate from source info in cache because - # that might only be available if we have deb-src lines. I think we - # could also generate it by iterating over all the binary package info - # we have, but that is costly. These don't change often. - return ['linux', - 'linux-cloud-tools-generic', - 'linux-cloud-tools-lowlatency', - 'linux-cloud-tools-virtual', - 'linux-crashdump', - 'linux-generic', - 'linux-generic-lpae', - 'linux-headers-generic', - 'linux-headers-generic-lpae', - 'linux-headers-lowlatency', - 'linux-headers-lowlatency-lpae', - 'linux-headers-server', - 'linux-headers-virtual', - 'linux-image', - 'linux-image-extra-virtual', - 'linux-image-generic', - 'linux-image-generic-lpae', - 'linux-image-lowlatency', - 'linux-image-virtual', - 'linux-lowlatency', - 'linux-signed-generic', - 'linux-signed-image-generic', - 'linux-signed-image-lowlatency', - 'linux-signed-lowlatency', - 'linux-source', - 'linux-tools-generic', - 'linux-tools-generic-lpae', - 'linux-tools-lowlatency', - 'linux-tools-virtual', - 'linux-virtual'] - - def _make_groups(self, cache, pkgs, eventloop_callback, to_remove=False): - if not pkgs: - return [] - ungrouped_pkgs = [] - app_groups = [] - pkg_groups = [] - - for pkg in pkgs: - #查看这个包属于那个应用的 并获取这个应用的一些属性 例如 应用名称和图标的等等 - app = self._get_application_for_package(pkg) - if app is not None: - #包含 应用名称和图标 - app_group = UpdateApplicationGroup(pkg, app, to_remove) - app_groups.append(app_group) - else: - ungrouped_pkgs.append(pkg) - - # Stick together applications and their immediate dependencies - #将应用和它们的依赖关系 结合在一起 - for pkg in list(ungrouped_pkgs): - dep_groups = [] - for group in app_groups: - if group.is_dependency(pkg, cache, eventloop_callback): - dep_groups.append(group) - if len(dep_groups) > 1: - break - #此来决定是这一个包所独有的依赖 如果一个依赖存在2个以上的就不 - if len(dep_groups) == 1: - dep_groups[0].add(pkg, cache, eventloop_callback, to_remove) - ungrouped_pkgs.remove(pkg) - - system_group = None - if ungrouped_pkgs: - # Separate out system base packages. If we have already found an - # application for all updates, don't bother. - meta_group = UpdateGroup(None, None, None, to_remove) - flavor_package = utils.get_ubuntu_flavor_package(cache=cache) - meta_pkgs = [flavor_package, "ubuntu-standard", "ubuntu-minimal"] - meta_pkgs.extend(self._get_linux_packages()) - for pkg in meta_pkgs: - if pkg in cache: - meta_group.add(cache[pkg]) - for pkg in ungrouped_pkgs: - if meta_group.is_dependency(pkg, cache, eventloop_callback): - if system_group is None: - system_group = UpdateSystemGroup(cache, to_remove) - system_group.add(pkg) - else: - pkg_groups.append(UpdatePackageGroup(pkg, to_remove)) - - app_groups.sort(key=lambda a: a.name.lower()) - pkg_groups.sort(key=lambda a: a.name.lower()) - if system_group: - pkg_groups.append(system_group) - - return app_groups + pkg_groups - - def _read_important_list(self): - header = '' - desc = '' - # 获取importantlist 本次更新推送 - try: - with open(self.IMPORTANT_LIST_PATH, 'r') as f: - data = f.read() - self.important_list = data.split() - logging.info("importantList: %s",self.important_list) - return True - except Exception as e: - header = _("read important list failed") - desc = ("%s",str(e)) - logging.info(header + desc) - return False,header,desc - - def _make_pkg_info_json(self,cache,pkgs_list): - size = 0 - total_size = 0 - pkgs_info_json = {} - for pkg_name in pkgs_list: - try: - pkg = cache[pkg_name] - - #获取下载大小 - size = getattr(pkg.candidate, "size", 0) - total_size = total_size + size - pkgs_info_json.update({pkg_name:{"size":size}}) - except Exception as e: - logging.info("this package(%s) not in list and error mes:%s",pkg_name,e) - pass - pkgs_info_json.update({"total_size":humanize_size(total_size)}) - return pkgs_info_json - - #检查包是否在cache中 返回新得列表 - def _check_pkg_in_cache(self,cache,pkgs_list): - new_pkgs_list = [] - for pkg_name in pkgs_list: - #检查是否在cache 以及 是否安装检查 - if pkg_name in cache and not cache[pkg_name].is_installed: - new_pkgs_list.append(pkg_name) - else: - pass - # logging.info("this package(%s) not in list ",pkg_name) - return new_pkgs_list - - def _make_output_json(self,data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list): - groups_base_info = {} - output_json = {} - - #FIXME: 确定输出文件的文件名 以及放置位置 - output_config_name = self.OUTPUT_CONFIG_PATH + '/' + data['package'] + '_output.json' - - #4、添加一些基础信息 - groups_base_info.update({"package":data['package']}) - groups_base_info.update({"version":data['version']}) - groups_base_info.update({"name":data['name']}) - groups_base_info.update({"description":data['description']}) - groups_base_info.update({"icon":data['icon']}) - - #5、添加升级的内容 - output_json.update(groups_base_info) - output_json.update({"upgrade_list":upgrade_pkgs_json}) - output_json.update({"install_list":install_pkgs_json}) - output_json.update({"hold_list":hold_pkgs_list}) - output_json.update({"remove_list":remove_pkgs_list}) - - #6 产生JSON文件 - with open(output_config_name, 'w', encoding='utf-8') as f: - json.dump(output_json, f, ensure_ascii=False, indent=4) - logging.info("Generate Jsonfile(%s) to complete... ",output_config_name) - - def _make_groups_upgrade(self,cache,pkgs_install = [], pkgs_upgrade = [], pkgs_remove = []): - try: - files = os.listdir(self.INPUT_CONFIG_PATH) #获得文件夹中所有文件的名称列表 - upgrade_groups_list = [] - - for file in files: - #判是否是目录以及是否以JSON结尾 - if file.endswith('.json'): - with open(self.INPUT_CONFIG_PATH+"/"+file,'r') as f: - data = json.load(f) - group_name = data['package'] - - #过滤没有推送的配置文件 - if not group_name in self.important_list: - continue - - upgrade_pkgs_list = data['upgrade_list'] - hold_pkgs_list = data['hold_list'] - - #这个安装升级列表中包含当前系统的cache中没有的包 需要过滤 - remove_pkgs_list = data['remove_list'] - - #检查包是否在cache中 以及是否已经安装 - new_install_pkgs_list = self._check_pkg_in_cache(cache,data['install_list']) - - #进行交集 升级列表 - upgrade_intersection_pkgs = list(set(pkgs_upgrade) & set(upgrade_pkgs_list)) - - #判断当前是否可升级或者新装的包 - if len(new_install_pkgs_list) == 0 and len(upgrade_intersection_pkgs) == 0: - continue - - #在总升级列表中移除这些包 - for pkg in upgrade_intersection_pkgs: - pkgs_upgrade.remove(pkg) - - #3、生成升级的包列表JSON - upgrade_pkgs_json = self._make_pkg_info_json(cache,upgrade_intersection_pkgs) - - #2、生成安装的软件列表 - install_pkgs_json = self._make_pkg_info_json(cache,new_install_pkgs_list) - - #输出JSON配置文件 - self._make_output_json(data,upgrade_pkgs_json,install_pkgs_json,hold_pkgs_list,remove_pkgs_list) - - upgrade_groups_list.append(group_name) - - #添加到字典维护的升级列表 - self.local_upgrade_list.update({group_name:{"pkgs_upgrade":upgrade_intersection_pkgs,"pkgs_install":new_install_pkgs_list}}) - logging.info("group(%s) upgrade:%d install:%d",group_name,len(upgrade_intersection_pkgs),len(new_install_pkgs_list)) - else: - pass - #添加所有可升级的组列表 - self.local_upgrade_list.update({"upgrade_groups_list":upgrade_groups_list}) - except Exception as e: - logging.warning("Generate Jsonfile to failed... ") - logging.error(e) - - - def update(self, cache, eventloop_callback=None): - pkgs_install = [] - pkgs_upgrade = [] - pkgs_remove = [] - - header = '' - desc = '' - - self._read_important_list() - - #important_list 为空时此次不需要升级 - if not self.important_list: - #不需要升级 全部的软件都是新的 - header = _("No software updates are available.") - desc = _('important_list is Empty') - return True,header,desc - - #查找所有可升级的包 - for pkg in cache: - try: - if pkg.marked_install: - pkgs_install.append(pkg) - elif pkg.marked_upgrade: - pkgs_upgrade.append(pkg) - elif pkg.marked_delete: - pkgs_remove.append(pkg) - except Exception as e: - logging.error(e) - logging.info("System all upgradeable packages:new_install:%d upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) - - #源过滤 - # fu = filter.UpdateListFilterCache() - # allowed_origin_upgrade_pkgs = fu.check_in_allowed_origin(pkgs_upgrade) - - self._make_groups_upgrade(cache,pkgs_upgrade = ([pkg.name for pkg in pkgs_upgrade])) - - #是否存在可升级的组 - if self.local_upgrade_list.get('upgrade_groups_list',[]): - #增加需要移除的包列表 - self.local_upgrade_list.update({"pkgs_remove":[pkg.name for pkg in pkgs_remove]}) - return True,header,desc - else: - #不需要升级 全部的软件都是新的 - header = _("The software on this computer is up to date.") - desc = '' - return True,header,desc - - #FIXME: 目前此功能不使用 但是以此按应用进行分组是更好的展示升级列表的方式 - # self.update_groups = self._make_groups(cache, self.pkgs_upgrade, - # eventloop_callback) \ No newline at end of file diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/__init__.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/filter.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/filter.py deleted file mode 100644 index a2c1671..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/filter.py +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/python3 - -import apt -import apt_pkg -import fnmatch -import logging -import logging.handlers -import re -import os -import string -import subprocess -import sys -import json -import dbus -import threading - -try: - from typing import AbstractSet, cast, DefaultDict, Dict, Iterable, List - AbstractSet # pyflakes - DefaultDict # pyflakes - Dict # pyflakes - Iterable # pyflakes - List # pyflakes - from typing import Set, Tuple, Union - Set # pyflakes - Tuple # pyflakes - Union # pyflakes -except ImportError: - pass - -from email.message import Message -from gettext import gettext as _ - -import apt -import apt_pkg - - -ImportantListPath="/var/lib/kylin-software-properties/template/important.list" -DesktopSystemPath="/usr/share/kylin-update-desktop-config/data/" - - -# no py3 lsb_release in debian :/ -DISTRO_CODENAME = subprocess.check_output( - ["lsb_release", "-c", "-s"], universal_newlines=True).strip() # type: str -DISTRO_DESC = subprocess.check_output( - ["lsb_release", "-d", "-s"], universal_newlines=True).strip() # type: str -DISTRO_ID = subprocess.check_output( - ["lsb_release", "-i", "-s"], universal_newlines=True).strip() # type: str - - -class UpdateListFilterCache(apt.Cache): - - def __init__(self): - # whitelist - self.upgradeList = [] - # 必须升级的包 - self.installList = [] - # self._cached_candidate_pkgnames = set() # type: Set[str] - - self.allowed_origins = get_allowed_origins() - self.allowed_origins = deleteDuplicatedElementFromList(self.allowed_origins) - logging.info("Allowed origins are: %s", - self.allowed_origins) - - self.blacklist = apt_pkg.config.value_list( - "Kylin-update-manager::Package-Blacklist") - self.blacklist = deleteDuplicatedElementFromList(self.blacklist) - # print("Initial blacklist: ", " ".join(self.blacklist)) - - self.whitelist = apt_pkg.config.value_list( - "Kylin-update-manager::Package-Whitelist") - self.whitelist = deleteDuplicatedElementFromList(self.whitelist) - # print("Initial whitelist: ", " ".join(self.whitelist)) - - self.strict_whitelist = apt_pkg.config.find_b( - "Kylin-update-manager::Package-Whitelist-Strict", False) - # print("Initial whitelist (%s): %s"%( - # "strict" if self.strict_whitelist else "not strict", - # " ".join(self.whitelist))) - - # update importantlist - # initUpdateImportantList() - - # 获取list - # self.initLocalPackagesList() - - #除掉不在cache中的包 - # self.checkInCache() - - def checkInCache(self): - logging.info("start Check in cache") - tmplist = [] - cache = apt.Cache() - for i in self.upgradeList: - try: - cache[i] - tmplist.append(i) - except Exception as e: - # print("not found pkg: ", str(e)) - pass - self.upgradeList = tmplist - - def initLocalPackagesList(self): - jsonfiles = [] - tmplist = [] - - # 获取importantlist 本次更新推送 - with open(ImportantListPath, 'r') as f: - text = f.read() - importantList = text.split() - logging.info("importantList: %s",importantList) - f.close() - - if not importantList: - logging.error("importantList is empty") - exit(-1) - - # 获取/usr/share/kylin-update-desktop-config/data/下所有json文件 - for root,dirs,files in os.walk(DesktopSystemPath): - pass - for i in files: - if ".json" in i: - jsonfiles.append(i.split('.')[0]) - # logging.info("all files: %s", jsonfiles) - - # 找到importantlist中对应的json文件 - for i in importantList: - if i not in jsonfiles: - # 说明这个是单独的包,不在分组中 - # 加入更新列表 - if i not in self.upgradeList: - self.upgradeList.append(i) - else: - # 在分组中 - # 获取每个对应json文件中的upgrade_list - if i in jsonfiles: - filepath = os.path.join(DesktopSystemPath, i) - filepath = filepath+".json" - with open(filepath, 'r') as f: - pkgdict = f.read() - jsonfile = json.loads(pkgdict) - tmplist = jsonfile['install_list'] - # print("\ntmplist: ", tmplist) - for j in tmplist: - if j not in self.upgradeList: - self.upgradeList.append(j) - f.close() - # logging.info("self.upgradeList: %s", self.upgradeList) - - - def check_in_allowed_origin(self, pkgs): - new_upgrade_pkgs = [] - for pkg in pkgs: - # print("checking %d pkgname: %s"%(i, pkg)) - for v in pkg.versions: - if is_in_allowed_origin(v, self.allowed_origins) and not pkg in new_upgrade_pkgs: - new_upgrade_pkgs.append(pkg) - # else: - # pkg.mark_keep() - return new_upgrade_pkgs - - def is_pkgname_in_blacklist(self, pkgs): - blacklist_filter_pkgs = [] - for pkg in pkgs: - if pkg.name in self.blacklist: - pass - # print("skipping blacklisted package %s" % pkg.name) - else : - blacklist_filter_pkgs.append(pkg) - - return blacklist_filter_pkgs - - def is_pkgname_in_whitelist(self, pkgs): - whitelist_filter_upgrade_pkgs = [] - for pkg in pkgs: - if pkg.name in self.upgradeList: - whitelist_filter_upgrade_pkgs.append(pkg) - else : - pkg.mark_keep() - pass - # print("skipping whitelist package %s" % pkg.name) - - return whitelist_filter_upgrade_pkgs - - -def get_allowed_origins(): - # type: () -> List[str] - """ return a list of allowed origins from apt.conf - - This will take substitutions (like distro_id) into account. - """ - allowed_origins = get_allowed_origins_legacy() - key = "Kylin-update-manager::Origins-Pattern" - try: - for s in apt_pkg.config.value_list(key): - allowed_origins.append(substitute(s)) - except ValueError: - print("Unable to parse %s." % key) - raise - return allowed_origins - -def get_allowed_origins_legacy(): - # type: () -> List[str] - """ legacy support for old Allowed-Origins var """ - allowed_origins = [] # type: List[str] - key = "Kylin-update-manager::Allowed-Origins" - try: - for s in apt_pkg.config.value_list(key): - # if there is a ":" use that as seperator, else use spaces - if re.findall(r'(? str - """ substitude known mappings and return a new string - - Currently supported ${distro-release} - """ - mapping = {"distro_codename": get_distro_codename(), - "distro_id": get_distro_id()} - return string.Template(line).substitute(mapping) - - -def get_distro_codename(): - # type: () -> str - return DISTRO_CODENAME - - -def get_distro_id(): - # type: () -> str - return DISTRO_ID - -def is_in_allowed_origin(ver, allowed_origins): - # type: (apt.package.Version, List[str]) -> bool - if not ver: - return False - for origin in ver.origins: - if is_allowed_origin(origin, allowed_origins): - return True - return False - -def is_allowed_origin(origin, allowed_origins): - # type: (Union[apt.package.Origin, apt_pkg.PackageFile], List[str]) -> bool - - # local origin is allowed by default - # if origin.component == 'now' and origin.archive == 'now' and \ - # not origin.label and not origin.site: - # return True - for allowed in allowed_origins: - if match_whitelist_string(allowed, origin): - return True - return False - -def match_whitelist_string(whitelist, origin): - # type: (str, Union[apt.package.Origin, apt_pkg.PackageFile]) -> bool - """ - take a whitelist string in the form "origin=Debian,label=Debian-Security" - and match against the given python-apt origin. A empty whitelist string - never matches anything. - """ - whitelist = whitelist.strip() - if whitelist == "": - logging.warning("empty match string matches nothing") - return False - res = True - # make "\," the html quote equivalent - whitelist = whitelist.replace("\\,", "%2C") - for token in whitelist.split(","): - # strip and unquote the "," back - (what, value) = [s.strip().replace("%2C", ",") - for s in token.split("=")] - # logging.debug("matching %s=%s against %s" % ( - # what, value, origin)) - # support substitution here as well - value = substitute(value) - # first char is apt-cache policy output, send is the name - # in the Release file - if what in ("o", "origin"): - match = fnmatch.fnmatch(origin.origin, value) - elif what in ("l", "label"): - match = fnmatch.fnmatch(origin.label, value) - elif what in ("a", "suite", "archive"): - match = fnmatch.fnmatch(origin.archive, value) - elif what in ("c", "component"): - match = fnmatch.fnmatch(origin.component, value) - elif what in ("site",): - match = fnmatch.fnmatch(origin.site, value) - elif what in ("n", "codename",): - match = fnmatch.fnmatch(origin.codename, value) - else: - raise UnknownMatcherError( - "Unknown whitelist entry for matcher %s (token %s)" % ( - what, token)) - # update res - res = res and match - # logging.debug("matching %s=%s against %s" % ( - # what, value, origin)) - return res - -def deleteDuplicatedElementFromList(list): - resultList = [] - for item in list: - if not item in resultList: - resultList.append(item) - return resultList - - -class UnknownMatcherError(ValueError): - pass \ No newline at end of file diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/roam.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/roam.py deleted file mode 100644 index 0714d89..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/roam.py +++ /dev/null @@ -1,212 +0,0 @@ -# utils.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2011 Canonical -# -# Author: Alex Chiang -# Michael Vogt -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - - -from __future__ import print_function - -import dbus -import sys - - -class ModemManagerHelper(object): - - # data taken from - # http://projects.gnome.org/NetworkManager/developers/mm-spec-04.html - MM_DBUS_IFACE = "org.freedesktop.ModemManager" - MM_DBUS_IFACE_MODEM = MM_DBUS_IFACE + ".Modem" - - # MM_MODEM_TYPE - MM_MODEM_TYPE_GSM = 1 - MM_MODEM_TYPE_CDMA = 2 - - # GSM - # Not registered, not searching for new operator to register. - MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE = 0 - # Registered on home network. - MM_MODEM_GSM_NETWORK_REG_STATUS_HOME = 1 - # Not registered, searching for new operator to register with. - MM_MODEM_GSM_NETWORK_REG_STATUS_SEARCHING = 2 - # Registration denied. - MM_MODEM_GSM_NETWORK_REG_STATUS_DENIED = 3 - # Unknown registration status. - MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN = 4 - # Registered on a roaming network. - MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING = 5 - - # CDMA - # Registration status is unknown or the device is not registered. - MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN = 0 - # Registered, but roaming status is unknown or cannot be provided - # by the device. The device may or may not be roaming. - MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED = 1 - # Currently registered on the home network. - MM_MODEM_CDMA_REGISTRATION_STATE_HOME = 2 - # Currently registered on a roaming network. - MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING = 3 - - def __init__(self): - self.bus = dbus.SystemBus() - self.proxy = self.bus.get_object("org.freedesktop.ModemManager", - "/org/freedesktop/ModemManager") - modem_manager = dbus.Interface(self.proxy, self.MM_DBUS_IFACE) - self.modems = modem_manager.EnumerateDevices() - - @staticmethod - def get_dbus_property(proxy, interface, property): - props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties") - property = props.Get(interface, property) - return property - - def is_gsm_roaming(self): - for m in self.modems: - dev = self.bus.get_object(self.MM_DBUS_IFACE, m) - type = self.get_dbus_property(dev, self.MM_DBUS_IFACE_MODEM, - "Type") - if type != self.MM_MODEM_TYPE_GSM: - continue - net = dbus.Interface(dev, - self.MM_DBUS_IFACE_MODEM + ".Gsm.Network") - reg = net.GetRegistrationInfo() - # Be conservative about roaming. If registration unknown, - # assume yes. - # MM_MODEM_GSM_NETWORK_REG_STATUS - if reg[0] in (self.MM_MODEM_GSM_NETWORK_REG_STATUS_UNKNOWN, - self.MM_MODEM_GSM_NETWORK_REG_STATUS_ROAMING): - return True - return False - - def is_cdma_roaming(self): - for m in self.modems: - dev = self.bus.get_object(self.MM_DBUS_IFACE, m) - type = self.get_dbus_property(dev, self.MM_DBUS_IFACE_MODEM, - "Type") - if type != self.MM_MODEM_TYPE_CDMA: - continue - cdma = dbus.Interface(dev, self.MM_DBUS_IFACE_MODEM + ".Cdma") - (cmda_1x, evdo) = cdma.GetRegistrationState() - # Be conservative about roaming. If registration unknown, - # assume yes. - # MM_MODEM_CDMA_REGISTRATION_STATE - roaming_states = (self.MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED, - self.MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING) - # evdo trumps cmda_1x (thanks to Mathieu Trudel-Lapierre) - if evdo in roaming_states: - return True - elif cmda_1x in roaming_states: - return True - return False - - -class NetworkManagerHelper(object): - NM_DBUS_IFACE = "org.freedesktop.NetworkManager" - - # connection states - # Old enum values are for NM 0.7 - - # The NetworkManager daemon is in an unknown state. - NM_STATE_UNKNOWN = 0 - # The NetworkManager daemon is connecting a device. - NM_STATE_CONNECTING_OLD = 2 - NM_STATE_CONNECTING = 40 - NM_STATE_CONNECTING_LIST = [NM_STATE_CONNECTING_OLD, - NM_STATE_CONNECTING] - # The NetworkManager daemon is connected. - NM_STATE_CONNECTED_OLD = 3 - NM_STATE_CONNECTED_LOCAL = 50 - NM_STATE_CONNECTED_SITE = 60 - NM_STATE_CONNECTED_GLOBAL = 70 - NM_STATE_CONNECTED_LIST = [NM_STATE_CONNECTED_OLD, - NM_STATE_CONNECTED_LOCAL, - NM_STATE_CONNECTED_SITE, - NM_STATE_CONNECTED_GLOBAL] - - # The device type is unknown. - NM_DEVICE_TYPE_UNKNOWN = 0 - # The device is wired Ethernet device. - NM_DEVICE_TYPE_ETHERNET = 1 - # The device is an 802.11 WiFi device. - NM_DEVICE_TYPE_WIFI = 2 - # The device is a GSM-based cellular WAN device. - NM_DEVICE_TYPE_GSM = 3 - # The device is a CDMA/IS-95-based cellular WAN device. - NM_DEVICE_TYPE_CDMA = 4 - - def __init__(self): - self.bus = dbus.SystemBus() - self.proxy = self.bus.get_object("org.freedesktop.NetworkManager", - "/org/freedesktop/NetworkManager") - - @staticmethod - def get_dbus_property(proxy, interface, property): - props = dbus.Interface(proxy, "org.freedesktop.DBus.Properties") - property = props.Get(interface, property) - return property - - def is_active_connection_gsm_or_cdma(self): - res = False - actives = self.get_dbus_property( - self.proxy, self.NM_DBUS_IFACE, 'ActiveConnections') - for a in actives: - active = self.bus.get_object(self.NM_DBUS_IFACE, a) - default_route = self.get_dbus_property( - active, self.NM_DBUS_IFACE + ".Connection.Active", 'Default') - if not default_route: - continue - devs = self.get_dbus_property( - active, self.NM_DBUS_IFACE + ".Connection.Active", 'Devices') - for d in devs: - dev = self.bus.get_object(self.NM_DBUS_IFACE, d) - type = self.get_dbus_property( - dev, self.NM_DBUS_IFACE + ".Device", 'DeviceType') - if type == self.NM_DEVICE_TYPE_GSM: - return True - elif type == self.NM_DEVICE_TYPE_CDMA: - return True - else: - continue - return res - - def is_active_connection_gsm_or_cdma_roaming(self): - res = False - if self.is_active_connection_gsm_or_cdma(): - mmhelper = ModemManagerHelper() - res |= mmhelper.is_gsm_roaming() - res |= mmhelper.is_cdma_roaming() - return res - - -if __name__ == "__main__": - - # test code - if sys.argv[1:] and sys.argv[1] == "--test": - mmhelper = ModemManagerHelper() - print("is_gsm_roaming", mmhelper.is_gsm_roaming()) - print("is_cdma_romaing", mmhelper.is_cdma_roaming()) - - # roaming? - nmhelper = NetworkManagerHelper() - is_roaming = nmhelper.is_active_connection_gsm_or_cdma_roaming() - print("roam: ", is_roaming) - if is_roaming: - sys.exit(1) - sys.exit(0) diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/utils.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/utils.py deleted file mode 100644 index 103f8bf..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/Core/utils.py +++ /dev/null @@ -1,557 +0,0 @@ -# utils.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- -# -# Copyright (c) 2004-2013 Canonical -# -# Authors: Michael Vogt -# Michael Terry -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA - -from __future__ import print_function - -from gettext import gettext as _ -from gettext import ngettext -from stat import (S_IMODE, ST_MODE, S_IXUSR) -from math import ceil - -import apt -import apt_pkg -apt_pkg.init_config() - -import locale -import logging -import re -import os -import subprocess -import sys -import time -from urllib.request import ( - ProxyHandler, - Request, - build_opener, - install_opener, - urlopen, -) -from urllib.parse import urlsplit - -from copy import copy - - -class ExecutionTime(object): - """ - Helper that can be used in with statements to have a simple - measure of the timing of a particular block of code, e.g. - with ExecutionTime("db flush"): - db.flush() - """ - def __init__(self, info=""): - self.info = info - - def __enter__(self): - self.now = time.time() - - def __exit__(self, type, value, stack): - print("%s: %s" % (self.info, time.time() - self.now)) - - -def get_string_with_no_auth_from_source_entry(entry): - tmp = copy(entry) - url_parts = urlsplit(tmp.uri) - if url_parts.username: - tmp.uri = tmp.uri.replace(url_parts.username, "hidden-u") - if url_parts.password: - tmp.uri = tmp.uri.replace(url_parts.password, "hidden-p") - return str(tmp) - - -def is_unity_running(): - """ return True if Unity is currently running """ - unity_running = False - try: - import dbus - bus = dbus.SessionBus() - unity_running = bus.name_has_owner("com.canonical.Unity") - except Exception: - logging.exception("could not check for Unity dbus service") - return unity_running - - -def is_child_of_process_name(processname, pid=None): - if not pid: - pid = os.getpid() - while pid > 0: - stat_file = "/proc/%s/stat" % pid - with open(stat_file) as stat_f: - stat = stat_f.read() - # extract command (inside ()) - command = stat.partition("(")[2].rpartition(")")[0] - if command == processname: - return True - # get parent (second to the right of command) and check that next - pid = int(stat.rpartition(")")[2].split()[1]) - return False - - -def inside_chroot(): - """ returns True if we are inside a chroot - """ - # if there is no proc or no pid 1 we are very likely inside a chroot - if not os.path.exists("/proc") or not os.path.exists("/proc/1"): - return True - # if the inode is differnt for pid 1 "/" and our "/" - return os.stat("/") != os.stat("/proc/1/root") - - -def wrap(t, width=70, subsequent_indent=""): - """ helpers inspired after textwrap - unfortunately - we can not use textwrap directly because it break - packagenames with "-" in them into new lines - """ - out = "" - for s in t.split(): - if (len(out) - out.rfind("\n")) + len(s) > width: - out += "\n" + subsequent_indent - out += s + " " - return out - - -def twrap(s, **kwargs): - msg = "" - paras = s.split("\n") - for par in paras: - s = wrap(par, **kwargs) - msg += s + "\n" - return msg - - -def lsmod(): - " return list of loaded modules (or [] if lsmod is not found) " - modules = [] - # FIXME raise? - if not os.path.exists("/sbin/lsmod"): - return [] - p = subprocess.Popen(["/sbin/lsmod"], stdout=subprocess.PIPE, - universal_newlines=True) - lines = p.communicate()[0].split("\n") - # remove heading line: "Modules Size Used by" - del lines[0] - # add lines to list, skip empty lines - for line in lines: - if line: - modules.append(line.split()[0]) - return modules - - -def check_and_fix_xbit(path): - " check if a given binary has the executable bit and if not, add it" - if not os.path.exists(path): - return - mode = S_IMODE(os.stat(path)[ST_MODE]) - if not ((mode & S_IXUSR) == S_IXUSR): - os.chmod(path, mode | S_IXUSR) - - -def country_mirror(): - " helper to get the country mirror from the current locale " - # special cases go here - lang_mirror = {'c': ''} - # no lang, no mirror - if 'LANG' not in os.environ: - return '' - lang = os.environ['LANG'].lower() - # check if it is a special case - if lang[:5] in lang_mirror: - return lang_mirror[lang[:5]] - # now check for the most comon form (en_US.UTF-8) - if "_" in lang: - country = lang.split(".")[0].split("_")[1] - if "@" in country: - country = country.split("@")[0] - return country + "." - else: - return lang[:2] + "." - return '' - - -def get_dist(): - " return the codename of the current runing distro " - # support debug overwrite - dist = os.environ.get("META_RELEASE_FAKE_CODENAME") - if dist: - logging.warning("using fake release name '%s' (because of " - "META_RELEASE_FAKE_CODENAME environment) " % dist) - return dist - # then check the real one - from subprocess import Popen, PIPE - p = Popen(["lsb_release", "-c", "-s"], stdout=PIPE, - universal_newlines=True) - res = p.wait() - if res != 0: - sys.stderr.write("lsb_release returned exitcode: %i\n" % res) - return "unknown distribution" - dist = p.stdout.readline().strip() - p.stdout.close() - return dist - - -def get_dist_version(): - " return the version of the current running distro " - # support debug overwrite - desc = os.environ.get("META_RELEASE_FAKE_VERSION") - if desc: - logging.warning("using fake release version '%s' (because of " - "META_RELEASE_FAKE_VERSION environment) " % desc) - return desc - # then check the real one - from subprocess import Popen, PIPE - p = Popen(["lsb_release", "-r", "-s"], stdout=PIPE, - universal_newlines=True) - res = p.wait() - if res != 0: - sys.stderr.write("lsb_release returned exitcode: %i\n" % res) - return "unknown distribution" - desc = p.stdout.readline().strip() - p.stdout.close() - return desc - - -class HeadRequest(Request): - def get_method(self): - return "HEAD" - - -def url_downloadable(uri, debug_func=None): - """ - helper that checks if the given uri exists and is downloadable - (supports optional debug_func function handler to support - e.g. logging) - - Supports http (via HEAD) and ftp (via size request) - """ - if not debug_func: - lambda x: True - debug_func("url_downloadable: %s" % uri) - (scheme, netloc, path, querry, fragment) = urlsplit(uri) - debug_func("s='%s' n='%s' p='%s' q='%s' f='%s'" % (scheme, netloc, path, - querry, fragment)) - if scheme in ("http", "https"): - try: - http_file = urlopen(HeadRequest(uri)) - http_file.close() - if http_file.code == 200: - return True - return False - except Exception as e: - debug_func("error from httplib: '%s'" % e) - return False - elif scheme == "ftp": - import ftplib - try: - f = ftplib.FTP(netloc) - f.login() - f.cwd(os.path.dirname(path)) - size = f.size(os.path.basename(path)) - f.quit() - if debug_func: - debug_func("ftplib.size() returned: %s" % size) - if size != 0: - return True - except Exception as e: - if debug_func: - debug_func("error from ftplib: '%s'" % e) - return False - return False - - -def init_proxy(gsettings=None): - """ init proxy settings - - * use apt.conf http proxy if present, - * otherwise look into synaptics config file, - * otherwise the default behavior will use http_proxy environment - if present - """ - SYNAPTIC_CONF_FILE = "/root/.synaptic/synaptic.conf" - proxies = {} - # generic apt config wins - if apt_pkg.config.find("Acquire::http::Proxy") != '': - proxies["http"] = apt_pkg.config.find("Acquire::http::Proxy") - # then synaptic - elif os.path.exists(SYNAPTIC_CONF_FILE): - cnf = apt_pkg.Configuration() - apt_pkg.read_config_file(cnf, SYNAPTIC_CONF_FILE) - use_proxy = cnf.find_b("Synaptic::useProxy", False) - if use_proxy: - proxy_host = cnf.find("Synaptic::httpProxy") - proxy_port = str(cnf.find_i("Synaptic::httpProxyPort")) - if proxy_host and proxy_port: - proxies["http"] = "http://%s:%s/" % (proxy_host, proxy_port) - if apt_pkg.config.find("Acquire::https::Proxy") != '': - proxies["https"] = apt_pkg.config.find("Acquire::https::Proxy") - elif "http" in proxies: - proxies["https"] = proxies["http"] - # if we have a proxy, set it - if proxies: - # basic verification - for proxy in proxies.values(): - if not re.match("https?://\\w+", proxy): - print("proxy '%s' looks invalid" % proxy, file=sys.stderr) - return - proxy_support = ProxyHandler(proxies) - opener = build_opener(proxy_support) - install_opener(opener) - if "http" in proxies: - os.putenv("http_proxy", proxies["http"]) - if "https" in proxies: - os.putenv("https_proxy", proxies["https"]) - return proxies - - -def on_battery(): - """ - Check via dbus if the system is running on battery. - This function is using UPower per default, if UPower is not - available it falls-back to DeviceKit.Power. - """ - try: - import dbus - bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - try: - devobj = bus.get_object('org.freedesktop.UPower', - '/org/freedesktop/UPower') - dev = dbus.Interface(devobj, 'org.freedesktop.DBus.Properties') - return dev.Get('org.freedesktop.UPower', 'OnBattery') - except dbus.exceptions.DBusException as e: - error_unknown = 'org.freedesktop.DBus.Error.ServiceUnknown' - if e._dbus_error_name != error_unknown: - raise - devobj = bus.get_object('org.freedesktop.DeviceKit.Power', - '/org/freedesktop/DeviceKit/Power') - dev = dbus.Interface(devobj, "org.freedesktop.DBus.Properties") - return dev.Get("org.freedesktop.DeviceKit.Power", "on_battery") - except Exception: - #import sys - #print("on_battery returned error: ", e, file=sys.stderr) - return False - - -def inhibit_sleep(): - """ - Send a dbus signal to logind to not suspend the system, it will be - released when the return value drops out of scope - """ - try: - from gi.repository import Gio, GLib - connection = Gio.bus_get_sync(Gio.BusType.SYSTEM) - - var, fdlist = connection.call_with_unix_fd_list_sync( - 'org.freedesktop.login1', '/org/freedesktop/login1', - 'org.freedesktop.login1.Manager', 'Inhibit', - GLib.Variant('(ssss)', - ('shutdown:sleep', - 'UpdateManager', 'Updating System', - 'block')), - None, 0, -1, None, None) - inhibitor = Gio.UnixInputStream(fd=fdlist.steal_fds()[var[0]]) - - return inhibitor - except Exception: - #print("could not send the dbus Inhibit signal: %s" % e) - return False - - -def str_to_bool(str): - if str == "0" or str.upper() == "FALSE": - return False - return True - - -def get_lang(): - import logging - try: - (locale_s, encoding) = locale.getdefaultlocale() - return locale_s - except Exception: - logging.exception("gedefaultlocale() failed") - return None - - -def get_ubuntu_flavor(cache=None): - """ try to guess the flavor based on the running desktop """ - # this will (of course) not work in a server environment, - # but the main use case for this is to show the right - # release notes. - pkg = get_ubuntu_flavor_package(cache=cache) - return pkg.split('-', 1)[0] - - -def _load_meta_pkg_list(): - # This could potentially introduce a circular dependency, but the config - # parser logic is simple, and doesn't rely on any UpdateManager code. - from DistUpgrade.DistUpgradeConfigParser import DistUpgradeConfig - parser = DistUpgradeConfig('/usr/share/ubuntu-release-upgrader') - return parser.getlist('Distro', 'MetaPkgs') - - -def get_ubuntu_flavor_package(cache=None): - """ try to guess the flavor metapackage based on the running desktop """ - # From spec, first if ubuntu-desktop is installed, use that. - # Second, grab first installed one from DistUpgrade.cfg. - # Lastly, fallback to ubuntu-desktop again. - meta_pkgs = ['ubuntu-desktop'] - - try: - meta_pkgs.extend(sorted(_load_meta_pkg_list())) - except Exception as e: - print('Could not load list of meta packages:', e) - - if cache is None: - cache = apt.Cache() - for meta_pkg in meta_pkgs: - cache_pkg = cache[meta_pkg] if meta_pkg in cache else None - if cache_pkg and cache_pkg.is_installed: - return meta_pkg - return 'ubuntu-desktop' - - -def get_ubuntu_flavor_name(cache=None): - """ try to guess the flavor name based on the running desktop """ - pkg = get_ubuntu_flavor_package(cache=cache) - lookup = {'ubuntustudio-desktop': 'Ubuntu Studio'} - if pkg in lookup: - return lookup[pkg] - elif pkg.endswith('-desktop'): - return capitalize_first_word(pkg.rsplit('-desktop', 1)[0]) - elif pkg.endswith('-netbook'): - return capitalize_first_word(pkg.rsplit('-netbook', 1)[0]) - else: - return 'Ubuntu' - - -# Unused by update-manager, but still used by ubuntu-release-upgrader -def error(parent, summary, message): - import gi - gi.require_version("Gtk", "3.0") - from gi.repository import Gtk, Gdk - d = Gtk.MessageDialog(parent=parent, - flags=Gtk.DialogFlags.MODAL, - type=Gtk.MessageType.ERROR, - buttons=Gtk.ButtonsType.CLOSE) - d.set_markup("%s\n\n%s" % (summary, message)) - d.realize() - d.get_window().set_functions(Gdk.WMFunction.MOVE) - d.set_title("") - d.run() - d.destroy() - return False - - -def humanize_size(bytes): - """ - Convert a given size in bytes to a nicer better readable unit - """ - - if bytes < 1000 * 1000: - # to have 0 for 0 bytes, 1 for 0-1000 bytes and for 1 and above - # round up - size_in_kb = int(ceil(bytes / float(1000))) - # TRANSLATORS: download size of small updates, e.g. "250 kB" - return ngettext("%(size).0f kB", "%(size).0f kB", size_in_kb) % { - "size": size_in_kb} - else: - # TRANSLATORS: download size of updates, e.g. "2.3 MB" - return locale.format_string(_("%.1f MB"), bytes / 1000.0 / 1000.0) - - -def get_arch(): - return apt_pkg.config.find("APT::Architecture") - - -def is_port_already_listening(port): - """ check if the current system is listening on the given tcp port """ - # index in the line - INDEX_LOCAL_ADDR = 1 - #INDEX_REMOTE_ADDR = 2 - INDEX_STATE = 3 - # state (st) that we care about - STATE_LISTENING = '0A' - # read the data - with open("/proc/net/tcp") as net_tcp: - for line in net_tcp.readlines(): - line = line.strip() - if not line: - continue - # split, values are: - # sl local_address rem_address st tx_queue rx_queue tr - # tm->when retrnsmt uid timeout inode - values = line.split() - state = values[INDEX_STATE] - if state != STATE_LISTENING: - continue - local_port_str = values[INDEX_LOCAL_ADDR].split(":")[1] - local_port = int(local_port_str, 16) - if local_port == port: - return True - return False - - -def iptables_active(): - """ Return True if iptables is active """ - # FIXME: is there a better way? - iptables_empty = """Chain INPUT (policy ACCEPT) -target prot opt source destination - -Chain FORWARD (policy ACCEPT) -target prot opt source destination - -Chain OUTPUT (policy ACCEPT) -target prot opt source destination -""" - if os.getuid() != 0: - raise OSError("Need root to check the iptables state") - if not os.path.exists("/sbin/iptables"): - return False - out = subprocess.Popen(["iptables", "-nL"], - stdout=subprocess.PIPE, - universal_newlines=True).communicate()[0] - if out == iptables_empty: - return False - return True - - -def capitalize_first_word(string): - """ this uppercases the first word's first letter - """ - if len(string) > 1 and string[0].isalpha() and not string[0].isupper(): - return string[0].capitalize() + string[1:] - return string - - -def get_package_label(pkg): - """ this takes a package synopsis and uppercases the first word's - first letter - """ - name = getattr(pkg.candidate, "summary", "") - return capitalize_first_word(name) - - -if __name__ == "__main__": - #print(mirror_from_sources_list()) - #print(on_battery()) - #print(inside_chroot()) - #print(iptables_active()) - error(None, "bar", "baz") diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManager.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManager.py deleted file mode 100644 index 3fc695b..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManager.py +++ /dev/null @@ -1,286 +0,0 @@ -# UpdateManager.py -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- - -from __future__ import absolute_import, print_function - -import os -import sys -import dbus -import shutil -import apt_pkg -import logging -import datetime -import warnings -import dbus.service -from dbus.mainloop.glib import DBusGMainLoop -DBusGMainLoop(set_as_default=True) - -from .Core.DistUpgradeCache import NotEnoughFreeSpaceError -from .Core.MyCache import MyCache -from .UpdateManagerDbus import UpdateManagerDbusController -from .Core.UpdateList import UpdateList -from .backend import (InstallBackend, - get_backend) -from .Core.Database import Sqlite3Server - - -from gettext import gettext as _ -warnings.filterwarnings("ignore", "Accessed deprecated property", - DeprecationWarning) - -#安装完成之后是否有请求需要重启 -REBOOT_REQUIRED_FILE = "/var/run/reboot-required" - -INSTALL_ALONE_PROGRESS = "alone" - -class UpdateManager(): - - def __init__(self,options): - self.options = options - self.cache = None - self.update_list = None - - #表示是否处于更新和安装的状态 - self.is_updating = False - self.is_upgrading = False - - #建立dbus - self.dbusController = self._setup_dbus() - - #连接数据库 - time = datetime.datetime.now() - timestr = datetime.datetime.strftime(time, "%Y-%m-%d %H:%M:%S") - self.sqlite3_server = Sqlite3Server() - - - # # FIXME: 目前此功能没有进行测试不知道是否可以进行检查 安装的时进行检查磁盘空间 - def check_free_space(self,cache): - err_sum = _("Not enough free disk space") - err_msg = _("The upgrade needs a total of %s free space on " - "disk '%s'. " - "Please free at least an additional %s of disk " - "space on '%s'. %s") - # specific ways to resolve lack of free space - remedy_archivedir = _("Remove temporary packages of former " - "installations using 'sudo apt clean'.") - remedy_boot = _("You can remove old kernels using " - "'sudo apt autoremove', and you could also " - "set COMPRESS=xz in " - "/etc/initramfs-tools/initramfs.conf to " - "reduce the size of your initramfs.") - remedy_root = _("Empty your trash and remove temporary " - "packages of former installations using " - "'sudo apt clean'.") - remedy_tmp = _("Reboot to clean up files in /tmp.") - remedy_usr = _("") - # check free space and error if its not enough - try: - cache.checkFreeSpace() - except NotEnoughFreeSpaceError as e: - # CheckFreeSpace examines where packages are cached - archivedir = apt_pkg.config.find_dir("Dir::Cache::archives") - err_long = "" - for req in e.free_space_required_list: - if err_long != "": - err_long += " " - if req.dir == archivedir: - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_archivedir) - elif req.dir == "/boot": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_boot) - elif req.dir == "/": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_root) - elif req.dir == "/tmp": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_tmp) - elif req.dir == "/usr": - err_long += err_msg % (req.size_total, req.dir, - req.size_needed, req.dir, - remedy_usr) - #在此抛出异常 - # self.window_main.start_error(False, err_sum, err_long) - return False - except SystemError: - logging.exception("free space check failed") - - return True - - #进行更新的操作 - def start_update(self): - try: - self.is_updating = True - update_backend = get_backend(self, InstallBackend.ACTION_UPDATE) - update_backend.start() - except Exception as e: - logging.error(e) - - #进行升级的操作 - def start_install(self,partial_upgrade_list = []): - #检查磁盘的状态 - if self.check_free_space(self.cache) == False: - return - logging.info("Disk Check finished...") - try: - self.is_upgrading = True - install_backend = get_backend(self, InstallBackend.ACTION_INSTALL) - install_backend.start(partial_upgrade_list=partial_upgrade_list) - except Exception as e: - logging.error(e) - - #进行升级的操作-传入包列表 - def start_install_alone(self,pkgs_install = [], pkgs_upgrade = [], pkgs_remove = [],pkgs_purge = []): - #检查磁盘的状态 - if self.check_free_space(self.cache) == False: - return - logging.info("Disk Check finished...") - self.is_upgrading = True - install_backend = get_backend(self, InstallBackend.ACTION_INSTALL) - install_backend.start_alone(pkgs_install,pkgs_upgrade,pkgs_remove,pkgs_purge) - - #更新结束之后会调到此获取要升级的列表 and 更新cache 生成升级组列表JSON - def start_available(self, cancelled_update=False): - _success,header,desc = self.refresh_cache() - - #特殊情况的处理 单独安装包需要直接退出 安装or卸载执行完毕后 还会调到start_available - if _success == True and header == INSTALL_ALONE_PROGRESS: - return - else: - #发送更新升级列表完成的标志 - self.dbusController.UpdateDetectFinished(_success,self.update_list.local_upgrade_list.get('upgrade_groups_list',[]),header,desc) - - #检查安装完成之后需要重启吗 - if os.path.exists(REBOOT_REQUIRED_FILE): - logging.error("REBOOT_REQUIRED_FILE") - - def refresh_cache(self): - _success = True - header = None - desc = None - try: - #第一次进入 之后update不进入 - if self.cache is None: - self.cache = MyCache(None) - else: - self.cache.open(None) - self.cache._initDepCache() - except AssertionError: - header = _("Software index is broken") - desc = _("It is impossible to install or remove any software. " - "Please use the package manager \"Synaptic\" or run " - "\"sudo apt-get install -f\" in a terminal to fix " - "this issue at first.") - _success = False - return _success,header,desc - - except SystemError as e: - header = _("Could not initialize the package information") - desc = _("An unresolvable problem occurred while " - "initializing the package information.\n\n" - "Please report this bug against the 'update-manager' " - "package and include the following error " - "message:\n") + str(e) - _success = False - return _success,header,desc - - self.update_list = UpdateList(self) - - '''1、 - dist-upgrade 标记在此处进行 - 来判断将要删除的包 如果存在要删除的break的包的话 会从dist-upgrade切换到upgrade 目前此功能不使用 默认使用dist-upgrade - ''' - self.distUpgradeWouldDelete = self.cache.saveDistUpgrade() - - #2、 安装JSON分组配置文件包 安装完毕会重新调start_available --> here 安装失败就直接退出不会进行下面的操作 - try: - pkg_json = self.cache[self.update_list.GROUPS_JSON_PKG] - #是否安装 - if pkg_json.is_installed: - #是否可升级 - if pkg_json.is_upgradable: - logging.info("groups JSON ConfigPkgs(%s) start upgrading...",self.GROUPS_JSON_PKG) - self.start_install_alone(pkgs_upgrade = [self.update_list.GROUPS_JSON_PKG]) - #直接退出 - _success = True - header = INSTALL_ALONE_PROGRESS - return _success,header,desc - else: - logging.info("ConfigPkgs(%s) No need to upgrade...",self.update_list.GROUPS_JSON_PKG) - else: - logging.info("groups JSON ConfigPkgs(%s) start new installing...",self.update_list.GROUPS_JSON_PKG) - self.start_install_alone(pkgs_install = [self.update_list.GROUPS_JSON_PKG]) - #直接退出 - _success = True - header = INSTALL_ALONE_PROGRESS - return _success,header,desc - - #FIXME: 错误处理未做 报告到控制面板 - except Exception as e: - logging.warning("groups JSON ConfigPkgs(%s) install failed...",self.update_list.GROUPS_JSON_PKG) - logging.error(e) - _success = False - - #3、 判断目录是JSON配置文件夹是否缺失 缺失后进行修复 卸载重新安装步骤 - if not os.path.exists(self.update_list.INPUT_CONFIG_PATH): - logging.info("groups JSON Config Path(%s) Missing and Trying to fix...",self.update_list.INPUT_CONFIG_PATH) - #将软件包卸载 之后进行重新安装here --> purge --> start_available 进行判断是否安装未安装重新安装 - self.start_install_alone(pkgs_purge = [self.update_list.GROUPS_JSON_PKG]) - #直接退出 - _success = True - header = INSTALL_ALONE_PROGRESS - return _success,header,desc - - #4、 清空上次输出的分组JSON文件 - try: - if not os.path.exists(self.update_list.OUTPUT_CONFIG_PATH): - os.makedirs(self.update_list.OUTPUT_CONFIG_PATH) - logging.info('making the configuration file is complete...') - else: - shutil.rmtree(self.update_list.OUTPUT_CONFIG_PATH) - os.makedirs(self.update_list.OUTPUT_CONFIG_PATH) - logging.info('Emptying the configuration file is complete...') - except Exception as e: - logging.warning(e) - - #FIXME: 5、 待开发功能 根据监测存在配置文件 不存在进行重新安装包 再检测还是未存在的话 就判断此次没有可升级的 - - #FIXME: 6、 出错后未进行处理 更新important.list 文件错误的话 - self.dbusController._on_update_important_list() - - try: - _success,header,desc = self.update_list.update(self.cache) - except SystemError as e: - header = _("Could not calculate the upgrade") - desc = _("An unresolvable problem occurred while " - "calculating the upgrade.\n\n" - "Please report this bug against the 'update-manager' " - "package and include the following error " - "message:\n") + str(e) - _success = False - - return _success,header,desc - - def _setup_dbus(self): - # check if there is another g-a-i already and if not setup one - # listening on dbus - try: - bus = dbus.SystemBus() - except Exception: - logging.error("warning: could not initiate dbus") - return - try: - proxy_obj = bus.get_object('com.kylin.systemupgrade', - '/com/kylin/systemupgrade') - - logging.warning("kylin-update-manager have started...") - sys.exit(0) - except dbus.DBusException: - bus_name = dbus.service.BusName('com.kylin.systemupgrade', - bus) - logging.info('initiate dbus success ...') - return UpdateManagerDbusController(self, bus_name) \ No newline at end of file diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerDbus.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerDbus.py deleted file mode 100644 index 53c8124..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerDbus.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/python3 -import dbus -import dbus.service -import logging -import threading - -from .Core.AlertWatcher import AlertWatcher -from .Core.roam import NetworkManagerHelper - -#dbus 建立 -class UpdateManagerDbusController(dbus.service.Object): - """ this is a helper to provide the UpdateManagerIFace """ - - INTERFACE = 'com.kylin.systemupgrade.interface' - - def __init__(self, parent, bus_name, - object_path='/com/kylin/systemupgrade'): - dbus.service.Object.__init__(self, bus_name, object_path) - self.parent = parent - - #网络检测 电池检测等等的启动检查 - self.alert_watcher = AlertWatcher() - self.alert_watcher.check_alert_state() - self.alert_watcher.connect("network-alert", self._on_network_alert) - self.connected = False - self.transaction = None - - #更新important.list的本次升级的列表 - def _on_update_important_list(self): - lock = threading.Lock() - bus = dbus.SystemBus() - try: - obj = bus.get_object('com.kylin.software.properties', '/com/kylin/software/properties') - interface = dbus.Interface(obj, dbus_interface='com.kylin.software.properties.interface') - lock.acquire() - retval = interface.updateSourceTemplate() - lock.release() - except Exception as e: - logging.error("update sourceTemplate Failed and Error mes:%s"%str(e)) - return False - - if retval == False: - logging.warning("update SourceTemplate failed") - return False - else: - logging.info("update sourceTemplate successed...") - return True - - #检测网络的状态 - def _on_network_alert(self, watcher, state): - if state in NetworkManagerHelper.NM_STATE_CONNECTED_LIST: - self.connected = True - logging.info('Network Connected ...') - else: - self.connected = False - logging.info('Network Disconnected ...') - - #更新的dbus - @dbus.service.method(INTERFACE,out_signature='b') - def UpdateDetect(self): - try: - #处于更新和升级中的话 不进行更新 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - self.parent.start_update() - logging.info('method dbus updating ...') - return True - except Exception: - return False - - #全部升级 - @dbus.service.method(INTERFACE,out_signature='bs') - def DistUpgradeSystem(self): - try: - if not self.parent.update_list: - logging.info('Perform \"UpdateDetect\" first') - return False,'Perform \"UpdateDetect\" first' - #处于更新和升级中的话 不进行升级 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - upgrade_groups_list = self.parent.update_list.local_upgrade_list.get('upgrade_groups_list',[]) - if upgrade_groups_list: - logging.info('method dbus upgrading ...') - self.parent.start_install() - return True,'success' - else: - return False,'False' - except Exception as e: - return False,str(e) - - #部分升级 - @dbus.service.method(INTERFACE,in_signature='as',out_signature='bs') - def DistUpgradePartial(self,_partial_upgrade_list): - try: - if not self.parent.update_list: - logging.info('Perform \"UpdateDetect\" first') - return False,'Perform \"UpdateDetect\" first' - #处于更新和升级中的话 不进行升级 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - partial_upgrade_list = [str(i) for i in _partial_upgrade_list] - #本地维护的可升级的组 - upgrade_groups_list = self.parent.update_list.local_upgrade_list.get('upgrade_groups_list',[]) - upgrade_list = list(set(partial_upgrade_list) & set(upgrade_groups_list)) - - if upgrade_list: - logging.info('dbus partial_upgrade(%s)',upgrade_list) - self.parent.start_install(upgrade_list) - return True,'dbus upgrading' - else: - logging.info('input upgrade list(%s) not in local upgrade_list(%s)',partial_upgrade_list,upgrade_groups_list) - return False,'upgrade_list is empty' - except Exception as e: - return False,e - - # 取消transaction - @dbus.service.method(INTERFACE, out_signature='bs') - def CancelDownload(self): - status = False - message = "" - try: - if self.transaction.cancellable == True: - self.transaction.cancel() - status = True - message = "Success" - logging.info("dbus-mothod cancel task Success") - elif self.transaction == None or self.transaction.cancellable == False: - message = "Can not Cancel" - except Exception as e: - return (status,str(e)) - return (status, message) - - # 依赖错误时调用的接口 - @dbus.service.method(INTERFACE, in_signature='b', out_signature='bs') - def Here_is_a_handsome_pot(self, repair): - pkgs_install = [] - pkgs_upgrade = [] - pkgs_remove = [] - try: - #处于更新和升级中的话 不进行升级 - if self.parent.is_updating or self.parent.is_upgrading: - logging.info('In the process of updating or Upgrading...') - return False,'In the process of updating or Upgrading...' - else: - if repair: - #查找所有可升级的包 - for pkg in self.parent.cache: - try: - if pkg.marked_install: - pkgs_install.append(pkg.name) - elif pkg.marked_upgrade: - pkgs_upgrade.append(pkg.name) - elif pkg.marked_delete: - pkgs_remove.append(pkg.name) - except Exception as e: - logging.error(e) - if pkgs_install or pkgs_upgrade or pkgs_remove: - logging.info('total: install pkgs num(%d) | upgrade pkgs num(%d) | remove pkgs num(%d) |', \ - len(pkgs_install), \ - len(pkgs_upgrade), \ - len(pkgs_remove)) - #开始安装 - self.parent.start_install_alone( \ - pkgs_install = pkgs_install, \ - pkgs_upgrade = pkgs_upgrade, \ - pkgs_remove = pkgs_remove) - return True,'dbus upgrading' - else: - logging.info('pkgs list is empty.') - return False,'upgrade_list is empty' - - else: - logging.info('Cancel repair') - return False,'Cancel repair' - except Exception as e: - return (False, str(e)) - - #更新进度信息 0~100 进度信息 101为非预期的信号 - @dbus.service.signal(INTERFACE,signature='is') - def UpdateDetectStatusChanged(self,progress,status): - logging.info("emit progress = %d , status = %s",progress,status) - - #更新完成的信号 - @dbus.service.signal(INTERFACE,signature='basss') - def UpdateDetectFinished(self, success, upgrade_group,error_string='',error_desc='',): - logging.info("emit update success = %r , upgrade_group = %a, error_string = %s , error_desc = %s ",\ - success,upgrade_group, error_string,error_desc) - - #升级的进度信息 0~100 进度信息 101为非预期的信号 - @dbus.service.signal(INTERFACE,signature='asis') - def UpdateDloadAndInstStaChanged(self,groups_list,progress,status): - logging.info("emit upgrade groups_list = %s progress = %d , status = %s",groups_list,progress,status) - - #升级完成的信号 - @dbus.service.signal(INTERFACE,signature='basss') - def UpdateDownloadFinished(self, success, upgrade_group,error_string='',error_desc='',): - logging.info("emit success = %r , upgrade_group = %a, error_string = %s , error_desc = %s ",\ - success,upgrade_group, error_string,error_desc) - - #发送下载包信息 - @dbus.service.signal(INTERFACE, signature='iiiii') - def UpdateDownloadInfo(self, current_items, total_items, currenty_bytes, total_bytes, current_cps): - logging.info("emit current_items = %d, total_items = %d, currenty_bytes = %d, total_bytes = %d, current_cps = %d .",\ - current_items, total_items, \ - currenty_bytes, total_bytes,\ - current_cps) - - # 信号是否可取消 - @dbus.service.signal(INTERFACE, signature='b') - def Cancelable(self, Cancelable): - logging.info("emit Cancelable: %r",\ - Cancelable) diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerVersion.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerVersion.py deleted file mode 100644 index 4224770..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/UpdateManagerVersion.py +++ /dev/null @@ -1 +0,0 @@ -VERSION = '1.0.4kord' diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/__init__.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py deleted file mode 100644 index e135fba..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/backend/InstallBackendAptdaemon.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env python - -from __future__ import print_function - -from apt.debfile import DebPackage -from aptdaemon import client, errors -from defer import inline_callbacks -from aptdaemon.enums import (EXIT_SUCCESS, - EXIT_FAILED, - EXIT_CANCELLED, - get_error_description_from_enum, - get_error_string_from_enum, - get_status_string_from_enum - ) - -from SystemUpdater.backend import InstallBackend -import logging -from gettext import gettext as _ -import dbus - -class InstallBackendAptdaemon(InstallBackend): - """Makes use of aptdaemon to refresh the cache and to install updates.""" - - def __init__(self, window_main, action): - InstallBackend.__init__(self, window_main, action) - self.window_main = window_main - #客户端连接aptdeamon的dbus接口 - self.client = client.AptClient() - self.trans_failed_msg = None - - self.trans_progress = 0 - self.trans_status = '' - - @inline_callbacks - def update(self): - """刷新包cache""" - try: - trans = yield self.client.update_cache(defer=True) - self.window_main.dbusController.transaction = trans - #注册回调函数 接收更新的状态 - yield self._show_transaction(trans, self.ACTION_UPDATE, - _("Checking for updates…"), False) - except errors.NotAuthorizedError: - self._action_done(self.ACTION_UPDATE, - authorized=False, success=False, - error_string=None, error_desc=None) - except Exception: - self._action_done(self.ACTION_UPDATE, - authorized=True, success=False, - error_string=None, error_desc=None) - raise - - @inline_callbacks - def commit(self, pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge): - """Commit a list of package adds and removes""" - try: - reinstall = downgrade = [] - trans = yield self.client.commit_packages( - pkgs_install, reinstall, pkgs_remove, purge = pkgs_purge, upgrade = pkgs_upgrade, - downgrade = downgrade, defer=True) - self.window_main.dbusController.transaction = trans - - yield self._show_transaction(trans, self.ACTION_INSTALL, - _("Installing updates…"), True) - except errors.NotAuthorizedError: - self._action_done(self.ACTION_INSTALL, - authorized=False, success=False, - error_string=None, error_desc=None) - except errors.TransactionFailed as e: - # if e.code == 'error-dep-resolution-failed': - # logging.error("依赖错误: %s", str(e)) - self.errors = e - self.trans_failed_msg = str(e) - except dbus.DBusException as e: - if e.get_dbus_name() != "org.freedesktop.DBus.Error.NoReply": - raise - self._action_done(self.ACTION_INSTALL, - authorized=False, success=False, - error_string=None, error_desc=None) - except Exception: - self._action_done(self.ACTION_INSTALL, - authorized=True, success=False, - error_string=None, error_desc=None) - raise - - #进度回调 - def _on_progress_changed(self, trans,progress,action): - self.trans_progress = progress - if action == self.ACTION_UPDATE: - self.window_main.dbusController.UpdateDetectStatusChanged(self.trans_progress,self.trans_status) - else: - self.window_main.dbusController.UpdateDloadAndInstStaChanged(self.upgrade_groups_list,self.trans_progress,self.trans_status) - - #同步状态回调 - def _on_status_changed(self, trans, status,action): - #转化词条 - self.trans_status = get_status_string_from_enum(status) - - if action == self.ACTION_UPDATE: - self.window_main.dbusController.UpdateDetectStatusChanged(self.trans_progress,self.trans_status) - else: - #升级的时候发送状态信号时需要上传更新组信息self.upgrade_groups_list - self.window_main.dbusController.UpdateDloadAndInstStaChanged(self.upgrade_groups_list,self.trans_progress,self.trans_status) - - def _on_details_changed(self, trans, details): - logging.info(details) - - def _on_download_changed(self, trans, details): - logging.info(details) - - # eta 下载速度不正确,取消掉 - def _on_progress_download_changed(self,trans,current_items, total_items, currenty_bytes, total_bytes, current_cps, eta): - if self.action == self.ACTION_INSTALL: - self.window_main.dbusController.UpdateDownloadInfo(\ - current_items, total_items, \ - currenty_bytes, total_bytes, \ - current_cps) - - def _on_cancellable_changed(self, trans, Cancelable): - self.window_main.dbusController.Cancelable(Cancelable) - - @inline_callbacks - def _show_transaction(self, trans, action, header, show_details): - - #更新和升级最后完成和失败都会走此在此进行完成之后的处理 - trans.connect("finished", self._on_finished, action) - - #升级和更新的状态信息和进度 - trans.connect("status-changed", self._on_status_changed,action) - trans.connect("progress-changed", self._on_progress_changed,action) - - #取消升级 - trans.connect("cancellable-changed", self._on_cancellable_changed) - - #下载的进度信息 - trans.connect("progress-details-changed", self._on_progress_download_changed) - - # trans.connect("medium-required", self._on_medium_required) - # trans.connect("status-details-changed", self._on_details_changed) - #状态改变的时候的回调函数 - # trans.connect("download-changed", self._on_download_changed) - # trans.connect("config-file-conflict", self._on_config_file_conflict) - # yield trans.set_debconf_frontend("ukui") - yield trans.run() - - def _on_finished(self, trans, status, action): - error_string = '' - error_desc = '' - trans_failed = False - - if status == EXIT_FAILED: - # error_string = get_error_string_from_enum(trans.error.code) - # error_desc = get_error_description_from_enum(trans.error.code) - if self.errors: - error_string = self.errors.code - error_string = get_error_string_from_enum(trans.error.code) - error_desc = get_error_description_from_enum(trans.error.code) - if self.trans_failed_msg: - trans_failed = True - error_desc = error_desc + "\n" + self.trans_failed_msg - elif status == EXIT_CANCELLED: - error_desc = 'cancel download' - is_success = (status == EXIT_SUCCESS) - - try: - self._action_done(action, - authorized=True, success=is_success, - error_string=error_string, error_desc=error_desc, - trans_failed=trans_failed) - # - # if self.errors.code == 'error-dep-resolution-failed': - except TypeError: - # this module used to be be lazily imported and in older code - # trans_failed= is not accepted - # TODO: this workaround can be dropped in Ubuntu 20.10 - self._action_done(action, - authorized=True, success=is_success, - error_string=error_string, error_desc=error_desc) diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/backend/__init__.py b/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/backend/__init__.py deleted file mode 100644 index b695ebe..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/SystemUpdater/backend/__init__.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python -# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4; coding: utf-8 -*- - -"""Integration of package managers into SystemUpdater""" -# (c) 2005-2009 Canonical, GPL - -from __future__ import absolute_import - -import logging -import os -from gettext import gettext as _ - - -class InstallBackend(): - ACTION_UPDATE = 0 - ACTION_INSTALL = 1 - - def __init__(self, window_main, action): - self.window_main = window_main - self.action = action - self.upgrade_groups_list = [] - - def start(self,partial_upgrade_list = []): - - #FIXME: 在下载升级的能抑制系统关闭或者睡眠 参考ubuntu此部分代码 - - if self.action == self.ACTION_INSTALL: - pkgs_install = [] - pkgs_upgrade = ['code', 'cpio', 'distro-info-data', 'ghostscript'] - pkgs_remove = [] - pkgs_purge = [] - try: - # #可选升级不为空 - # if partial_upgrade_list: - # self.upgrade_groups_list = partial_upgrade_list - # #全部升级列表 - # else: - # self.upgrade_groups_list = self.window_main.update_list.local_upgrade_list.get('upgrade_groups_list',[]) - - # #遍历升级组列表 - # if self.upgrade_groups_list: - # for group_name in self.upgrade_groups_list: - # pkgs_install += self.window_main.update_list.local_upgrade_list.get(group_name,[]).get('pkgs_install',[]) - # pkgs_upgrade += self.window_main.update_list.local_upgrade_list.get(group_name,[]).get('pkgs_upgrade',[]) - - # pkgs_remove = self.window_main.update_list.local_upgrade_list.get("pkgs_remove",[]) - # else: - # logging.info("no upgradeable packages") - # return - - # #目前不确定#auto含义 大概是自动安装新包 类似加-y ubuntu这样做 - # new_pkgs_install = [] - # for pkgname in pkgs_install: - # pkgname += "#auto" - # new_pkgs_install.append(pkgname) - - logging.info("commit install:%d , upgrade:%d remove:%d",len(pkgs_install),len(pkgs_upgrade),len(pkgs_remove)) - self.commit(pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge) - except Exception as e: - logging.error(e) - else: - self.update() - - def start_alone(self,pkgs_install = [], pkgs_upgrade = [], pkgs_remove = [],pkgs_purge = []): - os.environ["APT_LISTCHANGES_FRONTEND"] = "none" - - if self.action == self.ACTION_INSTALL: - # Get the packages which should be installed and update - self.commit(pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge) - else: - self.update() - - def update(self): - """Run a update to refresh the package list""" - raise NotImplementedError - - def commit(self, pkgs_install, pkgs_upgrade, pkgs_remove,pkgs_purge): - """Commit the cache changes """ - raise NotImplementedError - - #出现错误和更新升级完成都会调到此方法 进行处理 - def _action_done(self, action, authorized, success, error_string, - error_desc, trans_failed=False): - - #升级完成后走的分支 - if action == self.ACTION_INSTALL: - self.window_main.is_upgrading = False - if success: - #当组列表为空时 表示现在的单独进行安装某些包或卸载,不发信号到控制面板 - if self.upgrade_groups_list: - self.window_main.dbusController.UpdateDownloadFinished(success,self.upgrade_groups_list,'','') - else: - self.window_main.start_available() - elif error_string or error_desc: - logging.warning(error_string + error_desc) - if error_string.startswith('error-dep-resolution-failed'): - self.window_main.dbusController.UpdateDownloadFinished(success,self.upgrade_groups_list,error_string,error_desc) - else: - self.window_main.dbusController.UpdateDownloadFinished(success,self.upgrade_groups_list,'','') - else: - self.window_main.is_updating = False - if success: - self.window_main.start_available() - elif error_string or error_desc: - logging.warning(error_string + error_desc) - self.window_main.dbusController.UpdateDetectFinished(success,[],error_string,error_desc) - else: - self.window_main.dbusController.UpdateDetectFinished(success,[],'','') - -# try aptdaemon -if os.path.exists("/usr/sbin/aptd") \ - and "UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC" not in os.environ: - # check if the gtkwidgets are installed as well - try: - from .InstallBackendAptdaemon import InstallBackendAptdaemon - except ImportError: - logging.exception("importing aptdaemon") - - -def get_backend(*args, **kwargs): - """Select and return a package manager backend.""" - # try aptdaemon - if (os.path.exists("/usr/sbin/aptd") - and "UPDATE_MANAGER_FORCE_BACKEND_SYNAPTIC" not in os.environ): - # check if the gtkwidgets are installed as well - try: - return InstallBackendAptdaemon(*args, **kwargs) - except NameError: - logging.exception("using aptdaemon failed") - - # nothing found, raise - raise Exception("No working backend found, please try installing " - "aptdaemon or synaptic") diff --git a/debian/kylin-system-updater/usr/lib/python3/dist-packages/kylin_system_updater-1.0.4kord.egg-info b/debian/kylin-system-updater/usr/lib/python3/dist-packages/kylin_system_updater-1.0.4kord.egg-info deleted file mode 100644 index e92a73f..0000000 --- a/debian/kylin-system-updater/usr/lib/python3/dist-packages/kylin_system_updater-1.0.4kord.egg-info +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 1.0 -Name: kylin-system-updater -Version: 1.0.4kord -Summary: UNKNOWN -Home-page: UNKNOWN -Author: UNKNOWN -Author-email: UNKNOWN -License: UNKNOWN -Description: UNKNOWN -Platform: UNKNOWN diff --git a/debian/kylin-system-updater/usr/lib/systemd/system/kylin-system-updater.service b/debian/kylin-system-updater/usr/lib/systemd/system/kylin-system-updater.service deleted file mode 100644 index 89b2690..0000000 --- a/debian/kylin-system-updater/usr/lib/systemd/system/kylin-system-updater.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=kylin-system-updater dbus daemon - -[Service] -Type=dbus -BusName=com.kylin.systemupgrade -ExecStart=/usr/bin/kylin-system-updater - -[Install] -WantedBy=multi-user.target \ No newline at end of file diff --git a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/AUTHORS b/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/AUTHORS deleted file mode 100644 index d12b537..0000000 --- a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/AUTHORS +++ /dev/null @@ -1,19 +0,0 @@ -Hackers -======= -Michiel Sikkes -Michael Vogt - -Translators -=========== -Jorge Bernal -Jean Privat -Martin Willemoes Hansen -Zygmunt Krynicki - -Technical Author -================ -Sean Wheller - -Icons -===== -Jakub Steiner diff --git a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/README.MD b/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/README.MD deleted file mode 100644 index 89e7edc..0000000 --- a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/README.MD +++ /dev/null @@ -1,26 +0,0 @@ -### Software Updater for apt - -- 安装依赖 - - ``` - sudo apt install dh-python python3-all python3-distutils-extra gir1.2-snapd-1 apt-clone intltool at-spi2-core -y - ``` - -- 运行update-manager 运行 - - - -### 文档 - -#### Aptdaemon - -- https://pythonhosted.org/aptdaemon/aptdaemon.client.html?highlight=commit_packages#aptdaemon.client.AptClient.commit_packages - -#### python-apt - -- https://apt-team.pages.debiahn.net/python-apt/library/apt_pkg.html - -#### 方法与信号接口文档 - -- 参考interface.md 文档 - diff --git a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/TODO b/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/TODO deleted file mode 100644 index f6682db..0000000 --- a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/TODO +++ /dev/null @@ -1,20 +0,0 @@ -* offer removal of no-longer-supported apps -* improve countrymirror detection - - -UpdateManager.Common.aptsources.py: -- make the distro detection in sources.list more clever by using the - origin informaton to avoid adding full uris to (unofficial/internal) - mirrors -- make it possible to inherit the mirrros from a ParentSuite (for - the childs) - -Misc: -- add download size to treeview -- add /etc/apt/software-properties.d dir where the user can - install matchers and templates -- handle cases like "deb http://bla/ dist sec1 sec2 # comment" -- rework the add channel/cdrom dialogs -- d'n'd for key files -- use one row per section and not one per channel in the treeview -- sort the sources by dist diff --git a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/changelog.gz b/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/changelog.gz deleted file mode 100644 index 26b27df..0000000 Binary files a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/changelog.gz and /dev/null differ diff --git a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/copyright b/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/copyright deleted file mode 100644 index e93b7c6..0000000 --- a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/copyright +++ /dev/null @@ -1,22 +0,0 @@ -This package was debianized by Michiel Sikkes on -Mon, 25 Oct 2004 21:49:07 +0200. - -It was downloaded from http://code.launchpad.net/~ubuntu-core-dev/update-manager/main - -Upstream Authors: -Michiel Sikkes -Michael Vogt -Sebastian Heinlein -Jonathan Riddell - -Copyright: -2004-2008 Canonical Ltd. -2004-2005 Michiel Sikkes - -All code released under the GPL, see /usr/share/common-licenses/GPL - - -With the exception of -UpdateManager/SimpleGladeApp.py -which is released under the LGPL, see /usr/share/common-licenses/LGPL - diff --git a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/interface.md b/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/interface.md deleted file mode 100644 index 67e66fb..0000000 --- a/debian/kylin-system-updater/usr/share/doc/kylin-system-updater/interface.md +++ /dev/null @@ -1,64 +0,0 @@ -### DBUS接口 - -#### 描述 - -实现系统升级以python apt库和aptdeamon的形式 - - - -#### Dbus接口信息 - -| 名称 | 含义 | -| -------------- | --------------------------------- | -| BUS类型 | SYSTEM BUS | -| DBUS名称 | com.kylin.systemupgrade | -| OBJECT路径 | /com/kylin/systemupgrade | -| INTERFACES名称 | com.kylin.systemupgrade.interface | - - - -#### Method列表 - -| Method Name | Input Args | Output Args | means | -| ------------------ | ---------- | ----------- | --------------------------------- | -| UpdateDetect | 无 | b | 更新cache,产生组升级列表JSON文件 | -| DistUpgradeSystem | 无 | b | 全部升级 | -| DistUpgradePartial | as | b | 部分升级 | -| CancelDownload | 无 | b | 取消升级 | -| | | | | - -#### Method分析 - -##### - -#### Signal列表 - -| Method Name | Output Args | means | -| ---------------------------- | ----------- | ------------------------ | -| UpdateDetectStatusChanged | is | 更新进度信息以及状态信息 | -| UpdateDetectFinished | basss | 更新完成信号 | -| UpdateDloadAndInstStaChanged | asis | 升级的进度信号以及状态 | -| UpdateDownloadFinished | basss | 升级完成的信号 | -| UpdateDownloadInfo | iiiii | 发送下载包信息信号 | -| Cancelable | b | 是否可取消 | - - - -#### Signal分析 - -##### update_progress_signal - -| method name | out args | -| ---------------------- | -------------------------------------------- | -| update_progress_signal | is | -| 部分升级 | i:进度状态0-100,101为非预期状态 S:状态信息 | - - - -update_finished_signal - -| method name | out args | -| ---------------------- | --------------------------------------------------- | -| update_progress_signal | basss | -| 部分升级 | b:成功或失败、as:可升级的组、s:错误结果、s:错误原因 | - diff --git a/debian/kylin-system-updater/usr/share/kylin-system-updater/kylin-system-updater.db b/debian/kylin-system-updater/usr/share/kylin-system-updater/kylin-system-updater.db deleted file mode 100644 index d97de09..0000000 Binary files a/debian/kylin-system-updater/usr/share/kylin-system-updater/kylin-system-updater.db and /dev/null differ diff --git a/debian/kylin-system-updater/usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo b/debian/kylin-system-updater/usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo deleted file mode 100644 index 9ad85ac..0000000 Binary files a/debian/kylin-system-updater/usr/share/locale/zh_CN/LC_MESSAGES/kylin-system-updater.mo and /dev/null differ diff --git a/debian/kylin-system-updater/usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo b/debian/kylin-system-updater/usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo deleted file mode 100644 index 4b58ea2..0000000 Binary files a/debian/kylin-system-updater/usr/share/locale/zh_HK/LC_MESSAGES/kylin-system-updater.mo and /dev/null differ diff --git a/debian/kylin-system-updater/usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo b/debian/kylin-system-updater/usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo deleted file mode 100644 index 8a70c9b..0000000 Binary files a/debian/kylin-system-updater/usr/share/locale/zh_TW/LC_MESSAGES/kylin-system-updater.mo and /dev/null differ diff --git a/debian/kylin-system-updater/usr/share/man/man8/kylin-system-updater.8.gz b/debian/kylin-system-updater/usr/share/man/man8/kylin-system-updater.8.gz deleted file mode 100644 index efa4375..0000000 Binary files a/debian/kylin-system-updater/usr/share/man/man8/kylin-system-updater.8.gz and /dev/null differ