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.12.orig/bin/emerge (-328 / +739 lines)
Lines 2034-2039 Link Here
2034
		ignore_priority_soft_range.extend(
2034
		ignore_priority_soft_range.extend(
2035
			xrange(DepPriority.MIN, DepPriority.SOFT + 1))
2035
			xrange(DepPriority.MIN, DepPriority.SOFT + 1))
2036
		tree_mode = "--tree" in self.myopts
2036
		tree_mode = "--tree" in self.myopts
2037
		slotcount = 0
2038
2037
		# Tracks whether or not the current iteration should prefer asap_nodes
2039
		# Tracks whether or not the current iteration should prefer asap_nodes
2038
		# if available.  This is set to False when the previous iteration
2040
		# if available.  This is set to False when the previous iteration
2039
		# failed to select any nodes.  It is reset whenever nodes are
2041
		# failed to select any nodes.  It is reset whenever nodes are
Lines 2206-2212 Link Here
2206
2208
2207
			for node in selected_nodes:
2209
			for node in selected_nodes:
2208
				if node[-1] != "nomerge":
2210
				if node[-1] != "nomerge":
2209
					retlist.append(list(node))
2211
					node2 = list(node)
2212
					if len(node2) == 4:
2213
						node2.append(str(slotcount))
2214
					retlist.append(node2)
2210
				mygraph.remove(node)
2215
				mygraph.remove(node)
2211
				if not reversed and not circular_blocks and myblockers.contains(node):
2216
				if not reversed and not circular_blocks and myblockers.contains(node):
2212
					"""This node may have invalidated one or more blockers."""
2217
					"""This node may have invalidated one or more blockers."""
Lines 2220-2225 Link Here
2220
								self.blocker_parents[blocker] = unresolved
2225
								self.blocker_parents[blocker] = unresolved
2221
							else:
2226
							else:
2222
								del self.blocker_parents[blocker]
2227
								del self.blocker_parents[blocker]
2228
			slotcount += 1
2223
2229
2224
		if not reversed:
2230
		if not reversed:
2225
			"""Blocker validation does not work with reverse mode,
2231
			"""Blocker validation does not work with reverse mode,
Lines 2436-2442 Link Here
2436
			if "blocks" == x[0]:
2442
			if "blocks" == x[0]:
2437
				display_list.append((x, 0, True))
2443
				display_list.append((x, 0, True))
2438
				continue
2444
				continue
2439
			graph_key = tuple(x)
2445
			if len(x) > 4:
2446
				graph_key = tuple(x[:-1])
2447
			else:
2448
				graph_key = tuple(x)
2440
			if "--tree" in self.myopts:
2449
			if "--tree" in self.myopts:
2441
				depth = len(tree_nodes)
2450
				depth = len(tree_nodes)
2442
				while depth and graph_key not in \
2451
				while depth and graph_key not in \
Lines 2498-2504 Link Here
2498
				continue
2507
				continue
2499
			if "blocks" == graph_key[0]:
2508
			if "blocks" == graph_key[0]:
2500
				continue
2509
				continue
2501
			if ordered and graph_key[-1] != "nomerge":
2510
			if len(graph_key) > 4:
2511
				merge_op = graph_key[-2]
2512
			else:
2513
				merge_op = graph_key[-1]
2514
			if ordered and merge_op != "nomerge":
2502
				last_merge_depth = depth
2515
				last_merge_depth = depth
2503
				continue
2516
				continue
2504
			if depth >= last_merge_depth or \
2517
			if depth >= last_merge_depth or \
Lines 2720-2726 Link Here
2720
				if verbosity == 3:
2733
				if verbosity == 3:
2721
					# size verbose
2734
					# size verbose
2722
					mysize=0
2735
					mysize=0
2723
					if x[0] == "ebuild" and ordered and x[-1] != "nomerge":
2736
					if len(x) > 4:
2737
						merge_op = x[-2]
2738
					else:
2739
						merge_op = x[-1]
2740
					if x[0] == "ebuild" and ordered and merge_op != "nomerge":
2724
						try:
2741
						try:
2725
							myfilesdict = portdb.getfetchsizes(pkg_key,
2742
							myfilesdict = portdb.getfetchsizes(pkg_key,
2726
								useflags=self.useFlags[myroot][pkg_key],
2743
								useflags=self.useFlags[myroot][pkg_key],
Lines 2799-2805 Link Here
2799
							myprint=myprint+myoldbest
2816
							myprint=myprint+myoldbest
2800
							myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2817
							myprint=myprint+darkgreen("to "+x[1])+" "+verboseadd
2801
					else:
2818
					else:
2802
						if x[-1] == "nomerge" or not ordered:
2819
						if len(x) > 4:
2820
							merge_op = x[-2]
2821
						else:
2822
							merge_op = x[-1]
2823
						if merge_op == "nomerge" or not ordered:
2803
							myprint = darkblue("[nomerge      ] ")
2824
							myprint = darkblue("[nomerge      ] ")
2804
						else:
2825
						else:
2805
							myprint = "[" + pkg_type + " " + addl + "] "
2826
							myprint = "[" + pkg_type + " " + addl + "] "
Lines 3010-3020 Link Here
3010
			self.pkgsettings["/"] = \
3031
			self.pkgsettings["/"] = \
3011
				portage.config(clone=trees["/"]["vartree"].settings)
3032
				portage.config(clone=trees["/"]["vartree"].settings)
3012
3033
3013
	def merge(self, mylist, favorites, mtimedb):
3034
	def restart_portage(self, x, mergecount, totalcount, mtimedb):
3035
		xterm_titles = "notitles" not in self.settings.features
3036
		# don't really restart if any of these is true
3037
		# XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
3038
		if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
3039
			"--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
3040
			return
3041
3042
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3043
			"--resume"])
3044
		mysplit=portage.pkgsplit(x[2])
3045
		myver=mysplit[1]+"-"+mysplit[2]
3046
		if myver[-3:]=='-r0':
3047
			myver=myver[:-3]
3048
		if (myver != portage.VERSION) and \
3049
		   "livecvsportage" not in self.settings.features:
3050
			if totalcount > mergecount:
3051
				emergelog(xterm_titles,
3052
					" ::: completed emerge ("+ \
3053
					str(mergecount)+" of "+ \
3054
					str(totalcount)+") "+ \
3055
					x[2]+" to "+x[1])
3056
				emergelog(xterm_titles, " *** RESTARTING " + \
3057
					"emerge via exec() after change of " + \
3058
					"portage version.")
3059
				portage.run_exitfuncs()
3060
				mynewargv=[sys.argv[0],"--resume"]
3061
				resume_opts = self.myopts.copy()
3062
				# For automatic resume, we need to prevent
3063
				# any of bad_resume_opts from leaking in
3064
				# via EMERGE_DEFAULT_OPTS.
3065
				resume_opts["--ignore-default-opts"] = True
3066
				for myopt, myarg in resume_opts.iteritems():
3067
					if myopt not in bad_resume_opts:
3068
						if myarg is True:
3069
							mynewargv.append(myopt)
3070
						else:
3071
							mynewargv.append(myopt +"="+ myarg)
3072
				# priority only needs to be adjusted on the first run
3073
				os.environ["PORTAGE_NICENESS"] = "0"
3074
				os.execv(mynewargv[0], mynewargv)
3075
3076
	def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
3077
		xterm_titles = "notitles" not in self.settings.features
3078
		myfeat = self.settings.features[:]
3079
		ldpath_mtimes = mtimedb["ldpath"]
3080
		myroot=x[1]
3081
		pkg_key = x[2]
3082
		pkg_cat = x[2].split("/")[0]
