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 (-333 / +708 lines)
Lines 2005-2010 Link Here
2005
		ignore_priority_range.extend(
2005
		ignore_priority_range.extend(
2006
			xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2006
			xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2007
		tree_mode = "--tree" in self.myopts
2007
		tree_mode = "--tree" in self.myopts
2008
		slotcount = 0
2008
		while not mygraph.empty():
2009
		while not mygraph.empty():
2009
			ignore_priority = None
2010
			ignore_priority = None
2010
			nodes = None
2011
			nodes = None
Lines 2014-2024 Link Here
2014
					if not mygraph.contains(node):
2015
					if not mygraph.contains(node):
2015
						asap_nodes.remove(node)
2016
						asap_nodes.remove(node)
2016
						continue
2017
						continue
2017
					if not mygraph.child_nodes(node,
2018
					if not mygraph.child_nodes(node, ignore_priority=DepPriority.SOFT):
2018
						ignore_priority=DepPriority.SOFT):
2019
						nodes = [node]
2019
						nodes = [node]
2020
						asap_nodes.remove(node)
2020
						asap_nodes.remove(node)
2021
						break
2021
						break
2022
			# if no asap node, then get the first non-null set of leaf (root if --tree) nodes in the priority range
2022
			if not nodes:
2023
			if not nodes:
2023
				for ignore_priority in ignore_priority_range:
2024
				for ignore_priority in ignore_priority_range:
2024
					nodes = get_nodes(ignore_priority=ignore_priority)
2025
					nodes = get_nodes(ignore_priority=ignore_priority)
Lines 2055-2071 Link Here
2055
						if node not in mergeable_nodes:
2056
						if node not in mergeable_nodes:
2056
							return False
2057
							return False
2057
						selected_nodes.add(node)
2058
						selected_nodes.add(node)
2058
						for child in mygraph.child_nodes(node,
2059
						for child in mygraph.child_nodes(node, ignore_priority=DepPriority.SOFT):
2059
							ignore_priority=DepPriority.SOFT):
2060
							if not gather_deps(mergeable_nodes, selected_nodes, child):
2060
							if not gather_deps(
2061
								mergeable_nodes, selected_nodes, child):
2062
								return False
2061
								return False
2063
						return True
2062
						return True
2064
					mergeable_nodes = set(nodes)
2063
					mergeable_nodes = set(nodes)
2065
					for node in nodes:
2064
					for node in nodes:
2066
						selected_nodes = set()
2065
						selected_nodes = set()
2067
						if gather_deps(
2066
						if gather_deps(mergeable_nodes, selected_nodes, node):
2068
							mergeable_nodes, selected_nodes, node):
2069
							break
2067
							break
2070
						else:
2068
						else:
2071
							selected_nodes = None
2069
							selected_nodes = None
Lines 2122-2128 Link Here
2122
				sys.exit(1)
2120
				sys.exit(1)
2123
2121
2124
			for node in selected_nodes:
2122
			for node in selected_nodes:
2125
				retlist.append(list(node))
2123
				node2 = list(node)
2124
				if len(node2) == 4:
2125
					node2.append(str(slotcount))
2126
				retlist.append(node2)
2126
				mygraph.remove(node)
2127
				mygraph.remove(node)
2127
				if not reversed and not circular_blocks and myblockers.contains(node):
2128
				if not reversed and not circular_blocks and myblockers.contains(node):
2128
					"""This node may have invalidated one or more blockers."""
2129
					"""This node may have invalidated one or more blockers."""
Lines 2131-2136 Link Here
2131
						if not myblockers.child_nodes(blocker):
2132
						if not myblockers.child_nodes(blocker):
2132
							myblockers.remove(blocker)
2133
							myblockers.remove(blocker)
2133
							del self.blocker_parents[blocker]
2134
							del self.blocker_parents[blocker]
2135
			slotcount += 1
2134
2136
2135
		if not reversed:
2137
		if not reversed:
2136
			"""Blocker validation does not work with reverse mode,
2138
			"""Blocker validation does not work with reverse mode,
Lines 2333-2339 Link Here
2333
		for x in mylist:
2335
		for x in mylist:
2334
			if "blocks" == x[0]:
2336
			if "blocks" == x[0]:
2335
				continue
2337
				continue
2336
			graph_key = tuple(x)
2338
			graph_key = tuple(x[:-1])
2337
			if "--tree" in self.myopts:
2339
			if "--tree" in self.myopts:
2338
				depth = len(tree_nodes)
2340
				depth = len(tree_nodes)
2339
				while depth and graph_key not in \
2341
				while depth and graph_key not in \
Lines 2347-2359 Link Here
2347
		for i in xrange(len(mylist)-1,-1,-1):
2349
		for i in xrange(len(mylist)-1,-1,-1):
2348
			if "blocks" == mylist[i][0]:
2350
			if "blocks" == mylist[i][0]:
2349
				continue
2351
				continue
2350
			graph_key = tuple(mylist[i])
2352
			graph_key = tuple(mylist[i][:-1])
2351
			if mylist[i][-1] != "nomerge":
2353
			if mylist[i][-2] != "nomerge":
2352
				last_merge_depth = node_depth[graph_key]
2354
				last_merge_depth = node_depth[graph_key]
2353
				continue
2355
				continue
2354
			if node_depth[graph_key] >= last_merge_depth or \
2356
			if node_depth[graph_key] >= last_merge_depth or \
2355
				i < len(mylist) - 1 and \
2357
				i < len(mylist) - 1 and \
2356
				node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
2358
				node_depth[graph_key] >= node_depth[tuple(mylist[i+1][:-1])]:
2357
					del mylist[i]
2359
					del mylist[i]
2358
					del node_depth[graph_key]
2360
					del node_depth[graph_key]
2359
		del tree_nodes
2361
		del tree_nodes
Lines 2549-2555 Link Here
2549
				if verbosity == 3:
2551
				if verbosity == 3:
2550
					# size verbose
2552
					# size verbose
2551
					mysize=0
2553
					mysize=0
2552
					if x[0] == "ebuild" and x[-1]!="nomerge":
2554
					if x[0] == "ebuild" and x[-2]!="nomerge":
2553
						try:
2555
						try:
2554
							myfilesdict = portdb.getfetchsizes(pkg_key,
2556
							myfilesdict = portdb.getfetchsizes(pkg_key,
2555
								useflags=self.useFlags[myroot][pkg_key],
2557
								useflags=self.useFlags[myroot][pkg_key],
Lines 2601-2607 Link Here
2601
				oldlp=mywidth-30
2603
				oldlp=mywidth-30
2602
				newlp=oldlp-30
2604
				newlp=oldlp-30
2603
2605
2604
				indent = " " * node_depth[tuple(x)]
2606
				indent = " " * node_depth[tuple(x[:-1])]
2605
2607
2606
				if myoldbest:
2608
				if myoldbest:
2607
					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2609
					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
Lines 2833-2843 Link Here
2833
			self.pkgsettings["/"] = \
2835
			self.pkgsettings["/"] = \
2834
				portage.config(clone=trees["/"]["vartree"].settings)
2836
				portage.config(clone=trees["/"]["vartree"].settings)
2835
2837
2836
	def merge(self, mylist, favorites, mtimedb):
2838
	def restart_portage(self, x, mergecount, totalcount, mtimedb):
2839
		xterm_titles = "notitles" not in self.settings.features
2840
		# don't really restart if any of these is true
2841
		# XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
2842
		if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
2843
			"--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
2844
			return
2845
2846
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2847
			"--resume"])
2848
		mysplit=portage.pkgsplit(x[2])
2849
		myver=mysplit[1]+"-"+mysplit[2]
2850
		if myver[-3:]=='-r0':
2851
			myver=myver[:-3]
2852
		if (myver != portage.VERSION) and \
2853
		   "livecvsportage" not in self.settings.features:
2854
			if totalcount > mergecount:
2855
				emergelog(xterm_titles,
2856
					" ::: completed emerge ("+ \
2857
					str(mergecount)+" of "+ \
2858
					str(totalcount)+") "+ \
2859
					x[2]+" to "+x[1])
2860
				emergelog(xterm_titles, " *** RESTARTING " + \
2861
					"emerge via exec() after change of " + \
2862
					"portage version.")
2863
				portage.run_exitfuncs()
2864
				mynewargv=[sys.argv[0],"--resume"]
2865
				for myopt, myarg in self.myopts.iteritems():
2866
					if myopt not in bad_resume_opts:
2867
						if myarg is True:
2868
							mynewargv.append(myopt)
2869
						else:
2870
							mynewargv.append(myopt +"="+ myarg)
2871
				# priority only needs to be adjusted on the first run
2872
				os.environ["PORTAGE_NICENESS"] = "0"
2873
				os.execv(mynewargv[0], mynewargv)
2874
2875
	def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
2876
		xterm_titles = "notitles" not in self.settings.features
2877
		myfeat = self.settings.features[:]
2878
		ldpath_mtimes = mtimedb["ldpath"]
2879
		myroot=x[1]
2880
		pkg_key = x[2]
2881
		pkg_cat = x[2].split("/")[0]
2882
		pkg_pf = x[2].split("/")[1]
2883
		pkgindex=2
2884
		if x[0]=="blocks":
2885
			pkgindex=3
2886
2887
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
2888
		logid_path = None
2889
		null_log = 0
2890
2891
		if self.settings.get("PORT_LOGDIR", "") == "":
2892
			while "PORT_LOGDIR" in self.settings:
2893
				del self.settings["PORT_LOGDIR"]
2894
		if "PORT_LOGDIR" in self.settings:
2895
			port_logdir = self.settings["PORT_LOGDIR"]
2896
		else:
2897
			port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
2898
2899
		try:
2900
			portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
2901
						 gid=portage.portage_gid, mode=02770)
2902
		except portage_exception.PortageException, e:
2903
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
2904
			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
2905
				self.settings["PORT_LOGDIR"], noiselevel=-1)
