求3个文件
Tofloor
poster avatar
Bluek404
deepin
2014-05-17 04:30
Author
求发
/usr/bin/add-apt-repository
/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py
/usr/lib/python3/dist-packages/aptsources/distro.py
这三个文件里的内容
直接复制粘贴回复就行了
万分感谢
可以直接用
  1. gedit /usr/bin/add-apt-repository /usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py /usr/lib/python3/dist-packages/aptsources/distro.py
Copy the Code
这条命令打开
Reply Favorite View the author
All Replies
foundix
deepin
2014-05-17 05:23
#1
/usr/bin/add-apt-repository
  1. #! /usr/bin/python3
  2. from __future__ import print_function
  3. import io
  4. import os
  5. import sys
  6. import gettext
  7. import locale
  8. from softwareproperties.SoftwareProperties import SoftwareProperties, shortcut_handler
  9. from softwareproperties.shortcuts import ShortcutException
  10. from softwareproperties.ppa import DEFAULT_KEYSERVER
  11. import aptsources
  12. from aptsources.sourceslist import SourceEntry
  13. from optparse import OptionParser
  14. from gettext import gettext as _
  15. if __name__ == "__main__":
  16.     # Force encoding to UTF-8 even in non-UTF-8 locales.
  17.     sys.stdout = io.TextIOWrapper(
  18.         sys.stdout.detach(), encoding="UTF-8", line_buffering=True)
  19.     try:
  20.         locale.setlocale(locale.LC_ALL, "")
  21.     except:
  22.         pass
  23.     gettext.textdomain("software-properties")
  24.     usage = """Usage: %prog
  25. %prog is a script for adding apt sources.list entries.
  26. It can be used to add any repository and also provides a shorthand
  27. syntax for adding a Launchpad PPA (Personal Package Archive)
  28. repository.
  29. - The apt repository source line to add. This is one of:
  30.   a complete apt line in quotes,
  31.   a repo url and areas in quotes (areas defaults to 'main')
  32.   a PPA shortcut.
  33.   a distro component
  34.   Examples:
  35.     apt-add-repository 'deb http://myserver/path/to/repo stable myrepo'
  36.     apt-add-repository 'http://myserver/path/to/repo myrepo'
  37.     apt-add-repository 'https://packages.medibuntu.org free non-free'
  38.     apt-add-repository http://extras.ubuntu.com/ubuntu
  39.     apt-add-repository ppa:user/repository
  40.     apt-add-repository multiverse
  41. If --remove is given the tool will remove the given sourceline from your
  42. sources.list
  43. """
  44.     parser = OptionParser(usage)
  45.     # FIXME: provide a --sources-list-file= option that
  46.     #        puts the line into a specific file in sources.list.d
  47.     parser.add_option ("-m", "--massive-debug", action="store_true",
  48.         dest="massive_debug", default=False,
  49.         help=_("Print a lot of debug information to the command line"))
  50.     parser.add_option("-r", "--remove", action="store_true",
  51.         dest="remove", default=False,
  52.         help=_("remove repository from sources.list.d directory"))
  53.     parser.add_option("-k", "--keyserver",
  54.         dest="keyserver", default=DEFAULT_KEYSERVER,
  55.         help=_("URL of keyserver. Default: %default"))
  56.     parser.add_option("-s", "--enable-source", action="store_true",
  57.         dest="enable_source", default=False,
  58.         help=_("Allow downloading of the source packages from the repository"))
  59.     parser.add_option("-y", "--yes", action="store_true",
  60.         dest="assume_yes", default=False,
  61.         help=_("Assume yes to all queries"))
  62.     (options, args) = parser.parse_args()
  63.     if os.geteuid() != 0:
  64.         print(_("Error: must run as root"))
  65.         sys.exit(1)
  66.     if len(args) == 0:
  67.         print(_("Error: need a repository as argument"))
  68.         sys.exit(1)
  69.     elif len(args) > 1:
  70.         print(_("Error: need a single repository as argument"))
  71.         sys.exit(1)
  72.     # force new ppa file to be 644 (LP: #399709)
  73.     os.umask(0o022)
  74.     # get the line
  75.     line = args[0]
  76.     # add it
  77.     sp = SoftwareProperties(options=options)
  78.     distro = aptsources.distro.get_distro()
  79.     distro.get_sources(sp.sourceslist)
  80.     # check if its a component that should be added/removed
  81.     components = [comp.name for comp in distro.source_template.components]
  82.     if line in components:
  83.         if options.remove:
  84.             if line in distro.enabled_comps:
  85.                 distro.disable_component(line)
  86.                 print(_("'%s' distribution component disabled for all sources.") % line)
  87.             else:
  88.                 print(_("'%s' distribution component is already disabled for all sources.") % line)
  89.                 sys.exit(0)
  90.         else:
  91.             if line not in distro.enabled_comps:
  92.                 distro.enable_component(line)
  93.                 print(_("'%s' distribution component enabled for all sources.") % line)
  94.             else:
  95.                 print(_("'%s' distribution component is already enabled for all sources.") % line)
  96.                 sys.exit(0)
  97.         sp.sourceslist.save()
  98.         sys.exit(0)
  99.     # this wasn't a component name ('multiverse', 'backports'), so its either
  100.     # a actual line to be added or a shortcut.
  101.     try:
  102.         shortcut = shortcut_handler(line)
  103.     except ShortcutException as e:
  104.         print(e)
  105.         sys.exit(1)
  106.     # display more information about the shortcut / ppa info
  107.     if not options.assume_yes and shortcut.should_confirm():
  108.         try:
  109.             info = shortcut.info()
  110.         except ShortcutException as e:
  111.             print(e)
  112.             sys.exit(1)
  113.         print(" %s" % (info["description"] or ""))
  114.         print(_(" More info: %s") % str(info["web_link"]))
  115.         if (sys.stdin.isatty() and
  116.             not "FORCE_ADD_APT_REPOSITORY" in os.environ):
  117.             if options.remove:
  118.                 print(_("Press [ENTER] to continue or ctrl-c to cancel removing it"))
  119.             else:
  120.                 print(_("Press [ENTER] to continue or ctrl-c to cancel adding it"))
  121.             sys.stdin.readline()
  122.     if options.remove:
  123.         try:
  124.             (line, file) = shortcut.expand(sp.distro.codename)
  125.         except ShortcutException as e:
  126.             print(e)
  127.             sys.exit(1)
  128.         deb_line = sp.expand_http_line(line)
  129.         debsrc_line = 'deb-src' + deb_line[3:]
  130.         deb_entry = SourceEntry(deb_line, file)
  131.         debsrc_entry = SourceEntry(debsrc_line, file)
  132.         try:
  133.             sp.remove_source(deb_entry)
  134.         except ValueError:
  135.             print(_("Error: '%s' doesn't exist in a sourcelist file") % deb_line)
  136.         try:
  137.             sp.remove_source(debsrc_entry)
  138.         except ValueError:
  139.             print(_("Error: '%s' doesn't exist in a sourcelist file") % debsrc_line)
  140.     else:
  141.         try:
  142.             if not sp.add_source_from_shortcut(shortcut, options.enable_source):
  143.                 print(_("Error: '%s' invalid") % line)
  144.                 sys.exit(1)
  145.         except ShortcutException as e:
  146.             print(e)
  147.             sys.exit(1)
  148.         
  149.         sp.sourceslist.save()