3083
		pkg_pf = x[2].split("/")[1]
3084
		pkgindex=2
3085
		if x[0]=="blocks":
3086
			pkgindex=3
3087
3088
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3089
		portage_util.ensure_dirs(build_prefix, uid=portage.portage_uid, gid=portage.portage_gid, mode=0775)
3090
3091
		logid_path = None
3092
		null_log = 0
3093
3094
		if self.settings.get("PORT_LOGDIR", "") == "":
3095
			while "PORT_LOGDIR" in self.settings:
3096
				del self.settings["PORT_LOGDIR"]
3097
		if "PORT_LOGDIR" in self.settings:
3098
			port_logdir = self.settings["PORT_LOGDIR"]
3099
		else:
3100
			port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3101
3102
		try:
3103
			portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
3104
						 gid=portage.portage_gid, mode=02770)
3105
		except portage_exception.PortageException, e:
3106
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
3107
			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
3108
				self.settings["PORT_LOGDIR"], noiselevel=-1)
3109
			writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
3110
			null_log = 1
3111
3112
		if not null_log:
3113
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
3114
			if not os.path.exists(logid_path):
3115
				f = open(logid_path, "w")
3116
				f.close()
3117
				del f
3118
			logid_time = time.strftime("%Y%m%d-%H%M%S",
3119
				time.gmtime(os.stat(logid_path).st_mtime))
3120
			logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3121
				(pkg_cat, pkg_pf, logid_time))
3122
			del logid_time
3123
		else:
3124
			logfile = "/dev/null"
3125
3126
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
3127
			print ">>> Emerging (" + \
3128
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3129
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
3130
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
3131
			print ">>> Logfile in " + logfile
3132
			emergelog(xterm_titles, " >>> emerge ("+\
3133
				str(mergecount)+" of "+str(totalcount)+\
3134
				") "+x[pkgindex]+" to "+x[1])
3135
3136
		# need to spawn a --nodeps emerge in a separate process.
3137
		pkg="="+x[2]
3138
		merge_env = os.environ.copy()
3139
		merge_env["PORTAGE_INTERNAL_CALL"] = "1"
3140
		merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
3141
		merge_args = [sys.argv[0], "--nodeps", "--oneshot", "--nospinner", pkg]
3142
		good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
3143
					"--usepkg", "--usepkgonly"])
3144
		fd_pipes = None
3145
		merge_logfd = None
3146
		for myopt, myarg in self.myopts.iteritems():
3147
			# don't clobber the logfile at the same time as parallel fetch is
3148
			# all log of parallel fetch will go /var/log/emerge-fetch.log
3149
			# so, just leave 0,1,2 alone.
3150
			if "parallel-fetch" in myfeat and myopt == "--fetchonly":
3151
				fd_pipes = {0:0, 1:1, 2:2}
3152
			if myopt in good_nodeps_opts:
3153
				if myarg is True:
3154
					merge_args.append(myopt)
3155
				else:
3156
					merge_args.append(myopt +"="+ myarg)
3157
		if not fd_pipes:
3158
			merge_logfd = open(logfile, "w")
3159
			# put in a start message. This also makes sure that this fd is pointing to a good file on disk
3160
			# and hence will be used throughout the other spawns that will happen in the children.
3161
			merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
3162
			merge_logfd.flush()
3163
			fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
3164
			portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
3165
3166
		mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
3167
		if merge_logfd:
3168
			merge_logfd.close() # child has exclusive rights to it now.
3169
		return mypids[0]
3170
3171
	def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, mysysdict):
3172
		xterm_titles = "notitles" not in self.settings.features
3173
		myfeat = self.settings.features[:]
3174
		ldpath_mtimes = mtimedb["ldpath"]
3175
		myroot=x[1]
3176
		pkg_key = x[2]
3177
		pkg_cat = x[2].split("/")[0]
3178
		pkg_pf = x[2].split("/")[1]
3179
		pkgindex=2
3180
		if x[0]=="blocks":
3181
			pkgindex=3
3182
3183
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
3184
			print "\n>>> Emerging (" + \
3185
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3186
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
3187
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
3188
			emergelog(xterm_titles, " >>> emerge ("+\
3189
				str(mergecount)+" of "+str(totalcount)+\
3190
				") "+x[pkgindex]+" to "+x[1])
3191
3192
		portdb = self.trees[myroot]["porttree"].dbapi
3193
		bindb  = self.trees[myroot]["bintree"].dbapi
3194
		vartree = self.trees[myroot]["vartree"]
3195
		pkgsettings = self.pkgsettings[myroot]
3196
		y = portdb.findname(pkg_key)
3197
		pkgsettings["EMERGE_FROM"] = x[0]
3198
		pkgsettings.backup_changes("EMERGE_FROM")
3199
		pkgsettings.reset()
3200
3201
		#buildsyspkg: Check if we need to _force_ binary package creation
3202
		issyspkg = ("buildsyspkg" in myfeat) \
3203
				and x[0] != "blocks" \
3204
				and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3205
				and "--buildpkg" not in self.myopts
3206
		if x[0] in ["ebuild","blocks"]:
3207
			if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3208
				raise Exception, "Merging a blocker"
3209
			elif "--fetchonly" in self.myopts or \
3210
				"--fetch-all-uri" in self.myopts:
3211
				if "--fetch-all-uri" in self.myopts:
3212
					retval = portage.doebuild(y, "fetch", myroot,
3213
						pkgsettings, self.edebug,
3214
						"--pretend" in self.myopts, fetchonly=1,
3215
						fetchall=1, mydbapi=portdb, tree="porttree")
3216
				else:
3217
					retval = portage.doebuild(y, "fetch", myroot,
3218
						pkgsettings, self.edebug,
3219
						"--pretend" in self.myopts, fetchonly=1,
3220
						mydbapi=portdb, tree="porttree")
3221
				if (retval is None) or retval:
3222
					print
3223
					print "!!! Fetch for",y,"failed, continuing..."
3224
					print
3225
3226
				return retval
3227
3228
			portage.doebuild_environment(y, "setup", myroot,
3229
				pkgsettings, self.edebug, 1, portdb)
3230
			catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3231
			portage_util.ensure_dirs(os.path.dirname(catdir),
3232
				uid=portage.portage_uid, gid=portage.portage_gid,
3233
				mode=070, mask=0)
3234
			builddir_lock = None
3235
			catdir_lock = None
3236
			try:
3237
				catdir_lock = portage_locks.lockdir(catdir)
3238
				portage_util.ensure_dirs(catdir,
3239
					uid=portage.portage_uid, gid=portage.portage_gid,
3240
					mode=070, mask=0)
3241
				builddir_lock = portage_locks.lockdir(
3242
					pkgsettings["PORTAGE_BUILDDIR"])
3243
				try:
3244
					portage_locks.unlockdir(catdir_lock)
3245
				finally:
3246
					catdir_lock = None
3247
				msg = " === (%s of %s) Cleaning (%s::%s)" % \
3248
					(mergecount, totalcount, pkg_key, y)
3249
				short_msg = "emerge: (%s of %s) %s Clean" % \
3250
					(mergecount, totalcount, pkg_key)
3251
				emergelog(xterm_titles, msg, short_msg=short_msg)
3252
				retval = portage.doebuild(y, "clean", myroot,
3253
					pkgsettings, self.edebug, cleanup=1,
3254
					mydbapi=portdb, tree="porttree")
3255
3256
				if retval != os.EX_OK:
3257
					return retval
3258
				if "--buildpkg" in self.myopts or issyspkg:
3259
					if issyspkg:
3260
						print ">>> This is a system package, " + \
3261
							"let's pack a rescue tarball."
3262
					msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3263
						(mergecount, totalcount, pkg_key, y)
3264
					short_msg = "emerge: (%s of %s) %s Compile" % \
3265
						(mergecount, totalcount, pkg_key)
3266
					emergelog(xterm_titles, msg, short_msg=short_msg)
3267
					self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3268
					retval = portage.doebuild(y, "package", myroot,
3269
						pkgsettings, self.edebug, mydbapi=portdb,
3270
						tree="porttree")
3271
					if retval != os.EX_OK:
3272
						return retval
3273
					bintree = self.trees[myroot]["bintree"]
3274
					if bintree.populated:
3275
						bintree.inject(pkg_key)
3276
					if "--buildpkgonly" not in self.myopts:
3277
						msg = " === (%s of %s) Merging (%s::%s)" % \
3278
							(mergecount, totalcount, pkg_key, y)
3279
						short_msg = "emerge: (%s of %s) %s Merge" % \
3280
							(mergecount, totalcount, pkg_key)
3281
						emergelog(xterm_titles, msg, short_msg=short_msg)
3282
						retval = portage.merge(pkgsettings["CATEGORY"],
3283
							pkgsettings["PF"], pkgsettings["D"],
3284
							os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3285
							"build-info"), myroot, pkgsettings,
3286
							myebuild=pkgsettings["EBUILD"],
3287
							mytree="porttree", mydbapi=portdb,
3288
							vartree=vartree, prev_mtimes=ldpath_mtimes)
3289
						if retval != os.EX_OK:
3290
							return retval
3291
					elif "noclean" not in pkgsettings.features:
3292
						portage.doebuild(y, "clean", myroot,
3293
							pkgsettings, self.edebug, mydbapi=portdb,
3294
							tree="porttree")
3295
				else:
3296
					msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3297
						(mergecount, totalcount, pkg_key, y)
3298
					short_msg = "emerge: (%s of %s) %s Compile" % \
3299
						(mergecount, totalcount, pkg_key)
3300
					emergelog(xterm_titles, msg, short_msg=short_msg)
3301
					retval = portage.doebuild(y, "merge", myroot,
3302
						pkgsettings, self.edebug, vartree=vartree,
3303
						mydbapi=portdb, tree="porttree",
3304
						prev_mtimes=ldpath_mtimes)
3305
					if retval != os.EX_OK:
3306
						return retval
3307
			finally:
3308
				if builddir_lock:
3309
					portage_locks.unlockdir(builddir_lock)
3310
				try:
3311
					if not catdir_lock:
3312
						# Lock catdir for removal if empty.
3313
						catdir_lock = portage_locks.lockdir(catdir)
3314
				finally:
3315
					if catdir_lock:
3316
						try:
3317
							os.rmdir(catdir)
3318
						except OSError, e:
3319
							if e.errno not in (errno.ENOENT,
3320
								errno.ENOTEMPTY, errno.EEXIST):
3321
								raise
3322
							del e
3323
						portage_locks.unlockdir(catdir_lock)
3324
3325
		elif x[0]=="binary":
3326
			#merge the tbz2
3327
			mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3328
			if "--getbinpkg" in self.myopts:
3329
				tbz2_lock = None
3330
				try:
3331
					if "distlocks" in pkgsettings.features and \
3332
						os.access(pkgsettings["PKGDIR"], os.W_OK):
3333
						portage_util.ensure_dirs(os.path.dirname(mytbz2))
3334
						tbz2_lock = portage_locks.lockfile(mytbz2,
3335
							wantnewlockfile=1)
3336
					if self.trees[myroot]["bintree"].isremote(pkg_key):
3337
						msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3338
							(mergecount, totalcount, pkg_key, mytbz2)
3339
						short_msg = "emerge: (%s of %s) %s Fetch" % \
3340
							(mergecount, totalcount, pkg_key)
3341
						emergelog(xterm_titles, msg, short_msg=short_msg)
3342
						if not self.trees[myroot]["bintree"].gettbz2(
3343
							pkg_key):
3344
							return 1
3345
				finally:
3346
					if tbz2_lock:
3347
						portage_locks.unlockfile(tbz2_lock)
3348
3349
			if "--fetchonly" in self.myopts or \
3350
				"--fetch-all-uri" in self.myopts:
3351
				return os.EX_OK
3352
3353
			short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
3354
			emergelog(xterm_titles, " === ("+str(mergecount)+\
3355
				" of "+str(totalcount)+") Merging Binary ("+\
3356
				x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3357
3358
			retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3359
				mydbapi=bindb,
3360
				vartree=self.trees[myroot]["vartree"],
3361
				prev_mtimes=ldpath_mtimes)
3362
			if retval != os.EX_OK:
3363
				return retval
3364
			#need to check for errors
3365
3366
		# clean up the older version which emerged on top of
3367
		if "--buildpkgonly" not in self.myopts and \
3368
			"--pretend" not in self.myopts and \
3369
			"--fetchonly" not in self.myopts and \
3370
			"--fetch-all-uri" not in self.myopts:
3371
			# Clean the old package that we have merged over top of it.
3372
			if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3373
				xsplit=portage.pkgsplit(x[2])
