Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 147516 | Differences between
and this patch

Collapse All | Expand All

(-)portage-2.1.2.orig/bin/emerge (-335 / +720 lines)
Lines 1979-1984 Link Here
1979
		ignore_priority_range = [None]
1979
		ignore_priority_range = [None]
1980
		ignore_priority_range.extend(
1980
		ignore_priority_range.extend(
1981
			xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
1981
			xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
1982
		slotcount=0
1982
		while not mygraph.empty():
1983
		while not mygraph.empty():
1983
			ignore_priority = None
1984
			ignore_priority = None
1984
			nodes = None
1985
			nodes = None
Lines 1988-1998 Link Here
1988
					if not mygraph.contains(node):
1989
					if not mygraph.contains(node):
1989
						asap_nodes.remove(node)
1990
						asap_nodes.remove(node)
1990
						continue
1991
						continue
1991
					if not mygraph.child_nodes(node,
1992
					if not mygraph.child_nodes(node, ignore_priority=DepPriority.SOFT):
1992
						ignore_priority=DepPriority.SOFT):
1993
						nodes = [node]
1993
						nodes = [node]
1994
						asap_nodes.remove(node)
1994
						asap_nodes.remove(node)
1995
						break
1995
						break
1996
			# if no asap node, then get the first non-null set of leaf (root if --tree) nodes in the priority range
1996
			if not nodes:
1997
			if not nodes:
1997
				for ignore_priority in ignore_priority_range:
1998
				for ignore_priority in ignore_priority_range:
1998
					nodes = get_nodes(ignore_priority=ignore_priority)
1999
					nodes = get_nodes(ignore_priority=ignore_priority)
Lines 2007-2014 Link Here
2007
						# output, so it's disabled in reversed mode.
2008
						# output, so it's disabled in reversed mode.
2008
						selected_nodes = nodes
2009
						selected_nodes = nodes
2009
					else:
2010
					else:
2010
						# Only pop one node for optimal merge order.
2011
						# For optimal merge order:
2011
						selected_nodes = [nodes[0]]
2012
						#  * Only pop one node.
2013
						#  * Removing a root node (node without a parent)
2014
						#    will not produce a leaf node, so avoid it.
2015
						for node in nodes:
2016
							if mygraph.parent_nodes(node):
2017
								# found a non-root node
2018
								selected_nodes = [node]
2019
								break
2020
						if not selected_nodes:
2021
							# settle for a root node
2022
							selected_nodes = [nodes[0]]
2012
				else:
2023
				else:
2013
					"""Recursively gather a group of nodes that RDEPEND on
2024
					"""Recursively gather a group of nodes that RDEPEND on
2014
					eachother.  This ensures that they are merged as a group
2025
					eachother.  This ensures that they are merged as a group
Lines 2019-2035 Link Here
2019
						if node not in mergeable_nodes:
2030
						if node not in mergeable_nodes:
2020
							return False
2031
							return False
2021
						selected_nodes.add(node)
2032
						selected_nodes.add(node)
2022
						for child in mygraph.child_nodes(node,
2033
						for child in mygraph.child_nodes(node, ignore_priority=DepPriority.SOFT):
2023
							ignore_priority=DepPriority.SOFT):
2034
							if not gather_deps(mergeable_nodes, selected_nodes, child):
2024
							if not gather_deps(
2025
								mergeable_nodes, selected_nodes, child):
2026
								return False
2035
								return False
2027
						return True
2036
						return True
2028
					mergeable_nodes = set(nodes)
2037
					mergeable_nodes = set(nodes)
2029
					for node in nodes:
2038
					for node in nodes:
2030
						selected_nodes = set()
2039
						selected_nodes = set()
2031
						if gather_deps(
2040
						if gather_deps(mergeable_nodes, selected_nodes, node):
2032
							mergeable_nodes, selected_nodes, node):
2033
							break
2041
							break
2034
						else:
2042
						else:
2035
							selected_nodes = None
2043
							selected_nodes = None
Lines 2058-2064 Link Here
2058
				sys.exit(1)
2066
				sys.exit(1)
2059
2067
2060
			for node in selected_nodes:
2068
			for node in selected_nodes:
2061
				retlist.append(list(node))
2069
				node2 = list(node)
2070
				if len(node2) == 4:
2071
					node2.append(str(slotcount))
2072
				retlist.append(node2)
2062
				mygraph.remove(node)
2073
				mygraph.remove(node)
2063
				if not reversed and not circular_blocks and myblockers.contains(node):
2074
				if not reversed and not circular_blocks and myblockers.contains(node):
2064
					"""This node may have invalidated one or more blockers."""
2075
					"""This node may have invalidated one or more blockers."""
Lines 2067-2072 Link Here
2067
						if not myblockers.child_nodes(blocker):
2078
						if not myblockers.child_nodes(blocker):
2068
							myblockers.remove(blocker)
2079
							myblockers.remove(blocker)
2069
							del self.blocker_parents[blocker]
2080
							del self.blocker_parents[blocker]
2081
			slotcount += 1
2070
2082
2071
		if not reversed:
2083
		if not reversed:
2072
			"""Blocker validation does not work with reverse mode,
2084
			"""Blocker validation does not work with reverse mode,
Lines 2269-2275 Link Here
2269
		for x in mylist:
2281
		for x in mylist:
2270
			if "blocks" == x[0]:
2282
			if "blocks" == x[0]:
2271
				continue
2283
				continue
2272
			graph_key = tuple(x)
2284
			graph_key = tuple(x[:-1])
2273
			if "--tree" in self.myopts:
2285
			if "--tree" in self.myopts:
2274
				depth = len(tree_nodes)
2286
				depth = len(tree_nodes)
2275
				while depth and graph_key not in \
2287
				while depth and graph_key not in \
Lines 2283-2295 Link Here
2283
		for i in xrange(len(mylist)-1,-1,-1):
2295
		for i in xrange(len(mylist)-1,-1,-1):
2284
			if "blocks" == mylist[i][0]:
2296
			if "blocks" == mylist[i][0]:
2285
				continue
2297
				continue
2286
			graph_key = tuple(mylist[i])
2298
			graph_key = tuple(mylist[i][:-1])
2287
			if mylist[i][-1] != "nomerge":
2299
			if mylist[i][-2] != "nomerge":
2288
				last_merge_depth = node_depth[graph_key]
2300
				last_merge_depth = node_depth[graph_key]
2289
				continue
2301
				continue
2290
			if node_depth[graph_key] >= last_merge_depth or \
2302
			if node_depth[graph_key] >= last_merge_depth or \
2291
				i < len(mylist) - 1 and \
2303
				i < len(mylist) - 1 and \
2292
				node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
2304
				node_depth[graph_key] >= node_depth[tuple(mylist[i+1][:-1])]:
2293
					del mylist[i]
2305
					del mylist[i]
2294
					del node_depth[graph_key]
2306
					del node_depth[graph_key]
2295
		del tree_nodes
2307
		del tree_nodes
Lines 2485-2491 Link Here
2485
				if verbosity == 3:
2497
				if verbosity == 3:
2486
					# size verbose
2498
					# size verbose
2487
					mysize=0
2499
					mysize=0
2488
					if x[0] == "ebuild" and x[-1]!="nomerge":
2500
					if x[0] == "ebuild" and x[-2]!="nomerge":
2489
						try:
2501
						try:
2490
							myfilesdict = portdb.getfetchsizes(pkg_key,
2502
							myfilesdict = portdb.getfetchsizes(pkg_key,
2491
								useflags=self.useFlags[myroot][pkg_key],
2503
								useflags=self.useFlags[myroot][pkg_key],
Lines 2537-2543 Link Here
2537
				oldlp=mywidth-30
2549
				oldlp=mywidth-30
2538
				newlp=oldlp-30
2550
				newlp=oldlp-30
2539
2551
2540
				indent = " " * node_depth[tuple(x)]
2552
				indent = " " * node_depth[tuple(x[:-1])]
2541
2553
2542
				if myoldbest:
2554
				if myoldbest:
2543
					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2555
					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
Lines 2769-2779 Link Here
2769
			self.pkgsettings["/"] = \
2781
			self.pkgsettings["/"] = \
2770
				portage.config(clone=trees["/"]["vartree"].settings)
2782
				portage.config(clone=trees["/"]["vartree"].settings)
2771
2783
2772
	def merge(self, mylist, favorites, mtimedb):
2784
	def restart_portage(self, x, mergecount, totalcount, mtimedb):
2785
		xterm_titles = "notitles" not in self.settings.features
2786
		# don't really restart if any of these is true
2787
		# XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
2788
		if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
2789
			"--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
2790
			return
2791
2792
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2793
			"--resume"])
2794
		mysplit=portage.pkgsplit(x[2])
2795
		myver=mysplit[1]+"-"+mysplit[2]
2796
		if myver[-3:]=='-r0':
2797
			myver=myver[:-3]
2798
		if (myver != portage.VERSION) and \
2799
		   "livecvsportage" not in self.settings.features:
2800
			if totalcount > mergecount:
2801
				emergelog(xterm_titles,
2802
					" ::: completed emerge ("+ \
2803
					str(mergecount)+" of "+ \
2804
					str(totalcount)+") "+ \
2805
					x[2]+" to "+x[1])
2806
				emergelog(xterm_titles, " *** RESTARTING " + \
2807
					"emerge via exec() after change of " + \
2808
					"portage version.")
2809
				portage.run_exitfuncs()
2810
				mynewargv=[sys.argv[0],"--resume"]
2811
				for myopt, myarg in self.myopts.iteritems():
2812
					if myopt not in bad_resume_opts:
2813
						if myarg is True:
2814
							mynewargv.append(myopt)
2815
						else:
2816
							mynewargv.append(myopt +"="+ myarg)
2817
				# priority only needs to be adjusted on the first run
2818
				os.environ["PORTAGE_NICENESS"] = "0"
2819
				os.execv(mynewargv[0], mynewargv)
2820
2821
	def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
2822
		xterm_titles = "notitles" not in self.settings.features
2823
		myfeat = self.settings.features[:]
2824
		ldpath_mtimes = mtimedb["ldpath"]
2825
		myroot=x[1]
2826
		pkg_key = x[2]
2827
		pkg_cat = x[2].split("/")[0]
2828
		pkg_pf = x[2].split("/")[1]
2829
		pkgindex=2
2830
		if x[0]=="blocks":
2831
			pkgindex=3
2832
2833
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
2834
		logid_path = None
2835
		null_log = 0
2836
2837
		if self.settings.get("PORT_LOGDIR", "") == "":
2838
			while "PORT_LOGDIR" in self.settings:
2839
				del self.settings["PORT_LOGDIR"]
2840
		if "PORT_LOGDIR" in self.settings:
2841
			port_logdir = self.settings["PORT_LOGDIR"]
2842
		else:
2843
			port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
2844
2845
		try:
2846
			portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
2847
						 gid=portage.portage_gid, mode=02770)
2848
		except portage_exception.PortageException, e:
2849
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
2850
			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
2851
				self.settings["PORT_LOGDIR"], noiselevel=-1)
