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 (-336 / +711 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 2337-2343 Link Here
2337
			if "blocks" == x[0]:
2339
			if "blocks" == x[0]:
2338
				display_list.append((x, 0, True))
2340
				display_list.append((x, 0, True))
2339
				continue
2341
				continue
2340
			graph_key = tuple(x)
2342
			graph_key = tuple(x[:-1])
2341
			if "--tree" in self.myopts:
2343
			if "--tree" in self.myopts:
2342
				depth = len(tree_nodes)
2344
				depth = len(tree_nodes)
2343
				while depth and graph_key not in \
2345
				while depth and graph_key not in \
Lines 2391-2397 Link Here
2391
				continue
2393
				continue
2392
			if "blocks" == graph_key[0]:
2394
			if "blocks" == graph_key[0]:
2393
				continue
2395
				continue
2394
			if ordered and graph_key[-1] != "nomerge":
2396
			if ordered and graph_key[-2] != "nomerge":
2395
				last_merge_depth = depth
2397
				last_merge_depth = depth
2396
				continue
2398
				continue
2397
			if depth >= last_merge_depth or \
2399
			if depth >= last_merge_depth or \
Lines 2426-2432 Link Here
2426
					addl = addl + " " + red(resolved)
2428
					addl = addl + " " + red(resolved)
2427
				else:
2429
				else:
2428
					addl = "[blocks " + addl + "] " + red(resolved)
2430
					addl = "[blocks " + addl + "] " + red(resolved)
2429
				block_parents = self.blocker_parents[tuple(x)]
2431
				block_parents = self.blocker_parents[tuple(x[:-1])]
2430
				block_parents = set([pnode[2] for pnode in block_parents])
2432
				block_parents = set([pnode[2] for pnode in block_parents])
2431
				block_parents = ", ".join(block_parents)
2433
				block_parents = ", ".join(block_parents)
2432
				if resolved!=x[2]:
2434
				if resolved!=x[2]:
Lines 2600-2606 Link Here
2600
				if verbosity == 3:
2602
				if verbosity == 3:
2601
					# size verbose
2603
					# size verbose
2602
					mysize=0
2604
					mysize=0
2603
					if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2605
					if x[0] == "ebuild" and ordered and x[-2] != "nomerge":
2604
						try:
2606
						try:
2605
							myfilesdict = portdb.getfetchsizes(pkg_key,
2607
							myfilesdict = portdb.getfetchsizes(pkg_key,
2606
								useflags=self.useFlags[myroot][pkg_key],
2608
								useflags=self.useFlags[myroot][pkg_key],
Lines 2679-2685 Link Here
2679
							myprint=myprint+myoldbest
2681
							myprint=myprint+myoldbest
2680
							myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2682
							myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2681
					else:
2683
					else:
2682
						if x[-1] == "nomerge" or not ordered:
2684
						if x[-2] == "nomerge" or not ordered:
2683
							myprint = darkblue("[nomerge      ] ")
2685
							myprint = darkblue("[nomerge      ] ")
2684
						else:
2686
						else:
2685
							myprint = "[" + pkg_type + " " + addl + "] "
2687
							myprint = "[" + pkg_type + " " + addl + "] "
Lines 2886-2896 Link Here
2886
			self.pkgsettings["/"] = \
2888
			self.pkgsettings["/"] = \
2887
				portage.config(clone=trees["/"]["vartree"].settings)
2889
				portage.config(clone=trees["/"]["vartree"].settings)
2888
2890
2889
	def merge(self, mylist, favorites, mtimedb):
2891
	def restart_portage(self, x, mergecount, totalcount, mtimedb):
2892
		xterm_titles = "notitles" not in self.settings.features
2893
		# don't really restart if any of these is true
2894
		# XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
2895
		if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
2896
			"--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
2897
			return
2898
2899
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
2900
			"--resume"])
2901
		mysplit=portage.pkgsplit(x[2])
2902
		myver=mysplit[1]+"-"+mysplit[2]
2903
		if myver[-3:]=='-r0':
2904
			myver=myver[:-3]
2905
		if (myver != portage.VERSION) and \
2906
		   "livecvsportage" not in self.settings.features:
2907
			if totalcount > mergecount:
2908
				emergelog(xterm_titles,
2909
					" ::: completed emerge ("+ \
2910
					str(mergecount)+" of "+ \
2911
					str(totalcount)+") "+ \
2912
					x[2]+" to "+x[1])
2913
				emergelog(xterm_titles, " *** RESTARTING " + \
2914
					"emerge via exec() after change of " + \
2915
					"portage version.")
2916
				portage.run_exitfuncs()
2917
				mynewargv=[sys.argv[0],"--resume"]
2918
				resume_opts = self.myopts.copy()
2919
				# For automatic resume, we need to prevent
2920
				# any of bad_resume_opts from leaking in
2921
				# via EMERGE_DEFAULT_OPTS.
2922
				resume_opts["--ignore-default-opts"] = True
2923
				for myopt, myarg in resume_opts.iteritems():
2924
					if myopt not in bad_resume_opts:
2925
						if myarg is True:
2926
							mynewargv.append(myopt)
2927
						else:
2928
							mynewargv.append(myopt +"="+ myarg)
2929
				# priority only needs to be adjusted on the first run
2930
				os.environ["PORTAGE_NICENESS"] = "0"
2931
				os.execv(mynewargv[0], mynewargv)
2932
2933
	def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
2934
		xterm_titles = "notitles" not in self.settings.features
2935
		myfeat = self.settings.features[:]
2936
		ldpath_mtimes = mtimedb["ldpath"]
2937
		myroot=x[1]
2938
		pkg_key = x[2]
2939
		pkg_cat = x[2].split("/")[0]
2940
		pkg_pf = x[2].split("/")[1]
2941
		pkgindex=2
2942
		if x[0]=="blocks":
2943
			pkgindex=3
2944
2945
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
2946
		logid_path = None
2947
		null_log = 0
2948
2949
		if self.settings.get("PORT_LOGDIR", "") == "":
2950
			while "PORT_LOGDIR" in self.settings:
2951
				del self.settings["PORT_LOGDIR"]
2952
		if "PORT_LOGDIR" in self.settings:
2953
			port_logdir = self.settings["PORT_LOGDIR"]
2954
		else:
2955
			port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
2956
2957
		try:
2958
			portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
2959
						 gid=portage.portage_gid, mode=02770)
2960
		except portage_exception.PortageException, e:
2961
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
2962
			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
2963
				self.settings["PORT_LOGDIR"], noiselevel=-1)
2964
			writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
2965
			null_log = 1
2966
2967
		if not null_log:
2968
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
2969
			if not os.path.exists(logid_path):
2970
				f = open(logid_path, "w")
2971
				f.close()
2972
				del f
2973
			logid_time = time.strftime("%Y%m%d-%H%M%S",
2974
				time.gmtime(os.stat(logid_path).st_mtime))
2975
			logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
2976
				(pkg_cat, pkg_pf, logid_time))
2977
			del logid_time
2978
		else:
2979
			logfile = "/dev/null"
2980
2981
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
2982
			print ">>> 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
			print ">>> Logfile in " + logfile
2987
			emergelog(xterm_titles, " >>> emerge ("+\
2988
				str(mergecount)+" of "+str(totalcount)+\
2989
				") "+x[pkgindex]+" to "+x[1])
2990
2991
		# need to spawn a --nodeps emerge in a separate process.
2992
		pkg="="+x[2]
2993
		merge_env = os.environ.copy()
2994
		merge_env["PORTAGE_INTERNAL_CALL"] = "1"
2995
		merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
2996
		merge_args = [sys.argv[0], "--nodeps", "--oneshot", "--nospinner", pkg]
2997
		good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
2998
					"--usepkg", "--usepkgonly"])
2999
		fd_pipes = None
3000
		merge_logfd = None
3001
		for myopt, myarg in self.myopts.iteritems():
3002
			# don't clobber the logfile at the same time as parallel fetch is
3003
			# all log of parallel fetch will go /var/log/emerge-fetch.log
3004
			# so, just leave 0,1,2 alone.
3005
			if "parallel-fetch" in myfeat and myopt == "--fetchonly":
3006
				fd_pipes = {0:0, 1:1, 2:2}
3007
			if myopt in good_nodeps_opts:
3008
				if myarg is True:
3009
					merge_args.append(myopt)
3010
				else:
3011
					merge_args.append(myopt +"="+ myarg)
3012
		if not fd_pipes:
3013
			merge_logfd = open(logfile, "w")
3014
			# put in a start message. This also makes sure that this fd is pointing to a good file on disk
3015
			# and hence will be used throughout the other spawns that will happen in the children.
3016
			merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
3017
			merge_logfd.flush()
3018
			fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
3019
			portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
3020
3021
		mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
3022
		if merge_logfd:
3023
			merge_logfd.close() # child has exclusive rights to it now.
3024
		return mypids[0]
3025
3026
	def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
3027
		xterm_titles = "notitles" not in self.settings.features
3028
		myfeat = self.settings.features[:]
3029
		ldpath_mtimes = mtimedb["ldpath"]
3030
		myroot=x[1]
3031
		pkg_key = x[2]
3032
		pkg_cat = x[2].split("/")[0]
3033
		pkg_pf = x[2].split("/")[1]
3034
		pkgindex=2
3035
		if x[0]=="blocks":
3036
			pkgindex=3
3037
3038
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
3039
			print "\n>>> Emerging (" + \
3040
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3041
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
3042
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
3043
			emergelog(xterm_titles, " >>> emerge ("+\
3044
				str(mergecount)+" of "+str(totalcount)+\
3045
				") "+x[pkgindex]+" to "+x[1])
3046
3047
		portdb = self.trees[myroot]["porttree"].dbapi
3048
		bindb  = self.trees[myroot]["bintree"].dbapi
3049
		vartree = self.trees[myroot]["vartree"]
3050
		pkgsettings = self.pkgsettings[myroot]
3051
		y = portdb.findname(pkg_key)
3052
		pkgsettings["EMERGE_FROM"] = x[0]
3053
		pkgsettings.backup_changes("EMERGE_FROM")
3054
		pkgsettings.reset()
3055
3056
		#buildsyspkg: Check if we need to _force_ binary package creation
3057
		issyspkg = ("buildsyspkg" in myfeat) \
3058
				and x[0] != "blocks" \
3059
				and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3060
				and "--buildpkg" not in self.myopts
3061
		if x[0] in ["ebuild","blocks"]:
3062
			if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3063
				raise Exception, "Merging a blocker"
3064
			elif "--fetchonly" in self.myopts or \
3065
				"--fetch-all-uri" in self.myopts:
3066
				if "--fetch-all-uri" in self.myopts:
3067
					retval = portage.doebuild(y, "fetch", myroot,
3068
						pkgsettings, self.edebug,
3069
						"--pretend" in self.myopts, fetchonly=1,
3070
						fetchall=1, mydbapi=portdb, tree="porttree")
3071
				else:
3072
					retval = portage.doebuild(y, "fetch", myroot,
3073
						pkgsettings, self.edebug,
3074
						"--pretend" in self.myopts, fetchonly=1,
3075
						mydbapi=portdb, tree="porttree")
3076
				if (retval is None) or retval:
3077
					print
3078
					print "!!! Fetch for",y,"failed, continuing..."
3079
					print
3080
3081
				return retval
3082
3083
			portage.doebuild_environment(y, "setup", myroot,
3084
				pkgsettings, self.edebug, 1, portdb)
3085
			catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3086
			portage_util.ensure_dirs(os.path.dirname(catdir),
3087
				uid=portage.portage_uid, gid=portage.portage_gid,
3088
				mode=070, mask=0)
3089
			builddir_lock = None
3090
			catdir_lock = None
3091
			try:
3092
				catdir_lock = portage_locks.lockdir(catdir)
3093
				portage_util.ensure_dirs(catdir,
3094
					uid=portage.portage_uid, gid=portage.portage_gid,
3095
					mode=070, mask=0)
3096
				builddir_lock = portage_locks.lockdir(
3097
					pkgsettings["PORTAGE_BUILDDIR"])
3098
				try:
3099
					portage_locks.unlockdir(catdir_lock)
3100
				finally:
3101
					catdir_lock = None
3102
				msg = " === (%s of %s) Cleaning (%s::%s)" % \
3103
					(mergecount, totalcount, pkg_key, y)
3104
				short_msg = "emerge: (%s of %s) %s Clean" % \
3105
					(mergecount, totalcount, pkg_key)
3106
				emergelog(xterm_titles, msg, short_msg=short_msg)
3107
				retval = portage.doebuild(y, "clean", myroot,
3108
					pkgsettings, self.edebug, cleanup=1,
3109
					mydbapi=portdb, tree="porttree")
3110
3111
				if retval != os.EX_OK:
3112
					return retval
3113
				if "--buildpkg" in self.myopts or issyspkg:
3114
					if issyspkg:
3115
						print ">>> This is a system package, " + \
3116
							"let's pack a rescue tarball."
3117
					msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3118
						(mergecount, totalcount, pkg_key, y)
3119
					short_msg = "emerge: (%s of %s) %s Compile" % \
3120
						(mergecount, totalcount, pkg_key)
3121
					emergelog(xterm_titles, msg, short_msg=short_msg)
3122
					self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3123
					retval = portage.doebuild(y, "package", myroot,
3124
						pkgsettings, self.edebug, mydbapi=portdb,
3125
						tree="porttree")
3126
					if retval != os.EX_OK:
3127
						return retval
3128
					bintree = self.trees[myroot]["bintree"]
3129
					if bintree.populated:
3130
						bintree.inject(pkg_key)
3131
					if "--buildpkgonly" not in self.myopts:
3132
						msg = " === (%s of %s) Merging (%s::%s)" % \
3133
							(mergecount, totalcount, pkg_key, y)
3134
						short_msg = "emerge: (%s of %s) %s Merge" % \
3135
							(mergecount, totalcount, pkg_key)
3136
						emergelog(xterm_titles, msg, short_msg=short_msg)
3137
						retval = portage.merge(pkgsettings["CATEGORY"],
3138
							pkgsettings["PF"], pkgsettings["D"],
3139
							os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3140
							"build-info"), myroot, pkgsettings,
3141
							myebuild=pkgsettings["EBUILD"],
3142
							mytree="porttree", mydbapi=portdb,
3143
							vartree=vartree, prev_mtimes=ldpath_mtimes)
3144
						if retval != os.EX_OK:
3145
							return retval
3146
					elif "noclean" not in pkgsettings.features:
3147
						portage.doebuild(y, "clean", myroot,
3148
							pkgsettings, self.edebug, mydbapi=portdb,
3149
							tree="porttree")
3150
				else:
3151
					msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3152
						(mergecount, totalcount, pkg_key, y)
3153
					short_msg = "emerge: (%s of %s) %s Compile" % \
3154
						(mergecount, totalcount, pkg_key)
3155
					emergelog(xterm_titles, msg, short_msg=short_msg)
3156
					retval = portage.doebuild(y, "merge", myroot,
3157
						pkgsettings, self.edebug, vartree=vartree,
3158
						mydbapi=portdb, tree="porttree",
3159
						prev_mtimes=ldpath_mtimes)
3160
					if retval != os.EX_OK:
3161
						return retval
3162
			finally:
3163
				if builddir_lock:
3164
					portage_locks.unlockdir(builddir_lock)
3165
				try:
3166
					if not catdir_lock:
3167
						# Lock catdir for removal if empty.
3168
						catdir_lock = portage_locks.lockdir(catdir)
3169
				finally:
3170
					if catdir_lock:
3171
						try:
3172
							os.rmdir(catdir)
3173
						except OSError, e:
3174
							if e.errno not in (errno.ENOENT,
3175
								errno.ENOTEMPTY, errno.EEXIST):
3176
								raise
3177
							del e
3178
						portage_locks.unlockdir(catdir_lock)
3179
3180
		elif x[0]=="binary":
3181
			#merge the tbz2
3182
			mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3183
			if "--getbinpkg" in self.myopts:
3184
				tbz2_lock = None
3185
				try:
3186
					if "distlocks" in pkgsettings.features and \
3187
						os.access(pkgsettings["PKGDIR"], os.W_OK):
3188
						portage_util.ensure_dirs(os.path.dirname(mytbz2))
3189
						tbz2_lock = portage_locks.lockfile(mytbz2,
3190
							wantnewlockfile=1)
3191
					if self.trees[myroot]["bintree"].isremote(pkg_key):
3192
						msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3193
							(mergecount, totalcount, pkg_key, mytbz2)
3194
						short_msg = "emerge: (%s of %s) %s Fetch" % \
3195
							(mergecount, totalcount, pkg_key)
3196
						emergelog(xterm_titles, msg, short_msg=short_msg)
3197
						if not self.trees[myroot]["bintree"].gettbz2(
3198
							pkg_key):
3199
							return 1
3200
				finally:
3201
					if tbz2_lock:
3202
						portage_locks.unlockfile(tbz2_lock)
3203
3204
			if "--fetchonly" in self.myopts or \
3205
				"--fetch-all-uri" in self.myopts:
3206
				return os.EX_OK
3207
3208
			short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
3209
			emergelog(xterm_titles, " === ("+str(mergecount)+\
3210
				" of "+str(totalcount)+") Merging Binary ("+\
3211
				x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3212
3213
			retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3214
				mydbapi=bindb,
3215
				vartree=self.trees[myroot]["vartree"],
3216
				prev_mtimes=ldpath_mtimes)
3217
			if retval != os.EX_OK:
3218
				return retval
3219
			#need to check for errors
3220
		if "--buildpkgonly" not in self.myopts:
3221
			self.trees[x[1]]["vartree"].inject(x[2])
3222
			myfavkey=portage.cpv_getkey(x[2])
3223
			if "--fetchonly" not in self.myopts and \
3224
				"--fetch-all-uri" not in self.myopts and \
3225
				myfavkey in favorites:
3226
				myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3227
				myfavdict=genericdict(myfavs)
3228
				#don't record if already in system profile or already recorded
3229
				if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3230
					#we don't have a favorites entry for this package yet; add one
3231
					myfavdict[myfavkey]=myfavkey
3232
					print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3233
					emergelog(xterm_titles, " === ("+\
3234
						str(mergecount)+" of "+\
3235
						str(totalcount)+\
3236
						") Updating world file ("+x[pkgindex]+")")
3237
					portage.write_atomic(
3238
					os.path.join(myroot, portage.WORLD_FILE),
3239
					"\n".join(myfavdict.values()))
3240
3241
			if "--pretend" not in self.myopts and \
3242
				"--fetchonly" not in self.myopts and \
3243
				"--fetch-all-uri" not in self.myopts:
3244
				# Clean the old package that we have merged over top of it.
3245
				if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3246
					xsplit=portage.pkgsplit(x[2])