3374
				emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3375
				retval = unmerge(pkgsettings, self.myopts, vartree,
3376
					"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3377
				if not retval:
3378
					emergelog(xterm_titles,
3379
						" --- AUTOCLEAN: Nothing unmerged.")
3380
			else:
3381
				portage.writemsg_stdout(colorize("WARN", "WARNING:")
3382
					+ " AUTOCLEAN is disabled.  This can cause serious"
3383
					+ " problems due to overlapping packages.\n")
3384
3385
		if "--pretend" not in self.myopts and \
3386
			"--fetchonly" not in self.myopts and \
3387
			"--fetch-all-uri" not in self.myopts:
3388
			if "noclean" not in self.settings.features:
3389
				short_msg = "emerge: (%s of %s) %s Clean Post" % \
3390
					(mergecount, totalcount, x[pkgindex])
3391
				emergelog(xterm_titles, (" === (%s of %s) " + \
3392
					"Post-Build Cleaning (%s::%s)") % \
3393
					(mergecount, totalcount, x[pkgindex], y),
3394
					short_msg=short_msg)
3395
			emergelog(xterm_titles, " ::: completed emerge ("+\
3396
				str(mergecount)+" of "+str(totalcount)+") "+\
3397
				x[2]+" to "+x[1])
3398
3399
		return os.EX_OK
3400
3401
	def add_one_emerge_to_world(self, x, mergecount, totalcount, favorites, mysysdict):
3402
		xterm_titles = "notitles" not in self.settings.features
3403
		pkgindex=2
3404
		if x[0]=="blocks":
3405
			pkgindex=3
3406
3407
		if "--buildpkgonly" not in self.myopts:
3408
			self.trees[x[1]]["vartree"].inject(x[2])
3409
			myfavkey=portage.cpv_getkey(x[2])
3410
			if "--fetchonly" not in self.myopts and \
3411
				"--fetch-all-uri" not in self.myopts and \
3412
				myfavkey in favorites:
3413
				myfavs = portage.grabfile(os.path.join(x[1], portage.WORLD_FILE))
3414
				myfavdict=genericdict(myfavs)
3415
				#don't record if already in system profile or already recorded
3416
				if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3417
					#we don't have a favorites entry for this package yet; add one
3418
					myfavdict[myfavkey]=myfavkey
3419
					print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3420
					emergelog(xterm_titles, " === ("+\
3421
						str(mergecount)+" of "+\
3422
						str(totalcount)+\
3423
						") Updating world file ("+x[pkgindex]+")")
3424
					portage.write_atomic(
3425
					os.path.join(x[1], portage.WORLD_FILE),
3426
					"\n".join(myfavdict.values()))
3427
3428
	def print_status(self, totalcount, donec, qsize, failedc, spawnd_pkg, failed):
3429
		smsg = ""
3430
		fmsg = ""
3431
		if spawnd_pkg:
3432
			for pkgs in spawnd_pkg.values():
3433
				smsg = smsg+" "+pkgs[0][2]
3434
		if failed:
3435
			for pkgs in failed:
3436
				fmsg = fmsg+" "+pkgs
3437
		print ">>> Jobs [Total = "+colorize("blue", str(totalcount))+"] [Done = "+\
3438
			colorize("GOOD", str(donec))+"] [Running = "+colorize("WARN", str(qsize)+smsg)+\
3439
			"] [Failed = "+colorize("BAD", str(failedc)+fmsg)+"]"
3440
		xtermTitle("Jobs [Total="+str(totalcount)+"] [Done="+str(donec)+"] [Running="+str(qsize)+"] [Failed="+str(failedc)+"]")
3441
3442
	def wait_one_emerge(self, spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb):
3443
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3444
		# let's wait for one of the jobs to finish
3445
		onepid = -1
3446
		while onepid not in spawnd_pids:
3447
			onepid , retval = os.waitpid(-1, 0)
3448
		spawnd_pids.remove(onepid)
3449
3450
		pkg_compl = spawnd_pkg[onepid][0]
3451
		pkg_slot = spawnd_pkg[onepid][1]
3452
		del spawnd_pkg[onepid]
3453
3454
		if not retval:
3455
			# unlink the logid_path
3456
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl[2].split("/")[0]+"."+pkg_compl[2].split("/")[1]
3457
			if os.path.exists(logid_path):
3458
				os.unlink(logid_path)
3459
			index = 0
3460
			print ">>> Package "+colorize("GOOD", pkg_compl[2])+" finished emerging."
3461
			# we need to remove this pkg from resume DB
3462
			# this is the dirtiest shit I have ever written
3463
			for pkgs in mymergelist:
3464
				if pkgs[2] == pkg_compl[2]:
3465
					if len(mymergelist) > 1:
3466
						del mtimedb["resume"]["mergelist"][index]
3467
						mtimedb.commit()
3468
					del mymergelist[index]
3469
					# check if we need to restart portage
3470
					mysplit=portage.pkgsplit(pkg_compl[2])
3471
					if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
3472
						self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
3473
					break
3474
				index += 1
3475
		return (retval, pkg_compl)
3476
3477
	def merge(self, mylist, favorites, mtimedb, m_slots):
3014
		failed_fetches = []
3478
		failed_fetches = []
3015
		mymergelist=[]
3479
		mymergelist=[]
3016
		ldpath_mtimes = mtimedb["ldpath"]
3480
		ldpath_mtimes = mtimedb["ldpath"]
3017
		xterm_titles = "notitles" not in self.settings.features
3481
		xterm_titles = "notitles" not in self.settings.features
3482
		parallel = "parallel" in self.settings.features
3483
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3484
3485
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3486
		if self.edebug or "--fetchonly" in self.myopts:
3487
			parallel = False
3018
3488
3019
		#check for blocking dependencies
3489
		#check for blocking dependencies
3020
		if "--fetchonly" not in self.myopts and \
3490
		if "--fetchonly" not in self.myopts and \
Lines 3031-3038 Link Here
3031
3501
3032
		if "--resume" in self.myopts:
3502
		if "--resume" in self.myopts:
3033
			# We're resuming.
3503
			# We're resuming.
3034
			print colorize("GOOD", "*** Resuming merge...")
3035
			emergelog(xterm_titles, " *** Resuming merge...")
3036
			mylist = mtimedb["resume"]["mergelist"][:]
3504
			mylist = mtimedb["resume"]["mergelist"][:]
3037
			if "--skipfirst" in self.myopts and mylist:
3505
			if "--skipfirst" in self.myopts and mylist:
3038
				del mtimedb["resume"]["mergelist"][0]
3506
				del mtimedb["resume"]["mergelist"][0]
Lines 3060-3066 Link Here
3060
				if not shown_verifying_msg:
3528
				if not shown_verifying_msg:
3061
					shown_verifying_msg = True
3529
					shown_verifying_msg = True
3062
					print ">>> Verifying ebuild Manifests..."
3530
					print ">>> Verifying ebuild Manifests..."
3063
				mytype, myroot, mycpv, mystatus = x
3531
				mytype, myroot, mycpv, mystatus, slott = x
3064
				portdb = self.trees[myroot]["porttree"].dbapi
3532
				portdb = self.trees[myroot]["porttree"].dbapi
3065
				quiet_config = quiet_settings[myroot]
3533
				quiet_config = quiet_settings[myroot]
3066
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
3534
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
Lines 3098-3105 Link Here
3098
					os.path.join(self.target_root, portage.WORLD_FILE),
3566
					os.path.join(self.target_root, portage.WORLD_FILE),
3099
					"\n".join(myfavdict.values()))
3567
					"\n".join(myfavdict.values()))
3100
3568
3101
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3569
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
3102
			mtimedb.commit()
3570
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3571
				mtimedb.commit()
3572
3573
		totalcount = len(mymergelist)
3574
		mergecount=1
3575
3576
		if "--resume" in self.myopts and "--fetchonly" not in self.myopts:
3577
			# We're resuming.
3578
			print colorize("GOOD", "*** Resuming merge...")
3579
			emergelog(xterm_titles, " *** Resuming merge...")
3103
3580
3104
		myfeat = self.settings.features[:]
3581
		myfeat = self.settings.features[:]
3105
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3582
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 3117-3128 Link Here
3117
				print ">>> starting parallel fetching"
3594
				print ">>> starting parallel fetching"
3118
				fetch_log = "/var/log/emerge-fetch.log"
3595
				fetch_log = "/var/log/emerge-fetch.log"
3119
				logfile = open(fetch_log, "w")
3596
				logfile = open(fetch_log, "w")
3120
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3597
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
3121
				portage_util.apply_secpass_permissions(fetch_log,
3598
				portage_util.apply_secpass_permissions(fetch_log,
3122
					uid=portage.portage_uid, gid=portage.portage_gid,
3599
					uid=portage.portage_uid, gid=portage.portage_gid,
3123
					mode=0660)
3600
					mode=0660)
3124
				fetch_env = os.environ.copy()
3601
				fetch_env = os.environ.copy()
3125
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3602
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
3126
				fetch_env["PORTAGE_NICENESS"] = "0"
3603
				fetch_env["PORTAGE_NICENESS"] = "0"
3127
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3604
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3128
				resume_opts = self.myopts.copy()
3605
				resume_opts = self.myopts.copy()
Lines 3142-3452 Link Here
3142
				del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3619
				del fetch_log, logfile, fd_pipes, fetch_env, fetch_args, \
3143
					resume_opts
3620
					resume_opts
3144
3621
3145
		mergecount=0
3622
		if not parallel:
3146
		for x in mymergelist:
3623
			failed_fetches = []
3147
			mergecount+=1
3624
			for x in mymergelist:
3148
			myroot=x[1]
3625
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, mysysdict)
3149
			pkg_key = x[2]
3626
				mergecount += 1
3150
			pkgindex=2
3627
3151
			portdb = self.trees[myroot]["porttree"].dbapi
3628
				# need to short circuit the spawn with --nodeps