Copy the Code
Reply View the author
foundix
deepin
2014-05-17 05:24
#2
/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py
  1. #  software-properties backend
  2. #
  3. #  Copyright (c) 2004-2007 Canonical Ltd.
  4. #                2004-2005 Michiel Sikkes
  5. #
  6. #  Author: Michiel Sikkes
  7. #          Michael Vogt
  8. #          Sebastian Heinlein
  9. #
  10. #  This program is free software; you can redistribute it and/or
  11. #  modify it under the terms of the GNU General Public License as
  12. #  published by the Free Software Foundation; either version 2 of the
  13. #  License, or (at your option) any later version.
  14. #
  15. #  This program is distributed in the hope that it will be useful,
  16. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. #  GNU General Public License for more details.
  19. #
  20. #  You should have received a copy of the GNU General Public License
  21. #  along with this program; if not, write to the Free Software
  22. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  23. #  USA
  24. from __future__ import absolute_import, print_function
  25. import apt_pkg
  26. import copy
  27. from hashlib import md5
  28. import re
  29. import os
  30. import glob
  31. import shutil
  32. import threading
  33. import atexit
  34. import tempfile
  35. try:
  36.   from string import maketrans
  37. except ImportError:
  38.   maketrans = str.maketrans
  39. import stat
  40. from tempfile import NamedTemporaryFile
  41. from xml.sax.saxutils import escape
  42. try:
  43.   from configparser import ConfigParser
  44. except ImportError:
  45.   from ConfigParser import ConfigParser
  46. from gettext import gettext as _
  47. import aptsources
  48. import aptsources.distro
  49. import softwareproperties
  50. from .AptAuth import AptAuth
  51. from aptsources.sourceslist import SourcesList, SourceEntry
  52. from . import shortcuts
  53. from . import ppa
  54. from . import cloudarchive
  55. _SHORTCUT_FACTORIES = [
  56.     ppa.shortcut_handler,
  57.     cloudarchive.shortcut_handler,
  58.     shortcuts.shortcut_handler,
  59. ]
  60. class SoftwareProperties(object):
  61.   # known (whitelisted) channels
  62.   CHANNEL_PATH="/usr/share/app-install/channels/"
  63.   # release upgrades policy
  64.   RELEASE_UPGRADES_CONF = "/etc/update-manager/release-upgrades"
  65.   #RELEASE_UPGRADES_CONF = "/tmp/release-upgrades"
  66.   (
  67.     RELEASE_UPGRADES_NORMAL,
  68.     RELEASE_UPGRADES_LTS,
  69.     RELEASE_UPGRADES_NEVER
  70.   ) = list(range(3))
  71.   release_upgrades_policy_map = {
  72.     RELEASE_UPGRADES_NORMAL : 'normal',
  73.     RELEASE_UPGRADES_LTS    : 'lts',
  74.     RELEASE_UPGRADES_NEVER  : 'never',
  75.   }
  76.   
  77.   def __init__(self, datadir=None, options=None, rootdir="/"):
  78.     """ Provides the core functionality to configure the used software
  79.         repositories, the corresponding authentication keys and
  80.         update automation """
  81.     self.popconfile = rootdir+"/etc/popularity-contest.conf"
  82.     self.rootdir = rootdir
  83.     if rootdir != "/":
  84.       apt_pkg.config.set("Dir", rootdir)
  85.     # FIXME: some saner way is needed here
  86.     if datadir == None:
  87.       datadir = "/usr/share/software-properties/"
  88.     self.options = options
  89.     self.datadir = datadir
  90.     self.sourceslist = SourcesList()
  91.     self.distro = aptsources.distro.get_distro()
  92.    
  93.     self.seen_server = []
  94.     self.modified_sourceslist = False
  95.     self.reload_sourceslist()
  96.     self.backup_sourceslist()
  97.     self.backup_apt_conf()
  98.     # FIXME: we need to store this value in a config option
  99.     #self.custom_mirrors = ["http://adasdwww.de/ubuntu"]
  100.     self.custom_mirrors= []
  101.     # apt-key stuff
  102.     self.apt_key = AptAuth(rootdir=rootdir)
  103.     atexit.register(self.wait_for_threads)
  104.   def wait_for_threads(self):
  105.     " wait for all running threads (PPA key fetchers) to exit "
  106.     for t in threading.enumerate():
  107.       if t.ident != threading.current_thread().ident:
  108.         t.join()
  109.   def backup_apt_conf(self):
  110.     """Backup all apt configuration options"""
  111.     self.apt_conf_backup = {}
  112.     for option in softwareproperties.CONF_MAP.keys():
  113.         value = apt_pkg.config.find_i(softwareproperties.CONF_MAP[option])
  114.         self.apt_conf_backup[option] = value
  115.   def restore_apt_conf(self):
  116.     """Restore the stored apt configuration"""
  117.     for option in self.apt_conf_backup.keys():
  118.         apt_pkg.config.set(softwareproperties.CONF_MAP[option],
  119.                            str(self.apt_conf_backup[option]))
  120.     self.write_config()
  121.   def get_update_automation_level(self):
  122.     """ Parse the apt cron configuration. Try to fit a predefined use case
  123.         and return it. Special case: if the user made a custom
  124.         configurtation, that we cannot represent it will return None """
  125.     if apt_pkg.config.find_i(softwareproperties.CONF_MAP["autoupdate"]) > 0:
  126.         # Autodownload
  127.         if apt_pkg.config.find_i(softwareproperties.CONF_MAP["unattended"]) == 1\
  128.            and apt_pkg.config.find_i(softwareproperties.CONF_MAP["autodownload"]) == 1 :
  129.             return softwareproperties.UPDATE_INST_SEC
  130.         elif apt_pkg.config.find_i(softwareproperties.CONF_MAP["autodownload"]) == 1 and  \
  131.              apt_pkg.config.find_i(softwareproperties.CONF_MAP["unattended"]) == 0:
  132.             return softwareproperties.UPDATE_DOWNLOAD
  133.         elif apt_pkg.config.find_i(softwareproperties.CONF_MAP["unattended"]) == 0 and \
  134.              apt_pkg.config.find_i(softwareproperties.CONF_MAP["autodownload"]) == 0:
  135.             return softwareproperties.UPDATE_NOTIFY
  136.         else:
  137.             return None
  138.     elif apt_pkg.config.find_i(softwareproperties.CONF_MAP["unattended"]) == 0 and \
  139.          apt_pkg.config.find_i(softwareproperties.CONF_MAP["autodownload"]) == 0:
  140.         return softwareproperties.UPDATE_MANUAL
  141.     else:
  142.         return None
  143.   def set_update_automation_level(self, state):
  144.     """ Set the apt periodic configurtation to the selected
  145.         update automation level. To synchronize the cache update and the
  146.         actual upgrading function, the upgrade function, e.g. unattended,
  147.         will run every day, if enabled. """
  148.     if state == softwareproperties.UPDATE_INST_SEC:
  149.         apt_pkg.config.set(softwareproperties.CONF_MAP["unattended"], str(1))
  150.         apt_pkg.config.set(softwareproperties.CONF_MAP["autodownload"], str(1))
  151.     elif state == softwareproperties.UPDATE_DOWNLOAD:
  152.         apt_pkg.config.set(softwareproperties.CONF_MAP["autodownload"], str(1))
  153.         apt_pkg.config.set(softwareproperties.CONF_MAP["unattended"], str(0))
  154.     elif state == softwareproperties.UPDATE_NOTIFY:
  155.         apt_pkg.config.set(softwareproperties.CONF_MAP["autodownload"], str(0))
  156.         apt_pkg.config.set(softwareproperties.CONF_MAP["unattended"], str(0))
  157.     else:
  158.         apt_pkg.config.set(softwareproperties.CONF_MAP["autoupdate"], str(0))
  159.         apt_pkg.config.set(softwareproperties.CONF_MAP["unattended"], str(0))
  160.         apt_pkg.config.set(softwareproperties.CONF_MAP["autodownload"], str(0))
  161.     self.set_modified_config()
  162.   def set_update_interval(self, days):
  163.       """Set the interval in which we check for available updates"""
  164.       # Only write the key if it has changed
  165.       if not days == apt_pkg.config.find_i(softwareproperties.CONF_MAP["autoupdate"]):
  166.           apt_pkg.config.set(softwareproperties.CONF_MAP["autoupdate"], str(days))
  167.           self.set_modified_config()
  168.   def get_update_interval(self):
  169.     """ Returns the interval of the apt periodic cron job """
  170.     return apt_pkg.config.find_i(softwareproperties.CONF_MAP["autoupdate"])
  171.   def get_release_upgrades_policy(self):
  172.     """
  173.     return the release upgrade policy:
  174.      RELEASE_UPGRADES_NORMAL,
  175.      RELEASE_UPGRADES_LTS,
  176.      RELEASE_UPGRADES_NEVER
  177.     """
  178.     # default (if no option is set) is NORMAL
  179.     if not os.path.exists(self.RELEASE_UPGRADES_CONF):
  180.       return self.RELEASE_UPGRADES_NORMAL
  181.     parser = ConfigParser()
  182.     parser.read(self.RELEASE_UPGRADES_CONF)
  183.     if parser.has_option("DEFAULT","Prompt"):
  184.       type = parser.get("DEFAULT","Prompt").lower()
  185.       for k, v in self.release_upgrades_policy_map.items():
  186.         if v == type:
  187.           return k
  188.     return self.RELEASE_UPGRADES_NORMAL
  189.   def set_release_upgrades_policy(self, i):
  190.     """
  191.     set the release upgrade policy:
  192.      RELEASE_UPGRADES_NORMAL,
  193.      RELEASE_UPGRADES_LTS,
  194.      RELEASE_UPGRADES_NEVER
  195.      """
  196.     # we are note using ConfigParser.write() as it removes comments
  197.     if not os.path.exists(self.RELEASE_UPGRADES_CONF):
  198.       f = open(self.RELEASE_UPGRADES_CONF,"w")
  199.       f.write("[DEFAULT]\nPrompt=%s\n"% self.release_upgrades_policy_map[i])
  200.       return True
  201.     f = open(self.RELEASE_UPGRADES_CONF,"r")
  202.     out = NamedTemporaryFile(mode="w+")
  203.     for line in f:
  204.       line = line.strip()
  205.       if line.lower().startswith("prompt"):
  206.         out.write("Prompt=%s\n" % self.release_upgrades_policy_map[i])
  207.       else:
  208.         out.write(line+"\n")
  209.     out.flush()
  210.     shutil.copymode(self.RELEASE_UPGRADES_CONF, out.name)
  211.     shutil.copy(out.name, self.RELEASE_UPGRADES_CONF)
  212.     return True
  213.   def get_popcon_participation(self):
  214.     """ Will return True if the user wants to participate in the popularity
  215.         contest. Otherwise it will return False. Special case: if no
  216.         popcon is installed it will return False """
  217.     if os.path.exists(self.popconfile):
  218.         lines = open(self.popconfile).read().split("\n")
  219.         active = False
  220.         for line in lines:
  221.             try:
  222.                 (key,value) = line.split("=")
  223.                 if key == "PARTICIPATE" and value.strip('"').lower() == "yes":
  224.                     active = True
  225.             except ValueError:
  226.                 continue
  227.         return active
  228.     else:
  229.         return False
  230.   def set_popcon_pariticipation(self, is_helpful):
  231.     """ Enable or disable the participation in the popularity contest """
  232.     if is_helpful == True:
  233.         value = "yes"
  234.     else:
  235.         value = "no"
  236.     if os.path.exists(self.popconfile):
  237.         # read the current config and replace the corresponding settings
  238.         # FIXME: should we check the other values, too?
  239.         with open(self.popconfile, "r") as popconfile:
  240.             lines = [re.sub(r'^(PARTICIPATE=)(".+?")', '\\1"%s"' % value, line)
  241.                      for line in popconfile]
  242.     else:
  243.         # create a new popcon config file
  244.         m = md5()
  245.         m.update(open("/dev/urandom", "rb").read(1024))
  246.         id = m.hexdigest()
  247.         lines = []
  248.         lines.append("MY_HOSTID=\"%s\"\n" % id)
  249.         lines.append("PARTICIPATE=\"%s\"\n" % str(value))
  250.         lines.append("USE_HTTP=\"yes\"\n")
  251.     open(self.popconfile, "w").writelines(lines)
  252.   def get_source_code_state(self):
  253.     """Return True if all distro componets are also available as
  254.        source code. Otherwise return Flase. Special case: If the
  255.        configuration cannot be represented return None"""
  256.   
  257.     if len(self.distro.source_code_sources) < 1:
  258.         # we don't have any source code sources, so
  259.         # uncheck the button
  260.         self.distro.get_source_code = False
  261.         return False
  262.     else:
  263.         # there are source code sources, so we check the button
  264.         self.distro.get_source_code = True
  265.         # check if there is a corresponding source code source for
  266.         # every binary source. if not set the checkbutton to inconsistent
  267.         templates = {}
  268.         sources = []
  269.         sources.extend(self.distro.main_sources)
  270.         sources.extend(self.distro.child_sources)
  271.         for source in sources:
  272.             if source.template in templates:
  273.                 for comp in source.comps:
  274.                     templates[source.template].add(comp)
  275.             else:
  276.                 templates[source.template] = set(source.comps)
  277.         # add fake http sources for the cdrom, since the sources
  278.         # for the cdrom are only available in the internet
  279.         if len(self.distro.cdrom_sources) > 0:
  280.             templates[self.distro.source_template] = self.distro.cdrom_comps
  281.         for source in self.distro.source_code_sources:
  282.             if source.template not in templates or \
  283.                (source.template in templates and not \
  284.                 (len(set(templates[source.template]) ^ set(source.comps)) == 0\
  285.                  or (len(set(source.comps) ^ self.distro.enabled_comps) == 0))):
  286.                 self.distro.get_source_code = False
  287.                 return None
  288.                 break
  289.     return True
  290.   def print_source_entry(self, source):
  291.     """Print the data of a source entry to the command line"""
  292.     for (label, value) in [("URI:", source.uri),
  293.                            ("Comps:", source.comps),
  294.                            ("Enabled:", not source.disabled),
  295.                            ("Valid:", not source.invalid)]:
  296.         print(" %s %s" % (label, value))
  297.     if source.template:
  298.         for (label, value) in [("MatchURI:", source.template.match_uri),
  299.                                ("BaseURI:", source.template.base_uri)]:
  300.             print(" %s %s" % (label, value))
  301.     print("\n")
  302.   def massive_debug_output(self):
  303.     """Print the complete sources.list"""
  304.     print("START SOURCES.LIST:")
  305.     for source in self.sourceslist:
  306.         print(source.str())
  307.     print("END SOURCES.LIST\n")
  308.   def change_main_download_server(self, server):
  309.     """ change the main download server """
  310.     self.distro.default_server = server
  311.     res = self.distro.change_server(server)
  312.     self.set_modified_sourceslist()
  313.     return res
  314.   def enable_component(self, comp):
  315.     """Enable a component of the distro"""
  316.     self.distro.enable_component(comp)
  317.     self.set_modified_sourceslist()
  318.   def disable_component(self, comp):
  319.     """Disable a component of the distro"""
  320.     self.distro.disable_component(comp)
  321.     self.set_modified_sourceslist()
  322.   def _find_template_from_string(self, name):
  323.     for template in self.distro.source_template.children:
  324.       if template.name == name:
  325.         return template
  326.   def disable_child_source(self, template):
  327.     """Enable a child repo of the distribution main repository"""
  328.     if isinstance(template, str):
  329.       template = self._find_template_from_string(template)
  330.     for source in self.distro.child_sources:
  331.         if source.template == template:
  332.             self.sourceslist.remove(source)
  333.     for source in self.distro.source_code_sources:
  334.         if source.template == template:
  335.             self.sourceslist.remove(source)
  336.     self.set_modified_sourceslist()
  337.   def enable_child_source(self, template):
  338.     """Enable a child repo of the distribution main repository"""
  339.     if isinstance(template, str):
  340.       template = self._find_template_from_string(template)
  341.     # Use the currently selected mirror only if the child source
  342.     # did not override the server
  343.     if template.base_uri == None:
  344.         child_uri = self.distro.default_server
  345.     else:
  346.         child_uri = template.base_uri
  347.     self.distro.add_source(uri=child_uri, dist=template.name)
  348.     self.set_modified_sourceslist()
  349.   def disable_source_code_sources(self):
  350.     """Remove all distro source code sources"""
  351.     sources = []
  352.     sources.extend(self.distro.main_sources)
  353.     sources.extend(self.distro.child_sources)
  354.     # remove all exisiting sources
  355.     for source in self.distro.source_code_sources:
  356.         self.sourceslist.remove(source)
  357.     self.set_modified_sourceslist()
  358.   
  359.   def enable_source_code_sources(self):
  360.     """Enable source code source for all distro sources"""
  361.     sources = []
  362.     sources.extend(self.distro.main_sources)
  363.     sources.extend(self.distro.child_sources)
  364.     # remove all exisiting sources
  365.     for source in self.distro.source_code_sources:
  366.         self.sourceslist.remove(source)
  367.     for source in sources:
  368.         self.sourceslist.add("deb-src",
  369.                              source.uri,
  370.                              source.dist,
  371.                              source.comps,
  372.                              "Added by software-properties",
  373.                              self.sourceslist.list.index(source)+1,
  374.                              source.file)
  375.     for source in self.distro.cdrom_sources:
  376.         self.sourceslist.add("deb-src",
  377.                              self.distro.source_template.base_uri,
  378.                              self.distro.source_template.name,
  379.                              source.comps,
  380.                              "Added by software-properties",
  381.                              self.sourceslist.list.index(source)+1,
  382.                              source.file)
  383.     self.set_modified_sourceslist()
  384.   def backup_sourceslist(self):
  385.     """Store a backup of the source.list in memory"""
  386.     self.sourceslist_backup = []
  387.     for source in self.sourceslist.list:
  388.         source_bkp = SourceEntry(line=source.line,file=source.file)
  389.         self.sourceslist_backup.append(source_bkp)
  390.   
  391.   def _find_source_from_string(self, line):
  392.     # ensure that we have a current list, it might have been changed underneath
  393.     # us
  394.     self.reload_sourceslist()
  395.     for source in self.sourceslist.list:
  396.       if str(source) == line:
  397.         return source
  398.     return None
  399.   def toggle_source_use(self, source):
  400.     """Enable or disable the selected channel"""
  401.     #FIXME cdroms need to disable the comps in the childs and sources
  402.     if isinstance(source, str):
  403.       source = self._find_source_from_string(source)
  404.     source.disabled = not source.disabled
  405.     self.set_modified_sourceslist()
  406.   def replace_source_entry(self, old_entry, new_entry):
  407.     # find and replace, then write
  408.     for (index, entry) in enumerate(self.sourceslist.list):
  409.       if str(entry) == old_entry:
  410.         file = self.sourceslist.list[index].file
  411.         self.sourceslist.list[index] = SourceEntry(new_entry, file)
  412.         self.set_modified_sourceslist()
  413.         return True
  414.     return False
  415.   def revert(self):
  416.     """Revert all settings to the state when software-properties
  417.        was launched"""
  418.     #FIXME: GPG keys are still missing
  419.     self.restore_apt_conf()
  420.     self.revert_sourceslist()
  421.   def revert_sourceslist(self):
  422.     """Restore the source list from the startup of the dialog"""
  423.     self.sourceslist.list = []
  424.     for source in self.sourceslist_backup:
  425.         source_reset = SourceEntry(line=source.line,file=source.file)
  426.         self.sourceslist.list.append(source_reset)
  427.     self.save_sourceslist()
  428.     self.reload_sourceslist()
  429.   def set_modified_sourceslist(self):
  430.     """The sources list was changed and now needs to be saved and reloaded"""
  431.     self.modified_sourceslist = True
  432.     if self.options and self.options.massive_debug:
  433.         self.massive_debug_output()
  434.     self.save_sourceslist()
  435.     self.reload_sourceslist()
  436.   def set_modified_config(self):
  437.     """Write the changed apt configuration to file"""
  438.     self.write_config()
  439.   def render_source(self, source):
  440.     """Render a nice output to show the source in a treeview"""
  441.     if source.template == None:
  442.         if source.comment:
  443.             contents = "%s %s" % (escape(source.comment).strip(),
  444.                                          source.dist)
  445.             # Only show the components if there are more than one
  446.             if len(source.comps) > 1:
  447.                 for c in source.comps:
  448.                     contents += " %s" % c
  449.             if source.type in ("deb-src", "rpm-src"):
  450.                 contents += " %s" % _("(Source Code)")
  451.             contents += "\n%s" % source.uri
  452.         else:
  453.             contents = "%s %s" % (source.uri, source.dist)
  454.             for c in source.comps:
  455.                 contents += " %s" % c
  456.             if source.type in ("deb-src", "rpm-src"):
  457.                 contents += " %s" % _("(Source Code)")
  458.         return contents
  459.     else:
  460.         # try to make use of a corresponding template
  461.         contents = "%s" % source.template.description
  462.         if source.type in ("deb-src", "rpm-src"):
  463.             contents += " (%s)" % _("Source Code")
  464.         if source.comment:
  465.             contents +=" %s" % source.comment
  466.         if source.template.child == False:
  467.             for comp in source.comps:
  468.                 if source.template.has_component(comp):
  469.                     # fixme: move something like this into distinfo.Template
  470.                     #        (why not use a dictionary again?)
  471.                     for c in source.template.components:
  472.                         if c.name == comp:
  473.                             contents += "\n%s" % c.description
  474.                 else:
  475.                     contents += "\n%s" % comp
  476.         return contents
  477.   def get_comparable(self, source):
  478.       """extract attributes to sort the sources"""
  479.       cur_sys = 1
  480.       has_template = 1
  481.       has_comment = 1
  482.       is_source = 1
  483.       revert_numbers = maketrans("0123456789", "9876543210")
  484.       if source.template:
  485.         has_template = 0
  486.         desc = source.template.description
  487.         if source.template.distribution == self.distro:
  488.             cur_sys = 0
  489.       else:
  490.           desc = "%s %s %s" % (source.uri, source.dist, source.comps)
  491.           if source.comment:
  492.               has_comment = 0
  493.       if source.type.find("src"):
  494.           is_source = 0
  495.       return (cur_sys, has_template, has_comment, is_source,
  496.               desc.translate(revert_numbers))
  497.   def get_isv_sources(self):
  498.     """Return a list of sources that are not part of the distribution"""
  499.     isv_sources = []
  500.     for source in self.sourceslist.list:
  501.         if not source.invalid and\
  502.            (source not in self.distro.main_sources and\
  503.             source not in self.distro.cdrom_sources and\
  504.             source not in self.distro.child_sources and\
  505.             source not in self.distro.disabled_sources) and\
  506.            source not in self.distro.source_code_sources:
  507.             isv_sources.append(source)
  508.     return isv_sources
  509.   def get_cdrom_sources(self):
  510.     """Return the list of CDROM based distro sources"""
  511.     return self.distro.cdrom_sources
  512.       
  513.   def get_comp_download_state(self, comp):
  514.     """Return a tuple: the first value describes if a component is enabled
  515.        in the Internet repositories. The second value describes if the
  516.        first value is inconsistent."""
  517.     #FIXME: also return a correct inconsistent value
  518.     return (comp.name in self.distro.download_comps, False)
  519.   def get_comp_child_state(self, template):
  520.     """Return a tuple: the first value describes if a component is enabled
  521.        in one of the child source that matcth the given template.
  522.        The second value describes if the first value is inconsistent."""
  523.     comps = []
  524.     for child in self.distro.child_sources:
  525.         if child.template == template:
  526.             comps.extend(child.comps)
  527.     if len(comps) > 0 and \
  528.         len(self.distro.enabled_comps ^ set(comps)) == 0:
  529.         # All enabled distro components are also enabled for the child source
  530.         return (True, False)
  531.     elif len(comps) > 0 and\
  532.         len(self.distro.enabled_comps ^ set(comps)) != 0:
  533.         # A matching child source does exist but doesn't include all
  534.         # enabled distro components
  535.         return(False, True)
  536.     else:
  537.         # There is no corresponding child source at all
  538.         return (False, False)
  539.   
  540.   def reload_sourceslist(self):
  541.     self.sourceslist.refresh()
  542.     self.sourceslist_visible=[]
  543.     self.distro.get_sources(self.sourceslist)   
  544.   def write_config(self):
  545.     """Write the current apt configuration to file"""
  546.     # update the adept file as well if it is there
  547.     conffiles = [self.rootdir+"/etc/apt/apt.conf.d/10periodic",
  548.                  self.rootdir+"/etc/apt/apt.conf.d/20auto-upgrades",
  549.                  self.rootdir+"/etc/apt/apt.conf.d/15adept-periodic-update"]
  550.     # check (beforehand) if one exists, if not create one
  551.     for f in conffiles:
  552.       if os.path.isfile(f):
  553.         break
  554.     else:
  555.       print("No config found, creating one")
  556.       open(conffiles[0], "w")
  557.     # ensure /etc/cron.daily/apt is executable
  558.     ac = "/etc/cron.daily/apt"
  559.     if os.path.exists(ac):
  560.       perm = os.stat(ac)[stat.ST_MODE]
  561.       if not (perm & stat.S_IXUSR):
  562.         print("file '%s' not executable, fixing" % ac)
  563.         os.chmod(ac, 0o755)
  564.     # now update them
  565.     for periodic in conffiles:
  566.       # read the old content first
  567.       content = []
  568.       if os.path.isfile(periodic):
  569.         content = open(periodic, "r").readlines()
  570.         cnf = apt_pkg.config.subtree("APT::Periodic")
  571.         # then write a new file without the updated keys
  572.         f = open(periodic, "w")
  573.         for line in content:
  574.           for key in cnf.list():
  575.             if line.find("APT::Periodic::%s" % (key)) >= 0:
  576.               break
  577.           else:
  578.             f.write(line)
  579.         # and append the updated keys
  580.         for i in cnf.list():
  581.           f.write("APT::Periodic::%s \"%s\";\n" % (i, cnf.find_i(i)))
  582.         f.close()   
  583.   def save_sourceslist(self):
  584.     """Backup the existing sources.list files and write the current
  585.        configuration"""
  586.     self.sourceslist.backup(".save")
  587.     self.sourceslist.save()
  588.   def _is_line_in_whitelisted_channel(self, srcline):
  589.     """
  590.     helper that checks if a given line is in the source list
  591.     return the channel name or None if not found
  592.     """
  593.     srcentry = SourceEntry(srcline)
  594.     if os.path.exists(self.CHANNEL_PATH):
  595.       for f in glob.glob("%s/*.list" % self.CHANNEL_PATH):
  596.         for line in open(f):
  597.           if line.strip().startswith("#"):
  598.             continue
  599.           if srcentry == SourceEntry(line):
  600.             return os.path.splitext(os.path.basename(f))[0]
  601.     return None
  602.   def check_and_add_key_for_whitelisted_channels(self, srcline):
  603.     # This is maintained for any legacy callers
  604.     return self.check_and_add_key_for_whitelisted_shortcut(shortcut_handler(srcline))
  605.   def check_and_add_key_for_whitelisted_shortcut(self, shortcut):
  606.     """
  607.     helper that adds the gpg key of the channel to the apt
  608.     keyring *if* the channel is in the whitelist
  609.     /usr/share/app-install/channels or it is a public Launchpad PPA.
  610.     """
  611.     (srcline, _fname) = shortcut.expand(codename=self.distro.codename)
  612.     channel = self._is_line_in_whitelisted_channel(srcline)
  613.     if channel:
  614.       keyp = "%s/%s.key" % (self.CHANNEL_PATH, channel)
  615.       self.add_key(keyp)
  616.     cdata = (shortcut.add_key, {'keyserver': (self.options and
  617.                                               self.options.keyserver)})
  618.     def addkey_func():
  619.         func, kwargs = cdata
  620.         func(**kwargs)
  621.     worker = threading.Thread(target=addkey_func)
  622.     worker.start()
  623.     return worker
  624.   def update_interface(self):
  625.     " abstract interface to keep the UI alive "
  626.   def expand_http_line(self, line):
  627.     """
  628.     short cut - this:
  629.       apt-add-repository http://packages.medibuntu.org free non-free
  630.     same as
  631.       apt-add-repository 'deb http://packages.medibuntu.org/ '$(lsb_release -cs)' free non-free'
  632.     """
  633.     if not line.startswith("http"):
  634.       return line
  635.     repo = line.split()[0]
  636.     try:
  637.         areas = line.split(" ",1)[1]
  638.     except IndexError:
  639.         areas = "main"
  640.     line = "deb %s %s %s" % ( repo, self.distro.codename, areas )
  641.     return line
  642.   def add_source_from_line(self, line, enable_source_code=False):
  643.     """
  644.     Add a source for the given line.
  645.     """
  646.     return self.add_source_from_shortcut(
  647.         shortcut=shortcut_handler(line.strip()),
  648.         enable_source_code=enable_source_code)
  649.   def add_source_from_shortcut(self, shortcut, enable_source_code=False):
  650.     """
  651.     Add a source with the given shortcut and add the signing key if the
  652.     site is in whitelist or the shortcut implementer adds it.
  653.     """
  654.     (deb_line, file) = shortcut.expand(codename=self.distro.codename)
  655.     deb_line = self.expand_http_line(deb_line)
  656.     debsrc_entry_type = 'deb-src' if enable_source_code else '# deb-src'
  657.     debsrc_line = debsrc_entry_type + deb_line[3:]
  658.     new_deb_entry = SourceEntry(deb_line, file)
  659.     new_debsrc_entry = SourceEntry(debsrc_line, file)
  660.     if new_deb_entry.invalid or new_debsrc_entry.invalid:
  661.       return False
  662.     worker = self.check_and_add_key_for_whitelisted_shortcut(shortcut)
  663.     self.sourceslist.add(new_deb_entry.type,
  664.                          new_deb_entry.uri,
  665.                          new_deb_entry.dist,
  666.                          new_deb_entry.comps,
  667.                          comment=new_deb_entry.comment,
  668.                          file=new_deb_entry.file,
  669.                          architectures=new_deb_entry.architectures)
  670.     self.sourceslist.add(debsrc_entry_type,
  671.                          new_debsrc_entry.uri,
  672.                          new_debsrc_entry.dist,
  673.                          new_debsrc_entry.comps,
  674.                          comment=new_debsrc_entry.comment,
  675.                          file=new_debsrc_entry.file,
  676.                          architectures=new_debsrc_entry.architectures)
  677.     self.set_modified_sourceslist()
  678.     if worker:
  679.         # wait for GPG key to be downloaded
  680.         worker.join(30)
  681.     return True
  682.   def remove_source(self, source, remove_source_code=True):
  683.     """Remove the given source"""
  684.     if remove_source_code:
  685.       if isinstance(source, str):
  686.         # recall this method giving a SourceEntry as an argument
  687.         source = self._find_source_from_string(source)
  688.         self.remove_source(source, True)
  689.       elif source is not None:
  690.         self.remove_source(source, False)
  691.         # remove the deb-src lines (enabled or not) associated to
  692.         # this source entry
  693.         source = copy.copy(source)
  694.         source.type = 'deb-src'
  695.         source.disabled = True
  696.         self.remove_source(source, False)
  697.         source.disabled = False
  698.         self.remove_source(source, False)
  699.       return
  700.     # first find the source object if we got a string
  701.     if isinstance(source, str):
  702.       source = self._find_source_from_string(source)
  703.     if source is None:
  704.       return
  705.     # if its a sources.list.d file and it contains only a single line
  706.     # (the line that we just remove), then all references to that
  707.     # file are gone and the file is not saved. we work around that
  708.     # here
  709.     if source.file != apt_pkg.config.find_file("Dir::Etc::sourcelist"):
  710.       self.sourceslist.list.append(SourceEntry("", file=source.file))
  711.     try:
  712.       self.sourceslist.remove(source)
  713.     except ValueError:
  714.       # this exception is raised if trying to remove an entry that does
  715.       # not exist. in this case we suppress the error because there's no
  716.       # need to propagate it (the aim of this method is to ensure that
  717.       # the given entries are not listed in the sourceslist)
  718.       pass
  719.     self.set_modified_sourceslist()
  720.   def add_key(self, path):
  721.     """Add a gnupg key to the list of trusted software vendors"""
  722.     if not isinstance(path, str):
  723.       path = str(path) # allows non-ascii filenames
  724.     if not os.path.exists(path):
  725.         return False
  726.     try:
  727.         res = self.apt_key.add(path)
  728.         self.KeysModified()
  729.         return res
  730.     except:
  731.         return False
  732.   def add_key_from_data(self, keydata):
  733.     "Add a gnupg key from a data string (e.g. copy-n-paste)"
  734.     tmp = tempfile.NamedTemporaryFile()
  735.     tmp.write(keydata.encode())
  736.     tmp.flush()
  737.     return self.add_key(tmp.name)
  738.   def remove_key(self, keyid):
  739.     """Remove a gnupg key from the list of trusted software vendors"""
  740.     try:
  741.         self.apt_key.rm(keyid)
  742.         self.KeysModified()
  743.         return True
  744.     except:
  745.         return False
  746.   def update_keys(self):
  747.     """ Run apt-key update """
  748.     try:
  749.       self.apt_key.update()
  750.       self.KeysModified()
  751.       return True
  752.     except:
  753.       return False
  754. def shortcut_handler(shortcut):
  755.     for factory in _SHORTCUT_FACTORIES:
  756.         ret = factory(shortcut)
  757.         if ret is not None:
  758.             return ret
  759.     raise shortcuts.ShortcutException("Unable to handle input '%s'" % shortcut)
  760. if __name__ == "__main__":
  761.   sp = SoftwareProperties()
  762.   print(sp.get_release_upgrades_policy())
  763.   sp.set_release_upgrades_policy(0)
