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 (-328 / +739 lines)
Lines 2029-2034 Link Here
2029
		ignore_priority_soft_range.extend(
2029
		ignore_priority_soft_range.extend(
2030
			xrange(DepPriority.MIN, DepPriority.SOFT + 1))
2030
			xrange(DepPriority.MIN, DepPriority.SOFT + 1))
2031
		tree_mode = "--tree" in self.myopts
2031
		tree_mode = "--tree" in self.myopts
2032
		slotcount = 0
2033
2032
		# Tracks whether or not the current iteration should prefer asap_nodes
2034
		# Tracks whether or not the current iteration should prefer asap_nodes
2033
		# if available.  This is set to False when the previous iteration
2035
		# if available.  This is set to False when the previous iteration
2034
		# failed to select any nodes.  It is reset whenever nodes are
2036
		# failed to select any nodes.  It is reset whenever nodes are
Lines 2195-2201 Link Here
2195
			prefer_asap = True
2197
			prefer_asap = True
2196
2198
2197
			for node in selected_nodes:
2199
			for node in selected_nodes:
2198
				retlist.append(list(node))
2200
				node2 = list(node)
2201
				if len(node2) == 4:
2202
					node2.append(str(slotcount))
2203
				retlist.append(node2)
2199
				mygraph.remove(node)
2204
				mygraph.remove(node)
2200
				if not reversed and not circular_blocks and myblockers.contains(node):
2205
				if not reversed and not circular_blocks and myblockers.contains(node):
2201
					"""This node may have invalidated one or more blockers."""
2206
					"""This node may have invalidated one or more blockers."""
Lines 2209-2214 Link Here
2209
								self.blocker_parents[blocker] = unresolved
2214
								self.blocker_parents[blocker] = unresolved
2210
							else:
2215
							else:
2211
								del self.blocker_parents[blocker]
2216
								del self.blocker_parents[blocker]
2217
			slotcount += 1
2212
2218
2213
		if not reversed:
2219
		if not reversed:
2214
			"""Blocker validation does not work with reverse mode,
2220
			"""Blocker validation does not work with reverse mode,
Lines 2425-2431 Link Here
2425
			if "blocks" == x[0]:
2431
			if "blocks" == x[0]:
2426
				display_list.append((x, 0, True))
2432
				display_list.append((x, 0, True))
2427
				continue
2433
				continue
2428
			graph_key = tuple(x)
2434
			if len(x) > 4:
2435
				graph_key = tuple(x[:-1])
2436
			else:
2437
				graph_key = tuple(x)
2429
			if "--tree" in self.myopts:
2438
			if "--tree" in self.myopts:
2430
				depth = len(tree_nodes)
2439
				depth = len(tree_nodes)
2431
				while depth and graph_key not in \
2440
				while depth and graph_key not in \
Lines 2487-2493 Link Here
2487
				continue
2496
				continue
2488
			if "blocks" == graph_key[0]:
2497
			if "blocks" == graph_key[0]:
2489
				continue
2498
				continue
2490
			if ordered and graph_key[-1] != "nomerge":
2499
			if len(graph_key) > 4:
2500
				merge_op = graph_key[-2]
2501
			else:
2502
				merge_op = graph_key[-1]
2503
			if ordered and merge_op != "nomerge":
2491
				last_merge_depth = depth
2504
				last_merge_depth = depth
2492
				continue
2505
				continue
2493
			if depth >= last_merge_depth or \
2506
			if depth >= last_merge_depth or \
Lines 2709-2715 Link Here
2709
				if verbosity == 3:
2722
				if verbosity == 3:
2710
					# size verbose
2723
					# size verbose
2711
					mysize=0
2724
					mysize=0
2712
					if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2725
					if len(x) > 4:
2726
						merge_op = x[-2]
2727
					else:
2728
						merge_op = x[-1]
2729
					if x[0] == "ebuild" and ordered and merge_op != "nomerge":
2713
						try:
2730
						try:
2714
							myfilesdict = portdb.getfetchsizes(pkg_key,
2731
							myfilesdict = portdb.getfetchsizes(pkg_key,
2715
								useflags=self.useFlags[myroot][pkg_key],
2732
								useflags=self.useFlags[myroot][pkg_key],
Lines 2788-2794 Link Here
2788
							myprint=myprint+myoldbest
2805
							myprint=myprint+myoldbest
2789
							myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2806
							myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2790
					else:
2807
					else:
2791
						if x[-1] == "nomerge" or not ordered:
2808
						if len(x) > 4:
2809
							merge_op = x[-2]
2810
						else:
2811
							merge_op = x[-1]
2812
						if merge_op == "nomerge" or not ordered:
2792
							myprint = darkblue("[nomerge      ] ")
2813
							myprint = darkblue("[nomerge      ] ")
2793
						else:
2814
						else:
2794
							myprint = "[" + pkg_type + " " + addl + "] "
2815
							myprint = "[" + pkg_type + " " + addl + "] "
Lines 2999-3009 Link Here
2999
			self.pkgsettings["/"] = \
3020
			self.pkgsettings["/"] = \
3000
				portage.config(clone=trees["/"]["vartree"].settings)
3021
				portage.config(clone=trees["/"]["vartree"].settings)
3001
3022
3002
	def merge(self, mylist, favorites, mtimedb):
3023
	def restart_portage(self, x, mergecount, totalcount, mtimedb):
3024
		xterm_titles = "notitles" not in self.settings.features
3025
		# don't really restart if any of these is true
3026
		# XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
3027
		if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
3028
			"--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
3029
			return
3030
3031
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3032
			"--resume"])
3033
		mysplit=portage.pkgsplit(x[2])
3034
		myver=mysplit[1]+"-"+mysplit[2]
3035
		if myver[-3:]=='-r0':
3036
			myver=myver[:-3]
3037
		if (myver != portage.VERSION) and \
3038
		   "livecvsportage" not in self.settings.features:
3039
			if totalcount > mergecount:
3040
				emergelog(xterm_titles,
3041
					" ::: completed emerge ("+ \
3042
					str(mergecount)+" of "+ \
3043
					str(totalcount)+") "+ \
3044
					x[2]+" to "+x[1])
3045
				emergelog(xterm_titles, " *** RESTARTING " + \
3046
					"emerge via exec() after change of " + \
3047
					"portage version.")
3048
				portage.run_exitfuncs()
3049
				mynewargv=[sys.argv[0],"--resume"]
3050
				resume_opts = self.myopts.copy()
3051
				# For automatic resume, we need to prevent
3052
				# any of bad_resume_opts from leaking in
3053
				# via EMERGE_DEFAULT_OPTS.
3054
				resume_opts["--ignore-default-opts"] = True
3055
				for myopt, myarg in resume_opts.iteritems():
3056
					if myopt not in bad_resume_opts:
3057
						if myarg is True:
3058
							mynewargv.append(myopt)
3059
						else:
3060
							mynewargv.append(myopt +"="+ myarg)
3061
				# priority only needs to be adjusted on the first run
3062
				os.environ["PORTAGE_NICENESS"] = "0"
3063
				os.execv(mynewargv[0], mynewargv)
3064
3065
	def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
3066
		xterm_titles = "notitles" not in self.settings.features
3067
		myfeat = self.settings.features[:]
3068
		ldpath_mtimes = mtimedb["ldpath"]
3069
		myroot=x[1]
3070
		pkg_key = x[2]
3071
		pkg_cat = x[2].split("/")[0]
3072
		pkg_pf = x[2].split("/")[1]
3073
		pkgindex=2
3074
		if x[0]=="blocks":
3075
			pkgindex=3
3076
3077
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3078
		portage_util.ensure_dirs(build_prefix, uid=portage.portage_uid, gid=portage.portage_gid, mode=0775)
