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 / +697 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 wait_one_emerge(self, spawnd_pids, spawnd_pkg, mymergelist, mtimedb):
3234
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3235
		# let's wait for one of the jobs to finish
3236
		onepid = -1
3237
		while onepid not in spawnd_pids:
3238
			onepid , retval = os.waitpid(-1, 0)
3239
		spawnd_pids.remove(onepid)
3240
3241
		pkg_compl = spawnd_pkg[onepid][0]
3242
		pkg_slot = spawnd_pkg[onepid][1]
3243
		del spawnd_pkg[onepid]
3244
3245
		if not retval:
3246
			# unlink the logid_path
3247
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3248
			if os.path.exists(logid_path):
3249
				os.unlink(logid_path)
3250
			index = 0
3251
			print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3252
			# we need to remove this pkg from resume DB
3253
			# this is the dirtiest shit I have ever written
3254
			for pkgs in mymergelist:
3255
				if pkgs[2] == pkg_compl:
3256
					del mymergelist[index]
3257
					del mtimedb["resume"]["mergelist"][index]
3258
					mtimedb.commit()
3259
					# check if we need to restart portage
3260
					mysplit=portage.pkgsplit(pkg_compl)
3261
					if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3262
						self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3263
					break
3264
				index += 1
3265
		return (retval, pkg_compl)
3266
3267
	def merge(self, mylist, favorites, mtimedb, m_slots):
2838
		failed_fetches = []
3268
		failed_fetches = []
2839
		mymergelist=[]
3269
		mymergelist=[]
2840
		ldpath_mtimes = mtimedb["ldpath"]
3270
		ldpath_mtimes = mtimedb["ldpath"]
2841
		xterm_titles = "notitles" not in self.settings.features
3271
		xterm_titles = "notitles" not in self.settings.features
3272
		parallel = "parallel" in self.settings.features
3273
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3274
3275
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3276
		if self.edebug or "--fetchonly" in self.myopts:
3277
			parallel = False
2842
3278
2843
		#check for blocking dependencies
3279
		#check for blocking dependencies
2844
		if "--fetchonly" not in self.myopts and \
3280
		if "--fetchonly" not in self.myopts and \
Lines 2861-2868 Link Here
2861
		mysysdict = genericdict(getlist(self.settings, "system"))
3297
		mysysdict = genericdict(getlist(self.settings, "system"))
2862
		if "--resume" in self.myopts:
3298
		if "--resume" in self.myopts:
2863
			# We're resuming.
3299
			# We're resuming.
2864
			print colorize("GOOD", "*** Resuming merge...")
2865
			emergelog(xterm_titles, " *** Resuming merge...")
2866
			mymergelist=mtimedb["resume"]["mergelist"][:]
3300
			mymergelist=mtimedb["resume"]["mergelist"][:]
2867
			if "--skipfirst" in self.myopts and mymergelist:
3301
			if "--skipfirst" in self.myopts and mymergelist:
2868
				del mtimedb["resume"]["mergelist"][0]
3302
				del mtimedb["resume"]["mergelist"][0]
Lines 2896-2903 Link Here
2896
					os.path.join(self.target_root, portage.WORLD_FILE),
3330
					os.path.join(self.target_root, portage.WORLD_FILE),
2897
					"\n".join(myfavdict.values()))
3331
					"\n".join(myfavdict.values()))
2898
3332
2899
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3333
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
2900
			mtimedb.commit()
3334
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3335
				mtimedb.commit()
3336
3337
		totalcount = len(mymergelist)
3338
		mergecount=1
3339
3340
		if "--resume" in self.myopts and "--fetchonly" not in self.myopts:
3341
			# We're resuming.
3342
			print colorize("GOOD", "*** Resuming merge...")
3343
			emergelog(xterm_titles, " *** Resuming merge...")
2901
3344
2902
		myfeat = self.settings.features[:]
3345
		myfeat = self.settings.features[:]
2903
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3346
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 2915-2926 Link Here
2915
				print ">>> starting parallel fetching"
3358
				print ">>> starting parallel fetching"
2916
				fetch_log = "/var/log/emerge-fetch.log"
