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 (-326 / +713 lines)
Lines 2006-2011 Link Here
2006
		ignore_priority_range.extend(
2006
		ignore_priority_range.extend(
2007
			xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2007
			xrange(DepPriority.MIN, DepPriority.MEDIUM + 1))
2008
		tree_mode = "--tree" in self.myopts
2008
		tree_mode = "--tree" in self.myopts
2009
		slotcount = 0
2009
		while not mygraph.empty():
2010
		while not mygraph.empty():
2010
			ignore_priority = None
2011
			ignore_priority = None
2011
			nodes = None
2012
			nodes = None
Lines 2015-2025 Link Here
2015
					if not mygraph.contains(node):
2016
					if not mygraph.contains(node):
2016
						asap_nodes.remove(node)
2017
						asap_nodes.remove(node)
2017
						continue
2018
						continue
2018
					if not mygraph.child_nodes(node,
2019
					if not mygraph.child_nodes(node, ignore_priority=DepPriority.SOFT):
2019
						ignore_priority=DepPriority.SOFT):
2020
						nodes = [node]
2020
						nodes = [node]
2021
						asap_nodes.remove(node)
2021
						asap_nodes.remove(node)
2022
						break
2022
						break
2023
			# if no asap node, then get the first non-null set of leaf (root if --tree) nodes in the priority range
2023
			if not nodes:
2024
			if not nodes:
2024
				for ignore_priority in ignore_priority_range:
2025
				for ignore_priority in ignore_priority_range:
2025
					nodes = get_nodes(ignore_priority=ignore_priority)
2026
					nodes = get_nodes(ignore_priority=ignore_priority)
Lines 2056-2072 Link Here
2056
						if node not in mergeable_nodes:
2057
						if node not in mergeable_nodes:
2057
							return False
2058
							return False
2058
						selected_nodes.add(node)
2059
						selected_nodes.add(node)
2059
						for child in mygraph.child_nodes(node,
2060
						for child in mygraph.child_nodes(node, ignore_priority=DepPriority.SOFT):
2060
							ignore_priority=DepPriority.SOFT):
2061
							if not gather_deps(mergeable_nodes, selected_nodes, child):
2061
							if not gather_deps(
2062
								mergeable_nodes, selected_nodes, child):
2063
								return False
2062
								return False
2064
						return True
2063
						return True
2065
					mergeable_nodes = set(nodes)
2064
					mergeable_nodes = set(nodes)
2066
					for node in nodes:
2065
					for node in nodes:
2067
						selected_nodes = set()
2066
						selected_nodes = set()
2068
						if gather_deps(
2067
						if gather_deps(mergeable_nodes, selected_nodes, node):
2069
							mergeable_nodes, selected_nodes, node):
2070
							break
2068
							break
2071
						else:
2069
						else:
2072
							selected_nodes = None
2070
							selected_nodes = None
Lines 2123-2129 Link Here
2123
				sys.exit(1)
2121
				sys.exit(1)
2124
2122
2125
			for node in selected_nodes:
2123
			for node in selected_nodes:
2126
				retlist.append(list(node))
2124
				node2 = list(node)
2125
				if len(node2) == 4:
2126
					node2.append(str(slotcount))
2127
				retlist.append(node2)
2127
				mygraph.remove(node)
2128
				mygraph.remove(node)
2128
				if not reversed and not circular_blocks and myblockers.contains(node):
2129
				if not reversed and not circular_blocks and myblockers.contains(node):
2129
					"""This node may have invalidated one or more blockers."""
2130
					"""This node may have invalidated one or more blockers."""
Lines 2132-2137 Link Here
2132
						if not myblockers.child_nodes(blocker):
2133
						if not myblockers.child_nodes(blocker):
2133
							myblockers.remove(blocker)
2134
							myblockers.remove(blocker)
2134
							del self.blocker_parents[blocker]
2135
							del self.blocker_parents[blocker]
2136
			slotcount += 1
2135
2137
2136
		if not reversed:
2138
		if not reversed:
2137
			"""Blocker validation does not work with reverse mode,
2139
			"""Blocker validation does not work with reverse mode,
Lines 2334-2340 Link Here
2334
		for x in mylist:
2336
		for x in mylist:
2335
			if "blocks" == x[0]:
2337
			if "blocks" == x[0]:
2336
				continue
2338
				continue
2337
			graph_key = tuple(x)
2339
			graph_key = tuple(x[:-1])
2338
			if "--tree" in self.myopts:
2340
			if "--tree" in self.myopts:
2339
				depth = len(tree_nodes)
2341
				depth = len(tree_nodes)
2340
				while depth and graph_key not in \
2342
				while depth and graph_key not in \
Lines 2348-2360 Link Here
2348
		for i in xrange(len(mylist)-1,-1,-1):
2350
		for i in xrange(len(mylist)-1,-1,-1):
2349
			if "blocks" == mylist[i][0]:
2351
			if "blocks" == mylist[i][0]:
2350
				continue
2352
				continue
2351
			graph_key = tuple(mylist[i])
2353
			graph_key = tuple(mylist[i][:-1])
2352
			if mylist[i][-1] != "nomerge":
2354
			if mylist[i][-2] != "nomerge":
2353
				last_merge_depth = node_depth[graph_key]
2355
				last_merge_depth = node_depth[graph_key]
2354
				continue
2356
				continue
2355
			if node_depth[graph_key] >= last_merge_depth or \
2357
			if node_depth[graph_key] >= last_merge_depth or \
2356
				i < len(mylist) - 1 and \
2358
				i < len(mylist) - 1 and \
2357
				node_depth[graph_key] >= node_depth[tuple(mylist[i+1])]:
2359
				node_depth[graph_key] >= node_depth[tuple(mylist[i+1][:-1])]:
2358
					del mylist[i]
2360
					del mylist[i]
2359
					del node_depth[graph_key]
2361
					del node_depth[graph_key]
2360
		del tree_nodes
2362
		del tree_nodes
Lines 2550-2556 Link Here
2550
				if verbosity == 3:
2552
				if verbosity == 3:
2551
					# size verbose
2553
					# size verbose
2552
					mysize=0
2554
					mysize=0
2553
					if x[0] == "ebuild" and x[-1]!="nomerge":
2555
					if x[0] == "ebuild" and x[-2]!="nomerge":
2554
						try:
2556
						try:
2555
							myfilesdict = portdb.getfetchsizes(pkg_key,
2557
							myfilesdict = portdb.getfetchsizes(pkg_key,
2556
								useflags=self.useFlags[myroot][pkg_key],
2558
								useflags=self.useFlags[myroot][pkg_key],
Lines 2602-2608 Link Here
2602
				oldlp=mywidth-30
2604
				oldlp=mywidth-30
2603
				newlp=oldlp-30
2605
				newlp=oldlp-30
2604
2606
2605
				indent = " " * node_depth[tuple(x)]
2607
				indent = " " * node_depth[tuple(x[:-1])]
2606
2608
2607
				if myoldbest:
2609
				if myoldbest:
2608
					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
2610
					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
Lines 2834-2844 Link Here
2834
			self.pkgsettings["/"] = \
2836
			self.pkgsettings["/"] = \
2835
				portage.config(clone=trees["/"]["vartree"].settings)
2837
				portage.config(clone=trees["/"]["vartree"].settings)
2836
2838
2837
	def merge(self, mylist, favorites, mtimedb):
2839
	def restart_portage(self, x, mergecount, totalcount, mtimedb):
2840
		xterm_titles = "notitles" not in self.settings.features
2841
		# don't really restart if any of these is true
2842
		# XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
2843
		if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
2844
			"--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
2845
			return
2846
2847
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2848
			"--resume"])
2849
		mysplit=portage.pkgsplit(x[2])
2850
		myver=mysplit[1]+"-"+mysplit[2]
2851
		if myver[-3:]=='-r0':
2852
			myver=myver[:-3]
2853
		if (myver != portage.VERSION) and \
2854
		   "livecvsportage" not in self.settings.features:
2855
			if totalcount > mergecount:
2856
				emergelog(xterm_titles,
2857
					" ::: completed emerge ("+ \
2858
					str(mergecount)+" of "+ \
2859
					str(totalcount)+") "+ \
2860
					x[2]+" to "+x[1])
2861
				emergelog(xterm_titles, " *** RESTARTING " + \
2862
					"emerge via exec() after change of " + \
2863
					"portage version.")
2864
				portage.run_exitfuncs()
2865
				mynewargv=[sys.argv[0],"--resume"]
2866
				for myopt, myarg in self.myopts.iteritems():
2867
					if myopt not in bad_resume_opts:
2868
						if myarg is True:
2869
							mynewargv.append(myopt)
2870
						else:
2871
							mynewargv.append(myopt +"="+ myarg)
2872
				# priority only needs to be adjusted on the first run
2873
				os.environ["PORTAGE_NICENESS"] = "0"
2874
				os.execv(mynewargv[0], mynewargv)
2875
2876
	def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
2877
		xterm_titles = "notitles" not in self.settings.features
2878
		myfeat = self.settings.features[:]
2879
		ldpath_mtimes = mtimedb["ldpath"]
2880
		myroot=x[1]
2881
		pkg_key = x[2]
2882
		pkg_cat = x[2].split("/")[0]
2883
		pkg_pf = x[2].split("/")[1]
2884
		pkgindex=2
2885
		if x[0]=="blocks":
2886
			pkgindex=3
2887
2888
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
2889
		logid_path = None
2890
		null_log = 0
2891
2892
		if self.settings.get("PORT_LOGDIR", "") == "":
2893
			while "PORT_LOGDIR" in self.settings:
2894
				del self.settings["PORT_LOGDIR"]
2895
		if "PORT_LOGDIR" in self.settings:
2896
			port_logdir = self.settings["PORT_LOGDIR"]
2897
		else:
2898
			port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
2899
2900
		try:
2901
			portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
2902
						 gid=portage.portage_gid, mode=02770)
2903
		except portage_exception.PortageException, e:
2904
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
2905
			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
2906
				self.settings["PORT_LOGDIR"], noiselevel=-1)
2907
			writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
2908
			null_log = 1
2909
2910
		if not null_log:
2911
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
2912
			if not os.path.exists(logid_path):
2913
				f = open(logid_path, "w")
2914
				f.close()
2915
				del f
2916
			logid_time = time.strftime("%Y%m%d-%H%M%S",
2917
				time.gmtime(os.stat(logid_path).st_mtime))
2918
			logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
2919
				(pkg_cat, pkg_pf, logid_time))
2920
			del logid_time
2921
		else:
2922
			logfile = "/dev/null"
2923
2924
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
2925
			print ">>> Emerging (" + \
2926
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2927
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
2928
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
2929
			print ">>> Logfile in " + logfile
2930
			emergelog(xterm_titles, " >>> emerge ("+\
2931
				str(mergecount)+" of "+str(totalcount)+\
2932
				") "+x[pkgindex]+" to "+x[1])
2933
2934
		# need to spawn a --nodeps emerge in a separate process.
2935
		pkg="="+x[2]
2936
		merge_env = os.environ.copy()
2937
		merge_env["PORTAGE_INTERNAL_CALL"] = "1"
2938
		merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
2939
		merge_args = [sys.argv[0], "--nodeps", "--oneshot", "--nospinner", pkg]
2940
		good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
2941
					"--usepkg", "--usepkgonly"])
2942
		fd_pipes = None
2943
		merge_logfd = None
2944
		for myopt, myarg in self.myopts.iteritems():
2945
			# don't clobber the logfile at the same time as parallel fetch is
2946
			# all log of parallel fetch will go /var/log/emerge-fetch.log
2947
			# so, just leave 0,1,2 alone.
2948
			if "parallel-fetch" in myfeat and myopt == "--fetchonly":
2949
				fd_pipes = {0:0, 1:1, 2:2}
2950
			if myopt in good_nodeps_opts:
2951
				if myarg is True:
2952
					merge_args.append(myopt)
2953
				else:
2954
					merge_args.append(myopt +"="+ myarg)
2955
		if not fd_pipes:
2956
			merge_logfd = open(logfile, "w")
2957
			# put in a start message. This also makes sure that this fd is pointing to a good file on disk
2958
			# and hence will be used throughout the other spawns that will happen in the children.
2959
			merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
2960
			merge_logfd.flush()
2961
			fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
2962
			portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
2963
2964
		mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
2965
		if merge_logfd:
2966
			merge_logfd.close() # child has exclusive rights to it now.
2967
		return mypids[0]
2968
2969
	def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
2970
		xterm_titles = "notitles" not in self.settings.features
2971
		myfeat = self.settings.features[:]
2972
		ldpath_mtimes = mtimedb["ldpath"]
2973
		myroot=x[1]
2974
		pkg_key = x[2]
2975
		pkg_cat = x[2].split("/")[0]
2976
		pkg_pf = x[2].split("/")[1]
2977
		pkgindex=2
2978
		if x[0]=="blocks":
2979
			pkgindex=3
2980
2981
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
2982
			print "\n>>> Emerging (" + \
2983
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
2984
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
2985
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
2986
			emergelog(xterm_titles, " >>> emerge ("+\
2987
				str(mergecount)+" of "+str(totalcount)+\
2988
				") "+x[pkgindex]+" to "+x[1])
2989
2990
		portdb = self.trees[myroot]["porttree"].dbapi
2991
		bindb  = self.trees[myroot]["bintree"].dbapi
2992
		vartree = self.trees[myroot]["vartree"]
2993
		pkgsettings = self.pkgsettings[myroot]
2994
		y = portdb.findname(pkg_key)
2995
		pkgsettings["EMERGE_FROM"] = x[0]
2996
		pkgsettings.backup_changes("EMERGE_FROM")
2997
		pkgsettings.reset()
2998
2999
		#buildsyspkg: Check if we need to _force_ binary package creation
3000
		issyspkg = ("buildsyspkg" in myfeat) \
3001
				and x[0] != "blocks" \
3002
				and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3003
				and "--buildpkg" not in self.myopts
3004
		if x[0] in ["ebuild","blocks"]:
3005
			if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3006
				raise Exception, "Merging a blocker"
3007
			elif "--fetchonly" in self.myopts or \
3008
				"--fetch-all-uri" in self.myopts:
3009
				if "--fetch-all-uri" in self.myopts:
3010
					retval = portage.doebuild(y, "fetch", myroot,
3011
						pkgsettings, self.edebug,
3012
						"--pretend" in self.myopts, fetchonly=1,
3013
						fetchall=1, mydbapi=portdb, tree="porttree")
3014
				else:
3015
					retval = portage.doebuild(y, "fetch", myroot,
3016
						pkgsettings, self.edebug,
3017
						"--pretend" in self.myopts, fetchonly=1,
3018
						mydbapi=portdb, tree="porttree")
3019
				if (retval is None) or retval:
3020
					print
3021
					print "!!! Fetch for",y,"failed, continuing..."
3022
					print
3023
3024
				return retval
3025
3026
			portage.doebuild_environment(y, "setup", myroot,
3027
				pkgsettings, self.edebug, 1, portdb)
3028
			catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3029
			portage_util.ensure_dirs(os.path.dirname(catdir),
3030
				uid=portage.portage_uid, gid=portage.portage_gid,
3031
				mode=070, mask=0)
3032
			builddir_lock = None
3033
			catdir_lock = None
3034
			try:
3035
				catdir_lock = portage_locks.lockdir(catdir)
3036
				portage_util.ensure_dirs(catdir,
3037
					uid=portage.portage_uid, gid=portage.portage_gid,
3038
					mode=070, mask=0)
3039
				builddir_lock = portage_locks.lockdir(
3040
					pkgsettings["PORTAGE_BUILDDIR"])
3041
				try:
3042
					portage_locks.unlockdir(catdir_lock)
3043
				finally:
3044
					catdir_lock = None
3045
				msg = " === (%s of %s) Cleaning (%s::%s)" % \
3046
					(mergecount, totalcount, pkg_key, y)
3047
				short_msg = "emerge: (%s of %s) %s Clean" % \
3048
					(mergecount, totalcount, pkg_key)
3049
				emergelog(xterm_titles, msg, short_msg=short_msg)
3050
				retval = portage.doebuild(y, "clean", myroot,
3051
					pkgsettings, self.edebug, cleanup=1,
3052
					mydbapi=portdb, tree="porttree")
3053
3054
				if retval != os.EX_OK:
3055
					return retval
3056
				if "--buildpkg" in self.myopts or issyspkg:
3057
					if issyspkg:
3058
						print ">>> This is a system package, " + \
3059
							"let's pack a rescue tarball."
3060
					msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3061
						(mergecount, totalcount, pkg_key, y)
3062
					short_msg = "emerge: (%s of %s) %s Compile" % \
3063
						(mergecount, totalcount, pkg_key)
3064
					emergelog(xterm_titles, msg, short_msg=short_msg)
3065
					self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3066
					retval = portage.doebuild(y, "package", myroot,
3067
						pkgsettings, self.edebug, mydbapi=portdb,
3068
						tree="porttree")
3069
					if retval != os.EX_OK:
3070
						return retval
3071
					if "--buildpkgonly" not in self.myopts:
3072
						bintree = self.trees[myroot]["bintree"]
3073
						bintree.inject(pkg_key)
3074
						mytbz2 = bintree.getname(pkg_key)
3075
						msg = " === (%s of %s) Merging (%s::%s)" % \
3076
							(mergecount, totalcount, pkg_key, y)
3077
						short_msg = "emerge: (%s of %s) %s Merge" % \
3078
							(mergecount, totalcount, pkg_key)
3079
						emergelog(xterm_titles, msg, short_msg=short_msg)
3080
						retval = portage.merge(pkgsettings["CATEGORY"],
3081
							pkgsettings["PF"], pkgsettings["D"],
3082
							os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3083
							"build-info"), myroot, pkgsettings,
3084
							myebuild=pkgsettings["EBUILD"],
3085
							mytree="porttree", mydbapi=portdb,
3086
							vartree=vartree, prev_mtimes=ldpath_mtimes)
3087
						if retval != os.EX_OK:
3088
							return retval
3089
					elif "noclean" not in pkgsettings.features:
3090
						portage.doebuild(y, "clean", myroot,
3091
							pkgsettings, self.edebug, mydbapi=portdb,
3092
							tree="porttree")
3093
				else:
3094
					msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3095
						(mergecount, totalcount, pkg_key, y)
3096
					short_msg = "emerge: (%s of %s) %s Compile" % \
3097
						(mergecount, totalcount, pkg_key)
3098
					emergelog(xterm_titles, msg, short_msg=short_msg)
3099
					retval = portage.doebuild(y, "merge", myroot,
3100
						pkgsettings, self.edebug, vartree=vartree,
3101
						mydbapi=portdb, tree="porttree",
3102
						prev_mtimes=ldpath_mtimes)
3103
					if retval != os.EX_OK:
3104
						return retval
3105
			finally:
3106
				if builddir_lock:
3107
					portage_locks.unlockdir(builddir_lock)
3108
				try:
3109
					if not catdir_lock:
3110
						# Lock catdir for removal if empty.
3111
						catdir_lock = portage_locks.lockdir(catdir)
3112
				finally:
3113
					if catdir_lock:
3114
						try:
3115
							os.rmdir(catdir)
3116
						except OSError, e:
3117
							if e.errno not in (errno.ENOENT,
3118
								errno.ENOTEMPTY, errno.EEXIST):
3119
								raise
3120
							del e
3121
						portage_locks.unlockdir(catdir_lock)
3122
3123
		elif x[0]=="binary":
3124
			#merge the tbz2
3125
			mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3126
			if "--getbinpkg" in self.myopts:
3127
				tbz2_lock = None
3128
				try:
3129
					if "distlocks" in pkgsettings.features and \
3130
						os.access(pkgsettings["PKGDIR"], os.W_OK):
3131
						portage_util.ensure_dirs(os.path.dirname(mytbz2))
3132
						tbz2_lock = portage_locks.lockfile(mytbz2,
3133
							wantnewlockfile=1)
3134
					if self.trees[myroot]["bintree"].isremote(pkg_key):
3135
						msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3136
							(mergecount, totalcount, pkg_key, mytbz2)
3137
						short_msg = "emerge: (%s of %s) %s Fetch" % \
3138
							(mergecount, totalcount, pkg_key)
3139
						emergelog(xterm_titles, msg, short_msg=short_msg)
3140
						if not self.trees[myroot]["bintree"].gettbz2(
3141
							pkg_key):
3142
							return 1
3143
				finally:
3144
					if tbz2_lock:
3145
						portage_locks.unlockfile(tbz2_lock)
3146
3147
			if "--fetchonly" in self.myopts or \
3148
				"--fetch-all-uri" in self.myopts:
3149
				return os.EX_OK
3150
3151
			short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
3152
			emergelog(xterm_titles, " === ("+str(mergecount)+\
3153
				" of "+str(totalcount)+") Merging Binary ("+\
3154
				x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3155
3156
			retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3157
				mydbapi=bindb,
3158
				vartree=self.trees[myroot]["vartree"],
3159
				prev_mtimes=ldpath_mtimes)
3160
			if retval != os.EX_OK:
3161
				return retval
3162
			#need to check for errors
3163
		if "--buildpkgonly" not in self.myopts:
3164
			self.trees[x[1]]["vartree"].inject(x[2])
3165
			myfavkey=portage.cpv_getkey(x[2])
3166
			if "--fetchonly" not in self.myopts and \
3167
				"--fetch-all-uri" not in self.myopts and \
3168
				myfavkey in favorites:
3169
				myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3170
				myfavdict=genericdict(myfavs)
3171
				#don't record if already in system profile or already recorded
3172
				if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3173
					#we don't have a favorites entry for this package yet; add one
3174
					myfavdict[myfavkey]=myfavkey
3175
					print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3176
					emergelog(xterm_titles, " === ("+\
3177
						str(mergecount)+" of "+\
3178
						str(totalcount)+\
3179
						") Updating world file ("+x[pkgindex]+")")
3180
					portage.write_atomic(
3181
					os.path.join(myroot, portage.WORLD_FILE),
3182
					"\n".join(myfavdict.values()))