3079
3080
		logid_path = None
3081
		null_log = 0
3082
3083
		if self.settings.get("PORT_LOGDIR", "") == "":
3084
			while "PORT_LOGDIR" in self.settings:
3085
				del self.settings["PORT_LOGDIR"]
3086
		if "PORT_LOGDIR" in self.settings:
3087
			port_logdir = self.settings["PORT_LOGDIR"]
3088
		else:
3089
			port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3090
3091
		try:
3092
			portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
3093
						 gid=portage.portage_gid, mode=02770)
3094
		except portage_exception.PortageException, e:
3095
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
3096
			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
3097
				self.settings["PORT_LOGDIR"], noiselevel=-1)
3098
			writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
3099
			null_log = 1
3100
3101
		if not null_log:
3102
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
3103
			if not os.path.exists(logid_path):
3104
				f = open(logid_path, "w")
3105
				f.close()
3106
				del f
3107
			logid_time = time.strftime("%Y%m%d-%H%M%S",
3108
				time.gmtime(os.stat(logid_path).st_mtime))
3109
			logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3110
				(pkg_cat, pkg_pf, logid_time))
3111
			del logid_time
3112
		else:
3113
			logfile = "/dev/null"
3114
3115
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
3116
			print ">>> Emerging (" + \
3117
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3118
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
3119
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
3120
			print ">>> Logfile in " + logfile
3121
			emergelog(xterm_titles, " >>> emerge ("+\
3122
				str(mergecount)+" of "+str(totalcount)+\
3123
				") "+x[pkgindex]+" to "+x[1])
3124
3125
		# need to spawn a --nodeps emerge in a separate process.
3126
		pkg="="+x[2]
3127
		merge_env = os.environ.copy()
3128
		merge_env["PORTAGE_INTERNAL_CALL"] = "1"
3129
		merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
3130
		merge_args = [sys.argv[0], "--nodeps", "--oneshot", "--nospinner", pkg]
3131
		good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
3132
					"--usepkg", "--usepkgonly"])
3133
		fd_pipes = None
3134
		merge_logfd = None
3135
		for myopt, myarg in self.myopts.iteritems():
3136
			# don't clobber the logfile at the same time as parallel fetch is
3137
			# all log of parallel fetch will go /var/log/emerge-fetch.log
3138
			# so, just leave 0,1,2 alone.
3139
			if "parallel-fetch" in myfeat and myopt == "--fetchonly":
3140
				fd_pipes = {0:0, 1:1, 2:2}
3141
			if myopt in good_nodeps_opts:
3142
				if myarg is True:
3143
					merge_args.append(myopt)
3144
				else:
3145
					merge_args.append(myopt +"="+ myarg)
3146
		if not fd_pipes:
3147
			merge_logfd = open(logfile, "w")
3148
			# put in a start message. This also makes sure that this fd is pointing to a good file on disk
3149
			# and hence will be used throughout the other spawns that will happen in the children.
3150
			merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
3151
			merge_logfd.flush()
3152
			fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
3153
			portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
3154
3155
		mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
3156
		if merge_logfd:
3157
			merge_logfd.close() # child has exclusive rights to it now.
3158
		return mypids[0]
3159
3160
	def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
3161
		xterm_titles = "notitles" not in self.settings.features
3162
		myfeat = self.settings.features[:]
3163
		ldpath_mtimes = mtimedb["ldpath"]
3164
		myroot=x[1]
3165
		pkg_key = x[2]
3166
		pkg_cat = x[2].split("/")[0]
3167
		pkg_pf = x[2].split("/")[1]
3168
		pkgindex=2
3169
		if x[0]=="blocks":
3170
			pkgindex=3
3171
3172
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
3173
			print "\n>>> Emerging (" + \
3174
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3175
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
3176
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
3177
			emergelog(xterm_titles, " >>> emerge ("+\
3178
				str(mergecount)+" of "+str(totalcount)+\
3179
				") "+x[pkgindex]+" to "+x[1])
3180
3181
		portdb = self.trees[myroot]["porttree"].dbapi
3182
		bindb  = self.trees[myroot]["bintree"].dbapi
3183
		vartree = self.trees[myroot]["vartree"]
3184
		pkgsettings = self.pkgsettings[myroot]
3185
		y = portdb.findname(pkg_key)
3186
		pkgsettings["EMERGE_FROM"] = x[0]
3187
		pkgsettings.backup_changes("EMERGE_FROM")
3188
		pkgsettings.reset()
3189
3190
		#buildsyspkg: Check if we need to _force_ binary package creation
3191
		issyspkg = ("buildsyspkg" in myfeat) \
3192
				and x[0] != "blocks" \
3193
				and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3194
				and "--buildpkg" not in self.myopts
3195
		if x[0] in ["ebuild","blocks"]:
3196
			if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3197
				raise Exception, "Merging a blocker"
3198
			elif "--fetchonly" in self.myopts or \
3199
				"--fetch-all-uri" in self.myopts:
3200
				if "--fetch-all-uri" in self.myopts:
3201
					retval = portage.doebuild(y, "fetch", myroot,
3202
						pkgsettings, self.edebug,
3203
						"--pretend" in self.myopts, fetchonly=1,
3204
						fetchall=1, mydbapi=portdb, tree="porttree")
3205
				else:
3206
					retval = portage.doebuild(y, "fetch", myroot,
3207
						pkgsettings, self.edebug,
3208
						"--pretend" in self.myopts, fetchonly=1,
3209
						mydbapi=portdb, tree="porttree")
3210
				if (retval is None) or retval:
3211
					print
3212
					print "!!! Fetch for",y,"failed, continuing..."
3213
					print
3214
3215
				return retval
3216
3217
			portage.doebuild_environment(y, "setup", myroot,
3218
				pkgsettings, self.edebug, 1, portdb)
3219
			catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3220
			portage_util.ensure_dirs(os.path.dirname(catdir),
3221
				uid=portage.portage_uid, gid=portage.portage_gid,
3222
				mode=070, mask=0)
3223
			builddir_lock = None
3224
			catdir_lock = None
3225
			try:
3226
				catdir_lock = portage_locks.lockdir(catdir)
3227
				portage_util.ensure_dirs(catdir,
3228
					uid=portage.portage_uid, gid=portage.portage_gid,
3229
					mode=070, mask=0)
3230
				builddir_lock = portage_locks.lockdir(
3231
					pkgsettings["PORTAGE_BUILDDIR"])
3232
				try:
3233
					portage_locks.unlockdir(catdir_lock)
3234
				finally:
3235
					catdir_lock = None
3236
				msg = " === (%s of %s) Cleaning (%s::%s)" % \
3237
					(mergecount, totalcount, pkg_key, y)
3238
				short_msg = "emerge: (%s of %s) %s Clean" % \
3239
					(mergecount, totalcount, pkg_key)
3240
				emergelog(xterm_titles, msg, short_msg=short_msg)
3241
				retval = portage.doebuild(y, "clean", myroot,
3242
					pkgsettings, self.edebug, cleanup=1,
3243
					mydbapi=portdb, tree="porttree")
3244
3245
				if retval != os.EX_OK:
3246
					return retval
3247
				if "--buildpkg" in self.myopts or issyspkg:
3248
					if issyspkg:
3249
						print ">>> This is a system package, " + \
3250
							"let's pack a rescue tarball."
3251
					msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3252
						(mergecount, totalcount, pkg_key, y)
3253
					short_msg = "emerge: (%s of %s) %s Compile" % \
3254
						(mergecount, totalcount, pkg_key)
3255
					emergelog(xterm_titles, msg, short_msg=short_msg)
3256
					self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3257
					retval = portage.doebuild(y, "package", myroot,
3258
						pkgsettings, self.edebug, mydbapi=portdb,
3259
						tree="porttree")