2906
			writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
2907
			null_log = 1
2908
2909
		if not null_log:
2910
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
2911
			if not os.path.exists(logid_path):
2912
				f = open(logid_path, "w")
2913
				f.close()
2914
				del f
2915
			logid_time = time.strftime("%Y%m%d-%H%M%S",
2916
				time.gmtime(os.stat(logid_path).st_mtime))
2917
			logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
2918
				(pkg_cat, pkg_pf, logid_time))
2919
			del logid_time
2920
		else:
2921
			logfile = "/dev/null"
2922
2923
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
2924
			print ">>> Emerging (" + \
2925
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2926
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
2927
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
2928
			print ">>> Logfile in " + logfile
2929
			emergelog(xterm_titles, " >>> emerge ("+\
2930
				str(mergecount)+" of "+str(totalcount)+\
2931
				") "+x[pkgindex]+" to "+x[1])
2932
2933
		# need to spawn a --nodeps emerge in a separate process.
2934
		pkg="="+x[2]
2935
		merge_env = os.environ.copy()
2936
		merge_env["PORTAGE_INTERNAL_CALL"] = "1"
2937
		merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
2938
		merge_args = [sys.argv[0], "--nodeps", "--oneshot", pkg]
2939
		good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
2940
					"--usepkg", "--usepkgonly"])
2941
		fd_pipes = None
2942
		merge_logfd = None
2943
		for myopt, myarg in self.myopts.iteritems():
2944
			# don't clobber the logfile at the same time as parallel fetch is
2945
			# all log of parallel fetch will go /var/log/emerge-fetch.log
2946
			# so, just leave 0,1,2 alone.
2947
			if "parallel-fetch" in myfeat and myopt == "--fetchonly":
2948
				fd_pipes = {0:0, 1:1, 2:2}
2949
			if myopt in good_nodeps_opts:
2950
				if myarg is True:
2951
					merge_args.append(myopt)
2952
				else:
2953
					merge_args.append(myopt +"="+ myarg)
2954
		if not fd_pipes:
2955
			merge_logfd = open(logfile, "w")
2956
			# put in a start message. This also makes sure that this fd is pointing to a good file on disk
2957
			# and hence will be used throughout the other spawns that will happen in the children.
2958
			merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
2959
			merge_logfd.flush()
2960
			fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
2961
			portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
2962
2963
		mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
2964
		if merge_logfd:
2965
			merge_logfd.close() # child has exclusive rights to it now.
2966
		return mypids[0]
2967
2968
	def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
2969
		xterm_titles = "notitles" not in self.settings.features
2970
		myfeat = self.settings.features[:]
2971
		ldpath_mtimes = mtimedb["ldpath"]
2972
		myroot=x[1]
2973
		pkg_key = x[2]
2974
		pkg_cat = x[2].split("/")[0]
2975
		pkg_pf = x[2].split("/")[1]
2976
		pkgindex=2
2977
		if x[0]=="blocks":
2978
			pkgindex=3
2979
2980
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
2981
			print "\n>>> Emerging (" + \
2982
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2983
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
2984
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
2985
			emergelog(xterm_titles, " >>> emerge ("+\
2986
				str(mergecount)+" of "+str(totalcount)+\
2987
				") "+x[pkgindex]+" to "+x[1])
2988
2989
		portdb = self.trees[myroot]["porttree"].dbapi
2990
		bindb  = self.trees[myroot]["bintree"].dbapi
2991
		vartree = self.trees[myroot]["vartree"]
2992
		pkgsettings = self.pkgsettings[myroot]
2993
		y = portdb.findname(pkg_key)
2994
		pkgsettings["EMERGE_FROM"] = x[0]
2995
		pkgsettings.backup_changes("EMERGE_FROM")
2996
		pkgsettings.reset()
2997
2998
		#buildsyspkg: Check if we need to _force_ binary package creation
2999
		issyspkg = ("buildsyspkg" in myfeat) \
3000
				and x[0] != "blocks" \
3001
				and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3002
				and "--buildpkg" not in self.myopts
3003
		if x[0] in ["ebuild","blocks"]:
3004
			if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3005
				raise Exception, "Merging a blocker"
3006
			elif "--fetchonly" in self.myopts or \
3007
				"--fetch-all-uri" in self.myopts:
3008
				if "--fetch-all-uri" in self.myopts:
3009
					retval = portage.doebuild(y, "fetch", myroot,
3010
						pkgsettings, self.edebug,
3011
						"--pretend" in self.myopts, fetchonly=1,
3012
						fetchall=1, mydbapi=portdb, tree="porttree")
3013
				else:
3014
					retval = portage.doebuild(y, "fetch", myroot,
3015
						pkgsettings, self.edebug,
3016
						"--pretend" in self.myopts, fetchonly=1,
3017
						mydbapi=portdb, tree="porttree")
3018
				if (retval is None) or retval:
3019
					print
3020
					print "!!! Fetch for",y,"failed, continuing..."
3021
					print
3022
3023
				return retval
3024
3025
			portage.doebuild_environment(y, "setup", myroot,
3026
				pkgsettings, self.edebug, 1, portdb)
3027
			catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3028
			portage_util.ensure_dirs(os.path.dirname(catdir),
3029
				uid=portage.portage_uid, gid=portage.portage_gid,
3030
				mode=070, mask=0)
3031
			builddir_lock = None
3032
			catdir_lock = None
3033
			try:
3034
				catdir_lock = portage_locks.lockdir(catdir)
3035
				portage_util.ensure_dirs(catdir,
3036
					uid=portage.portage_uid, gid=portage.portage_gid,
3037
					mode=070, mask=0)
3038
				builddir_lock = portage_locks.lockdir(
3039
					pkgsettings["PORTAGE_BUILDDIR"])
3040
				try:
3041
					portage_locks.unlockdir(catdir_lock)
3042
				finally:
3043
					catdir_lock = None
3044
				msg = " === (%s of %s) Cleaning (%s::%s)" % \
3045
					(mergecount, totalcount, pkg_key, y)
3046
				short_msg = "emerge: (%s of %s) %s Clean" % \
3047
					(mergecount, totalcount, pkg_key)
