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.4.orig/bin/emerge (-364 / +792 lines)
Lines 2622-2627 Link Here
2622
		ignore_priority_soft_range.extend(
2622
		ignore_priority_soft_range.extend(
2623
			xrange(DepPriority.MIN, DepPriority.MEDIUM_SOFT + 1))
2623
			xrange(DepPriority.MIN, DepPriority.MEDIUM_SOFT + 1))
2624
		tree_mode = "--tree" in self.myopts
2624
		tree_mode = "--tree" in self.myopts
2625
		slotcount = 0
2626
2625
		# Tracks whether or not the current iteration should prefer asap_nodes
2627
		# Tracks whether or not the current iteration should prefer asap_nodes
2626
		# if available.  This is set to False when the previous iteration
2628
		# if available.  This is set to False when the previous iteration
2627
		# failed to select any nodes.  It is reset whenever nodes are
2629
		# failed to select any nodes.  It is reset whenever nodes are
Lines 2840-2846 Link Here
2840
2842
2841
			for node in selected_nodes:
2843
			for node in selected_nodes:
2842
				if node[-1] != "nomerge":
2844
				if node[-1] != "nomerge":
2843
					retlist.append(list(node))
2845
					node2 = list(node)
2846
					if len(node2) == 4:
2847
						node2.append(str(slotcount))
2848
					retlist.append(node2)
2844
				mygraph.remove(node)
2849
				mygraph.remove(node)
2845
				if not reversed and not circular_blocks and myblockers.contains(node):
2850
				if not reversed and not circular_blocks and myblockers.contains(node):
2846
					"""This node may have invalidated one or more blockers."""
2851
					"""This node may have invalidated one or more blockers."""
Lines 2854-2859 Link Here
2854
								self.blocker_parents[blocker] = unresolved
2859
								self.blocker_parents[blocker] = unresolved
2855
							else:
2860
							else:
2856
								del self.blocker_parents[blocker]
2861
								del self.blocker_parents[blocker]
2862
			slotcount += 1
2857
2863
2858
		if not reversed:
2864
		if not reversed:
2859
			"""Blocker validation does not work with reverse mode,
2865
			"""Blocker validation does not work with reverse mode,
Lines 3027-3033 Link Here
3027
			if "blocks" == x[0]:
3033
			if "blocks" == x[0]:
3028
				display_list.append((x, 0, True))
3034
				display_list.append((x, 0, True))
3029
				continue
3035
				continue
3030
			graph_key = tuple(x)
3036
			if len(x) > 4:
3037
				graph_key = tuple(x[:-1])
3038
			else:
3039
				graph_key = tuple(x)
3031
			if "--tree" in self.myopts:
3040
			if "--tree" in self.myopts:
3032
				depth = len(tree_nodes)
3041
				depth = len(tree_nodes)
3033
				while depth and graph_key not in \
3042
				while depth and graph_key not in \
Lines 3094-3100 Link Here
3094
				continue
3103
				continue
3095
			if "blocks" == graph_key[0]:
3104
			if "blocks" == graph_key[0]:
3096
				continue
3105
				continue
3097
			if ordered and graph_key[-1] != "nomerge":
3106
			if len(graph_key) > 4:
3107
				merge_op = graph_key[-2]
3108
			else:
3109
				merge_op = graph_key[-1]
3110
			if ordered and merge_op != "nomerge":
3098
				last_merge_depth = depth
3111
				last_merge_depth = depth
3099
				continue
3112
				continue
3100
			if depth >= last_merge_depth or \
3113
			if depth >= last_merge_depth or \
Lines 3110-3116 Link Here
3110
3123
3111
		for mylist_index in xrange(len(mylist)):
3124
		for mylist_index in xrange(len(mylist)):
3112
			x, depth, ordered = mylist[mylist_index]
3125
			x, depth, ordered = mylist[mylist_index]
3113
			pkg_node = tuple(x)
3114
			pkg_type = x[0]
3126
			pkg_type = x[0]
3115
			myroot = x[1]
3127
			myroot = x[1]
3116
			pkg_key = x[2]
3128
			pkg_key = x[2]
Lines 3119-3124 Link Here
3119
			vardb = self.trees[myroot]["vartree"].dbapi
3131
			vardb = self.trees[myroot]["vartree"].dbapi
3120
			vartree = self.trees[myroot]["vartree"]
3132
			vartree = self.trees[myroot]["vartree"]
3121
			pkgsettings = self.pkgsettings[myroot]
3133
			pkgsettings = self.pkgsettings[myroot]
3134
			if len(x) > 4:
3135
				pkg_node = tuple(x[:-1])
3136
			else:
3137
				pkg_node = tuple(x)
3122
3138
3123
			fetch=" "
3139
			fetch=" "
3124
3140
Lines 3132-3138 Link Here
3132
					addl = addl + " " + red(resolved)
3148
					addl = addl + " " + red(resolved)
3133
				else:
3149
				else:
3134
					addl = "[blocks " + addl + "] " + red(resolved)
3150
					addl = "[blocks " + addl + "] " + red(resolved)
3135
				block_parents = self.blocker_parents[tuple(x)]
3151
				block_parents = self.blocker_parents[pkg_node]
3136
				block_parents = set([pnode[2] for pnode in block_parents])
3152
				block_parents = set([pnode[2] for pnode in block_parents])
3137
				block_parents = ", ".join(block_parents)
3153
				block_parents = ", ".join(block_parents)
3138
				if resolved!=x[2]:
3154
				if resolved!=x[2]:
Lines 3847-3855 Link Here
3847
		self.curval = 0
3863
		self.curval = 0
3848
		self._spawned_pids = []
3864
		self._spawned_pids = []
3849
3865
3850
	def merge(self, mylist, favorites, mtimedb):
3866
	def merge(self, mylist, favorites, mtimedb, m_slots):
3851
		try:
3867
		try:
3852
			return self._merge(mylist, favorites, mtimedb)
3868
			return self._merge(mylist, favorites, mtimedb, m_slots)
3853
		finally:
3869
		finally:
3854
			if self._spawned_pids:
3870
			if self._spawned_pids:
3855
				portage.portage_exec.spawned_pids.extend(self._spawned_pids)
3871
				portage.portage_exec.spawned_pids.extend(self._spawned_pids)
Lines 3874-3880 Link Here
3874
				pass
3890
				pass
3875
			spawned_pids.remove(pid)
3891
			spawned_pids.remove(pid)
3876
3892
3877
	def _merge(self, mylist, favorites, mtimedb):
3893
	def _merge(self, mylist, favorites, mtimedb, m_slots):
3878
		failed_fetches = []
3894
		failed_fetches = []
3879
		fetchonly = "--fetchonly" in self.myopts or \
3895
		fetchonly = "--fetchonly" in self.myopts or \
3880
			"--fetch-all-uri" in self.myopts
3896
			"--fetch-all-uri" in self.myopts
Lines 3882-3887 Link Here
3882
		mymergelist=[]
3898
		mymergelist=[]
3883
		ldpath_mtimes = mtimedb["ldpath"]
3899
		ldpath_mtimes = mtimedb["ldpath"]
3884
		xterm_titles = "notitles" not in self.settings.features
3900
		xterm_titles = "notitles" not in self.settings.features
3901
		parallel = "parallel" in self.settings.features
3902
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
3903
3904
		# parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
3905
		if self.edebug or "--fetchonly" in self.myopts:
3906
			parallel = False
3907
3885
3908
3886
		if "--resume" in self.myopts:
3909
		if "--resume" in self.myopts:
3887
			# We're resuming.
3910
			# We're resuming.
Lines 3913-3919 Link Here
3913
				if not shown_verifying_msg:
3936
				if not shown_verifying_msg:
3914
					shown_verifying_msg = True
3937
					shown_verifying_msg = True
3915
					print ">>> Verifying ebuild Manifests..."
3938
					print ">>> Verifying ebuild Manifests..."
3916
				mytype, myroot, mycpv, mystatus = x
3939
				mytype, myroot, mycpv, mystatus, slott = x
3917
				portdb = self.trees[myroot]["porttree"].dbapi
3940
				portdb = self.trees[myroot]["porttree"].dbapi
3918
				quiet_config = quiet_settings[myroot]
3941
				quiet_config = quiet_settings[myroot]
3919
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
3942
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
Lines 3922-3935 Link Here
3922
				del x, mytype, myroot, mycpv, mystatus, quiet_config
3945
				del x, mytype, myroot, mycpv, mystatus, quiet_config
3923
			del shown_verifying_msg, quiet_settings
3946
			del shown_verifying_msg, quiet_settings
3924
3947
3925
		root_config = RootConfig(self.trees[self.target_root])
3926
		system_set = root_config.sets["system"]
3927
		args_set = AtomSet(favorites)
3928
		world_set = root_config.sets["world"]
3929
		if "--resume" not in self.myopts:
3948
		if "--resume" not in self.myopts:
3930
			mymergelist = mylist
3949
			mymergelist = mylist
3931
			mtimedb["resume"]["mergelist"]=mymergelist[:]
3950
			if "--nodeps" not in self.myopts or len(mymergelist) > 1:
3932
			mtimedb.commit()
3951
				mtimedb["resume"]["mergelist"]=mymergelist[:]
3952
				mtimedb.commit()
3953
3954
		totalcount = len(mymergelist)
3955
		mergecount=1
3933
3956
3934
		myfeat = self.settings.features[:]
3957
		myfeat = self.settings.features[:]
3935
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
3958
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 3946-3957 Link Here
3946
			elif len(mymergelist) > 1:
3969
			elif len(mymergelist) > 1:
3947
				fetch_log = "/var/log/emerge-fetch.log"
3970
				fetch_log = "/var/log/emerge-fetch.log"
3948
				logfile = open(fetch_log, "w")
3971
				logfile = open(fetch_log, "w")
3949
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
3972
				fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
3950
				portage_util.apply_secpass_permissions(fetch_log,
3973
				portage_util.apply_secpass_permissions(fetch_log,
3951
					uid=portage.portage_uid, gid=portage.portage_gid,
3974
					uid=portage.portage_uid, gid=portage.portage_gid,
3952
					mode=0660)
3975
					mode=0660)
3953
				fetch_env = os.environ.copy()
3976
				fetch_env = os.environ.copy()
3954
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
3977
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
3955
				fetch_env["PORTAGE_NICENESS"] = "0"
3978
				fetch_env["PORTAGE_NICENESS"] = "0"
3956
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3979
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
3957
				resume_opts = self.myopts.copy()
3980
				resume_opts = self.myopts.copy()
Lines 3978-4327 Link Here
3978
		metadata_keys = [k for k in portage.auxdbkeys \
4001
		metadata_keys = [k for k in portage.auxdbkeys \
3979
			if not k.startswith("UNUSED_")] + ["USE"]
4002
			if not k.startswith("UNUSED_")] + ["USE"]
3980
4003
3981
		mergecount=0
4004
		if not parallel:
3982
		for x in mymergelist:
4005
			failed_fetches = []
3983
			mergecount+=1
4006
			for x in mymergelist:
3984
			pkg_type = x[0]
4007
				retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, metadata_keys)
3985
			myroot=x[1]
4008
				mergecount += 1
3986
			pkg_key = x[2]
4009
3987
			pkgindex=2
4010
				# need to short circuit the spawn with --nodeps
3988
			portdb = self.trees[myroot]["porttree"].dbapi
4011
				if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
3989
			bindb  = self.trees[myroot]["bintree"].dbapi
4012
					if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3990
			vartree = self.trees[myroot]["vartree"]
4013
						continue
3991
			pkgsettings = self.pkgsettings[myroot]
4014
					if retcode != os.EX_OK:
3992
			metadata = {}
4015
						if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
3993
			if pkg_type == "blocks":
4016
							failed_fetches.append(x[2])
3994
				pass
4017
							continue
3995
			elif pkg_type == "ebuild":
4018
						else:
3996
				mydbapi = portdb
4019
							return retcode
3997
				metadata.update(izip(metadata_keys,
4020
					# Unsafe for parallel merges
3998
					mydbapi.aux_get(pkg_key, metadata_keys)))
4021
					del mtimedb["resume"]["mergelist"][0]
3999
				pkgsettings.setcpv(pkg_key, mydb=mydbapi)
4022
					# Commit after each merge so that --resume may still work in
4000
				metadata["USE"] = pkgsettings["USE"]
4023
					# in the event that portage is not allowed to exit normally
4001
			else:
4024
					# due to power failure, SIGKILL, etc...
4002
				if pkg_type == "binary":
4025
					mtimedb.commit()
4003
					mydbapi = bindb
4026
					self.curval += 1
4027
					self._poll_child_processes()
4028
4029
					# unlink the logid_path if any exists
4030
					logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
4031
					if os.path.exists(logid_path):
4032
						os.unlink(logid_path)
4033
					del logid_path
4034
  
4035
					# check if we need to restart portage
4036
					mysplit=portage.pkgsplit(x[2])
4037
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
4038
							self.restart_portage(x, mergecount, totalcount, mtimedb)
4039
  
4004
				else:
4040
				else:
4005
					raise AssertionError("Package type: '%s'" % pkg_type)
4041
					if retcode != os.EX_OK:
4006
				metadata.update(izip(metadata_keys,
4042
						sys.exit(1)
4007
					mydbapi.aux_get(pkg_key, metadata_keys)))
4043
  					else:
4008
			if x[0]=="blocks":
4044
						sys.exit(0)
4009
				pkgindex=3
4045
  
4010
			y = portdb.findname(pkg_key)
4011
			if "--pretend" not in self.myopts:
4046
			if "--pretend" not in self.myopts:
4012
				print "\n>>> Emerging (" + \
4047
				emergelog(xterm_titles, " *** Finished. Cleaning up...")
4013
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
4048
  
4014
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
4049
			# We're out of the loop... We're done. Delete the resume data.
4015
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
4050
			if mtimedb.has_key("resume"):
4016
				emergelog(xterm_titles, " >>> emerge ("+\
4051
				del mtimedb["resume"]
4017
					str(mergecount)+" of "+str(len(mymergelist))+\
4052
			mtimedb.commit()
4018
					") "+x[pkgindex]+" to "+x[1])
4053
			
4054
			#by doing an exit this way, --fetchonly can continue to try to
4055
			#fetch everything even if a particular download fails.
4056
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4057
				if failed_fetches:
4058
					sys.stderr.write("\n\n!!! Some fetch errors were " + \
4059
						"encountered.  Please see above for details.\n\n")
4060
					for cpv in failed_fetches:
4061
						sys.stderr.write("   ")
4062
						sys.stderr.write(cpv)
4063
						sys.stderr.write("\n")
4064
					sys.stderr.write("\n")
4065
					sys.exit(1)
4066
				else:
4067
					sys.exit(0)
4068
			return os.EX_OK
4069
  
4070
		# parallel code - dirty starts here...;-)
4071
		one_in_slot_failed=0
4072
		spawnd_pids=[]
4073
4074
		# dirty little trick to get number of cpus from the system
4075
		fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
4076
		cpu_count = 0
4077
		for data_cpuinfo in fd_cpuinfo.readlines():
4078
			if data_cpuinfo.find("cpu MHz") > -1 :
4079
				cpu_count += 1
4080
		fd_cpuinfo.close()
4081
4082
		# if someone really screwed with /proc/cpuinfo output, we should not suffer
4083
		if cpu_count == 0:
4084
			cpu_count = 1
4085
4086
		spawnd_pkg = {}
4087
		donec = 0
4088
		failedc = 0
4089
		failedPkgs = []
4090
		logid_path = None
4091
		mylist = m_slots.keys()
4092
		mylist.sort()
4093
		for x in mylist:
4094
			# if slot is empty, go on
4095
			if not m_slots[x]:
4096
				continue
4019
4097
4020
			pkgsettings["EMERGE_FROM"] = x[0]
4098
			# if previous slot failed, discontinue the emerge
4021
			pkgsettings.backup_changes("EMERGE_FROM")
4099
			if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
4022
			pkgsettings.reset()
4100
				break
4023
4101
4024
			#buildsyspkg: Check if we need to _force_ binary package creation
4102
			# start multiple merges in parallel mode
4025
			issyspkg = ("buildsyspkg" in myfeat) \
4103
			num_at_atime = cpu_count + 1
4026
					and x[0] != "blocks" \
4104
4027
					and system_set.findAtomForPackage(pkg_key, metadata) \
4105
			qsize = 0
4028
					and "--buildpkg" not in self.myopts
4106
			for y in m_slots[x]:
4029
			if x[0] in ["ebuild","blocks"]:
4107
				# these all can go in parallel, so fork one after the other
4030
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
4108
				# but num_at_atime at most
4031
					raise Exception, "Merging a blocker"
4109
				if num_at_atime:
4032
				elif "--fetchonly" in self.myopts or \
4110
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, metadata_keys)
4033
					"--fetch-all-uri" in self.myopts:
4111
					spawnd_pids.append(onepid)
4034
					if "--fetch-all-uri" in self.myopts:
4112
					spawnd_pkg[onepid] = (y, x)
4035
						retval = portage.doebuild(y, "fetch", myroot,
4113
					num_at_atime -= 1
4036
							pkgsettings, self.edebug,
4114
					mergecount += 1
4037
							"--pretend" in self.myopts, fetchonly=1,
4115
					qsize += 1
4038
							fetchall=1, mydbapi=portdb, tree="porttree")
4116
				else:
4039
					else:
4117
					self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
