Enable BytesWarnings.
[portage.git] / bin / regenworld
index b43f5c7cfdda21410b219517c0d1304b4c302f4e..239ea9a466510aa8fca530485763df89885869ef 100755 (executable)
@@ -1,16 +1,21 @@
-#!/usr/bin/python
-# Copyright 1999-2006 Gentoo Foundation
+#!/usr/bin/python -bb
+# Copyright 1999-2014 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
-# $Id$
-
-import sys, os
-try:
-       import portage
-except ImportError:
-       from os import path as osp
-       sys.path.insert(0, osp.join(osp.dirname(osp.dirname(__file__)), "pym"))
-       import portage
+
+from __future__ import print_function
+
+import sys
+from os import path as osp
+pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")
+sys.path.insert(0, pym_path)
+import portage
+portage._internal_caller = True
+from portage import os
+from portage._sets.files import StaticFileSet, WorldSelectedSet
+
 import re
+import tempfile
+import textwrap
 
 __candidatematcher__ = re.compile("^[0-9]+: \\*\\*\\* emerge ")
 __noncandidatematcher__ = re.compile(" sync( |$)| clean( |$)| search( |$)|--oneshot|--fetchonly| unmerge( |$)")
@@ -40,27 +45,28 @@ def isunwanted(pkgline):
                __uniqlist__.append(pkgline)
                return True
 
+eroot = portage.settings['EROOT']
+world_file = os.path.join(eroot, portage.WORLD_FILE)
+
 # show a little description if we have arguments
 if len(sys.argv) >= 2 and sys.argv[1] in ["-h", "--help"]:
-       print "This script regenerates the portage world file by checking the portage"
-       print "logfile for all actions that you've done in the past. It ignores any"
-       print "arguments except --help. It is recommended that you make a backup of"
-       print "your existing world file (%s) before using this tool." % portage.WORLD_FILE
+       print("This script regenerates the portage world file by checking the portage")
+       print("logfile for all actions that you've done in the past. It ignores any")
+       print("arguments except --help. It is recommended that you make a backup of")
+       print("your existing world file (%s) before using this tool." % world_file)
        sys.exit(0)
 
-worldlist = portage.grabfile(os.path.join("/", portage.WORLD_FILE))
-syslist = portage.settings.packages
-syslist = filter(issyspkg, syslist)
+worldlist = portage.grabfile(world_file)
+syslist = [x for x in portage.settings.packages if issyspkg(x)]
 
-logfile = portage.grabfile("/var/log/emerge.log")
-biglist = filter(iscandidate, logfile)
-biglist = map(getpkginfo, biglist)
+logfile = portage.grabfile(os.path.join(eroot, "var/log/emerge.log"))
+biglist = [getpkginfo(x) for x in logfile if iscandidate(x)]
 tmplist = []
 for l in biglist:
        tmplist += l.split()
-biglist = filter(isunwanted, tmplist)
+biglist = [x for x in tmplist if isunwanted(x)]
 #for p in biglist:
-#      print p
+#      print(p)
 #sys.exit(0)
 
 # resolving virtuals
@@ -68,28 +74,68 @@ realsyslist = []
 for mykey in syslist:
        # drop the asterix
        mykey = mykey[1:]
-       #print "candidate:",mykey
-       mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
+       #print("candidate:",mykey)
+       mylist = portage.db[eroot]["vartree"].dbapi.match(mykey)
        if mylist:
                mykey=portage.cpv_getkey(mylist[0])
                if mykey not in realsyslist:
                        realsyslist.append(mykey)
 
 for mykey in biglist:
-       #print "checking:",mykey
+       #print("checking:",mykey)
        try:
-               mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
-       except KeyError:
+               mylist = portage.db[eroot]["vartree"].dbapi.match(mykey)
+       except (portage.exception.InvalidAtom, KeyError):
                if "--debug" in sys.argv:
-                       print "* ignoring broken log entry for %s (likely injected)" % mykey
-       except ValueError, e:
-               print "* %s is an ambigous package name, candidates are:\n%s" % (mykey, e)
+                       print("* ignoring broken log entry for %s (likely injected)" % mykey)
+       except ValueError as e:
+               try:
+                       print("* %s is an ambiguous package name, candidates are:\n%s" % (mykey, e))
+               except AttributeError:
+                       # FIXME: Find out what causes this (bug #344845).
+                       print("* %s is an ambiguous package name" % (mykey,))
                continue
        if mylist:
                #print "mylist:",mylist
                myfavkey=portage.cpv_getkey(mylist[0])
                if (myfavkey not in realsyslist) and (myfavkey not in worldlist):
-                       print "add to world:",myfavkey
+                       print("add to world:",myfavkey)
                        worldlist.append(myfavkey)
 
-portage.write_atomic(os.path.join("/", portage.WORLD_FILE), "\n".join(worldlist))
+if not worldlist:
+       pass
+else:
+       existing_set = WorldSelectedSet(eroot)
+       existing_set.load()
+
+       if not existing_set:
+               existing_set.replace(worldlist)
+       else:
+               old_world = existing_set._filename
+               fd, tmp_filename = tempfile.mkstemp(suffix=".tmp",
+                       prefix=os.path.basename(old_world) + ".",
+                       dir=os.path.dirname(old_world))
+               os.close(fd)
+
+               new_set = StaticFileSet(tmp_filename)
+               new_set.update(worldlist)
+
+               if existing_set.getAtoms() == new_set.getAtoms():
+                       os.unlink(tmp_filename)
+               else:
+                       new_set.write()
+
+                       msg = "Please review differences between old and new files, " + \
+                               "and replace the old file if desired."
+
+                       portage.util.writemsg_stdout("\n",
+                               noiselevel=-1)
+                       for line in textwrap.wrap(msg, 65):
+                               portage.util.writemsg_stdout("%s\n" % line,
+                                       noiselevel=-1)
+                       portage.util.writemsg_stdout("\n",
+                               noiselevel=-1)
+                       portage.util.writemsg_stdout("  old: %s\n\n" % old_world,
+                               noiselevel=-1)
+                       portage.util.writemsg_stdout("  new: %s\n\n" % tmp_filename,
+                               noiselevel=-1)