Advertisement
Guest User

orphan management command

a guest
Jan 29th, 2011
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.92 KB | None | 0 0
  1. #
  2. # Copyright (c) 2004 Conectiva, Inc.
  3. #
  4. # Written by Gustavo Niemeyer <niemeyer@conectiva.com>
  5. #
  6. # This file is part of Smart Package Manager.
  7. #
  8. # Smart Package Manager is free software; you can redistribute it and/or
  9. # modify it under the terms of the GNU General Public License as published
  10. # by the Free Software Foundation; either version 2 of the License, or (at
  11. # your option) any later version.
  12. #
  13. # Smart Package Manager is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. # General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with Smart Package Manager; if not, write to the Free Software
  20. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21. #
  22. from smart.option import OptionParser
  23. from smart.const import *
  24. from smart import *
  25. from smart.commands import remove
  26. from smart.commands import install
  27. import re
  28. import os.path
  29.  
  30. target_file = os.path.expanduser('~/.targets')
  31.  
  32. USAGE=_('smart target [[--remove] package ...]')
  33.  
  34. DESCRIPTION=_("""
  35. This command will list packages which will never be considered orphans.
  36. If pkgname is provided, the packages will be added to the targeted packages
  37. list. If --remove is specified, they will be removed from targets list, and all
  38. non-essential packages that are not required by any of the targets will be
  39. removed.
  40. The removal tries to be conservative: if a package depends on multiple
  41. alternatives, they are both kept.
  42. """)
  43.  
  44.  
  45. EXAMPLES=_("""
  46. smart target
  47. smart target pkgname
  48. smart target '*kgnam*'
  49. smart target pkgname-1.0
  50. smart target pkgname-1.0-1
  51. smart target pkgname1 pkgname2
  52. smart target --remove
  53. smart target --remove pkgname
  54. smart target --remove '*kgnam*'
  55. smart target --remove pkgname-1.0
  56. smart target --remove pkgname-1.0-1
  57. smart target --remove pkgname1 pkgname2
  58. """)
  59.  
  60.  
  61. def option_parser():
  62.     parser = OptionParser(usage=USAGE,
  63.                           description=DESCRIPTION,
  64.                           examples=EXAMPLES)
  65.     parser.allow_interspersed_args = False
  66.     parser.add_option("--remove", action="store_true",
  67.                       help=_("optionally remove a package and all orphans"))
  68.     return parser
  69.  
  70.  
  71. def parse_options(argv):
  72.     parser = option_parser()
  73.     opts, args = parser.parse_args(argv)
  74.     opts.args = args
  75.     return opts
  76.  
  77. def get_installed(ctrl):
  78.     packages = ctrl.getCache().getPackages()
  79.     return (package for package in packages if package.installed)
  80.  
  81.  
  82. def get_immediate_deps(packages):
  83.     """Returns all installed deps"""
  84.     deps = set()
  85.     for package in packages:
  86.         for req in package.requires:
  87.             for prv in req.providedby:
  88.                 for prvpkg in prv.packages:
  89.                     if prvpkg.installed:
  90.                         deps.add(prvpkg)
  91.     return deps
  92.  
  93.  
  94. def get_dependencies(targets):
  95.     """Dependency graph traversal. Finding all packages in required lists,
  96.    breadth first.
  97.    If there is more than one package providing the same dependency, all are
  98.    selected.
  99.    """
  100.     required_packages = set()
  101.     targets = set(targets)
  102.     while targets:
  103.         required_packages.update(targets)
  104.         deps = get_immediate_deps(targets)
  105.         targets = deps - required_packages
  106.     return required_packages
  107.  
  108.  
  109. def find_targets(ctrl, targetnames):
  110.     """Converts target names to packages"""
  111.     targets = []
  112.     for name in targetnames:
  113.         ratio, packages, suggestions = ctrl.search(name)
  114.         if not packages:
  115.             raise ValueError(name + " not found")
  116.         for package in packages:
  117.             if package.installed:
  118.                 targets.append(package)
  119.     return targets
  120.  
  121.  
  122. def find_orphans(ctrl, targetnames):
  123.     """Finds all packags not in targets' dependencies"""
  124.     installed = get_installed(ctrl)
  125.     targets = find_targets(ctrl, targetnames)
  126.    
  127.     necessary = get_dependencies(targets)
  128.     return [package for package in set(installed) - set(necessary) if not package.essential]
  129.  
  130.  
  131. def main(ctrl, opts, reloadchannels=True):
  132.     try:
  133.         targets_list = [name.strip() for name in open(target_file)]
  134.     except Exception, e:
  135.         import traceback
  136.         traceback.print_exc()
  137.         return
  138.    
  139.     if opts.remove is None and not opts.args:
  140.         for pkgname in sorted(targets_list):
  141.             print pkgname
  142.         print len(targets_list)
  143.     else:
  144.         if sysconf.get("auto-update"):
  145.             from smart.commands import update
  146.             updateopts = update.parse_options([])
  147.             update.main(ctrl, updateopts)
  148.         else:
  149.             if reloadchannels:
  150.                 ctrl.reloadChannels()
  151.         cache = ctrl.getCache()
  152.        
  153.         if opts.remove:
  154.             targets_set = set(targets_list)
  155.             removal_list = set(opts.args)
  156.             not_targets = removal_list - targets_set
  157.             if not_targets:
  158.                 raise Error, _('The following packages are not targets, therefore cannot be removed:'
  159.                             '\n'.join(not_target for not_target in sorted(not_targets)))
  160.  
  161.             targets_list = list(targets_set - removal_list)
  162.             full_removal_list = find_orphans(ctrl, targets_list)
  163.             pkgnames = [pkg.name for pkg in full_removal_list]
  164.             remove_opts = remove.parse_options(pkgnames)
  165.             remove.main(ctrl, remove_opts)
  166.                         # FIXME: don't remove if command failed
  167.         else:
  168.             pkgnames = opts.args[:]
  169.             install_opts = install.parse_options(pkgnames)
  170.             install.main(ctrl, install_opts)
  171.             # FIXME: don't add if command failed
  172.             targets_list = list(set(targets_list).union(set(pkgnames)))
  173.  
  174.  
  175.         f = open(target_file, 'w')
  176.         f.write('\n'.join(targets_list))
  177.         f.close()
  178.    
  179. # vim:ts=4:sw=4:et
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement