Rely on PYTHONPATH instead of PORTAGE_PYM_PATH for locating portage's python modules...
[portage.git] / bin / regenworld
1 #!/usr/bin/python
2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Id$
5
6 import sys, os
7 try:
8         import portage
9 except ImportError:
10         sys.path.insert(0, "/usr/lib/portage/pym")
11         import portage
12 import string, re
13
14 __candidatematcher__ = re.compile("^[0-9]+: \\*\\*\\* emerge ")
15 __noncandidatematcher__ = re.compile(" sync( |$)| clean( |$)| search( |$)|--oneshot|--fetchonly| unmerge( |$)")
16
17 def issyspkg(pkgline):
18         return (pkgline[0] == "*")
19
20 def iscandidate(logline):
21         return (__candidatematcher__.match(logline) \
22                                 and not __noncandidatematcher__.search(logline))
23
24 def getpkginfo(logline):
25         logline = re.sub("^[0-9]+: \\*\\*\\* emerge ", "", logline)
26         logline = logline.strip()
27         logline = re.sub("(\\S+\\.(ebuild|tbz2))|(--\\S+)|inject ", "", logline)
28         return logline.strip()
29
30 __uniqlist__ = []
31 def isunwanted(pkgline):
32         if pkgline in ["world", "system", "depclean", "info", "regen", ""]:
33                 return False
34         elif pkgline in __uniqlist__:
35                 return False
36         elif not re.search("^[a-zA-Z<>=~]", pkgline):
37                 return False
38         else:
39                 __uniqlist__.append(pkgline)
40                 return True
41
42 # show a little description if we have arguments
43 if len(sys.argv) >= 2 and sys.argv[1] in ["-h", "--help"]:
44         print "This script regenerates the portage world file by checking the portage"
45         print "logfile for all actions that you've done in the past. It ignores any"
46         print "arguments except --help. It is recommended that you make a backup of"
47         print "your existing world file (%s) before using this tool." % portage.WORLD_FILE
48         sys.exit(0)
49
50 worldlist = portage.grabfile(os.path.join("/", portage.WORLD_FILE))
51 syslist = portage.settings.packages
52 syslist = filter(issyspkg, syslist)
53
54 logfile = portage.grabfile("/var/log/emerge.log")
55 biglist = filter(iscandidate, logfile)
56 biglist = map(getpkginfo, biglist)
57 tmplist = []
58 for l in biglist:
59         tmplist += l.split()
60 biglist = filter(isunwanted, tmplist)
61 #for p in biglist:
62 #       print p
63 #sys.exit(0)
64
65 # resolving virtuals
66 realsyslist = []
67 for mykey in syslist:
68         # drop the asterix
69         mykey = mykey[1:]
70         #print "candidate:",mykey
71         mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
72         if mylist:
73                 mykey=portage.cpv_getkey(mylist[0])
74                 if mykey not in realsyslist:
75                         realsyslist.append(mykey)
76
77 for mykey in biglist:
78         #print "checking:",mykey
79         try:
80                 mylist=portage.db["/"]["vartree"].dbapi.match(mykey)
81         except KeyError:
82                 if "--debug" in sys.argv:
83                         print "* ignoring broken log entry for %s (likely injected)" % mykey
84         except ValueError, e:
85                 print "* %s is an ambigous package name, candidates are:\n%s" % (mykey, e)
86                 continue
87         if mylist:
88                 #print "mylist:",mylist
89                 myfavkey=portage.cpv_getkey(mylist[0])
90                 if (myfavkey not in realsyslist) and (myfavkey not in worldlist):
91                         print "add to world:",myfavkey
92                         worldlist.append(myfavkey)
93
94 portage.write_atomic(os.path.join("/", portage.WORLD_FILE), "\n".join(worldlist))