3359
				fetch_log = "/var/log/emerge-fetch.log"
2917
				logfile = open(fetch_log, "w")
3360
				logfile = open(fetch_log, "w")
2918
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3361
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
2919
				portage_util.apply_secpass_permissions(fetch_log,
3362
				portage_util.apply_secpass_permissions(fetch_log,
2920
					uid=portage.portage_uid, gid=portage.portage_gid,
3363
					uid=portage.portage_uid, gid=portage.portage_gid,
2921
					mode=0660)
3364
					mode=0660)
2922
				fetch_env = os.environ.copy()
3365
				fetch_env = os.environ.copy()
2923
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3366
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
2924
				fetch_env["PORTAGE_NICENESS"] = "0"
3367
				fetch_env["PORTAGE_NICENESS"] = "0"
2925
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3368
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2926
				for myopt, myarg in self.myopts.iteritems():
3369
				for myopt, myarg in self.myopts.iteritems():
Lines 2933-3215 Link Here
2933
					fd_pipes=fd_pipes, returnpid=True)
3376
					fd_pipes=fd_pipes, returnpid=True)
2934
				logfile.close() # belongs to the spawned process
3377
				logfile.close() # belongs to the spawned process
2935
3378
2936
		mergecount=0
3379
		if not parallel:
2937
		for x in mymergelist:
3380
			failed_fetches = []
2938
			mergecount+=1
3381
			for x in mymergelist:
2939
			myroot=x[1]
3382
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, mysysdict)
2940
			pkg_key = x[2]
3383
				mergecount += 1
2941
			pkgindex=2
3384
2942
			portdb = self.trees[myroot]["porttree"].dbapi
3385
				# need to short circuit the spawn with --nodeps
2943
			bindb  = self.trees[myroot]["bintree"].dbapi
3386
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
2944
			vartree = self.trees[myroot]["vartree"]
3387
					if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
2945
			pkgsettings = self.pkgsettings[myroot]
3388
						continue
2946
			if x[0]=="blocks":
3389
					if retcode != os.EX_OK:
2947
				pkgindex=3
3390
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
2948
			y = portdb.findname(pkg_key)
3391
							failed_fetches.append(x[2])
2949
			if "--pretend" not in self.myopts:
3392
							continue
2950
				print "\n>>> Emerging (" + \
3393
						else:
2951
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3394
							return retcode
2952
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3395
					# Unsafe for parallel merges
2953
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
3396
					del mtimedb["resume"]["mergelist"][0]
2954
				emergelog(xterm_titles, " >>> emerge ("+\
3397
					# Commit after each merge so that --resume may still work in
2955
					str(mergecount)+" of "+str(len(mymergelist))+\
3398
					# in the event that portage is not allowed to exit normally
2956
					") "+x[pkgindex]+" to "+x[1])
3399
					# due to power failure, SIGKILL, etc...
3400
					mtimedb.commit()
3401
3402
					# unlink the logid_path if any exists
3403
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
3404
					if os.path.exists(logid_path):
3405
						os.unlink(logid_path)
3406
					del logid_path
2957
3407
2958
			pkgsettings["EMERGE_FROM"] = x[0]
3408
					# check if we need to restart portage
2959
			pkgsettings.backup_changes("EMERGE_FROM")
3409
					mysplit=portage.pkgsplit(x[2])
2960
			pkgsettings.reset()
3410
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3411
							self.restart_portage(x, mergecount, totalcount, mtimedb)
2961
3412
2962
			#buildsyspkg: Check if we need to _force_ binary package creation
3413
				else:
2963
			issyspkg = ("buildsyspkg" in myfeat) \
3414
					if retcode != os.EX_OK:
2964
					and x[0] != "blocks" \
3415
						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:
3416
					else:
2978
						retval = portage.doebuild(y, "fetch", myroot,
3417
						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
3418
2989
				portage.doebuild_environment(y, "setup", myroot,
3419
			if "--pretend" not in self.myopts:
2990
					pkgsettings, self.edebug, 1, portdb)
3420
				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
3421
3109
				if "--fetchonly" in self.myopts or \
3422
			# We're out of the loop... We're done. Delete the resume data.
3110
					"--fetch-all-uri" in self.myopts:
3423
			if mtimedb.has_key("resume"):
3111
					continue
3424
				del mtimedb["resume"]
3425
			mtimedb.commit()
3426
			
3427
			#by doing an exit this way, --fetchonly can continue to try to
3428
			#fetch everything even if a particular download fails.
3429
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3430
				if failed_fetches:
3431
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
3432
						"encountered.  Please see above for details.\n\n")
3433
					for cpv in failed_fetches:
3434
						sys.stderr.write("   ")
3435
						sys.stderr.write(cpv)
3436
						sys.stderr.write("\n")
3437
					sys.stderr.write("\n")
3438
					sys.exit(1)
3439
				else:
3440
					sys.exit(0)
3441
			return os.EX_OK
3112
3442
3113
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3443
		# parallel code - dirty starts here...;-)
3114
				emergelog(xterm_titles, " === ("+str(mergecount)+\
3444
		one_in_slot_failed=0
3115
					" of "+str(len(mymergelist))+") Merging Binary ("+\
3445
		spawnd_pids=[]
3116
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3446
3117
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3447
		# dirty little trick to get number of cpus from the system
3118
					mydbapi=bindb,
3448
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
3119
					vartree=self.trees[myroot]["vartree"],
3449
		cpu_count = 0
3120
					prev_mtimes=ldpath_mtimes)
3450
		for data_cpuinfo in fd_cpuinfo.readlines():
3121
				if retval != os.EX_OK:
3451
			if data_cpuinfo.find("cpu MHz") > -1 :
3122
					return retval
3452
				cpu_count += 1
3123
				#need to check for errors
3453
		fd_cpuinfo.close()
3124
			if "--buildpkgonly" not in self.myopts:
3454
3125
				self.trees[x[1]]["vartree"].inject(x[2])
3455
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
3126
				myfavkey=portage.cpv_getkey(x[2])
3456
		if cpu_count == 0:
3127
				if "--fetchonly" not in self.myopts and \
3457
			cpu_count = 1
3128
					"--fetch-all-uri" not in self.myopts and \
3458
3129
					myfavkey in favorites:
3459
		spawnd_pkg = {}
3130
					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3460
		donec = 0
3131
					myfavdict=genericdict(myfavs)
3461
		failedc = 0
3132
					#don't record if already in system profile or already recorded
3462
		failedPkgs = []
3133
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3463
		logid_path = None
3134
						#we don't have a favorites entry for this package yet; add one
3464
		mylist = m_slots.keys()
3135
						myfavdict[myfavkey]=myfavkey
3465
		mylist.sort()
3136
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3466
		for x in mylist:
3137
						emergelog(xterm_titles, " === ("+\
3467
			# if slot is empty, go on
3138
							str(mergecount)+" of "+\
3468
			if not m_slots[x]:
3139
							str(len(mymergelist))+\
3469
				continue
3140
							") Updating world file ("+x[pkgindex]+")")
3470
3141
						portage.write_atomic(
3471
			# if previous slot failed, discontinue the emerge
3142
						os.path.join(myroot, portage.WORLD_FILE),
3472
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
3143
						"\n".join(myfavdict.values()))
3473
				break
3144
3474
3145
				if "--pretend" not in self.myopts and \
3475
			# start multiple merges in parallel mode
3146
					"--fetchonly" not in self.myopts and \
3476
			num_at_atime = cpu_count + 1
3147
					"--fetch-all-uri" not in self.myopts:
3477
3148
					# Clean the old package that we have merged over top of it.
3478
			qsize = 0
3149
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3479
			for y in m_slots[x]:
3150
						xsplit=portage.pkgsplit(x[2])
3480
				# these all can go in parallel, so fork one after the other
3151
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3481
				# but num_at_atime at most