3247
					emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3248
					retval = unmerge(pkgsettings, self.myopts, vartree,
3249
						"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3250
					if not retval:
3251
						emergelog(xterm_titles,
3252
							" --- AUTOCLEAN: Nothing unmerged.")
3253
				else:
3254
					portage.writemsg_stdout(colorize("WARN", "WARNING:")
3255
						+ " AUTOCLEAN is disabled.  This can cause serious"
3256
						+ " problems due to overlapping packages.\n")
3257
3258
3259
		if "--pretend" not in self.myopts and \
3260
			"--fetchonly" not in self.myopts and \
3261
			"--fetch-all-uri" not in self.myopts:
3262
			if "noclean" not in self.settings.features:
3263
				short_msg = "emerge: (%s of %s) %s Clean Post" % \
3264
					(mergecount, totalcount, x[pkgindex])
3265
				emergelog(xterm_titles, (" === (%s of %s) " + \
3266
					"Post-Build Cleaning (%s::%s)") % \
3267
					(mergecount, totalcount, x[pkgindex], y),
3268
					short_msg=short_msg)
3269
			emergelog(xterm_titles, " ::: completed emerge ("+\
3270
				str(mergecount)+" of "+str(totalcount)+") "+\
3271
				x[2]+" to "+x[1])
3272
3273
		return os.EX_OK
3274
3275
	def print_status(self, totalcount, donec, qsize, failedc, spawnd, failed):
3276
		smsg = ""
3277
		fmsg = ""
3278
		if spawnd:
3279
			for pkgs in spawnd.values():
3280
				smsg = smsg+" "+pkgs[0]
3281
		if failed:
3282
			for pkgs in failed:
3283
				fmsg = fmsg+" "+pkgs
3284
		print ">>> Jobs [Total = "+colorize("blue", str(totalcount))+"] [Done = "+\
3285
			colorize("GOOD", str(donec))+"] [Running = "+colorize("WARN", str(qsize)+smsg)+\
3286
			"] [Failed = "+colorize("BAD", str(failedc)+fmsg)+"]"
3287
		xtermTitle("Jobs Total = "+str(totalcount)+" Done = "+\
3288
			str(donec)+" Running = "+str(qsize)+" Failed = "+str(failedc))
3289
3290
	def wait_one_emerge(self, spawnd_pids, spawnd_pkg, mymergelist, mtimedb):
3291
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3292
		# let's wait for one of the jobs to finish
3293
		onepid = -1
3294
		while onepid not in spawnd_pids:
3295
			onepid , retval = os.waitpid(-1, 0)
3296
		spawnd_pids.remove(onepid)
3297
3298
		pkg_compl = spawnd_pkg[onepid][0]
3299
		pkg_slot = spawnd_pkg[onepid][1]
3300
		del spawnd_pkg[onepid]
3301
3302
		if not retval:
3303
			# unlink the logid_path
3304
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl.split("/")[0]+"."+pkg_compl.split("/")[1]
3305
			if os.path.exists(logid_path):
3306
				os.unlink(logid_path)
3307
			index = 0
3308
			print ">>> Package "+colorize("GOOD", pkg_compl)+" finished emerging."
3309
			# we need to remove this pkg from resume DB
3310
			# this is the dirtiest shit I have ever written
3311
			for pkgs in mymergelist:
3312
				if pkgs[2] == pkg_compl:
3313
					del mymergelist[index]
3314
					del mtimedb["resume"]["mergelist"][index]
3315
					mtimedb.commit()
3316
					# check if we need to restart portage
3317
					mysplit=portage.pkgsplit(pkg_compl)
3318
					if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3319
						self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3320
					break
3321
				index += 1
3322
		return (retval, pkg_compl)
3323
3324
	def merge(self, mylist, favorites, mtimedb, m_slots):
2890
		failed_fetches = []
3325
		failed_fetches = []
2891
		mymergelist=[]
3326
		mymergelist=[]
2892
		ldpath_mtimes = mtimedb["ldpath"]
3327
		ldpath_mtimes = mtimedb["ldpath"]
2893
		xterm_titles = "notitles" not in self.settings.features
3328
		xterm_titles = "notitles" not in self.settings.features
3329
		parallel = "parallel" in self.settings.features
3330
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3331
3332
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3333
		if self.edebug or "--fetchonly" in self.myopts:
3334
			parallel = False
2894
3335
2895
		#check for blocking dependencies
3336
		#check for blocking dependencies
2896
		if "--fetchonly" not in self.myopts and \
3337
		if "--fetchonly" not in self.myopts and \
Lines 2913-2920 Link Here
2913
		mysysdict = genericdict(getlist(self.settings, "system"))
3354
		mysysdict = genericdict(getlist(self.settings, "system"))
2914
		if "--resume" in self.myopts:
3355
		if "--resume" in self.myopts:
2915
			# We're resuming.
3356
			# We're resuming.
2916
			print colorize("GOOD", "*** Resuming merge...")
2917
			emergelog(xterm_titles, " *** Resuming merge...")
2918
			mymergelist=mtimedb["resume"]["mergelist"][:]
3357
			mymergelist=mtimedb["resume"]["mergelist"][:]
2919
			if "--skipfirst" in self.myopts and mymergelist:
3358
			if "--skipfirst" in self.myopts and mymergelist:
2920
				del mtimedb["resume"]["mergelist"][0]
3359
				del mtimedb["resume"]["mergelist"][0]
Lines 2948-2955 Link Here
2948
					os.path.join(self.target_root, portage.WORLD_FILE),
3387
					os.path.join(self.target_root, portage.WORLD_FILE),
2949
					"\n".join(myfavdict.values()))
3388
					"\n".join(myfavdict.values()))
2950
3389
2951
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3390
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
2952
			mtimedb.commit()
3391
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3392
				mtimedb.commit()
3393
3394
		totalcount = len(mymergelist)
3395
		mergecount=1
3396
3397
		if "--resume" in self.myopts and "--fetchonly" not in self.myopts:
3398
			# We're resuming.
3399
			print colorize("GOOD", "*** Resuming merge...")
3400
			emergelog(xterm_titles, " *** Resuming merge...")
2953
3401
2954
		myfeat = self.settings.features[:]
3402
		myfeat = self.settings.features[:]
2955
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3403
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 2967-2978 Link Here
2967
				print ">>> starting parallel fetching"
3415
				print ">>> starting parallel fetching"
2968
				fetch_log = "/var/log/emerge-fetch.log"
3416
				fetch_log = "/var/log/emerge-fetch.log"
2969
				logfile = open(fetch_log, "w")
3417
				logfile = open(fetch_log, "w")
2970
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3418
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
2971
				portage_util.apply_secpass_permissions(fetch_log,
3419
				portage_util.apply_secpass_permissions(fetch_log,
2972
					uid=portage.portage_uid, gid=portage.portage_gid,
3420
					uid=portage.portage_uid, gid=portage.portage_gid,
2973
					mode=0660)
3421
					mode=0660)
2974
				fetch_env = os.environ.copy()
3422
				fetch_env = os.environ.copy()
2975
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3423
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
2976
				fetch_env["PORTAGE_NICENESS"] = "0"
3424
				fetch_env["PORTAGE_NICENESS"] = "0"
2977
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3425
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
2978
				resume_opts = self.myopts.copy()
3426
				resume_opts = self.myopts.copy()
Lines 2992-3280 Link Here
2992
				del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3440
				del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
2993
					resume_opts
3441
					resume_opts
2994
3442
2995
		mergecount=0
3443
		if not parallel:
2996
		for x in mymergelist:
3444
			failed_fetches = []
2997
			mergecount+=1
3445
			for x in mymergelist:
2998
			myroot=x[1]
3446
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, mysysdict)
2999
			pkg_key = x[2]
3447
				mergecount += 1
3000
			pkgindex=2
3448
3001
			portdb = self.trees[myroot]["porttree"].dbapi
3449
				# need to short circuit the spawn with --nodeps
3002
			bindb  = self.trees[myroot]["bintree"].dbapi
3450
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
3003
			vartree = self.trees[myroot]["vartree"]
3451
					if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3004
			pkgsettings = self.pkgsettings[myroot]
3452
						continue
3005
			if x[0]=="blocks":
3453
					if retcode != os.EX_OK:
3006
				pkgindex=3
3454
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3007
			y = portdb.findname(pkg_key)
3455
							failed_fetches.append(x[2])
3008
			if "--pretend" not in self.myopts:
3456
							continue
3009
				print "\n>>> Emerging (" + \
3457
						else:
3010
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3458
							return retcode
3011
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3459
					# Unsafe for parallel merges
3012
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
3460
					del mtimedb["resume"]["mergelist"][0]
3013
				emergelog(xterm_titles, " >>> emerge ("+\
3461
					# Commit after each merge so that --resume may still work in
3014
					str(mergecount)+" of "+str(len(mymergelist))+\
3462
					# in the event that portage is not allowed to exit normally
3015
					") "+x[pkgindex]+" to "+x[1])
