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