4040
						retval = portage.doebuild(y, "fetch", myroot,
4118
					# let's wait for one of the jobs to finish
4041
							pkgsettings, self.edebug,
4119
					(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
4042
							"--pretend" in self.myopts, fetchonly=1,
4120
4043
							mydbapi=portdb, tree="porttree")
4121
					# if it failed, I need to fail next slot but continue to merge all in this slot
4044
					if (retval is None) or retval:
4122
					if retval:
4045
						print
4123
						one_in_slot_failed = retval
4046
						print "!!! Fetch for",y,"failed, continuing..."
4124
						failedc += 1
4047
						print
4125
						failedPkgs.append(pkg_compl[2])
4048
						failed_fetches.append(pkg_key)
4126
  					else:
4127
						donec += 1
4128
						self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, metadata_keys)
4129
					onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, metadata_keys)
4130
					spawnd_pids.append(onepid)
4131
					spawnd_pkg[onepid] = (y, x)
4132
					mergecount += 1
4133
4134
			# this slot is exhausted, so wait for all of the forks to finish
4135
			while spawnd_pids:
4136
				self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
4137
				# let's wait for one of the jobs to finish
4138
				(retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
4139
4140
				qsize -= 1
4141
				if retval:
4142
					one_in_slot_failed = retval
4143
					failedc += 1
4144
					failedPkgs.append(pkg_compl[2])
4145
				else:
4146
					donec += 1
4147
					self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, metadata_keys)
4148
		if totalcount:
4149
			self.print_status(totalcount, donec, qsize, failedc, None, failedPkgs)
4150
  
4151
		if one_in_slot_failed:
4152
			portage.writemsg_stdout(red("\nSome packages failed to emerge, summary follows:\n"))
4153
  
4154
		for pkgs in failedPkgs:
4155
			if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4156
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
4157
				sys.exit(1)
4158
4159
			portage.writemsg_stdout(red("\nPackage "+pkgs+" failed to emerge\n"))
4160
			logfile = None
4161
			if "PORT_LOGDIR" in self.settings:
4162
				port_logdir = self.settings["PORT_LOGDIR"]
4163
			else:
4164
				port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
4165
4166
			pkg_cat = pkgs.split("/")[0]
4167
			pkg_pf = pkgs.split("/")[1]
4168
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
4169
			if os.path.exists(logid_path):
4170
				logid_time = time.strftime("%Y%m%d-%H%M%S", time.gmtime(os.stat(logid_path).st_mtime))
4171
				logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
4172
					(pkg_cat, pkg_pf, logid_time))
4173
				del logid_time
4174
4175
			if logfile and os.path.exists(logfile):
4176
				portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
4177
4178
			if logfile and os.path.exists(logfile):
4179
				portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
4180
				os.unlink(logid_path)
4181
		if one_in_slot_failed:
4182
			sys.exit(1)
4183
		if "--pretend" not in self.myopts:
4184
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
4185
4186
		# see if there are any extraneous files in build_prefix, which we might have leftover
4187
		import glob
4188
		for fnames in glob.glob(os.path.join(build_prefix, ".logid.")+"*"):
4189
			os.unlink(fnames)
4190
4191
		# We're out of the loop... We're done. Delete the resume data.
4192
		if mtimedb.has_key("resume"):
4193
			del mtimedb["resume"]
4194
		mtimedb.commit()
4195
4196
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4197
			sys.exit(0)
4198
4199
		return os.EX_OK
4200
4201
	def print_status(self, totalcount, donec, qsize, failedc, spawnd_pkg, failed):
4202
		smsg = ""
4203
		fmsg = ""
4204
		if spawnd_pkg:
4205
			for pkgs in spawnd_pkg.values():
4206
				smsg = smsg+" "+pkgs[0][2]
4207
		if failed:
4208
			for pkgs in failed:
4209
				fmsg = fmsg+" "+pkgs
4210
		print ">>> Jobs [Total = "+colorize("blue", str(totalcount))+"] [Done = "+\
4211
			colorize("GOOD", str(donec))+"] [Running = "+colorize("WARN", str(qsize)+smsg)+\
4212
			"] [Failed = "+colorize("BAD", str(failedc)+fmsg)+"]"
4213
		xtermTitle("Jobs [Total="+str(totalcount)+"] [Done="+str(donec)+"] [Running="+str(qsize)+"] [Failed="+str(failedc)+"]")
4214
4215
	def wait_one_emerge(self, spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb):
4216
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
4217
		# let's wait for one of the jobs to finish
4218
		onepid = -1
4219
		while onepid not in spawnd_pids:
4220
			onepid , retval = os.waitpid(-1, 0)
4221
		spawnd_pids.remove(onepid)
4222
4223
		pkg_compl = spawnd_pkg[onepid][0]
4224
		pkg_slot = spawnd_pkg[onepid][1]
4225
		del spawnd_pkg[onepid]
4226
4227
		if not retval:
4228
			# unlink the logid_path
4229
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl[2].split("/")[0]+"."+pkg_compl[2].split("/")[1]
4230
			if os.path.exists(logid_path):
4231
				os.unlink(logid_path)
4232
			index = 0
4233
			print ">>> Package "+colorize("GOOD", pkg_compl[2])+" finished emerging."
4234
			# we need to remove this pkg from resume DB
4235
			# this is the dirtiest shit I have ever written
4236
			for pkgs in mymergelist:
4237
				if pkgs[2] == pkg_compl[2]:
4238
					if len(mymergelist) > 1:
4239
						del mtimedb["resume"]["mergelist"][index]
4240
						mtimedb.commit()
4049
					self.curval += 1
4241
					self.curval += 1
4050
					continue
4242
					self._poll_child_processes()
4243
					del mymergelist[index]
4244
					# check if we need to restart portage
4245
					mysplit=portage.pkgsplit(pkg_compl[2])
4246
					if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
4247
						self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
4248
					break
4249
				index += 1
4250
		return (retval, pkg_compl)
4251
4252
	def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, metadata_keys):
4253
		xterm_titles = "notitles" not in self.settings.features
4254
		myfeat = self.settings.features[:]
4255
		ldpath_mtimes = mtimedb["ldpath"]
4256
		myroot=x[1]
4257
		pkg_key = x[2]
4258
		pkg_cat = x[2].split("/")[0]
4259
		pkg_pf = x[2].split("/")[1]
4260
		pkgindex=2
4261
		if x[0]=="blocks":
4262
			pkgindex=3
4263
4264
		build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
4265
		portage_util.ensure_dirs(build_prefix, uid=portage.portage_uid, gid=portage.portage_gid, mode=0775)
4266
4267
		logid_path = None
4268
		null_log = 0
4269
4270
		if self.settings.get("PORT_LOGDIR", "") == "":
4271
			while "PORT_LOGDIR" in self.settings:
4272
				del self.settings["PORT_LOGDIR"]
4273
		if "PORT_LOGDIR" in self.settings:
4274
			port_logdir = self.settings["PORT_LOGDIR"]
4275
		else:
4276
			port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
4277
4278
		try:
4279
			portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
4280
						 gid=portage.portage_gid, mode=02770)
4281
		except portage_exception.PortageException, e:
4282
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
4283
			writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
4284
				self.settings["PORT_LOGDIR"], noiselevel=-1)
4285
			writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
4286
			null_log = 1
4287
4288
		if not null_log:
4289
			logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
4290
			if not os.path.exists(logid_path):
4291
				f = open(logid_path, "w")
4292
				f.close()
4293
				del f
4294
			logid_time = time.strftime("%Y%m%d-%H%M%S",
4295
				time.gmtime(os.stat(logid_path).st_mtime))
4296
			logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
4297
				(pkg_cat, pkg_pf, logid_time))
4298
			del logid_time
4299
		else:
4300
			logfile = "/dev/null"
4301
4302
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
4303
			print ">>> Emerging (" + \
4304
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
4305
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
4306
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
4307
			print ">>> Logfile in " + logfile
4308
			emergelog(xterm_titles, " >>> emerge ("+\
4309
				str(mergecount)+" of "+str(totalcount)+\
4310
				") "+x[pkgindex]+" to "+x[1])
4311
4312
		# need to spawn a --nodeps emerge in a separate process.
4313
		pkg="="+x[2]
4314
		merge_env = os.environ.copy()
4315
		merge_env["PORTAGE_INTERNAL_CALL"] = "1"
4316
		merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
4317
		merge_args = [sys.argv[0], "--nodeps", "--oneshot", "--nospinner", pkg]
4318
		good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
4319
					"--usepkg", "--usepkgonly"])
4320
		fd_pipes = None
4321
		merge_logfd = None
4322
		for myopt, myarg in self.myopts.iteritems():
4323
			# don't clobber the logfile at the same time as parallel fetch is
4324
			# all log of parallel fetch will go /var/log/emerge-fetch.log
4325
			# so, just leave 0,1,2 alone.
4326
			if "parallel-fetch" in myfeat and myopt == "--fetchonly":
4327
				fd_pipes = {0:0, 1:1, 2:2}
4328
			if myopt in good_nodeps_opts:
4329
				if myarg is True:
4330
					merge_args.append(myopt)
4331
				else:
4332
					merge_args.append(myopt +"="+ myarg)
