For bug #183167, explicitly call elog_process() when --buildpkgonly is enabled.
[portage.git] / pym / emerge / __init__.py
index b3a03b632fc1a73f624aeafcb57f833b6da589a9..57447e8f1b63867ad4a4528dabd4eb155d6b8ba5 100644 (file)
@@ -208,7 +208,7 @@ def emergelog(xterm_titles, mystr, short_msg=None):
        if xterm_titles:
                if short_msg == None:
                        short_msg = mystr
-               if "HOSTNAME" in os.environ.keys():
+               if "HOSTNAME" in os.environ:
                        short_msg = os.environ["HOSTNAME"]+": "+short_msg
                xtermTitle(short_msg)
        try:
@@ -362,7 +362,7 @@ def create_depgraph_params(myopts, myaction):
        return myparams
 
 # search functionality
-class search:
+class search(object):
 
        #
        # class constants
@@ -441,7 +441,7 @@ class search:
                                if self.searchre.search(full_desc):
                                        self.matches["desc"].append([full_package,masked])
                self.mlen=0
-               for mtype in self.matches.keys():
+               for mtype in self.matches:
                        self.matches[mtype].sort()
                        self.mlen += len(self.matches[mtype])
 
@@ -450,7 +450,7 @@ class search:
                print "\b\b  \n[ Results for search key : "+white(self.searchkey)+" ]"
                print "[ Applications found : "+white(str(self.mlen))+" ]"
                print " "
-               for mtype in self.matches.keys():
+               for mtype in self.matches:
                        for match,masked in self.matches[mtype]:
                                if mtype=="pkg":
                                        catpack=match
@@ -586,10 +586,12 @@ def clean_world(vardb, cpv):
                else:
                        #this doesn't match the package we're unmerging; keep it.
                        newworldlist.append(x)
-
+       
+       newworldlist.sort()
+       
        portage.util.ensure_dirs(os.path.join(vardb.root, portage.PRIVATE_PATH),
                gid=portage.portage_gid, mode=02770)
-       portage.util.write_atomic(world_filename, "\n".join(newworldlist))
+       portage.util.write_atomic(world_filename, "\n".join(newworldlist)+"\n")
 
 def genericdict(mylist):
        mynewdict={}
@@ -910,7 +912,7 @@ def show_invalid_depstring_notice(parent_node, depstring, error_msg):
                f.add_flowing_data(x)
        f.end_paragraph(1)
 