2852
			writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
2853
			null_log = 1
2854
2855
		if not null_log:
2856
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
2857
			if not os.path.exists(logid_path):
2858
				f = open(logid_path, "w")
2859
				f.close()
2860
				del f
2861
			logid_time = time.strftime("%Y%m%d-%H%M%S",
2862
				time.gmtime(os.stat(logid_path).st_mtime))
2863
			logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
2864
				(pkg_cat, pkg_pf, logid_time))
2865
			del logid_time
2866
		else:
2867
			logfile = "/dev/null"
2868
2869
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
2870
			print ">>> Emerging (" + \
2871
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2872
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
2873
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
2874
			print ">>> Logfile in " + logfile
2875
			emergelog(xterm_titles, " >>> emerge ("+\
2876
				str(mergecount)+" of "+str(totalcount)+\
2877
				") "+x[pkgindex]+" to "+x[1])
2878
2879
		# need to spawn a --nodeps emerge in a separate process.
2880
		pkg="="+x[2]
2881
		merge_env = os.environ.copy()
2882
		merge_env["PORTAGE_INTERNAL_CALL"] = "1"
2883
		merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
2884
		merge_args = [sys.argv[0], "--nodeps", "--oneshot", pkg]
2885
		good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
2886
					"--usepkg", "--usepkgonly"])
2887
		fd_pipes = None
2888
		merge_logfd = None
2889
		for myopt, myarg in self.myopts.iteritems():
2890
			# don't clobber the logfile at the same time as parallel fetch is
2891
			# all log of parallel fetch will go /var/log/emerge-fetch.log
2892
			# so, just leave 0,1,2 alone.
2893
			if "parallel-fetch" in myfeat and myopt == "--fetchonly":
2894
				fd_pipes = {0:0, 1:1, 2:2}
2895
			if myopt in good_nodeps_opts:
2896
				if myarg is True:
2897
					merge_args.append(myopt)
2898
				else:
2899
					merge_args.append(myopt +"="+ myarg)
2900
		if not fd_pipes:
2901
			merge_logfd = open(logfile, "w")
2902
			# put in a start message. This also makes sure that this fd is pointing to a good file on disk
2903
			# and hence will be used throughout the other spawns that will happen in the children.
2904
			merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
2905
			merge_logfd.flush()
2906
			fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
2907
			portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
2908
2909
		mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
2910
		if merge_logfd:
2911
			merge_logfd.close() # child has exclusive rights to it now.
2912
		return mypids[0]
2913
2914
	def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
2915
		xterm_titles = "notitles" not in self.settings.features
2916
		myfeat = self.settings.features[:]
2917
		ldpath_mtimes = mtimedb["ldpath"]
2918
		myroot=x[1]
2919
		pkg_key = x[2]
2920
		pkg_cat = x[2].split("/")[0]
2921
		pkg_pf = x[2].split("/")[1]
2922
		pkgindex=2
2923
		if x[0]=="blocks":
2924
			pkgindex=3
2925
2926
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
2927
			print "\n>>> Emerging (" + \
2928
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2929
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
2930
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
2931
			emergelog(xterm_titles, " >>> emerge ("+\
2932
				str(mergecount)+" of "+str(totalcount)+\
2933
				") "+x[pkgindex]+" to "+x[1])
2934
2935
		portdb = self.trees[myroot]["porttree"].dbapi
2936
		bindb  = self.trees[myroot]["bintree"].dbapi
2937
		vartree = self.trees[myroot]["vartree"]
2938
		pkgsettings = self.pkgsettings[myroot]
2939
		y = portdb.findname(pkg_key)
2940
		pkgsettings["EMERGE_FROM"] = x[0]
2941
		pkgsettings.backup_changes("EMERGE_FROM")
2942
		pkgsettings.reset()
2943
2944
		#buildsyspkg: Check if we need to _force_ binary package creation
2945
		issyspkg = ("buildsyspkg" in myfeat) \
2946
				and x[0] != "blocks" \
2947
				and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2948
				and "--buildpkg" not in self.myopts
2949
		if x[0] in ["ebuild","blocks"]:
2950
			if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2951
				raise Exception, "Merging a blocker"
2952
			elif "--fetchonly" in self.myopts or \
2953
				"--fetch-all-uri" in self.myopts:
2954
				if "--fetch-all-uri" in self.myopts:
2955
					retval = portage.doebuild(y, "fetch", myroot,
2956
						pkgsettings, self.edebug,
2957
						"--pretend" in self.myopts, fetchonly=1,
2958
						fetchall=1, mydbapi=portdb, tree="porttree")
2959
				else:
2960
					retval = portage.doebuild(y, "fetch", myroot,
2961
						pkgsettings, self.edebug,
2962
						"--pretend" in self.myopts, fetchonly=1,
2963
						mydbapi=portdb, tree="porttree")
2964
				if (retval is None) or retval:
2965
					print
2966
					print "!!! Fetch for",y,"failed, continuing..."
2967
					print
2968
2969
				return retval
2970
2971
			portage.doebuild_environment(y, "setup", myroot,
2972
				pkgsettings, self.edebug, 1, portdb)
2973
			catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2974
			portage_util.ensure_dirs(os.path.dirname(catdir),
2975
				uid=portage.portage_uid, gid=portage.portage_gid,
2976
				mode=070, mask=0)
2977
			builddir_lock = None
2978
			catdir_lock = None
2979
			try:
2980
				catdir_lock = portage_locks.lockdir(catdir)
2981
				portage_util.ensure_dirs(catdir,
2982
					uid=portage.portage_uid, gid=portage.portage_gid,
2983
					mode=070, mask=0)
2984
				builddir_lock = portage_locks.lockdir(
2985
					pkgsettings["PORTAGE_BUILDDIR"])
2986
				try:
2987
					portage_locks.unlockdir(catdir_lock)
2988
				finally:
2989
					catdir_lock = None
2990
				msg = " === (%s of %s) Cleaning (%s::%s)" % \
2991
					(mergecount, totalcount, pkg_key, y)
2992
				short_msg = "emerge: (%s of %s) %s Clean" % \
2993
					(mergecount, totalcount, pkg_key)
2994
				emergelog(xterm_titles, msg, short_msg=short_msg)
2995
				retval = portage.doebuild(y, "clean", myroot,
2996
					pkgsettings, self.edebug, cleanup=1,
2997
					mydbapi=portdb, tree="porttree")
2998
2999
				if retval != os.EX_OK:
3000
					return retval
3001
				if "--buildpkg" in self.myopts or issyspkg:
3002
					if issyspkg:
3003
						print ">>> This is a system package, " + \
3004
							"let's pack a rescue tarball."
3005
					msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3006
						(mergecount, totalcount, pkg_key, y)
3007
					short_msg = "emerge: (%s of %s) %s Compile" % \
3008
						(mergecount, totalcount, pkg_key)
3009
					emergelog(xterm_titles, msg, short_msg=short_msg)
3010
					self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3011
					retval = portage.doebuild(y, "package", myroot,
3012
						pkgsettings, self.edebug, mydbapi=portdb,
3013
						tree="porttree")
3014
					if retval != os.EX_OK:
3015
						return retval
3016
					if "--buildpkgonly" not in self.myopts:
3017
						bintree = self.trees[myroot]["bintree"]
3018
						bintree.inject(pkg_key)
3019
						mytbz2 = bintree.getname(pkg_key)
3020
						msg = " === (%s of %s) Merging (%s::%s)" % \
3021
							(mergecount, totalcount, pkg_key, y)
3022
						short_msg = "emerge: (%s of %s) %s Merge" % \
3023
							(mergecount, totalcount, pkg_key)
3024
						emergelog(xterm_titles, msg, short_msg=short_msg)
3025
						retval = portage.merge(pkgsettings["CATEGORY"],
3026
							pkgsettings["PF"], pkgsettings["D"],
3027
							os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3028
							"build-info"), myroot, pkgsettings,
3029
							myebuild=pkgsettings["EBUILD"],
3030
							mytree="porttree", mydbapi=portdb,
3031
							vartree=vartree, prev_mtimes=ldpath_mtimes)
3032
						if retval != os.EX_OK:
3033
							return retval
3034
					elif "noclean" not in pkgsettings.features:
3035
						portage.doebuild(y, "clean", myroot,
3036
							pkgsettings, self.edebug, mydbapi=portdb,
3037
							tree="porttree")
3038
				else:
3039
					msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3040
						(mergecount, totalcount, pkg_key, y)
3041
					short_msg = "emerge: (%s of %s) %s Compile" % \
3042
						(mergecount, totalcount, pkg_key)
3043
					emergelog(xterm_titles, msg, short_msg=short_msg)
3044
					retval = portage.doebuild(y, "merge", myroot,
3045
						pkgsettings, self.edebug, vartree=vartree,
3046
						mydbapi=portdb, tree="porttree",
3047
						prev_mtimes=ldpath_mtimes)
3048
					if retval != os.EX_OK:
3049
						return retval
3050
			finally:
3051
				if builddir_lock:
3052
					portage_locks.unlockdir(builddir_lock)
3053
				try:
3054
					if not catdir_lock:
3055
						# Lock catdir for removal if empty.
3056
						catdir_lock = portage_locks.lockdir(catdir)
3057
				finally:
3058
					if catdir_lock:
3059
						try:
3060
							os.rmdir(catdir)
3061
						except OSError, e:
3062
							if e.errno not in (errno.ENOENT,
3063
								errno.ENOTEMPTY, errno.EEXIST):
3064
								raise
3065
							del e
3066
						portage_locks.unlockdir(catdir_lock)
3067
3068
		elif x[0]=="binary":
3069
			#merge the tbz2
3070
			mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3071
			if "--getbinpkg" in self.myopts:
3072
				tbz2_lock = None
3073
				try:
3074
					if "distlocks" in pkgsettings.features and \
3075
						os.access(pkgsettings["PKGDIR"], os.W_OK):
3076
						portage_util.ensure_dirs(os.path.dirname(mytbz2))
3077
						tbz2_lock = portage_locks.lockfile(mytbz2,
3078
							wantnewlockfile=1)
3079
					if self.trees[myroot]["bintree"].isremote(pkg_key):
3080
						msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3081
							(mergecount, totalcount, pkg_key, mytbz2)
3082
						short_msg = "emerge: (%s of %s) %s Fetch" % \
3083
							(mergecount, totalcount, pkg_key)
3084
						emergelog(xterm_titles, msg, short_msg=short_msg)
3085
						if not self.trees[myroot]["bintree"].gettbz2(
3086
							pkg_key):
3087
							return 1
3088
				finally:
3089
					if tbz2_lock:
3090
						portage_locks.unlockfile(tbz2_lock)
3091
3092
			if "--fetchonly" in self.myopts or \
3093
				"--fetch-all-uri" in self.myopts:
3094
				return os.EX_OK
3095
3096
			short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
3097
			emergelog(xterm_titles, " === ("+str(mergecount)+\
3098
				" of "+str(totalcount)+") Merging Binary ("+\
3099
				x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3100
3101
			retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3102
				mydbapi=bindb,
3103
				vartree=self.trees[myroot]["vartree"],
3104
				prev_mtimes=ldpath_mtimes)
3105
			if retval != os.EX_OK:
3106
				return retval
3107
			#need to check for errors
3108
		if "--buildpkgonly" not in self.myopts:
3109
			self.trees[x[1]]["vartree"].inject(x[2])
3110
			myfavkey=portage.cpv_getkey(x[2])
3111
			if "--fetchonly" not in self.myopts and \
3112
				"--fetch-all-uri" not in self.myopts and \
3113
				myfavkey in favorites:
3114
				myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3115
				myfavdict=genericdict(myfavs)
3116
				#don't record if already in system profile or already recorded
3117
				if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3118
					#we don't have a favorites entry for this package yet; add one
3119
					myfavdict[myfavkey]=myfavkey
3120
					print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3121
					emergelog(xterm_titles, " === ("+\
3122
						str(mergecount)+" of "+\
3123
						str(totalcount)+\
3124
						") Updating world file ("+x[pkgindex]+")")
3125
					portage.write_atomic(
3126
					os.path.join(myroot, portage.WORLD_FILE),
3127
					"\n".join(myfavdict.values()))
3128
3129
			if "--pretend" not in self.myopts and \
3130
				"--fetchonly" not in self.myopts and \
3131
				"--fetch-all-uri" not in self.myopts:
3132
				# Clean the old package that we have merged over top of it.
3133
				if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3134
					xsplit=portage.pkgsplit(x[2])
3135
					emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3136
					retval = unmerge(pkgsettings, self.myopts, vartree,
3137
						"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3138
					if not retval:
3139
						emergelog(xterm_titles,
3140
							" --- AUTOCLEAN: Nothing unmerged.")
3141
				else:
3142
					portage.writemsg_stdout(colorize("WARN", "WARNING:")
3143
						+ " AUTOCLEAN is disabled.  This can cause serious"
3144
						+ " problems due to overlapping packages.\n")
3145
3146
3147
		if "--pretend" not in self.myopts and \
3148
			"--fetchonly" not in self.myopts and \
3149
			"--fetch-all-uri" not in self.myopts:
3150
			if "noclean" not in self.settings.features:
3151
				short_msg = "emerge: (%s of %s) %s Clean Post" % \
3152
					(mergecount, totalcount, x[pkgindex])
3153
				emergelog(xterm_titles, (" === (%s of %s) " + \
3154
					"Post-Build Cleaning (%s::%s)") % \
3155
					(mergecount, totalcount, x[pkgindex], y),
3156
					short_msg=short_msg)
3157
			emergelog(xterm_titles, " ::: completed emerge ("+\
3158
				str(mergecount)+" of "+str(totalcount)+") "+\
3159
				x[2]+" to "+x[1])
3160
3161
		return os.EX_OK
3162
3163
	def print_status(self, totalcount, donec, qsize, failedc):
3164
		print ">>> Jobs Total = "+colorize("WARN", str(totalcount))+" Done = "+\
3165
			colorize("GOOD", str(donec))+" Running = "+colorize("BAD", str(qsize))+\
3166
			" Failed = "+colorize("BAD", str(failedc))
3167
		xtermTitle("Jobs Total = "+str(totalcount)+" Done = "+\
3168
			str(donec)+" Running = "+str(qsize)+" Failed = "+str(failedc))
3169
3170
	def merge(self, mylist, favorites, mtimedb, m_slots):
2773
		failed_fetches = []
3171
		failed_fetches = []
2774
		mymergelist=[]
3172
		mymergelist=[]
2775
		ldpath_mtimes = mtimedb["ldpath"]
3173
		ldpath_mtimes = mtimedb["ldpath"]
2776
		xterm_titles = "notitles" not in self.settings.features
3174
		xterm_titles = "notitles" not in self.settings.features
3175
		parallel = "parallel" in self.settings.features
3176
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3177
3178
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3179
		if self.edebug or "--fetchonly" in self.myopts:
3180
			parallel = False
2777
3181
2778
		#check for blocking dependencies
3182
		#check for blocking dependencies
2779
		if "--fetchonly" not in self.myopts and \
3183
		if "--fetchonly" not in self.myopts and \
Lines 2796-2803 Link Here
2796
		mysysdict = genericdict(getlist(self.settings, "system"))
3200
		mysysdict = genericdict(getlist(self.settings, "system"))
2797
		if "--resume" in self.myopts:
3201
		if "--resume" in self.myopts:
2798
			# We're resuming.
3202
			# We're resuming.
2799
			print colorize("GOOD", "*** Resuming merge...")
2800
			emergelog(xterm_titles, " *** Resuming merge...")
2801
			mymergelist=mtimedb["resume"]["mergelist"][:]
3203
			mymergelist=mtimedb["resume"]["mergelist"][:]
2802
			if "--skipfirst" in self.myopts and mymergelist:
3204
			if "--skipfirst" in self.myopts and mymergelist:
2803
				del mtimedb["resume"]["mergelist"][0]
3205
				del mtimedb["resume"]["mergelist"][0]
Lines 2831-2838 Link Here
2831
					os.path.join(self.target_root, portage.WORLD_FILE),
3233
					os.path.join(self.target_root, portage.WORLD_FILE),
2832
					"\n".join(myfavdict.values()))
3234
					"\n".join(myfavdict.values()))
2833
3235
2834
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3236
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
2835
			mtimedb.commit()
3237
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3238
				mtimedb.commit()
3239
3240
		totalcount = len(mymergelist)
3241
		mergecount=1
3242
3243
		if "--resume" in self.myopts and "--fetchonly" not in self.myopts:
3244
			# We're resuming.
3245
			print colorize("GOOD", "*** Resuming merge...")
3246
			emergelog(xterm_titles, " *** Resuming merge...")
2836
3247
2837
		myfeat = self.settings.features[:]
3248
		myfeat = self.settings.features[:]
2838
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3249
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 2850-2861 Link Here
2850
				print ">>> starting parallel fetching"
3261
				print ">>> starting parallel fetching"
2851
				fetch_log = "/var/log/emerge-fetch.log"
3262
				fetch_log = "/var/log/emerge-fetch.log"
2852
				logfile = open(fetch_log, "w")
3263
				logfile = open(fetch_log, "w")
2853
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3264
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
2854
				portage_util.apply_secpass_permissions(fetch_log,
3265
				portage_util.apply_secpass_permissions(fetch_log,
2855
					uid=portage.portage_uid, gid=portage.portage_gid,
3266
					uid=portage.portage_uid, gid=portage.portage_gid,
2856
					mode=0660)
3267
					mode=0660)
2857
				fetch_env = os.environ.copy()
3268
				fetch_env = os.environ.copy()
2858
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3269
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
2859
				fetch_env["PORTAGE_NICENESS"] = "0"
3270
				fetch_env["PORTAGE_NICENESS"] = "0"
2860
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3271
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2861
				for myopt, myarg in self.myopts.iteritems():
3272
				for myopt, myarg in self.myopts.iteritems():
Lines 2868-3150 Link Here
2868
					fd_pipes=fd_pipes, returnpid=True)
3279
					fd_pipes=fd_pipes, returnpid=True)
2869
				logfile.close() # belongs to the spawned process
3280
				logfile.close() # belongs to the spawned process
2870
3281
2871
		mergecount=0
3282
		if not parallel:
2872
		for x in mymergelist:
3283
			failed_fetches = []
2873
			mergecount+=1
3284
			for x in mymergelist:
2874
			myroot=x[1]
3285
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, mysysdict)
2875
			pkg_key = x[2]
3286
				mergecount += 1
2876
			pkgindex=2
3287
2877
			portdb = self.trees[myroot]["porttree"].dbapi
3288
				# need to short circuit the spawn with --nodeps
2878
			bindb  = self.trees[myroot]["bintree"].dbapi
3289
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
2879
			vartree = self.trees[myroot]["vartree"]
3290
					if retcode != os.EX_OK:
2880
			pkgsettings = self.pkgsettings[myroot]
3291
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
2881
			if x[0]=="blocks":
3292
							failed_fetches.append(x[2])
2882
				pkgindex=3
3293
						else:
2883
			y = portdb.findname(pkg_key)
3294
							return retcode
3295
					# Unsafe for parallel merges
3296
					del mtimedb["resume"]["mergelist"][0]
3297
					# Commit after each merge so that --resume may still work in
3298
					# in the event that portage is not allowed to exit normally
3299
					# due to power failure, SIGKILL, etc...
3300
					mtimedb.commit()
3301
3302
					# unlink the logid_path if any exists
3303
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
3304
					if os.path.exists(logid_path):
3305
						os.unlink(logid_path)
3306
					del logid_path
3307
3308
					# check if we need to restart portage
3309
					mysplit=portage.pkgsplit(pkg_compl)
3310
					if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3311
							self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3312
3313
				else:
3314
					if retcode != os.EX_OK:
3315
						sys.exit(1)
3316
					else:
3317
						sys.exit(0)
3318
2884
			if "--pretend" not in self.myopts:
3319
			if "--pretend" not in self.myopts:
2885
				print "\n>>> Emerging (" + \
3320
				emergelog(xterm_titles, " *** Finished. Cleaning up...")
2886
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2887
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
2888
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
2889
				emergelog(xterm_titles, " >>> emerge ("+\
2890
					str(mergecount)+" of "+str(len(mymergelist))+\
2891
					") "+x[pkgindex]+" to "+x[1])
2892
3321
2893
			pkgsettings["EMERGE_FROM"] = x[0]
3322
			# We're out of the loop... We're done. Delete the resume data.
2894
			pkgsettings.backup_changes("EMERGE_FROM")
3323
			if mtimedb.has_key("resume"):
2895
			pkgsettings.reset()
3324
				del mtimedb["resume"]
3325
			mtimedb.commit()
3326
			
3327
			#by doing an exit this way, --fetchonly can continue to try to
3328
			#fetch everything even if a particular download fails.
3329
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3330
				if failed_fetches:
3331
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
3332
						"encountered.  Please see above for details.\n\n")
3333
					for cpv in failed_fetches:
3334
						sys.stderr.write("   ")
3335
						sys.stderr.write(cpv)
3336
						sys.stderr.write("\n")
3337
					sys.stderr.write("\n")
3338
					sys.exit(1)
3339
				else:
3340
					sys.exit(0)
3341
			return os.EX_OK
2896
3342
2897
			#buildsyspkg: Check if we need to _force_ binary package creation
3343
		# parallel code - dirty starts here...;-)
2898
			issyspkg = ("buildsyspkg" in myfeat) \
3344
		one_in_slot_failed=0
2899
					and x[0] != "blocks" \
3345
		spawnd_pids=[]
2900
					and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3346
2901
					and "--buildpkg" not in self.myopts
3347
		# dirty little trick to get number of cpus from the system
2902
			if x[0] in ["ebuild","blocks"]:
3348
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
2903
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3349
		cpu_count = 0
2904
					raise Exception, "Merging a blocker"
3350
		for data_cpuinfo in fd_cpuinfo.readlines():
2905
				elif "--fetchonly" in self.myopts or \
3351
			if data_cpuinfo.find("cpu MHz") > -1 :
2906
					"--fetch-all-uri" in self.myopts:
3352
				cpu_count += 1
2907
					if "--fetch-all-uri" in self.myopts:
3353
		fd_cpuinfo.close()
2908
						retval = portage.doebuild(y, "fetch", myroot,
3354
2909
							pkgsettings, self.edebug,
3355
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
2910
							"--pretend" in self.myopts, fetchonly=1,
3356
		if cpu_count == 0:
2911
							fetchall=1, mydbapi=portdb, tree="porttree")
3357
			cpu_count = 1
2912
					else:
3358
2913
						retval = portage.doebuild(y, "fetch", myroot,
3359
		spawnd_pkg = {}
2914
							pkgsettings, self.edebug,
3360
		failed_pid = 0
2915
							"--pretend" in self.myopts, fetchonly=1,
3361
		donec = 0
2916
							mydbapi=portdb, tree="porttree")
3362
		failedc = 0
2917
					if (retval is None) or retval:
3363
		logid_path = None
2918
						print
3364
		mylist = m_slots.keys()
2919
						print "!!! Fetch for",y,"failed, continuing..."
3365
		mylist.sort()
2920
						print
3366
		for x in mylist:
2921
						failed_fetches.append(pkg_key)
3367
			# if slot is empty, go on
2922
					continue
3368
			if not m_slots[x]:
3369
				continue
2923
3370
2924
				portage.doebuild_environment(y, "setup", myroot,
3371
			# if previous slot failed, discontinue the emerge
2925
					pkgsettings, self.edebug, 1, portdb)
3372
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
2926
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3373
				break
2927
				portage_util.ensure_dirs(os.path.dirname(catdir),
2928
					uid=portage.portage_uid, gid=portage.portage_gid,
2929
					mode=070, mask=0)