3463
					# due to power failure, SIGKILL, etc...
3016
3464
					mtimedb.commit()
3017
			pkgsettings["EMERGE_FROM"] = x[0]
3465
3018
			pkgsettings.backup_changes("EMERGE_FROM")
3466
					# unlink the logid_path if any exists
3019
			pkgsettings.reset()
3467
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
3020
3468
					if os.path.exists(logid_path):
3021
			#buildsyspkg: Check if we need to _force_ binary package creation
3469
						os.unlink(logid_path)
3022
			issyspkg = ("buildsyspkg" in myfeat) \
3470
					del logid_path
3023
					and x[0] != "blocks" \
3471
  
3024
					and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3472
					# check if we need to restart portage
3025
					and "--buildpkg" not in self.myopts
3026
			if x[0] in ["ebuild","blocks"]:
3027
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3028
					raise Exception, "Merging a blocker"
3029
				elif "--fetchonly" in self.myopts or \
3030
					"--fetch-all-uri" in self.myopts:
3031
					if "--fetch-all-uri" in self.myopts:
3032
						retval = portage.doebuild(y, "fetch", myroot,
3033
							pkgsettings, self.edebug,
3034
							"--pretend" in self.myopts, fetchonly=1,
3035
							fetchall=1, mydbapi=portdb, tree="porttree")
3036
					else:
3037
						retval = portage.doebuild(y, "fetch", myroot,
3038
							pkgsettings, self.edebug,
3039
							"--pretend" in self.myopts, fetchonly=1,
3040
							mydbapi=portdb, tree="porttree")
3041
					if (retval is None) or retval:
3042
						print
3043
						print "!!! Fetch for",y,"failed, continuing..."
3044
						print
3045
						failed_fetches.append(pkg_key)
3046
					continue
3047
3048
				portage.doebuild_environment(y, "setup", myroot,
3049
					pkgsettings, self.edebug, 1, portdb)
3050
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3051
				portage_util.ensure_dirs(os.path.dirname(catdir),
3052
					uid=portage.portage_uid, gid=portage.portage_gid,
3053
					mode=070, mask=0)
3054
				builddir_lock = None
3055
				catdir_lock = None
3056
				try:
3057
					catdir_lock = portage_locks.lockdir(catdir)
3058
					portage_util.ensure_dirs(catdir,
3059
						uid=portage.portage_uid, gid=portage.portage_gid,
3060
						mode=070, mask=0)
3061
					builddir_lock = portage_locks.lockdir(
3062
						pkgsettings["PORTAGE_BUILDDIR"])
3063
					try:
3064
						portage_locks.unlockdir(catdir_lock)
3065
					finally:
3066
						catdir_lock = None
3067
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
3068
						(mergecount, len(mymergelist), pkg_key, y)
3069
					short_msg = "emerge: (%s of %s) %s Clean" % \
3070
						(mergecount, len(mymergelist), pkg_key)
3071
					emergelog(xterm_titles, msg, short_msg=short_msg)
3072
					retval = portage.doebuild(y, "clean", myroot,
3073
						pkgsettings, self.edebug, cleanup=1,
3074
						mydbapi=portdb, tree="porttree")
3075
					if retval != os.EX_OK:
3076
						return retval
3077
					if "--buildpkg" in self.myopts or issyspkg:
3078
						if issyspkg:
3079
							print ">>> This is a system package, " + \
3080
								"let's pack a rescue tarball."
3081
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3082
							(mergecount, len(mymergelist), pkg_key, y)
3083
						short_msg = "emerge: (%s of %s) %s Compile" % \
3084
							(mergecount, len(mymergelist), pkg_key)
3085
						emergelog(xterm_titles, msg, short_msg=short_msg)
3086
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3087
						retval = portage.doebuild(y, "package", myroot,
3088
							pkgsettings, self.edebug, mydbapi=portdb,
3089
							tree="porttree")
3090
						if retval != os.EX_OK:
3091
							return retval
3092
						bintree = self.trees[myroot]["bintree"]
3093
						if bintree.populated:
3094
							bintree.inject(pkg_key)
3095
						if "--buildpkgonly" not in self.myopts:
3096
							msg = " === (%s of %s) Merging (%s::%s)" % \
3097
								(mergecount, len(mymergelist), pkg_key, y)
3098
							short_msg = "emerge: (%s of %s) %s Merge" % \
3099
								(mergecount, len(mymergelist), pkg_key)
3100
							emergelog(xterm_titles, msg, short_msg=short_msg)
3101
							retval = portage.merge(pkgsettings["CATEGORY"],
3102
								pkgsettings["PF"], pkgsettings["D"],
3103
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3104
								"build-info"), myroot, pkgsettings,
3105
								myebuild=pkgsettings["EBUILD"],
3106
								mytree="porttree", mydbapi=portdb,
3107
								vartree=vartree, prev_mtimes=ldpath_mtimes)
3108
							if retval != os.EX_OK:
3109
								return retval
3110
						elif "noclean" not in pkgsettings.features:
3111
							portage.doebuild(y, "clean", myroot,
3112
								pkgsettings, self.edebug, mydbapi=portdb,
3113
								tree="porttree")
3114
					else:
3115
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3116
							(mergecount, len(mymergelist), pkg_key, y)
3117
						short_msg = "emerge: (%s of %s) %s Compile" % \
3118
							(mergecount, len(mymergelist), pkg_key)
3119
						emergelog(xterm_titles, msg, short_msg=short_msg)
3120
						retval = portage.doebuild(y, "merge", myroot,
3121
							pkgsettings, self.edebug, vartree=vartree,
3122
							mydbapi=portdb, tree="porttree",
3123
							prev_mtimes=ldpath_mtimes)
3124
						if retval != os.EX_OK:
3125
							return retval
3126
				finally:
3127
					if builddir_lock:
3128
						portage_locks.unlockdir(builddir_lock)
3129
					try:
3130
						if not catdir_lock:
3131
							# Lock catdir for removal if empty.
3132
							catdir_lock = portage_locks.lockdir(catdir)
3133
					finally:
3134
						if catdir_lock:
3135
							try:
3136
								os.rmdir(catdir)
3137
							except OSError, e:
3138
								if e.errno not in (errno.ENOENT,
3139
									errno.ENOTEMPTY, errno.EEXIST):
3140
									raise
3141
								del e
3142
							portage_locks.unlockdir(catdir_lock)
3143
3144
			elif x[0]=="binary":
3145
				#merge the tbz2
3146
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3147
				if "--getbinpkg" in self.myopts:
3148
					tbz2_lock = None
3149
					try:
3150
						if "distlocks" in pkgsettings.features and \
3151
							os.access(pkgsettings["PKGDIR"], os.W_OK):
3152
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
3153
							tbz2_lock = portage_locks.lockfile(mytbz2,
3154
								wantnewlockfile=1)
3155
						if self.trees[myroot]["bintree"].isremote(pkg_key):