3260
					if retval != os.EX_OK:
3261
						return retval
3262
					bintree = self.trees[myroot]["bintree"]
3263
					if bintree.populated:
3264
						bintree.inject(pkg_key)
3265
					if "--buildpkgonly" not in self.myopts:
3266
						msg = " === (%s of %s) Merging (%s::%s)" % \
3267
							(mergecount, totalcount, pkg_key, y)
3268
						short_msg = "emerge: (%s of %s) %s Merge" % \
3269
							(mergecount, totalcount, pkg_key)
3270
						emergelog(xterm_titles, msg, short_msg=short_msg)
3271
						retval = portage.merge(pkgsettings["CATEGORY"],
3272
							pkgsettings["PF"], pkgsettings["D"],
3273
							os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3274
							"build-info"), myroot, pkgsettings,
3275
							myebuild=pkgsettings["EBUILD"],
3276
							mytree="porttree", mydbapi=portdb,
3277
							vartree=vartree, prev_mtimes=ldpath_mtimes)
3278
						if retval != os.EX_OK:
3279
							return retval
3280
					elif "noclean" not in pkgsettings.features:
3281
						portage.doebuild(y, "clean", myroot,
3282
							pkgsettings, self.edebug, mydbapi=portdb,
3283
							tree="porttree")
3284
				else:
3285
					msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3286
						(mergecount, totalcount, pkg_key, y)
3287
					short_msg = "emerge: (%s of %s) %s Compile" % \
3288
						(mergecount, totalcount, pkg_key)
3289
					emergelog(xterm_titles, msg, short_msg=short_msg)
3290
					retval = portage.doebuild(y, "merge", myroot,
3291
						pkgsettings, self.edebug, vartree=vartree,
3292
						mydbapi=portdb, tree="porttree",
3293
						prev_mtimes=ldpath_mtimes)
3294
					if retval != os.EX_OK:
3295
						return retval
3296
			finally:
3297
				if builddir_lock:
3298
					portage_locks.unlockdir(builddir_lock)
3299
				try:
3300
					if not catdir_lock:
3301
						# Lock catdir for removal if empty.
3302
						catdir_lock = portage_locks.lockdir(catdir)
3303
				finally:
3304
					if catdir_lock:
3305
						try:
3306
							os.rmdir(catdir)
3307
						except OSError, e:
3308
							if e.errno not in (errno.ENOENT,
3309
								errno.ENOTEMPTY, errno.EEXIST):
3310
								raise
3311
							del e
3312
						portage_locks.unlockdir(catdir_lock)
3313
3314
		elif x[0]=="binary":
3315
			#merge the tbz2
3316
			mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3317
			if "--getbinpkg" in self.myopts:
3318
				tbz2_lock = None
3319
				try:
3320
					if "distlocks" in pkgsettings.features and \
3321
						os.access(pkgsettings["PKGDIR"], os.W_OK):
3322
						portage_util.ensure_dirs(os.path.dirname(mytbz2))
3323
						tbz2_lock = portage_locks.lockfile(mytbz2,
3324
							wantnewlockfile=1)
3325
					if self.trees[myroot]["bintree"].isremote(pkg_key):
3326
						msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3327
							(mergecount, totalcount, pkg_key, mytbz2)
3328
						short_msg = "emerge: (%s of %s) %s Fetch" % \
3329
							(mergecount, totalcount, pkg_key)
3330
						emergelog(xterm_titles, msg, short_msg=short_msg)
3331
						if not self.trees[myroot]["bintree"].gettbz2(
3332
							pkg_key):
3333
							return 1
3334
				finally:
3335
					if tbz2_lock:
3336
						portage_locks.unlockfile(tbz2_lock)
3337
3338
			if "--fetchonly" in self.myopts or \
3339
				"--fetch-all-uri" in self.myopts:
3340
				return os.EX_OK
3341
3342
			short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
3343
			emergelog(xterm_titles, " === ("+str(mergecount)+\
3344
				" of "+str(totalcount)+") Merging Binary ("+\
3345
				x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3346
3347
			retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3348
				mydbapi=bindb,
3349
				vartree=self.trees[myroot]["vartree"],
3350
				prev_mtimes=ldpath_mtimes)
3351
			if retval != os.EX_OK:
3352
				return retval
3353
			#need to check for errors
3354
3355
		# clean up the older version which emerged on top of
3356
		if "--buildpkgonly" not in self.myopts and \
3357
			"--pretend" not in self.myopts and \
3358
			"--fetchonly" not in self.myopts and \
3359
			"--fetch-all-uri" not in self.myopts:
3360
			# Clean the old package that we have merged over top of it.
3361
			if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3362
				xsplit=portage.pkgsplit(x[2])