-class depgraph:
+class depgraph(object):
 
        pkg_tree_map = {
                "ebuild":"porttree",
@@ -2214,13 +2216,25 @@ class depgraph:
                        mylist = getlist(self.settings, "system")
                        worlddict=genericdict(worldlist)
 
-                       for x in worlddict.keys():
+                       for x in worlddict:
                                if not portage.isvalidatom(x):
                                        world_problems = True
-                               elif not self.trees[self.target_root]["vartree"].dbapi.match(x):
+                                       continue
+                               elif not vardb.match(x):
                                        world_problems = True
-                               else:
-                                       mylist.append(x)
+                                       available = False
+                                       if "--usepkgonly" not in self.myopts and \
+                                               portdb.match(x):
+                                               available = True
+                                       elif "--usepkg" in self.myopts:
+                                               mymatches = bindb.match(x)
+                                               if "--usepkgonly" not in self.myopts:
+                                                       mymatches = visible(mymatches)
+                                               if mymatches:
+                                                       available = True
+                                       if not available:
+                                               continue
+                               mylist.append(x)
 
                newlist = []
                for atom in mylist:
@@ -2464,6 +2478,8 @@ class depgraph:
                # files to fetch list - avoids counting a same file twice
                # in size display (verbose mode)
                myfetchlist=[]
+               worldlist = set(getlist(self.settings, "world"))
+
                for mylist_index in xrange(len(mylist)):
                        x, depth, ordered = mylist[mylist_index]
                        pkg_type = x[0]
@@ -2499,6 +2515,7 @@ class depgraph:
                        else:
                                mydbapi = self.trees[myroot][self.pkg_tree_map[pkg_type]].dbapi
                                pkg_status = x[3]
+                               pkg_merge = ordered and pkg_status != "nomerge"
                                binary_package = True
                                if "ebuild" == pkg_type:
                                        if "merge" == x[3] or \
@@ -2672,7 +2689,7 @@ class depgraph:
                                if verbosity == 3:
                                        # size verbose
                                        mysize=0
-                                       if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
+                                       if pkg_type == "ebuild" and pkg_merge:
                                                try:
                                                        myfilesdict = portdb.getfetchsizes(pkg_key,
                                                                useflags=self.useFlags[myroot][pkg_key],
@@ -2685,7 +2702,7 @@ class depgraph:
                                                if myfilesdict is None:
                                                        myfilesdict="[empty/missing/bad digest]"
                                                else:
-                                                       for myfetchfile in myfilesdict.keys():
+                                                       for myfetchfile in myfilesdict:
                                                                if myfetchfile not in myfetchlist:
                                                                        mysize+=myfilesdict[myfetchfile]
                                                                        myfetchlist.append(myfetchfile)
@@ -2732,17 +2749,32 @@ class depgraph:
                                                myoldbest=myoldbest[:-3]
                                        myoldbest=blue("["+myoldbest+"]")
 
+                               pkg_cp = xs[0]
+                               pkg_world = pkg_cp in worldlist
+
+                               def pkgprint(pkg):
+                                       if pkg_merge:
+                                               if pkg_world:
+                                                       return colorize("PKG_MERGE_WORLD", pkg)
+                                               else:
+                                                       return colorize("PKG_MERGE", pkg)
+                                       else:
+                                               if pkg_world:
+                                                       return colorize("PKG_NOMERGE_WORLD", pkg)
+                                               else:
+                                                       return colorize("PKG_NOMERGE", pkg)
+
                                if x[1]!="/":
                                        if myoldbest:
                                                myoldbest +=" "
                                        if "--columns" in self.myopts:
                                                if "--quiet" in self.myopts:
-                                                       myprint=addl+" "+indent+darkgreen(xs[0])
+                                                       myprint=addl+" "+indent+pkgprint(pkg_cp)
                                                        myprint=myprint+darkblue(" "+xs[1]+xs[2])+" "
                                                        myprint=myprint+myoldbest
                                                        myprint=myprint+darkgreen("to "+x[1])
                                                else:
-                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+                                                       myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
                                                        if (newlp-nc_len(myprint)) > 0:
                                                                myprint=myprint+(" "*(newlp-nc_len(myprint)))
                                                        myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
@@ -2751,21 +2783,21 @@ class depgraph:
                                                        myprint=myprint+myoldbest
                                                        myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
                                        else:
-                                               if x[-1] == "nomerge" or not ordered:
-                                                       myprint = darkblue("[nomerge      ] ")
+                                               if not pkg_merge:
+                                                       myprint = "[%s      ] " % pkgprint("nomerge")
                                                else:
                                                        myprint = "[" + pkg_type + " " + addl + "] "
-                                               myprint += indent + darkgreen(pkg_key) + " " + \
+                                               myprint += indent + pkgprint(pkg_key) + " " + \
                                                        myoldbest + darkgreen("to " + myroot) + " " + \
                                                        verboseadd
                                else:
                                        if "--columns" in self.myopts:
                                                if "--quiet" in self.myopts:
-                                                       myprint=addl+" "+indent+darkgreen(xs[0])
+                                                       myprint=addl+" "+indent+pkgprint(pkg_cp)
                                                        myprint=myprint+" "+green(xs[1]+xs[2])+" "
                                                        myprint=myprint+myoldbest
                                                else:
-                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(xs[0])
+                                                       myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_cp)
                                                        if (newlp-nc_len(myprint)) > 0:
                                                                myprint=myprint+(" "*(newlp-nc_len(myprint)))
                                                        myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
@@ -2773,10 +2805,10 @@ class depgraph:
                                                                myprint=myprint+(" "*(oldlp-nc_len(myprint)))
                                                        myprint=myprint+myoldbest+"  "+verboseadd
                                        else:
-                                               if x[-1] == "nomerge" or not ordered:
-                                                       myprint=darkblue("[nomerge      ] "+indent+x[2]+" "+myoldbest+" ")+verboseadd
+                                               if not pkg_merge:
+                                                       myprint="["+pkgprint("nomerge")+"      ] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
                                                else:
-                                                       myprint="["+x[0]+" "+addl+"] "+indent+darkgreen(x[2])+" "+myoldbest+" "+verboseadd
+                                                       myprint="["+pkgprint(pkg_type)+" "+addl+"] "+indent+pkgprint(pkg_key)+" "+myoldbest+" "+verboseadd
                                p.append(myprint)
 
                        mysplit = portage.pkgsplit(x[2])
@@ -2963,6 +2995,7 @@ class MergeTask(object):
                                portage.config(clone=trees["/"]["vartree"].settings)
 
        def merge(self, mylist, favorites, mtimedb):
+               from portage.elog import elog_process
                failed_fetches = []
                fetchonly = "--fetchonly" in self.myopts or \
                        "--fetch-all-uri" in self.myopts
@@ -3050,7 +3083,7 @@ class MergeTask(object):
                                "--pretend" in self.myopts):
                                portage.write_atomic(
                                        os.path.join(self.target_root, portage.WORLD_FILE),
-                                       "\n".join(myfavdict.values()))
+                                               "\n".join(sorted(myfavdict.values())) + "\n")
 
                        mtimedb["resume"]["mergelist"]=mymergelist[:]
                        mtimedb.commit()