Copy the Code
Reply View the author
foundix
deepin
2014-05-17 05:24
#3
/usr/lib/python3/dist-packages/aptsources/distro.py
  1. #  distro.py - Provide a distro abstraction of the sources.list
  2. #
  3. #  Copyright (c) 2004-2009 Canonical Ltd.
  4. #  Copyright (c) 2006-2007 Sebastian Heinlein
  5. #
  6. #  Authors: Sebastian Heinlein
  7. #           Michael Vogt
  8. #
  9. #  This program is free software; you can redistribute it and/or
  10. #  modify it under the terms of the GNU General Public License as
  11. #  published by the Free Software Foundation; either version 2 of the
  12. #  License, or (at your option) any later version.
  13. #
  14. #  This program is distributed in the hope that it will be useful,
  15. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. #  GNU General Public License for more details.
  18. #
  19. #  You should have received a copy of the GNU General Public License
  20. #  along with this program; if not, write to the Free Software
  21. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  22. #  USA
  23. import gettext
  24. import logging
  25. import re
  26. import os
  27. from xml.etree.ElementTree import ElementTree
  28. from apt_pkg import gettext as _
  29. class NoDistroTemplateException(Exception):
  30.     pass
  31. class Distribution(object):
  32.     def __init__(self, id, codename, description, release):
  33.         """ Container for distribution specific informations """
  34.         # LSB information
  35.         self.id = id
  36.         self.codename = codename
  37.         self.description = description
  38.         self.release = release
  39.         self.binary_type = "deb"
  40.         self.source_type = "deb-src"
  41.     def get_sources(self, sourceslist):
  42.         """
  43.         Find the corresponding template, main and child sources
  44.         for the distribution
  45.         """
  46.         self.sourceslist = sourceslist
  47.         # corresponding sources
  48.         self.source_template = None
  49.         self.child_sources = []
  50.         self.main_sources = []
  51.         self.disabled_sources = []
  52.         self.cdrom_sources = []
  53.         self.download_comps = []
  54.         self.enabled_comps = []
  55.         self.cdrom_comps = []
  56.         self.used_media = []
  57.         self.get_source_code = False
  58.         self.source_code_sources = []
  59.         # location of the sources
  60.         self.default_server = ""
  61.         self.main_server = ""
  62.         self.nearest_server = ""
  63.         self.used_servers = []
  64.         # find the distro template
  65.         for template in self.sourceslist.matcher.templates:
  66.             if (self.is_codename(template.name) and
  67.                 template.distribution == self.id):
  68.                 #print "yeah! found a template for %s" % self.description
  69.                 #print template.description, template.base_uri, \
  70.                 #    template.components
  71.                 self.source_template = template
  72.                 break
  73.         if self.source_template is None:
  74.             raise NoDistroTemplateException(
  75.                 "Error: could not find a distribution template for %s/%s" %
  76.                 (self.id, self.codename))
  77.         # find main and child sources
  78.         media = []
  79.         comps = []
  80.         cdrom_comps = []
  81.         enabled_comps = []
  82.         #source_code = []
  83.         for source in self.sourceslist.list:
  84.             if (source.invalid == False and
  85.                 self.is_codename(source.dist) and
  86.                 source.template and
  87.                 source.template.official == True and
  88.                 self.is_codename(source.template.name)):
  89.                 #print "yeah! found a distro repo:  %s" % source.line
  90.                 # cdroms need do be handled differently
  91.                 if (source.uri.startswith("cdrom:") and
  92.                     source.disabled == False):
  93.                     self.cdrom_sources.append(source)
  94.                     cdrom_comps.extend(source.comps)
  95.                 elif (source.uri.startswith("cdrom:") and
  96.                       source.disabled == True):
  97.                     self.cdrom_sources.append(source)
  98.                 elif (source.type == self.binary_type and
  99.                       source.disabled == False):
  100.                     self.main_sources.append(source)
  101.                     comps.extend(source.comps)
  102.                     media.append(source.uri)
  103.                 elif (source.type == self.binary_type and
  104.                       source.disabled == True):
  105.                     self.disabled_sources.append(source)
  106.                 elif (source.type == self.source_type
  107.                         and source.disabled == False):
  108.                     self.source_code_sources.append(source)
  109.                 elif (source.type == self.source_type and
  110.                       source.disabled == True):
  111.                     self.disabled_sources.append(source)
  112.             if (source.invalid == False and
  113.                 source.template in self.source_template.children):
  114.                 if (source.disabled == False
  115.                     and source.type == self.binary_type):
  116.                     self.child_sources.append(source)
  117.                 elif (source.disabled == False
  118.                       and source.type == self.source_type):
  119.                     self.source_code_sources.append(source)
  120.                 else:
  121.                     self.disabled_sources.append(source)
  122.         self.download_comps = set(comps)
  123.         self.cdrom_comps = set(cdrom_comps)
  124.         enabled_comps.extend(comps)
  125.         enabled_comps.extend(cdrom_comps)
  126.         self.enabled_comps = set(enabled_comps)
  127.         self.used_media = set(media)
  128.         self.get_mirrors()
  129.     def get_mirrors(self, mirror_template=None):
  130.         """
  131.         Provide a set of mirrors where you can get the distribution from
  132.         """
  133.         # the main server is stored in the template
  134.         self.main_server = self.source_template.base_uri
  135.         # other used servers
  136.         for medium in self.used_media:
  137.             if not medium.startswith("cdrom:"):
  138.                 # seems to be a network source
  139.                 self.used_servers.append(medium)
  140.         if len(self.main_sources) == 0:
  141.             self.default_server = self.main_server
  142.         else:
  143.             self.default_server = self.main_sources[0].uri
  144.         # get a list of country codes and real names
  145.         self.countries = {}
  146.         fname = "/usr/share/xml/iso-codes/iso_3166.xml"
  147.         if os.path.exists(fname):
  148.             et = ElementTree(file=fname)
  149.             # python2.6 compat, the next two lines can get removed
  150.             # once we do not use py2.6 anymore
  151.             if getattr(et, "iter", None) is None:
  152.                 et.iter = et.getiterator
  153.             it = et.iter('iso_3166_entry')
  154.             for elm in it:
  155.                 try:
  156.                     descr = elm.attrib["common_name"]
  157.                 except KeyError:
  158.                     descr = elm.attrib["name"]
  159.                 try:
  160.                     code = elm.attrib["alpha_2_code"]
  161.                 except KeyError:
  162.                     code = elm.attrib["alpha_3_code"]
  163.                 self.countries[code.lower()] = gettext.dgettext('iso_3166',
  164.                                                                 descr)
  165.         # try to guess the nearest mirror from the locale
  166.         self.country = None
  167.         self.country_code = None
  168.         locale = os.getenv("LANG", default="en_UK")
  169.         a = locale.find("_")
  170.         z = locale.find(".")
  171.         if z == -1:
  172.             z = len(locale)
  173.         country_code = locale[a+1:z].lower()
  174.         if mirror_template:
  175.             self.nearest_server = mirror_template % country_code
  176.         if country_code in self.countries:
  177.             self.country = self.countries[country_code]
  178.             self.country_code = country_code
  179.     def _get_mirror_name(self, server):
  180.         ''' Try to get a human readable name for the main mirror of a country
  181.             Customize for different distributions '''
  182.         country = None
  183.         i = server.find("://")
  184.         l = server.find(".archive.ubuntu.com")
  185.         if i != -1 and l != -1:
  186.             country = server[i+len("://"):l]
  187.         if country in self.countries:
  188.             # TRANSLATORS: %s is a country
  189.             return _("Server for %s") % self.countries[country]
  190.         else:
  191.             return("%s" % server.rstrip("/ "))
  192.     def get_server_list(self):
  193.         ''' Return a list of used and suggested servers '''
  194.         def compare_mirrors(mir1, mir2):
  195.             ''' Helper function that handles comaprision of mirror urls
  196.                 that could contain trailing slashes'''
  197.             return re.match(mir1.strip("/ "), mir2.rstrip("/ "))
  198.         # Store all available servers:
  199.         # Name, URI, active
  200.         mirrors = []
  201.         if (len(self.used_servers) < 1 or
  202.             (len(self.used_servers) == 1 and
  203.              compare_mirrors(self.used_servers[0], self.main_server))):
  204.             mirrors.append([_("Main server"), self.main_server, True])
  205.             if self.nearest_server:
  206.                 mirrors.append([self._get_mirror_name(self.nearest_server),
  207.                                 self.nearest_server, False])
  208.         elif (len(self.used_servers) == 1 and not
  209.               compare_mirrors(self.used_servers[0], self.main_server)):
  210.             mirrors.append([_("Main server"), self.main_server, False])
  211.             # Only one server is used
  212.             server = self.used_servers[0]
  213.             # Append the nearest server if it's not already used
  214.             if self.nearest_server:
  215.                 if not compare_mirrors(server, self.nearest_server):
  216.                     mirrors.append([self._get_mirror_name(self.nearest_server),
  217.                                     self.nearest_server, False])
  218.             if server:
  219.                 mirrors.append([self._get_mirror_name(server), server, True])
  220.         elif len(self.used_servers) > 1:
  221.             # More than one server is used. Since we don't handle this case
  222.             # in the user interface we set "custom servers" to true and
  223.             # append a list of all used servers
  224.             mirrors.append([_("Main server"), self.main_server, False])
  225.             if self.nearest_server:
  226.                 mirrors.append([self._get_mirror_name(self.nearest_server),
  227.                                 self.nearest_server, False])
  228.             mirrors.append([_("Custom servers"), None, True])
  229.             for server in self.used_servers:
  230.                 mirror_entry = [self._get_mirror_name(server), server, False]
  231.                 if (compare_mirrors(server, self.nearest_server) or
  232.                     compare_mirrors(server, self.main_server)):
  233.                     continue
  234.                 elif not mirror_entry in mirrors:
  235.                     mirrors.append(mirror_entry)
  236.         return mirrors
  237.     def add_source(self, type=None,
  238.                  uri=None, dist=None, comps=None, comment=""):
  239.         """
  240.         Add distribution specific sources
  241.         """
  242.         if uri is None:
  243.             # FIXME: Add support for the server selector
  244.             uri = self.default_server
  245.         if dist is None:
  246.             dist = self.codename
  247.         if comps is None:
  248.             comps = list(self.enabled_comps)
  249.         if type is None:
  250.             type = self.binary_type
  251.         new_source = self.sourceslist.add(type, uri, dist, comps, comment)
  252.         # if source code is enabled add a deb-src line after the new
  253.         # source
  254.         if self.get_source_code == True and type == self.binary_type:
  255.             self.sourceslist.add(self.source_type, uri, dist, comps, comment,
  256.                                  file=new_source.file,
  257.                                  pos=self.sourceslist.list.index(new_source)+1)
  258.     def enable_component(self, comp):
  259.         """
  260.         Enable a component in all main, child and source code sources
  261.         (excluding cdrom based sources)
  262.         comp:         the component that should be enabled
  263.         """
  264.         comps = set([comp])
  265.         # look for parent components that we may have to add
  266.         for source in self.main_sources:
  267.             for c in source.template.components:
  268.                 if c.name == comp and c.parent_component:
  269.                     comps.add(c.parent_component)
  270.         for c in comps:
  271.             self._enable_component(c)
  272.     def _enable_component(self, comp):
  273.         def add_component_only_once(source, comps_per_dist):
  274.             """
  275.             Check if we already added the component to the repository, since
  276.             a repository could be splitted into different apt lines. If not
  277.             add the component
  278.             """
  279.             # if we don't have that distro, just return (can happen for e.g.
  280.             # dapper-update only in deb-src
  281.             if source.dist not in comps_per_dist:
  282.                 return
  283.             # if we have seen this component already for this distro,
  284.             # return (nothing to do)
  285.             if comp in comps_per_dist[source.dist]:
  286.                 return
  287.             # add it
  288.             source.comps.append(comp)
  289.             comps_per_dist[source.dist].add(comp)
  290.         sources = []
  291.         sources.extend(self.main_sources)
  292.         sources.extend(self.child_sources)
  293.         # store what comps are enabled already per distro (where distro is
  294.         # e.g. "dapper", "dapper-updates")
  295.         comps_per_dist = {}
  296.         comps_per_sdist = {}
  297.         for s in sources:
  298.             if s.type == self.binary_type:
  299.                 if s.dist not in comps_per_dist:
  300.                     comps_per_dist[s.dist] = set()
  301.                 for c in s.comps:
  302.                     comps_per_dist[s.dist].add(c)
  303.         for s in self.source_code_sources:
  304.             if s.type == self.source_type:
  305.                 if s.dist not in comps_per_sdist:
  306.                     comps_per_sdist[s.dist] = set()
  307.                 for c in s.comps:
  308.                     comps_per_sdist[s.dist].add(c)
  309.         # check if there is a main source at all
  310.         if len(self.main_sources) < 1:
  311.             # create a new main source
  312.             self.add_source(comps=["%s"%comp])
  313.         else:
  314.             # add the comp to all main, child and source code sources
  315.             for source in sources:
  316.                 add_component_only_once(source, comps_per_dist)
  317.             for source in self.source_code_sources:
  318.                 add_component_only_once(source, comps_per_sdist)
  319.         # check if there is a main source code source at all
  320.         if self.get_source_code == True:
  321.             if len(self.source_code_sources) < 1:
  322.                 # create a new main source
  323.                 self.add_source(type=self.source_type, comps=["%s"%comp])
  324.             else:
  325.                 # add the comp to all main, child and source code sources
  326.                 for source in self.source_code_sources:
  327.                     add_component_only_once(source, comps_per_sdist)
  328.     def disable_component(self, comp):
  329.         """
  330.         Disable a component in all main, child and source code sources
  331.         (excluding cdrom based sources)
  332.         """
  333.         sources = []
  334.         sources.extend(self.main_sources)
  335.         sources.extend(self.child_sources)
  336.         sources.extend(self.source_code_sources)
  337.         if comp in self.cdrom_comps:
  338.             sources = []
  339.             sources.extend(self.main_sources)
  340.         for source in sources:
  341.             if comp in source.comps:
  342.                 source.comps.remove(comp)
  343.                 if len(source.comps) < 1:
  344.                     self.sourceslist.remove(source)
  345.     def change_server(self, uri):
  346.         ''' Change the server of all distro specific sources to
  347.             a given host '''
  348.         def change_server_of_source(source, uri, seen):
  349.             # Avoid creating duplicate entries
  350.             source.uri = uri
  351.             for comp in source.comps:
  352.                 if [source.uri, source.dist, comp] in seen:
  353.                     source.comps.remove(comp)
  354.                 else:
  355.                     seen.append([source.uri, source.dist, comp])
  356.             if len(source.comps) < 1:
  357.                 self.sourceslist.remove(source)
  358.         seen_binary = []
  359.         seen_source = []
  360.         self.default_server = uri
  361.         for source in self.main_sources:
  362.             change_server_of_source(source, uri, seen_binary)
  363.         for source in self.child_sources:
  364.             # Do not change the forces server of a child source
  365.             if (source.template.base_uri is None or
  366.                 source.template.base_uri != source.uri):
  367.                 change_server_of_source(source, uri, seen_binary)
  368.         for source in self.source_code_sources:
  369.             change_server_of_source(source, uri, seen_source)
  370.     def is_codename(self, name):
  371.         ''' Compare a given name with the release codename. '''
  372.         if name == self.codename:
  373.             return True
  374.         else:
  375.             return False
  376. class DebianDistribution(Distribution):
  377.     ''' Class to support specific Debian features '''
  378.     def is_codename(self, name):
  379.         ''' Compare a given name with the release codename and check if
  380.             if it can be used as a synonym for a development releases '''
  381.         if name == self.codename or self.release in ("testing", "unstable"):
  382.             return True
  383.         else:
  384.             return False
  385.     def _get_mirror_name(self, server):
  386.         ''' Try to get a human readable name for the main mirror of a country
  387.             Debian specific '''
  388.         country = None
  389.         i = server.find("://ftp.")
  390.         l = server.find(".debian.org")
  391.         if i != -1 and l != -1:
  392.             country = server[i+len("://ftp."):l]
  393.         if country in self.countries:
  394.             # TRANSLATORS: %s is a country
  395.             return _("Server for %s") % gettext.dgettext(
  396.                 "iso_3166", self.countries[country].rstrip()).rstrip()
  397.         else:
  398.             return("%s" % server.rstrip("/ "))
  399.     def get_mirrors(self):
  400.         Distribution.get_mirrors(
  401.             self, mirror_template="http://ftp.%s.debian.org/debian/")
  402. class UbuntuDistribution(Distribution):
  403.     ''' Class to support specific Ubuntu features '''
  404.     def get_mirrors(self):
  405.         Distribution.get_mirrors(
  406.             self, mirror_template="http://%s.archive.ubuntu.com/ubuntu/")
  407. def _lsb_release():
  408.     """Call lsb_release --idrc and return a mapping."""
  409.     from subprocess import Popen, PIPE
  410.     import errno
  411.     result = {'Codename': 'sid', 'Distributor ID': 'Debian',
  412.               'Description': 'Debian GNU/Linux unstable (sid)',
  413.               'Release': 'unstable'}
  414.     try:
  415.         out = Popen(['lsb_release', '-idrc'], stdout=PIPE).communicate()[0]
  416.         # Convert to unicode string, needed for Python 3.1
  417.         out = out.decode("utf-8")
  418.         result.update(l.split(":\t") for l in out.split("\n") if ':\t' in l)
  419.     except OSError as exc:
  420.         if exc.errno != errno.ENOENT:
  421.             logging.warning('lsb_release failed, using defaults:' % exc)
  422.     return result
  423. def get_distro(id=None, codename=None, description=None, release=None):
  424.     """
  425.     Check the currently used distribution and return the corresponding
  426.     distriubtion class that supports distro specific features.
  427.     If no paramter are given the distro will be auto detected via
  428.     a call to lsb-release
  429.     """
  430.     # make testing easier
  431.     if not (id and codename and description and release):
  432.         result = _lsb_release()
  433.         id = result['Distributor ID']
  434.         codename = result['Codename']
  435.         description = result['Description']
  436.         release = result['Release']
  437.     if id == "Ubuntu":
  438.         return UbuntuDistribution(id, codename, description, release)
  439.     elif id == "Debian":
  440.         return DebianDistribution(id, codename, description, release)
  441.     else:
  442.         return Distribution(id, codename, description, release)
