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

Return to bug 147516