3156
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3157
								(mergecount, len(mymergelist), pkg_key, mytbz2)
3158
							short_msg = "emerge: (%s of %s) %s Fetch" % \
3159
								(mergecount, len(mymergelist), pkg_key)
3160
							emergelog(xterm_titles, msg, short_msg=short_msg)
3161
							if not self.trees[myroot]["bintree"].gettbz2(
3162
								pkg_key):
3163
								return 1
3164
					finally:
3165
						if tbz2_lock:
3166
							portage_locks.unlockfile(tbz2_lock)
3167
3168
				if "--fetchonly" in self.myopts or \
3169
					"--fetch-all-uri" in self.myopts:
3170
					continue
3171
3172
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3173
				emergelog(xterm_titles, " === ("+str(mergecount)+\
3174
					" of "+str(len(mymergelist))+") Merging Binary ("+\
3175
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3176
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3177
					mydbapi=bindb,
3178
					vartree=self.trees[myroot]["vartree"],
3179
					prev_mtimes=ldpath_mtimes)
3180
				if retval != os.EX_OK:
3181
					return retval
3182
				#need to check for errors
3183
			if "--buildpkgonly" not in self.myopts:
3184
				self.trees[x[1]]["vartree"].inject(x[2])
3185
				myfavkey=portage.cpv_getkey(x[2])
3186
				if "--fetchonly" not in self.myopts and \
3187
					"--fetch-all-uri" not in self.myopts and \
3188
					myfavkey in favorites:
3189
					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3190
					myfavdict=genericdict(myfavs)
3191
					#don't record if already in system profile or already recorded
3192
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3193
						#we don't have a favorites entry for this package yet; add one
3194
						myfavdict[myfavkey]=myfavkey
3195
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3196
						emergelog(xterm_titles, " === ("+\
3197
							str(mergecount)+" of "+\
3198
							str(len(mymergelist))+\
3199
							") Updating world file ("+x[pkgindex]+")")
3200
						portage.write_atomic(
3201
						os.path.join(myroot, portage.WORLD_FILE),
3202
						"\n".join(myfavdict.values()))
3203
3204
				if "--pretend" not in self.myopts and \
3205
					"--fetchonly" not in self.myopts and \
3206
					"--fetch-all-uri" not in self.myopts:
3207
					# Clean the old package that we have merged over top of it.
3208
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3209
						xsplit=portage.pkgsplit(x[2])
3210
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3211
						retval = unmerge(pkgsettings, self.myopts, vartree,
3212
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3213
						if not retval:
3214
							emergelog(xterm_titles,
3215
								" --- AUTOCLEAN: Nothing unmerged.")
3216
					else:
3217
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
3218
							+ " AUTOCLEAN is disabled.  This can cause serious"
3219
							+ " problems due to overlapping packages.\n")
3220
3221
					# Figure out if we need a restart.
3222
					mysplit=portage.pkgsplit(x[2])
3473
					mysplit=portage.pkgsplit(x[2])
3223
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3474
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3224
						myver=mysplit[1]+"-"+mysplit[2]
3475
							self.restart_portage(x, mergecount, totalcount, mtimedb)
3225
						if myver[-3:]=='-r0':
3476
  
3226
							myver=myver[:-3]
3477
				else:
3227
						if (myver != portage.VERSION) and \
3478
					if retcode != os.EX_OK:
3228
						   "livecvsportage" not in self.settings.features:
3479
						sys.exit(1)
3229
							if len(mymergelist) > mergecount:
3480
  					else:
3230
								emergelog(xterm_titles,
3481
						sys.exit(0)
3231
									" ::: completed emerge ("+ \
3482
  
3232
									str(mergecount)+" of "+ \
3483
			if "--pretend" not in self.myopts:
3233
									str(len(mymergelist))+") "+ \
3484
				emergelog(xterm_titles, " *** Finished. Cleaning up...")
3234
									x[2]+" to "+x[1])
3485
  
3235
								emergelog(xterm_titles, " *** RESTARTING " + \
3486
			# We're out of the loop... We're done. Delete the resume data.
3236
									"emerge via exec() after change of " + \
3487
			if mtimedb.has_key("resume"):
3237
									"portage version.")
3488
				del mtimedb["resume"]
3238
								del mtimedb["resume"]["mergelist"][0]
3489
			mtimedb.commit()
3239
								mtimedb.commit()
3490
			
3240
								portage.run_exitfuncs()
3491
			#by doing an exit this way, --fetchonly can continue to try to
3241
								mynewargv=[sys.argv[0],"--resume"]
3492
			#fetch everything even if a particular download fails.
3242
								resume_opts = self.myopts.copy()
3493
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3243
								# For automatic resume, we need to prevent
3494
				if failed_fetches:
3244
								# any of bad_resume_opts from leaking in
3495
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
3245
								# via EMERGE_DEFAULT_OPTS.
3496
						"encountered.  Please see above for details.\n\n")
3246
								resume_opts["--ignore-default-opts"] = True
3497
					for cpv in failed_fetches:
3247
								for myopt, myarg in resume_opts.iteritems():
3498
						sys.stderr.write("   ")
3248
									if myopt not in bad_resume_opts:
3499
						sys.stderr.write(cpv)
3249
										if myarg is True:
3500
						sys.stderr.write("\n")
3250
											mynewargv.append(myopt)
3501
					sys.stderr.write("\n")
3251
										else:
3502
					sys.exit(1)
3252
											mynewargv.append(myopt +"="+ myarg)
3503
				else:
3253
								# priority only needs to be adjusted on the first run
3504
					sys.exit(0)
3254
								os.environ["PORTAGE_NICENESS"] = "0"
3505
			return os.EX_OK
3255
								os.execv(mynewargv[0], mynewargv)
3506
  
3507
		# parallel code - dirty starts here...;-)
3508
		one_in_slot_failed=0
3509
		spawnd_pids=[]
3510
3511
		# dirty little trick to get number of cpus from the system
3512
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
3513
		cpu_count = 0
3514
		for data_cpuinfo in fd_cpuinfo.readlines():
3515
			if data_cpuinfo.find("cpu MHz") > -1 :
3516
				cpu_count += 1
3517
		fd_cpuinfo.close()
3518
3519
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
3520
		if cpu_count == 0:
3521
			cpu_count = 1
3522
3523
		spawnd_pkg = {}
3524
		donec = 0
3525
		failedc = 0
3526
		failedPkgs = []
3527
		logid_path = None
3528
		mylist = m_slots.keys()
3529
		mylist.sort()
3530
		for x in mylist:
3531
			# if slot is empty, go on
3532
			if not m_slots[x]:
3533
				continue
3256
3534
3257
			if "--pretend" not in self.myopts and \
3535
			# if previous slot failed, discontinue the emerge
3258
				"--fetchonly" not in self.myopts and \
3536
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
3259
				"--fetch-all-uri" not in self.myopts:
3537
				break
3260
				if "noclean" not in self.settings.features:
3261
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
3262
						(mergecount, len(mymergelist), x[pkgindex])