4333
		if not fd_pipes:
4334
			merge_logfd = open(logfile, "w")
4335
			# put in a start message. This also makes sure that this fd is pointing to a good file on disk
4336
			# and hence will be used throughout the other spawns that will happen in the children.
4337
			merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
4338
			merge_logfd.flush()
4339
			fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
4340
			portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
4341
4342
		mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
4343
		if merge_logfd:
4344
			merge_logfd.close() # child has exclusive rights to it now.
4345
		return mypids[0]
4346
4347
	def restart_portage(self, x, mergecount, totalcount, mtimedb):
4348
		xterm_titles = "notitles" not in self.settings.features
4349
		# don't really restart if any of these is true
4350
		# XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
4351
		if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
4352
			"--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
4353
			return
4354
4355
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
4356
			"--resume"])
4357
		mysplit=portage.pkgsplit(x[2])
4358
		if "livecvsportage" not in self.settings.features:
4359
			if totalcount > mergecount:
4360
				emergelog(xterm_titles,
4361
					" ::: completed emerge ("+ \
4362
					str(mergecount)+" of "+ \
4363
					str(totalcount)+") "+ \
4364
					x[2]+" to "+x[1])
4365
				emergelog(xterm_titles, " *** RESTARTING " + \
4366
					"emerge via exec() after change of " + \
4367
					"portage version.")
4368
				portage.run_exitfuncs()
4369
				mynewargv=[sys.argv[0],"--resume"]
4370
				resume_opts = self.myopts.copy()
4371
				# For automatic resume, we need to prevent
4372
				# any of bad_resume_opts from leaking in
4373
				# via EMERGE_DEFAULT_OPTS.
4374
				resume_opts["--ignore-default-opts"] = True
4375
				for myopt, myarg in resume_opts.iteritems():
4376
					if myopt not in bad_resume_opts:
4377
						if myarg is True:
4378
							mynewargv.append(myopt)
4379
						else:
4380
							mynewargv.append(myopt +"="+ myarg)
4381
				# priority only needs to be adjusted on the first run
4382
				os.environ["PORTAGE_NICENESS"] = "0"
4383
				os.execv(mynewargv[0], mynewargv)
4384
4385
4386
	def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, metadata_keys):
4387
		xterm_titles = "notitles" not in self.settings.features
4388
		myfeat = self.settings.features[:]
4389
		ldpath_mtimes = mtimedb["ldpath"]
4390
		pkg_type = x[0]
4391
		myroot=x[1]
4392
		pkg_key = x[2]
4393
		pkg_cat = x[2].split("/")[0]
4394
		pkg_pf = x[2].split("/")[1]
4395
		pkgindex=2
4396
		if x[0]=="blocks":
4397
			pkgindex=3
4398
4399
		if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
4400
			print "\n>>> Emerging (" + \
4401
				colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
4402
				colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
4403
				colorize("GOOD", x[pkgindex]) + " to " + x[1]
4404
			emergelog(xterm_titles, " >>> emerge ("+\
4405
				str(mergecount)+" of "+str(totalcount)+\
4406
				") "+x[pkgindex]+" to "+x[1])
4407
4408
		portdb = self.trees[myroot]["porttree"].dbapi
4409
		bindb  = self.trees[myroot]["bintree"].dbapi
4410
		vartree = self.trees[myroot]["vartree"]
4411
		pkgsettings = self.pkgsettings[myroot]
4412
		metadata = {}
4413
		if pkg_type == "blocks":
4414
			pass
4415
		elif pkg_type == "ebuild":
4416
			mydbapi = portdb
4417
			metadata.update(izip(metadata_keys,
4418
				mydbapi.aux_get(pkg_key, metadata_keys)))
4419
			pkgsettings.setcpv(pkg_key, mydb=mydbapi)
4420
			metadata["USE"] = pkgsettings["USE"]
4421
		else:
4422
			if pkg_type == "binary":
4423
				mydbapi = bindb
4424
			else:
4425
				raise AssertionError("Package type: '%s'" % pkg_type)
4426
			metadata.update(izip(metadata_keys,
4427
				mydbapi.aux_get(pkg_key, metadata_keys)))
4428
		y = portdb.findname(pkg_key)
4429
		pkgsettings["EMERGE_FROM"] = x[0]
4430
		pkgsettings.backup_changes("EMERGE_FROM")
4431
		pkgsettings.reset()
4432
4433
		#buildsyspkg: Check if we need to _force_ binary package creation
4434
		issyspkg = ("buildsyspkg" in myfeat) \
4435
				and x[0] != "blocks" \
4436
				and system_set.findAtomForPackage(pkg_key, metadata) \
4437
				and "--buildpkg" not in self.myopts
4438
		if x[0] in ["ebuild","blocks"]:
4439
			if x[0] == "blocks" and "--fetchonly" not in self.myopts:
4440
				raise Exception, "Merging a blocker"
4441
			elif "--fetchonly" in self.myopts or \
4442
				"--fetch-all-uri" in self.myopts:
4443
				if "--fetch-all-uri" in self.myopts:
4444
					retval = portage.doebuild(y, "fetch", myroot,
4445
						pkgsettings, self.edebug,
4446
						"--pretend" in self.myopts, fetchonly=1,
4447
						fetchall=1, mydbapi=portdb, tree="porttree")
4448
				else:
4449
					retval = portage.doebuild(y, "fetch", myroot,
4450
						pkgsettings, self.edebug,
4451
						"--pretend" in self.myopts, fetchonly=1,
4452
						mydbapi=portdb, tree="porttree")
4453
				if (retval is None) or retval:
4454
					print
4455
					print "!!! Fetch for",y,"failed, continuing..."
4456
					print
4457
4458
				self.curval += 1
4459
				return retval
4051
4460
4052
				portage.doebuild_environment(y, "setup", myroot,
4461
			portage.doebuild_environment(y, "setup", myroot,
4053
					pkgsettings, self.edebug, 1, portdb)
4462
				pkgsettings, self.edebug, 1, portdb)
4054
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
4463
			catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
4055
				portage_util.ensure_dirs(os.path.dirname(catdir),
4464
			portage_util.ensure_dirs(os.path.dirname(catdir),
4465
				uid=portage.portage_uid, gid=portage.portage_gid,
4466
				mode=070, mask=0)
4467
			builddir_lock = None
4468
			catdir_lock = None
4469
			try:
4470
				catdir_lock = portage_locks.lockdir(catdir)
4471
				portage_util.ensure_dirs(catdir,
4056
					uid=portage.portage_uid, gid=portage.portage_gid,
4472
					uid=portage.portage_uid, gid=portage.portage_gid,
4057
					mode=070, mask=0)
4473
					mode=070, mask=0)
4058
				builddir_lock = None
4474
				builddir_lock = portage_locks.lockdir(
4059
				catdir_lock = None
4475
					pkgsettings["PORTAGE_BUILDDIR"])
4060
				try:
4476
				try:
4061
					catdir_lock = portage_locks.lockdir(catdir)
4477
					portage_locks.unlockdir(catdir_lock)
4062
					portage_util.ensure_dirs(catdir,
4478
				finally:
4063
						uid=portage.portage_uid, gid=portage.portage_gid,
4479
					catdir_lock = None
4064
						mode=070, mask=0)
4480
				msg = " === (%s of %s) Cleaning (%s::%s)" % \
4065
					builddir_lock = portage_locks.lockdir(
4481
					(mergecount, totalcount, pkg_key, y)
4066
						pkgsettings["PORTAGE_BUILDDIR"])
4482
				short_msg = "emerge: (%s of %s) %s Clean" % \
4067
					try:
4483
					(mergecount, totalcount, pkg_key)
4068
						portage_locks.unlockdir(catdir_lock)
4484
				emergelog(xterm_titles, msg, short_msg=short_msg)
4069
					finally:
4485
				retval = portage.doebuild(y, "clean", myroot,
4070
						catdir_lock = None
4486
					pkgsettings, self.edebug, cleanup=1,
4071
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
4487
					mydbapi=portdb, tree="porttree")
4072
						(mergecount, len(mymergelist), pkg_key, y)
4488
4073
					short_msg = "emerge: (%s of %s) %s Clean" % \
4489
				if retval != os.EX_OK:
4074
						(mergecount, len(mymergelist), pkg_key)
4490
					return retval
4491
				if "--buildpkg" in self.myopts or issyspkg:
4492
					if issyspkg:
4493
						print ">>> This is a system package, " + \
4494
							"let's pack a rescue tarball."
4495
					msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
4496
						(mergecount, totalcount, pkg_key, y)
4497
					short_msg = "emerge: (%s of %s) %s Compile" % \
4498
						(mergecount, totalcount, pkg_key)
4075
					emergelog(xterm_titles, msg, short_msg=short_msg)
4499
					emergelog(xterm_titles, msg, short_msg=short_msg)