3152
						retval = unmerge(pkgsettings, self.myopts, vartree,
3482
				if num_at_atime:
3153
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3483
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3154
						if not retval:
3484
					spawnd_pids.append(onepid)
3155
							emergelog(xterm_titles,
3485
					spawnd_pkg[onepid] = (y[2], x)
3156
								" --- AUTOCLEAN: Nothing unmerged.")
3486
					num_at_atime -= 1
3487
					mergecount += 1
3488
					qsize += 1
3489
				else:
3490
					self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3491
					# let's wait for one of the jobs to finish
3492
					(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mymergelist, mtimedb)
3493
3494
					# if it failed, I need to fail next slot but continue to merge all in this slot
3495
					if retval:
3496
						one_in_slot_failed = retval
3497
						failedc += 1
3498
						failedPkgs.append(pkg_compl)
3157
					else:
3499
					else:
3158
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
3500
						donec += 1
3159
							+ " AUTOCLEAN is disabled.  This can cause serious"
3501
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3160
							+ " problems due to overlapping packages.\n")
3502
					spawnd_pids.append(onepid)
3503
					spawnd_pkg[onepid] = (y[2], x)
3504
					mergecount += 1
3505
3506
			# this slot is exhausted, so wait for all of the forks to finish
3507
			while spawnd_pids:
3508
				self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3509
				# let's wait for one of the jobs to finish
3510
				(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mymergelist, mtimedb)
3511
3512
				qsize -= 1
3513
				if retval:
3514
					one_in_slot_failed = retval
3515
					failedc += 1
3516
					failedPkgs.append(pkg_compl)
3517
				else:
3518
					donec += 1
3161
3519
3162
					# Figure out if we need a restart.
3520
		self.print_status(totalcount, donec, qsize, failedc, None, failedPkgs)
3163
					mysplit=portage.pkgsplit(x[2])
3164
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3165
						myver=mysplit[1]+"-"+mysplit[2]
3166
						if myver[-3:]=='-r0':
3167
							myver=myver[:-3]
3168
						if (myver != portage.VERSION) and \
3169
						   "livecvsportage" not in self.settings.features:
3170
							if len(mymergelist) > mergecount:
3171
								emergelog(xterm_titles,
3172
									" ::: completed emerge ("+ \
3173
									str(mergecount)+" of "+ \
3174
									str(len(mymergelist))+") "+ \
3175
									x[2]+" to "+x[1])
3176
								emergelog(xterm_titles, " *** RESTARTING " + \
3177
									"emerge via exec() after change of " + \
3178
									"portage version.")
3179
								del mtimedb["resume"]["mergelist"][0]
3180
								mtimedb.commit()
3181
								portage.run_exitfuncs()
3182
								mynewargv=[sys.argv[0],"--resume"]
3183
								for myopt, myarg in self.myopts.iteritems():
3184
									if myopt not in bad_resume_opts:
3185
										if myarg is True:
3186
											mynewargv.append(myopt)
3187
										else:
3188
											mynewargv.append(myopt +"="+ myarg)
3189
								# priority only needs to be adjusted on the first run
3190
								os.environ["PORTAGE_NICENESS"] = "0"
3191
								os.execv(mynewargv[0], mynewargv)
3192
3521
3193
			if "--pretend" not in self.myopts and \
3522
		if one_in_slot_failed:
3194
				"--fetchonly" not in self.myopts and \
3523
			portage.writemsg_stdout(red("\nSome packages failed to emerge, summary follows:\n"))
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
3524
3207
			# Unsafe for parallel merges
3525
		for pkgs in failedPkgs:
3208
			del mtimedb["resume"]["mergelist"][0]
3526
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3209
			# Commit after each merge so that --resume may still work in
3527
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
3210
			# in the event that portage is not allowed to exit normally
3528
				sys.exit(1)
3211
			# due to power failure, SIGKILL, etc...
3529
3212
			mtimedb.commit()
3530
			portage.writemsg_stdout(red("\nPackage "+pkgs+" failed to emerge\n"))
3531
			logfile = None
3532
			if "PORT_LOGDIR" in self.settings:
3533
				port_logdir = self.settings["PORT_LOGDIR"]
3534
			else:
3535
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3536
3537
			pkg_cat = pkgs.split("/")[0]
3538
			pkg_pf = pkgs.split("/")[1]