3048
				emergelog(xterm_titles, msg, short_msg=short_msg)
3049
				retval = portage.doebuild(y, "clean", myroot,
3050
					pkgsettings, self.edebug, cleanup=1,
3051
					mydbapi=portdb, tree="porttree")
3052
3053
				if retval != os.EX_OK:
3054
					return retval
3055
				if "--buildpkg" in self.myopts or issyspkg:
3056
					if issyspkg:
3057
						print ">>> This is a system package, " + \
3058
							"let's pack a rescue tarball."
3059
					msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3060
						(mergecount, totalcount, pkg_key, y)
3061
					short_msg = "emerge: (%s of %s) %s Compile" % \
3062
						(mergecount, totalcount, pkg_key)
3063
					emergelog(xterm_titles, msg, short_msg=short_msg)
3064
					self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3065
					retval = portage.doebuild(y, "package", myroot,
3066
						pkgsettings, self.edebug, mydbapi=portdb,
3067
						tree="porttree")
3068
					if retval != os.EX_OK:
3069
						return retval
3070
					if "--buildpkgonly" not in self.myopts:
3071
						bintree = self.trees[myroot]["bintree"]
3072
						bintree.inject(pkg_key)
3073
						mytbz2 = bintree.getname(pkg_key)
3074
						msg = " === (%s of %s) Merging (%s::%s)" % \
3075
							(mergecount, totalcount, pkg_key, y)
3076
						short_msg = "emerge: (%s of %s) %s Merge" % \
3077
							(mergecount, totalcount, pkg_key)
3078
						emergelog(xterm_titles, msg, short_msg=short_msg)
3079
						retval = portage.merge(pkgsettings["CATEGORY"],
3080
							pkgsettings["PF"], pkgsettings["D"],
3081
							os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3082
							"build-info"), myroot, pkgsettings,
3083
							myebuild=pkgsettings["EBUILD"],
3084
							mytree="porttree", mydbapi=portdb,
3085
							vartree=vartree, prev_mtimes=ldpath_mtimes)
3086
						if retval != os.EX_OK:
3087
							return retval
3088
					elif "noclean" not in pkgsettings.features:
3089
						portage.doebuild(y, "clean", myroot,
3090
							pkgsettings, self.edebug, mydbapi=portdb,
3091
							tree="porttree")
3092
				else:
3093
					msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3094
						(mergecount, totalcount, pkg_key, y)
3095
					short_msg = "emerge: (%s of %s) %s Compile" % \
3096
						(mergecount, totalcount, pkg_key)
3097
					emergelog(xterm_titles, msg, short_msg=short_msg)
3098
					retval = portage.doebuild(y, "merge", myroot,
3099
						pkgsettings, self.edebug, vartree=vartree,
3100
						mydbapi=portdb, tree="porttree",
3101
						prev_mtimes=ldpath_mtimes)
3102
					if retval != os.EX_OK:
3103
						return retval
3104
			finally:
3105
				if builddir_lock:
3106
					portage_locks.unlockdir(builddir_lock)
3107
				try:
3108
					if not catdir_lock:
3109
						# Lock catdir for removal if empty.
3110
						catdir_lock = portage_locks.lockdir(catdir)
3111
				finally:
3112
					if catdir_lock:
3113
						try:
3114
							os.rmdir(catdir)
3115
						except OSError, e:
3116
							if e.errno not in (errno.ENOENT,
3117
								errno.ENOTEMPTY, errno.EEXIST):
3118
								raise
3119
							del e
3120
						portage_locks.unlockdir(catdir_lock)
3121
3122
		elif x[0]=="binary":
3123
			#merge the tbz2
3124
			mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3125
			if "--getbinpkg" in self.myopts:
3126
				tbz2_lock = None
3127
				try:
3128
					if "distlocks" in pkgsettings.features and \
3129
						os.access(pkgsettings["PKGDIR"], os.W_OK):
3130
						portage_util.ensure_dirs(os.path.dirname(mytbz2))
3131
						tbz2_lock = portage_locks.lockfile(mytbz2,
3132
							wantnewlockfile=1)
3133
					if self.trees[myroot]["bintree"].isremote(pkg_key):
3134
						msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3135
							(mergecount, totalcount, pkg_key, mytbz2)
3136
						short_msg = "emerge: (%s of %s) %s Fetch" % \
3137
							(mergecount, totalcount, pkg_key)
3138
						emergelog(xterm_titles, msg, short_msg=short_msg)
3139
						if not self.trees[myroot]["bintree"].gettbz2(
3140
							pkg_key):
3141
							return 1
3142
				finally:
3143
					if tbz2_lock:
3144
						portage_locks.unlockfile(tbz2_lock)
3145
3146
			if "--fetchonly" in self.myopts or \
3147
				"--fetch-all-uri" in self.myopts:
3148
				return os.EX_OK
3149
3150
			short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
3151
			emergelog(xterm_titles, " === ("+str(mergecount)+\
3152
				" of "+str(totalcount)+") Merging Binary ("+\
3153
				x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3154
3155
			retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3156
				mydbapi=bindb,
3157
				vartree=self.trees[myroot]["vartree"],
3158
				prev_mtimes=ldpath_mtimes)
3159
			if retval != os.EX_OK:
3160
				return retval
3161
			#need to check for errors
3162
		if "--buildpkgonly" not in self.myopts:
3163
			self.trees[x[1]]["vartree"].inject(x[2])
3164
			myfavkey=portage.cpv_getkey(x[2])
3165
			if "--fetchonly" not in self.myopts and \
3166
				"--fetch-all-uri" not in self.myopts and \
3167
				myfavkey in favorites:
3168
				myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3169
				myfavdict=genericdict(myfavs)
3170
				#don't record if already in system profile or already recorded
3171
				if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3172
					#we don't have a favorites entry for this package yet; add one
3173
					myfavdict[myfavkey]=myfavkey
3174
					print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3175
					emergelog(xterm_titles, " === ("+\
3176
						str(mergecount)+" of "+\
3177
						str(totalcount)+\
3178
						") Updating world file ("+x[pkgindex]+")")
3179
					portage.write_atomic(
3180
					os.path.join(myroot, portage.WORLD_FILE),
3181
					"\n".join(myfavdict.values()))
3182
3183
			if "--pretend" not in self.myopts and \
3184
				"--fetchonly" not in self.myopts and \
3185
				"--fetch-all-uri" not in self.myopts:
3186
				# Clean the old package that we have merged over top of it.
3187
				if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3188
					xsplit=portage.pkgsplit(x[2])