@@ -3196,6 +3229,8 @@ class MergeTask(object):
                                                        pkgsettings, self.edebug, mydbapi=portdb,
                                                        tree="porttree")
                                                del pkgsettings["PORTAGE_BINPKG_TMPFILE"]
+                                               if "--buildpkgonly" in self.myopts:
+                                                       elog_process(pkg_key, pkgsettings)
                                                if retval != os.EX_OK:
                                                        return retval
                                                bintree = self.trees[myroot]["bintree"]
@@ -3327,7 +3362,7 @@ class MergeTask(object):
                                                        ") Updating world file ("+x[pkgindex]+")")
                                                portage.write_atomic(
                                                os.path.join(myroot, portage.WORLD_FILE),
-                                               "\n".join(myfavdict.values()))
+                                               "\n".join(sorted(myfavdict.values()))+"\n")
 
                                if "--pretend" not in self.myopts and \
                                        "--fetchonly" not in self.myopts and \
@@ -3600,7 +3635,7 @@ def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
                                        if not slotmap.has_key(myslot):
                                                slotmap[myslot]={}
                                        slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
-                               for myslot in slotmap.keys():
+                               for myslot in slotmap:
                                        counterkeys=slotmap[myslot].keys()
                                        counterkeys.sort()
                                        if not counterkeys:
@@ -3627,7 +3662,7 @@ def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
        finally:
                if vdb_lock:
                        portage.locks.unlockdir(vdb_lock)
-       for x in pkgmap.keys():
+       for x in pkgmap:
                for y in localtree.dep_match(x):
                        if y not in pkgmap[x]["omitted"] and \
                           y not in pkgmap[x]["selected"] and \
@@ -3683,7 +3718,7 @@ def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
        if not autoclean:
                countdown(int(settings["CLEAN_DELAY"]), ">>> Unmerging")
 
-       for x in pkgmap.keys():
+       for x in pkgmap:
                for y in pkgmap[x]["selected"]:
                        print ">>> Unmerging "+y+"..."
                        emergelog(xterm_titles, "=== Unmerging... ("+y+")")
@@ -3788,15 +3823,20 @@ def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
                                print " "+green("*")+" Processed",icount,"info files."
 
 
-def display_news_notification(settings):
-       target_root = settings["ROOT"]
+def display_news_notification(trees):
+       for target_root in trees:
+               if len(trees) > 1 and target_root != "/":
+                       break
+       settings = trees[target_root]["vartree"].settings
+       portdb = trees[target_root]["porttree"].dbapi
+       vardb = trees[target_root]["vartree"].dbapi
        NEWS_PATH = os.path.join("metadata", "news")
        UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
