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_orig/bin/emerge (-373 / +806 lines)
Lines 2740-2745 Link Here
2740
		ignore_priority_soft_range.extend(
2740
		ignore_priority_soft_range.extend(
2741
			xrange(DepPriority.MIN, DepPriority.MEDIUM_SOFT + 1))
2741
			xrange(DepPriority.MIN, DepPriority.MEDIUM_SOFT + 1))
2742
		tree_mode = "--tree" in self.myopts
2742
		tree_mode = "--tree" in self.myopts
2743
        slotcount = 0
2744
2743
		# Tracks whether or not the current iteration should prefer asap_nodes
2745
		# Tracks whether or not the current iteration should prefer asap_nodes
2744
		# if available.  This is set to False when the previous iteration
2746
		# if available.  This is set to False when the previous iteration
2745
		# failed to select any nodes.  It is reset whenever nodes are
2747
		# failed to select any nodes.  It is reset whenever nodes are
Lines 2958-2964 Link Here
2958
2960
2959
			for node in selected_nodes:
2961
			for node in selected_nodes:
2960
				if node[-1] != "nomerge":
2962
				if node[-1] != "nomerge":
2961
					retlist.append(list(node))
2963
                    node2 = list(node)
2964
                    if len(node2) == 4:
2965
                        node2.append(str(slotcount))
2966
                    retlist.append(node2)
2962
				mygraph.remove(node)
2967
				mygraph.remove(node)
2963
				if not reversed and not circular_blocks and myblockers.contains(node):
2968
				if not reversed and not circular_blocks and myblockers.contains(node):
2964
					"""This node may have invalidated one or more blockers."""
2969
					"""This node may have invalidated one or more blockers."""
Lines 2972-2977 Link Here
2972
								self.blocker_parents[blocker] = unresolved
2977
								self.blocker_parents[blocker] = unresolved
2973
							else:
2978
							else:
2974
								del self.blocker_parents[blocker]
2979
								del self.blocker_parents[blocker]
2980
            slotcount += 1
2975
2981
2976
		if not reversed:
2982
		if not reversed:
2977
			"""Blocker validation does not work with reverse mode,
2983
			"""Blocker validation does not work with reverse mode,
Lines 3157-3162 Link Here
3157
				display_list.append((x, 0, True))
3163
				display_list.append((x, 0, True))
3158
				continue
3164
				continue
3159
			graph_key = tuple(x)
3165
			graph_key = tuple(x)
3166
            if len(x) > 4:
3167
                graph_key = tuple(x[:-1])
3168
            else:
3169
                graph_key = tuple(x)
3160
			if "--tree" in self.myopts:
3170
			if "--tree" in self.myopts:
3161
				depth = len(tree_nodes)
3171
				depth = len(tree_nodes)
3162
				while depth and graph_key not in \
3172
				while depth and graph_key not in \
Lines 3223-3229 Link Here
3223
				continue
3233
				continue
3224
			if "blocks" == graph_key[0]:
3234
			if "blocks" == graph_key[0]:
3225
				continue
3235
				continue
3226
			if ordered and graph_key[-1] != "nomerge":
3236
            if len(graph_key) > 4:
3237
                merge_op = graph_key[-2]
3238
            else:
3239
                merge_op = graph_key[-1]
3240
            if ordered and merge_op != "nomerge":
3227
				last_merge_depth = depth
3241
				last_merge_depth = depth
3228
				continue
3242
				continue
3229
			if depth >= last_merge_depth or \
3243
			if depth >= last_merge_depth or \
Lines 3239-3245 Link Here
3239
3253
3240
		for mylist_index in xrange(len(mylist)):
3254
		for mylist_index in xrange(len(mylist)):
3241
			x, depth, ordered = mylist[mylist_index]
3255
			x, depth, ordered = mylist[mylist_index]
3242
			pkg_node = tuple(x)
3243
			pkg_type = x[0]
3256
			pkg_type = x[0]
3244
			myroot = x[1]
3257
			myroot = x[1]
3245
			pkg_key = x[2]
3258
			pkg_key = x[2]
Lines 3248-3253 Link Here
3248
			vardb = self.trees[myroot]["vartree"].dbapi
3261
			vardb = self.trees[myroot]["vartree"].dbapi
3249
			vartree = self.trees[myroot]["vartree"]
3262
			vartree = self.trees[myroot]["vartree"]
3250
			pkgsettings = self.pkgsettings[myroot]
3263
			pkgsettings = self.pkgsettings[myroot]
3264
            if len(x) > 4:
3265
                pkg_node = tuple(x[:-1])
3266
            else:
3267
                pkg_node = tuple(x)
3251
3268
3252
			fetch=" "
3269
			fetch=" "
3253
3270
Lines 3261-3267 Link Here
3261
					addl = addl + " " + red(resolved)
3278
					addl = addl + " " + red(resolved)
3262
				else:
3279
				else:
3263
					addl = "[blocks " + addl + "] " + red(resolved)
3280
					addl = "[blocks " + addl + "] " + red(resolved)
3264
				block_parents = self.blocker_parents[tuple(x)]
3281
				block_parents = self.blocker_parents[pkg_node]
3265
				block_parents = set([pnode[2] for pnode in block_parents])
3282
				block_parents = set([pnode[2] for pnode in block_parents])
3266
				block_parents = ", ".join(block_parents)
3283
				block_parents = ", ".join(block_parents)
3267
				if resolved!=x[2]:
3284
				if resolved!=x[2]:
Lines 3820-3828 Link Here
3820
		fakedb = self.mydbapi
3837
		fakedb = self.mydbapi
3821
		trees = self.trees
3838
		trees = self.trees
3822
		for x in mergelist:
3839
		for x in mergelist:
3823
			if len(x) != 4:
3840
			if len(x) != 5:
3824
				continue
3841
				continue
3825
			pkg_type, myroot, pkg_key, action = x
3842
			pkg_type, myroot, pkg_key, action, slott = x
3826
			if pkg_type not in self.pkg_tree_map:
3843
			if pkg_type not in self.pkg_tree_map:
3827
				continue
3844
				continue
3828
			if action != "merge":
3845
			if action != "merge":
Lines 3976-3984 Link Here
3976
		self.curval = 0
3993
		self.curval = 0
3977
		self._spawned_pids = []
3994
		self._spawned_pids = []
3978
3995
3979
	def merge(self, mylist, favorites, mtimedb):
3996
	def merge(self, mylist, favorites, mtimedb, m_slots):
3980
		try:
3997
		try:
3981
			return self._merge(mylist, favorites, mtimedb)
3998
			return self._merge(mylist, favorites, mtimedb, m_slots)
3982
		finally:
3999
		finally:
3983
			if self._spawned_pids:
4000
			if self._spawned_pids:
3984
				portage.portage_exec.spawned_pids.extend(self._spawned_pids)
4001
				portage.portage_exec.spawned_pids.extend(self._spawned_pids)
Lines 4003-4009 Link Here
4003
				pass
4020
				pass
4004
			spawned_pids.remove(pid)
4021
			spawned_pids.remove(pid)
4005
4022
4006
	def _merge(self, mylist, favorites, mtimedb):
4023
	def _merge(self, mylist, favorites, mtimedb, m_slots):
4007
		failed_fetches = []
4024
		failed_fetches = []
4008
		fetchonly = "--fetchonly" in self.myopts or \
4025
		fetchonly = "--fetchonly" in self.myopts or \
4009
			"--fetch-all-uri" in self.myopts
4026
			"--fetch-all-uri" in self.myopts
Lines 4011-4016 Link Here
4011
		mymergelist=[]
4028
		mymergelist=[]
4012
		ldpath_mtimes = mtimedb["ldpath"]
4029
		ldpath_mtimes = mtimedb["ldpath"]
4013
		xterm_titles = "notitles" not in self.settings.features
4030
		xterm_titles = "notitles" not in self.settings.features
4031
        parallel = "parallel" in self.settings.features
4032
        build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
4033
4034
        # parallel merge will be painful to watch with debug or fetchonly. So, you get only one of these...:-)
4035
        if self.edebug or "--fetchonly" in self.myopts:
4036
            parallel = False
4014
4037
4015
		if "--resume" in self.myopts:
4038
		if "--resume" in self.myopts:
4016
			# We're resuming.
4039
			# We're resuming.
Lines 4042-4048 Link Here
4042
				if not shown_verifying_msg:
4065
				if not shown_verifying_msg:
4043
					shown_verifying_msg = True
4066
					shown_verifying_msg = True
4044
					print ">>> Verifying ebuild Manifests..."
4067
					print ">>> Verifying ebuild Manifests..."
4045
				mytype, myroot, mycpv, mystatus = x
4068
				mytype, myroot, mycpv, mystatus, slott = x
4046
				portdb = self.trees[myroot]["porttree"].dbapi
4069
				portdb = self.trees[myroot]["porttree"].dbapi
4047
				quiet_config = quiet_settings[myroot]
4070
				quiet_config = quiet_settings[myroot]
4048
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
4071
				quiet_config["O"] = os.path.dirname(portdb.findname(mycpv))
Lines 4051-4064 Link Here
4051
				del x, mytype, myroot, mycpv, mystatus, quiet_config
4074
				del x, mytype, myroot, mycpv, mystatus, quiet_config
4052
			del shown_verifying_msg, quiet_settings
4075
			del shown_verifying_msg, quiet_settings
4053
4076
4054
		root_config = RootConfig(self.trees[self.target_root])
4055
		system_set = root_config.sets["system"]
4056
		args_set = AtomSet(favorites)
4057
		world_set = root_config.sets["world"]
4058
		if "--resume" not in self.myopts:
4077
		if "--resume" not in self.myopts:
4059
			mymergelist = mylist
4078
			mymergelist = mylist
4060
			mtimedb["resume"]["mergelist"]=mymergelist[:]
4079
            if "--nodeps" not in self.myopts or len(mymergelist) > 1:
4061
			mtimedb.commit()
4080
			    mtimedb["resume"]["mergelist"]=mymergelist[:]
4081
			    mtimedb.commit()
4082
4083
        totalcount = len(mymergelist)
4084
        mergecount=1
4062
4085
4063
		myfeat = self.settings.features[:]
4086
		myfeat = self.settings.features[:]
4064
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
4087
		bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
Lines 4075-4086 Link Here
4075
			elif len(mymergelist) > 1:
4098
			elif len(mymergelist) > 1:
4076
				fetch_log = "/var/log/emerge-fetch.log"
4099
				fetch_log = "/var/log/emerge-fetch.log"
4077
				logfile = open(fetch_log, "w")
4100
				logfile = open(fetch_log, "w")
4078
				fd_pipes = {1:logfile.fileno(), 2:logfile.fileno()}
4101
                fd_pipes = {0:0, 1:logfile.fileno(), 2:logfile.fileno()}
4079
				portage_util.apply_secpass_permissions(fetch_log,
4102
				portage_util.apply_secpass_permissions(fetch_log,
4080
					uid=portage.portage_uid, gid=portage.portage_gid,
4103
					uid=portage.portage_uid, gid=portage.portage_gid,
4081
					mode=0660)
4104
					mode=0660)
4082
				fetch_env = os.environ.copy()
4105
				fetch_env = os.environ.copy()
4083
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs"
4106
				fetch_env["FEATURES"] = fetch_env.get("FEATURES", "") + " -cvs -parallel"
4084
				fetch_env["PORTAGE_NICENESS"] = "0"
4107
				fetch_env["PORTAGE_NICENESS"] = "0"
4085
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
4108
				fetch_args = [sys.argv[0], "--resume", "--fetchonly"]
4086
				resume_opts = self.myopts.copy()
4109
				resume_opts = self.myopts.copy()
Lines 4107-4453 Link Here
4107
		metadata_keys = [k for k in portage.auxdbkeys \
4130
		metadata_keys = [k for k in portage.auxdbkeys \
4108
			if not k.startswith("UNUSED_")] + ["USE"]
4131
			if not k.startswith("UNUSED_")] + ["USE"]
4109
4132
4110
		mergecount=0
4111
		for x in mymergelist:
4112
			mergecount+=1
4113
			pkg_type = x[0]
4114
			myroot=x[1]
4115
			pkg_key = x[2]
4116
			pkgindex=2
4117
			portdb = self.trees[myroot]["porttree"].dbapi
4118
			bindb  = self.trees[myroot]["bintree"].dbapi
4119
			vartree = self.trees[myroot]["vartree"]
4120
			pkgsettings = self.pkgsettings[myroot]
4121
			metadata = {}
4122
			if pkg_type == "blocks":
4123
				pass
4124
			elif pkg_type == "ebuild":
4125
				mydbapi = portdb
4126
				metadata.update(izip(metadata_keys,
4127
					mydbapi.aux_get(pkg_key, metadata_keys)))
4128
				pkgsettings.setcpv(pkg_key, mydb=mydbapi)
4129
				metadata["USE"] = pkgsettings["USE"]
4130
			else:
4131
				if pkg_type == "binary":
4132
					mydbapi = bindb
4133
				else:
4134
					raise AssertionError("Package type: '%s'" % pkg_type)
4135
				metadata.update(izip(metadata_keys,
4136
					mydbapi.aux_get(pkg_key, metadata_keys)))
4137
			if x[0]=="blocks":
4138
				pkgindex=3
4139
			y = portdb.findname(pkg_key)
4140
			if "--pretend" not in self.myopts:
4141
				print "\n>>> Emerging (" + \
4142
					colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
4143
					colorize("MERGE_LIST_PROGRESS", str(len(mymergelist))) + ") " + \
4144
					colorize("GOOD", x[pkgindex]) + " to " + x[1]
4145
				emergelog(xterm_titles, " >>> emerge ("+\
4146
					str(mergecount)+" of "+str(len(mymergelist))+\
4147
					") "+x[pkgindex]+" to "+x[1])
4148
4133
4149
			pkgsettings["EMERGE_FROM"] = x[0]
4134
        if not parallel:
4150
			pkgsettings.backup_changes("EMERGE_FROM")
4135
            failed_fetches = []
4151
			pkgsettings.reset()
4136
            for x in mymergelist:
4137
                retcode = self.do_one_emerge(x, mergecount, totalcount, mtimedb, favorites, metadata_keys)
4138
                mergecount += 1
4139
                # need to short circuit the spawn with --nodeps
4140
                if os.environ.get("PORTAGE_INTERNAL_CALL", "0") != "1":
4141
                    if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4142
                        continue
4143
                    if retcode != os.EX_OK:
4144
                        if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4145
                            failed_fetches.append(x[2])
4146
                            continue
4147
                        else:
4148
                            return retcode
4149
                    # Unsafe for parallel merges
4150
                    del mtimedb["resume"]["mergelist"][0]
4151
                    # Commit after each merge so that --resume may still work in
4152
                    # in the event that portage is not allowed to exit normally
4153
                    # due to power failure, SIGKILL, etc...
4154
                    mtimedb.commit()
4155
                    self.curval += 1
4156
                    self._poll_child_processes()
4157
4158
                    # unlink the logid_path if any exists
4159
                    logid_path = os.path.join(build_prefix, ".logid.")+x[2].split("/")[0]+"."+x[2].split("/")[1]
4160
                    if os.path.exists(logid_path):
4161
                        os.unlink(logid_path)
4162
                    del logid_path
4163
4164
                    # check if we need to restart portage
4165
                    mysplit=portage.pkgsplit(x[2])
4166
                    if mysplit[0] == "sys-apps/portage" and x[1] == "/":
4167
                        self.restart_portage(x, mergecount, totalcount, mtimedb)
4168
				else:
4169
                    if retcode != os.EX_OK:
4170
                        sys.exit(1)
4171
                    else:
4172
                        sys.exit(0)
4152
4173
4153
			#buildsyspkg: Check if we need to _force_ binary package creation
4174
			if "--pretend" not in self.myopts:
4154
			issyspkg = ("buildsyspkg" in myfeat) \
4175
                emergelog(xterm_titles, " *** Finished. Cleaning up...")
4155
					and x[0] != "blocks" \
4156
					and system_set.findAtomForPackage(pkg_key, metadata) \
4157
					and "--buildpkg" not in self.myopts
4158
			if x[0] in ["ebuild","blocks"]:
4159
				if x[0] == "blocks" and "--fetchonly" not in self.myopts:
4160
					raise Exception, "Merging a blocker"
4161
				elif "--fetchonly" in self.myopts or \
4162
					"--fetch-all-uri" in self.myopts:
4163
					if "--fetch-all-uri" in self.myopts:
4164
						retval = portage.doebuild(y, "fetch", myroot,
4165
							pkgsettings, self.edebug,
4166
							"--pretend" in self.myopts, fetchonly=1,
4167
							fetchall=1, mydbapi=portdb, tree="porttree")
4168
					else:
4169
						retval = portage.doebuild(y, "fetch", myroot,
4170
							pkgsettings, self.edebug,
4171
							"--pretend" in self.myopts, fetchonly=1,
4172
							mydbapi=portdb, tree="porttree")
4173
					if (retval is None) or retval:
4174
						print
4175
						print "!!! Fetch for",y,"failed, continuing..."
4176
						print
4177
						failed_fetches.append(pkg_key)
4178
					self.curval += 1
4179
					continue
4180
4176
4181
				portage.doebuild_environment(y, "setup", myroot,
4177
            # We're out of the loop... We're done. Delete the resume data.
4182
					pkgsettings, self.edebug, 1, portdb)
4178
            if mtimedb.has_key("resume"):
4183
				catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
4179
                del mtimedb["resume"]
4184
				portage_util.ensure_dirs(os.path.dirname(catdir),
4180
            mtimedb.commit()
4181
4182
            #by doing an exit this way, --fetchonly can continue to try to
4183
            #fetch everything even if a particular download fails.
4184
            if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4185
                if failed_fetches:
4186
                    sys.stderr.write("\n\n!!! Some fetch errors were " + \
4187
                            "encountered.  Please see above for details.\n\n")
4188
                    for cpv in failed_fetches:
4189
                        sys.stderr.write("   ")
4190
                        sys.stderr.write(cpv)
4191
                        sys.stderr.write("\n")
4192
                    sys.stderr.write("\n")
4193
                    sys.exit(1)
4194
                else:
4195
                    sys.exit(0)
4196
            return os.EX_OK
4197
4198
        # parallel code - dirty starts here...;-)
4199
        one_in_slot_failed=0
4200
        spawnd_pids=[]
4201
4202
        # dirty little trick to get number of cpus from the system
4203
        fd_cpuinfo = os.popen("cat /proc/cpuinfo","r")
4204
        cpu_count = 0
4205
        for data_cpuinfo in fd_cpuinfo.readlines():
4206
            if data_cpuinfo.find("cpu MHz") > -1 :
4207
                cpu_count += 1
4208
        fd_cpuinfo.close()
4209
4210
        # if someone really screwed with /proc/cpuinfo output, we should not suffer
4211
        if cpu_count == 0:
4212
            cpu_count = 1
4213
4214
        spawnd_pkg = {}
4215
        donec = 0
4216
        failedc = 0
4217
        failedPkgs = []
4218
        logid_path = None
4219
        mylist = m_slots.keys()
4220
        mylist.sort()
4221
        for x in mylist:
4222
            # if slot is empty, go on
4223
            if not m_slots[x]:
4224
                continue
4225
4226
            # if previous slot failed, discontinue the emerge
4227
            if one_in_slot_failed and not ("--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts):
4228
                break
4229
4230
            # start multiple merges in parallel mode
4231
            num_at_atime = cpu_count + 1
4232
4233
            qsize = 0
4234
            for y in m_slots[x]:
4235
                # these all can go in parallel, so fork one after the other
4236
                # but num_at_atime at most
4237
                if num_at_atime:
4238
                    onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, metadata_keys)
4239
                    spawnd_pids.append(onepid)
4240
                    spawnd_pkg[onepid] = (y, x)
4241
                    num_at_atime -= 1
4242
                    mergecount += 1
4243
                    qsize += 1
4244
                else:
4245
                    self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
4246
                    # let's wait for one of the jobs to finish
4247
                    (retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
4248
4249
                    # if it failed, I need to fail next slot but continue to merge all in this slot
4250
                    if retval:
4251
                        one_in_slot_failed = retval
4252
                        failedc += 1
4253
                        failedPkgs.append(pkg_compl[2])
4254
                    else:
4255
                        donec += 1
4256
                        self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, metadata_keys)
4257
                    onepid = self.fork_one_emerge(y, mergecount, totalcount, mtimedb, favorites, metadata_keys)
4258
                    spawnd_pids.append(onepid)
4259
                    spawnd_pkg[onepid] = (y, x)
4260
                    mergecount += 1
4261
4262
            # this slot is exhausted, so wait for all of the forks to finish
4263
            while spawnd_pids:
4264
                self.print_status(totalcount, donec, qsize, failedc, spawnd_pkg, failedPkgs)
4265
                # let's wait for one of the jobs to finish
4266
                (retval, pkg_compl) = self.wait_one_emerge(spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb)
4267
4268
                qsize -= 1
4269
                if retval:
4270
                    one_in_slot_failed = retval
4271
                    failedc += 1
4272
                    failedPkgs.append(pkg_compl[2])
4273
                else:
4274
                    donec += 1
4275
                    self.add_one_emerge_to_world(pkg_compl, mergecount, totalcount, favorites, metadata_keys)
4276
        if totalcount:
4277
            self.print_status(totalcount, donec, qsize, failedc, None, failedPkgs)
4278
   
4279
        if one_in_slot_failed:
4280
            portage.writemsg_stdout(red("\nSome packages failed to emerge, summary follows:\n"))
4281
   
4282
        for pkgs in failedPkgs:
4283
            if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4284
                print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
4285
                sys.exit(1)
4286
4287
            portage.writemsg_stdout(red("\nPackage "+pkgs+" failed to emerge\n"))
4288
            logfile = None
4289
            if "PORT_LOGDIR" in self.settings:
4290
                port_logdir = self.settings["PORT_LOGDIR"]
4291
            else:
4292
                port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
4293
4294
            pkg_cat = pkgs.split("/")[0]
4295
            pkg_pf = pkgs.split("/")[1]
4296
            logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
4297
            if os.path.exists(logid_path):
4298
                logid_time = time.strftime("%Y%m%d-%H%M%S", 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
4303
            if logfile and os.path.exists(logfile):
4304
                portage.portage_exec.spawn(('tail', '-n', '20', logfile), returnpid=False)
4305
4306
            if logfile and os.path.exists(logfile):
4307
                portage.writemsg_stdout(red("Please take a look at the file "+logfile+"\n"))
4308
                os.unlink(logid_path)
4309
        if one_in_slot_failed:
4310
            sys.exit(1)
4311
        if "--pretend" not in self.myopts:
4312
            emergelog(xterm_titles, " *** Finished. Cleaning up...")
4313
4314
        # see if there are any extraneous files in build_prefix, which we might have leftover
4315
        import glob
4316
        for fnames in glob.glob(os.path.join(build_prefix, ".logid.")+"*"):
4317
            os.unlink(fnames)
4318
4319
        # We're out of the loop... We're done. Delete the resume data.
4320
        if mtimedb.has_key("resume"):
4321
            del mtimedb["resume"]
4322
        mtimedb.commit()
4323
4324
        if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4325
            sys.exit(0)
4326
4327
        return os.EX_OK
4328
4329
    def print_status(self, totalcount, donec, qsize, failedc, spawnd_pkg, failed):
4330
        smsg = ""
4331
        fmsg = ""
4332
        if spawnd_pkg:
4333
            for pkgs in spawnd_pkg.values():
4334
                smsg = smsg+" "+pkgs[0][2]
4335
        if failed:
4336
            for pkgs in failed:
4337
                fmsg = fmsg+" "+pkgs
4338
        print ">>> Jobs [Total = "+colorize("blue", str(totalcount))+"] [Done = "+\
4339
            colorize("GOOD", str(donec))+"] [Running = "+colorize("WARN", str(qsize)+smsg)+\
4340
            "] [Failed = "+colorize("BAD", str(failedc)+fmsg)+"]"
4341
        xtermTitle("Jobs [Total="+str(totalcount)+"] [Done="+str(donec)+"] [Running="+str(qsize)+"] [Failed="+str(failedc)+"]")
4342
4343
    def wait_one_emerge(self, spawnd_pids, spawnd_pkg, mergecount, totalcount, mymergelist, mtimedb):
4344
        build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
4345
        # let's wait for one of the jobs to finish
4346
        onepid = -1
4347
        while onepid not in spawnd_pids:
4348
            onepid , retval = os.waitpid(-1, 0)
4349
        spawnd_pids.remove(onepid)
4350
4351
        pkg_compl = spawnd_pkg[onepid][0]
4352
        pkg_slot = spawnd_pkg[onepid][1]
4353
        del spawnd_pkg[onepid]
4354
4355
        if not retval:
4356
            # unlink the logid_path
4357
            logid_path = os.path.join(build_prefix, ".logid.")+pkg_compl[2].split("/")[0]+"."+pkg_compl[2].split("/")[1]
4358
            if os.path.exists(logid_path):
4359
                os.unlink(logid_path)
4360
            index = 0
4361
            print ">>> Package "+colorize("GOOD", pkg_compl[2])+" finished emerging."
4362
            # we need to remove this pkg from resume DB
4363
            # this is the dirtiest shit I have ever written
4364
            for pkgs in mymergelist:
4365
                if pkgs[2] == pkg_compl[2]:
4366
                    if len(mymergelist) > 1:
4367
                        del mtimedb["resume"]["mergelist"][index]
4368
                        mtimedb.commit()
4369
                    self.curval += 1
4370
                    self._poll_child_processes()
4371
                    del mymergelist[index]
4372
                    # check if we need to restart portage
4373
                    mysplit=portage.pkgsplit(pkg_compl[2])
4374
                    if mysplit[0] == "sys-apps/portage" and pkgs[1] == "/":
4375
                        self.restart_portage(pkgs, mergecount, totalcount, mtimedb)
4376
                    break
4377
                index += 1
4378
        return (retval, pkg_compl)
4379
4380
    def fork_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, metadata_keys):
4381
        xterm_titles = "notitles" not in self.settings.features
4382
        myfeat = self.settings.features[:]
4383
        ldpath_mtimes = mtimedb["ldpath"]
4384
        myroot=x[1]
4385
        pkg_key = x[2]
4386
        pkg_cat = x[2].split("/")[0]
4387
        pkg_pf = x[2].split("/")[1]
4388
        pkgindex=2
4389
        if x[0]=="blocks":
4390
            pkgindex=3
4391
4392
        build_prefix=self.settings["PORTAGE_TMPDIR"]+"/portage"
4393
        portage_util.ensure_dirs(build_prefix, uid=portage.portage_uid, gid=portage.portage_gid, mode=0775)
4394
4395
        logid_path = None
4396
        null_log = 0
4397
4398
        if self.settings.get("PORT_LOGDIR", "") == "":
4399
            while "PORT_LOGDIR" in self.settings:
4400
                del self.settings["PORT_LOGDIR"]
4401
        if "PORT_LOGDIR" in self.settings:
4402
            port_logdir = self.settings["PORT_LOGDIR"]
4403
        else:
4404
            port_logdir = self.settings["ROOT"] + portage.DEF_LOGDIR
4405
4406
        try:
4407
            portage_util.ensure_dirs(port_logdir, uid=portage.portage_uid,
4408
                         gid=portage.portage_gid, mode=02770)
4409
        except portage_exception.PortageException, e:
4410
            writemsg("!!! %s\n" % str(e), noiselevel=-1)
4411
            writemsg("!!! Permission issues with PORT_LOGDIR='%s'\n" % \
4412
                self.settings["PORT_LOGDIR"], noiselevel=-1)
4413
            writemsg("!!! Because 'parallel' feature is enabled, you won't get any logs.\n", noiselevel=-1)
4414
            null_log = 1
4415
4416
        if not null_log:
4417
            logid_path = os.path.join(build_prefix, ".logid.")+pkg_cat+"."+pkg_pf
4418
            if not os.path.exists(logid_path):
4419
                f = open(logid_path, "w")
4420
                f.close()
4421
                del f
4422
            logid_time = time.strftime("%Y%m%d-%H%M%S",
4423
                time.gmtime(os.stat(logid_path).st_mtime))
4424
            logfile = os.path.join(port_logdir, "%s:%s:%s.log" % \
4425
                (pkg_cat, pkg_pf, logid_time))
4426
            del logid_time
4427
        else:
4428
            logfile = "/dev/null"
4429
4430
        if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
4431
            print ">>> Emerging (" + \
4432
                colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
4433
                colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
4434
                colorize("GOOD", x[pkgindex]) + " to " + x[1]
4435
            print ">>> Logfile in " + logfile
4436
            emergelog(xterm_titles, " >>> emerge ("+\
4437
                str(mergecount)+" of "+str(totalcount)+\
4438
                ") "+x[pkgindex]+" to "+x[1])
4439
4440
        # need to spawn a --nodeps emerge in a separate process.
4441
        pkg="="+x[2]
4442
        merge_env = os.environ.copy()
4443
        merge_env["PORTAGE_INTERNAL_CALL"] = "1"
4444
        merge_env["FEATURES"] = merge_env.get("FEATURES", "") + " notitles -parallel"
4445
        merge_args = [sys.argv[0], "--nodeps", "--oneshot", "--nospinner", pkg]
4446
        good_nodeps_opts = set(["--buildpkg", "--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--getbinpkg",\
4447
                    "--usepkg", "--usepkgonly"])
4448
        fd_pipes = None
4449
        merge_logfd = None
4450
        for myopt, myarg in self.myopts.iteritems():
4451
            # don't clobber the logfile at the same time as parallel fetch is
4452
            # all log of parallel fetch will go /var/log/emerge-fetch.log
4453
            # so, just leave 0,1,2 alone.
4454
            if "parallel-fetch" in myfeat and myopt == "--fetchonly":
4455
                fd_pipes = {0:0, 1:1, 2:2}
4456
            if myopt in good_nodeps_opts:
4457
                if myarg is True:
4458
                    merge_args.append(myopt)
4459
                else:
4460
                    merge_args.append(myopt +"="+ myarg)
4461
        if not fd_pipes:
4462
            merge_logfd = open(logfile, "w")
4463
            # put in a start message. This also makes sure that this fd is pointing to a good file on disk
4464
            # and hence will be used throughout the other spawns that will happen in the children.
4465
            merge_logfd.write("Package "+x[pkgindex]+" started at "+time.ctime()+"\n\n")
4466
            merge_logfd.flush()
4467
            fd_pipes = {0:0, 1:merge_logfd.fileno(), 2:merge_logfd.fileno()}
4468
            portage_util.apply_secpass_permissions(logfile, uid=portage.portage_uid, gid=portage.portage_gid, mode=0660)
4469
4470
        mypids = portage.portage_exec.spawn(merge_args, env=merge_env, fd_pipes=fd_pipes, returnpid=True)
4471
        if merge_logfd:
4472
            merge_logfd.close() # child has exclusive rights to it now.
4473
        return mypids[0]
4474
4475
    def restart_portage(self, x, mergecount, totalcount, mtimedb):
4476
        xterm_titles = "notitles" not in self.settings.features
4477
        # don't really restart if any of these is true
4478
        # XXXXX - seems like redundant check, but what the hell! sky is not falling as yet.
4479
        if "--pretend" in self.myopts or "--fetchonly" in self.myopts or \
4480
            "--fetch-all-uri" in self.myopts or "--buildpkgonly" in self.myopts:
4481
            return
4482
4483
        bad_resume_opts = set(["--ask", "--tree", "--changelog", "--skipfirst",
4484
            "--resume"])
4485
        mysplit=portage.pkgsplit(x[2])
4486
        if "livecvsportage" not in self.settings.features:
4487
            if totalcount > mergecount:
4488
                emergelog(xterm_titles,
4489
                    " ::: completed emerge ("+ \
4490
                    str(mergecount)+" of "+ \
4491
                    str(totalcount)+") "+ \
4492
                    x[2]+" to "+x[1])
4493
                emergelog(xterm_titles, " *** RESTARTING " + \
4494
                    "emerge via exec() after change of " + \
4495
                    "portage version.")
4496
                portage.run_exitfuncs()
4497
                mynewargv=[sys.argv[0],"--resume"]
4498
                resume_opts = self.myopts.copy()
4499
                # For automatic resume, we need to prevent
4500
                # any of bad_resume_opts from leaking in
4501
                # via EMERGE_DEFAULT_OPTS.
4502
                resume_opts["--ignore-default-opts"] = True
4503
                for myopt, myarg in resume_opts.iteritems():
4504
                    if myopt not in bad_resume_opts:
4505
                        if myarg is True:
4506
                            mynewargv.append(myopt)
4507
                        else:
4508
                            mynewargv.append(myopt +"="+ myarg)
4509
                # priority only needs to be adjusted on the first run
4510
                os.environ["PORTAGE_NICENESS"] = "0"
4511
                os.execv(mynewargv[0], mynewargv)
4512
4513
4514
    def do_one_emerge(self, x, mergecount, totalcount, mtimedb, favorites, metadata_keys):
4515
        xterm_titles = "notitles" not in self.settings.features
4516
        myfeat = self.settings.features[:]
4517
        ldpath_mtimes = mtimedb["ldpath"]
4518
        pkg_type = x[0]
4519
        myroot=x[1]
4520
        pkg_key = x[2]
4521
        pkg_cat = x[2].split("/")[0]
4522
        pkg_pf = x[2].split("/")[1]
4523
        pkgindex=2
4524
        if x[0]=="blocks":
4525
            pkgindex=3
4526
4527
        if "--pretend" not in self.myopts and "--fetchonly" not in self.myopts:
4528
            print "\n>>> Emerging (" + \
4529
                colorize("MERGE_LIST_PROGRESS", str(mergecount)) + " of " + \
4530
                colorize("MERGE_LIST_PROGRESS", str(totalcount)) + ") " + \
4531
                colorize("GOOD", x[pkgindex]) + " to " + x[1]
4532
            emergelog(xterm_titles, " >>> emerge ("+\
4533
                str(mergecount)+" of "+str(totalcount)+\
4534
                ") "+x[pkgindex]+" to "+x[1])
4535
4536
        portdb = self.trees[myroot]["porttree"].dbapi
4537
        bindb  = self.trees[myroot]["bintree"].dbapi
4538
        vartree = self.trees[myroot]["vartree"]
4539
        pkgsettings = self.pkgsettings[myroot]
4540
        metadata = {}
4541
        if pkg_type == "blocks":
4542
            pass
4543
        elif pkg_type == "ebuild":
4544
            mydbapi = portdb
4545
            metadata.update(izip(metadata_keys,
4546
                mydbapi.aux_get(pkg_key, metadata_keys)))
4547
            pkgsettings.setcpv(pkg_key, mydb=mydbapi)
4548
            metadata["USE"] = pkgsettings["USE"]
4549
        else:
4550
            if pkg_type == "binary":
4551
                mydbapi = bindb
4552
            else:
4553
                raise AssertionError("Package type: '%s'" % pkg_type)
4554
            metadata.update(izip(metadata_keys,
4555
                mydbapi.aux_get(pkg_key, metadata_keys)))
4556
        y = portdb.findname(pkg_key)
4557
        pkgsettings["EMERGE_FROM"] = x[0]
4558
        pkgsettings.backup_changes("EMERGE_FROM")
4559
        pkgsettings.reset()
4560
4561
        #buildsyspkg: Check if we need to _force_ binary package creation
4562
        issyspkg = ("buildsyspkg" in myfeat) \
4563
                and x[0] != "blocks" \
4564
                and system_set.findAtomForPackage(pkg_key, metadata) \
4565
                and "--buildpkg" not in self.myopts
4566
        if x[0] in ["ebuild","blocks"]:
4567
            if x[0] == "blocks" and "--fetchonly" not in self.myopts:
4568
                raise Exception, "Merging a blocker"
4569
            elif "--fetchonly" in self.myopts or \
4570
                "--fetch-all-uri" in self.myopts:
4571
                if "--fetch-all-uri" in self.myopts:
4572
                    retval = portage.doebuild(y, "fetch", myroot,
4573
                        pkgsettings, self.edebug,
4574
                        "--pretend" in self.myopts, fetchonly=1,
4575
                        fetchall=1, mydbapi=portdb, tree="porttree")
4576
                else:
4577
                    retval = portage.doebuild(y, "fetch", myroot,
4578
                        pkgsettings, self.edebug,
4579
                        "--pretend" in self.myopts, fetchonly=1,
4580
                        mydbapi=portdb, tree="porttree")
4581
                if (retval is None) or retval:
4582
                    print
4583
                    print "!!! Fetch for",y,"failed, continuing..."
4584
                    print
4585
4586
                self.curval += 1
4587
                return retval
4588
4589
            portage.doebuild_environment(y, "setup", myroot,
4590
                pkgsettings, self.edebug, 1, portdb)
4591
            catdir = os.path.dirname(pkgsettings["PORTAGE_BUILDDIR"])
4592
            portage_util.ensure_dirs(os.path.dirname(catdir),
4593
                uid=portage.portage_uid, gid=portage.portage_gid,
4594
                mode=070, mask=0)
4595
            builddir_lock = None
4596
            catdir_lock = None
4597
            try:
4598
                catdir_lock = portage_locks.lockdir(catdir)
4599
                portage_util.ensure_dirs(catdir,
4185
					uid=portage.portage_uid, gid=portage.portage_gid,
4600
					uid=portage.portage_uid, gid=portage.portage_gid,
4186
					mode=070, mask=0)
4601
					mode=070, mask=0)
4187
				builddir_lock = None
4602
                builddir_lock = portage_locks.lockdir(
4188
				catdir_lock = None
4603
                    pkgsettings["PORTAGE_BUILDDIR"])
4189
				try:
4604
				try:
4190
					catdir_lock = portage_locks.lockdir(catdir)
4605
                    portage_locks.unlockdir(catdir_lock)
4191
					portage_util.ensure_dirs(catdir,
4606
                finally:
4192
						uid=portage.portage_uid, gid=portage.portage_gid,
4607
                    catdir_lock = None
4193
						mode=070, mask=0)
4608
                msg = " === (%s of %s) Cleaning (%s::%s)" % \
4194
					builddir_lock = portage_locks.lockdir(
4609
                    (mergecount, totalcount, pkg_key, y)
4195
						pkgsettings["PORTAGE_BUILDDIR"])
4610
                short_msg = "emerge: (%s of %s) %s Clean" % \
4196
					try:
4611
                    (mergecount, totalcount, pkg_key)
4197
						portage_locks.unlockdir(catdir_lock)
4612
                emergelog(xterm_titles, msg, short_msg=short_msg)
4198
					finally:
4613
                retval = portage.doebuild(y, "clean", myroot,
4199
						catdir_lock = None
4614
                    pkgsettings, self.edebug, cleanup=1,
4200
					msg = " === (%s of %s) Cleaning (%s::%s)" % \
4615
                    mydbapi=portdb, tree="porttree")