3189
					emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3190
					retval = unmerge(pkgsettings, self.myopts, vartree,
3191
						"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3192
					if not retval:
3193
						emergelog(xterm_titles,
3194
							" --- AUTOCLEAN: Nothing unmerged.")
3195
				else:
3196
					portage.writemsg_stdout(colorize("WARN", "WARNING:")
3197
						+ " AUTOCLEAN is disabled.  This can cause serious"
3198
						+ " problems due to overlapping packages.\n")
3199
3200
3201
		if "--pretend" not in self.myopts and \
3202
			"--fetchonly" not in self.myopts and \
3203
			"--fetch-all-uri" not in self.myopts:
3204
			if "noclean" not in self.settings.features:
3205
				short_msg = "emerge: (%s of %s) %s Clean Post" % \
3206
					(mergecount, totalcount, x[pkgindex])
3207
				emergelog(xterm_titles, (" === (%s of %s) " + \
3208
					"Post-Build Cleaning (%s::%s)") % \
3209
					(mergecount, totalcount, x[pkgindex], y),
3210
					short_msg=short_msg)
3211
			emergelog(xterm_titles, " ::: completed emerge ("+\
3212
				str(mergecount)+" of "+str(totalcount)+") "+\
3213
				x[2]+" to "+x[1])
3214
3215
		return os.EX_OK
3216
3217
	def print_status(self, totalcount, donec, qsize, failedc):
3218
		print ">>> Jobs Total = "+colorize("WARN", str(totalcount))+" Done = "+\
3219
			colorize("GOOD", str(donec))+" Running = "+colorize("BAD", str(qsize))+\
3220
			" Failed = "+colorize("BAD", str(failedc))
3221
		xtermTitle("Jobs Total = "+str(totalcount)+" Done = "+\
3222
			str(donec)+" Running = "+str(qsize)+" Failed = "+str(failedc))
3223
3224
	def merge(self, mylist, favorites, mtimedb, m_slots):
2837
		failed_fetches = []
3225
		failed_fetches = []
2838
		mymergelist=[]
3226
		mymergelist=[]
2839
		ldpath_mtimes = mtimedb["ldpath"]
3227
		ldpath_mtimes = mtimedb["ldpath"]
2840
		xterm_titles = "notitles" not in self.settings.features
3228
		xterm_titles = "notitles" not in self.settings.features
3229
		parallel = "parallel" in self.settings.features
3230
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3231
3232
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3233
		if self.edebug or "--fetchonly" in self.myopts:
3234
			parallel = False
2841
3235
2842
		#check for blocking dependencies
3236
		#check for blocking dependencies
2843
		if "--fetchonly" not in self.myopts and \
3237
		if "--fetchonly" not in self.myopts and \
Lines 2860-2867 Link Here
2860
		mysysdict = genericdict(getlist(self.settings, "system"))
3254
		mysysdict = genericdict(getlist(self.settings, "system"))
2861
		if "--resume" in self.myopts:
3255
		if "--resume" in self.myopts:
2862
			# We're resuming.
3256
			# We're resuming.
2863
			print colorize("GOOD", "*** Resuming merge...")
2864
			emergelog(xterm_titles, " *** Resuming merge...")
2865
			mymergelist=mtimedb["resume"]["mergelist"][:]
3257
			mymergelist=mtimedb["resume"]["mergelist"][:]
2866
			if "--skipfirst" in self.myopts and mymergelist:
3258
			if "--skipfirst" in self.myopts and mymergelist:
2867
				del mtimedb["resume"]["mergelist"][0]
3259
				del mtimedb["resume"]["mergelist"][0]
Lines 2895-2902 Link Here
2895
					os.path.join(self.target_root, portage.WORLD_FILE),
3287
					os.path.join(self.target_root, portage.WORLD_FILE),
2896
					"\n".join(myfavdict.values()))
3288
					"\n".join(myfavdict.values()))
2897
3289
2898
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3290
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
2899
			mtimedb.commit()
3291
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3292
				mtimedb.commit()
3293
3294
		totalcount = len(mymergelist)
3295
		mergecount=1
3296
3297
		if "--resume" in self.myopts and "--fetchonly" not in self.myopts:
3298
			# We're resuming.
3299
			print colorize("GOOD", "*** Resuming merge...")
3300
			emergelog(xterm_titles, " *** Resuming merge...")
2900
3301
2901
		myfeat = self.settings.features[:]
3302
		myfeat = self.settings.features[:]
2902
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3303
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 2914-2925 Link Here
2914
				print ">>> starting parallel fetching"
3315
				print ">>> starting parallel fetching"
2915
				fetch_log = "/var/log/emerge-fetch.log"
3316
				fetch_log = "/var/log/emerge-fetch.log"
2916
				logfile = open(fetch_log, "w")
3317
				logfile = open(fetch_log, "w")
2917
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3318
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
2918
				portage_util.apply_secpass_permissions(fetch_log,
3319
				portage_util.apply_secpass_permissions(fetch_log,
2919
					uid=portage.portage_uid, gid=portage.portage_gid,
3320
					uid=portage.portage_uid, gid=portage.portage_gid,
2920
					mode=0660)
3321
					mode=0660)
2921
				fetch_env = os.environ.copy()
3322
				fetch_env = os.environ.copy()
2922
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3323
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
2923
				fetch_env["PORTAGE_NICENESS"] = "0"
3324
				fetch_env["PORTAGE_NICENESS"] = "0"
2924
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3325
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2925
				for myopt, myarg in self.myopts.iteritems():
3326
				for myopt, myarg in self.myopts.iteritems():
Lines 2932-3214 Link Here
2932
					fd_pipes=fd_pipes, returnpid=True)
3333
					fd_pipes=fd_pipes, returnpid=True)
2933
				logfile.close() # belongs to the spawned process
3334
				logfile.close() # belongs to the spawned process
2934
3335
2935
		mergecount=0
3336
		if not parallel:
2936
		for x in mymergelist:
3337
			failed_fetches = []
2937
			mergecount+=1
3338
			for x in mymergelist:
2938
			myroot=x[1]
3339
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, mysysdict)
2939
			pkg_key = x[2]
3340
				mergecount += 1
2940
			pkgindex=2
3341
2941
			portdb = self.trees[myroot]["porttree"].dbapi
3342
				# need to short circuit the spawn with --nodeps
2942
			bindb  = self.trees[myroot]["bintree"].dbapi
3343
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
2943
			vartree = self.trees[myroot]["vartree"]
3344
					if retcode != os.EX_OK:
2944
			pkgsettings = self.pkgsettings[myroot]
3345
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
2945
			if x[0]=="blocks":
3346
							failed_fetches.append(x[2])
2946
				pkgindex=3
3347
						else:
2947
			y = portdb.findname(pkg_key)
3348
							return retcode
2948
			if "--pretend" not in self.myopts:
3349
					# Unsafe for parallel merges
2949
				print "\n>>> Emerging (" + \
3350
					del mtimedb["resume"]["mergelist"][0]
2950
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3351
					# Commit after each merge so that --resume may still work in
2951
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3352
					# in the event that portage is not allowed to exit normally
2952
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
3353
					# due to power failure, SIGKILL, etc...
2953
				emergelog(xterm_titles, " >>> emerge ("+\
3354
					mtimedb.commit()
2954
					str(mergecount)+" of "+str(len(mymergelist))+\
3355
2955
					") "+x[pkgindex]+" to "+x[1])
3356
					# unlink the logid_path if any exists
3357
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
3358
					if os.path.exists(logid_path):
3359
						os.unlink(logid_path)
3360
					del logid_path
2956
3361
2957
			pkgsettings["EMERGE_FROM"] = x[0]
3362
					# check if we need to restart portage
2958
			pkgsettings.backup_changes("EMERGE_FROM")
3363
					mysplit=portage.pkgsplit(x[2])
2959
			pkgsettings.reset()
3364
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3365
							self.restart_portage(x, mergecount, totalcount, mtimedb)
2960
3366
2961
			#buildsyspkg: Check if we need to _force_ binary package creation
3367
				else:
2962
			issyspkg = ("buildsyspkg" in myfeat) \
3368
					if retcode != os.EX_OK:
2963
					and x[0] != "blocks" \
3369
						sys.exit(1)
2964
					and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2965
					and "--buildpkg" not in self.myopts
2966
			if x[0] in ["ebuild","blocks"]:
2967
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2968
					raise Exception, "Merging a blocker"
2969
				elif "--fetchonly" in self.myopts or \
2970
					"--fetch-all-uri" in self.myopts:
2971
					if "--fetch-all-uri" in self.myopts:
2972
						retval = portage.doebuild(y, "fetch", myroot,
2973
							pkgsettings, self.edebug,
2974
							"--pretend" in self.myopts, fetchonly=1,
2975
							fetchall=1, mydbapi=portdb, tree="porttree")
2976
					else:
3370
					else:
2977
						retval = portage.doebuild(y, "fetch", myroot,
3371
						sys.exit(0)
2978
							pkgsettings, self.edebug,
2979
							"--pretend" in self.myopts, fetchonly=1,
2980
							mydbapi=portdb, tree="porttree")
2981
					if (retval is None) or retval:
2982
						print
2983
						print "!!! Fetch for",y,"failed, continuing..."
2984
						print
2985
						failed_fetches.append(pkg_key)
2986
					continue
2987
3372
2988
				portage.doebuild_environment(y, "setup", myroot,
3373
			if "--pretend" not in self.myopts:
2989
					pkgsettings, self.edebug, 1, portdb)
3374
				emergelog(xterm_titles, " *** Finished. Cleaning up...")