3363
				emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3364
				retval = unmerge(pkgsettings, self.myopts, vartree,
3365
					"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3366
				if not retval:
3367
					emergelog(xterm_titles,
3368
						" --- AUTOCLEAN: Nothing unmerged.")
3369
			else:
3370
				portage.writemsg_stdout(colorize("WARN", "WARNING:")
3371
					+ " AUTOCLEAN is disabled.  This can cause serious"
3372
					+ " problems due to overlapping packages.\n")
3373
3374
		if "--pretend" not in self.myopts and \
3375
			"--fetchonly" not in self.myopts and \
3376
			"--fetch-all-uri" not in self.myopts:
3377
			if "noclean" not in self.settings.features:
3378
				short_msg = "emerge: (%s of %s) %s Clean Post" % \
3379
					(mergecount, totalcount, x[pkgindex])
3380
				emergelog(xterm_titles, (" === (%s of %s) " + \
3381
					"Post-Build Cleaning (%s::%s)") % \
3382
					(mergecount, totalcount, x[pkgindex], y),
3383
					short_msg=short_msg)
3384
			emergelog(xterm_titles, " ::: completed emerge ("+\
3385
				str(mergecount)+" of "+str(totalcount)+") "+\
3386
				x[2]+" to "+x[1])
3387
3388
		return os.EX_OK
3389
3390
	def add_one_emerge_to_world(self, x, mergecount, totalcount, favorites, mysysdict):
3391
		xterm_titles = "notitles" not in self.settings.features
3392
		pkgindex=2
3393
		if x[0]=="blocks":
3394
			pkgindex=3
3395
3396
		if "--buildpkgonly" not in self.myopts:
3397
			self.trees[x[1]]["vartree"].inject(x[2])
3398
			myfavkey=portage.cpv_getkey(x[2])
3399
			if "--fetchonly" not in self.myopts and \
3400
				"--fetch-all-uri" not in self.myopts and \
3401
				myfavkey in favorites:
3402
				myfavs = portage.grabfile(os.path.join(x[1], portage.WORLD_FILE))
3403
				myfavdict=genericdict(myfavs)
3404
				#don't record if already in system profile or already recorded
3405
				if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3406
					#we don't have a favorites entry for this package yet; add one
3407
					myfavdict[myfavkey]=myfavkey
3408
					print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3409
					emergelog(xterm_titles, " === ("+\
3410
						str(mergecount)+" of "+\
3411
						str(totalcount)+\
3412
						") Updating world file ("+x[pkgindex]+")")
3413
					portage.write_atomic(
3414
					os.path.join(x[1], portage.WORLD_FILE),
3415
					"\n".join(myfavdict.values()))
3416
3417
	def print_status(self, totalcount, donec, qsize, failedc, spawnd_pkg, failed):
3418
		smsg = ""
3419
		fmsg = ""
3420
		if spawnd_pkg:
3421
			for pkgs in spawnd_pkg.values():
3422
				smsg = smsg+" "+pkgs[0][2]
3423
		if failed:
3424
			for pkgs in failed:
3425
				fmsg = fmsg+" "+pkgs
3426
		print ">>> Jobs [Total = "+colorize("blue", str(totalcount))+"] [Done = "+\
3427
			colorize("GOOD", str(donec))+"] [Running = "+colorize("WARN", str(qsize)+smsg)+\
3428
			"] [Failed = "+colorize("BAD", str(failedc)+fmsg)+"]"
3429
		xtermTitle("Jobs [Total="+str(totalcount)+"] [Done="+str(donec)+"] [Running="+str(qsize)+"] [Failed="+str(failedc)+"]")
3430
3431
	def wait_one_emerge(self, spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb):
3432
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3433
		# let's wait for one of the jobs to finish
3434
		onepid = -1
3435
		while onepid not in spawnd_pids:
3436
			onepid , retval = os.waitpid(-1, 0)
3437
		spawnd_pids.remove(onepid)
3438
3439
		pkg_compl = spawnd_pkg[onepid][0]
3440
		pkg_slot = spawnd_pkg[onepid][1]
3441
		del spawnd_pkg[onepid]
3442
3443
		if not retval:
3444
			# unlink the logid_path
3445
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl[2].split("/")[0]+"."+pkg_compl[2].split("/")[1]
3446
			if os.path.exists(logid_path):
3447
				os.unlink(logid_path)
3448
			index = 0
3449
			print ">>> Package "+colorize("GOOD", pkg_compl[2])+" finished emerging."
3450
			# we need to remove this pkg from resume DB
3451
			# this is the dirtiest shit I have ever written
3452
			for pkgs in mymergelist:
3453
				if pkgs[2] == pkg_compl[2]:
3454
					if len(mymergelist) > 1:
3455
						del mtimedb["resume"]["mergelist"][index]
3456
						mtimedb.commit()
3457
					del mymergelist[index]
3458
					# check if we need to restart portage
3459
					mysplit=portage.pkgsplit(pkg_compl[2])
3460
					if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3461
						self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3462
					break
3463
				index += 1
3464
		return (retval, pkg_compl)
3465
3466
	def merge(self, mylist, favorites, mtimedb, m_slots):
3003
		failed_fetches = []
3467
		failed_fetches = []
3004
		mymergelist=[]
3468
		mymergelist=[]
3005
		ldpath_mtimes = mtimedb["ldpath"]
3469
		ldpath_mtimes = mtimedb["ldpath"]
3006
		xterm_titles = "notitles" not in self.settings.features
3470
		xterm_titles = "notitles" not in self.settings.features
3471
		parallel = "parallel" in self.settings.features
3472
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3473
3474
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3475
		if self.edebug or "--fetchonly" in self.myopts:
3476
			parallel = False
3007
3477
3008
		#check for blocking dependencies
3478
		#check for blocking dependencies
3009
		if "--fetchonly" not in self.myopts and \
3479
		if "--fetchonly" not in self.myopts and \
Lines 3020-3027 Link Here
3020
3490
3021
		if "--resume" in self.myopts:
3491
		if "--resume" in self.myopts:
3022
			# We're resuming.
3492
			# We're resuming.
3023
			print colorize("GOOD", "*** Resuming merge...")
3024
			emergelog(xterm_titles, " *** Resuming merge...")
3025
			mylist = mtimedb["resume"]["mergelist"][:]
3493
			mylist = mtimedb["resume"]["mergelist"][:]
3026
			if "--skipfirst" in self.myopts and mylist:
3494
			if "--skipfirst" in self.myopts and mylist:
3027
				del mtimedb["resume"]["mergelist"][0]
3495
				del mtimedb["resume"]["mergelist"][0]
Lines 3049-3055 Link Here
3049
				if not shown_verifying_msg:
3517
				if not shown_verifying_msg:
3050
					shown_verifying_msg = True
3518
					shown_verifying_msg = True
3051
					print ">>> Verifying ebuild Manifests..."
3519
					print ">>> Verifying ebuild Manifests..."
3052
				mytype, myroot, mycpv, mystatus = x
3520
				mytype, myroot, mycpv, mystatus, slott = x
3053
				portdb = self.trees[myroot]["porttree"].dbapi
3521
				portdb = self.trees[myroot]["porttree"].dbapi
3054
				quiet_config = quiet_settings[myroot]
3522
				quiet_config = quiet_settings[myroot]
3055
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
3523
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
Lines 3087-3094 Link Here
3087
					os.path.join(self.target_root, portage.WORLD_FILE),
3555
					os.path.join(self.target_root, portage.WORLD_FILE),
3088
					"\n".join(myfavdict.values()))
3556
					"\n".join(myfavdict.values()))
3089
3557
3090
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3558
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
3091
			mtimedb.commit()
3559
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3560
				mtimedb.commit()
3561
3562
		totalcount = len(mymergelist)
3563
		mergecount=1
3564
3565
		if "--resume" in self.myopts and "--fetchonly" not in self.myopts:
3566
			# We're resuming.
3567
			print colorize("GOOD", "*** Resuming merge...")
3568
			emergelog(xterm_titles, " *** Resuming merge...")
3092
3569
3093
		myfeat = self.settings.features[:]
3570
		myfeat = self.settings.features[:]
3094
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3571
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 3106-3117 Link Here
3106
				print ">>> starting parallel fetching"
3583
				print ">>> starting parallel fetching"
3107
				fetch_log = "/var/log/emerge-fetch.log"
3584
				fetch_log = "/var/log/emerge-fetch.log"
3108
				logfile = open(fetch_log, "w")
3585
				logfile = open(fetch_log, "w")
3109
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3586
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
3110
				portage_util.apply_secpass_permissions(fetch_log,
3587
				portage_util.apply_secpass_permissions(fetch_log,
3111
					uid=portage.portage_uid, gid=portage.portage_gid,
3588
					uid=portage.portage_uid, gid=portage.portage_gid,
3112
					mode=0660)
3589
					mode=0660)
3113
				fetch_env = os.environ.copy()
3590
				fetch_env = os.environ.copy()
3114
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3591
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
3115
				fetch_env["PORTAGE_NICENESS"] = "0"
3592
				fetch_env["PORTAGE_NICENESS"] = "0"
3116
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3593
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3117
				resume_opts = self.myopts.copy()
3594
				resume_opts = self.myopts.copy()
Lines 3131-3441 Link Here
3131
				del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3608
				del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3132
					resume_opts
3609
					resume_opts
3133
3610
3134
		mergecount=0
3611
		if not parallel:
3135
		for x in mymergelist:
3612
			failed_fetches = []
3136
			mergecount+=1
3613
			for x in mymergelist:
3137
			myroot=x[1]
3614
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, mysysdict)
3138
			pkg_key = x[2]
3615
				mergecount += 1
3139
			pkgindex=2
3616
3140
			portdb = self.trees[myroot]["porttree"].dbapi
3617
				# need to short circuit the spawn with --nodeps
3141
			bindb  = self.trees[myroot]["bintree"].dbapi
3618
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
3142
			vartree = self.trees[myroot]["vartree"]
3619
					if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3143
			pkgsettings = self.pkgsettings[myroot]
3620
						continue
3144
			if x[0]=="blocks":
3621
					if retcode != os.EX_OK:
3145
				pkgindex=3
3622
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3146
			y = portdb.findname(pkg_key)
3623
							failed_fetches.append(x[2])
3624
							continue
3625
						else:
3626
							return retcode
3627
					# Unsafe for parallel merges
3628
					del mtimedb["resume"]["mergelist"][0]
3629
					# Commit after each merge so that --resume may still work in
3630
					# in the event that portage is not allowed to exit normally
3631
					# due to power failure, SIGKILL, etc...
3632
					mtimedb.commit()
3633
3634
					# unlink the logid_path if any exists
