2 # Copyright 1999-2013 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
5 from __future__ import print_function
8 from os import path as osp
9 pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")
10 sys.path.insert(0, pym_path)
12 portage._internal_caller = True
13 from portage import os
14 from portage._sets.files import StaticFileSet, WorldSelectedSet
20 __candidatematcher__ = re.compile("^[0-9]+: \\*\\*\\* emerge ")
21 __noncandidatematcher__ = re.compile(" sync( |$)| clean( |$)| search( |$)|--oneshot|--fetchonly| unmerge( |$)")
23 def issyspkg(pkgline):
24 return (pkgline[0] == "*")
26 def iscandidate(logline):
27 return (__candidatematcher__.match(logline) \
28 and not __noncandidatematcher__.search(logline))
30 def getpkginfo(logline):
31 logline = re.sub("^[0-9]+: \\*\\*\\* emerge ", "", logline)
32 logline = logline.strip()
33 logline = re.sub("(\\S+\\.(ebuild|tbz2))|(--\\S+)|inject ", "", logline)
34 return logline.strip()
37 def isunwanted(pkgline):
38 if pkgline in ["world", "system", "depclean", "info", "regen", ""]:
40 elif pkgline in __uniqlist__:
42 elif not re.search("^[a-zA-Z<>=~]", pkgline):
45 __uniqlist__.append(pkgline)
48 eroot = portage.settings['EROOT']
49 world_file = os.path.join(eroot, portage.WORLD_FILE)
51 # show a little description if we have arguments
52 if len(sys.argv) >= 2 and sys.argv[1] in ["-h", "--help"]:
53 print("This script regenerates the portage world file by checking the portage")
54 print("logfile for all actions that you've done in the past. It ignores any")
55 print("arguments except --help. It is recommended that you make a backup of")
56 print("your existing world file (%s) before using this tool." % world_file)
59 worldlist = portage.grabfile(world_file)
60 syslist = [x for x in portage.settings.packages if issyspkg(x)]
62 logfile = portage.grabfile(os.path.join(eroot, "var/log/emerge.log"))
63 biglist = [getpkginfo(x) for x in logfile if iscandidate(x)]
67 biglist = [x for x in tmplist if isunwanted(x)]
77 #print("candidate:",mykey)
78 mylist = portage.db[eroot]["vartree"].dbapi.match(mykey)
80 mykey=portage.cpv_getkey(mylist[0])
81 if mykey not in realsyslist:
82 realsyslist.append(mykey)
85 #print("checking:",mykey)
87 mylist = portage.db[eroot]["vartree"].dbapi.match(mykey)
88 except (portage.exception.InvalidAtom, KeyError):
89 if "--debug" in sys.argv:
90 print("* ignoring broken log entry for %s (likely injected)" % mykey)
91 except ValueError as e:
93 print("* %s is an ambiguous package name, candidates are:\n%s" % (mykey, e))
94 except AttributeError:
95 # FIXME: Find out what causes this (bug #344845).
96 print("* %s is an ambiguous package name" % (mykey,))
99 #print "mylist:",mylist
100 myfavkey=portage.cpv_getkey(mylist[0])
101 if (myfavkey not in realsyslist) and (myfavkey not in worldlist):
102 print("add to world:",myfavkey)
103 worldlist.append(myfavkey)
108 existing_set = WorldSelectedSet(eroot)
112 existing_set.replace(worldlist)
114 old_world = existing_set._filename
115 fd, tmp_filename = tempfile.mkstemp(suffix=".tmp",
116 prefix=os.path.basename(old_world) + ".",
117 dir=os.path.dirname(old_world))
120 new_set = StaticFileSet(tmp_filename)
121 new_set.update(worldlist)
123 if existing_set.getAtoms() == new_set.getAtoms():
124 os.unlink(tmp_filename)
128 msg = "Please review differences between old and new files, " + \
129 "and replace the old file if desired."
131 portage.util.writemsg_stdout("\n",
133 for line in textwrap.wrap(msg, 65):
134 portage.util.writemsg_stdout("%s\n" % line,
136 portage.util.writemsg_stdout("\n",
138 portage.util.writemsg_stdout(" old: %s\n\n" % old_world,
140 portage.util.writemsg_stdout(" new: %s\n\n" % tmp_filename,