3539
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
3540
			if os.path.exists(logid_path):
3541
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
3542
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3543
					(pkg_cat, pkg_pf, logid_time))
3544
				del logid_time
3545
3546
			if logfile and os.path.exists(logfile):
3547
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
3548
3549
			if logfile and os.path.exists(logfile):
3550
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
3551
				os.unlink(logid_path)
3552
		if one_in_slot_failed:
3553
			sys.exit(1)
3213
3554
3214
		if "--pretend" not in self.myopts:
3555
		if "--pretend" not in self.myopts:
3215
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3556
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
Lines 3219-3238 Link Here
3219
			del mtimedb["resume"]
3560
			del mtimedb["resume"]
3220
		mtimedb.commit()
3561
		mtimedb.commit()
3221
3562
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:
3563
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3225
			if failed_fetches:
3564
			sys.exit(0)
3226
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
3565
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
3566
		return os.EX_OK
3237
3567
3238
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3568
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
Lines 3673-3679 Link Here
3673
def validate_merge_list(trees, mergelist):
4003
def validate_merge_list(trees, mergelist):
3674
	"""Validate the list to make sure all the packages are still available.
4004
	"""Validate the list to make sure all the packages are still available.
3675
	This is needed for --resume."""
4005
	This is needed for --resume."""
3676
	for (pkg_type, myroot, pkg_key, action) in mergelist:
4006
	for (pkg_type, myroot, pkg_key, action, merge_slot) in mergelist:
3677
		if pkg_type == "binary" and \
4007
		if pkg_type == "binary" and \
3678
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4008
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3679
			pkg_type == "ebuild" and \
4009
			pkg_type == "ebuild" and \
Lines 4519-4525 Link Here
4519
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4849
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4520
		emergelog(xterm_titles, " >>> depclean")
4850
		emergelog(xterm_titles, " >>> depclean")
4521
4851
4522
	if "--quiet" not in myopts:
4852
	if "--quiet" not in myopts and "--nodeps" not in myopts:
4523
		print "\nCalculating dependencies  ",
4853
		print "\nCalculating dependencies  ",
4524
4854
4525
	soft = 0
4855
	soft = 0
Lines 4616-4621 Link Here
4616
	else:
4946
	else:
4617
		print "Number removed:       "+str(len(cleanlist))
4947
		print "Number removed:       "+str(len(cleanlist))
4618
4948
4949
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
4950
	merge_slots = {}
4951
	for pkg in mergelist:
4952
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
4953
			slot = int(pkg[4])
4954
			try:
4955
				if pkg not in merge_slots[slot]:
4956
					merge_slots[slot].append(pkg)
4957
			except KeyError:
4958
				merge_slots[slot] = [pkg]
4959
	# print the merge slots
4960
	max_slot = 0
4961
	mylist = merge_slots.keys()
4962
	mylist.sort()
4963
	for x in mylist:
4964
		if x > max_slot:
4965
			max_slot = x
4966
		if parallel:
4967
			print "Package list for slot = "+str(x)
4968
			for y in merge_slots[x]:
4969
				print "	",y
4970
	if printonly:
4971
		return
4972
4973
	# make one last pass at the merge_slots and initialize the missing slots to None
4974
	x = 0
4975
	while x < max_slot:
4976
		if x not in merge_slots.keys():
4977
			merge_slots[x] = None
4978
		x += 1
4979
	return merge_slots
4980
4619
def action_build(settings, trees, mtimedb,
4981
def action_build(settings, trees, mtimedb,
4620
	myopts, myaction, myfiles, spinner):
4982
	myopts, myaction, myfiles, spinner):
4621
	ldpath_mtimes = mtimedb["ldpath"]
4983
	ldpath_mtimes = mtimedb["ldpath"]
Lines 4723-4735 Link Here
4723
			if len(mymergelist) == 0:
5085
			if len(mymergelist) == 0:
4724
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5086
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4725
				sys.exit(0)
5087
				sys.exit(0)
5088
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4726
			mydepgraph.display(mymergelist)
5089
			mydepgraph.display(mymergelist)