-       porttree = portdbapi(porttree_root=settings["PORTDIR"], mysettings=settings)
        newsReaderDisplay = False
 
-       for repo in porttree.getRepositories():
-               unreadItems = checkUpdatedNewsItems(target_root, NEWS_PATH, UNREAD_PATH, repo)
+       for repo in portdb.getRepositories():
+               unreadItems = checkUpdatedNewsItems(
+                       portdb, vardb, NEWS_PATH, UNREAD_PATH, repo)
                if unreadItems:
                        if not newsReaderDisplay:
                                newsReaderDisplay = True
@@ -3810,7 +3850,7 @@ def display_news_notification(settings):
                print "Use " + colorize("GOOD", "eselect news") + " to read news items."
                print
 
-def post_emerge(settings, mtimedb, retval, vardbapi):
+def post_emerge(trees, mtimedb, retval):
        """
        Misc. things to run at the end of a merge session.
        
@@ -3820,9 +3860,9 @@ def post_emerge(settings, mtimedb, retval, vardbapi):
        Commit mtimeDB
        Display preserved libs warnings
        Exit Emerge
-       
-       @param settings: Configuration settings (typically portage.settings)
-       @type settings: portage.config()
+
+       @param trees: A dictionary mapping each ROOT to it's package databases
+       @type trees: dict
        @param mtimedb: The mtimeDB to store data needed across merge invocations
        @type mtimedb: MtimeDB class instance
        @param retval: Emerge's return value
@@ -3831,7 +3871,11 @@ def post_emerge(settings, mtimedb, retval, vardbapi):
        @returns:
        1.  Calls sys.exit(retval)
        """
-       target_root = settings["ROOT"]
+       for target_root in trees:
+               if len(trees) > 1 and target_root != "/":
+                       break
+       vardbapi = trees[target_root]["vartree"].dbapi
+       settings = vardbapi.settings
        info_mtimes = mtimedb["info"]
 
        # Load the most current variables from ${ROOT}/etc/profile.env
@@ -3848,17 +3892,22 @@ def post_emerge(settings, mtimedb, retval, vardbapi):
        emergelog("notitles" not in settings.features,
                " *** exiting successfully.")
 
+       # Dump the mod_echo output now so that our other notifications are shown
+       # last.
+       from portage.elog import mod_echo
+       mod_echo.finalize()
+
        if "noinfo" not in settings.features:
                chk_updated_info_files(target_root, infodirs, info_mtimes, retval)
 
        chk_updated_cfg_files(target_root, config_protect)
        
-       display_news_notification(settings)
+       display_news_notification(trees)
        
        if vardbapi.plib_registry.hasEntries():
                print colorize("WARN", "!!!") + " existing preserved libs:"
                plibdata = vardbapi.plib_registry.getPreservedLibs()
-               for cpv in plibdata.keys():
+               for cpv in plibdata:
                        print colorize("WARN", ">>>") + " package: %s" % cpv
                        for f in plibdata[cpv]:
                                print colorize("WARN", " * ") + " - %s" % f
@@ -3903,13 +3952,15 @@ def chk_updated_cfg_files(target_root, config_protect):
                        #print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
                        print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
 
-def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
+def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id):
        """
        Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
        Returns the number of unread (yet relevent) items.
        
-       @param root:
-       @type root:
+       @param portdb: a portage tree database
+       @type portdb: pordbapi
+       @param vardb: an installed package database
+       @type vardb: vardbapi
        @param NEWS_PATH:
        @type NEWS_PATH:
        @param UNREAD_PATH:
@@ -3922,7 +3973,7 @@ def checkUpdatedNewsItems( root, NEWS_PATH, UNREAD_PATH, repo_id ):
        
        """
        from portage.news import NewsManager
-       manager = NewsManager( root, NEWS_PATH, UNREAD_PATH )
+       manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH)
        return manager.getUnreadItems( repo_id, update=True )
 
 def is_valid_package_atom(x):
@@ -4412,7 +4463,7 @@ def action_sync(settings, trees, mtimedb, myopts, myaction):
                print red(" * ")+"To update portage, run 'emerge portage'."
                print
        