4076
					retval = portage.doebuild(y, "clean", myroot,
4500
					self.trees[myroot]["bintree"].prevent_collision(pkg_key)
4077
						pkgsettings, self.edebug, cleanup=1,
4501
					retval = portage.doebuild(y, "package", myroot,
4078
						mydbapi=portdb, tree="porttree")
4502
						pkgsettings, self.edebug, mydbapi=portdb,
4503
						tree="porttree")
4504
					if retval != os.EX_OK or \
4505
						"--buildpkgonly" in self.myopts:
4506
						portage.elog_process(pkg_key, pkgsettings)
4079
					if retval != os.EX_OK:
4507
					if retval != os.EX_OK:
4080
						return retval
4508
						return retval
4081
					if "--buildpkg" in self.myopts or issyspkg:
4509
					bintree = self.trees[myroot]["bintree"]
4082
						if issyspkg:
4510
					if bintree.populated:
4083
							print ">>> This is a system package, " + \
4511
						bintree.inject(pkg_key)
4084
								"let's pack a rescue tarball."
4512
					if "--buildpkgonly" not in self.myopts:
4085
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
4513
						msg = " === (%s of %s) Merging (%s::%s)" % \
4086
							(mergecount, len(mymergelist), pkg_key, y)
4514
							(mergecount, totalcount, pkg_key, y)
4087
						short_msg = "emerge: (%s of %s) %s Compile" % \
4515
						short_msg = "emerge: (%s of %s) %s Merge" % \
4088
							(mergecount, len(mymergelist), pkg_key)
4516
							(mergecount, totalcount, pkg_key)
4089
						emergelog(xterm_titles, msg, short_msg=short_msg)
4517
						emergelog(xterm_titles, msg, short_msg=short_msg)
4090
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
4518
						retval = portage.merge(pkgsettings["CATEGORY"],
4091
						retval = portage.doebuild(y, "package", myroot,
4519
							pkgsettings["PF"], pkgsettings["D"],
4092
							pkgsettings, self.edebug, mydbapi=portdb,
4520
							os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
4093
							tree="porttree")
4521
							"build-info"), myroot, pkgsettings,
4094
						if retval != os.EX_OK or \
4522
							myebuild=pkgsettings["EBUILD"],
4095
							"--buildpkgonly" in self.myopts:
4523
							mytree="porttree", mydbapi=portdb,
4096
							portage.elog_process(pkg_key, pkgsettings)
4524
							vartree=vartree, prev_mtimes=ldpath_mtimes)
4097
						if retval != os.EX_OK:
4098
							return retval
4099
						bintree = self.trees[myroot]["bintree"]
4100
						if bintree.populated:
4101
							bintree.inject(pkg_key)
4102
						if "--buildpkgonly" not in self.myopts:
4103
							msg = " === (%s of %s) Merging (%s::%s)" % \
4104
								(mergecount, len(mymergelist), pkg_key, y)
4105
							short_msg = "emerge: (%s of %s) %s Merge" % \
4106
								(mergecount, len(mymergelist), pkg_key)
4107
							emergelog(xterm_titles, msg, short_msg=short_msg)
4108
							retval = portage.merge(pkgsettings["CATEGORY"],
4109
								pkgsettings["PF"], pkgsettings["D"],
4110
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
4111
								"build-info"), myroot, pkgsettings,
4112
								myebuild=pkgsettings["EBUILD"],
4113
								mytree="porttree", mydbapi=portdb,
4114
								vartree=vartree, prev_mtimes=ldpath_mtimes)
4115
							if retval != os.EX_OK:
4116
								return retval
4117
						elif "noclean" not in pkgsettings.features:
4118
							portage.doebuild(y, "clean", myroot,
4119
								pkgsettings, self.edebug, mydbapi=portdb,
4120
								tree="porttree")
4121
					else:
4122
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
4123
							(mergecount, len(mymergelist), pkg_key, y)
4124
						short_msg = "emerge: (%s of %s) %s Compile" % \
4125
							(mergecount, len(mymergelist), pkg_key)
4126
						emergelog(xterm_titles, msg, short_msg=short_msg)
4127
						retval = portage.doebuild(y, "merge", myroot,
4128
							pkgsettings, self.edebug, vartree=vartree,
4129
							mydbapi=portdb, tree="porttree",
4130
							prev_mtimes=ldpath_mtimes)
4131
						if retval != os.EX_OK:
4525
						if retval != os.EX_OK:
4132
							return retval
4526
							return retval
4527
					elif "noclean" not in pkgsettings.features:
4528
						portage.doebuild(y, "clean", myroot,
4529
							pkgsettings, self.edebug, mydbapi=portdb,
4530
							tree="porttree")
4531
				else:
4532
					msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
4533
						(mergecount, totalcount, pkg_key, y)
4534
					short_msg = "emerge: (%s of %s) %s Compile" % \
4535
						(mergecount, totalcount, pkg_key)
4536
					emergelog(xterm_titles, msg, short_msg=short_msg)
4537
					retval = portage.doebuild(y, "merge", myroot,
4538
						pkgsettings, self.edebug, vartree=vartree,
4539
						mydbapi=portdb, tree="porttree",
4540
						prev_mtimes=ldpath_mtimes)
4541
					if retval != os.EX_OK:
4542
						return retval
4543
			finally:
4544
				if builddir_lock:
4545
					portage_locks.unlockdir(builddir_lock)
4546
				try:
4547
					if not catdir_lock:
4548
						# Lock catdir for removal if empty.
4549
						catdir_lock = portage_locks.lockdir(catdir)
4133
				finally:
4550
				finally:
4134
					if builddir_lock:
4551
					if catdir_lock:
4135
						portage_locks.unlockdir(builddir_lock)
4552
						try:
4136
					try:
4553
							os.rmdir(catdir)
4137
						if not catdir_lock:
4554
						except OSError, e:
4138
							# Lock catdir for removal if empty.
4555
							if e.errno not in (errno.ENOENT,
4139
							catdir_lock = portage_locks.lockdir(catdir)
4556
								errno.ENOTEMPTY, errno.EEXIST):
4140
					finally:
4557
								raise
4141
						if catdir_lock:
4558
							del e
4142
							try:
4559
						portage_locks.unlockdir(catdir_lock)
4143
								os.rmdir(catdir)
4144
							except OSError, e:
4145
								if e.errno not in (errno.ENOENT,
4146
									errno.ENOTEMPTY, errno.EEXIST):
4147
									raise
4148
								del e
4149
							portage_locks.unlockdir(catdir_lock)
4150
4151
			elif x[0]=="binary":
4152
				#merge the tbz2
4153
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
4154
				if "--getbinpkg" in self.myopts:
4155
					tbz2_lock = None
4156
					try:
4157
						if "distlocks" in pkgsettings.features and \
4158
							os.access(pkgsettings["PKGDIR"], os.W_OK):
4159
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
4160
							tbz2_lock = portage_locks.lockfile(mytbz2,
4161
								wantnewlockfile=1)
4162
						if self.trees[myroot]["bintree"].isremote(pkg_key):
4163
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
4164
								(mergecount, len(mymergelist), pkg_key, mytbz2)
4165
							short_msg = "emerge: (%s of %s) %s Fetch" % \
4166
								(mergecount, len(mymergelist), pkg_key)
4167
							emergelog(xterm_titles, msg, short_msg=short_msg)
4168
							try:
4169
								self.trees[myroot]["bintree"].gettbz2(pkg_key)
4170
							except portage_exception.FileNotFound:
4171
								writemsg("!!! Fetching Binary failed " + \
4172
									"for '%s'\n" % pkg_key, noiselevel=-1)
4173
								if not fetchonly:
4174
									return 1
4175
								failed_fetches.append(pkg_key)
4176
							except portage_exception.DigestException, e:
4177
								writemsg("\n!!! Digest verification failed:\n",
4178
									noiselevel=-1)
4179
								writemsg("!!! %s\n" % e.value[0],
4180
									noiselevel=-1)
4181
								writemsg("!!! Reason: %s\n" % e.value[1],
4182
									noiselevel=-1)
4183
								writemsg("!!! Got: %s\n" % e.value[2],
4184
									noiselevel=-1)
4185
								writemsg("!!! Expected: %s\n" % e.value[3],
4186
									noiselevel=-1)
4187
								os.unlink(mytbz2)
4188
								if not fetchonly:
4189
									return 1
4190
								failed_fetches.append(pkg_key)
4191
					finally:
4192
						if tbz2_lock:
4193
							portage_locks.unlockfile(tbz2_lock)
4194
4560
4195
				if "--fetchonly" in self.myopts or \
4561
		elif x[0]=="binary":
4196
					"--fetch-all-uri" in self.myopts:
4562
			#merge the tbz2
4197
					self.curval += 1
4563
			mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
4198
					continue
4564
			if "--getbinpkg" in self.myopts:
4565
				tbz2_lock = None
4566
				try:
4567
					if "distlocks" in pkgsettings.features and \
4568
						os.access(pkgsettings["PKGDIR"], os.W_OK):