3183
3184
			if "--pretend" not in self.myopts and \
3185
				"--fetchonly" not in self.myopts and \
3186
				"--fetch-all-uri" not in self.myopts:
3187
				# Clean the old package that we have merged over top of it.
3188
				if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3189
					xsplit=portage.pkgsplit(x[2])
3190
					emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3191
					retval = unmerge(pkgsettings, self.myopts, vartree,
3192
						"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3193
					if not retval:
3194
						emergelog(xterm_titles,
3195
							" --- AUTOCLEAN: Nothing unmerged.")
3196
				else:
3197
					portage.writemsg_stdout(colorize("WARN", "WARNING:")
3198
						+ " AUTOCLEAN is disabled.  This can cause serious"
3199
						+ " problems due to overlapping packages.\n")
3200
3201
3202
		if "--pretend" not in self.myopts and \
3203
			"--fetchonly" not in self.myopts and \
3204
			"--fetch-all-uri" not in self.myopts:
3205
			if "noclean" not in self.settings.features:
3206
				short_msg = "emerge: (%s of %s) %s Clean Post" % \
3207
					(mergecount, totalcount, x[pkgindex])
3208
				emergelog(xterm_titles, (" === (%s of %s) " + \
3209
					"Post-Build Cleaning (%s::%s)") % \
3210
					(mergecount, totalcount, x[pkgindex], y),
3211
					short_msg=short_msg)
3212
			emergelog(xterm_titles, " ::: completed emerge ("+\
3213
				str(mergecount)+" of "+str(totalcount)+") "+\
3214
				x[2]+" to "+x[1])
3215
3216
		return os.EX_OK
3217
3218
	def print_status(self, totalcount, donec, qsize, failedc, spawnd, failed):
3219
		smsg = ""
3220
		fmsg = ""
3221
		if spawnd:
3222
			for pkgs in spawnd.values():
3223
				smsg = smsg+" "+pkgs[0]
3224
		if failed:
3225
			for pkgs in failed:
3226
				fmsg = fmsg+" "+pkgs
3227
		print ">>> Jobs [Total = "+colorize("blue", str(totalcount))+"] [Done = "+\
3228
			colorize("GOOD", str(donec))+"] [Running = "+colorize("WARN", str(qsize)+smsg)+\
3229
			"] [Failed = "+colorize("BAD", str(failedc)+fmsg)+"]"
3230
		xtermTitle("Jobs Total = "+str(totalcount)+" Done = "+\
3231
			str(donec)+" Running = "+str(qsize)+" Failed = "+str(failedc))
3232
3233
	def merge(self, mylist, favorites, mtimedb, m_slots):
2838
		failed_fetches = []
3234
		failed_fetches = []
2839
		mymergelist=[]
3235
		mymergelist=[]
2840
		ldpath_mtimes = mtimedb["ldpath"]
3236
		ldpath_mtimes = mtimedb["ldpath"]
2841
		xterm_titles = "notitles" not in self.settings.features
3237
		xterm_titles = "notitles" not in self.settings.features
3238
		parallel = "parallel" in self.settings.features
3239
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3240
3241
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3242
		if self.edebug or "--fetchonly" in self.myopts:
3243
			parallel = False
2842
3244
2843
		#check for blocking dependencies
3245
		#check for blocking dependencies
2844
		if "--fetchonly" not in self.myopts and \
3246
		if "--fetchonly" not in self.myopts and \
Lines 2861-2868 Link Here
2861
		mysysdict = genericdict(getlist(self.settings, "system"))
3263
		mysysdict = genericdict(getlist(self.settings, "system"))
2862
		if "--resume" in self.myopts:
3264
		if "--resume" in self.myopts:
2863
			# We're resuming.
3265
			# We're resuming.
2864
			print colorize("GOOD", "*** Resuming merge...")
2865
			emergelog(xterm_titles, " *** Resuming merge...")
2866
			mymergelist=mtimedb["resume"]["mergelist"][:]
3266
			mymergelist=mtimedb["resume"]["mergelist"][:]
2867
			if "--skipfirst" in self.myopts and mymergelist:
3267
			if "--skipfirst" in self.myopts and mymergelist:
2868
				del mtimedb["resume"]["mergelist"][0]
3268
				del mtimedb["resume"]["mergelist"][0]
Lines 2896-2903 Link Here
2896
					os.path.join(self.target_root, portage.WORLD_FILE),
3296
					os.path.join(self.target_root, portage.WORLD_FILE),
2897
					"\n".join(myfavdict.values()))
3297
					"\n".join(myfavdict.values()))
2898
3298
2899
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3299
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
2900
			mtimedb.commit()
3300
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3301
				mtimedb.commit()
3302
3303
		totalcount = len(mymergelist)
3304
		mergecount=1
3305
3306
		if "--resume" in self.myopts and "--fetchonly" not in self.myopts:
3307
			# We're resuming.
3308
			print colorize("GOOD", "*** Resuming merge...")
3309
			emergelog(xterm_titles, " *** Resuming merge...")
2901
3310
2902
		myfeat = self.settings.features[:]
3311
		myfeat = self.settings.features[:]
2903
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3312
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 2915-2926 Link Here
2915
				print ">>> starting parallel fetching"
3324
				print ">>> starting parallel fetching"
2916
				fetch_log = "/var/log/emerge-fetch.log"
3325
				fetch_log = "/var/log/emerge-fetch.log"
2917
				logfile = open(fetch_log, "w")
3326
				logfile = open(fetch_log, "w")
2918
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3327
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
2919
				portage_util.apply_secpass_permissions(fetch_log,
3328
				portage_util.apply_secpass_permissions(fetch_log,
2920
					uid=portage.portage_uid, gid=portage.portage_gid,
3329
					uid=portage.portage_uid, gid=portage.portage_gid,
2921
					mode=0660)
3330
					mode=0660)
2922
				fetch_env = os.environ.copy()
3331
				fetch_env = os.environ.copy()
2923
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3332
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
2924
				fetch_env["PORTAGE_NICENESS"] = "0"
3333
				fetch_env["PORTAGE_NICENESS"] = "0"
2925
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3334
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2926
				for myopt, myarg in self.myopts.iteritems():
3335
				for myopt, myarg in self.myopts.iteritems():
Lines 2933-3215 Link Here
2933
					fd_pipes=fd_pipes, returnpid=True)
3342
					fd_pipes=fd_pipes, returnpid=True)
2934
				logfile.close() # belongs to the spawned process
3343
				logfile.close() # belongs to the spawned process
2935
3344
2936
		mergecount=0
3345
		if not parallel:
2937
		for x in mymergelist:
3346
			failed_fetches = []
2938
			mergecount+=1
3347
			for x in mymergelist:
2939
			myroot=x[1]
3348
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, mysysdict)
2940
			pkg_key = x[2]
3349
				mergecount += 1
2941
			pkgindex=2
3350
2942
			portdb = self.trees[myroot]["porttree"].dbapi
3351
				# need to short circuit the spawn with --nodeps
2943
			bindb  = self.trees[myroot]["bintree"].dbapi
3352
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
2944
			vartree = self.trees[myroot]["vartree"]
3353
					if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
2945
			pkgsettings = self.pkgsettings[myroot]
3354
						continue
2946
			if x[0]=="blocks":
3355
					if retcode != os.EX_OK:
2947
				pkgindex=3
3356
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
2948
			y = portdb.findname(pkg_key)
3357
							failed_fetches.append(x[2])