4201
						(mergecount, len(mymergelist), pkg_key, y)
4616
4202
					short_msg = "emerge: (%s of %s) %s Clean" % \
4617
                if retval != os.EX_OK:
4203
						(mergecount, len(mymergelist), pkg_key)
4618
                    return retval
4619
                if "--buildpkg" in self.myopts or issyspkg:
4620
                    if issyspkg:
4621
                        print ">>> This is a system package, " + \
4622
                            "let's pack a rescue tarball."
4623
                    msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
4624
                        (mergecount, totalcount, pkg_key, y)
4625
                    short_msg = "emerge: (%s of %s) %s Compile" % \
4626
                        (mergecount, totalcount, pkg_key)
4204
					emergelog(xterm_titles, msg, short_msg=short_msg)
4627
					emergelog(xterm_titles, msg, short_msg=short_msg)
4205
					retval = portage.doebuild(y, "clean", myroot,
4628
                    self.trees[myroot]["bintree"].prevent_collision(pkg_key)
4206
						pkgsettings, self.edebug, cleanup=1,
4629
                    retval = portage.doebuild(y, "package", myroot,
4207
						mydbapi=portdb, tree="porttree")
4630
                        pkgsettings, self.edebug, mydbapi=portdb,
4631
                        tree="porttree")
4632
                    if retval != os.EX_OK or \
4633
                        "--buildpkgonly" in self.myopts:
4634
                        portage.elog_process(pkg_key, pkgsettings)
4208
					if retval != os.EX_OK:
4635
					if retval != os.EX_OK:
4209
						return retval
4636
						return retval
4210
					if "--buildpkg" in self.myopts or issyspkg:
4637
                    bintree = self.trees[myroot]["bintree"]
4211
						if issyspkg:
4638
                    if bintree.populated:
4212
							print ">>> This is a system package, " + \
4639
                        bintree.inject(pkg_key)
4213
								"let's pack a rescue tarball."
4640
                    if "--buildpkgonly" not in self.myopts:
4214
						msg = " === (%s of %s) Compiling/Packaging (%s::%s)" % \
4641
                        msg = " === (%s of %s) Merging (%s::%s)" % \
4215
							(mergecount, len(mymergelist), pkg_key, y)
4642
                            (mergecount, totalcount, pkg_key, y)
4216
						short_msg = "emerge: (%s of %s) %s Compile" % \
4643
                        short_msg = "emerge: (%s of %s) %s Merge" % \
4217
							(mergecount, len(mymergelist), pkg_key)
4644
                            (mergecount, totalcount, pkg_key)
4218
						emergelog(xterm_titles, msg, short_msg=short_msg)
4645
						emergelog(xterm_titles, msg, short_msg=short_msg)
4219
						self.trees[myroot]["bintree"].prevent_collision(pkg_key)
4646
                        retval = portage.merge(pkgsettings["CATEGORY"],
4220
						retval = portage.doebuild(y, "package", myroot,
4647
                            pkgsettings["PF"], pkgsettings["D"],
4221
							pkgsettings, self.edebug, mydbapi=portdb,
4648
                            os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
4222
							tree="porttree")
4649
                            "build-info"), myroot, pkgsettings,
4223
						if retval != os.EX_OK or \
4650
                            myebuild=pkgsettings["EBUILD"],
4224
							"--buildpkgonly" in self.myopts:
4651
                            mytree="porttree", mydbapi=portdb,
4225
							portage.elog_process(pkg_key, pkgsettings)
4652
                            vartree=vartree, prev_mtimes=ldpath_mtimes)
4226
						if retval != os.EX_OK:
4227
							return retval
4228
						bintree = self.trees[myroot]["bintree"]
4229
						if bintree.populated:
4230
							bintree.inject(pkg_key)
4231
						if "--buildpkgonly" not in self.myopts:
4232
							msg = " === (%s of %s) Merging (%s::%s)" % \
4233
								(mergecount, len(mymergelist), pkg_key, y)
4234
							short_msg = "emerge: (%s of %s) %s Merge" % \
4235
								(mergecount, len(mymergelist), pkg_key)
4236
							emergelog(xterm_titles, msg, short_msg=short_msg)
4237
							retval = portage.merge(pkgsettings["CATEGORY"],
4238
								pkgsettings["PF"], pkgsettings["D"],
4239
								os.path.join(pkgsettings["PORTAGE_BUILDDIR"],
4240
								"build-info"), myroot, pkgsettings,
4241
								myebuild=pkgsettings["EBUILD"],
4242
								mytree="porttree", mydbapi=portdb,
4243
								vartree=vartree, prev_mtimes=ldpath_mtimes)
4244
							if retval != os.EX_OK:
4245
								return retval
4246
						elif "noclean" not in pkgsettings.features:
4247
							portage.doebuild(y, "clean", myroot,
4248
								pkgsettings, self.edebug, mydbapi=portdb,
4249
								tree="porttree")
4250
					else:
4251
						msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
4252
							(mergecount, len(mymergelist), pkg_key, y)
4253
						short_msg = "emerge: (%s of %s) %s Compile" % \
4254
							(mergecount, len(mymergelist), pkg_key)
4255
						emergelog(xterm_titles, msg, short_msg=short_msg)
4256
						retval = portage.doebuild(y, "merge", myroot,
4257
							pkgsettings, self.edebug, vartree=vartree,
4258
							mydbapi=portdb, tree="porttree",
4259
							prev_mtimes=ldpath_mtimes)
4260
						if retval != os.EX_OK:
4653
						if retval != os.EX_OK:
4261
							return retval
4654
							return retval
4655
                    elif "noclean" not in pkgsettings.features:
4656
                        portage.doebuild(y, "clean", myroot,
4657
                            pkgsettings, self.edebug, mydbapi=portdb,
4658
                            tree="porttree")
4659
                else:
4660
                    msg = " === (%s of %s) Compiling/Merging (%s::%s)" % \
4661
                        (mergecount, totalcount, pkg_key, y)
4662
                    short_msg = "emerge: (%s of %s) %s Compile" % \
4663
                        (mergecount, totalcount, pkg_key)
4664
                    emergelog(xterm_titles, msg, short_msg=short_msg)
4665
                    retval = portage.doebuild(y, "merge", myroot,
4666
                        pkgsettings, self.edebug, vartree=vartree,
4667
                        mydbapi=portdb, tree="porttree",
4668
                        prev_mtimes=ldpath_mtimes)
4669
                    if retval != os.EX_OK:
4670
                        return retval
4671
            finally:
4672
                if builddir_lock:
4673
                    portage_locks.unlockdir(builddir_lock)
4674
                try:
4675
                    if not catdir_lock:
4676
                        # Lock catdir for removal if empty.
4677
                        catdir_lock = portage_locks.lockdir(catdir)
4262
				finally:
4678
				finally:
4263
					if builddir_lock:
4679
                    if catdir_lock:
4264
						portage_locks.unlockdir(builddir_lock)
4680
                        try:
4265
					try:
4681
                            os.rmdir(catdir)
4266
						if not catdir_lock:
4682
                        except OSError, e:
4267
							# Lock catdir for removal if empty.
4683
                            if e.errno not in (errno.ENOENT,
4268
							catdir_lock = portage_locks.lockdir(catdir)
4684
                                errno.ENOTEMPTY, errno.EEXIST):
4269
					finally:
4685
                                raise
4270
						if catdir_lock:
4686
                            del e
4271
							try:
4687
                        portage_locks.unlockdir(catdir_lock)
4272
								os.rmdir(catdir)
4688
4273
							except OSError, e:
4689
        elif x[0]=="binary":
4274
								if e.errno not in (errno.ENOENT,
4690
            #merge the tbz2
4275
									errno.ENOTEMPTY, errno.EEXIST):
4691
            mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
4276
									raise
4692
            if "--getbinpkg" in self.myopts:
4277
								del e
4693
                tbz2_lock = None
4278
							portage_locks.unlockdir(catdir_lock)
4694
                try:
4279
4695
                    if "distlocks" in pkgsettings.features and \
4280
			elif x[0]=="binary":
4696
                        os.access(pkgsettings["PKGDIR"], os.W_OK):
4281
				#merge the tbz2
4697
                        portage_util.ensure_dirs(os.path.dirname(mytbz2))
4282
				mytbz2 = self.trees[myroot]["bintree"].getname(pkg_key)
4698
                        tbz2_lock = portage_locks.lockfile(mytbz2,
4283
				if "--getbinpkg" in self.myopts:
4699
                            wantnewlockfile=1)
4284
					tbz2_lock = None
4700
                    if self.trees[myroot]["bintree"].isremote(pkg_key):
4285
					try:
4701
                        msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
4286
						if "distlocks" in pkgsettings.features and \
4702
                            (mergecount, totalcount, pkg_key, mytbz2)
4287
							os.access(pkgsettings["PKGDIR"], os.W_OK):
4703
                        short_msg = "emerge: (%s of %s) %s Fetch" % \
4288
							portage_util.ensure_dirs(os.path.dirname(mytbz2))
4704
                            (mergecount, totalcount, pkg_key)
4289
							tbz2_lock = portage_locks.lockfile(mytbz2,
4705
                        emergelog(xterm_titles, msg, short_msg=short_msg)
4290
								wantnewlockfile=1)
4706
                        try:
4291
						if self.trees[myroot]["bintree"].isremote(pkg_key):
4707
                            self.trees[myroot]["bintree"].gettbz2(pkg_key)
4292
							msg = " --- (%s of %s) Fetching Binary (%s::%s)" %\
4708
                        except portage_exception.FileNotFound:
4293
								(mergecount, len(mymergelist), pkg_key, mytbz2)
4709
                            writemsg("!!! Fetching Binary failed " + \
4294
							short_msg = "emerge: (%s of %s) %s Fetch" % \
4710
                                "for '%s'\n" % pkg_key, noiselevel=-1)
4295
								(mergecount, len(mymergelist), pkg_key)
4711
                            if not fetchonly:
4296
							emergelog(xterm_titles, msg, short_msg=short_msg)
4712
                                return 1
4297
							try:
4713
                        except portage_exception.DigestException, e:
4298
								self.trees[myroot]["bintree"].gettbz2(pkg_key)
4714
                            writemsg("\n!!! Digest verification failed:\n",
4299
							except portage_exception.FileNotFound:
4715
                                noiselevel=-1)
4300
								writemsg("!!! Fetching Binary failed " + \
4716
                            writemsg("!!! %s\n" % e.value[0],
4301
									"for '%s'\n" % pkg_key, noiselevel=-1)
4717
                                noiselevel=-1)
4302
								if not fetchonly:
4718
                            writemsg("!!! Reason: %s\n" % e.value[1],
4303
									return 1
4719
                                noiselevel=-1)
4304
								failed_fetches.append(pkg_key)
4720
                            writemsg("!!! Got: %s\n" % e.value[2],
4305
							except portage_exception.DigestException, e:
4721
                                noiselevel=-1)
4306
								writemsg("\n!!! Digest verification failed:\n",
4722
                            writemsg("!!! Expected: %s\n" % e.value[3],
4307
									noiselevel=-1)
4723
                                noiselevel=-1)
4308
								writemsg("!!! %s\n" % e.value[0],
4724
                            os.unlink(mytbz2)
4309
									noiselevel=-1)
4725
                            if not fetchonly:
4310
								writemsg("!!! Reason: %s\n" % e.value[1],
4726
                                return 1
4311
									noiselevel=-1)
4727
                finally:
4312
								writemsg("!!! Got: %s\n" % e.value[2],
4728
                    if tbz2_lock:
4313
									noiselevel=-1)
4729
                        portage_locks.unlockfile(tbz2_lock)
4314
								writemsg("!!! Expected: %s\n" % e.value[3],
4730
4315
									noiselevel=-1)
4731
            if "--fetchonly" in self.myopts or \
4316
								os.unlink(mytbz2)
4732
                "--fetch-all-uri" in self.myopts:
4317
								if not fetchonly:
4733
                self.curval += 1
4318
									return 1
4734
                return os.EX_OK
4319
								failed_fetches.append(pkg_key)
4735
4320
					finally:
4736
            short_msg = "emerge: ("+str(mergecount)+" of "+str(totalcount)+") "+x[pkgindex]+" Merge Binary"
4321
						if tbz2_lock:
4737
            emergelog(xterm_titles, " === ("+str(mergecount)+\
4322
							portage_locks.unlockfile(tbz2_lock)
4738
                " of "+str(totalcount)+") Merging Binary ("+\
4323
4739
                x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
4324
				if "--fetchonly" in self.myopts or \
4740
4325
					"--fetch-all-uri" in self.myopts:
4741
            retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
4326
					self.curval += 1
4742
                mydbapi=bindb,
4327
					continue
4743
                vartree=self.trees[myroot]["vartree"],
4328
4744
                prev_mtimes=ldpath_mtimes)
4329
				short_msg = "emerge: ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" Merge Binary"
4745
            if retval != os.EX_OK:
4330
				emergelog(xterm_titles, " === ("+str(mergecount)+\
4746
                return retval
4331
					" of "+str(len(mymergelist))+") Merging Binary ("+\
4747
            #need to check for errors
4332
					x[pkgindex]+"::"+mytbz2+")", short_msg=short_msg)
4748
4333
				retval = portage.pkgmerge(mytbz2, x[1], pkgsettings,
4749
        # clean up the older version which emerged on top of
4334
					mydbapi=bindb,
4750
        if "--buildpkgonly" not in self.myopts and \
4335
					vartree=self.trees[myroot]["vartree"],
4751
            "--pretend" not in self.myopts and \
4336
					prev_mtimes=ldpath_mtimes)
4752
            "--fetchonly" not in self.myopts and \
4337
				if retval != os.EX_OK:
4753
            "--fetch-all-uri" not in self.myopts:
4338
					return retval
4754
            # Clean the old package that we have merged over top of it.
4339
				#need to check for errors
4755
            if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
4340
			if "--buildpkgonly" not in self.myopts:
4756
                xsplit=portage.pkgsplit(x[2])
4341
				self.trees[x[1]]["vartree"].inject(x[2])
4757
                emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
4342
				myfavkey = portage.cpv_getkey(x[2])