Copy the Code
Reply View the author
Bluek404
deepin
2014-05-17 06:53
#4
/usr/lib/python3/dist-packages/aptsources/distro.py
  1. #  distro.py - Provide a distro abstraction of the sources.list
  2. #
  3. #  Copyright (c) 2004-2009 Canonical Ltd.
  4. #  Copyright (c) 2006-2007 Sebastian Heinlein
  5. #
  6. #  Authors: Sebastian Heinlein
  7. #           Michael Vogt
  8. #
  9. #  This program is free software; you can redistribute it and/or
  10. #  modify it under the terms of the GNU General Public License as
  11. #  published by the Free Software Foundation; either version 2 of the
  12. #  License, or (at your option) any later version.
  13. #
  14. #  This program is distributed in the hope that it will be useful,
  15. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. #  GNU General Public License for more details.
  18. #
  19. #  You should have received a copy of the GNU General Public License
  20. #  along with this program; if not, write to the Free Software
  21. #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  22. #  USA
  23. import gettext
  24. import logging
  25. import re
  26. import os
  27. from xml.etree.ElementTree import ElementTree
  28. from apt_pkg import gettext as _
  29. class NoDistroTemplateException(Exception):
  30.     pass
  31. class Distribution(object):
  32.     def __init__(self, id, codename, description, release):
  33.         """ Container for distribution specific informations """
  34.         # LSB information
  35.         self.id = id
  36.         self.codename = codename
  37.         self.description = description
  38.         self.release = release
  39.         self.binary_type = "deb"
  40.         self.source_type = "deb-src"
  41.     def get_sources(self, sourceslist):
  42.         """
  43.         Find the corresponding template, main and child sources
  44.         for the distribution
  45.         """
  46.         self.sourceslist = sourceslist
  47.         # corresponding sources
  48.         self.source_template = None
  49.         self.child_sources = []
  50.         self.main_sources = []
  51.         self.disabled_sources = []
  52.         self.cdrom_sources = []
  53.         self.download_comps = []
  54.         self.enabled_comps = []
  55.         self.cdrom_comps = []
  56.         self.used_media = []
  57.         self.get_source_code = False
  58.         self.source_code_sources = []
  59.         # location of the sources
  60.         self.default_server = ""
  61.         self.main_server = ""
  62.         self.nearest_server = ""
  63.         self.used_servers = []
  64.         # find the distro template
  65.         for template in self.sourceslist.matcher.templates:
  66.             if (self.is_codename(template.name) and
  67.                 template.distribution == self.id):
  68.                 #print "yeah! found a template for %s" % self.description
  69.                 #print template.description, template.base_uri, \
  70.                 #    template.components
  71.                 self.source_template = template
  72.                 break
  73.         if self.source_template is None:
  74.             raise NoDistroTemplateException(
  75.                 "Error: could not find a distribution template for %s/%s" %
  76.                 (self.id, self.codename))
  77.         # find main and child sources
  78.         media = []
  79.         comps = []
  80.         cdrom_comps = []
  81.         enabled_comps = []
  82.         #source_code = []
  83.         for source in self.sourceslist.list:
  84.             if (source.invalid == False and
  85.                 self.is_codename(source.dist) and
  86.                 source.template and
  87.                 source.template.official == True and
  88.                 self.is_codename(source.template.name)):
  89.                 #print "yeah! found a distro repo:  %s" % source.line
  90.                 # cdroms need do be handled differently
  91.                 if (source.uri.startswith("cdrom:") and
  92.                     source.disabled == False):
  93.                     self.cdrom_sources.append(source)
  94.                     cdrom_comps.extend(source.comps)
  95.                 elif (source.uri.startswith("cdrom:") and
  96.                       source.disabled == True):
  97.                     self.cdrom_sources.append(source)
  98.                 elif (source.type == self.binary_type and
  99.                       source.disabled == False):
  100.                     self.main_sources.append(source)
  101.                     comps.extend(source.comps)
  102.                     media.append(source.uri)
  103.                 elif (source.type == self.binary_type and
  104.                       source.disabled == True):
  105.                     self.disabled_sources.append(source)
  106.                 elif (source.type == self.source_type
  107.                         and source.disabled == False):
  108.                     self.source_code_sources.append(source)
  109.                 elif (source.type == self.source_type and
  110.                       source.disabled == True):
  111.                     self.disabled_sources.append(source)
  112.             if (source.invalid == False and
  113.                 source.template in self.source_template.children):
  114.                 if (source.disabled == False
  115.                     and source.type == self.binary_type):
  116.                     self.child_sources.append(source)
  117.                 elif (source.disabled == False
  118.                       and source.type == self.source_type):
  119.                     self.source_code_sources.append(source)
  120.                 else:
  121.                     self.disabled_sources.append(source)
  122.         self.download_comps = set(comps)
  123.         self.cdrom_comps = set(cdrom_comps)
  124.         enabled_comps.extend(comps)
  125.         enabled_comps.extend(cdrom_comps)
  126.         self.enabled_comps = set(enabled_comps)
  127.         self.used_media = set(media)
  128.         self.get_mirrors()
  129.     def get_mirrors(self, mirror_template=None):
  130.         """
  131.         Provide a set of mirrors where you can get the distribution from
  132.         """
  133.         # the main server is stored in the template
  134.         self.main_server = self.source_template.base_uri
  135.         # other used servers
  136.         for medium in self.used_media:
  137.             if not medium.startswith("cdrom:"):
  138.                 # seems to be a network source
  139.                 self.used_servers.append(medium)
  140.         if len(self.main_sources) == 0:
  141.             self.default_server = self.main_server
  142.         else:
  143.             self.default_server = self.main_sources[0].uri
  144.         # get a list of country codes and real names
  145.         self.countries = {}
  146.         fname = "/usr/share/xml/iso-codes/iso_3166.xml"
  147.         if os.path.exists(fname):
  148.             et = ElementTree(file=fname)
  149.             # python2.6 compat, the next two lines can get removed
  150.             # once we do not use py2.6 anymore
  151.             if getattr(et, "iter", None) is None:
  152.                 et.iter = et.getiterator
  153.             it = et.iter('iso_3166_entry')
  154.             for elm in it:
  155.                 try:
  156.                     descr = elm.attrib["common_name"]
  157.                 except KeyError:
  158.                     descr = elm.attrib["name"]
  159.                 try:
  160.                     code = elm.attrib["alpha_2_code"]
  161.                 except KeyError:
  162.                     code = elm.attrib["alpha_3_code"]
  163.                 self.countries[code.lower()] = gettext.dgettext('iso_3166',
  164.                                                                 descr)
  165.         # try to guess the nearest mirror from the locale
  166.         self.country = None
  167.         self.country_code = None
  168.         locale = os.getenv("LANG", default="en_UK")
  169.         a = locale.find("_")
  170.         z = locale.find(".")
  171.         if z == -1:
  172.             z = len(locale)
  173.         country_code = locale[a+1:z].lower()
  174.         if mirror_template:
  175.             self.nearest_server = mirror_template % country_code
  176.         if country_code in self.countries:
  177.             self.country = self.countries[country_code]
  178.             self.country_code = country_code
  179.     def _get_mirror_name(self, server):
  180.         ''' Try to get a human readable name for the main mirror of a country
  181.             Customize for different distributions '''
  182.         country = None
  183.         i = server.find("://")
  184.         l = server.find(".archive.ubuntu.com")
  185.         if i != -1 and l != -1:
  186.             country = server[i+len("://"):l]
  187.         if country in self.countries:
  188.             # TRANSLATORS: %s is a country
  189.             return _("Server for %s") % self.countries[country]
  190.         else:
  191.             return("%s" % server.rstrip("/ "))
  192.     def get_server_list(self):
  193.         ''' Return a list of used and suggested servers '''
  194.         def compare_mirrors(mir1, mir2):
  195.             ''' Helper function that handles comaprision of mirror urls
  196.                 that could contain trailing slashes'''
  197.             return re.match(mir1.strip("/ "), mir2.rstrip("/ "))
  198.         # Store all available servers:
  199.         # Name, URI, active
  200.         mirrors = []
  201.         if (len(self.used_servers) < 1 or
  202.             (len(self.used_servers) == 1 and
  203.              compare_mirrors(self.used_servers[0], self.main_server))):
  204.             mirrors.append([_("Main server"), self.main_server, True])
  205.             if self.nearest_server:
  206.                 mirrors.append([self._get_mirror_name(self.nearest_server),
  207.                                 self.nearest_server, False])
  208.         elif (len(self.used_servers) == 1 and not
  209.               compare_mirrors(self.used_servers[0], self.main_server)):
  210.             mirrors.append([_("Main server"), self.main_server, False])
  211.             # Only one server is used
  212.             server = self.used_servers[0]
  213.             # Append the nearest server if it's not already used
  214.             if self.nearest_server:
  215.                 if not compare_mirrors(server, self.nearest_server):
  216.                     mirrors.append([self._get_mirror_name(self.nearest_server),
  217.                                     self.nearest_server, False])
  218.             if server:
  219.                 mirrors.append([self._get_mirror_name(server), server, True])
  220.         elif len(self.used_servers) > 1:
  221.             # More than one server is used. Since we don't handle this case
  222.             # in the user interface we set "custom servers" to true and
  223.             # append a list of all used servers
  224.             mirrors.append([_("Main server"), self.main_server, False])
  225.             if self.nearest_server:
  226.                 mirrors.append([self._get_mirror_name(self.nearest_server),
  227.                                 self.nearest_server, False])
  228.             mirrors.append([_("Custom servers"), None, True])
  229.             for server in self.used_servers:
  230.                 mirror_entry = [self._get_mirror_name(server), server, False]
  231.                 if (compare_mirrors(server, self.nearest_server) or
  232.                     compare_mirrors(server, self.main_server)):
  233.                     continue
  234.                 elif not mirror_entry in mirrors:
  235.                     mirrors.append(mirror_entry)
  236.         return mirrors
  237.     def add_source(self, type=None,
  238.                  uri=None, dist=None, comps=None, comment=""):
  239.         """
  240.         Add distribution specific sources
  241.         """
  242.         if uri is None:
  243.             # FIXME: Add support for the server selector
  244.             uri = self.default_server
  245.         if dist is None:
  246.             dist = self.codename
  247.         if comps is None:
  248.             comps = list(self.enabled_comps)
  249.         if type is None:
  250.             type = self.binary_type
  251.         new_source = self.sourceslist.add(type, uri, dist, comps, comment)
  252.         # if source code is enabled add a deb-src line after the new
  253.         # source
  254.         if self.get_source_code == True and type == self.binary_type:
  255.             self.sourceslist.add(self.source_type, uri, dist, comps, comment,
  256.                                  file=new_source.file,
  257.                                  pos=self.sourceslist.list.index(new_source)+1)
  258.     def enable_component(self, comp):
  259.         """
  260.         Enable a component in all main, child and source code sources
  261.         (excluding cdrom based sources)
  262.         comp:         the component that should be enabled
  263.         """
  264.         comps = set([comp])
  265.         # look for parent components that we may have to add
  266.         for source in self.main_sources:
  267.             for c in source.template.components:
  268.                 if c.name == comp and c.parent_component:
  269.                     comps.add(c.parent_component)
  270.         for c in comps:
  271.             self._enable_component(c)
  272.     def _enable_component(self, comp):
  273.         def add_component_only_once(source, comps_per_dist):
  274.             """
  275.             Check if we already added the component to the repository, since
  276.             a repository could be splitted into different apt lines. If not
  277.             add the component
  278.             """
  279.             # if we don't have that distro, just return (can happen for e.g.
  280.             # dapper-update only in deb-src
  281.             if source.dist not in comps_per_dist:
  282.                 return
  283.             # if we have seen this component already for this distro,
  284.             # return (nothing to do)
  285.             if comp in comps_per_dist[source.dist]:
  286.                 return
  287.             # add it
  288.             source.comps.append(comp)
  289.             comps_per_dist[source.dist].add(comp)
  290.         sources = []
  291.         sources.extend(self.main_sources)
  292.         sources.extend(self.child_sources)
  293.         # store what comps are enabled already per distro (where distro is
  294.         # e.g. "dapper", "dapper-updates")
  295.         comps_per_dist = {}
  296.         comps_per_sdist = {}
  297.         for s in sources:
  298.             if s.type == self.binary_type:
  299.                 if s.dist not in comps_per_dist:
  300.                     comps_per_dist[s.dist] = set()
  301.                 for c in s.comps:
  302.                     comps_per_dist[s.dist].add(c)
  303.         for s in self.source_code_sources:
  304.             if s.type == self.source_type:
  305.                 if s.dist not in comps_per_sdist:
  306.                     comps_per_sdist[s.dist] = set()
  307.                 for c in s.comps:
  308.                     comps_per_sdist[s.dist].add(c)
  309.         # check if there is a main source at all
  310.         if len(self.main_sources) < 1:
  311.             # create a new main source
  312.             self.add_source(comps=["%s"%comp])
  313.         else:
  314.             # add the comp to all main, child and source code sources
  315.             for source in sources:
  316.                 add_component_only_once(source, comps_per_dist)
  317.             for source in self.source_code_sources:
  318.                 add_component_only_once(source, comps_per_sdist)
  319.         # check if there is a main source code source at all
  320.         if self.get_source_code == True:
  321.             if len(self.source_code_sources) < 1:
  322.                 # create a new main source
  323.                 self.add_source(type=self.source_type, comps=["%s"%comp])
  324.             else:
  325.                 # add the comp to all main, child and source code sources
  326.                 for source in self.source_code_sources:
  327.                     add_component_only_once(source, comps_per_sdist)
  328.     def disable_component(self, comp):
  329.         """
  330.         Disable a component in all main, child and source code sources
  331.         (excluding cdrom based sources)
  332.         """
  333.         sources = []
  334.         sources.extend(self.main_sources)
  335.         sources.extend(self.child_sources)
  336.         sources.extend(self.source_code_sources)
  337.         if comp in self.cdrom_comps:
  338.             sources = []
  339.             sources.extend(self.main_sources)
  340.         for source in sources:
  341.             if comp in source.comps:
  342.                 source.comps.remove(comp)
  343.                 if len(source.comps) < 1:
  344.                     self.sourceslist.remove(source)
  345.     def change_server(self, uri):
  346.         ''' Change the server of all distro specific sources to
  347.             a given host '''
  348.         def change_server_of_source(source, uri, seen):
  349.             # Avoid creating duplicate entries
  350.             source.uri = uri
  351.             for comp in source.comps:
  352.                 if [source.uri, source.dist, comp] in seen:
  353.                     source.comps.remove(comp)
  354.                 else:
  355.                     seen.append([source.uri, source.dist, comp])
  356.             if len(source.comps) < 1:
  357.                 self.sourceslist.remove(source)
  358.         seen_binary = []
  359.         seen_source = []
  360.         self.default_server = uri
  361.         for source in self.main_sources:
  362.             change_server_of_source(source, uri, seen_binary)
  363.         for source in self.child_sources:
  364.             # Do not change the forces server of a child source
  365.             if (source.template.base_uri is None or
  366.                 source.template.base_uri != source.uri):
  367.                 change_server_of_source(source, uri, seen_binary)
  368.         for source in self.source_code_sources:
  369.             change_server_of_source(source, uri, seen_source)
  370.     def is_codename(self, name):
  371.         ''' Compare a given name with the release codename. '''
  372.         if name == self.codename:
  373.             return True
  374.         else:
  375.             return False
  376. class DebianDistribution(Distribution):
  377.     ''' Class to support specific Debian features '''
  378.     def is_codename(self, name):
  379.         ''' Compare a given name with the release codename and check if
  380.             if it can be used as a synonym for a development releases '''
  381.         if name == self.codename or self.release in ("testing", "unstable"):
  382.             return True
  383.         else:
  384.             return False
  385.     def _get_mirror_name(self, server):
  386.         ''' Try to get a human readable name for the main mirror of a country
  387.             Debian specific '''
  388.         country = None
  389.         i = server.find("://ftp.")
  390.         l = server.find(".debian.org")
  391.         if i != -1 and l != -1:
  392.             country = server[i+len("://ftp."):l]
  393.         if country in self.countries:
  394.             # TRANSLATORS: %s is a country
  395.             return _("Server for %s") % gettext.dgettext(
  396.                 "iso_3166", self.countries[country].rstrip()).rstrip()
  397.         else:
  398.             return("%s" % server.rstrip("/ "))
  399.     def get_mirrors(self):
  400.         Distribution.get_mirrors(
  401.             self, mirror_template="http://ftp.%s.debian.org/debian/")
  402. class UbuntuDistribution(Distribution):
  403.     ''' Class to support specific Ubuntu features '''
  404.     def get_mirrors(self):
  405.         Distribution.get_mirrors(
  406.             self, mirror_template="http://%s.archive.ubuntu.com/ubuntu/")
  407. def _lsb_release():
  408.     """Call lsb_release --idrc and return a mapping."""
  409.     from subprocess import Popen, PIPE
  410.     import errno
  411.     result = {'Codename': 'sid', 'Distributor ID': 'Debian',
  412.               'Description': 'Debian GNU/Linux unstable (sid)',
  413.               'Release': 'unstable'}
  414.     try:
  415.         out = Popen(['lsb_release', '-idrc'], stdout=PIPE).communicate()[0]
  416.         # Convert to unicode string, needed for Python 3.1
  417.         out = out.decode("utf-8")
  418.         result.update(l.split(":\t") for l in out.split("\n") if ':\t' in l)
  419.     except OSError as exc:
  420.         if exc.errno != errno.ENOENT:
  421.             logging.warning('lsb_release failed, using defaults:' % exc)
  422.     return result
  423. def get_distro(id=None, codename=None, description=None, release=None):
  424.     """
  425.     Check the currently used distribution and return the corresponding
  426.     distriubtion class that supports distro specific features.
  427.     If no paramter are given the distro will be auto detected via
  428.     a call to lsb-release
  429.     """
  430.     # make testing easier
  431.     if not (id and codename and description and release):
  432.         result = _lsb_release()
  433.         id = result['Distributor ID']
  434.         codename = result['Codename']
  435.         description = result['Description']
  436.         release = result['Release']
  437.     if id == "Ubuntu":
  438.         return UbuntuDistribution(id, codename, description, release)
  439.     elif id == "Debian":
  440.         return DebianDistribution(id, codename, description, release)
  441.     else:
  442.         return Distribution(id, codename, description, release)
Copy the Code
多谢 : D
Reply View the author
v***h@gmail.com
deepin
2023-06-14 17:32
#5
It has been deleted!