2949
			if "--pretend" not in self.myopts:
3358
							continue
2950
				print "\n>>> Emerging (" + \
3359
						else:
2951
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3360
							return retcode
2952
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3361
					# Unsafe for parallel merges
2953
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
3362
					del mtimedb["resume"]["mergelist"][0]
2954
				emergelog(xterm_titles, " >>> emerge ("+\
3363
					# Commit after each merge so that --resume may still work in
2955
					str(mergecount)+" of "+str(len(mymergelist))+\
3364
					# in the event that portage is not allowed to exit normally
2956
					") "+x[pkgindex]+" to "+x[1])
3365
					# due to power failure, SIGKILL, etc...
3366
					mtimedb.commit()
3367
3368
					# unlink the logid_path if any exists
3369
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
3370
					if os.path.exists(logid_path):
3371
						os.unlink(logid_path)
3372
					del logid_path
2957
3373
2958
			pkgsettings["EMERGE_FROM"] = x[0]
3374
					# check if we need to restart portage
2959
			pkgsettings.backup_changes("EMERGE_FROM")
3375
					mysplit=portage.pkgsplit(x[2])
2960
			pkgsettings.reset()
3376
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3377
							self.restart_portage(x, mergecount, totalcount, mtimedb)
2961
3378
2962
			#buildsyspkg: Check if we need to _force_ binary package creation
3379
				else:
2963
			issyspkg = ("buildsyspkg" in myfeat) \
3380
					if retcode != os.EX_OK:
2964
					and x[0] != "blocks" \
3381
						sys.exit(1)
2965
					and mysysdict.has_key(portage.cpv_getkey(x[2])) \
2966
					and "--buildpkg" not in self.myopts
2967
			if x[0] in ["ebuild","blocks"]:
2968
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
2969
					raise Exception, "Merging a blocker"
2970
				elif "--fetchonly" in self.myopts or \
2971
					"--fetch-all-uri" in self.myopts:
2972
					if "--fetch-all-uri" in self.myopts:
2973
						retval = portage.doebuild(y, "fetch", myroot,
2974
							pkgsettings, self.edebug,
2975
							"--pretend" in self.myopts, fetchonly=1,
2976
							fetchall=1, mydbapi=portdb, tree="porttree")
2977
					else:
3382
					else:
2978
						retval = portage.doebuild(y, "fetch", myroot,
3383
						sys.exit(0)
2979
							pkgsettings, self.edebug,
2980
							"--pretend" in self.myopts, fetchonly=1,
2981
							mydbapi=portdb, tree="porttree")
2982
					if (retval is None) or retval:
2983
						print
2984
						print "!!! Fetch for",y,"failed, continuing..."
2985
						print
2986
						failed_fetches.append(pkg_key)
2987
					continue
2988
3384
2989
				portage.doebuild_environment(y, "setup", myroot,
3385
			if "--pretend" not in self.myopts:
2990
					pkgsettings, self.edebug, 1, portdb)
3386
				emergelog(xterm_titles, " *** Finished. Cleaning up...")
2991
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
2992
				portage_util.ensure_dirs(os.path.dirname(catdir),
2993
					uid=portage.portage_uid, gid=portage.portage_gid,
2994
					mode=070, mask=0)
2995
				builddir_lock = None
2996
				catdir_lock = None
2997
				try:
2998
					catdir_lock = portage_locks.lockdir(catdir)
2999
					portage_util.ensure_dirs(catdir,
3000
						uid=portage.portage_uid, gid=portage.portage_gid,
3001
						mode=070, mask=0)
3002
					builddir_lock = portage_locks.lockdir(
3003
						pkgsettings["PORTAGE_BUILDDIR"])
3004
					try:
3005
						portage_locks.unlockdir(catdir_lock)
3006
					finally:
3007
						catdir_lock = None
3008
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
3009
						(mergecount, len(mymergelist), pkg_key, y)
3010
					short_msg = "emerge: (%s of %s) %s Clean" % \
3011
						(mergecount, len(mymergelist), pkg_key)
3012
					emergelog(xterm_titles, msg, short_msg=short_msg)
3013
					retval = portage.doebuild(y, "clean", myroot,
3014
						pkgsettings, self.edebug, cleanup=1,
3015
						mydbapi=portdb, tree="porttree")
3016
					if retval != os.EX_OK:
3017
						return retval
3018
					if "--buildpkg" in self.myopts or issyspkg:
3019
						if issyspkg:
3020
							print ">>> This is a system package, " + \
3021
								"let's pack a rescue tarball."
3022
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3023
							(mergecount, len(mymergelist), pkg_key, y)
3024
						short_msg = "emerge: (%s of %s) %s Compile" % \
3025
							(mergecount, len(mymergelist), pkg_key)
3026
						emergelog(xterm_titles, msg, short_msg=short_msg)
3027
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3028
						retval = portage.doebuild(y, "package", myroot,
3029
							pkgsettings, self.edebug, mydbapi=portdb,
3030
							tree="porttree")
3031
						if retval != os.EX_OK:
3032
							return retval
3033
						if "--buildpkgonly" not in self.myopts:
3034
							bintree = self.trees[myroot]["bintree"]
3035
							bintree.inject(pkg_key)
3036
							mytbz2 = bintree.getname(pkg_key)
3037
							msg = " === (%s of %s) Merging (%s::%s)" % \
3038
								(mergecount, len(mymergelist), pkg_key, y)
3039
							short_msg = "emerge: (%s of %s) %s Merge" % \
3040
								(mergecount, len(mymergelist), pkg_key)
3041
							emergelog(xterm_titles, msg, short_msg=short_msg)
3042
							retval = portage.merge(pkgsettings["CATEGORY"],
3043
								pkgsettings["PF"], pkgsettings["D"],
3044
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3045
								"build-info"), myroot, pkgsettings,
3046
								myebuild=pkgsettings["EBUILD"],
3047
								mytree="porttree", mydbapi=portdb,
3048
								vartree=vartree, prev_mtimes=ldpath_mtimes)
3049
							if retval != os.EX_OK:
3050
								return retval
3051
						elif "noclean" not in pkgsettings.features:
3052
							portage.doebuild(y, "clean", myroot,
3053
								pkgsettings, self.edebug, mydbapi=portdb,
3054
								tree="porttree")
3055
					else:
3056
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3057
							(mergecount, len(mymergelist), pkg_key, y)
3058
						short_msg = "emerge: (%s of %s) %s Compile" % \
3059
							(mergecount, len(mymergelist), pkg_key)
3060
						emergelog(xterm_titles, msg, short_msg=short_msg)
3061
						retval = portage.doebuild(y, "merge", myroot,
3062
							pkgsettings, self.edebug, vartree=vartree,
3063
							mydbapi=portdb, tree="porttree",
3064
							prev_mtimes=ldpath_mtimes)
3065
						if retval != os.EX_OK:
3066
							return retval
3067
				finally:
3068
					if builddir_lock:
3069
						portage_locks.unlockdir(builddir_lock)
3070
					try:
3071
						if not catdir_lock:
3072
							# Lock catdir for removal if empty.
3073
							catdir_lock = portage_locks.lockdir(catdir)
3074
					finally:
3075
						if catdir_lock:
3076
							try:
3077
								os.rmdir(catdir)
3078
							except OSError, e:
3079
								if e.errno not in (errno.ENOENT,
3080
									errno.ENOTEMPTY, errno.EEXIST):
3081
									raise
3082
								del e
3083
							portage_locks.unlockdir(catdir_lock)