4758
                retval = unmerge(pkgsettings, self.myopts, vartree,
4343
				if not fetchonly and not pretend and \
4759
                    "clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
4344
					args_set.findAtomForPackage(pkg_key, metadata):
4760
                if not retval:
4345
					world_set.lock()
4761
                    emergelog(xterm_titles,
4346
					world_set.load()
4762
                        " --- AUTOCLEAN: Nothing unmerged.")
4347
					myfavkey = create_world_atom(pkg_key, metadata,
4763
            else:
4348
						args_set, root_config)
4764
                portage.writemsg_stdout(colorize("WARN", "WARNING:")
4349
					if myfavkey:
4765
                    + " AUTOCLEAN is disabled.  This can cause serious"
4350
						world_set.add(myfavkey)
4766
                    + " problems due to overlapping packages.\n")
4351
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
4767
4352
						emergelog(xterm_titles, " === ("+\
4768
-       if "--pretend" not in self.myopts:
4353
							str(mergecount)+" of "+\
4769
-           emergelog(xterm_titles, " *** Finished. Cleaning up...")
4354
							str(len(mymergelist))+\
4770
        if "--pretend" not in self.myopts and \
4355
							") Updating world file ("+x[pkgindex]+")")
4771
            "--fetchonly" not in self.myopts and \
4356
						world_set.save()
4772
            "--fetch-all-uri" not in self.myopts:
4357
					world_set.unlock()
4773
            if "noclean" not in self.settings.features:
4358
4774
                short_msg = "emerge: (%s of %s) %s Clean Post" % \
4359
				if "--pretend" not in self.myopts and \
4775
                    (mergecount, totalcount, x[pkgindex])
4360
					"--fetchonly" not in self.myopts and \
4776
                emergelog(xterm_titles, (" === (%s of %s) " + \
4361
					"--fetch-all-uri" not in self.myopts:
4777
                    "Post-Build Cleaning (%s::%s)") % \
4362
					# Clean the old package that we have merged over top of it.
4778
                    (mergecount, totalcount, x[pkgindex], y),
4363
					if pkgsettings.get("AUTOCLEAN", "yes") == "yes":
4779
                    short_msg=short_msg)
4364
						xsplit=portage.pkgsplit(x[2])
4780
            emergelog(xterm_titles, " ::: completed emerge ("+\
4365
						emergelog(xterm_titles, " >>> AUTOCLEAN: " + xsplit[0])
4781
                str(mergecount)+" of "+str(totalcount)+") "+\
4366
						retval = unmerge(pkgsettings, self.myopts, vartree,
4782
                x[2]+" to "+x[1])
4367
							"clean", [xsplit[0]], ldpath_mtimes, autoclean=1)
4783
4368
						if not retval:
4784
        return os.EX_OK
4369
							emergelog(xterm_titles,
4785
4370
								" --- AUTOCLEAN: Nothing unmerged.")
4786
    def add_one_emerge_to_world(self, x, mergecount, totalcount, favorites, metadata_keys):
4371
					else:
4787
        fetchonly = "--fetchonly" in self.myopts or \
4372
						portage.writemsg_stdout(colorize("WARN", "WARNING:")
4788
            "--fetch-all-uri" in self.myopts
4373
							+ " AUTOCLEAN is disabled.  This can cause serious"
4789
        pretend = "--pretend" in self.myopts
4374
							+ " problems due to overlapping packages.\n")
4790
        xterm_titles = "notitles" not in self.settings.features
4375
4791
        pkg_type = x[0]
4376
					# Figure out if we need a restart.
4792
        myroot=x[1]
4377
					mysplit=portage.pkgsplit(x[2])
4793
        pkg_key = x[2]
4378
					if mysplit[0] == "sys-apps/portage" and x[1] == "/":
4794
        pkgindex=2
4379
						if "livecvsportage" not in self.settings.features:
4795
        if x[0]=="blocks":
4380
							if len(mymergelist) > mergecount:
4796
            pkgindex=3
4381
								emergelog(xterm_titles,
4797
4382
									" ::: completed emerge ("+ \
4798
        portdb = self.trees[myroot]["porttree"].dbapi
4383
									str(mergecount)+" of "+ \
4799
        bindb  = self.trees[myroot]["bintree"].dbapi
4384
									str(len(mymergelist))+") "+ \
4800
        pkgsettings = self.pkgsettings[myroot]
4385
									x[2]+" to "+x[1])
4801
        root_config = RootConfig(self.trees[self.target_root])
4386
								emergelog(xterm_titles, " *** RESTARTING " + \
4802
        system_set = root_config.sets["system"]
4387
									"emerge via exec() after change of " + \
4803
        args_set = AtomSet(favorites)
4388
									"portage version.")
4804
        world_set = root_config.sets["world"]
4389
								del mtimedb["resume"]["mergelist"][0]
4805
        metadata = {}
4390
								mtimedb.commit()
4806
        if pkg_type == "blocks":
4391
								portage.run_exitfuncs()
4807
            pass
4392
								mynewargv=[sys.argv[0],"--resume"]
4808
        elif pkg_type == "ebuild":
4393
								resume_opts = self.myopts.copy()
4809
            mydbapi = portdb
4394
								# For automatic resume, we need to prevent
4810
            metadata.update(izip(metadata_keys,
4395
								# any of bad_resume_opts from leaking in
4811
                mydbapi.aux_get(pkg_key, metadata_keys)))
4396
								# via EMERGE_DEFAULT_OPTS.
4812
            pkgsettings.setcpv(pkg_key, mydb=mydbapi)
4397
								resume_opts["--ignore-default-opts"] = True
4813
            metadata["USE"] = pkgsettings["USE"]
4398
								for myopt, myarg in resume_opts.iteritems():
4814
        else:
4399
									if myopt not in bad_resume_opts:
4815
            if pkg_type == "binary":
4400
										if myarg is True:
4816
                mydbapi = bindb
4401
											mynewargv.append(myopt)
4817
            else:
4402
										else:
4818
-               sys.exit(0)
4403
											mynewargv.append(myopt +"="+ myarg)
4819
-       return os.EX_OK
4404
								# priority only needs to be adjusted on the first run
4820
                raise AssertionError("Package type: '%s'" % pkg_type)
4405
								os.environ["PORTAGE_NICENESS"] = "0"
4821
            metadata.update(izip(metadata_keys,
4406
								os.execv(mynewargv[0], mynewargv)
4822
                mydbapi.aux_get(pkg_key, metadata_keys)))
4407
4823
4408
			if "--pretend" not in self.myopts and \
4824
        if "--buildpkgonly" not in self.myopts:
4409
				"--fetchonly" not in self.myopts and \
4825
            self.trees[x[1]]["vartree"].inject(x[2])
4410
				"--fetch-all-uri" not in self.myopts:
4826
            myfavkey = portage.cpv_getkey(x[2])
4411
				if "noclean" not in self.settings.features:
4827
            if not fetchonly and not pretend and \
4412
					short_msg = "emerge: (%s of %s) %s Clean Post" % \
4828
                args_set.findAtomForPackage(pkg_key, metadata):
4413
						(mergecount, len(mymergelist), x[pkgindex])
4829
                world_set.lock()
4414
					emergelog(xterm_titles, (" === (%s of %s) " + \
4830
                world_set.load()
4415
						"Post-Build Cleaning (%s::%s)") % \
4831
                myfavkey = create_world_atom(pkg_key, metadata,
4416
						(mergecount, len(mymergelist), x[pkgindex], y),
4832
                    args_set, root_config)
4417
						short_msg=short_msg)
4833
                if myfavkey:
4418
				emergelog(xterm_titles, " ::: completed emerge ("+\
4834
                    world_set.add(myfavkey)
4419
					str(mergecount)+" of "+str(len(mymergelist))+") "+\
4835
                    print ">>> Recording",myfavkey,"in \"world\" favorites file..."
4420
					x[2]+" to "+x[1])
4836
                    emergelog(xterm_titles, " === ("+\
4421
4837
                        str(mergecount)+" of "+\
4422
			# Unsafe for parallel merges
4838
                        str(totalcount)+\
4423
			del mtimedb["resume"]["mergelist"][0]
4839
                        ") Updating world file ("+x[pkgindex]+")")
4424
			# Commit after each merge so that --resume may still work in
4840
                    world_set.save()
4425
			# in the event that portage is not allowed to exit normally
4841
                world_set.unlock()
4426
			# due to power failure, SIGKILL, etc...
4427
			mtimedb.commit()
4428
			self.curval += 1
4429
			self._poll_child_processes()
4430
4431
		if "--pretend" not in self.myopts:
4432
			emergelog(xterm_titles, " *** Finished. Cleaning up...")
4433
4434
		# We're out of the loop... We're done. Delete the resume data.
4435
		if mtimedb.has_key("resume"):
4436
			del mtimedb["resume"]
4437
		mtimedb.commit()
4438
4439
		#by doing an exit this way, --fetchonly can continue to try to
4440
		#fetch everything even if a particular download fails.
4441
		if "--fetchonly" in self.myopts or "--fetch-all-uri" in self.myopts:
4442
			if failed_fetches:
4443
				sys.stderr.write("\n\n!!! Some fetch errors were " + \
4444
					"encountered.  Please see above for details.\n\n")
4445
				for cpv in failed_fetches:
4446
					sys.stderr.write("   ")
4447
					sys.stderr.write(cpv)
4448
					sys.stderr.write("\n")
4449
				sys.stderr.write("\n")
4450
				sys.exit(1)
4451
			else:
4842
			else:
4452
				sys.exit(0)
4843
				sys.exit(0)
4453
		return os.EX_OK
4844
		return os.EX_OK
Lines 5904-5910 Link Here
5904
				">>> No packages selected for removal by %s\n" % action)
6295
				">>> No packages selected for removal by %s\n" % action)
5905
			return
6296
			return
5906
6297
5907
	if "--quiet" not in myopts:
6298
	if "--quiet" not in myopts and "--nodeps" not in myopts:
5908
		print "\nCalculating dependencies  ",
6299
		print "\nCalculating dependencies  ",
5909
6300
5910
	soft = 0
6301
	soft = 0
Lines 6124-6129 Link Here
6124
	else:
6515
	else:
6125
		print "Number removed:       "+str(len(cleanlist))
6516
		print "Number removed:       "+str(len(cleanlist))
6126
6517
6518
 def mergelist_to_merge_slot(mergelist, myopts, printonly=False, parallel=False):
6519
    merge_slots = {}
6520
    for pkg in mergelist:
6521
        if pkg[0] != 'blocks' and pkg[3] == 'merge':
6522
            slot = int(pkg[4])
6523
            try:
6524
                if pkg not in merge_slots[slot]:
6525
                    merge_slots[slot].append(pkg)
6526
            except KeyError:
6527
                merge_slots[slot] = [pkg]
6528
    # print the merge slots
6529
    max_slot = 0
6530
    mylist = merge_slots.keys()
6531
    mylist.sort()
6532
    for x in mylist:
6533
        if x > max_slot:
6534
            max_slot = x
6535
        if parallel:
6536
            print "Package list for slot = "+str(x)
6537
            for y in merge_slots[x]:
6538
                print " ",y
6539
    if printonly:
6540
        return
6541
6542
    # make one last pass at the merge_slots and initialize the missing slots to None
6543
    x = 0
6544
    while x < max_slot:
6545
        if x not in merge_slots.keys():
6546
            merge_slots[x] = None
6547
        x += 1
6548
    return merge_slots
6549
6127
def action_build(settings, trees, mtimedb,
6550
def action_build(settings, trees, mtimedb,
6128
	myopts, myaction, myfiles, spinner):
6551
	myopts, myaction, myfiles, spinner):
6129
	ldpath_mtimes = mtimedb["ldpath"]
6552
	ldpath_mtimes = mtimedb["ldpath"]
Lines 6250-6267 Link Here
6250
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6673
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6251
				return os.EX_OK
6674
				return os.EX_OK
6252
			favorites = mtimedb["resume"]["favorites"]
6675
			favorites = mtimedb["resume"]["favorites"]
6676
            mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6253
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6677
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6254
			if retval != os.EX_OK:
6678
			if retval != os.EX_OK:
6255
				return retval
6679
				return retval
6256
			prompt="Would you like to resume merging these packages?"
6680
			prompt="Would you like to resume merging these packages?"
6257
		else:
6681
		else:
6258
			retval = mydepgraph.display(
6682
            mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
6259
				mydepgraph.altlist(reversed=("--tree" in myopts)),
6683
            mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6260
				favorites=favorites)
6684
            retval = mydepgraph.display(mymergelist, favorites=favorites)
6261
			if retval != os.EX_OK:
6685
			if retval != os.EX_OK:
6262
				return retval
6686
				return retval
6263
			mergecount=0
6687
			mergecount=0
6264
			for x in mydepgraph.altlist():
6688
			for x in mymergelist:
6265
				if x[0] != "blocks" and x[3] != "nomerge":
6689
				if x[0] != "blocks" and x[3] != "nomerge":
6266
					mergecount+=1
6690
					mergecount+=1
6267
				#check for blocking dependencies
6691
				#check for blocking dependencies
Lines 6306-6318 Link Here
6306
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6730
				print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6307
				return os.EX_OK
6731
				return os.EX_OK
6308
			favorites = mtimedb["resume"]["favorites"]
6732
			favorites = mtimedb["resume"]["favorites"]