3152
			bindb  = self.trees[myroot]["bintree"].dbapi
3629
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
3153
			vartree = self.trees[myroot]["vartree"]
3630
					if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3154
			pkgsettings = self.pkgsettings[myroot]
3631
						continue
3155
			if x[0]=="blocks":
3632
					if retcode != os.EX_OK:
3156
				pkgindex=3
3633
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3157
			y = portdb.findname(pkg_key)
3634
							failed_fetches.append(x[2])
3635
							continue
3636
						else:
3637
							return retcode
3638
					# Unsafe for parallel merges
3639
					del mtimedb["resume"]["mergelist"][0]
3640
					# Commit after each merge so that --resume may still work in
3641
					# in the event that portage is not allowed to exit normally
3642
					# due to power failure, SIGKILL, etc...
3643
					mtimedb.commit()
3644
3645
					# unlink the logid_path if any exists
3646
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
3647
					if os.path.exists(logid_path):
3648
						os.unlink(logid_path)
3649
					del logid_path
3650
  
3651
					# check if we need to restart portage
3652
					mysplit=portage.pkgsplit(x[2])
3653
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3654
							self.restart_portage(x, mergecount, totalcount, mtimedb)
3655
  
3656
				else:
3657
					if retcode != os.EX_OK:
3658
						sys.exit(1)
3659
  					else:
3660
						sys.exit(0)
3661
  
3158
			if "--pretend" not in self.myopts:
3662
			if "--pretend" not in self.myopts:
3159
				print "\n>>> Emerging (" + \
3663
				emergelog(xterm_titles, " *** Finished. Cleaning up...")
3160
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
3664
  
3161
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
3665
			# We're out of the loop... We're done. Delete the resume data.
3162
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
3666
			if mtimedb.has_key("resume"):
3163
				emergelog(xterm_titles, " >>> emerge ("+\
3667
				del mtimedb["resume"]
3164
					str(mergecount)+" of "+str(len(mymergelist))+\
3668
			mtimedb.commit()
3165
					") "+x[pkgindex]+" to "+x[1])
3669
			
3166
3670
			#by doing an exit this way, --fetchonly can continue to try to
3167
			pkgsettings["EMERGE_FROM"] = x[0]
3671
			#fetch everything even if a particular download fails.
3168
			pkgsettings.backup_changes("EMERGE_FROM")
3672
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3169
			pkgsettings.reset()
3673
				if failed_fetches:
3170
3674
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
3171
			#buildsyspkg: Check if we need to _force_ binary package creation
3675
						"encountered.  Please see above for details.\n\n")
3172
			issyspkg = ("buildsyspkg" in myfeat) \
3676
					for cpv in failed_fetches:
3173
					and x[0] != "blocks" \
3677
						sys.stderr.write("   ")
3174
					and mysysdict.has_key(portage.cpv_getkey(x[2])) \
3678
						sys.stderr.write(cpv)
3175
					and "--buildpkg" not in self.myopts
3679
						sys.stderr.write("\n")
3176
			if x[0] in ["ebuild","blocks"]:
3680
					sys.stderr.write("\n")
3177
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
3681
					sys.exit(1)
3178
					raise Exception, "Merging a blocker"
3682
				else:
3179
				elif "--fetchonly" in self.myopts or \
3683
					sys.exit(0)
3180
					"--fetch-all-uri" in self.myopts:
3684
			return os.EX_OK
3181
					if "--fetch-all-uri" in self.myopts:
3685
  
3182
						retval = portage.doebuild(y, "fetch", myroot,
3686
		# parallel code - dirty starts here...;-)
3183
							pkgsettings, self.edebug,
3687
		one_in_slot_failed=0
3184
							"--pretend" in self.myopts, fetchonly=1,
3688
		spawnd_pids=[]
3185
							fetchall=1, mydbapi=portdb, tree="porttree")
3689
3186
					else:
3690
		# dirty little trick to get number of cpus from the system
3187
						retval = portage.doebuild(y, "fetch", myroot,
3691
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
3188
							pkgsettings, self.edebug,
3692
		cpu_count = 0
3189
							"--pretend" in self.myopts, fetchonly=1,
3693
		for data_cpuinfo in fd_cpuinfo.readlines():
3190
							mydbapi=portdb, tree="porttree")
3694
			if data_cpuinfo.find("cpu MHz") > -1 :
3191
					if (retval is None) or retval:
3695
				cpu_count += 1
3192
						print
3696
		fd_cpuinfo.close()
3193
						print "!!! Fetch for",y,"failed, continuing..."
3697
3194
						print
3698
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
3195
						failed_fetches.append(pkg_key)
3699
		if cpu_count == 0:
3196
					continue
3700
			cpu_count = 1
3197
3701
3198
				portage.doebuild_environment(y, "setup", myroot,
3702
		spawnd_pkg = {}
3199
					pkgsettings, self.edebug, 1, portdb)
3703
		donec = 0
3200
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
3704
		failedc = 0
3201
				portage_util.ensure_dirs(os.path.dirname(catdir),
3705
		failedPkgs = []
3202
					uid=portage.portage_uid, gid=portage.portage_gid,
3706
		logid_path = None
3203
					mode=070, mask=0)
3707
		mylist = m_slots.keys()
3204
				builddir_lock = None
3708
		mylist.sort()
3205
				catdir_lock = None
3709
		for x in mylist:
3206
				try:
3710
			# if slot is empty, go on
3207
					catdir_lock = portage_locks.lockdir(catdir)
3711
			if not m_slots[x]:
3208
					portage_util.ensure_dirs(catdir,
3712
				continue
3209
						uid=portage.portage_uid, gid=portage.portage_gid,
3210
						mode=070, mask=0)
3211
					builddir_lock = portage_locks.lockdir(
3212
						pkgsettings["PORTAGE_BUILDDIR"])
3213
					try:
3214
						portage_locks.unlockdir(catdir_lock)
3215
					finally:
3216
						catdir_lock = None
3217
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
3218
						(mergecount, len(mymergelist), pkg_key, y)
3219
					short_msg = "emerge: (%s of %s) %s Clean" % \
3220
						(mergecount, len(mymergelist), pkg_key)
3221
					emergelog(xterm_titles, msg, short_msg=short_msg)
3222
					retval = portage.doebuild(y, "clean", myroot,
3223
						pkgsettings, self.edebug, cleanup=1,
3224
						mydbapi=portdb, tree="porttree")
3225
					if retval != os.EX_OK:
3226
						return retval
3227
					if "--buildpkg" in self.myopts or issyspkg:
3228
						if issyspkg:
3229
							print ">>> This is a system package, " + \
3230
								"let's pack a rescue tarball."
3231
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
3232
							(mergecount, len(mymergelist), pkg_key, y)
3233
						short_msg = "emerge: (%s of %s) %s Compile" % \
3234
							(mergecount, len(mymergelist), pkg_key)
3235
						emergelog(xterm_titles, msg, short_msg=short_msg)
3236
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
3237
						retval = portage.doebuild(y, "package", myroot,
3238
							pkgsettings, self.edebug, mydbapi=portdb,
3239
							tree="porttree")
3240
						if retval != os.EX_OK:
3241
							return retval
3242
						bintree = self.trees[myroot]["bintree"]
3243
						if bintree.populated:
3244
							bintree.inject(pkg_key)
3245
						if "--buildpkgonly" not in self.myopts:
3246
							msg = " === (%s of %s) Merging (%s::%s)" % \
3247
								(mergecount, len(mymergelist), pkg_key, y)
3248
							short_msg = "emerge: (%s of %s) %s Merge" % \
3249
								(mergecount, len(mymergelist), pkg_key)