3635
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
3636
					if os.path.exists(logid_path):
3637
						os.unlink(logid_path)
3638
					del logid_path
3639
  
3640
					# check if we need to restart portage
3641
					mysplit=portage.pkgsplit(x[2])
3642
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3643
							self.restart_portage(x, mergecount, totalcount, mtimedb)
3644
  
3645
				else:
3646
					if retcode != os.EX_OK:
3647
						sys.exit(1)
3648
  					else:
3649
						sys.exit(0)
3650
  
3147
			if "--pretend" not in self.myopts:
3651
			if "--pretend" not in self.myopts:
3148
				print "\n>>> Emerging (" + \
3652
				emergelog(xterm_titles, " *** Finished. Cleaning up...")
3149
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3653
  
3150
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3654
			# We're out of the loop... We're done. Delete the resume data.
3151
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
3655
			if mtimedb.has_key("resume"):
3152
				emergelog(xterm_titles, " >>> emerge ("+\
3656
				del mtimedb["resume"]
3153
					str(mergecount)+" of "+str(len(mymergelist))+\
3657
			mtimedb.commit()
3154
					") "+x[pkgindex]+" to "+x[1])
3658
			
3155
3659
			#by doing an exit this way, --fetchonly can continue to try to
3156
			pkgsettings["EMERGE_FROM"] = x[0]
3660
			#fetch everything even if a particular download fails.
3157
			pkgsettings.backup_changes("EMERGE_FROM")
3661
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3158
			pkgsettings.reset()
3662
				if failed_fetches:
3159
3663
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
3160
			#buildsyspkg: Check if we need to _force_ binary package creation
3664
						"encountered.  Please see above for details.\n\n")
3161
			issyspkg = ("buildsyspkg" in myfeat) \
3665
					for cpv in failed_fetches:
3162
					and x[0] != "blocks" \
3666
						sys.stderr.write("   ")
3163
					and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3667
						sys.stderr.write(cpv)
3164
					and "--buildpkg" not in self.myopts
3668
						sys.stderr.write("\n")
3165
			if x[0] in ["ebuild","blocks"]:
3669
					sys.stderr.write("\n")
3166
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3670
					sys.exit(1)
3167
					raise Exception, "Merging a blocker"
3671
				else:
3168
				elif "--fetchonly" in self.myopts or \
3672
					sys.exit(0)
3169
					"--fetch-all-uri" in self.myopts:
3673
			return os.EX_OK
3170
					if "--fetch-all-uri" in self.myopts:
3674
  
3171
						retval = portage.doebuild(y, "fetch", myroot,
3675
		# parallel code - dirty starts here...;-)
3172
							pkgsettings, self.edebug,
3676
		one_in_slot_failed=0
3173
							"--pretend" in self.myopts, fetchonly=1,
3677
		spawnd_pids=[]
3174
							fetchall=1, mydbapi=portdb, tree="porttree")
3678
3175
					else:
3679
		# dirty little trick to get number of cpus from the system
3176
						retval = portage.doebuild(y, "fetch", myroot,
3680
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
3177
							pkgsettings, self.edebug,
3681
		cpu_count = 0
3178
							"--pretend" in self.myopts, fetchonly=1,
3682
		for data_cpuinfo in fd_cpuinfo.readlines():
3179
							mydbapi=portdb, tree="porttree")
3683
			if data_cpuinfo.find("cpu MHz") > -1 :
3180
					if (retval is None) or retval:
3684
				cpu_count += 1
3181
						print
3685
		fd_cpuinfo.close()
3182
						print "!!! Fetch for",y,"failed, continuing..."
3686
3183
						print
3687
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
3184
						failed_fetches.append(pkg_key)
3688
		if cpu_count == 0:
3185
					continue
3689
			cpu_count = 1
3186
3690
3187
				portage.doebuild_environment(y, "setup", myroot,
3691
		spawnd_pkg = {}
3188
					pkgsettings, self.edebug, 1, portdb)
3692
		donec = 0
3189
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3693
		failedc = 0
3190
				portage_util.ensure_dirs(os.path.dirname(catdir),
3694
		failedPkgs = []
3191
					uid=portage.portage_uid, gid=portage.portage_gid,
3695
		logid_path = None
3192
					mode=070, mask=0)
3696
		mylist = m_slots.keys()
3193
				builddir_lock = None
3697
		mylist.sort()
3194
				catdir_lock = None
3698
		for x in mylist:
3195
				try:
3699
			# if slot is empty, go on
3196
					catdir_lock = portage_locks.lockdir(catdir)
3700
			if not m_slots[x]:
3197
					portage_util.ensure_dirs(catdir,
3701
				continue
3198
						uid=portage.portage_uid, gid=portage.portage_gid,
3199
						mode=070, mask=0)
3200
					builddir_lock = portage_locks.lockdir(
3201
						pkgsettings["PORTAGE_BUILDDIR"])
3202
					try:
3203
						portage_locks.unlockdir(catdir_lock)
3204
					finally:
3205
						catdir_lock = None
3206
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
3207
						(mergecount, len(mymergelist), pkg_key, y)
3208
					short_msg = "emerge: (%s of %s) %s Clean" % \
3209
						(mergecount, len(mymergelist), pkg_key)
3210
					emergelog(xterm_titles, msg, short_msg=short_msg)
3211
					retval = portage.doebuild(y, "clean", myroot,
3212
						pkgsettings, self.edebug, cleanup=1,
3213
						mydbapi=portdb, tree="porttree")
3214
					if retval != os.EX_OK:
3215
						return retval
3216
					if "--buildpkg" in self.myopts or issyspkg:
3217
						if issyspkg:
3218
							print ">>> This is a system package, " + \
3219
								"let's pack a rescue tarball."
3220
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3221
							(mergecount, len(mymergelist), pkg_key, y)
3222
						short_msg = "emerge: (%s of %s) %s Compile" % \
3223
							(mergecount, len(mymergelist), pkg_key)
3224
						emergelog(xterm_titles, msg, short_msg=short_msg)
3225
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3226
						retval = portage.doebuild(y, "package", myroot,
3227
							pkgsettings, self.edebug, mydbapi=portdb,
3228
							tree="porttree")
3229
						if retval != os.EX_OK:
3230
							return retval
3231
						bintree = self.trees[myroot]["bintree"]
3232
						if bintree.populated:
3233
							bintree.inject(pkg_key)
3234
						if "--buildpkgonly" not in self.myopts:
3235
							msg = " === (%s of %s) Merging (%s::%s)" % \
3236
								(mergecount, len(mymergelist), pkg_key, y)
3237
							short_msg = "emerge: (%s of %s) %s Merge" % \
3238
								(mergecount, len(mymergelist), pkg_key)
3239
							emergelog(xterm_titles, msg, short_msg=short_msg)
3240
							retval = portage.merge(pkgsettings["CATEGORY"],
3241
								pkgsettings["PF"], pkgsettings["D"],
3242
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3243
								"build-info"), myroot, pkgsettings,
3244
								myebuild=pkgsettings["EBUILD"],
3245
								mytree="porttree", mydbapi=portdb,
3246
								vartree=vartree, prev_mtimes=ldpath_mtimes)
3247
							if retval != os.EX_OK:
3248
								return retval
3249
						elif "noclean" not in pkgsettings.features:
3250
							portage.doebuild(y, "clean", myroot,
3251
								pkgsettings, self.edebug, mydbapi=portdb,
3252
								tree="porttree")
3253
					else:
3254
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3255
							(mergecount, len(mymergelist), pkg_key, y)
3256
						short_msg = "emerge: (%s of %s) %s Compile" % \
3257
							(mergecount, len(mymergelist), pkg_key)
3258
						emergelog(xterm_titles, msg, short_msg=short_msg)