6733
            mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6309
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6734
			retval = mydepgraph.display(mymergelist, favorites=favorites)
6310
			if retval != os.EX_OK:
6735
			if retval != os.EX_OK:
6311
				return retval
6736
				return retval
6312
		else:
6737
		else:
6313
			retval = mydepgraph.display(
6738
            mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
6314
				mydepgraph.altlist(reversed=("--tree" in myopts)),
6739
            mergelist_to_merge_slot(mymergelist, myopts, True, "parallel" in settings.features)
6315
				favorites=favorites)
6740
            retval = mydepgraph.display(mymergelist, favorites=favorites)
6316
			if retval != os.EX_OK:
6741
			if retval != os.EX_OK:
6317
				return retval
6742
				return retval
6318
			if "--buildpkgonly" in myopts and \
6743
			if "--buildpkgonly" in myopts and \
Lines 6335-6356 Link Here
6335
				it to write the mtimedb"""
6760
				it to write the mtimedb"""
6336
				mtimedb.filename = None
6761
				mtimedb.filename = None
6337
				time.sleep(3) # allow the parent to have first fetch
6762
				time.sleep(3) # allow the parent to have first fetch
6763
            mymergelist = mtimedb["resume"]["mergelist"]
6764
            if "--skipfirst" in myopts:
6765
                mymergelist = mymergelist[1:]
6766
            if len(mymergelist) == 0:
6767
                print colorize("INFORM", "emerge: It seems we have nothing to resume...")
6768
                sys.exit(0)
6769
            merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
6338
			del mydepgraph
6770
			del mydepgraph
6339
			retval = mergetask.merge(
6771
            retval = mergetask.merge(mymergelist, favorites, mtimedb, merge_slots)
6340
				mtimedb["resume"]["mergelist"], favorites, mtimedb)
6341
			merge_count = mergetask.curval
6772
			merge_count = mergetask.curval
6342
		else:
6773
		else:
6343
			if "resume" in mtimedb and \
6774
            mymergelist = mydepgraph.altlist(reversed=("--tree" in myopts))
6344
			"mergelist" in mtimedb["resume"] and \
6775
            merge_slots = mergelist_to_merge_slot(mymergelist, myopts, False, False)
6345
			len(mtimedb["resume"]["mergelist"]) > 1:
6776
            if "--nodeps" not in myopts or len(mymergelist) > 1:
6346
				mtimedb["resume_backup"] = mtimedb["resume"]
6777
                if "resume" in mtimedb and \
6347
				del mtimedb["resume"]
6778
                "mergelist" in mtimedb["resume"] and \
6348
				mtimedb.commit()
6779
                len(mtimedb["resume"]["mergelist"]) > 1:
6349
			mtimedb["resume"]={}
6780
                    mtimedb["resume_backup"] = mtimedb["resume"]
6350
			# XXX: Stored as a list for backward compatibility.
6781
                    del mtimedb["resume"]
6351
			mtimedb["resume"]["myopts"] = \
6782
                    mtimedb.commit()
6352
				[k for k in myopts if myopts[k] is True]
6783
                mtimedb["resume"]={}
6353
			mtimedb["resume"]["favorites"]=favorites
6784
                # XXX: Stored as a list for backward compatibility.
6785
                mtimedb["resume"]["myopts"] = \
6786
                    [k for k in myopts if myopts[k] is True]
6787
                mtimedb["resume"]["favorites"]=favorites
6354
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
6788
			if ("--digest" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
6355
				for pkgline in mydepgraph.altlist():
6789
				for pkgline in mydepgraph.altlist():
6356
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
6790
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
Lines 6365-6371 Link Here
6365
							mydbapi=trees[pkgline[1]]["porttree"].dbapi,
6799
							mydbapi=trees[pkgline[1]]["porttree"].dbapi,
6366
							tree="porttree")
6800
							tree="porttree")
6367
6801
6368
			pkglist = mydepgraph.altlist()
6802
			pkglist = mymergelist
6369
6803
6370
			if fetchonly or "--buildpkgonly"  in myopts:
6804
			if fetchonly or "--buildpkgonly"  in myopts:
6371
				pkglist = [pkg for pkg in pkglist if pkg[0] != "blocks"]
6805
				pkglist = [pkg for pkg in pkglist if pkg[0] != "blocks"]
Lines 6373-6381 Link Here
6373
				for x in pkglist:
6807
				for x in pkglist:
6374
					if x[0] != "blocks":
6808
					if x[0] != "blocks":
6375
						continue
6809
						continue
6376
					retval = mydepgraph.display(mydepgraph.altlist(
6810
                    retval = mydepgraph.display(mymergelist, favorites=favorites)
6377
						reversed=("--tree" in myopts)),
6378
						favorites=favorites)
6379
					msg = "Error: The above package list contains " + \
6811
					msg = "Error: The above package list contains " + \
6380
						"packages which cannot be installed " + \
6812
						"packages which cannot be installed " + \
6381
						"at the same time on the same system."
6813
						"at the same time on the same system."
Lines 6392-6402 Link Here
6392
				mydepgraph.saveNomergeFavorites()
6824
				mydepgraph.saveNomergeFavorites()
6393
			del mydepgraph
6825
			del mydepgraph
6394
			mergetask = MergeTask(settings, trees, myopts)
6826
			mergetask = MergeTask(settings, trees, myopts)
6395
			retval = mergetask.merge(pkglist, favorites, mtimedb)
6827
			retval = mergetask.merge(pkglist, favorites, mtimedb, merge_slots)
6396
			merge_count = mergetask.curval
6828
			merge_count = mergetask.curval
6397
6829
6398
		if retval == os.EX_OK and not (pretend or fetchonly):
6830
		if retval == os.EX_OK and not (pretend or fetchonly):
6399
			mtimedb.pop("resume", None)
6831
            if ("--nodeps" not in myopts or len(mymergelist) > 1):
6832
                mtimedb.pop("resume", None)
6400
			if "yes" == settings.get("AUTOCLEAN"):
6833
			if "yes" == settings.get("AUTOCLEAN"):
6401
				portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
6834
				portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
6402
				vartree = trees[settings["ROOT"]]["vartree"]
6835
				vartree = trees[settings["ROOT"]]["vartree"]
(-)portage_orig/pym/portage.py (-12 / +27 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 481-496 Link Here
481
		return len(self.leaf_nodes(ignore_priority=ignore_priority)) == \
481
		return len(self.leaf_nodes(ignore_priority=ignore_priority)) == \
482
			len(self.order)
482
			len(self.order)
483
483
484
    def debug_print(self):
484
	def debug_print(self):
485
        for node in self.nodes:
485
		lista = dict()
486
            print node, 
486
		for node in self.nodes:
487
            if self.nodes[node][0]:
487
			#print node,
488
                print "depends on"
488
			#if self.nodes[node][0]:
489
            else: 
489
				#print "depends on"
490
                print "(no children)"
490
			#else:
491
            for child in self.nodes[node][0]:
491
			#	print "(no children)"
492
                print "  ",child,
492
			for child in self.nodes[node][0]:
493
                print "(%s)" % self.nodes[node][0][child]
493
				#print "  ",child,
494
				#print "(%s)" % self.nodes[node][0][child]
495
				for node2 in self.nodes:
496
				    if child[2] == node2[2]:
497
					for child2 in self.nodes[node2][0]:
498
					    if child2[2] == node[2]:
499
						if not node[2] in lista.keys() and not node2[2] in lista.keys():
500
						    lista[node[2]] = node2[2]
501
						    
502
		for i in lista.keys():
503
		    print "%s depends on %s" % (i, lista[i])
504
494
505
495
_elog_atexit_handlers = []
506
_elog_atexit_handlers = []
496
def elog_process(cpv, mysettings):
507
def elog_process(cpv, mysettings):
Lines 3810-3815 Link Here
3810
	if mysettings.get("PORT_LOGDIR", "") == "":
3821
	if mysettings.get("PORT_LOGDIR", "") == "":
3811
		while "PORT_LOGDIR" in mysettings:
3822
		while "PORT_LOGDIR" in mysettings:
3812
			del mysettings["PORT_LOGDIR"]
3823
			del mysettings["PORT_LOGDIR"]
3824
3825
    if not "PORT_LOGDIR" in mysettings and "parallel" in mysettings.features:
3826
        mysettings["PORT_LOGDIR"] = mysettings["ROOT"] + DEF_LOGDIR
3827
3813
	if "PORT_LOGDIR" in mysettings:
3828
	if "PORT_LOGDIR" in mysettings:
3814
		try:
3829
		try:
3815
			modified = portage_util.ensure_dirs(mysettings["PORT_LOGDIR"])
3830
			modified = portage_util.ensure_dirs(mysettings["PORT_LOGDIR"])
Lines 3824-3830 Link Here
3824
			while "PORT_LOGDIR" in mysettings:
3839
			while "PORT_LOGDIR" in mysettings:
3825
				del mysettings["PORT_LOGDIR"]
3840
				del mysettings["PORT_LOGDIR"]
3826
	if "PORT_LOGDIR" in mysettings:
3841
	if "PORT_LOGDIR" in mysettings:
3827
		logid_path = os.path.join(mysettings["PORTAGE_BUILDDIR"], ".logid")
3842
        logid_path = os.path.join(mysettings["BUILD_PREFIX"], ".logid.")+mysettings["CATEGORY"]+"."+ mysettings["PF"]
3828
		if not os.path.exists(logid_path):
3843
		if not os.path.exists(logid_path):
3829
			f = open(logid_path, "w")
3844
			f = open(logid_path, "w")
3830
			f.close()
3845
			f.close()
(-)portage_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_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_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