3084
3085
			elif x[0]=="binary":
3086
				#merge the tbz2
3087
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3088
				if "--getbinpkg" in self.myopts:
3089
					tbz2_lock = None
3090
					try:
3091
						if "distlocks" in pkgsettings.features and \
3092
							os.access(pkgsettings["PKGDIR"], os.W_OK):
3093
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
3094
							tbz2_lock = portage_locks.lockfile(mytbz2,
3095
								wantnewlockfile=1)
3096
						if self.trees[myroot]["bintree"].isremote(pkg_key):
3097
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3098
								(mergecount, len(mymergelist), pkg_key, mytbz2)
3099
							short_msg = "emerge: (%s of %s) %s Fetch" % \
3100
								(mergecount, len(mymergelist), pkg_key)
3101
							emergelog(xterm_titles, msg, short_msg=short_msg)
3102
							if not self.trees[myroot]["bintree"].gettbz2(
3103
								pkg_key):
3104
								return 1
3105
					finally:
3106
						if tbz2_lock:
3107
							portage_locks.unlockfile(tbz2_lock)
3108
3387
3109
				if "--fetchonly" in self.myopts or \
3388
			# We're out of the loop... We're done. Delete the resume data.
3110
					"--fetch-all-uri" in self.myopts:
3389
			if mtimedb.has_key("resume"):
3111
					continue
3390
				del mtimedb["resume"]
3391
			mtimedb.commit()
3392
			
3393
			#by doing an exit this way, --fetchonly can continue to try to
3394
			#fetch everything even if a particular download fails.
3395
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3396
				if failed_fetches:
3397
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
3398
						"encountered.  Please see above for details.\n\n")
3399
					for cpv in failed_fetches:
3400
						sys.stderr.write("   ")
3401
						sys.stderr.write(cpv)
3402
						sys.stderr.write("\n")
3403
					sys.stderr.write("\n")
3404
					sys.exit(1)
3405
				else:
3406
					sys.exit(0)
3407
			return os.EX_OK
3112
3408
3113
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3409
		# parallel code - dirty starts here...;-)
3114
				emergelog(xterm_titles, " === ("+str(mergecount)+\
3410
		one_in_slot_failed=0
3115
					" of "+str(len(mymergelist))+") Merging Binary ("+\
3411
		spawnd_pids=[]
3116
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3412
3117
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3413
		# dirty little trick to get number of cpus from the system
3118
					mydbapi=bindb,
3414
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
3119
					vartree=self.trees[myroot]["vartree"],
3415
		cpu_count = 0
3120
					prev_mtimes=ldpath_mtimes)
3416
		for data_cpuinfo in fd_cpuinfo.readlines():
3121
				if retval != os.EX_OK:
3417
			if data_cpuinfo.find("cpu MHz") > -1 :
3122
					return retval
3418
				cpu_count += 1
3123
				#need to check for errors
3419
		fd_cpuinfo.close()
3124
			if "--buildpkgonly" not in self.myopts:
3420
3125
				self.trees[x[1]]["vartree"].inject(x[2])
3421
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
3126
				myfavkey=portage.cpv_getkey(x[2])
3422
		if cpu_count == 0:
3127
				if "--fetchonly" not in self.myopts and \
3423
			cpu_count = 1
3128
					"--fetch-all-uri" not in self.myopts and \
3424
3129
					myfavkey in favorites:
3425
		spawnd_pkg = {}
3130
					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3426
		donec = 0
3131
					myfavdict=genericdict(myfavs)
3427
		failedc = 0
3132
					#don't record if already in system profile or already recorded
3428
		failedPkgs = []
3133
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3429
		logid_path = None
3134
						#we don't have a favorites entry for this package yet; add one
3430
		mylist = m_slots.keys()
3135
						myfavdict[myfavkey]=myfavkey
3431
		mylist.sort()
3136
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3432
		for x in mylist:
3137
						emergelog(xterm_titles, " === ("+\
3433
			# if slot is empty, go on
3138
							str(mergecount)+" of "+\
3434
			if not m_slots[x]:
3139
							str(len(mymergelist))+\
3435
				continue
3140
							") Updating world file ("+x[pkgindex]+")")
3141
						portage.write_atomic(
3142
						os.path.join(myroot, portage.WORLD_FILE),
3143
						"\n".join(myfavdict.values()))
3144
3145
				if "--pretend" not in self.myopts and \
3146
					"--fetchonly" not in self.myopts and \
3147
					"--fetch-all-uri" not in self.myopts:
3148
					# Clean the old package that we have merged over top of it.
3149
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3150
						xsplit=portage.pkgsplit(x[2])
3151
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3152
						retval = unmerge(pkgsettings, self.myopts, vartree,
3153
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3154
						if not retval:
3155
							emergelog(xterm_titles,
3156
								" --- AUTOCLEAN: Nothing unmerged.")
3157
					else:
3158
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
3159
							+ " AUTOCLEAN is disabled.  This can cause serious"
3160
							+ " problems due to overlapping packages.\n")
3161
3436
3162
					# Figure out if we need a restart.
3437
			# if previous slot failed, discontinue the emerge
3163
					mysplit=portage.pkgsplit(x[2])
3438
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
3164
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3439
				break
3165
						myver=mysplit[1]+"-"+mysplit[2]
3440
3166
						if myver[-3:]=='-r0':
3441
			# start multiple merges in parallel mode
3167
							myver=myver[:-3]
3442
			num_at_atime = cpu_count + 1
3168
						if (myver != portage.VERSION) and \
3443
3169
						   "livecvsportage" not in self.settings.features:
3444
			qsize = 0
3170
							if len(mymergelist) > mergecount:
3445
			for y in m_slots[x]:
3171
								emergelog(xterm_titles,
3446
				# these all can go in parallel, so fork one after the other
3172
									" ::: completed emerge ("+ \
3447
				# but num_at_atime at most
3173
									str(mergecount)+" of "+ \
3448
				if num_at_atime:
3174
									str(len(mymergelist))+") "+ \
3449
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3175
									x[2]+" to "+x[1])
3450
					spawnd_pids.append(onepid)
3176
								emergelog(xterm_titles, " *** RESTARTING " + \
3451
					spawnd_pkg[onepid] = (y[2], x)
3177
									"emerge via exec() after change of " + \
3452
					num_at_atime -= 1
3178
									"portage version.")
3453
					mergecount += 1
3179
								del mtimedb["resume"]["mergelist"][0]
3454
					qsize += 1
3455
				else:
3456
					self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3457
					# let's wait for one of the jobs to finish
3458
					onepid = -1
3459
					while onepid not in spawnd_pids:
3460
						onepid , retval = os.waitpid(-1, 0)
3461
					spawnd_pids.remove(onepid)
3462
3463
					pkg_compl = spawnd_pkg[onepid][0]
3464
					pkg_slot = spawnd_pkg[onepid][1]
3465
					del spawnd_pkg[onepid]
3466
3467
					# if it failed, I need to fail next slot but continue to merge all in this slot
3468
					if retval:
3469
						one_in_slot_failed = retval
3470
						failedc += 1
3471
						failedPkgs.append(pkg_compl)
3472
					else:
3473
						# unlink the logid_path
3474
						logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3475
						if os.path.exists(logid_path):
3476
							os.unlink(logid_path)
3477
						donec += 1
3478
						index = 0
3479
						print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3480
						# we need to remove this pkg from resume DB
3481
						# this is the dirtiest shit I have ever written
3482
						for pkgs in mymergelist:
3483
							if pkgs[2] == pkg_compl:
3484
								del mymergelist[index]
3485
								del mtimedb["resume"]["mergelist"][index]
3180
								mtimedb.commit()
3486
								mtimedb.commit()
3181
								portage.run_exitfuncs()
3487
								# check if we need to restart portage
3182
								mynewargv=[sys.argv[0],"--resume"]
3488
								mysplit=portage.pkgsplit(pkg_compl)
3183
								for myopt, myarg in self.myopts.iteritems():
3489
								if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3184
									if myopt not in bad_resume_opts:
3490
									self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3185
										if myarg is True:
3491
								break
3186
											mynewargv.append(myopt)
3492
							index += 1
3187
										else:
3493
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3188
											mynewargv.append(myopt +"="+ myarg)
3494
					spawnd_pids.append(onepid)
3189
								# priority only needs to be adjusted on the first run
3495
					spawnd_pkg[onepid] = (y[2], x)
3190
								os.environ["PORTAGE_NICENESS"] = "0"
3496
					mergecount += 1
3191
								os.execv(mynewargv[0], mynewargv)
3497
3498
			# this slot is exhausted, so wait for all of the forks to finish
3499
			while spawnd_pids:
3500
				self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3501
				onepid = -1
3502
				while onepid not in spawnd_pids:
3503
					onepid , retval = os.waitpid(-1, 0)
3504
				spawnd_pids.remove(onepid)
3505
				pkg_compl = spawnd_pkg[onepid][0]
3506
				pkg_slot = spawnd_pkg[onepid][1]
3507
				del spawnd_pkg[onepid]
3508
3509
				qsize -= 1
3510
				if retval:
3511
					one_in_slot_failed = retval
3512
					failedc += 1
3513
					failedPkgs.append(pkg_compl)
3514
				else:
3515
					# unlink the logid_path
3516
					logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3517
					if os.path.exists(logid_path):
3518
						os.unlink(logid_path)
3519
					donec += 1
3520
					index = 0
3521
					print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3522
					# we need to remove this pkg from resume DB
3523
					# this is the dirtiest shit I have ever written
3524
					for pkgs in mymergelist:
3525
						if pkgs[2] == pkg_compl:
3526
							del mymergelist[index]
3527
							del mtimedb["resume"]["mergelist"][index]
3528
							mtimedb.commit()
3529
							# check if we need to restart portage
3530
							mysplit=portage.pkgsplit(pkg_compl)
3531
							if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3532
								self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3533
							break
3534
						index += 1
3192
3535
3193
			if "--pretend" not in self.myopts and \
3536
		self.print_status(totalcount, donec, qsize, failedc, None, failedPkgs)
3194
				"--fetchonly" not in self.myopts and \
3195
				"--fetch-all-uri" not in self.myopts:
3196
				if "noclean" not in self.settings.features:
3197
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
3198
						(mergecount, len(mymergelist), x[pkgindex])
3199
					emergelog(xterm_titles, (" === (%s of %s) " + \
3200
						"Post-Build Cleaning (%s::%s)") % \
3201
						(mergecount, len(mymergelist), x[pkgindex], y),
3202
						short_msg=short_msg)
3203
				emergelog(xterm_titles, " ::: completed emerge ("+\
3204
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
3205
					x[2]+" to "+x[1])
3206
3537
3207
			# Unsafe for parallel merges
3538
		if one_in_slot_failed:
3208
			del mtimedb["resume"]["mergelist"][0]
3539
			portage.writemsg_stdout(red("\nSome packages failed to emerge, summary follows:\n"))
3209
			# Commit after each merge so that --resume may still work in
3540
3210
			# in the event that portage is not allowed to exit normally
3541
		for pkgs in failedPkgs:
3211
			# due to power failure, SIGKILL, etc...
3542
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3212
			mtimedb.commit()
3543
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
3544
				sys.exit(1)
3545
3546
			portage.writemsg_stdout(red("\nPackage "+pkgs+" failed to emerge\n"))
3547
			logfile = None
3548
			if "PORT_LOGDIR" in self.settings:
3549
				port_logdir = self.settings["PORT_LOGDIR"]
3550
			else:
3551
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3552
3553
			pkg_cat = pkgs.split("/")[0]
3554
			pkg_pf = pkgs.split("/")[1]
3555
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
3556
			if os.path.exists(logid_path):
3557
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
3558
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3559
					(pkg_cat, pkg_pf, logid_time))
3560
				del logid_time
3561
3562
			if logfile and os.path.exists(logfile):
3563
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
3564
3565
			if logfile and os.path.exists(logfile):
3566
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
3567
				os.unlink(logid_path)
3568
		if one_in_slot_failed:
3569
			sys.exit(1)
3213
3570
3214
		if "--pretend" not in self.myopts:
3571
		if "--pretend" not in self.myopts:
3215
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3572
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
Lines 3219-3238 Link Here
3219
			del mtimedb["resume"]
3576
			del mtimedb["resume"]
3220
		mtimedb.commit()
3577
		mtimedb.commit()
3221
3578
3222
		#by doing an exit this way, --fetchonly can continue to try to
3223
		#fetch everything even if a particular download fails.
3224
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3579
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3225
			if failed_fetches:
3580
			sys.exit(0)
3226
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
3581
3227
					"encountered.  Please see above for details.\n\n")
3228
				for cpv in failed_fetches:
3229
					sys.stderr.write("   ")
3230
					sys.stderr.write(cpv)
3231
					sys.stderr.write("\n")
3232
				sys.stderr.write("\n")
3233
				sys.exit(1)
3234
			else:
3235
				sys.exit(0)
3236
		return os.EX_OK
3582
		return os.EX_OK
3237
3583
3238
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3584
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
Lines 3673-3679 Link Here
3673
def validate_merge_list(trees, mergelist):
4019
def validate_merge_list(trees, mergelist):
3674
	"""Validate the list to make sure all the packages are still available.
4020
	"""Validate the list to make sure all the packages are still available.
3675
	This is needed for --resume."""
4021
	This is needed for --resume."""
3676
	for (pkg_type, myroot, pkg_key, action) in mergelist:
4022
	for (pkg_type, myroot, pkg_key, action, merge_slot) in mergelist:
3677
		if pkg_type == "binary" and \
4023
		if pkg_type == "binary" and \
3678
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4024
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3679
			pkg_type == "ebuild" and \
4025
			pkg_type == "ebuild" and \
Lines 4518-4524 Link Here
4518
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4864
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4519
		emergelog(xterm_titles, " >>> depclean")
4865
		emergelog(xterm_titles, " >>> depclean")
4520
4866
4521
	if "--quiet" not in myopts:
4867
	if "--quiet" not in myopts and "--nodeps" not in myopts:
4522
		print "\nCalculating dependencies  ",
4868
		print "\nCalculating dependencies  ",
4523
4869
4524
	soft = 0
4870
	soft = 0
Lines 4615-4620 Link Here
4615
	else:
4961
	else:
4616
		print "Number removed:       "+str(len(cleanlist))
4962
		print "Number removed:       "+str(len(cleanlist))
4617
4963
4964
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
4965
	merge_slots = {}
4966
	for pkg in mergelist:
4967
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
4968
			slot = int(pkg[4])
4969
			try:
4970
				if pkg not in merge_slots[slot]:
4971
					merge_slots[slot].append(pkg)
4972
			except KeyError:
4973
				merge_slots[slot] = [pkg]
4974
	# print the merge slots
4975
	max_slot = 0