2930
				builddir_lock = None
2931
				catdir_lock = None
2932
				try:
2933
					catdir_lock = portage_locks.lockdir(catdir)
2934
					portage_util.ensure_dirs(catdir,
2935
						uid=portage.portage_uid, gid=portage.portage_gid,
2936
						mode=070, mask=0)
2937
					builddir_lock = portage_locks.lockdir(
2938
						pkgsettings["PORTAGE_BUILDDIR"])
2939
					try:
2940
						portage_locks.unlockdir(catdir_lock)
2941
					finally:
2942
						catdir_lock = None
2943
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
2944
						(mergecount, len(mymergelist), pkg_key, y)
2945
					short_msg = "emerge: (%s of %s) %s Clean" % \
2946
						(mergecount, len(mymergelist), pkg_key)
2947
					emergelog(xterm_titles, msg, short_msg=short_msg)
2948
					retval = portage.doebuild(y, "clean", myroot,
2949
						pkgsettings, self.edebug, cleanup=1,
2950
						mydbapi=portdb, tree="porttree")
2951
					if retval != os.EX_OK:
2952
						return retval
2953
					if "--buildpkg" in self.myopts or issyspkg:
2954
						if issyspkg:
2955
							print ">>> This is a system package, " + \
2956
								"let's pack a rescue tarball."
2957
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
2958
							(mergecount, len(mymergelist), pkg_key, y)
2959
						short_msg = "emerge: (%s of %s) %s Compile" % \
2960
							(mergecount, len(mymergelist), pkg_key)
2961
						emergelog(xterm_titles, msg, short_msg=short_msg)
2962
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
2963
						retval = portage.doebuild(y, "package", myroot,
2964
							pkgsettings, self.edebug, mydbapi=portdb,
2965
							tree="porttree")
2966
						if retval != os.EX_OK:
2967
							return retval
2968
						if "--buildpkgonly" not in self.myopts:
2969
							bintree = self.trees[myroot]["bintree"]
2970
							bintree.inject(pkg_key)
2971
							mytbz2 = bintree.getname(pkg_key)
2972
							msg = " === (%s of %s) Merging (%s::%s)" % \
2973
								(mergecount, len(mymergelist), pkg_key, y)
2974
							short_msg = "emerge: (%s of %s) %s Merge" % \
2975
								(mergecount, len(mymergelist), pkg_key)
2976
							emergelog(xterm_titles, msg, short_msg=short_msg)
2977
							retval = portage.merge(pkgsettings["CATEGORY"],
2978
								pkgsettings["PF"], pkgsettings["D"],
2979
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
2980
								"build-info"), myroot, pkgsettings,
2981
								myebuild=pkgsettings["EBUILD"],
2982
								mytree="porttree", mydbapi=portdb,
2983
								vartree=vartree, prev_mtimes=ldpath_mtimes)
2984
							if retval != os.EX_OK:
2985
								return retval
2986
						elif "noclean" not in pkgsettings.features:
2987
							portage.doebuild(y, "clean", myroot,
2988
								pkgsettings, self.edebug, mydbapi=portdb,
2989
								tree="porttree")
2990
					else:
2991
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
2992
							(mergecount, len(mymergelist), pkg_key, y)
2993
						short_msg = "emerge: (%s of %s) %s Compile" % \
2994
							(mergecount, len(mymergelist), pkg_key)
2995
						emergelog(xterm_titles, msg, short_msg=short_msg)
2996
						retval = portage.doebuild(y, "merge", myroot,
2997
							pkgsettings, self.edebug, vartree=vartree,
2998
							mydbapi=portdb, tree="porttree",
2999
							prev_mtimes=ldpath_mtimes)
3000
						if retval != os.EX_OK:
3001
							return retval
3002
				finally:
3003
					if builddir_lock:
3004
						portage_locks.unlockdir(builddir_lock)
3005
					try:
3006
						if not catdir_lock:
3007
							# Lock catdir for removal if empty.
3008
							catdir_lock = portage_locks.lockdir(catdir)
3009
					finally:
3010
						if catdir_lock:
3011
							try:
3012
								os.rmdir(catdir)
3013
							except OSError, e:
3014
								if e.errno not in (errno.ENOENT,
3015
									errno.ENOTEMPTY, errno.EEXIST):
3016
									raise
3017
								del e
3018
							portage_locks.unlockdir(catdir_lock)
3019
3020
			elif x[0]=="binary":
3021
				#merge the tbz2
3022
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3023
				if "--getbinpkg" in self.myopts:
3024
					tbz2_lock = None
3025
					try:
3026
						if "distlocks" in pkgsettings.features and \
3027
							os.access(pkgsettings["PKGDIR"], os.W_OK):
3028
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
3029
							tbz2_lock = portage_locks.lockfile(mytbz2,
3030
								wantnewlockfile=1)
3031
						if self.trees[myroot]["bintree"].isremote(pkg_key):
3032
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3033
								(mergecount, len(mymergelist), pkg_key, mytbz2)
3034
							short_msg = "emerge: (%s of %s) %s Fetch" % \
3035
								(mergecount, len(mymergelist), pkg_key)
3036
							emergelog(xterm_titles, msg, short_msg=short_msg)
3037
							if not self.trees[myroot]["bintree"].gettbz2(
3038
								pkg_key):
3039
								return 1
3040
					finally:
3041
						if tbz2_lock:
3042
							portage_locks.unlockfile(tbz2_lock)
3043
3374
3044
				if "--fetchonly" in self.myopts or \
3375
			# start multiple merges in parallel mode
3045
					"--fetch-all-uri" in self.myopts:
3376
			num_at_atime = cpu_count + 1
3046
					continue
3047
3377
3048
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3378
			qsize = 0
3049
				emergelog(xterm_titles, " === ("+str(mergecount)+\
3379
			for y in m_slots[x]:
3050
					" of "+str(len(mymergelist))+") Merging Binary ("+\
3380
				# these all can go in parallel, so fork one after the other
3051
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3381
				# but num_at_atime at most
3052
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3382
				if num_at_atime:
3053
					mydbapi=bindb,
3383
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3054
					vartree=self.trees[myroot]["vartree"],
3384
					spawnd_pids.append(onepid)
3055
					prev_mtimes=ldpath_mtimes)
3385
					spawnd_pkg[onepid] = (y[2], x)
3056
				if retval != os.EX_OK:
3386
					num_at_atime -= 1
3057
					return retval
3387
					mergecount += 1
3058
				#need to check for errors
3388
					qsize += 1
3059
			if "--buildpkgonly" not in self.myopts:
3389
				else:
3060
				self.trees[x[1]]["vartree"].inject(x[2])
3390
					self.print_status(totalcount, donec, qsize, failedc)
3061
				myfavkey=portage.cpv_getkey(x[2])
3391
					# let's wait for one of the jobs to finish
3062
				if "--fetchonly" not in self.myopts and \
3392
					onepid = -1
3063
					"--fetch-all-uri" not in self.myopts and \
3393
					while onepid not in spawnd_pids:
3064
					myfavkey in favorites:
3394
						onepid , retval = os.waitpid(-1, 0)
3065
					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3395
					spawnd_pids.remove(onepid)
3066
					myfavdict=genericdict(myfavs)
3396
3067
					#don't record if already in system profile or already recorded
3397
					pkg_compl = spawnd_pkg[onepid][0]
3068
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3398
					pkg_slot = spawnd_pkg[onepid][1]
3069
						#we don't have a favorites entry for this package yet; add one
3399
					# unlink the logid_path
3070
						myfavdict[myfavkey]=myfavkey
3400
					logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3071
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3401
					if os.path.exists(logid_path):
3072
						emergelog(xterm_titles, " === ("+\
3402
						os.unlink(logid_path)
3073
							str(mergecount)+" of "+\
3403
3074
							str(len(mymergelist))+\
3404
					# if it failed, I need to fail next slot but continue to merge all in this slot
3075
							") Updating world file ("+x[pkgindex]+")")
3405
					if retval:
3076
						portage.write_atomic(
3406
						one_in_slot_failed = retval
3077
						os.path.join(myroot, portage.WORLD_FILE),
3407
						failed_pid = onepid
3078
						"\n".join(myfavdict.values()))
3408
						failedc += 1
3079
3080
				if "--pretend" not in self.myopts and \
3081
					"--fetchonly" not in self.myopts and \
3082
					"--fetch-all-uri" not in self.myopts:
3083
					# Clean the old package that we have merged over top of it.
3084
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3085
						xsplit=portage.pkgsplit(x[2])
3086
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3087
						retval = unmerge(pkgsettings, self.myopts, vartree,
3088
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3089
						if not retval:
3090
							emergelog(xterm_titles,
3091
								" --- AUTOCLEAN: Nothing unmerged.")
3092
					else:
3409
					else:
3093
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
3410
						donec += 1
3094
							+ " AUTOCLEAN is disabled.  This can cause serious"
3411
						index = 0
3095
							+ " problems due to overlapping packages.\n")