4569
						portage_util.ensure_dirs(os.path.dirname(mytbz2))
4570
						tbz2_lock = portage_locks.lockfile(mytbz2,
4571
							wantnewlockfile=1)
4572
					if self.trees[myroot]["bintree"].isremote(pkg_key):
4573
						msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
4574
							(mergecount, totalcount, pkg_key, mytbz2)
4575
						short_msg = "emerge: (%s of %s) %s Fetch" % \
4576
							(mergecount, totalcount, pkg_key)
4577
						emergelog(xterm_titles, msg, short_msg=short_msg)
4578
						try:
4579
							self.trees[myroot]["bintree"].gettbz2(pkg_key)
4580
						except portage_exception.FileNotFound:
4581
							writemsg("!!! Fetching Binary failed " + \
4582
								"for '%s'\n" % pkg_key, noiselevel=-1)
4583
							if not fetchonly:
4584
								return 1
4585
						except portage_exception.DigestException, e:
4586
							writemsg("\n!!! Digest verification failed:\n",
4587
								noiselevel=-1)
4588
							writemsg("!!! %s\n" % e.value[0],
4589
								noiselevel=-1)
4590
							writemsg("!!! Reason: %s\n" % e.value[1],
4591
								noiselevel=-1)
4592
							writemsg("!!! Got: %s\n" % e.value[2],
4593
								noiselevel=-1)
4594
							writemsg("!!! Expected: %s\n" % e.value[3],
4595
								noiselevel=-1)
4596
							os.unlink(mytbz2)
4597
							if not fetchonly:
4598
								return 1
4599
				finally:
4600
					if tbz2_lock:
4601
						portage_locks.unlockfile(tbz2_lock)
4199
4602
4200
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
4603
			if "--fetchonly" in self.myopts or \
4201
				emergelog(xterm_titles, " === ("+str(mergecount)+\
4604
				"--fetch-all-uri" in self.myopts:
4202
					" of "+str(len(mymergelist))+") Merging Binary ("+\
4605
				self.curval += 1
4203
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
4606
				return os.EX_OK
4204
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
4205
					mydbapi=bindb,
4206
					vartree=self.trees[myroot]["vartree"],
4207
					prev_mtimes=ldpath_mtimes)
4208
				if retval != os.EX_OK:
4209
					return retval
4210
				#need to check for errors
4211
			if "--buildpkgonly" not in self.myopts:
4212
				self.trees[x[1]]["vartree"].inject(x[2])
4213
				myfavkey = portage.cpv_getkey(x[2])
4214
				if not fetchonly and not pretend and \
4215
					args_set.findAtomForPackage(pkg_key, metadata):
4216
					world_set.lock()
4217
					world_set.load()
4218
					myfavkey = create_world_atom(pkg_key, metadata,
4219
						args_set, root_config)
4220
					if myfavkey:
4221
						world_set.add(myfavkey)
4222
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
4223
						emergelog(xterm_titles, " === ("+\
4224
							str(mergecount)+" of "+\
4225
							str(len(mymergelist))+\
4226
							") Updating world file ("+x[pkgindex]+")")
4227
						world_set.save()
4228
					world_set.unlock()
4229
4230
				if "--pretend" not in self.myopts and \
4231
					"--fetchonly" not in self.myopts and \
4232
					"--fetch-all-uri" not in self.myopts:
4233
					# Clean the old package that we have merged over top of it.
4234
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
4235
						xsplit=portage.pkgsplit(x[2])
4236
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
4237
						retval = unmerge(pkgsettings, self.myopts, vartree,
4238
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
4239
						if not retval:
4240
							emergelog(xterm_titles,
4241
								" --- AUTOCLEAN: Nothing unmerged.")
4242
					else:
4243
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
4244
							+ " AUTOCLEAN is disabled.  This can cause serious"
4245
							+ " problems due to overlapping packages.\n")
4246
4607
4247
					# Figure out if we need a restart.
4608
			short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
4248
					mysplit=portage.pkgsplit(x[2])
4609
			emergelog(xterm_titles, " === ("+str(mergecount)+\
4249
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
4610
				" of "+str(totalcount)+") Merging Binary ("+\
4250
						if "livecvsportage" not in self.settings.features:
4611
				x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
4251
							if len(mymergelist) > mergecount:
4612
4252
								emergelog(xterm_titles,
4613
			retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
4253
									" ::: completed emerge ("+ \
4614
				mydbapi=bindb,
4254
									str(mergecount)+" of "+ \
4615
				vartree=self.trees[myroot]["vartree"],
4255
									str(len(mymergelist))+") "+ \
4616
				prev_mtimes=ldpath_mtimes)
4256
									x[2]+" to "+x[1])
4617
			if retval != os.EX_OK:
4257
								emergelog(xterm_titles, " *** RESTARTING " + \
4618
				return retval
4258
									"emerge via exec() after change of " + \
4619
			#need to check for errors
4259
									"portage version.")
4260
								del mtimedb["resume"]["mergelist"][0]
4261
								mtimedb.commit()
4262
								portage.run_exitfuncs()
4263
								mynewargv=[sys.argv[0],"--resume"]
4264
								resume_opts = self.myopts.copy()
4265
								# For automatic resume, we need to prevent
4266
								# any of bad_resume_opts from leaking in
4267
								# via EMERGE_DEFAULT_OPTS.
4268
								resume_opts["--ignore-default-opts"] = True
4269
								for myopt, myarg in resume_opts.iteritems():
4270
									if myopt not in bad_resume_opts:
4271
										if myarg is True:
4272
											mynewargv.append(myopt)
4273
										else:
4274
											mynewargv.append(myopt +"="+ myarg)
4275
								# priority only needs to be adjusted on the first run
4276
								os.environ["PORTAGE_NICENESS"] = "0"
4277
								os.execv(mynewargv[0], mynewargv)
4278
4279
			if "--pretend" not in self.myopts and \
4280
				"--fetchonly" not in self.myopts and \
4281
				"--fetch-all-uri" not in self.myopts:
4282
				if "noclean" not in self.settings.features:
4283
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
4284
						(mergecount, len(mymergelist), x[pkgindex])
4285
					emergelog(xterm_titles, (" === (%s of %s) " + \
4286
						"Post-Build Cleaning (%s::%s)") % \
4287
						(mergecount, len(mymergelist), x[pkgindex], y),
4288
						short_msg=short_msg)
4289
				emergelog(xterm_titles, " ::: completed emerge ("+\
4290
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
4291
					x[2]+" to "+x[1])
4292
4620
4293
			# Unsafe for parallel merges
4621
		# clean up the older version which emerged on top of
4294
			del mtimedb["resume"]["mergelist"][0]
4622
		if "--buildpkgonly" not in self.myopts and \
4295
			# Commit after each merge so that --resume may still work in
4623
			"--pretend" not in self.myopts and \
4296
			# in the event that portage is not allowed to exit normally
4624
			"--fetchonly" not in self.myopts and \
4297
			# due to power failure, SIGKILL, etc...
4625
			"--fetch-all-uri" not in self.myopts:
4298
			mtimedb.commit()
4626
			# Clean the old package that we have merged over top of it.
4299
			self.curval += 1
4627
			if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
4300
			self._poll_child_processes()
4628
				xsplit=portage.pkgsplit(x[2])
4629
				emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
4630
				retval = unmerge(pkgsettings, self.myopts, vartree,
4631
					"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
4632
				if not retval:
4633
					emergelog(xterm_titles,
4634
						" --- AUTOCLEAN: Nothing unmerged.")
4635
			else:
4636
				portage.writemsg_stdout(colorize("WARN", "WARNING:")
4637
					+ " AUTOCLEAN is disabled.  This can cause serious"
4638
					+ " problems due to overlapping packages.\n")
4301
4639
4302
		if "--pretend" not in self.myopts:
4640
		if "--pretend" not in self.myopts and \
4303
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
4641
			"--fetchonly" not in self.myopts and \
4642
			"--fetch-all-uri" not in self.myopts:
4643
			if "noclean" not in self.settings.features:
4644
				short_msg = "emerge: (%s of %s) %s Clean Post" % \
4645
					(mergecount, totalcount, x[pkgindex])
4646
				emergelog(xterm_titles, (" === (%s of %s) " + \
4647
					"Post-Build Cleaning (%s::%s)") % \
4648
					(mergecount, totalcount, x[pkgindex], y),
4649
					short_msg=short_msg)
4650
			emergelog(xterm_titles, " ::: completed emerge ("+\
4651
				str(mergecount)+" of "+str(totalcount)+") "+\
4652
				x[2]+" to "+x[1])
4304
4653
4305
		# We're out of the loop... We're done. Delete the resume data.
4654
		return os.EX_OK
4306
		if mtimedb.has_key("resume"):
4307
			del mtimedb["resume"]
4308
		mtimedb.commit()
4309
4655
4310
		#by doing an exit this way, --fetchonly can continue to try to
4656
	def add_one_emerge_to_world(self, x, mergecount, totalcount, favorites, metadata_keys):
4311
		#fetch everything even if a particular download fails.
4657
		fetchonly = "--fetchonly" in self.myopts or \
4312
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4658
			"--fetch-all-uri" in self.myopts
4313
			if failed_fetches:
4659
		pretend = "--pretend" in self.myopts
4314
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
4660
		xterm_titles = "notitles" not in self.settings.features
4315
					"encountered.  Please see above for details.\n\n")