4976
	mylist = merge_slots.keys()
4977
	mylist.sort()
4978
	for x in mylist:
4979
		if x > max_slot:
4980
			max_slot = x
4981
		if parallel:
4982
			print "Package list for slot = "+str(x)
4983
			for y in merge_slots[x]:
4984
				print "	",y
4985
	if printonly:
4986
		return
4987
4988
	# make one last pass at the merge_slots and initialize the missing slots to None
4989
	x = 0
4990
	while x < max_slot:
4991
		if x not in merge_slots.keys():
4992
			merge_slots[x] = None
4993
		x += 1
4994
	return merge_slots
4995
4618
def action_build(settings, trees, mtimedb,
4996
def action_build(settings, trees, mtimedb,
4619
	myopts, myaction, myfiles, spinner):
4997
	myopts, myaction, myfiles, spinner):
4620
	ldpath_mtimes = mtimedb["ldpath"]
4998
	ldpath_mtimes = mtimedb["ldpath"]
Lines 4722-4734 Link Here
4722
			if len(mymergelist) == 0:
5100
			if len(mymergelist) == 0:
4723
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5101
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4724
				sys.exit(0)
5102
				sys.exit(0)
5103
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4725
			mydepgraph.display(mymergelist)
5104
			mydepgraph.display(mymergelist)
4726
			prompt="Would you like to resume merging these packages?"
5105
			prompt="Would you like to resume merging these packages?"
4727
		else:
5106
		else:
4728
			mydepgraph.display(
5107
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
4729
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5108
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5109
			mydepgraph.display(mymergelist)
4730
			mergecount=0
5110
			mergecount=0
4731
			for x in mydepgraph.altlist():
5111
			for x in mymergelist:
4732
				if x[0] != "blocks" and x[3] != "nomerge":
5112
				if x[0] != "blocks" and x[3] != "nomerge":
4733
					mergecount+=1
5113
					mergecount+=1
4734
				#check for blocking dependencies
5114
				#check for blocking dependencies
Lines 4773-4782 Link Here
4773
			if len(mymergelist) == 0:
5153
			if len(mymergelist) == 0:
4774
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5154
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4775
				sys.exit(0)
5155
				sys.exit(0)
5156
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4776
			mydepgraph.display(mymergelist)
5157
			mydepgraph.display(mymergelist)
4777
		else:
5158
		else:
4778
			mydepgraph.display(
5159
			# mydepgraph.digraph.debug_print()
4779
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5160
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5161
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5162
			mydepgraph.display(mymergelist)
4780
	else:
5163
	else:
4781
		if ("--buildpkgonly" in myopts):
5164
		if ("--buildpkgonly" in myopts):
4782
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5165
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
Lines 4792-4814 Link Here
4792
				it to write the mtimedb"""
5175
				it to write the mtimedb"""
4793
				mtimedb.filename = None
5176
				mtimedb.filename = None
4794
				time.sleep(3) # allow the parent to have first fetch
5177
				time.sleep(3) # allow the parent to have first fetch
5178
			mymergelist = mtimedb["resume"]["mergelist"]
5179
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
4795
			del mydepgraph
5180
			del mydepgraph
4796
			retval = mergetask.merge(
5181
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
4797
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
4798
			if retval != os.EX_OK:
5182
			if retval != os.EX_OK:
4799
				sys.exit(retval)
5183
				sys.exit(retval)
4800
		else:
5184
		else:
4801
			if "resume" in mtimedb and \
5185
			mymergelist = mydepgraph.altlist()
4802
			"mergelist" in mtimedb["resume"] and \
5186
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
4803
			len(mtimedb["resume"]["mergelist"]) > 1:
5187
			if "--nodeps" not in myopts or len(mymergelist) > 1:
4804
				mtimedb["resume_backup"] = mtimedb["resume"]
5188
				if "resume" in mtimedb and \
4805
				del mtimedb["resume"]
5189
				"mergelist" in mtimedb["resume"] and \
4806
				mtimedb.commit()
5190
				len(mtimedb["resume"]["mergelist"]) > 1:
4807
			mtimedb["resume"]={}
5191
					mtimedb["resume_backup"] = mtimedb["resume"]
4808
			# XXX: Stored as a list for backward compatibility.
5192
					del mtimedb["resume"]
4809
			mtimedb["resume"]["myopts"] = \
5193
					mtimedb.commit()
4810
				[k for k in myopts if myopts[k] is True]
5194
				mtimedb["resume"]={}
4811
			mtimedb["resume"]["favorites"]=favorites
5195
				# XXX: Stored as a list for backward compatibility.
5196
				mtimedb["resume"]["myopts"] = \
5197
					[k for k in myopts if myopts[k] is True]
5198
				mtimedb["resume"]["favorites"]=favorites
4812
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5199
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4813
				for pkgline in mydepgraph.altlist():
5200
				for pkgline in mydepgraph.altlist():
4814
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5201
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 4824-4841 Link Here
4824
							tree="porttree")
5211
							tree="porttree")
4825
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5212
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4826
				pkglist = []
5213
				pkglist = []
4827
				for pkg in mydepgraph.altlist():
5214
				for pkg in mymergelist:
4828
					if pkg[0] != "blocks":
5215
					if pkg[0] != "blocks":
4829
						pkglist.append(pkg)
5216
						pkglist.append(pkg)
4830
			else:
5217
			else:
4831
				pkglist = mydepgraph.altlist()
5218
				pkglist = mymergelist
4832
			del mydepgraph
5219
			del mydepgraph
4833
			mergetask = MergeTask(settings, trees, myopts)
5220
			mergetask = MergeTask(settings, trees, myopts)
4834
			retval = mergetask.merge(pkglist, favorites, mtimedb)
5221
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
4835
			if retval != os.EX_OK:
5222
			if retval != os.EX_OK:
4836
				sys.exit(retval)
5223
				sys.exit(retval)
4837
5224
4838
		if mtimedb.has_key("resume"):
5225
		if mtimedb.has_key("resume") and ("--nodeps" not in myopts or len(mymergelist) > 1):
4839
			del mtimedb["resume"]
5226
			del mtimedb["resume"]
4840
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5227
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4841
			print ">>> Auto-cleaning packages..."
5228
			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 3218-3223 Link Here
3218
	if mysettings.get("PORT_LOGDIR", "") == "":
3231
	if mysettings.get("PORT_LOGDIR", "") == "":
3219
		while "PORT_LOGDIR" in mysettings:
3232
		while "PORT_LOGDIR" in mysettings:
3220
			del mysettings["PORT_LOGDIR"]
3233
			del mysettings["PORT_LOGDIR"]
3234
3235
	if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
3236
		mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + DEF_LOGDIR
3237
3221
	if "PORT_LOGDIR" in mysettings:
3238
	if "PORT_LOGDIR" in mysettings:
3222
		try:
3239
		try:
3223
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
3240
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
Lines 3230-3236 Link Here
3230
			while "PORT_LOGDIR" in mysettings:
3247
			while "PORT_LOGDIR" in mysettings:
3231
				del mysettings["PORT_LOGDIR"]
3248
				del mysettings["PORT_LOGDIR"]
3232
	if "PORT_LOGDIR" in mysettings:
3249
	if "PORT_LOGDIR" in mysettings:
3233
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
3250
		logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
3234
		if not os.path.exists(logid_path):
3251
		if not os.path.exists(logid_path):
3235
			f = open(logid_path, "w")
3252
			f = open(logid_path, "w")
3236
			f.close()
3253
			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