4727
			prompt="Would you like to resume merging these packages?"
5090
			prompt="Would you like to resume merging these packages?"
4728
		else:
5091
		else:
4729
			mydepgraph.display(
5092
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
4730
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5093
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5094
			mydepgraph.display(mymergelist)
4731
			mergecount=0
5095
			mergecount=0
4732
			for x in mydepgraph.altlist():
5096
			for x in mymergelist:
4733
				if x[0] != "blocks" and x[3] != "nomerge":
5097
				if x[0] != "blocks" and x[3] != "nomerge":
4734
					mergecount+=1
5098
					mergecount+=1
4735
				#check for blocking dependencies
5099
				#check for blocking dependencies
Lines 4774-4783 Link Here
4774
			if len(mymergelist) == 0:
5138
			if len(mymergelist) == 0:
4775
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5139
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4776
				sys.exit(0)
5140
				sys.exit(0)
5141
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4777
			mydepgraph.display(mymergelist)
5142
			mydepgraph.display(mymergelist)
4778
		else:
5143
		else:
4779
			mydepgraph.display(
5144
			# mydepgraph.digraph.debug_print()
4780
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5145
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5146
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5147
			mydepgraph.display(mymergelist)
4781
	else:
5148
	else:
4782
		if ("--buildpkgonly" in myopts):
5149
		if ("--buildpkgonly" in myopts):
4783
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5150
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
Lines 4793-4815 Link Here
4793
				it to write the mtimedb"""
5160
				it to write the mtimedb"""
4794
				mtimedb.filename = None
5161
				mtimedb.filename = None
4795
				time.sleep(3) # allow the parent to have first fetch
5162
				time.sleep(3) # allow the parent to have first fetch
5163
			mymergelist = mtimedb["resume"]["mergelist"]
5164
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
4796
			del mydepgraph
5165
			del mydepgraph
4797
			retval = mergetask.merge(
5166
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
4798
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
4799
			if retval != os.EX_OK:
5167
			if retval != os.EX_OK:
4800
				sys.exit(retval)
5168
				sys.exit(retval)
4801
		else:
5169
		else:
4802
			if "resume" in mtimedb and \
5170
			mymergelist = mydepgraph.altlist()
4803
			"mergelist" in mtimedb["resume"] and \
5171
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
4804
			len(mtimedb["resume"]["mergelist"]) > 1:
5172
			if "--nodeps" not in myopts or len(mymergelist) > 1:
4805
				mtimedb["resume_backup"] = mtimedb["resume"]
5173
				if "resume" in mtimedb and \
4806
				del mtimedb["resume"]
5174
				"mergelist" in mtimedb["resume"] and \
4807
				mtimedb.commit()
5175
				len(mtimedb["resume"]["mergelist"]) > 1:
4808
			mtimedb["resume"]={}
5176
					mtimedb["resume_backup"] = mtimedb["resume"]
4809
			# XXX: Stored as a list for backward compatibility.
5177
					del mtimedb["resume"]
4810
			mtimedb["resume"]["myopts"] = \
5178
					mtimedb.commit()
4811
				[k for k in myopts if myopts[k] is True]
5179
				mtimedb["resume"]={}
4812
			mtimedb["resume"]["favorites"]=favorites
5180
				# XXX: Stored as a list for backward compatibility.
5181
				mtimedb["resume"]["myopts"] = \
5182
					[k for k in myopts if myopts[k] is True]
5183
				mtimedb["resume"]["favorites"]=favorites
4813
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5184
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4814
				for pkgline in mydepgraph.altlist():
5185
				for pkgline in mydepgraph.altlist():
4815
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5186
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 4825-4842 Link Here
4825
							tree="porttree")
5196
							tree="porttree")
4826
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5197
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4827
				pkglist = []
5198
				pkglist = []
4828
				for pkg in mydepgraph.altlist():
5199
				for pkg in mymergelist:
4829
					if pkg[0] != "blocks":
5200
					if pkg[0] != "blocks":
4830
						pkglist.append(pkg)
5201
						pkglist.append(pkg)
4831
			else:
5202
			else:
4832
				pkglist = mydepgraph.altlist()
5203
				pkglist = mymergelist
4833
			del mydepgraph
5204
			del mydepgraph
4834
			mergetask = MergeTask(settings, trees, myopts)
5205
			mergetask = MergeTask(settings, trees, myopts)
4835
			retval = mergetask.merge(pkglist, favorites, mtimedb)
5206
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
4836
			if retval != os.EX_OK:
5207
			if retval != os.EX_OK:
4837
				sys.exit(retval)
5208
				sys.exit(retval)
4838
5209
4839
		if mtimedb.has_key("resume"):
5210
		if mtimedb.has_key("resume") and ("--nodeps" not in myopts or len(mymergelist) > 1):
4840
			del mtimedb["resume"]
5211
			del mtimedb["resume"]
4841
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5212
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4842
			print ">>> Auto-cleaning packages..."
5213
			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 2192-2210 Link Here
2192
	mypids = []
2192
	mypids = []
2193
	pw = None
2193
	pw = None
2194
	if logfile:
2194
	if logfile:
2195
		del keywords["logfile"]
2195
		tee_good = 1
2196
		fd_pipes = keywords.get("fd_pipes")
2196
		fd_pipes = keywords.get("fd_pipes")
2197
		if fd_pipes is None:
2197
		if fd_pipes is None:
2198
			fd_pipes = {0:0, 1:1, 2:2}
2198
			fd_pipes = {0:0, 1:1, 2:2}
2199
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2199
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2200
			raise ValueError(fd_pipes)
2200
			raise ValueError(fd_pipes)
2201
		pr, pw = os.pipe()
2201
		try:
2202
		mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2202
			statinfo1 = os.stat(logfile)
2203
			 returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2203
			statinfo2 = os.fstat(fd_pipes[1])
2204
		os.close(pr)
2204
			statinfo3 = os.fstat(fd_pipes[2])
2205
		fd_pipes[1] = pw
2205
			# if they are pointing to same file as logfile, no 'tee' is required.
2206
		fd_pipes[2] = pw
2206
			if statinfo1 == statinfo2 and statinfo2 == statinfo3:
2207
		keywords["fd_pipes"] = fd_pipes
2207
				tee_good = 0
2208
		except:
2209
			tee_good = 1
2210
2211
		if tee_good:
2212
2213
			del keywords["logfile"]
2214
			pr, pw = os.pipe()
2215
			mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2216
			 	returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2217
			os.close(pr)
2218
			fd_pipes[1] = pw
2219
			fd_pipes[2] = pw
2220
			keywords["fd_pipes"] = fd_pipes
2208
2221
2209
	features = mysettings.features
2222
	features = mysettings.features
2210
	# XXX: Negative RESTRICT word
2223
	# XXX: Negative RESTRICT word
Lines 3225-3230 Link Here
3225
	if mysettings.get("PORT_LOGDIR", "") == "":
3238
	if mysettings.get("PORT_LOGDIR", "") == "":
3226
		while "PORT_LOGDIR" in mysettings:
3239
		while "PORT_LOGDIR" in mysettings:
3227
			del mysettings["PORT_LOGDIR"]
3240
			del mysettings["PORT_LOGDIR"]
3241
3242
	if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
3243
		mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + DEF_LOGDIR
3244
3228
	if "PORT_LOGDIR" in mysettings:
3245
	if "PORT_LOGDIR" in mysettings:
3229
		try:
3246
		try:
3230
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
3247
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
Lines 3237-3243 Link Here
3237
			while "PORT_LOGDIR" in mysettings:
3254
			while "PORT_LOGDIR" in mysettings:
3238
				del mysettings["PORT_LOGDIR"]
3255
				del mysettings["PORT_LOGDIR"]
3239
	if "PORT_LOGDIR" in mysettings:
3256
	if "PORT_LOGDIR" in mysettings:
3240
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
3257
		logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
3241
		if not os.path.exists(logid_path):
3258
		if not os.path.exists(logid_path):
3242
			f = open(logid_path, "w")
3259
			f = open(logid_path, "w")
3243
			f.close()
3260
			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