3412
						print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3096
3413
						# we need to remove this pkg from resume DB
3097
					# Figure out if we need a restart.
3414
						# this is the dirtiest shit I have ever written
3098
					mysplit=portage.pkgsplit(x[2])
3415
						for pkgs in mymergelist:
3099
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3416
							if pkgs[2] == pkg_compl:
3100
						myver=mysplit[1]+"-"+mysplit[2]
3417
								del mymergelist[index]
3101
						if myver[-3:]=='-r0':
3418
								del mtimedb["resume"]["mergelist"][index]
3102
							myver=myver[:-3]
3103
						if (myver != portage.VERSION) and \
3104
						   "livecvsportage" not in self.settings.features:
3105
							if len(mymergelist) > mergecount:
3106
								emergelog(xterm_titles,
3107
									" ::: completed emerge ("+ \
3108
									str(mergecount)+" of "+ \
3109
									str(len(mymergelist))+") "+ \
3110
									x[2]+" to "+x[1])
3111
								emergelog(xterm_titles, " *** RESTARTING " + \
3112
									"emerge via exec() after change of " + \
3113
									"portage version.")
3114
								del mtimedb["resume"]["mergelist"][0]
3115
								mtimedb.commit()
3419
								mtimedb.commit()
3116
								portage.run_exitfuncs()
3420
								# check if we need to restart portage
3117
								mynewargv=[sys.argv[0],"--resume"]
3421
								mysplit=portage.pkgsplit(pkg_compl)
3118
								for myopt, myarg in self.myopts.iteritems():
3422
								if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3119
									if myopt not in bad_resume_opts:
3423
									self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3120
										if myarg is True:
3424
								break
3121
											mynewargv.append(myopt)
3425
							index += 1
3122
										else:
3426
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3123
											mynewargv.append(myopt +"="+ myarg)
3427
					spawnd_pids.append(onepid)
3124
								# priority only needs to be adjusted on the first run
3428
					spawnd_pkg[onepid] = (y[2], x)
3125
								os.environ["PORTAGE_NICENESS"] = "0"
3429
					mergecount += 1
3126
								os.execv(mynewargv[0], mynewargv)
3430
3431
			# this slot is exhausted, so wait for all of the forks to finish
3432
			while spawnd_pids:
3433
				self.print_status(totalcount, donec, qsize, failedc)
3434
				onepid = spawnd_pids[0]
3435
				retval = os.waitpid(onepid, 0)[1]
3436
				spawnd_pids.remove(onepid)
3437
				pkg_compl = spawnd_pkg[onepid][0]
3438
				pkg_slot = spawnd_pkg[onepid][1]
3439
				# unlink the logid_path
3440
				logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3441
				if os.path.exists(logid_path):
3442
					os.unlink(logid_path)
3443
3444
				qsize -= 1
3445
				if retval:
3446
					one_in_slot_failed = retval
3447
					failed_pid = onepid
3448
					failedc += 1
3449
				else:
3450
					donec += 1
3451
					index = 0
3452
					print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3453
					# we need to remove this pkg from resume DB
3454
					# this is the dirtiest shit I have ever written
3455
					for pkgs in mymergelist:
3456
						if pkgs[2] == pkg_compl:
3457
							del mymergelist[index]
3458
							del mtimedb["resume"]["mergelist"][index]
3459
							mtimedb.commit()
3460
							# check if we need to restart portage
3461
							mysplit=portage.pkgsplit(pkg_compl)
3462
							if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3463
								self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3464
							break
3465
						index += 1
3127
3466
3128
			if "--pretend" not in self.myopts and \
3467
		self.print_status(totalcount, donec, qsize, failedc)
3129
				"--fetchonly" not in self.myopts and \
3130
				"--fetch-all-uri" not in self.myopts:
3131
				if "noclean" not in self.settings.features:
3132
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
3133
						(mergecount, len(mymergelist), x[pkgindex])
3134
					emergelog(xterm_titles, (" === (%s of %s) " + \
3135
						"Post-Build Cleaning (%s::%s)") % \
3136
						(mergecount, len(mymergelist), x[pkgindex], y),
3137
						short_msg=short_msg)
3138
				emergelog(xterm_titles, " ::: completed emerge ("+\
3139
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
3140
					x[2]+" to "+x[1])
3141
3468
3142
			# Unsafe for parallel merges
3469
		if one_in_slot_failed:
3143
			del mtimedb["resume"]["mergelist"][0]
3470
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3144
			# Commit after each merge so that --resume may still work in
3471
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
3145
			# in the event that portage is not allowed to exit normally
3472
				sys.exit(1)
3146
			# due to power failure, SIGKILL, etc...
3473
3147
			mtimedb.commit()
3474
			logfile = None
3475
			if "PORT_LOGDIR" in self.settings:
3476
				port_logdir = self.settings["PORT_LOGDIR"]
3477
			else:
3478
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3479
3480
			pkg_cat = spawnd_pkg[failed_pid][0].split("/")[0]
3481
			pkg_pf = spawnd_pkg[failed_pid][0].split("/")[1]
3482
			logid_path = os.path.join(self.settings["PORTAGE_TMPDIR"], "portage")+".logid."+pkg_cat+pkg_pf
3483
			if os.path.exists(logid_path):
3484
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
3485
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3486
					(pkg_cat, pkg_pf, logid_time))
3487
				del logid_time
3488
			del logid_path
3489
3490
			if logfile and os.path.exists(logfile):
3491
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
3492
3493
			portage.writemsg_stdout(red("Package "+spawnd_pkg[failed_pid][0]+" failed to emerge\n"))
3494
			if logfile and os.path.exists(logfile):
3495
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
3496
			sys.exit(one_in_slot_failed)
3148
3497
3149
		if "--pretend" not in self.myopts:
3498
		if "--pretend" not in self.myopts:
3150
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3499
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
Lines 3154-3173 Link Here
3154
			del mtimedb["resume"]
3503
			del mtimedb["resume"]
3155
		mtimedb.commit()
3504
		mtimedb.commit()
3156
3505
3157
		#by doing an exit this way, --fetchonly can continue to try to
3158
		#fetch everything even if a particular download fails.
3159
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3506
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3160
			if failed_fetches:
3507
			sys.exit(0)
3161
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
3508
3162
					"encountered.  Please see above for details.\n\n")
3163
				for cpv in failed_fetches:
3164
					sys.stderr.write("   ")
3165
					sys.stderr.write(cpv)
3166
					sys.stderr.write("\n")
3167
				sys.stderr.write("\n")
3168
				sys.exit(1)
3169
			else:
3170
				sys.exit(0)
3171
		return os.EX_OK
3509
		return os.EX_OK
3172
3510
3173
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3511
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
Lines 3608-3614 Link Here
3608
def validate_merge_list(trees, mergelist):
3946
def validate_merge_list(trees, mergelist):
3609
	"""Validate the list to make sure all the packages are still available.
3947
	"""Validate the list to make sure all the packages are still available.
3610
	This is needed for --resume."""
3948
	This is needed for --resume."""
3611
	for (pkg_type, myroot, pkg_key, action) in mergelist:
3949
	for (pkg_type, myroot, pkg_key, action, merge_slot) in mergelist:
3612
		if pkg_type == "binary" and \
3950
		if pkg_type == "binary" and \
3613
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3951
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3614
			pkg_type == "ebuild" and \
3952
			pkg_type == "ebuild" and \
Lines 4450-4456 Link Here
4450
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4788
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4451
		emergelog(xterm_titles, " >>> depclean")
4789
		emergelog(xterm_titles, " >>> depclean")
4452
4790
4453
	if "--quiet" not in myopts:
4791
	if "--quiet" not in myopts and "--nodeps" not in myopts:
4454
		print "\nCalculating dependencies  ",
4792
		print "\nCalculating dependencies  ",
4455
4793
4456
	soft = 0
4794
	soft = 0
Lines 4547-4552 Link Here
4547
	else:
4885
	else:
4548
		print "Number removed:       "+str(len(cleanlist))
4886
		print "Number removed:       "+str(len(cleanlist))
4549
4887
4888
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
4889
	merge_slots = {}
4890
	for pkg in mergelist:
4891
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
4892
			slot = int(pkg[4])
4893
			try:
4894
				if pkg not in merge_slots[slot]:
4895
					merge_slots[slot].append(pkg)
4896
			except KeyError:
4897
				merge_slots[slot] = [pkg]
4898
	# print the merge slots
4899
	max_slot = 0
4900
	mylist = merge_slots.keys()
4901
	mylist.sort()
4902
	for x in mylist:
4903
		if x > max_slot:
4904
			max_slot = x
4905
		if parallel:
4906
			print "Package list for slot = "+str(x)
4907
			for y in merge_slots[x]:
4908
				print "	",y
4909
	if printonly:
4910
		return
4911
4912
	# make one last pass at the merge_slots and initialize the missing slots to None
4913
	x = 0
4914
	while x < max_slot:
4915
		if x not in merge_slots.keys():
4916
			merge_slots[x] = None
4917
		x += 1
4918
	return merge_slots
4919
4550
def action_build(settings, trees, mtimedb,
4920
def action_build(settings, trees, mtimedb,
4551
	myopts, myaction, myfiles, spinner):
4921
	myopts, myaction, myfiles, spinner):
4552
	ldpath_mtimes = mtimedb["ldpath"]
4922
	ldpath_mtimes = mtimedb["ldpath"]
Lines 4594-4604 Link Here
4594
				myresumeopts[myopt] = myarg
4964
				myresumeopts[myopt] = myarg
4595
		myopts=myresumeopts
4965
		myopts=myresumeopts
4596
		myparams = create_depgraph_params(myopts, myaction)
4966
		myparams = create_depgraph_params(myopts, myaction)
4597
		if not "--quiet" in myopts:
4967
		if not "--quiet" in myopts and "--nodeps" not in myopts:
4598
			print "Calculating dependencies  ",
4968
			print "Calculating dependencies  ",
4969
		if "--nodeps" in myopts:
4970
			spinner.update = spinner.update_quiet
4599
		mydepgraph = depgraph(settings, trees,
4971
		mydepgraph = depgraph(settings, trees,
4600
			myopts, myparams, spinner)
4972
			myopts, myparams, spinner)
4601
		if not "--quiet" in myopts:
4973
		if not "--quiet" in myopts and "--nodeps" not in myopts:
4602
			print "\b\b... done!"
4974
			print "\b\b... done!"
4603
	else:
4975
	else:
4604
		if ("--resume" in myopts):
4976
		if ("--resume" in myopts):
Lines 4607-4625 Link Here
4607
4979
4608
		myparams = create_depgraph_params(myopts, myaction)
4980
		myparams = create_depgraph_params(myopts, myaction)
4609
		if myaction in ["system","world"]:
4981
		if myaction in ["system","world"]:
4610
			if not ("--quiet" in myopts):
4982
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4611
				print "Calculating",myaction,"dependencies  ",
4983
				print "Calculating",myaction,"dependencies  ",
4612
				sys.stdout.flush()
4984
				sys.stdout.flush()
4985
			if "--nodeps" in myopts:
4986
				spinner.update = spinner.update_quiet
4613
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4987
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4614
			if not mydepgraph.xcreate(myaction):
4988
			if not mydepgraph.xcreate(myaction):
4615
				print "!!! Depgraph creation failed."
4989
				print "!!! Depgraph creation failed."
4616
				sys.exit(1)
4990
				sys.exit(1)
4617
			if not ("--quiet" in myopts):
4991
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4618
				print "\b\b... done!"
4992
				print "\b\b... done!"
4619
		else:
4993
		else:
4620
			if not ("--quiet" in myopts):
4994
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4621
				print "Calculating dependencies  ",
4995
				print "Calculating dependencies  ",
4622
				sys.stdout.flush()
4996
				sys.stdout.flush()
4997
			if "--nodeps" in myopts:
4998
				spinner.update = spinner.update_quiet
4623
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4999
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4624
			try:
5000
			try:
4625
				retval, favorites = mydepgraph.select_files(myfiles)
5001
				retval, favorites = mydepgraph.select_files(myfiles)
Lines 4628-4634 Link Here
4628
				sys.exit(1)
5004
				sys.exit(1)
4629
			if not retval:
5005
			if not retval:
4630
				sys.exit(1)
5006
				sys.exit(1)
4631
			if not ("--quiet" in myopts):
5007
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4632
				print "\b\b... done!"
5008
				print "\b\b... done!"
4633
5009
4634
			if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
5010
			if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
Lines 4649-4661 Link Here
4649
			if len(mymergelist) == 0:
5025
			if len(mymergelist) == 0:
4650
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5026
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4651
				sys.exit(0)
5027
				sys.exit(0)
5028
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4652
			mydepgraph.display(mymergelist)
5029
			mydepgraph.display(mymergelist)
4653
			prompt="Would you like to resume merging these packages?"
5030
			prompt="Would you like to resume merging these packages?"
4654
		else:
5031
		else:
4655
			mydepgraph.display(
5032
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
4656
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5033
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5034
			mydepgraph.display(mymergelist)
4657
			mergecount=0
5035
			mergecount=0
4658
			for x in mydepgraph.altlist():
5036
			for x in mymergelist:
4659
				if x[0] != "blocks" and x[3] != "nomerge":
5037
				if x[0] != "blocks" and x[3] != "nomerge":
4660
					mergecount+=1
5038
					mergecount+=1
4661
				#check for blocking dependencies
5039
				#check for blocking dependencies
Lines 4700-4709 Link Here
4700
			if len(mymergelist) == 0:
5078
			if len(mymergelist) == 0:
4701
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5079
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4702
				sys.exit(0)
5080
				sys.exit(0)
5081
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4703
			mydepgraph.display(mymergelist)
5082
			mydepgraph.display(mymergelist)
4704
		else:
5083
		else:
4705
			mydepgraph.display(
5084
			# mydepgraph.digraph.debug_print()
4706
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5085
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5086
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5087
			mydepgraph.display(mymergelist)
4707
	else:
5088
	else:
4708
		if ("--buildpkgonly" in myopts):
5089
		if ("--buildpkgonly" in myopts):
4709
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5090
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
Lines 4718-4741 Link Here
4718
				""" parallel-fetch uses --resume --fetchonly and we don't want
5099
				""" parallel-fetch uses --resume --fetchonly and we don't want
4719
				it to write the mtimedb"""
5100
				it to write the mtimedb"""
4720
				mtimedb.filename = None
5101
				mtimedb.filename = None
4721
				time.sleep(3) # allow the parent to have first fetch
5102
				time.sleep(10) # allow the parent to have first fetch
5103
			mymergelist = mtimedb["resume"]["mergelist"]
5104
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, "parallel" in settings.features)
4722
			del mydepgraph
5105
			del mydepgraph
4723
			retval = mergetask.merge(
5106
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
4724
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
4725
			if retval != os.EX_OK:
5107
			if retval != os.EX_OK:
4726
				sys.exit(retval)
5108
				sys.exit(retval)
4727
		else:
5109
		else:
4728
			if "resume" in mtimedb and \
5110
			mymergelist = mydepgraph.altlist()
4729
			"mergelist" in mtimedb["resume"] and \
5111
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, "parallel" in settings.features)
4730
			len(mtimedb["resume"]["mergelist"]) > 1:
5112
			if "--nodeps" not in myopts or len(mymergelist) > 1:
4731
				mtimedb["resume_backup"] = mtimedb["resume"]
5113
				if "resume" in mtimedb and \
4732
				del mtimedb["resume"]
5114
				"mergelist" in mtimedb["resume"] and \
4733
				mtimedb.commit()
5115
				len(mtimedb["resume"]["mergelist"]) > 1:
4734
			mtimedb["resume"]={}
5116
					mtimedb["resume_backup"] = mtimedb["resume"]
4735
			# XXX: Stored as a list for backward compatibility.
5117
					del mtimedb["resume"]
4736
			mtimedb["resume"]["myopts"] = \
5118
					mtimedb.commit()
4737
				[k for k in myopts if myopts[k] is True]
5119
				mtimedb["resume"]={}
4738
			mtimedb["resume"]["favorites"]=favorites
5120
				# XXX: Stored as a list for backward compatibility.
5121
				mtimedb["resume"]["myopts"] = \
5122
					[k for k in myopts if myopts[k] is True]
5123
				mtimedb["resume"]["favorites"]=favorites
4739
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5124
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4740
				for pkgline in mydepgraph.altlist():
5125
				for pkgline in mydepgraph.altlist():
4741
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5126
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 4751-4768 Link Here
4751
							tree="porttree")
5136
							tree="porttree")
4752
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5137
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4753
				pkglist = []
5138
				pkglist = []
4754
				for pkg in mydepgraph.altlist():
5139
				for pkg in mymergelist:
4755
					if pkg[0] != "blocks":
5140
					if pkg[0] != "blocks":
4756
						pkglist.append(pkg)
5141
						pkglist.append(pkg)
4757
			else:
5142
			else:
4758
				pkglist = mydepgraph.altlist()
5143
				pkglist = mymergelist
4759
			del mydepgraph
5144
			del mydepgraph
4760
			mergetask = MergeTask(settings, trees, myopts)
5145
			mergetask = MergeTask(settings, trees, myopts)
