From 3943cfc73b5f0ba24bdfa7d767000ebed668f959 Mon Sep 17 00:00:00 2001
From: Matthias Klumpp <mak@debian.org>
Date: Mon, 9 Jan 2023 00:09:31 +0100
Subject: [PATCH] Add Debian support

Implement some Debian support and make a lot of Ubuntu features optional
and only active when run on Ubuntu, instead of crashing on Debian.
---
 .../gtk/SoftwarePropertiesGtk.py              | 19 +++++++++++--------
 softwareproperties/gtk/utils.py               | 14 +++++++++++---
 2 files changed, 22 insertions(+), 11 deletions(-)

--- a/softwareproperties/gtk/SoftwarePropertiesGtk.py
+++ b/softwareproperties/gtk/SoftwarePropertiesGtk.py
@@ -57,10 +57,10 @@
 from .DialogEditDeb822 import DialogEditDeb822
 from .DialogCacheOutdated import DialogCacheOutdated
 from .DialogAddSourcesList import DialogAddSourcesList
-from .UbuntuProPage import UbuntuProPage
 
 import softwareproperties
 import softwareproperties.distro
+from softwareproperties.distro import is_current_distro_ubuntu
 from softwareproperties.SoftwareProperties import SoftwareProperties
 import softwareproperties.SoftwareProperties
 
@@ -71,7 +71,9 @@
     is_current_distro_lts,
 )
 
-from UbuntuDrivers import detect
+if is_current_distro_ubuntu():
+    from .UbuntuProPage import UbuntuProPage
+    from UbuntuDrivers import detect
 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
 
 if GLib.pyglib_version < (3, 9, 1):
@@ -273,11 +275,15 @@
         # Setup and show the distro elements
         self.init_distro()
         self.show_distro()
-        # Setup and show the Additonal Drivers tab
-        self.init_drivers()
-        # Setup and show the Ubuntu Pro tab if the serie is a LTS
-        if is_current_distro_lts():
-            self.init_ubuntu_pro()
+        if is_current_distro_ubuntu():
+            # Setup and show the Additonal Drivers tab
+            self.init_drivers()
+            # Setup and show the Ubuntu Pro tab if the serie is a LTS
+            if is_current_distro_lts():
+                self.init_ubuntu_pro()
+        else:
+            self.label_snap_info.set_visible(False)
+            self.tab_updates.set_visible(self.have_unattended_upgrades())
 
         # Connect to switch-page before setting initial tab. Otherwise the
         # first switch goes unnoticed.
@@ -496,18 +502,23 @@
                 eol_text = _("Basic Security Maintenance")
                 eol_date = distro.eol
         self.label_esm_status.set_markup(eol_text)
+        if not is_current_distro_ubuntu():
+            self.label_updates_1.set_markup(_("Software on this system has:"))
         esm_url = "https://ubuntu.com/esm"  # Non-EOL LTS generic ESM
         today = datetime.datetime.now().date()
-        if today >= eol_date:
+        if eol_date and today >= eol_date:
                 if esm_available:
                         # EOL LTS uses release-specific ESM ubuntu.com/XX-YY
                         distro_ver = distro.version.replace(' LTS', '')
                         esm_url = "https://ubuntu.com/%s" % distro_ver.replace(".", "-")
                 eol_expiry_text = _("Ended %s - extend or upgrade now") % eol_date.strftime("%x")
-        elif today >= eol_date - datetime.timedelta(days=60):
+        elif eol_date and today >= eol_date - datetime.timedelta(days=60):
                 eol_expiry_text = _("Ends %s - extend or upgrade soon") % eol_date.strftime("%x")
         else:
+            if eol_date:
                 eol_expiry_text = _("Active until %s") % eol_date.strftime("%x")