2990
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2991
				portage_util.ensure_dirs(os.path.dirname(catdir),
2992
					uid=portage.portage_uid, gid=portage.portage_gid,
2993
					mode=070, mask=0)
2994
				builddir_lock = None
2995
				catdir_lock = None
2996
				try:
2997
					catdir_lock = portage_locks.lockdir(catdir)
2998
					portage_util.ensure_dirs(catdir,
2999
						uid=portage.portage_uid, gid=portage.portage_gid,
3000
						mode=070, mask=0)
3001
					builddir_lock = portage_locks.lockdir(
3002
						pkgsettings["PORTAGE_BUILDDIR"])
3003
					try:
3004
						portage_locks.unlockdir(catdir_lock)
3005
					finally:
3006
						catdir_lock = None
3007
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
3008
						(mergecount, len(mymergelist), pkg_key, y)
3009
					short_msg = "emerge: (%s of %s) %s Clean" % \
3010
						(mergecount, len(mymergelist), pkg_key)
3011
					emergelog(xterm_titles, msg, short_msg=short_msg)
3012
					retval = portage.doebuild(y, "clean", myroot,
3013
						pkgsettings, self.edebug, cleanup=1,
3014
						mydbapi=portdb, tree="porttree")
3015
					if retval != os.EX_OK:
3016
						return retval
3017
					if "--buildpkg" in self.myopts or issyspkg:
3018
						if issyspkg:
3019
							print ">>> This is a system package, " + \
3020
								"let's pack a rescue tarball."
3021
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3022
							(mergecount, len(mymergelist), pkg_key, y)
3023
						short_msg = "emerge: (%s of %s) %s Compile" % \
3024
							(mergecount, len(mymergelist), pkg_key)
3025
						emergelog(xterm_titles, msg, short_msg=short_msg)
3026
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3027
						retval = portage.doebuild(y, "package", myroot,
3028
							pkgsettings, self.edebug, mydbapi=portdb,
3029
							tree="porttree")
3030
						if retval != os.EX_OK:
3031
							return retval
3032
						if "--buildpkgonly" not in self.myopts:
3033
							bintree = self.trees[myroot]["bintree"]
3034
							bintree.inject(pkg_key)
3035
							mytbz2 = bintree.getname(pkg_key)
3036
							msg = " === (%s of %s) Merging (%s::%s)" % \
3037
								(mergecount, len(mymergelist), pkg_key, y)
3038
							short_msg = "emerge: (%s of %s) %s Merge" % \
3039
								(mergecount, len(mymergelist), pkg_key)
3040
							emergelog(xterm_titles, msg, short_msg=short_msg)
3041
							retval = portage.merge(pkgsettings["CATEGORY"],
3042
								pkgsettings["PF"], pkgsettings["D"],
3043
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3044
								"build-info"), myroot, pkgsettings,
3045
								myebuild=pkgsettings["EBUILD"],
3046
								mytree="porttree", mydbapi=portdb,
3047
								vartree=vartree, prev_mtimes=ldpath_mtimes)
3048
							if retval != os.EX_OK:
3049
								return retval
3050
						elif "noclean" not in pkgsettings.features:
3051
							portage.doebuild(y, "clean", myroot,
3052
								pkgsettings, self.edebug, mydbapi=portdb,
3053
								tree="porttree")
3054
					else:
3055
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3056
							(mergecount, len(mymergelist), pkg_key, y)
3057
						short_msg = "emerge: (%s of %s) %s Compile" % \
3058
							(mergecount, len(mymergelist), pkg_key)
3059
						emergelog(xterm_titles, msg, short_msg=short_msg)
3060
						retval = portage.doebuild(y, "merge", myroot,
3061
							pkgsettings, self.edebug, vartree=vartree,
3062
							mydbapi=portdb, tree="porttree",
3063
							prev_mtimes=ldpath_mtimes)
3064
						if retval != os.EX_OK:
3065
							return retval
3066
				finally:
3067
					if builddir_lock:
3068
						portage_locks.unlockdir(builddir_lock)
3069
					try:
3070
						if not catdir_lock:
3071
							# Lock catdir for removal if empty.
3072
							catdir_lock = portage_locks.lockdir(catdir)
3073
					finally:
3074
						if catdir_lock:
3075
							try:
3076
								os.rmdir(catdir)
3077
							except OSError, e:
3078
								if e.errno not in (errno.ENOENT,
3079
									errno.ENOTEMPTY, errno.EEXIST):
3080
									raise
3081
								del e
3082
							portage_locks.unlockdir(catdir_lock)
3083
3084
			elif x[0]=="binary":
3085
				#merge the tbz2
3086
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3087
				if "--getbinpkg" in self.myopts:
3088
					tbz2_lock = None
3089
					try:
3090
						if "distlocks" in pkgsettings.features and \
3091
							os.access(pkgsettings["PKGDIR"], os.W_OK):
3092
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
3093
							tbz2_lock = portage_locks.lockfile(mytbz2,
3094
								wantnewlockfile=1)
3095
						if self.trees[myroot]["bintree"].isremote(pkg_key):
3096
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3097
								(mergecount, len(mymergelist), pkg_key, mytbz2)
3098
							short_msg = "emerge: (%s of %s) %s Fetch" % \
3099
								(mergecount, len(mymergelist), pkg_key)
3100
							emergelog(xterm_titles, msg, short_msg=short_msg)
3101
							if not self.trees[myroot]["bintree"].gettbz2(
3102
								pkg_key):
3103
								return 1
3104
					finally:
3105
						if tbz2_lock:
3106
							portage_locks.unlockfile(tbz2_lock)
3107
3375
3108
				if "--fetchonly" in self.myopts or \
3376
			# We're out of the loop... We're done. Delete the resume data.
3109
					"--fetch-all-uri" in self.myopts:
3377
			if mtimedb.has_key("resume"):
3110
					continue
3378
				del mtimedb["resume"]
3379
			mtimedb.commit()
3380
			
3381
			#by doing an exit this way, --fetchonly can continue to try to
3382
			#fetch everything even if a particular download fails.
3383
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3384
				if failed_fetches:
3385
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
3386
						"encountered.  Please see above for details.\n\n")
3387
					for cpv in failed_fetches:
3388
						sys.stderr.write("   ")
3389
						sys.stderr.write(cpv)
3390
						sys.stderr.write("\n")
3391
					sys.stderr.write("\n")
3392
					sys.exit(1)
3393
				else:
3394
					sys.exit(0)
3395
			return os.EX_OK
3111
3396
3112
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3397
		# parallel code - dirty starts here...;-)
3113
				emergelog(xterm_titles, " === ("+str(mergecount)+\
3398
		one_in_slot_failed=0
3114
					" of "+str(len(mymergelist))+") Merging Binary ("+\
3399
		spawnd_pids=[]
3115
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3400
3116
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3401
		# dirty little trick to get number of cpus from the system
3117
					mydbapi=bindb,
3402
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
3118
					vartree=self.trees[myroot]["vartree"],
3403
		cpu_count = 0
3119
					prev_mtimes=ldpath_mtimes)
3404
		for data_cpuinfo in fd_cpuinfo.readlines():
3120
				if retval != os.EX_OK:
3405
			if data_cpuinfo.find("cpu MHz") > -1 :
3121
					return retval
3406
				cpu_count += 1
3122
				#need to check for errors
3407
		fd_cpuinfo.close()
3123
			if "--buildpkgonly" not in self.myopts:
3408
3124
				self.trees[x[1]]["vartree"].inject(x[2])
3409
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
3125
				myfavkey=portage.cpv_getkey(x[2])
3410
		if cpu_count == 0:
3126
				if "--fetchonly" not in self.myopts and \
3411
			cpu_count = 1
3127
					"--fetch-all-uri" not in self.myopts and \
3412
3128
					myfavkey in favorites:
3413
		spawnd_pkg = {}
3129
					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3414
		failed_pid = 0
3130
					myfavdict=genericdict(myfavs)
3415
		donec = 0
3131
					#don't record if already in system profile or already recorded
3416
		failedc = 0