4761
			retval = mergetask.merge(pkglist, favorites, mtimedb)
5146
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
4762
			if retval != os.EX_OK:
5147
			if retval != os.EX_OK:
4763
				sys.exit(retval)
5148
				sys.exit(retval)
4764
5149
4765
		if mtimedb.has_key("resume"):
5150
		if mtimedb.has_key("resume") and ("--nodeps" not in myopts or len(mymergelist) > 1):
4766
			del mtimedb["resume"]
5151
			del mtimedb["resume"]
4767
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5152
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4768
			print ">>> Auto-cleaning packages..."
5153
			print ">>> Auto-cleaning packages..."
(-)portage-2.1.2.orig/pym/portage.py (-10 / +27 lines)
Lines 64-70 Link Here
64
	from output import bold, colorize, green, red, yellow
64
	from output import bold, colorize, green, red, yellow
65
65
66
	import portage_const
66
	import portage_const
67
	from portage_const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \
67
	from portage_const import VDB_PATH, PRIVATE_PATH, DEF_LOGDIR, CACHE_PATH, DEPCACHE_PATH, \
68
	  USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
68
	  USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
69
	  PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
69
	  PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
70
	  EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
70
	  EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
Lines 2173-2191 Link Here
2173
	mypids = []
2173
	mypids = []
2174
	pw = None
2174
	pw = None
2175
	if logfile:
2175
	if logfile:
2176
		del keywords["logfile"]
2176
		tee_good = 1
2177
		fd_pipes = keywords.get("fd_pipes")
2177
		fd_pipes = keywords.get("fd_pipes")
2178
		if fd_pipes is None:
2178
		if fd_pipes is None:
2179
			fd_pipes = {0:0, 1:1, 2:2}
2179
			fd_pipes = {0:0, 1:1, 2:2}
2180
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2180
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2181
			raise ValueError(fd_pipes)
2181
			raise ValueError(fd_pipes)
2182
		pr, pw = os.pipe()
2182
		try:
2183
		mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2183
			statinfo1 = os.stat(logfile)
2184
			 returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2184
			statinfo2 = os.fstat(fd_pipes[1])
2185
		os.close(pr)
2185
			statinfo3 = os.fstat(fd_pipes[2])
2186
		fd_pipes[1] = pw
2186
			# if they are pointing to same file as logfile, no 'tee' is required.
2187
		fd_pipes[2] = pw
2187
			if statinfo1 == statinfo2 and statinfo2 == statinfo3:
2188
		keywords["fd_pipes"] = fd_pipes
2188
				tee_good = 0
2189
		except:
2190
			tee_good = 1
2191
2192
		if tee_good:
2193
2194
			del keywords["logfile"]
2195
			pr, pw = os.pipe()
2196
			mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2197
			 	returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2198
			os.close(pr)
2199
			fd_pipes[1] = pw
2200
			fd_pipes[2] = pw
2201
			keywords["fd_pipes"] = fd_pipes
2189
2202
2190
	features = mysettings.features
2203
	features = mysettings.features
2191
	# XXX: Negative RESTRICT word
2204
	# XXX: Negative RESTRICT word
Lines 3198-3203 Link Here
3198
	if mysettings.get("PORT_LOGDIR", "") == "":
3211
	if mysettings.get("PORT_LOGDIR", "") == "":
3199
		while "PORT_LOGDIR" in mysettings:
3212
		while "PORT_LOGDIR" in mysettings:
3200
			del mysettings["PORT_LOGDIR"]
3213
			del mysettings["PORT_LOGDIR"]
3214
3215
	if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
3216
		mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + portage.DEF_LOGDIR
3217
3201
	if "PORT_LOGDIR" in mysettings:
3218
	if "PORT_LOGDIR" in mysettings:
3202
		try:
3219
		try:
3203
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
3220
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
Lines 3210-3216 Link Here
3210
			while "PORT_LOGDIR" in mysettings:
3227
			while "PORT_LOGDIR" in mysettings:
3211
				del mysettings["PORT_LOGDIR"]
3228
				del mysettings["PORT_LOGDIR"]
3212
	if "PORT_LOGDIR" in mysettings:
3229
	if "PORT_LOGDIR" in mysettings:
3213
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
3230
		logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
3214
		if not os.path.exists(logid_path):
3231
		if not os.path.exists(logid_path):
3215
			f = open(logid_path, "w")
3232
			f = open(logid_path, "w")
3216
			f.close()
3233
			f.close()
(-)portage-2.1.2.orig/pym/portage_const.py (+1 lines)
Lines 12-17 Link Here
12
12
13
VDB_PATH                = "var/db/pkg"
13
VDB_PATH                = "var/db/pkg"
14
PRIVATE_PATH            = "var/lib/portage"
14
PRIVATE_PATH            = "var/lib/portage"
15
DEF_LOGDIR              = "var/log/portage"
15
CACHE_PATH              = "/var/cache/edb"
16
CACHE_PATH              = "/var/cache/edb"
16
DEPCACHE_PATH           = CACHE_PATH+"/dep"
17
DEPCACHE_PATH           = CACHE_PATH+"/dep"
17
18
(-)portage-2.1.2.orig/pym/portage_exec.py (-16 / +32 lines)
Lines 19-24 Link Here
19
19
20
if os.path.isdir("/proc/%i/fd" % os.getpid()):
20
if os.path.isdir("/proc/%i/fd" % os.getpid()):
21
	def get_open_fds():
21
	def get_open_fds():
22
		# there is a race here - fd used by listdir may be in the list but closed
23
		# before this method returns.
22
		return map(int, [fd for fd in os.listdir("/proc/%i/fd" % os.getpid()) if fd.isdigit()])
24
		return map(int, [fd for fd in os.listdir("/proc/%i/fd" % os.getpid()) if fd.isdigit()])
23
else:
25
else:
24
	def get_open_fds():
26
	def get_open_fds():
Lines 167-193 Link Here
167
	# mypids will hold the pids of all processes created.
169
	# mypids will hold the pids of all processes created.
168
	mypids = []
170
	mypids = []
169
171
172
	pw = None
170
	if logfile:
173
	if logfile:
171
		# Using a log file requires that stdout and stderr
174
		# Using a log file requires that stdout and stderr
172
		# are assigned to the process we're running.
175
		# are assigned to the process we're running.
173
		if 1 not in fd_pipes or 2 not in fd_pipes:
176
		if 1 not in fd_pipes or 2 not in fd_pipes:
174
			raise ValueError(fd_pipes)
177
			raise ValueError(fd_pipes)
175
178
176
		# Create a pipe
179
		tee_good = 1
177
		(pr, pw) = os.pipe()
180
		try:
178
181
			statinfo1 = os.stat(logfile)
179
		# Create a tee process, giving it our stdout and stderr
182
			statinfo2 = os.fstat(fd_pipes[1])
180
		# as well as the read end of the pipe.
183
			statinfo3 = os.fstat(fd_pipes[2])
181
		mypids.extend(spawn(('tee', '-i', '-a', logfile),
184
			# if they are pointing to same file as logfile, no 'tee' is required.
182
		              returnpid=True, fd_pipes={0:pr,
185
			if statinfo1 == statinfo2 and statinfo2 == statinfo3:
183
		              1:fd_pipes[1], 2:fd_pipes[2]}))
186
				tee_good = 0
184
187
		except:
185
		# We don't need the read end of the pipe, so close it.
188
			tee_good = 1
186
		os.close(pr)
189
187
190
		if tee_good:
188
		# Assign the write end of the pipe to our stdout and stderr.
191
189
		fd_pipes[1] = pw
192
			# Create a pipe
190
		fd_pipes[2] = pw
193
			(pr, pw) = os.pipe()
194
195
			# Create a tee process, giving it our stdout and stderr
196
			# as well as the read end of the pipe.
197
			mypids.extend(spawn(('tee', '-i', '-a', logfile),
198
					returnpid=True, fd_pipes={0:pr,
199
					1:fd_pipes[1], 2:fd_pipes[2]}))
200
201
			# We don't need the read end of the pipe, so close it.
202
			os.close(pr)
203
204
			# Assign the write end of the pipe to our stdout and stderr.
205
			fd_pipes[1] = pw
206
			fd_pipes[2] = pw
191
207
192
	pid = os.fork()
208
	pid = os.fork()
193
209
Lines 209-215 Link Here
209
225
210
	# If we started a tee process the write side of the pipe is no
226
	# If we started a tee process the write side of the pipe is no
211
	# longer needed, so close it.
227
	# longer needed, so close it.
212
	if logfile:
228
	if logfile and pw:
213
		os.close(pw)
229
		os.close(pw)
214
230
215
	# If the caller wants to handle cleaning up the processes, we tell
231
	# If the caller wants to handle cleaning up the processes, we tell

Return to bug 147516