3259
						retval = portage.doebuild(y, "merge", myroot,
3260
							pkgsettings, self.edebug, vartree=vartree,
3261
							mydbapi=portdb, tree="porttree",
3262
							prev_mtimes=ldpath_mtimes)
3263
						if retval != os.EX_OK:
3264
							return retval
3265
				finally:
3266
					if builddir_lock:
3267
						portage_locks.unlockdir(builddir_lock)
3268
					try:
3269
						if not catdir_lock:
3270
							# Lock catdir for removal if empty.
3271
							catdir_lock = portage_locks.lockdir(catdir)
3272
					finally:
3273
						if catdir_lock:
3274
							try:
3275
								os.rmdir(catdir)
3276
							except OSError, e:
3277
								if e.errno not in (errno.ENOENT,
3278
									errno.ENOTEMPTY, errno.EEXIST):
3279
									raise
3280
								del e
3281
							portage_locks.unlockdir(catdir_lock)
3282
3283
			elif x[0]=="binary":
3284
				#merge the tbz2
3285
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3286
				if "--getbinpkg" in self.myopts:
3287
					tbz2_lock = None
3288
					try:
3289
						if "distlocks" in pkgsettings.features and \
3290
							os.access(pkgsettings["PKGDIR"], os.W_OK):
3291
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
3292
							tbz2_lock = portage_locks.lockfile(mytbz2,
3293
								wantnewlockfile=1)
3294
						if self.trees[myroot]["bintree"].isremote(pkg_key):
3295
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3296
								(mergecount, len(mymergelist), pkg_key, mytbz2)
3297
							short_msg = "emerge: (%s of %s) %s Fetch" % \
3298
								(mergecount, len(mymergelist), pkg_key)
3299
							emergelog(xterm_titles, msg, short_msg=short_msg)
3300
							if not self.trees[myroot]["bintree"].gettbz2(
3301
								pkg_key):
3302
								return 1
3303
					finally:
3304
						if tbz2_lock:
3305
							portage_locks.unlockfile(tbz2_lock)
3306
3307
				if "--fetchonly" in self.myopts or \
3308
					"--fetch-all-uri" in self.myopts:
3309
					continue
3310
3702
3311
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3703
			# if previous slot failed, discontinue the emerge
3312
				emergelog(xterm_titles, " === ("+str(mergecount)+\
3704
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
3313
					" of "+str(len(mymergelist))+") Merging Binary ("+\
3705
				break
3314
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3315
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3316
					mydbapi=bindb,
3317
					vartree=self.trees[myroot]["vartree"],
3318
					prev_mtimes=ldpath_mtimes)
3319
				if retval != os.EX_OK:
3320
					return retval
3321
				#need to check for errors
3322
			if "--buildpkgonly" not in self.myopts:
3323
				self.trees[x[1]]["vartree"].inject(x[2])
3324
				myfavkey=portage.cpv_getkey(x[2])
3325
				if "--fetchonly" not in self.myopts and \
3326
					"--fetch-all-uri" not in self.myopts and \
3327
					myfavkey in favorites:
3328
					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3329
					myfavdict=genericdict(myfavs)
3330
					#don't record if already in system profile or already recorded
3331
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3332
						#we don't have a favorites entry for this package yet; add one
3333
						myfavdict[myfavkey]=myfavkey
3334
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3335
						emergelog(xterm_titles, " === ("+\
3336
							str(mergecount)+" of "+\
3337
							str(len(mymergelist))+\
3338
							") Updating world file ("+x[pkgindex]+")")
3339
						portage.write_atomic(
3340
						os.path.join(myroot, portage.WORLD_FILE),
3341
						"\n".join(myfavdict.values()))
3342
3343
				if "--pretend" not in self.myopts and \
3344
					"--fetchonly" not in self.myopts and \
3345
					"--fetch-all-uri" not in self.myopts:
3346
					# Clean the old package that we have merged over top of it.
3347
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3348
						xsplit=portage.pkgsplit(x[2])
3349
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3350
						retval = unmerge(pkgsettings, self.myopts, vartree,
3351
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3352
						if not retval:
3353
							emergelog(xterm_titles,
3354
								" --- AUTOCLEAN: Nothing unmerged.")
3355
					else:
3356
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
3357
							+ " AUTOCLEAN is disabled.  This can cause serious"
3358
							+ " problems due to overlapping packages.\n")
3359
3706
3360
					# Figure out if we need a restart.
3707
			# start multiple merges in parallel mode
3361
					mysplit=portage.pkgsplit(x[2])
3708
			num_at_atime = cpu_count + 1
3362
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3363
						myver=mysplit[1]+"-"+mysplit[2]
3364
						if myver[-3:]=='-r0':
3365
							myver=myver[:-3]
3366
						if (myver != portage.VERSION) and \
3367
						   "livecvsportage" not in self.settings.features:
3368
							if len(mymergelist) > mergecount:
3369
								emergelog(xterm_titles,
3370
									" ::: completed emerge ("+ \
3371
									str(mergecount)+" of "+ \
3372
									str(len(mymergelist))+") "+ \
3373
									x[2]+" to "+x[1])
3374
								emergelog(xterm_titles, " *** RESTARTING " + \
3375
									"emerge via exec() after change of " + \
3376
									"portage version.")
3377
								del mtimedb["resume"]["mergelist"][0]
3378
								mtimedb.commit()
3379
								portage.run_exitfuncs()
3380
								mynewargv=[sys.argv[0],"--resume"]
3381
								resume_opts = self.myopts.copy()
3382
								# For automatic resume, we need to prevent
3383
								# any of bad_resume_opts from leaking in
3384
								# via EMERGE_DEFAULT_OPTS.
3385
								resume_opts["--ignore-default-opts"] = True
3386
								for myopt, myarg in resume_opts.iteritems():
3387
									if myopt not in bad_resume_opts:
3388
										if myarg is True:
3389
											mynewargv.append(myopt)
3390
										else:
3391
											mynewargv.append(myopt +"="+ myarg)
3392
								# priority only needs to be adjusted on the first run
3393
								os.environ["PORTAGE_NICENESS"] = "0"
3394
								os.execv(mynewargv[0], mynewargv)
3395
3396
			if "--pretend" not in self.myopts and \
3397
				"--fetchonly" not in self.myopts and \
3398
				"--fetch-all-uri" not in self.myopts:
3399
				if "noclean" not in self.settings.features:
3400
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
3401
						(mergecount, len(mymergelist), x[pkgindex])
3402
					emergelog(xterm_titles, (" === (%s of %s) " + \
3403
						"Post-Build Cleaning (%s::%s)") % \
3404
						(mergecount, len(mymergelist), x[pkgindex], y),
3405
						short_msg=short_msg)
3406
				emergelog(xterm_titles, " ::: completed emerge ("+\
3407
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
3408
					x[2]+" to "+x[1])
3409
3709
3410
			# Unsafe for parallel merges
3710
			qsize = 0
3411
			del mtimedb["resume"]["mergelist"][0]
3711
			for y in m_slots[x]:
3412
			# Commit after each merge so that --resume may still work in
3712
				# these all can go in parallel, so fork one after the other
3413
			# in the event that portage is not allowed to exit normally
3713
				# but num_at_atime at most
3414
			# due to power failure, SIGKILL, etc...
3714
				if num_at_atime:
3415
			mtimedb.commit()
3715
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3716
					spawnd_pids.append(onepid)
3717
					spawnd_pkg[onepid] = (y, x)
3718
					num_at_atime -= 1
3719
					mergecount += 1
3720
					qsize += 1
3721
				else:
3722
					self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3723
					# let's wait for one of the jobs to finish