3263
					emergelog(xterm_titles, (" === (%s of %s) " + \
3264
						"Post-Build Cleaning (%s::%s)") % \
3265
						(mergecount, len(mymergelist), x[pkgindex], y),
3266
						short_msg=short_msg)
3267
				emergelog(xterm_titles, " ::: completed emerge ("+\
3268
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
3269
					x[2]+" to "+x[1])
3270
3538
3271
			# Unsafe for parallel merges
3539
			# start multiple merges in parallel mode
3272
			del mtimedb["resume"]["mergelist"][0]
3540
			num_at_atime = cpu_count + 1
3273
			# Commit after each merge so that --resume may still work in
3274
			# in the event that portage is not allowed to exit normally
3275
			# due to power failure, SIGKILL, etc...
3276
			mtimedb.commit()
3277
3541
3542
			qsize = 0
3543
			for y in m_slots[x]:
3544
				# these all can go in parallel, so fork one after the other
3545
				# but num_at_atime at most
3546
				if num_at_atime:
3547
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3548
					spawnd_pids.append(onepid)
3549
					spawnd_pkg[onepid] = (y[2], x)
3550
					num_at_atime -= 1
3551
					mergecount += 1
3552
					qsize += 1
3553
				else:
3554
					self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3555
					# let's wait for one of the jobs to finish
3556
					(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mymergelist, mtimedb)
3557
3558
					# if it failed, I need to fail next slot but continue to merge all in this slot
3559
					if retval:
3560
						one_in_slot_failed = retval
3561
						failedc += 1
3562
						failedPkgs.append(pkg_compl)
3563
  					else:
3564
						donec += 1
3565
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3566
					spawnd_pids.append(onepid)
3567
					spawnd_pkg[onepid] = (y[2], x)
3568
					mergecount += 1
3569
3570
			# this slot is exhausted, so wait for all of the forks to finish
3571
			while spawnd_pids:
3572
				self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3573
				# let's wait for one of the jobs to finish
3574
				(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mymergelist, mtimedb)
3575
3576
				qsize -= 1
3577
				if retval:
3578
					one_in_slot_failed = retval
3579
					failedc += 1
3580
					failedPkgs.append(pkg_compl)
3581
				else:
3582
					donec += 1
3583
		if totalcount:
3584
			self.print_status(totalcount, donec, qsize, failedc, None, failedPkgs)
3585
  
3586
		if one_in_slot_failed:
3587
			portage.writemsg_stdout(red("\nSome packages failed to emerge, summary follows:\n"))
3588
  
3589
		for pkgs in failedPkgs:
3590
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3591
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
3592
				sys.exit(1)
3593
3594
			portage.writemsg_stdout(red("\nPackage "+pkgs+" failed to emerge\n"))
3595
			logfile = None
3596
			if "PORT_LOGDIR" in self.settings:
3597
				port_logdir = self.settings["PORT_LOGDIR"]
3598
			else:
3599
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3600
3601
			pkg_cat = pkgs.split("/")[0]
3602
			pkg_pf = pkgs.split("/")[1]
3603
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
3604
			if os.path.exists(logid_path):
3605
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
3606
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3607
					(pkg_cat, pkg_pf, logid_time))
3608
				del logid_time
3609
3610
			if logfile and os.path.exists(logfile):
3611
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
3612
3613
			if logfile and os.path.exists(logfile):
3614
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
3615
				os.unlink(logid_path)
3616
		if one_in_slot_failed:
3617
			sys.exit(1)
3278
		if "--pretend" not in self.myopts:
3618
		if "--pretend" not in self.myopts:
3279
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3619
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3280
3620
Lines 3283-3302 Link Here
3283
			del mtimedb["resume"]
3623
			del mtimedb["resume"]
3284
		mtimedb.commit()
3624
		mtimedb.commit()
3285
3625
3286
		#by doing an exit this way, --fetchonly can continue to try to
3287
		#fetch everything even if a particular download fails.
3288
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3626
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3289
			if failed_fetches:
3627
			sys.exit(0)
3290
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
3628
3291
					"encountered.  Please see above for details.\n\n")
3292
				for cpv in failed_fetches:
3293
					sys.stderr.write("   ")
3294
					sys.stderr.write(cpv)
3295
					sys.stderr.write("\n")
3296
				sys.stderr.write("\n")
3297
				sys.exit(1)
3298
			else:
3299
				sys.exit(0)
3300
		return os.EX_OK
3629
		return os.EX_OK
3301
3630
3302
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3631
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
Lines 3736-3742 Link Here
3736
def validate_merge_list(trees, mergelist):
4065
def validate_merge_list(trees, mergelist):
3737
	"""Validate the list to make sure all the packages are still available.
4066
	"""Validate the list to make sure all the packages are still available.
3738
	This is needed for --resume."""
4067
	This is needed for --resume."""
3739
	for (pkg_type, myroot, pkg_key, action) in mergelist:
4068
	for (pkg_type, myroot, pkg_key, action, merge_slot) in mergelist:
3740
		if pkg_type == "binary" and \
4069
		if pkg_type == "binary" and \
3741
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4070
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3742
			pkg_type == "ebuild" and \
4071
			pkg_type == "ebuild" and \
Lines 4622-4628 Link Here
4622
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4951
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4623
		emergelog(xterm_titles, " >>> depclean")
4952
		emergelog(xterm_titles, " >>> depclean")
4624
4953
4625
	if "--quiet" not in myopts:
4954
	if "--quiet" not in myopts and "--nodeps" not in myopts:
4626
		print "\nCalculating dependencies  ",
4955
		print "\nCalculating dependencies  ",
4627
4956
4628
	soft = 0
4957
	soft = 0
Lines 4724-4729 Link Here
4724
	else:
5053
	else:
4725
		print "Number removed:       "+str(len(cleanlist))
5054
		print "Number removed:       "+str(len(cleanlist))
4726
5055
5056
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
5057
	merge_slots = {}
5058
	for pkg in mergelist:
5059
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
5060
			slot = int(pkg[4])
5061
			try:
5062
				if pkg not in merge_slots[slot]:
5063
					merge_slots[slot].append(pkg)
5064
			except KeyError:
5065
				merge_slots[slot] = [pkg]
5066
	# print the merge slots
5067
	max_slot = 0
5068
	mylist = merge_slots.keys()
5069
	mylist.sort()
5070
	for x in mylist:
5071
		if x > max_slot:
5072
			max_slot = x
5073
		if parallel:
5074
			print "Package list for slot = "+str(x)
5075
			for y in merge_slots[x]:
5076
				print "	",y
5077
	if printonly:
5078
		return
5079
5080
	# make one last pass at the merge_slots and initialize the missing slots to None
5081
	x = 0
5082
	while x < max_slot:
5083
		if x not in merge_slots.keys():
5084
			merge_slots[x] = None
5085
		x += 1
5086
	return merge_slots
5087
4727
def action_build(settings, trees, mtimedb,
5088
def action_build(settings, trees, mtimedb,
4728
	myopts, myaction, myfiles, spinner):
5089
	myopts, myaction, myfiles, spinner):