3250
							emergelog(xterm_titles, msg, short_msg=short_msg)
3251
							retval = portage.merge(pkgsettings["CATEGORY"],
3252
								pkgsettings["PF"], pkgsettings["D"],
3253
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
3254
								"build-info"), myroot, pkgsettings,
3255
								myebuild=pkgsettings["EBUILD"],
3256
								mytree="porttree", mydbapi=portdb,
3257
								vartree=vartree, prev_mtimes=ldpath_mtimes)
3258
							if retval != os.EX_OK:
3259
								return retval
3260
						elif "noclean" not in pkgsettings.features:
3261
							portage.doebuild(y, "clean", myroot,
3262
								pkgsettings, self.edebug, mydbapi=portdb,
3263
								tree="porttree")
3264
					else:
3265
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
3266
							(mergecount, len(mymergelist), pkg_key, y)
3267
						short_msg = "emerge: (%s of %s) %s Compile" % \
3268
							(mergecount, len(mymergelist), pkg_key)
3269
						emergelog(xterm_titles, msg, short_msg=short_msg)
3270
						retval = portage.doebuild(y, "merge", myroot,
3271
							pkgsettings, self.edebug, vartree=vartree,
3272
							mydbapi=portdb, tree="porttree",
3273
							prev_mtimes=ldpath_mtimes)
3274
						if retval != os.EX_OK:
3275
							return retval
3276
				finally:
3277
					if builddir_lock:
3278
						portage_locks.unlockdir(builddir_lock)
3279
					try:
3280
						if not catdir_lock:
3281
							# Lock catdir for removal if empty.
3282
							catdir_lock = portage_locks.lockdir(catdir)
3283
					finally:
3284
						if catdir_lock:
3285
							try:
3286
								os.rmdir(catdir)
3287
							except OSError, e:
3288
								if e.errno not in (errno.ENOENT,
3289
									errno.ENOTEMPTY, errno.EEXIST):
3290
									raise
3291
								del e
3292
							portage_locks.unlockdir(catdir_lock)
3293
3294
			elif x[0]=="binary":
3295
				#merge the tbz2
3296
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
3297
				if "--getbinpkg" in self.myopts:
3298
					tbz2_lock = None
3299
					try:
3300
						if "distlocks" in pkgsettings.features and \
3301
							os.access(pkgsettings["PKGDIR"], os.W_OK):
3302
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
3303
							tbz2_lock = portage_locks.lockfile(mytbz2,
3304
								wantnewlockfile=1)
3305
						if self.trees[myroot]["bintree"].isremote(pkg_key):
3306
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
3307
								(mergecount, len(mymergelist), pkg_key, mytbz2)
3308
							short_msg = "emerge: (%s of %s) %s Fetch" % \
3309
								(mergecount, len(mymergelist), pkg_key)
3310
							emergelog(xterm_titles, msg, short_msg=short_msg)
3311
							if not self.trees[myroot]["bintree"].gettbz2(
3312
								pkg_key):
3313
								return 1
3314
					finally:
3315
						if tbz2_lock:
3316
							portage_locks.unlockfile(tbz2_lock)
3317
3318
				if "--fetchonly" in self.myopts or \
3319
					"--fetch-all-uri" in self.myopts:
3320
					continue
3321
3713
3322
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
3714
			# if previous slot failed, discontinue the emerge
3323
				emergelog(xterm_titles, " === ("+str(mergecount)+\
3715
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
3324
					" of "+str(len(mymergelist))+") Merging Binary ("+\
3716
				break
3325
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
3326
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
3327
					mydbapi=bindb,
3328
					vartree=self.trees[myroot]["vartree"],
3329
					prev_mtimes=ldpath_mtimes)
3330
				if retval != os.EX_OK:
3331
					return retval
3332
				#need to check for errors
3333
			if "--buildpkgonly" not in self.myopts:
3334
				self.trees[x[1]]["vartree"].inject(x[2])
3335
				myfavkey=portage.cpv_getkey(x[2])
3336
				if "--fetchonly" not in self.myopts and \
3337
					"--fetch-all-uri" not in self.myopts and \
3338
					myfavkey in favorites:
3339
					myfavs = portage.grabfile(os.path.join(myroot, portage.WORLD_FILE))
3340
					myfavdict=genericdict(myfavs)
3341
					#don't record if already in system profile or already recorded
3342
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
3343
						#we don't have a favorites entry for this package yet; add one
3344
						myfavdict[myfavkey]=myfavkey
3345
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
3346
						emergelog(xterm_titles, " === ("+\
3347
							str(mergecount)+" of "+\
3348
							str(len(mymergelist))+\
3349
							") Updating world file ("+x[pkgindex]+")")
3350
						portage.write_atomic(
3351
						os.path.join(myroot, portage.WORLD_FILE),
3352
						"\n".join(myfavdict.values()))
3353
3354
				if "--pretend" not in self.myopts and \
3355
					"--fetchonly" not in self.myopts and \
3356
					"--fetch-all-uri" not in self.myopts:
3357
					# Clean the old package that we have merged over top of it.
3358
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
3359
						xsplit=portage.pkgsplit(x[2])
3360
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
3361
						retval = unmerge(pkgsettings, self.myopts, vartree,
3362
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
3363
						if not retval:
3364
							emergelog(xterm_titles,
3365
								" --- AUTOCLEAN: Nothing unmerged.")
3366
					else:
3367
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
3368
							+ " AUTOCLEAN is disabled.  This can cause serious"
3369
							+ " problems due to overlapping packages.\n")
3370
3717
3371
					# Figure out if we need a restart.
3718
			# start multiple merges in parallel mode
3372
					mysplit=portage.pkgsplit(x[2])
3719
			num_at_atime = cpu_count + 1
3373
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
3374
						myver=mysplit[1]+"-"+mysplit[2]
3375
						if myver[-3:]=='-r0':
3376
							myver=myver[:-3]
3377
						if (myver != portage.VERSION) and \
3378
						   "livecvsportage" not in self.settings.features:
3379
							if len(mymergelist) > mergecount:
3380
								emergelog(xterm_titles,
3381
									" ::: completed emerge ("+ \
3382
									str(mergecount)+" of "+ \
3383
									str(len(mymergelist))+") "+ \
3384
									x[2]+" to "+x[1])
3385
								emergelog(xterm_titles, " *** RESTARTING " + \
3386
									"emerge via exec() after change of " + \
3387
									"portage version.")
3388
								del mtimedb["resume"]["mergelist"][0]
3389
								mtimedb.commit()
3390
								portage.run_exitfuncs()
3391
								mynewargv=[sys.argv[0],"--resume"]
3392
								resume_opts = self.myopts.copy()
3393
								# For automatic resume, we need to prevent
3394
								# any of bad_resume_opts from leaking in
3395
								# via EMERGE_DEFAULT_OPTS.
3396
								resume_opts["--ignore-default-opts"] = True
3397
								for myopt, myarg in resume_opts.iteritems():
3398
									if myopt not in bad_resume_opts:
3399
										if myarg is True:
3400
											mynewargv.append(myopt)
3401
										else:
3402
											mynewargv.append(myopt +"="+ myarg)
3403
								# priority only needs to be adjusted on the first run
3404
								os.environ["PORTAGE_NICENESS"] = "0"
3405
								os.execv(mynewargv[0], mynewargv)
3406
3407
			if "--pretend" not in self.myopts and \
3408
				"--fetchonly" not in self.myopts and \
3409
				"--fetch-all-uri" not in self.myopts:
3410
				if "noclean" not in self.settings.features:
3411
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
3412
						(mergecount, len(mymergelist), x[pkgindex])
3413
					emergelog(xterm_titles, (" === (%s of %s) " + \
3414
						"Post-Build Cleaning (%s::%s)") % \
3415
						(mergecount, len(mymergelist), x[pkgindex], y),
3416
						short_msg=short_msg)
3417
				emergelog(xterm_titles, " ::: completed emerge ("+\
3418
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
3419
					x[2]+" to "+x[1])
3420
3720
3421
			# Unsafe for parallel merges
3721
			qsize = 0
3422
			del mtimedb["resume"]["mergelist"][0]
3722
			for y in m_slots[x]:
3423
			# Commit after each merge so that --resume may still work in
3723
				# these all can go in parallel, so fork one after the other
3424
			# in the event that portage is not allowed to exit normally
3724
				# but num_at_atime at most
3425
			# due to power failure, SIGKILL, etc...
3725
				if num_at_atime:
3426
			mtimedb.commit()
3726
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3727
					spawnd_pids.append(onepid)
3728
					spawnd_pkg[onepid] = (y, x)
3729
					num_at_atime -= 1
3730
					mergecount += 1
3731
					qsize += 1
3732
				else:
3733
					self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3734
					# let's wait for one of the jobs to finish
3735
					(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
3736
3737
					# if it failed, I need to fail next slot but continue to merge all in this slot
3738
					if retval:
3739
						one_in_slot_failed = retval
3740
						failedc += 1
3741
						failedPkgs.append(pkg_compl[2])
3742
  					else:
3743
						donec += 1
3744
						self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, mysysdict)
3745
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, mysysdict)
3746
					spawnd_pids.append(onepid)
3747
					spawnd_pkg[onepid] = (y, x)
3748
					mergecount += 1
3749
3750
			# this slot is exhausted, so wait for all of the forks to finish
3751
			while spawnd_pids:
3752
				self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
3753
				# let's wait for one of the jobs to finish
3754
				(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
3755
3756
				qsize -= 1
3757
				if retval:
3758
					one_in_slot_failed = retval
3759
					failedc += 1
3760
					failedPkgs.append(pkg_compl[2])
3761
				else:
3762
					donec += 1
3763
					self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, mysysdict)
3764
		if totalcount:
3765
			self.print_status(totalcount, donec, qsize, failedc, None, failedPkgs)
3766
  
3767
		if one_in_slot_failed:
3768
			portage.writemsg_stdout(red("\nSome packages failed to emerge, summary follows:\n"))
3769
  
3770
		for pkgs in failedPkgs:
3771
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3772
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
3773
				sys.exit(1)
3427
3774
3775
			portage.writemsg_stdout(red("\nPackage "+pkgs+" failed to emerge\n"))
3776
			logfile = None
3777
			if "PORT_LOGDIR" in self.settings:
3778
				port_logdir = self.settings["PORT_LOGDIR"]
3779
			else:
3780
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
3781
3782
			pkg_cat = pkgs.split("/")[0]
3783
			pkg_pf = pkgs.split("/")[1]
3784
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
3785
			if os.path.exists(logid_path):
3786
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
3787
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
3788
					(pkg_cat, pkg_pf, logid_time))
3789
				del logid_time
3790
3791
			if logfile and os.path.exists(logfile):
3792
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
3793
3794
			if logfile and os.path.exists(logfile):
3795
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
3796
				os.unlink(logid_path)
3797
		if one_in_slot_failed:
3798
			sys.exit(1)
3428
		if "--pretend" not in self.myopts:
3799
		if "--pretend" not in self.myopts:
3429
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3800
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
3430
3801
3802
		# see if there are any extraneous files in build_prefix, which we might have leftover
3803
		import glob
3804
		for fnames in glob.glob(os.path.join(build_prefix, ".logid.")+"*"):
3805
			os.unlink(fnames)
3806
3431
		# We're out of the loop... We're done. Delete the resume data.
3807
		# We're out of the loop... We're done. Delete the resume data.
3432
		if mtimedb.has_key("resume"):
3808
		if mtimedb.has_key("resume"):
3433
			del mtimedb["resume"]
3809
			del mtimedb["resume"]
3434
		mtimedb.commit()
3810
		mtimedb.commit()
3435
3811
3436
		#by doing an exit this way, --fetchonly can continue to try to
3437
		#fetch everything even if a particular download fails.
3438
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3812
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3439
			if failed_fetches:
3813
			sys.exit(0)
3440
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
3814
3441
					"encountered.  Please see above for details.\n\n")
3442
				for cpv in failed_fetches:
3443
					sys.stderr.write("   ")
3444
					sys.stderr.write(cpv)
3445
					sys.stderr.write("\n")
3446
				sys.stderr.write("\n")
3447
				sys.exit(1)
3448
			else:
3449
				sys.exit(0)
3450
		return os.EX_OK
3815
		return os.EX_OK
3451
3816
3452
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
3817
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
Lines 3892-3898 Link Here
3892
def validate_merge_list(trees, mergelist):
4257
def validate_merge_list(trees, mergelist):
3893
	"""Validate the list to make sure all the packages are still available.
4258
	"""Validate the list to make sure all the packages are still available.
3894
	This is needed for --resume."""
4259
	This is needed for --resume."""
3895
	for (pkg_type, myroot, pkg_key, action) in mergelist:
4260
	for (pkg_type, myroot, pkg_key, action, merge_slot) in mergelist:
3896
		if pkg_type == "binary" and \
4261
		if pkg_type == "binary" and \
3897
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
4262
			not trees[myroot]["bintree"].dbapi.match("="+pkg_key) or \
3898
			pkg_type == "ebuild" and \
4263
			pkg_type == "ebuild" and \
Lines 4793-4799 Link Here
4793
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
5158
	if not "--pretend" in myopts: #just check pretend, since --ask implies pretend
4794
		emergelog(xterm_titles, " >>> depclean")
5159
		emergelog(xterm_titles, " >>> depclean")
4795
5160
4796
	if "--quiet" not in myopts:
5161
	if "--quiet" not in myopts and "--nodeps" not in myopts:
4797
		print "\nCalculating dependencies  ",
5162
		print "\nCalculating dependencies  ",
4798
5163
4799
	soft = 0
5164
	soft = 0
Lines 4901-4906 Link Here
4901
	else:
5266
	else:
4902
		print "Number removed:       "+str(len(cleanlist))
5267
		print "Number removed:       "+str(len(cleanlist))
4903
5268
5269
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
5270
	merge_slots = {}
5271
	for pkg in mergelist:
5272
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
5273
			slot = int(pkg[4])
5274
			try:
5275
				if pkg not in merge_slots[slot]:
5276
					merge_slots[slot].append(pkg)
5277
			except KeyError:
5278
				merge_slots[slot] = [pkg]
5279
	# print the merge slots
5280
	max_slot = 0
5281
	mylist = merge_slots.keys()
5282
	mylist.sort()
5283
	for x in mylist:
5284
		if x > max_slot:
5285
			max_slot = x
5286
		if parallel:
5287
			print "Package list for slot = "+str(x)
5288
			for y in merge_slots[x]:
5289
				print "	",y
5290
	if printonly:
5291
		return
5292
5293
	# make one last pass at the merge_slots and initialize the missing slots to None
5294
	x = 0
5295
	while x < max_slot:
5296
		if x not in merge_slots.keys():
5297
			merge_slots[x] = None
5298
		x += 1
5299
	return merge_slots
5300
4904
def action_build(settings, trees, mtimedb,
5301
def action_build(settings, trees, mtimedb,
4905
	myopts, myaction, myfiles, spinner):
5302
	myopts, myaction, myfiles, spinner):
