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