4661
		pkg_type = x[0]
4316
				for cpv in failed_fetches:
4662
		myroot=x[1]
4317
					sys.stderr.write("   ")
4663
		pkg_key = x[2]
4318
					sys.stderr.write(cpv)
4664
		pkgindex=2
4319
					sys.stderr.write("\n")
4665
		if x[0]=="blocks":
4320
				sys.stderr.write("\n")
4666
			pkgindex=3
4321
				sys.exit(1)
4667
4668
		portdb = self.trees[myroot]["porttree"].dbapi
4669
		bindb  = self.trees[myroot]["bintree"].dbapi
4670
		pkgsettings = self.pkgsettings[myroot]
4671
		root_config = RootConfig(self.trees[self.target_root])
4672
		system_set = root_config.sets["system"]
4673
		args_set = AtomSet(favorites)
4674
		world_set = root_config.sets["world"]
4675
		metadata = {}
4676
		if pkg_type == "blocks":
4677
			pass
4678
		elif pkg_type == "ebuild":
4679
			mydbapi = portdb
4680
			metadata.update(izip(metadata_keys,
4681
				mydbapi.aux_get(pkg_key, metadata_keys)))
4682
			pkgsettings.setcpv(pkg_key, mydb=mydbapi)
4683
			metadata["USE"] = pkgsettings["USE"]
4684
		else:
4685
			if pkg_type == "binary":
4686
				mydbapi = bindb
4322
			else:
4687
			else:
4323
				sys.exit(0)
4688
				raise AssertionError("Package type: '%s'" % pkg_type)
4324
		return os.EX_OK
4689
			metadata.update(izip(metadata_keys,
4690
				mydbapi.aux_get(pkg_key, metadata_keys)))
4691
4692
		if "--buildpkgonly" not in self.myopts:
4693
			self.trees[x[1]]["vartree"].inject(x[2])
4694
			myfavkey = portage.cpv_getkey(x[2])
4695
			if not fetchonly and not pretend and \
4696
				args_set.findAtomForPackage(pkg_key, metadata):
4697
				world_set.lock()
4698
				world_set.load()
4699
				myfavkey = create_world_atom(pkg_key, metadata,
4700
					args_set, root_config)
4701
				if myfavkey:
4702
					world_set.add(myfavkey)
4703
					print ">>> Recording",myfavkey,"in \"world\" favorites file..."
4704
					emergelog(xterm_titles, " === ("+\
4705
						str(mergecount)+" of "+\
4706
						str(totalcount)+\
4707
						") Updating world file ("+x[pkgindex]+")")
4708
					world_set.save()
4709
				world_set.unlock()
4710
4325
4711
4326
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
4712
def unmerge(settings, myopts, vartree, unmerge_action, unmerge_files,
4327
	ldpath_mtimes, autoclean=0):
4713
	ldpath_mtimes, autoclean=0):
Lines 5764-5770 Link Here
5764
				">>> No packages selected for removal by %s\n" % action)
6150
				">>> No packages selected for removal by %s\n" % action)
5765
			return
6151
			return
5766
6152
5767
	if "--quiet" not in myopts:
6153
	if "--quiet" not in myopts and "--nodeps" not in myopts:
5768
		print "\nCalculating dependencies  ",
6154
		print "\nCalculating dependencies  ",
5769
6155
5770
	soft = 0
6156
	soft = 0
Lines 5984-5989 Link Here
5984
	else:
6370
	else:
5985
		print "Number removed:       "+str(len(cleanlist))
6371
		print "Number removed:       "+str(len(cleanlist))
5986
6372
6373
def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
6374
	merge_slots = {}
6375
	for pkg in mergelist:
6376
		if pkg[0] != 'blocks' and pkg[3] == 'merge':
6377
			slot = int(pkg[4])
6378
			try:
6379
				if pkg not in merge_slots[slot]:
6380
					merge_slots[slot].append(pkg)
6381
			except KeyError:
6382
				merge_slots[slot] = [pkg]
6383
	# print the merge slots
6384
	max_slot = 0
6385
	mylist = merge_slots.keys()
6386
	mylist.sort()
6387
	for x in mylist:
6388
		if x > max_slot:
6389
			max_slot = x
6390
		if parallel:
6391
			print "Package list for slot = "+str(x)
6392
			for y in merge_slots[x]:
6393
				print "	",y
6394
	if printonly:
6395
		return
6396
6397
	# make one last pass at the merge_slots and initialize the missing slots to None
6398
	x = 0
6399
	while x < max_slot:
6400
		if x not in merge_slots.keys():
6401
			merge_slots[x] = None
6402
		x += 1
6403
	return merge_slots
6404
5987
def action_build(settings, trees, mtimedb,
6405
def action_build(settings, trees, mtimedb,
5988
	myopts, myaction, myfiles, spinner):
6406
	myopts, myaction, myfiles, spinner):
5989
	ldpath_mtimes = mtimedb["ldpath"]
6407
	ldpath_mtimes = mtimedb["ldpath"]
Lines 6110-6127 Link Here
6110
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6528
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6111
				return os.EX_OK
6529
				return os.EX_OK
6112
			favorites = mtimedb["resume"]["favorites"]
6530
			favorites = mtimedb["resume"]["favorites"]
6531
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6113
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6532
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6114
			if retval != os.EX_OK:
6533
			if retval != os.EX_OK:
6115
				return retval
6534
				return retval
6116
			prompt="Would you like to resume merging these packages?"
6535
			prompt="Would you like to resume merging these packages?"
6117
		else:
6536
		else:
6118
			retval = mydepgraph.display(
6537
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
6119
				mydepgraph.altlist(reversed=("--tree" in myopts)),
6538
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6120
				favorites=favorites)
6539
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6121
			if retval != os.EX_OK:
6540
			if retval != os.EX_OK:
6122
				return retval
6541
				return retval
6123
			mergecount=0
6542
			mergecount=0
6124
			for x in mydepgraph.altlist():
6543
			for x in mymergelist:
6125
				if x[0] != "blocks" and x[3] != "nomerge":
6544
				if x[0] != "blocks" and x[3] != "nomerge":
6126
					mergecount+=1
6545
					mergecount+=1
6127
				#check for blocking dependencies
6546
				#check for blocking dependencies
Lines 6166-6178 Link Here
6166
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6585
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6167
				return os.EX_OK
6586
				return os.EX_OK
6168
			favorites = mtimedb["resume"]["favorites"]
6587
			favorites = mtimedb["resume"]["favorites"]
6588
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6169
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6589
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6170
			if retval != os.EX_OK:
6590
			if retval != os.EX_OK:
6171
				return retval
6591
				return retval
6172
		else:
6592
		else:
6173
			retval = mydepgraph.display(
6593
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
6174
				mydepgraph.altlist(reversed=("--tree" in myopts)),
6594
			mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6175
				favorites=favorites)
6595
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6176
			if retval != os.EX_OK:
6596
			if retval != os.EX_OK:
6177
				return retval
6597
				return retval
6178
			if "--buildpkgonly" in myopts and \
6598
			if "--buildpkgonly" in myopts and \
Lines 6195-6216 Link Here
6195
				it to write the mtimedb"""
6615
				it to write the mtimedb"""
6196
				mtimedb.filename = None
6616
				mtimedb.filename = None
6197
				time.sleep(3) # allow the parent to have first fetch
6617
				time.sleep(3) # allow the parent to have first fetch
6618
			mymergelist = mtimedb["resume"]["mergelist"]
6619
			if "--skipfirst" in myopts:
6620
				mymergelist = mymergelist[1:]
6621
			if len(mymergelist) == 0:
6622
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6623
				sys.exit(0)
6624
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
6198
			del mydepgraph
6625
			del mydepgraph