4729
	ldpath_mtimes = mtimedb["ldpath"]
5090
	ldpath_mtimes = mtimedb["ldpath"]
Lines 4831-4843 Link Here
4831
			if len(mymergelist) == 0:
5192
			if len(mymergelist) == 0:
4832
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5193
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4833
				sys.exit(0)
5194
				sys.exit(0)
5195
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4834
			mydepgraph.display(mymergelist)
5196
			mydepgraph.display(mymergelist)
4835
			prompt="Would you like to resume merging these packages?"
5197
			prompt="Would you like to resume merging these packages?"
4836
		else:
5198
		else:
4837
			mydepgraph.display(
5199
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
4838
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5200
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5201
			mydepgraph.display(mymergelist)
4839
			mergecount=0
5202
			mergecount=0
4840
			for x in mydepgraph.altlist():
5203
			for x in mymergelist:
4841
				if x[0] != "blocks" and x[3] != "nomerge":
5204
				if x[0] != "blocks" and x[3] != "nomerge":
4842
					mergecount+=1
5205
					mergecount+=1
4843
				#check for blocking dependencies
5206
				#check for blocking dependencies
Lines 4882-4891 Link Here
4882
			if len(mymergelist) == 0:
5245
			if len(mymergelist) == 0:
4883
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5246
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
4884
				sys.exit(0)
5247
				sys.exit(0)
5248
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
4885
			mydepgraph.display(mymergelist)
5249
			mydepgraph.display(mymergelist)
4886
		else:
5250
		else:
4887
			mydepgraph.display(
5251
			# mydepgraph.digraph.debug_print()
4888
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5252
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5253
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5254
			mydepgraph.display(mymergelist)
4889
	else:
5255
	else:
4890
		if ("--buildpkgonly" in myopts):
5256
		if ("--buildpkgonly" in myopts):
4891
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5257
			if not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
Lines 4901-4923 Link Here
4901
				it to write the mtimedb"""
5267
				it to write the mtimedb"""
4902
				mtimedb.filename = None
5268
				mtimedb.filename = None
4903
				time.sleep(3) # allow the parent to have first fetch
5269
				time.sleep(3) # allow the parent to have first fetch
5270
			mymergelist = mtimedb["resume"]["mergelist"]
5271
			if "--skipfirst" in myopts:
5272
				mymergelist = mymergelist[1:]
5273
			if len(mymergelist) == 0:
5274
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5275
				sys.exit(0)
5276
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
4904
			del mydepgraph
5277
			del mydepgraph
4905
			retval = mergetask.merge(
5278
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
4906
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
4907
			if retval != os.EX_OK:
5279
			if retval != os.EX_OK:
4908
				sys.exit(retval)
5280
				sys.exit(retval)
4909
		else:
5281
		else:
4910
			if "resume" in mtimedb and \
5282
			mymergelist = mydepgraph.altlist()
4911
			"mergelist" in mtimedb["resume"] and \
5283
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
4912
			len(mtimedb["resume"]["mergelist"]) > 1:
5284
			if "--nodeps" not in myopts or len(mymergelist) > 1:
4913
				mtimedb["resume_backup"] = mtimedb["resume"]
5285
				if "resume" in mtimedb and \
4914
				del mtimedb["resume"]
5286
				"mergelist" in mtimedb["resume"] and \
4915
				mtimedb.commit()
5287
				len(mtimedb["resume"]["mergelist"]) > 1:
4916
			mtimedb["resume"]={}
5288
					mtimedb["resume_backup"] = mtimedb["resume"]
4917
			# XXX: Stored as a list for backward compatibility.
5289
					del mtimedb["resume"]
4918
			mtimedb["resume"]["myopts"] = \
5290
					mtimedb.commit()
4919
				[k for k in myopts if myopts[k] is True]
5291
				mtimedb["resume"]={}
4920
			mtimedb["resume"]["favorites"]=favorites
5292
				# XXX: Stored as a list for backward compatibility.
5293
				mtimedb["resume"]["myopts"] = \
5294
					[k for k in myopts if myopts[k] is True]
5295
				mtimedb["resume"]["favorites"]=favorites
4921
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5296
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
4922
				for pkgline in mydepgraph.altlist():
5297
				for pkgline in mydepgraph.altlist():
4923
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5298
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 4933-4950 Link Here
4933
							tree="porttree")
5308
							tree="porttree")
4934
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5309
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
4935
				pkglist = []
5310
				pkglist = []
4936
				for pkg in mydepgraph.altlist():
5311
				for pkg in mymergelist:
4937
					if pkg[0] != "blocks":
5312
					if pkg[0] != "blocks":
4938
						pkglist.append(pkg)
5313
						pkglist.append(pkg)
4939
			else:
5314
			else:
4940
				pkglist = mydepgraph.altlist()
5315
				pkglist = mymergelist
4941
			del mydepgraph
5316
			del mydepgraph
4942
			mergetask = MergeTask(settings, trees, myopts)
5317
			mergetask = MergeTask(settings, trees, myopts)
4943
			retval = mergetask.merge(pkglist, favorites, mtimedb)
5318
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
4944
			if retval != os.EX_OK:
5319
			if retval != os.EX_OK:
4945
				sys.exit(retval)
5320
				sys.exit(retval)
4946
5321
4947
		if mtimedb.has_key("resume"):
5322
		if mtimedb.has_key("resume") and ("--nodeps" not in myopts or len(mymergelist) > 1):
4948
			del mtimedb["resume"]
5323
			del mtimedb["resume"]
4949
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5324
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
4950
			portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5325
			portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
(-)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 3230-3235 Link Here
3230
	if mysettings.get("PORT_LOGDIR", "") == "":
3243
	if mysettings.get("PORT_LOGDIR", "") == "":
3231
		while "PORT_LOGDIR" in mysettings:
3244
		while "PORT_LOGDIR" in mysettings:
3232
			del mysettings["PORT_LOGDIR"]
3245
			del mysettings["PORT_LOGDIR"]
3246
3247
	if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
3248
		mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + DEF_LOGDIR
3249
3233
	if "PORT_LOGDIR" in mysettings:
3250
	if "PORT_LOGDIR" in mysettings:
3234
		try:
3251
		try:
3235
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
3252
			portage_util.ensure_dirs(mysettings["PORT_LOGDIR"],
Lines 3242-3248 Link Here
3242
			while "PORT_LOGDIR" in mysettings:
3259
			while "PORT_LOGDIR" in mysettings:
3243
				del mysettings["PORT_LOGDIR"]
3260
				del mysettings["PORT_LOGDIR"]
3244
	if "PORT_LOGDIR" in mysettings:
3261
	if "PORT_LOGDIR" in mysettings:
3245
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
3262
		logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
3246
		if not os.path.exists(logid_path):
3263
		if not os.path.exists(logid_path):
3247
			f = open(logid_path, "w")
3264
			f = open(logid_path, "w")
3248
			f.close()
3265
			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