+            else:
+                eol_expiry_text = _("End of life date not known yet.")
         self.label_eol.set_label(eol_expiry_text)
         self.label_esm_subscribe.set_markup(
                 "<a href=\"%s\">%s</a>" % (esm_url, _("Extend…"))
@@ -515,12 +526,14 @@
         self.label_esm_subscribe.set_visible(
                 esm_available and not esm_enabled
         )
-        eol_expiry_text = _("Ended %s") % eol_date.strftime("%x")
 
         # Setup the combo box for updates subscriptions
         combobox = self.combobox_updates_subscription
         self.handlers[combobox] = combobox.connect(
             "changed", self.on_combobox_updates_subscription_changed)
+        if not is_current_distro_ubuntu():
+            combobox.set_visible(False)
+            self.label_updates_3.set_visible(False)
 
         # setup the server chooser
         cell = Gtk.CellRendererText()
@@ -1341,7 +1354,6 @@
 
     def init_drivers(self):
         """Additional Drivers tab"""
-
         self.button_driver_revert = Gtk.Button(label=_("Re_vert"), use_underline=True)
         self.button_driver_revert.connect("clicked", self.on_driver_changes_revert)
         self.button_driver_apply = Gtk.Button(label=_("_Apply Changes"), use_underline=True)
@@ -1439,7 +1451,7 @@
         self.update_drivers_control_button()
 
     def on_driver_selection_changed(self, button, modalias, pkg_name=None):
-        if self.ui_building:
+        if self.ui_building or not is_current_distro_ubuntu():
             return
 
         pkg = None
--- a/softwareproperties/gtk/utils.py
+++ b/softwareproperties/gtk/utils.py
@@ -27,6 +27,7 @@
 import json
 import os
 import subprocess
+from softwareproperties.distro import is_current_distro_ubuntu
 
 import logging
 LOG=logging.getLogger(__name__)
@@ -55,19 +56,26 @@
     except Exception:
         return False
 
+def get_distro_info(distro):
+    if isinstance(distro, aptsources.distro.UbuntuDistribution):
+        return distro_info.UbuntuDistroInfo()
+    return distro_info.DebianDistroInfo()
+
 def is_current_distro_lts():
+    if not is_current_distro_ubuntu():
+        return False
     distro = aptsources.distro.get_distro()
-    di = distro_info.UbuntuDistroInfo()
+    di = get_distro_info(distro)
     return di.is_lts(distro.codename)
 
 def is_current_distro_supported():
     distro = aptsources.distro.get_distro()
-    di = distro_info.UbuntuDistroInfo()
+    di = get_distro_info(distro)
     return distro.codename in di.supported(datetime.now().date())
 
 def current_distro():
     distro = aptsources.distro.get_distro()
-    di = distro_info.UbuntuDistroInfo()
+    di = get_distro_info(distro)
     releases = di.get_all(result="object")
     for release in releases:
         if release.series == distro.codename:
@@ -82,6 +90,8 @@
     # Invoking `pro status` with subp will result in a network call to
     # contracts.canonical.com which could raise Timeouts on network limited
     # machines. So, prefer the status.json file when possible.
+    if not is_current_distro_ubuntu():
+        return {}
     status_json = ""
     if os.path.exists(UA_STATUS_JSON):
         with open(UA_STATUS_JSON) as stream:
--- a/softwareproperties/distro.py
+++ b/softwareproperties/distro.py
@@ -23,6 +23,10 @@
 import aptsources.distro
 from gettext import gettext as _
 
+
+def is_current_distro_ubuntu():
+    return isinstance(aptsources.distro.get_distro(), aptsources.distro.UbuntuDistribution)
+
 def get_popcon_description(distro):
     if isinstance(distro, aptsources.distro.UbuntuDistribution):
         return(_("<i>To improve the user experience of Ubuntu please "
--- a/softwareproperties/qt/SoftwarePropertiesQt.py
+++ b/softwareproperties/qt/SoftwarePropertiesQt.py
@@ -41,6 +41,7 @@
 
 import softwareproperties
 import softwareproperties.distro
+from softwareproperties.distro import is_current_distro_ubuntu
 from softwareproperties.SoftwareProperties import SoftwareProperties
 import softwareproperties.SoftwareProperties
 from .I18nHelper import *
@@ -52,12 +53,14 @@
 from .DialogMirror import DialogMirror
 from .CdromProgress import CdromProgress
 
-from UbuntuDrivers import detect
 import sys
 from functools import partial
 import aptsources.distro
 import logging
 
+if is_current_distro_ubuntu():
+    from UbuntuDrivers import detect
+
 class DetectDriverThread(QThread):
   #WARNING class to run detect_drivers() in separate thread
   #so GUI won't freeze.
@@ -133,6 +136,8 @@
     self.show_cdrom_sources()
     # Setup and show the Additonal Drivers tab
     self.init_drivers()
+    # Only show updates tab if unattended-upgrades is installed
+    self.userinterface.tabWidget.setTabVisible(2, self.have_unattended_upgrades())
 
     # Connect to switch-page before setting initial tab. Otherwise the
     # first switch goes unnoticed.
@@ -999,6 +1004,10 @@
 
   def init_drivers(self):
     """Additional Drivers tab"""
+    if not is_current_distro_ubuntu():
+        self.userinterface.tabWidget.setTabVisible(4, False)
+        return
+
     self.button_driver_revert = QPushButton("Revert")
     self.button_driver_apply = QPushButton("Apply Changes")
     self.button_driver_cancel = QPushButton("Cancel")
@@ -1047,6 +1056,8 @@
 
   def detect_drivers(self):
     # WARNING: This is run in a separate thread.
+    if not is_current_distro_ubuntu():
+        return
     self.detect_called = True
     self.init_apt_cache()
     try:
@@ -1064,7 +1075,7 @@
     #print(modalias)
     #print(pkg_name)
 
-    if self.ui_building:
+    if self.ui_building or not is_current_distro_ubuntu():
       return
 
     pkg = None
--- a/data/gtkbuilder/main.ui
+++ b/data/gtkbuilder/main.ui
@@ -395,7 +395,7 @@
               </packing>
             </child>
             <child>
-              <object class="GtkAlignment">
+              <object class="GtkAlignment" id="tab_updates">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="xscale">0</property>
@@ -408,7 +408,7 @@
                     <property name="spacing">18</property>
                     <property name="orientation">vertical</property>
                     <child>
-                      <object class="GtkLabel">
+                      <object class="GtkLabel" id="label_snap_info">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="label" translatable="yes">Snap package updates are checked routinely and installed automatically.</property>
--- a/softwareproperties/SoftwareProperties.py
+++ b/softwareproperties/SoftwareProperties.py
@@ -283,6 +283,9 @@
     with open(self.popconfile, "w") as f:
         f.writelines(lines)
 
+  def have_unattended_upgrades(self):
+      return os.path.isfile("/usr/bin/unattended-upgrade")
+
   def get_source_code_state(self):
     """Return True if all distro componets are also available as
        source code. Otherwise return Flase. Special case: If the