4906
	ldpath_mtimes = mtimedb["ldpath"]
5303
	ldpath_mtimes = mtimedb["ldpath"]
Lines 5019-5031 Link Here
5019
			if len(mymergelist) == 0:
5416
			if len(mymergelist) == 0:
5020
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5417
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5021
				sys.exit(0)
5418
				sys.exit(0)
5419
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5022
			mydepgraph.display(mymergelist)
5420
			mydepgraph.display(mymergelist)
5023
			prompt="Would you like to resume merging these packages?"
5421
			prompt="Would you like to resume merging these packages?"
5024
		else:
5422
		else:
5025
			mydepgraph.display(
5423
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5026
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5424
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5425
			mydepgraph.display(mymergelist)
5027
			mergecount=0
5426
			mergecount=0
5028
			for x in mydepgraph.altlist():
5427
			for x in mymergelist:
5029
				if x[0] != "blocks" and x[3] != "nomerge":
5428
				if x[0] != "blocks" and x[3] != "nomerge":
5030
					mergecount+=1
5429
					mergecount+=1
5031
				#check for blocking dependencies
5430
				#check for blocking dependencies
Lines 5070-5079 Link Here
5070
			if len(mymergelist) == 0:
5469
			if len(mymergelist) == 0:
5071
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5470
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5072
				sys.exit(0)
5471
				sys.exit(0)
5472
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5073
			mydepgraph.display(mymergelist)
5473
			mydepgraph.display(mymergelist)
5074
		else:
5474
		else:
5075
			mydepgraph.display(
5475
			# mydepgraph.digraph.debug_print()
5076
				mydepgraph.altlist(reversed=("--tree" in myopts)))
5476
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
5477
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
5478
			mydepgraph.display(mymergelist)
5077
			if "--buildpkgonly" in myopts and \
5479
			if "--buildpkgonly" in myopts and \
5078
				not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5480
				not mydepgraph.digraph.hasallzeros(ignore_priority=DepPriority.MEDIUM):
5079
					print "\n!!! --buildpkgonly requires all dependencies to be merged."
5481
					print "\n!!! --buildpkgonly requires all dependencies to be merged."
Lines 5094-5116 Link Here
5094
				it to write the mtimedb"""
5496
				it to write the mtimedb"""
5095
				mtimedb.filename = None
5497
				mtimedb.filename = None
5096
				time.sleep(3) # allow the parent to have first fetch
5498
				time.sleep(3) # allow the parent to have first fetch
5499
			mymergelist = mtimedb["resume"]["mergelist"]
5500
			if "--skipfirst" in myopts:
5501
				mymergelist = mymergelist[1:]
5502
			if len(mymergelist) == 0:
5503
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
5504
				sys.exit(0)
5505
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
5097
			del mydepgraph
5506
			del mydepgraph
5098
			retval = mergetask.merge(
5507
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
5099
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
5100
			if retval != os.EX_OK:
5508
			if retval != os.EX_OK:
5101
				sys.exit(retval)
5509
				sys.exit(retval)
5102
		else:
5510
		else:
5103
			if "resume" in mtimedb and \
5511
			mymergelist = mydepgraph.altlist()
5104
			"mergelist" in mtimedb["resume"] and \
5512
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
5105
			len(mtimedb["resume"]["mergelist"]) > 1:
5513
			if "--nodeps" not in myopts or len(mymergelist) > 1:
5106
				mtimedb["resume_backup"] = mtimedb["resume"]
5514
				if "resume" in mtimedb and \
5107
				del mtimedb["resume"]
5515
				"mergelist" in mtimedb["resume"] and \
5108
				mtimedb.commit()
5516
				len(mtimedb["resume"]["mergelist"]) > 1:
5109
			mtimedb["resume"]={}
5517
					mtimedb["resume_backup"] = mtimedb["resume"]
5110
			# XXX: Stored as a list for backward compatibility.
5518
					del mtimedb["resume"]
5111
			mtimedb["resume"]["myopts"] = \
5519
					mtimedb.commit()
5112
				[k for k in myopts if myopts[k] is True]
5520
				mtimedb["resume"]={}
5113
			mtimedb["resume"]["favorites"]=favorites
5521
				# XXX: Stored as a list for backward compatibility.
5522
				mtimedb["resume"]["myopts"] = \
5523
					[k for k in myopts if myopts[k] is True]
5524
				mtimedb["resume"]["favorites"]=favorites
5114
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5525
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
5115
				for pkgline in mydepgraph.altlist():
5526
				for pkgline in mydepgraph.altlist():
5116
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
5527
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 5126-5143 Link Here
5126
							tree="porttree")
5537
							tree="porttree")
5127
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5538
			if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
5128
				pkglist = []
5539
				pkglist = []
5129
				for pkg in mydepgraph.altlist():
5540
				for pkg in mymergelist:
5130
					if pkg[0] != "blocks":
5541
					if pkg[0] != "blocks":
5131
						pkglist.append(pkg)
5542
						pkglist.append(pkg)
5132
			else:
5543
			else:
5133
				pkglist = mydepgraph.altlist()
5544
				pkglist = mymergelist
5134
			del mydepgraph
5545
			del mydepgraph
5135
			mergetask = MergeTask(settings, trees, myopts)
5546
			mergetask = MergeTask(settings, trees, myopts)
5136
			retval = mergetask.merge(pkglist, favorites, mtimedb)
5547
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
5137
			if retval != os.EX_OK:
5548
			if retval != os.EX_OK:
5138
				sys.exit(retval)
5549
				sys.exit(retval)
5139
5550
5140
		if mtimedb.has_key("resume"):
5551
		if mtimedb.has_key("resume") and ("--nodeps" not in myopts or len(mymergelist) > 1):
5141
			del mtimedb["resume"]
5552
			del mtimedb["resume"]
5142
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5553
		if settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
5143
			portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
5554
			portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
(-)portage-2.1.2.12.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.12.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.12.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
(-)portage-2.1.2.12.orig/pym/portage_locks.py (-1 / +3 lines)
Lines 79-85 Link Here
79
	except IOError, e:
79
	except IOError, e:
80
		if "errno" not in dir(e):
80
		if "errno" not in dir(e):
81
			raise
81
			raise
82
		if e.errno == errno.EAGAIN:
82
		if (e.errno == errno.EAGAIN or e.errno == errno.EPERM):
83
			# resource temp unavailable; eg, someone beat us to the lock.
83
			# resource temp unavailable; eg, someone beat us to the lock.
84
			if waiting_msg is None:
84
			if waiting_msg is None:
85
				if isinstance(mypath, int):
85
				if isinstance(mypath, int):
Lines 89-94 Link Here
89
			elif waiting_msg:
89
			elif waiting_msg:
90
				print waiting_msg
90
				print waiting_msg
91
			# try for the exclusive lock now.
91
			# try for the exclusive lock now.
92
			time.sleep(5)
92
			fcntl.lockf(myfd,fcntl.LOCK_EX)
93
			fcntl.lockf(myfd,fcntl.LOCK_EX)
93
		elif e.errno == errno.ENOLCK:
94
		elif e.errno == errno.ENOLCK:
94
			# We're not allowed to lock on this FS.
95
			# We're not allowed to lock on this FS.
Lines 107-112 Link Here
107
			locking_method = None
108
			locking_method = None
108
			myfd = HARDLINK_FD
109
			myfd = HARDLINK_FD
109
		else:
110
		else:
111
			print "waiting for lock on "+str(lockfilename)
110
			raise
112
			raise
111
113
112
		
114
		

Return to bug 147516