3132
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3417
		logid_path = None
3133
						#we don't have a favorites entry for this package yet; add one
3418
		mylist = m_slots.keys()
3134
						myfavdict[myfavkey]=myfavkey
3419
		mylist.sort()
3135
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3420
		for x in mylist:
3136
						emergelog(xterm_titles, " === ("+\
3421
			# if slot is empty, go on
3137
							str(mergecount)+" of "+\
3422
			if not m_slots[x]:
3138
							str(len(mymergelist))+\
3423
				continue
3139
							") Updating world file ("+x[pkgindex]+")")
3140
						portage.write_atomic(
3141
						os.path.join(myroot, portage.WORLD_FILE),
3142
						"\n".join(myfavdict.values()))
3143
3144
				if "--pretend" not in self.myopts and \
3145
					"--fetchonly" not in self.myopts and \
3146
					"--fetch-all-uri" not in self.myopts:
3147
					# Clean the old package that we have merged over top of it.
3148
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3149
						xsplit=portage.pkgsplit(x[2])
3150
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3151
						retval = unmerge(pkgsettings, self.myopts, vartree,
3152
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3153
						if not retval:
3154
							emergelog(xterm_titles,
3155
								" --- AUTOCLEAN: Nothing unmerged.")
3156
					else:
3157
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
3158
							+ " AUTOCLEAN is disabled.  This can cause serious"
3159
							+ " problems due to overlapping packages.\n")
3160
3424
3161
					# Figure out if we need a restart.
3425
			# if previous slot failed, discontinue the emerge
3162
					mysplit=portage.pkgsplit(x[2])
3426
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
3163
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3427
				break
3164
						myver=mysplit[1]+"-"+mysplit[2]
3428
3165
						if myver[-3:]=='-r0':
3429
			# start multiple merges in parallel mode
3166
							myver=myver[:-3]
3430
			num_at_atime = cpu_count + 1
3167
						if (myver != portage.VERSION) and \
3431
3168
						   "livecvsportage" not in self.settings.features:
3432
			qsize = 0
3169
							if len(mymergelist) > mergecount:
3433
			for y in m_slots[x]:
3170
								emergelog(xterm_titles,
3434
				# these all can go in parallel, so fork one after the other
3171
									" ::: completed emerge ("+ \
3435
				# but num_at_atime at most
3172
									str(mergecount)+" of "+ \
3436
				if num_at_atime:
3173
									str(len(mymergelist))+") "+ \
3437
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3174
									x[2]+" to "+x[1])
3438
					spawnd_pids.append(onepid)
3175
								emergelog(xterm_titles, " *** RESTARTING " + \
3439
					spawnd_pkg[onepid] = (y[2], x)
3176
									"emerge via exec() after change of " + \
3440
					num_at_atime -= 1
3177
									"portage version.")
3441
					mergecount += 1
3178
								del mtimedb["resume"]["mergelist"][0]
3442
					qsize += 1
3443
				else:
3444
					self.print_status(totalcount, donec, qsize, failedc)
3445
					# let's wait for one of the jobs to finish
3446
					onepid = -1
3447
					while onepid not in spawnd_pids:
3448
						onepid , retval = os.waitpid(-1, 0)
3449
					spawnd_pids.remove(onepid)
3450
3451
					pkg_compl = spawnd_pkg[onepid][0]
3452
					pkg_slot = spawnd_pkg[onepid][1]
3453
					# unlink the logid_path
3454
					logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3455
					if os.path.exists(logid_path):
3456
						os.unlink(logid_path)
3457
3458
					# if it failed, I need to fail next slot but continue to merge all in this slot
3459
					if retval:
3460
						one_in_slot_failed = retval
3461
						failed_pid = onepid
3462
						failedc += 1
3463
					else:
3464
						donec += 1
3465
						index = 0
3466
						print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3467
						# we need to remove this pkg from resume DB
3468
						# this is the dirtiest shit I have ever written
3469
						for pkgs in mymergelist:
3470
							if pkgs[2] == pkg_compl:
3471
								del mymergelist[index]
3472
								del mtimedb["resume"]["mergelist"][index]
3179
								mtimedb.commit()
3473
								mtimedb.commit()
3180
								portage.run_exitfuncs()
3474
								# check if we need to restart portage
3181
								mynewargv=[sys.argv[0],"--resume"]
3475
								mysplit=portage.pkgsplit(pkg_compl)
3182
								for myopt, myarg in self.myopts.iteritems():
3476
								if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3183
									if myopt not in bad_resume_opts:
3477
									self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3184
										if myarg is True:
3478
								break
3185
											mynewargv.append(myopt)
3479
							index += 1
3186
										else:
3480
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3187
											mynewargv.append(myopt +"="+ myarg)
3481
					spawnd_pids.append(onepid)
3188
								# priority only needs to be adjusted on the first run
3482
					spawnd_pkg[onepid] = (y[2], x)
3189
								os.environ["PORTAGE_NICENESS"] = "0"
3483
					mergecount += 1
3190
								os.execv(mynewargv[0], mynewargv)
3484
3485
			# this slot is exhausted, so wait for all of the forks to finish
3486
			while spawnd_pids:
3487
				self.print_status(totalcount, donec, qsize, failedc)
3488
				onepid = spawnd_pids[0]
3489
				retval = os.waitpid(onepid, 0)[1]
3490
				spawnd_pids.remove(onepid)
3491
				pkg_compl = spawnd_pkg[onepid][0]
3492
				pkg_slot = spawnd_pkg[onepid][1]
3493
				# unlink the logid_path
3494
				logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3495
				if os.path.exists(logid_path):
3496
					os.unlink(logid_path)
3497
3498
				qsize -= 1
3499
				if retval:
3500
					one_in_slot_failed = retval
3501
					failed_pid = onepid
3502
					failedc += 1
3503
				else:
3504
					donec += 1
3505
					index = 0
3506
					print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3507
					# we need to remove this pkg from resume DB
3508
					# this is the dirtiest shit I have ever written
3509
					for pkgs in mymergelist:
3510
						if pkgs[2] == pkg_compl:
3511
							del mymergelist[index]
3512
							del mtimedb["resume"]["mergelist"][index]
3513
							mtimedb.commit()
3514
							# check if we need to restart portage
3515
							mysplit=portage.pkgsplit(pkg_compl)
3516
							if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3517
								self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3518
							break
3519
						index += 1
3191
3520
3192
			if "--pretend" not in self.myopts and \
3521
		self.print_status(totalcount, donec, qsize, failedc)
3193
				"--fetchonly" not in self.myopts and \
3194
				"--fetch-all-uri" not in self.myopts:
3195
				if "noclean" not in self.settings.features:
3196
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
3197
						(mergecount, len(mymergelist), x[pkgindex])
3198
					emergelog(xterm_titles, (" === (%s of %s) " + \
3199
						"Post-Build Cleaning (%s::%s)") % \
3200
						(mergecount, len(mymergelist), x[pkgindex], y),
3201
						short_msg=short_msg)
3202
				emergelog(xterm_titles, " ::: completed emerge ("+\
3203
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
3204
					x[2]+" to "+x[1])
3205
3522
3206
			# Unsafe for parallel merges
3523
		if one_in_slot_failed:
3207
			del mtimedb["resume"]["mergelist"][0]
3524
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3208
			# Commit after each merge so that --resume may still work in
3525
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
3209
			# in the event that portage is not allowed to exit normally
3526
				sys.exit(1)
3210
			# due to power failure, SIGKILL, etc...
3527
3211
			mtimedb.commit()
3528
			logfile = None
3529
			if "PORT_LOGDIR" in self.settings:
3530
				port_logdir = self.settings["PORT_LOGDIR"]
3531
			else:
3532
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3533
3534
			pkg_cat = spawnd_pkg[failed_pid][0].split("/")[0]
3535
			pkg_pf = spawnd_pkg[failed_pid][0].split("/")[1]
3536
			logid_path = os.path.join(self.settings["PORTAGE_TMPDIR"], "portage")+".logid."+pkg_cat+pkg_pf