6199
			retval = mergetask.merge(
6626
			retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
6200
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
6201
			merge_count = mergetask.curval
6627
			merge_count = mergetask.curval
6202
		else:
6628
		else:
6203
			if "resume" in mtimedb and \
6629
			mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
6204
			"mergelist" in mtimedb["resume"] and \
6630
			merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
6205
			len(mtimedb["resume"]["mergelist"]) > 1:
6631
			if "--nodeps" not in myopts or len(mymergelist) > 1:
6206
				mtimedb["resume_backup"] = mtimedb["resume"]
6632
				if "resume" in mtimedb and \
6207
				del mtimedb["resume"]
6633
				"mergelist" in mtimedb["resume"] and \
6208
				mtimedb.commit()
6634
				len(mtimedb["resume"]["mergelist"]) > 1:
6209
			mtimedb["resume"]={}
6635
					mtimedb["resume_backup"] = mtimedb["resume"]
6210
			# XXX: Stored as a list for backward compatibility.
6636
					del mtimedb["resume"]
6211
			mtimedb["resume"]["myopts"] = \
6637
					mtimedb.commit()
6212
				[k for k in myopts if myopts[k] is True]
6638
				mtimedb["resume"]={}
6213
			mtimedb["resume"]["favorites"]=favorites
6639
				# XXX: Stored as a list for backward compatibility.
6640
				mtimedb["resume"]["myopts"] = \
6641
					[k for k in myopts if myopts[k] is True]
6642
				mtimedb["resume"]["favorites"]=favorites
6214
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
6643
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
6215
				for pkgline in mydepgraph.altlist():
6644
				for pkgline in mydepgraph.altlist():
6216
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
6645
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 6225-6231 Link Here
6225
							mydbapi=trees[pkgline[1]]["porttree"].dbapi,
6654
							mydbapi=trees[pkgline[1]]["porttree"].dbapi,
6226
							tree="porttree")
6655
							tree="porttree")
6227
6656
6228
			pkglist = mydepgraph.altlist()
6657
			pkglist = mymergelist
6229
6658
6230
			if fetchonly or "--buildpkgonly"  in myopts:
6659
			if fetchonly or "--buildpkgonly"  in myopts:
6231
				pkglist = [pkg for pkg in pkglist if pkg[0] != "blocks"]
6660
				pkglist = [pkg for pkg in pkglist if pkg[0] != "blocks"]
Lines 6233-6241 Link Here
6233
				for x in pkglist:
6662
				for x in pkglist:
6234
					if x[0] != "blocks":
6663
					if x[0] != "blocks":
6235
						continue
6664
						continue
6236
					retval = mydepgraph.display(mydepgraph.altlist(
6665
					retval = mydepgraph.display(mymergelist, favorites=favorites)
6237
						reversed=("--tree" in myopts)),
6238
						favorites=favorites)
6239
					msg = "Error: The above package list contains " + \
6666
					msg = "Error: The above package list contains " + \
6240
						"packages which cannot be installed " + \
6667
						"packages which cannot be installed " + \
6241
						"at the same time on the same system."
6668
						"at the same time on the same system."
Lines 6252-6262 Link Here
6252
				mydepgraph.saveNomergeFavorites()
6679
				mydepgraph.saveNomergeFavorites()
6253
			del mydepgraph
6680
			del mydepgraph
6254
			mergetask = MergeTask(settings, trees, myopts)
6681
			mergetask = MergeTask(settings, trees, myopts)
6255
			retval = mergetask.merge(pkglist, favorites, mtimedb)
6682
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
6256
			merge_count = mergetask.curval
6683
			merge_count = mergetask.curval
6257
6684
6258
		if retval == os.EX_OK and not (pretend or fetchonly):
6685
		if retval == os.EX_OK and not (pretend or fetchonly):
6259
			mtimedb.pop("resume", None)
6686
			if ("--nodeps" not in myopts or len(mymergelist) > 1):
6687
				mtimedb.pop("resume", None)
6260
			if "yes" == settings.get("AUTOCLEAN"):
6688
			if "yes" == settings.get("AUTOCLEAN"):
6261
				portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
6689
				portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
6262
				vartree = trees[settings["ROOT"]]["vartree"]
6690
				vartree = trees[settings["ROOT"]]["vartree"]
(-)portage-2.1.4.orig/pym/portage.py (-2 / +6 lines)
Lines 86-92 Link Here
86
	from output import bold, colorize, green, red, yellow
86
	from output import bold, colorize, green, red, yellow
87
87
88
	import portage_const
88
	import portage_const
89
	from portage_const import VDB_PATH, PRIVATE_PATH, CACHE_PATH, DEPCACHE_PATH, \
89
	from portage_const import VDB_PATH, PRIVATE_PATH, DEF_LOGDIR, CACHE_PATH, DEPCACHE_PATH, \
90
	  USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
90
	  USER_CONFIG_PATH, MODULES_FILE_PATH, CUSTOM_PROFILE_PATH, PORTAGE_BASE_PATH, \
91
	  PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
91
	  PORTAGE_BIN_PATH, PORTAGE_PYM_PATH, PROFILE_PATH, LOCALE_DATA_PATH, \
92
	  EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
92
	  EBUILD_SH_BINARY, SANDBOX_BINARY, BASH_BINARY, \
Lines 4117-4122 Link Here
4117
	if mysettings.get("PORT_LOGDIR", "") == "":
4117
	if mysettings.get("PORT_LOGDIR", "") == "":
4118
		while "PORT_LOGDIR" in mysettings:
4118
		while "PORT_LOGDIR" in mysettings:
4119
			del mysettings["PORT_LOGDIR"]
4119
			del mysettings["PORT_LOGDIR"]
4120
4121
	if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
4122
		mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + DEF_LOGDIR
4123
4120
	if "PORT_LOGDIR" in mysettings:
4124
	if "PORT_LOGDIR" in mysettings:
4121
		try:
4125
		try:
4122
			modified = portage_util.ensure_dirs(mysettings["PORT_LOGDIR"])
4126
			modified = portage_util.ensure_dirs(mysettings["PORT_LOGDIR"])
Lines 4131-4137 Link Here
4131
			while "PORT_LOGDIR" in mysettings:
4135
			while "PORT_LOGDIR" in mysettings:
4132
				del mysettings["PORT_LOGDIR"]
4136
				del mysettings["PORT_LOGDIR"]
4133
	if "PORT_LOGDIR" in mysettings:
4137
	if "PORT_LOGDIR" in mysettings:
4134
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
4138
		logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
4135
		if not os.path.exists(logid_path):
4139
		if not os.path.exists(logid_path):
4136
			f = open(logid_path, "w")
4140
			f = open(logid_path, "w")
4137
			f.close()
4141
			f.close()
(-)portage-2.1.4.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.4.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 190-216 Link Here
190
	# mypids will hold the pids of all processes created.
192
	# mypids will hold the pids of all processes created.
191
	mypids = []
193
	mypids = []
192
194
195
	pw = None
193
	if logfile:
196
	if logfile:
194
		# Using a log file requires that stdout and stderr
197
		# Using a log file requires that stdout and stderr
195
		# are assigned to the process we're running.
198
		# are assigned to the process we're running.
196
		if 1 not in fd_pipes or 2 not in fd_pipes:
199
		if 1 not in fd_pipes or 2 not in fd_pipes:
197
			raise ValueError(fd_pipes)
200
			raise ValueError(fd_pipes)
198
201
199
		# Create a pipe
202
		tee_good = 1
200
		(pr, pw) = os.pipe()
203
		try:
201
204
			statinfo1 = os.stat(logfile)
202
		# Create a tee process, giving it our stdout and stderr
205
			statinfo2 = os.fstat(fd_pipes[1])
203
		# as well as the read end of the pipe.
206
			statinfo3 = os.fstat(fd_pipes[2])
204
		mypids.extend(spawn(('tee', '-i', '-a', logfile),
207
			# if they are pointing to same file as logfile, no 'tee' is required.
205
		              returnpid=True, fd_pipes={0:pr,
208
			if statinfo1 == statinfo2 and statinfo2 == statinfo3:
206
		              1:fd_pipes[1], 2:fd_pipes[2]}))
209
				tee_good = 0
207
210
		except:
208
		# We don't need the read end of the pipe, so close it.
211
			tee_good = 1
209
		os.close(pr)
212
210
213
		if tee_good:
211
		# Assign the write end of the pipe to our stdout and stderr.
214
212
		fd_pipes[1] = pw
215
			# Create a pipe
213
		fd_pipes[2] = pw
216
			(pr, pw) = os.pipe()
217
218
			# Create a tee process, giving it our stdout and stderr
219
			# as well as the read end of the pipe.
220
			mypids.extend(spawn(('tee', '-i', '-a', logfile),
221
					returnpid=True, fd_pipes={0:pr,
222
					1:fd_pipes[1], 2:fd_pipes[2]}))
223
224
			# We don't need the read end of the pipe, so close it.
225
			os.close(pr)
226
227
			# Assign the write end of the pipe to our stdout and stderr.
228
			fd_pipes[1] = pw
229
			fd_pipes[2] = pw
214
230
215
	pid = os.fork()
231
	pid = os.fork()
216
232
Lines 232-238 Link Here
232
248
233
	# If we started a tee process the write side of the pipe is no
249
	# If we started a tee process the write side of the pipe is no
234
	# longer needed, so close it.
250
	# longer needed, so close it.
235
	if logfile:
251
	if logfile and pw:
236
		os.close(pw)
252
		os.close(pw)
237
253
238
	# If the caller wants to handle cleaning up the processes, we tell
254
	# If the caller wants to handle cleaning up the processes, we tell
(-)portage-2.1.4.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