-       display_news_notification(settings)
+       display_news_notification(trees)
 
 def action_metadata(settings, portdb, myopts):
        portage.writemsg_stdout("\n>>> Updating Portage cache:      ")
@@ -5116,11 +5167,11 @@ def action_build(settings, trees, mtimedb,
                else:
                        mydepgraph.display(
                                mydepgraph.altlist(reversed=("--tree" in myopts)))
-               if ("--buildpkgonly" in myopts):
-                       if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
-                               print "\n!!! --buildpkgonly requires all dependencies to be merged."
-                               print "!!! You have to merge the dependencies before you can build this package.\n"
-                               sys.exit(1)
+                       if "--buildpkgonly" in myopts and \
+                               not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
+                                       print "\n!!! --buildpkgonly requires all dependencies to be merged."
+                                       print "!!! You have to merge the dependencies before you can build this package.\n"
+                                       sys.exit(1)
        else:
                if ("--buildpkgonly" in myopts):
                        if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
@@ -5438,7 +5489,7 @@ def emerge_main():
        xterm_titles = "notitles" not in settings.features
 
        tmpcmdline = []
-       if "--ignore-default-opts" not in sys.argv:
+       if "--ignore-default-opts" not in myopts:
                tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
        tmpcmdline.extend(sys.argv[1:])
        myaction, myopts, myfiles = parse_opts(tmpcmdline)
@@ -5590,12 +5641,12 @@ def emerge_main():
        # check if root user is the current user for the actions where emerge needs this
        if portage.secpass < 2:
                # We've already allowed "--version" and "--help" above.
-               if "--pretend" not in myopts and \
-               myaction not in ("search","info"):
+               if "--pretend" not in myopts and myaction not in ("search","info"):
                        need_superuser = not \
                                ("--fetchonly" in myopts or \
                                "--fetch-all-uri" in myopts or \
-                               myaction in ("metadata", "regen"))
+                               myaction in ("metadata", "regen") or \
+                               (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK)))
                        if portage.secpass < 1 or \
                                need_superuser:
                                if need_superuser:
@@ -5608,12 +5659,12 @@ def emerge_main():
                                if "--ask" in myopts:
                                        myopts["--pretend"] = True
                                        del myopts["--ask"]
-                                       print ("%s access would be required... " + \
+                                       print ("%s access is required... " + \
                                                "adding --pretend to options.\n") % access_desc
                                        if portage.secpass < 1 and not need_superuser:
                                                portage_group_warning()
                                else:
-                                       sys.stderr.write(("emerge: %s access would be " + \
+                                       sys.stderr.write(("emerge: %s access is " + \
                                                "required.\n\n") % access_desc)
                                        if portage.secpass < 1 and not need_superuser:
                                                portage_group_warning()
@@ -5695,25 +5746,25 @@ def emerge_main():
                if 1 == unmerge(settings, myopts, vartree, myaction, myfiles,
                        mtimedb["ldpath"]):
                        if "--pretend" not in myopts:
-                               post_emerge(settings, mtimedb, 0, trees[settings["ROOT"]]["vartree"].dbapi)
+                               post_emerge(trees, mtimedb, os.EX_OK)
 
        elif "depclean"==myaction:
                validate_ebuild_environment(trees)
                action_depclean(settings, trees, mtimedb["ldpath"],
                        myopts, spinner)
                if "--pretend" not in myopts:
-                       post_emerge(settings, mtimedb, 0, trees[settings["ROOT"]]["vartree"].dbapi)
+                       post_emerge(trees, mtimedb, os.EX_OK)
        # "update", "system", or just process files:
        else:
                validate_ebuild_environment(trees)
                if "--pretend" not in myopts:
-                       display_news_notification(settings)
+                       display_news_notification(trees)
                action_build(settings, trees, mtimedb,
                        myopts, myaction, myfiles, spinner)
                if "--pretend" not in myopts:
-                       post_emerge(settings, mtimedb, 0, trees[settings["ROOT"]]["vartree"].dbapi)
+                       post_emerge(trees, mtimedb, os.EX_OK)
                else:
-                       display_news_notification(settings)
+                       display_news_notification(trees)
 
 if __name__ == "__main__":
        retval = emerge_main()