3537
			if os.path.exists(logid_path):
3538
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
3539
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3540
					(pkg_cat, pkg_pf, logid_time))
3541
				del logid_time
3542
			del logid_path
3543
3544
			if logfile and os.path.exists(logfile):
3545
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
3546
3547
			portage.writemsg_stdout(red("Package "+spawnd_pkg[failed_pid][0]+" failed to emerge\n"))
3548
			if logfile and os.path.exists(logfile):
3549
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
3550
			sys.exit(one_in_slot_failed)
3212
3551
3213
		if "--pretend" not in self.myopts:
3552
		if "--pretend" not in self.myopts:
3214
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3553
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
Lines 3218-3237 Link Here
3218
			del mtimedb["resume"]
3557
			del mtimedb["resume"]
3219
		mtimedb.commit()
3558
		mtimedb.commit()
3220
3559
3221
		#by doing an exit this way, --fetchonly can continue to try to
3222
		#fetch everything even if a particular download fails.
3223
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3560
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3224
			if failed_fetches:
3561
			sys.exit(0)
3225
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
3562
3226
					"encountered.  Please see above for details.\n\n")
3227
				for cpv in failed_fetches:
3228
					sys.stderr.write("   ")
3229
					sys.stderr.write(cpv)
3230
					sys.stderr.write("\n")
3231
				sys.stderr.write("\n")
3232
				sys.exit(1)
3233
			else:
3234
				sys.exit(0)
3235
		return os.EX_OK
3563
		return os.EX_OK
3236
3564
3237
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3565
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
Lines 3672-3678 Link Here
3672
def validate_merge_list(trees, mergelist):
4000
def validate_merge_list(trees, mergelist):
3673
	"""Validate the list to make sure all the packages are still available.
4001
	"""Validate the list to make sure all the packages are still available.
3674
	This is needed for --resume."""
4002
	This is needed for --resume."""
3675
	for (pkg_type, myroot, pkg_key, action) in mergelist:
4003
	for (pkg_type, myroot, pkg_key, action, merge_slot) in mergelist:
3676
		if pkg_type == "binary" and \
4004
		if pkg_type == "binary" and \
3677
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4005
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3678
			pkg_type == "ebuild" and \
4006
			pkg_type == "ebuild" and \
Lines 4514-4520 Link Here
4514
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4842
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4515
		emergelog(xterm_titles, " >>> depclean")
4843
		emergelog(xterm_titles, " >>> depclean")
4516
4844
4517
	if "--quiet" not in myopts:
4845
	if "--quiet" not in myopts and "--nodeps" not in myopts:
4518
		print "\nCalculating dependencies  ",
4846
		print "\nCalculating dependencies  ",
4519
4847
4520
	soft = 0
4848
	soft = 0
Lines 4611-4616 Link Here
4611
	else:
4939
	else:
4612
		print "Number removed:       "+str(len(cleanlist))
4940
		print "Number removed:       "+str(len(cleanlist))
4613
4941
4942
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
4943
	merge_slots = {}
4944
	for pkg in mergelist:
4945
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
4946
			slot = int(pkg[4])
4947
			try:
4948
				if pkg not in merge_slots[slot]:
4949
					merge_slots[slot].append(pkg)
4950
			except KeyError:
4951
				merge_slots[slot] = [pkg]
4952
	# print the merge slots
4953
	max_slot = 0
4954
	mylist = merge_slots.keys()
4955
	mylist.sort()
4956
	for x in mylist:
4957
		if x > max_slot:
4958
			max_slot = x
4959
		if parallel:
4960
			print "Package list for slot = "+str(x)
4961
			for y in merge_slots[x]:
4962
				print "	",y
4963
	if printonly:
4964
		return
4965
4966
	# make one last pass at the merge_slots and initialize the missing slots to None
4967
	x = 0
4968
	while x < max_slot:
4969
		if x not in merge_slots.keys():
4970
			merge_slots[x] = None
4971
		x += 1
4972
	return merge_slots
4973
4614
def action_build(settings, trees, mtimedb,
4974
def action_build(settings, trees, mtimedb,
4615
	myopts, myaction, myfiles, spinner):
4975
	myopts, myaction, myfiles, spinner):
4616
	ldpath_mtimes = mtimedb["ldpath"]
4976
	ldpath_mtimes = mtimedb["ldpath"]
Lines 4658-4668 Link Here
4658
				myresumeopts[myopt] = myarg
5018
				myresumeopts[myopt] = myarg
4659
		myopts=myresumeopts
5019
		myopts=myresumeopts
4660
		myparams = create_depgraph_params(myopts, myaction)
5020
		myparams = create_depgraph_params(myopts, myaction)
4661
		if not "--quiet" in myopts:
5021
		if not "--quiet" in myopts and "--nodeps" not in myopts:
4662
			print "Calculating dependencies  ",
5022
			print "Calculating dependencies  ",
5023
		if "--nodeps" in myopts:
5024
			spinner.update = spinner.update_quiet
4663
		mydepgraph = depgraph(settings, trees,
5025
		mydepgraph = depgraph(settings, trees,
4664
			myopts, myparams, spinner)
5026
			myopts, myparams, spinner)
4665
		if not "--quiet" in myopts:
5027
		if not "--quiet" in myopts and "--nodeps" not in myopts:
4666
			print "\b\b... done!"
5028
			print "\b\b... done!"
4667
	else:
5029
	else:
4668
		if ("--resume" in myopts):
5030
		if ("--resume" in myopts):
Lines 4671-4689 Link Here
4671
5033
4672
		myparams = create_depgraph_params(myopts, myaction)
5034
		myparams = create_depgraph_params(myopts, myaction)
4673
		if myaction in ["system","world"]:
5035
		if myaction in ["system","world"]:
4674
			if not ("--quiet" in myopts):
5036
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4675
				print "Calculating",myaction,"dependencies  ",
5037
				print "Calculating",myaction,"dependencies  ",
4676
				sys.stdout.flush()
5038
				sys.stdout.flush()
5039
			if "--nodeps" in myopts:
5040
				spinner.update = spinner.update_quiet
4677
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5041
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4678
			if not mydepgraph.xcreate(myaction):
5042
			if not mydepgraph.xcreate(myaction):
4679
				print "!!! Depgraph creation failed."
5043
				print "!!! Depgraph creation failed."
4680
				sys.exit(1)
5044
				sys.exit(1)
4681
			if not ("--quiet" in myopts):
5045
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4682
				print "\b\b... done!"
5046
				print "\b\b... done!"
4683
		else:
5047
		else:
4684
			if not ("--quiet" in myopts):
5048
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4685
				print "Calculating dependencies  ",
5049
				print "Calculating dependencies  ",
4686
				sys.stdout.flush()
5050
				sys.stdout.flush()
5051
			if "--nodeps" in myopts:
5052
				spinner.update = spinner.update_quiet
4687
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
5053
			mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
4688
			try:
5054
			try:
4689
				retval, favorites = mydepgraph.select_files(myfiles)
5055
				retval, favorites = mydepgraph.select_files(myfiles)
Lines 4692-4698 Link Here
4692
				sys.exit(1)
5058
				sys.exit(1)
4693
			if not retval:
5059
			if not retval:
4694
				sys.exit(1)
5060
				sys.exit(1)
4695
			if not ("--quiet" in myopts):
5061
			if not ("--quiet" in myopts) and "--nodeps" not in myopts:
4696
				print "\b\b... done!"
5062
				print "\b\b... done!"
4697
5063
4698
			if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
5064
			if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
Lines 4713-4725 Link Here
4713
			if len(mymergelist) == 0:
5079
			if len(mymergelist) == 0:
4714
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5080
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4715
				sys.exit(0)
5081
				sys.exit(0)
5082
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4716
			mydepgraph.display(mymergelist)
5083
			mydepgraph.display(mymergelist)
4717
			prompt="Would you like to resume merging these packages?"
5084
			prompt="Would you like to resume merging these packages?"
4718
		else:
5085
		else:
4719
			mydepgraph.display(
5086
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
4720
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5087
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5088
			mydepgraph.display(mymergelist)
4721
			mergecount=0
5089
			mergecount=0
4722
			for x in mydepgraph.altlist():
5090
			for x in mymergelist:
4723
				if x[0] != "blocks" and x[3] != "nomerge":
5091
				if x[0] != "blocks" and x[3] != "nomerge":
4724
					mergecount+=1
5092
					mergecount+=1
4725
				#check for blocking dependencies
5093
				#check for blocking dependencies
Lines 4764-4773 Link Here
4764
			if len(mymergelist) == 0:
5132
			if len(mymergelist) == 0:
4765
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5133
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4766
				sys.exit(0)
5134
				sys.exit(0)
5135
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4767
			mydepgraph.display(mymergelist)
5136
			mydepgraph.display(mymergelist)
4768
		else:
5137
		else:
4769
			mydepgraph.display(
5138
			# mydepgraph.digraph.debug_print()
4770
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5139
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5140
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5141
			mydepgraph.display(mymergelist)
4771
	else:
5142
	else:
4772
		if ("--buildpkgonly" in myopts):
5143
		if ("--buildpkgonly" in myopts):
4773
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5144
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
Lines 4782-4805 Link Here
4782
				""" parallel-fetch uses --resume --fetchonly and we don't want
5153
				""" parallel-fetch uses --resume --fetchonly and we don't want
4783
				it to write the mtimedb"""
5154
				it to write the mtimedb"""
4784
				mtimedb.filename = None
5155
				mtimedb.filename = None
4785
				time.sleep(3) # allow the parent to have first fetch
5156
				time.sleep(10) # allow the parent to have first fetch
5157
			mymergelist = mtimedb["resume"]["mergelist"]
5158
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, "parallel" in settings.features)
4786
			del mydepgraph
5159
			del mydepgraph
4787
			retval = mergetask.merge(
5160
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
4788
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
4789
			if retval != os.EX_OK:
5161
			if retval != os.EX_OK:
4790
				sys.exit(retval)
5162
				sys.exit(retval)
4791
		else:
5163
		else:
4792
			if "resume" in mtimedb and \
5164
			mymergelist = mydepgraph.altlist()
4793
			"mergelist" in mtimedb["resume"] and \
5165
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, "parallel" in settings.features)
4794
			len(mtimedb["resume"]["mergelist"]) > 1:
5166
			if "--nodeps" not in myopts or len(mymergelist) > 1:
4795
				mtimedb["resume_backup"] = mtimedb["resume"]
5167
				if "resume" in mtimedb and \
4796
				del mtimedb["resume"]
5168
				"mergelist" in mtimedb["resume"] and \
4797
				mtimedb.commit()
5169
				len(mtimedb["resume"]["mergelist"]) > 1:
4798
			mtimedb["resume"]={}
5170
					mtimedb["resume_backup"] = mtimedb["resume"]
4799
			# XXX: Stored as a list for backward compatibility.
5171
					del mtimedb["resume"]
4800
			mtimedb["resume"]["myopts"] = \
5172
					mtimedb.commit()
4801
				[k for k in myopts if myopts[k] is True]
5173
				mtimedb["resume"]={}
4802
			mtimedb["resume"]["favorites"]=favorites
5174
				# XXX: Stored as a list for backward compatibility.
5175
				mtimedb["resume"]["myopts"] = \
5176
					[k for k in myopts if myopts[k] is True]
5177
				mtimedb["resume"]["favorites"]=favorites
4803
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5178
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4804
				for pkgline in mydepgraph.altlist():
5179
				for pkgline in mydepgraph.altlist():
4805
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5180
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 4815-4832 Link Here
4815
							tree="porttree")
5190
							tree="porttree")
4816
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5191
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4817
				pkglist = []
5192
				pkglist = []
4818
				for pkg in mydepgraph.altlist():
5193
				for pkg in mymergelist:
4819
					if pkg[0] != "blocks":
5194
					if pkg[0] != "blocks":
4820
						pkglist.append(pkg)
5195
						pkglist.append(pkg)
4821
			else:
5196
			else:
4822
				pkglist = mydepgraph.altlist()
5197
				pkglist = mymergelist
4823
			del mydepgraph
5198
			del mydepgraph
4824
			mergetask = MergeTask(settings, trees, myopts)
5199
			mergetask = MergeTask(settings, trees, myopts)
4825
			retval = mergetask.merge(pkglist, favorites, mtimedb)
5200
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
4826
			if retval != os.EX_OK:
5201
			if retval != os.EX_OK:
4827
				sys.exit(retval)
5202
				sys.exit(retval)
4828
5203
4829
		if mtimedb.has_key("resume"):
5204
		if mtimedb.has_key("resume") and ("--nodeps" not in myopts or len(mymergelist) > 1):
4830
			del mtimedb["resume"]
5205
			del mtimedb["resume"]
4831
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5206
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4832
			print ">>> Auto-cleaning packages..."
5207
			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 2185-2203 Link Here
2185
	mypids = []
2185
	mypids = []
2186
	pw = None
2186
	pw = None
2187
	if logfile:
2187
	if logfile:
2188
		del keywords["logfile"]
2188
		tee_good = 1
2189
		fd_pipes = keywords.get("fd_pipes")
2189
		fd_pipes = keywords.get("fd_pipes")
2190
		if fd_pipes is None:
2190
		if fd_pipes is None:
2191
			fd_pipes = {0:0, 1:1, 2:2}
2191
			fd_pipes = {0:0, 1:1, 2:2}
2192
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2192
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2193
			raise ValueError(fd_pipes)
2193
			raise ValueError(fd_pipes)
2194
		pr, pw = os.pipe()
2194
		try:
2195
		mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2195
			statinfo1 = os.stat(logfile)
2196
			 returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2196
			statinfo2 = os.fstat(fd_pipes[1])
2197
		os.close(pr)
2197
			statinfo3 = os.fstat(fd_pipes[2])
2198
		fd_pipes[1] = pw
2198
			# if they are pointing to same file as logfile, no 'tee' is required.
2199
		fd_pipes[2] = pw
2199
			if statinfo1 == statinfo2 and statinfo2 == statinfo3:
2200
		keywords["fd_pipes"] = fd_pipes
2200
				tee_good = 0
2201
		except:
2202
			tee_good = 1
2203
2204
		if tee_good:
2205
2206
			del keywords["logfile"]
2207
			pr, pw = os.pipe()
2208
			mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2209
			 	returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2210
			os.close(pr)
2211
			fd_pipes[1] = pw
2212
			fd_pipes[2] = pw
2213
			keywords["fd_pipes"] = fd_pipes
2201
2214
2202
	features = mysettings.features
2215
	features = mysettings.features
2203
	# XXX: Negative RESTRICT word
2216
	# XXX: Negative RESTRICT word
Lines 3210-3215 Link Here
3210
	if mysettings.get("PORT_LOGDIR", "") == "":
3223
	if mysettings.get("PORT_LOGDIR", "") == "":
3211
		while "PORT_LOGDIR" in mysettings:
3224
		while "PORT_LOGDIR" in mysettings:
3212
			del mysettings["PORT_LOGDIR"]
3225
			del mysettings["PORT_LOGDIR"]
3226
3227
	if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
3228
		mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + portage.DEF_LOGDIR
3229
3213
	if "PORT_LOGDIR" in mysettings:
3230
	if "PORT_LOGDIR" in mysettings:
3214
		try:
3231
		try:
3215
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
3232
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
Lines 3222-3228 Link Here
3222
			while "PORT_LOGDIR" in mysettings:
3239
			while "PORT_LOGDIR" in mysettings:
3223
				del mysettings["PORT_LOGDIR"]
3240
				del mysettings["PORT_LOGDIR"]
3224
	if "PORT_LOGDIR" in mysettings:
3241
	if "PORT_LOGDIR" in mysettings:
3225
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
3242
		logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
3226
		if not os.path.exists(logid_path):
3243
		if not os.path.exists(logid_path):
3227
			f = open(logid_path, "w")
3244
			f = open(logid_path, "w")
3228
			f.close()
3245
			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