3724
					(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
3725
3726
					# if it failed, I need to fail next slot but continue to merge all in this slot
3727
					if retval:
3728
						one_in_slot_failed = retval
3729
						failedc += 1
3730
						failedPkgs.append(pkg_compl[2])
3731
  					else:
3732
						donec += 1
3733
						self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, mysysdict)
3734
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3735
					spawnd_pids.append(onepid)
3736
					spawnd_pkg[onepid] = (y, x)
3737
					mergecount += 1
3738
3739
			# this slot is exhausted, so wait for all of the forks to finish
3740
			while spawnd_pids:
3741
				self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3742
				# let's wait for one of the jobs to finish
3743
				(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
3744
3745
				qsize -= 1
3746
				if retval:
3747
					one_in_slot_failed = retval
3748
					failedc += 1
3749
					failedPkgs.append(pkg_compl[2])
3750
				else:
3751
					donec += 1
3752
					self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, mysysdict)
3753
		if totalcount:
3754
			self.print_status(totalcount, donec, qsize, failedc, None, failedPkgs)
3755
  
3756
		if one_in_slot_failed:
3757
			portage.writemsg_stdout(red("\nSome packages failed to emerge, summary follows:\n"))
3758
  
3759
		for pkgs in failedPkgs:
3760
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3761
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
3762
				sys.exit(1)
3416
3763
3764
			portage.writemsg_stdout(red("\nPackage "+pkgs+" failed to emerge\n"))
3765
			logfile = None
3766
			if "PORT_LOGDIR" in self.settings:
3767
				port_logdir = self.settings["PORT_LOGDIR"]
3768
			else:
3769
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3770
3771
			pkg_cat = pkgs.split("/")[0]
3772
			pkg_pf = pkgs.split("/")[1]
3773
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
3774
			if os.path.exists(logid_path):
3775
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
3776
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3777
					(pkg_cat, pkg_pf, logid_time))
3778
				del logid_time
3779
3780
			if logfile and os.path.exists(logfile):
3781
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
3782
3783
			if logfile and os.path.exists(logfile):
3784
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
3785
				os.unlink(logid_path)
3786
		if one_in_slot_failed:
3787
			sys.exit(1)
3417
		if "--pretend" not in self.myopts:
3788
		if "--pretend" not in self.myopts:
3418
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3789
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3419
3790
3791
		# see if there are any extraneous files in build_prefix, which we might have leftover
3792
		import glob
3793
		for fnames in glob.glob(os.path.join(build_prefix, ".logid.")+"*"):
3794
			os.unlink(fnames)
3795
3420
		# We're out of the loop... We're done. Delete the resume data.
3796
		# We're out of the loop... We're done. Delete the resume data.
3421
		if mtimedb.has_key("resume"):
3797
		if mtimedb.has_key("resume"):
3422
			del mtimedb["resume"]
3798
			del mtimedb["resume"]
3423
		mtimedb.commit()
3799
		mtimedb.commit()
3424
3800
3425
		#by doing an exit this way, --fetchonly can continue to try to
3426
		#fetch everything even if a particular download fails.
3427
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3801
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3428
			if failed_fetches:
3802
			sys.exit(0)
3429
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
3803
3430
					"encountered.  Please see above for details.\n\n")
3431
				for cpv in failed_fetches:
3432
					sys.stderr.write("   ")
3433
					sys.stderr.write(cpv)
3434
					sys.stderr.write("\n")
3435
				sys.stderr.write("\n")
3436
				sys.exit(1)
3437
			else:
3438
				sys.exit(0)
3439
		return os.EX_OK
3804
		return os.EX_OK
3440
3805
3441
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3806
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
Lines 3876-3882 Link Here
3876
def validate_merge_list(trees, mergelist):
4241
def validate_merge_list(trees, mergelist):
3877
	"""Validate the list to make sure all the packages are still available.
4242
	"""Validate the list to make sure all the packages are still available.
3878
	This is needed for --resume."""
4243
	This is needed for --resume."""
3879
	for (pkg_type, myroot, pkg_key, action) in mergelist:
4244
	for (pkg_type, myroot, pkg_key, action, merge_slot) in mergelist:
3880
		if pkg_type == "binary" and \
4245
		if pkg_type == "binary" and \
3881
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4246
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3882
			pkg_type == "ebuild" and \
4247
			pkg_type == "ebuild" and \
Lines 4777-4783 Link Here
4777
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
5142
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4778
		emergelog(xterm_titles, " >>> depclean")
5143
		emergelog(xterm_titles, " >>> depclean")
4779
5144
4780
	if "--quiet" not in myopts:
5145
	if "--quiet" not in myopts and "--nodeps" not in myopts:
4781
		print "\nCalculating dependencies  ",
5146
		print "\nCalculating dependencies  ",
4782
5147
4783
	soft = 0
5148
	soft = 0
Lines 4885-4890 Link Here
4885
	else:
5250
	else:
4886
		print "Number removed:       "+str(len(cleanlist))
5251
		print "Number removed:       "+str(len(cleanlist))
4887
5252
5253
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
5254
	merge_slots = {}
5255
	for pkg in mergelist:
5256
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
5257
			slot = int(pkg[4])
5258
			try:
5259
				if pkg not in merge_slots[slot]:
5260
					merge_slots[slot].append(pkg)
5261
			except KeyError:
5262
				merge_slots[slot] = [pkg]
5263
	# print the merge slots
5264
	max_slot = 0
5265
	mylist = merge_slots.keys()
5266
	mylist.sort()
5267
	for x in mylist:
5268
		if x > max_slot:
5269
			max_slot = x
5270
		if parallel:
5271
			print "Package list for slot = "+str(x)
5272
			for y in merge_slots[x]:
5273
				print "	",y
5274
	if printonly:
5275
		return
5276
5277
	# make one last pass at the merge_slots and initialize the missing slots to None
5278
	x = 0
5279
	while x < max_slot:
5280
		if x not in merge_slots.keys():
5281
			merge_slots[x] = None
5282
		x += 1
5283
	return merge_slots
5284
4888
def action_build(settings, trees, mtimedb,
5285
def action_build(settings, trees, mtimedb,
4889
	myopts, myaction, myfiles, spinner):
5286
	myopts, myaction, myfiles, spinner):
4890
	ldpath_mtimes = mtimedb["ldpath"]
5287
	ldpath_mtimes = mtimedb["ldpath"]
Lines 5003-5015 Link Here
5003
			if len(mymergelist) == 0:
5400
			if len(mymergelist) == 0:
5004
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5401
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5005
				sys.exit(0)
5402
				sys.exit(0)
5403
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5006
			mydepgraph.display(mymergelist)
5404
			mydepgraph.display(mymergelist)
5007
			prompt="Would you like to resume merging these packages?"
5405
			prompt="Would you like to resume merging these packages?"
5008
		else:
5406
		else:
5009
			mydepgraph.display(
5407
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5010
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5408
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5409
			mydepgraph.display(mymergelist)
5011
			mergecount=0
5410
			mergecount=0
5012
			for x in mydepgraph.altlist():
5411
			for x in mymergelist:
5013
				if x[0] != "blocks" and x[3] != "nomerge":
5412
				if x[0] != "blocks" and x[3] != "nomerge":
5014
					mergecount+=1
5413
					mergecount+=1
5015
				#check for blocking dependencies
5414
				#check for blocking dependencies
Lines 5054-5063 Link Here
5054
			if len(mymergelist) == 0:
5453
			if len(mymergelist) == 0:
5055
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5454
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5056
				sys.exit(0)
5455
				sys.exit(0)
5456
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5057
			mydepgraph.display(mymergelist)
5457
			mydepgraph.display(mymergelist)
5058
		else:
5458
		else:
5059
			mydepgraph.display(
5459
			# mydepgraph.digraph.debug_print()
5060
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5460
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5461
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5462
			mydepgraph.display(mymergelist)
5061
			if "--buildpkgonly" in myopts and \
5463
			if "--buildpkgonly" in myopts and \
5062
				not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5464
				not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5063
					print "\n!!! --buildpkgonly requires all dependencies to be merged."
5465
					print "\n!!! --buildpkgonly requires all dependencies to be merged."
Lines 5078-5100 Link Here
5078
				it to write the mtimedb"""
5480
				it to write the mtimedb"""
5079
				mtimedb.filename = None
5481
				mtimedb.filename = None
5080
				time.sleep(3) # allow the parent to have first fetch
5482
				time.sleep(3) # allow the parent to have first fetch
5483
			mymergelist = mtimedb["resume"]["mergelist"]
5484
			if "--skipfirst" in myopts:
5485
				mymergelist = mymergelist[1:]
5486
			if len(mymergelist) == 0:
5487
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5488
				sys.exit(0)
5489
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
5081
			del mydepgraph
5490
			del mydepgraph
5082
			retval = mergetask.merge(
5491
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
5083
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
5084
			if retval != os.EX_OK:
5492
			if retval != os.EX_OK:
5085
				sys.exit(retval)
5493
				sys.exit(retval)
5086
		else:
5494
		else:
5087
			if "resume" in mtimedb and \
5495
			mymergelist = mydepgraph.altlist()
5088
			"mergelist" in mtimedb["resume"] and \
5496
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
5089
			len(mtimedb["resume"]["mergelist"]) > 1:
5497
			if "--nodeps" not in myopts or len(mymergelist) > 1:
5090
				mtimedb["resume_backup"] = mtimedb["resume"]
5498
				if "resume" in mtimedb and \
5091
				del mtimedb["resume"]
5499
				"mergelist" in mtimedb["resume"] and \
5092
				mtimedb.commit()
5500
				len(mtimedb["resume"]["mergelist"]) > 1:
5093
			mtimedb["resume"]={}
5501
					mtimedb["resume_backup"] = mtimedb["resume"]
5094
			# XXX: Stored as a list for backward compatibility.
5502
					del mtimedb["resume"]
5095
			mtimedb["resume"]["myopts"] = \
5503
					mtimedb.commit()
5096
				[k for k in myopts if myopts[k] is True]
5504
				mtimedb["resume"]={}
5097
			mtimedb["resume"]["favorites"]=favorites
5505
				# XXX: Stored as a list for backward compatibility.
5506
				mtimedb["resume"]["myopts"] = \
5507
					[k for k in myopts if myopts[k] is True]
5508
				mtimedb["resume"]["favorites"]=favorites
5098
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5509
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5099
				for pkgline in mydepgraph.altlist():
5510
				for pkgline in mydepgraph.altlist():
5100
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5511
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 5110-5127 Link Here
5110
							tree="porttree")
5521
							tree="porttree")
5111
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5522
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5112
				pkglist = []
5523
				pkglist = []
5113
				for pkg in mydepgraph.altlist():
5524
				for pkg in mymergelist:
5114
					if pkg[0] != "blocks":
5525
					if pkg[0] != "blocks":
5115
						pkglist.append(pkg)
5526
						pkglist.append(pkg)
5116
			else:
5527
			else:
5117
				pkglist = mydepgraph.altlist()
5528
				pkglist = mymergelist
5118
			del mydepgraph
5529
			del mydepgraph
5119
			mergetask = MergeTask(settings, trees, myopts)
5530
			mergetask = MergeTask(settings, trees, myopts)
5120
			retval = mergetask.merge(pkglist, favorites, mtimedb)
5531
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
5121
			if retval != os.EX_OK:
5532
			if retval != os.EX_OK:
5122
				sys.exit(retval)
5533
				sys.exit(retval)
5123
5534
5124
		if mtimedb.has_key("resume"):
5535
		if mtimedb.has_key("resume") and ("--nodeps" not in myopts or len(mymergelist) > 1):
5125
			del mtimedb["resume"]
5536
			del mtimedb["resume"]
5126
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5537
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5127
			portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5538
			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 2246-2264 Link Here
2246
	mypids = []
2246
	mypids = []
2247
	pw = None
2247
	pw = None
2248
	if logfile:
2248
	if logfile:
2249
		del keywords["logfile"]
2249
		tee_good = 1
2250
		fd_pipes = keywords.get("fd_pipes")
2250
		fd_pipes = keywords.get("fd_pipes")
2251
		if fd_pipes is None:
2251
		if fd_pipes is None:
2252
			fd_pipes = {0:0, 1:1, 2:2}
2252
			fd_pipes = {0:0, 1:1, 2:2}
2253
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2253
		elif 1 not in fd_pipes or 2 not in fd_pipes:
2254
			raise ValueError(fd_pipes)
2254
			raise ValueError(fd_pipes)
2255
		pr, pw = os.pipe()
2255
		try:
2256
		mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2256
			statinfo1 = os.stat(logfile)
2257
			 returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2257
			statinfo2 = os.fstat(fd_pipes[1])
2258
		os.close(pr)
2258
			statinfo3 = os.fstat(fd_pipes[2])
2259
		fd_pipes[1] = pw
2259
			# if they are pointing to same file as logfile, no 'tee' is required.
2260
		fd_pipes[2] = pw
2260
			if statinfo1 == statinfo2 and statinfo2 == statinfo3:
2261
		keywords["fd_pipes"] = fd_pipes
2261
				tee_good = 0
2262
		except:
2263
			tee_good = 1
2264
2265
		if tee_good:
2266
2267
			del keywords["logfile"]
2268
			pr, pw = os.pipe()
2269
			mypids.extend(portage_exec.spawn(('tee', '-i', '-a', logfile),
2270
			 	returnpid=True, fd_pipes={0:pr, 1:fd_pipes[1], 2:fd_pipes[2]}))
2271
			os.close(pr)
2272
			fd_pipes[1] = pw
2273
			fd_pipes[2] = pw
2274
			keywords["fd_pipes"] = fd_pipes
2262
2275
2263
	features = mysettings.features
2276
	features = mysettings.features
2264
	restrict = mysettings.get("PORTAGE_RESTRICT","").split()
2277
	restrict = mysettings.get("PORTAGE_RESTRICT","").split()
Lines 3355-3360 Link Here
3355
	if mysettings.get("PORT_LOGDIR", "") == "":
3368
	if mysettings.get("PORT_LOGDIR", "") == "":
3356
		while "PORT_LOGDIR" in mysettings:
3369
		while "PORT_LOGDIR" in mysettings:
3357
			del mysettings["PORT_LOGDIR"]
3370
			del mysettings["PORT_LOGDIR"]
3371
3372
	if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
3373
		mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + DEF_LOGDIR
3374
3358
	if "PORT_LOGDIR" in mysettings:
3375
	if "PORT_LOGDIR" in mysettings:
3359
		try:
3376
		try:
3360
			modified = portage_util.ensure_dirs(mysettings["PORT_LOGDIR"])
3377
			modified = portage_util.ensure_dirs(mysettings["PORT_LOGDIR"])
Lines 3369-3375 Link Here
3369
			while "PORT_LOGDIR" in mysettings:
3386
			while "PORT_LOGDIR" in mysettings:
3370
				del mysettings["PORT_LOGDIR"]
3387
				del mysettings["PORT_LOGDIR"]
3371
	if "PORT_LOGDIR" in mysettings:
3388
	if "PORT_LOGDIR" in mysettings:
3372
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
3389
		logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
3373
		if not os.path.exists(logid_path):
3390
		if not os.path.exists(logid_path):
3374
			f = open(logid_path, "w")
3391
			f = open(logid_path, "w")
3375
			f.close()
3392
			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