Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 2365 | Differences between
and this patch

Collapse All | Expand All

(-)emergehelp.py (-2055 / +337 lines)
Lines 1-2079 Link Here
1
#!/usr/bin/env python2.2
1
#!/usr/bin/env python2.2
2
# Copyright 1999-2003 Gentoo Technologies, Inc.
2
# Copyright 1999-2003 Gentoo Technologies, Inc.
3
# Distributed under the terms of the GNU General Public License v2
3
# Distributed under the terms of the GNU General Public License v2
4
# $Header: /home/cvsroot/gentoo-src/portage/bin/emerge,v 1.224 2003/08/21 01:01:26 carpaski Exp $
4
# $Header: /home/cvsroot/gentoo-src/portage/bin/emergehelp.py,v 1.16 2003/08/16 07:28:22 carpaski Exp $
5
6
import os
7
os.environ["PORTAGE_CALLER"]="emerge"
8
5
9
import sys,emergehelp,xpak,string,re,commands,time,shutil,traceback,atexit,signal
6
import os,sys
10
from stat import *
11
from output import *
7
from output import *
12
8
13
import portage
9
def shorthelp():
14
if (not sys.stdout.isatty()) or (portage.settings["NOCOLOR"] in ["yes","true"]):
10
	print
15
	nocolor()
11
	print
16
12
	print bold("Usage:")
17
if portage.settings.has_key("PORTAGE_NICENESS"):
13
	print "   "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] [ "+turquoise("ebuildfile")+" | "+turquoise("tbz2file")+" | "+turquoise("dependency")+" ] [ ... ]"
18
	try:
14
	print "   "+turquoise("emerge")+" [ "+green("options")+" ] [ "+green("action")+" ] < "+turquoise("system")+" | "+turquoise("world")+" >"
19
		os.nice(int(portage.settings["PORTAGE_NICENESS"]))
15
	print "   "+turquoise("emerge")+" < "+turquoise("sync")+" | "+turquoise("info")+" >"
20
	except Exception,e:
16
	print "   "+turquoise("emerge")+" "+turquoise("--resume")+" ["+green("--pretend")+" | "+green("--skip-first")+"]"
21
		print "!!! Failed to change nice value to '"+str(portage.settings["PORTAGE_NICENESS"])+"'"
17
	print "   "+turquoise("emerge")+" "+turquoise("help")+" [ "+green("system")+" | "+green("config")+" | "+green("sync")+" ] "
22
		print "!!!",e
18
	print bold("Options:")+" "+green("-")+"["+green("bcCdDefhikKlnoOpPsSuUvV")+"] ["+green("--once-only")+"] ["+green("--forget-configuration")+"]"
23
19
	print      "                                    ["+green("--columns")+"] ["+green("--no-spinner")+"]"
24
#Freeze the portdbapi for enhanced performance:
20
	print bold("Actions:")+" [ "+green("clean")+" | "+green("depclean")+" | "+green("inject")+" | "+green("prune")+" | "+green("regen")+" | "+green("search")+" | "+green("unmerge")+" ]"
25
portage.portdb.freeze()
21
	print
26
27
# Kill noauto as it will break merges otherwise.
28
while 'noauto' in portage.features:
29
	del portage.features[portage.features.index('noauto')]
30
31
32
spinner="\|/-\|/-"
33
spinpos=0
34
#number of ebuilds merged
35
merged=0
36
params=["selective", "deep", "self", "recurse", "empty"]
37
actions=[
38
"clean", "config", "depclean", "help", "info",   "inject",  "prune",
39
"regen", "rsync",  "search",   "sync", "system", "unmerge", "world"
40
]
41
options=[
42
"--buildpkg",     "--buildpkgonly",
43
"--changelog",    "--columns",
44
"--debug",        "--deep",
45
"--digest",
46
"--emptytree",    "--fetchonly",
47
"--getbinpkg",    "--getbinpkgonly",
48
"--help",         "--noconfmem",
49
"--nodeps",       "--noreplace",
50
"--nospinner",    "--oneshot",
51
"--onlydeps",     "--pretend",
52
"--quiet",        "--resume",
53
"--searchdesc",   "--selective",
54
"--skipfirst",
55
"--update",       "--upgradeonly",
56
"--usepkg",       "--usepkgonly",
57
"--verbose",      "--version"
58
]
59
60
shortmapping={
61
"b":"--buildpkg",  "B":"--buildpkgonly",
62
"c":"--clean",     "C":"--unmerge",
63
"d":"--debug",     "D":"--deep",
64
"e":"--emptytree",
65
"f":"--fetchonly",
66
"g":"--getbinpkg", "G":"--getbinpkgonly",
67
"h":"--help",
68
"i":"--inject",
69
"k":"--usepkg",    "K":"--usepkgonly",
70
"l":"--changelog",
71
"n":"--noreplace",
72
"o":"--onlydeps",  "O":"--nodeps",
73
"p":"--pretend",   "P":"--prune",
74
"q":"--quiet",
75
"s":"--search",    "S":"--searchdesc",
76
"u":"--update",    "U":"--upgradeonly",
77
"v":"--verbose",   "V":"--version"
78
}
79
80
myaction=None
81
myopts=[]
82
myfiles=[]
83
edebug=0
84
85
# process short actions and options
86
tmpcmdline=sys.argv[1:]
87
#tmpcmdline.extend(portage.settings["EMERGE_OPTS"].split())
88
cmdline=[]
89
for x in tmpcmdline:
90
	if x[0:1]=="-"and x[1:2]!="-":
91
		for y in x[1:]:
92
			if shortmapping.has_key(y):
93
				if shortmapping[y] in cmdline:
94
					print
95
					print "*** Warning: Redundant use of",shortmapping[y]
96
				else:
97
					cmdline.append(shortmapping[y])
98
			else:
99
				print "!!! Error: -"+y+" is an invalid short action or option."
100
				sys.exit(1)
101
	else:
102
		cmdline.append(x)
103
104
# process the command arguments
105
for x in cmdline:
106
	if not x:
107
		continue
108
	if len(x)>=2 and x[0:2]=="--":
109
			if x in options:
110
				myopts.append(x)
111
			elif x[2:] in actions:
112
				if x[2:]=="rsync":
113
					#print
114
					#print red("*** --rsync has been deprecated.")
115
					#print red("***   Please use '--sync' instead.")
116
					x="--sync"
117
				if myaction:
118
					if myaction not in ["system", "world"]:
119
						myaction="--"+myaction
120
					print
121
					print red("!!!")+green(" Multiple actions requested... Please choose one only.")
122
					print red("!!!")+" '"+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
123
					print
124
					sys.exit(1)
125
				myaction=x[2:]
126
			else:
127
				print "!!! Error:",x,"is an invalid option."
128
				sys.exit(1)
129
	elif (not myaction) and (x in actions):
130
		if x not in ["system", "world"]:
131
			#print red("*** Deprecated use of action '"+x+"'")
132
			if x=="rsync":
133
				#print red("***   Please use '--sync' instead.")
134
				x="sync"
135
			#else:
136
				#print red("***   Please use '--"+x+"' instead.")
137
		if myaction:
138
			print
139
			print red("!!!")+green(" Multiple actions requested... Please choose one only.")
140
			#print red("!!! '")+darkgreen("--"+myaction)+"' "+red("or")+" '"+darkgreen("--"+x)+"'"
141
			print red("!!! '")+darkgreen(myaction)+"' "+red("or")+" '"+darkgreen(x)+"'"
142
			print
143
			sys.exit(1)
144
		myaction=x
145
	elif x[-1]=="/":
146
		# this little conditional helps tab completion
147
		myfiles.append(x[:-1])
148
	else:
149
		myfiles.append(x)
150
151
if (myaction in ["world", "system"]) and myfiles:
152
	print "emerge: please specify a package class (\"world\" or \"system\") or individual packages, but not both."
153
	sys.exit(1)
154
155
# Always create packages if FEATURES=buildpkg
156
# Imply --buildpkg if --buildpkgonly
157
if ("buildpkg" in portage.features) or ("--buildpkgonly" in myopts):
158
	if "--buildpkg" not in myopts:
159
		myopts.append("--buildpkg")
160
161
# Also allow -S to invoke search action (-sS)
162
if ("--searchdesc" in myopts) and (not myaction):
163
	myaction = "search"
164
165
if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
166
	myopts.append("--usepkgonly")
167
168
if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
169
	myopts.append("--getbinpkg")
170
171
if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
172
	myopts.append("--usepkg")
173
174
# Also allow -K to apply --usepkg/-k
175
if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
176
	myopts.append("--usepkg")
177
178
# Also allow -U to apply --update/-u
179
if ("--upgradeonly" in myopts) and not ("--update" in myopts):
180
	print ">>> --upgradeonly implies --update... adding --update to options."
181
	myopts.append("--update")
182
183
# Also allow -l to apply --pretend/-p
184
if ("--changelog" in myopts) and not ("--pretend" in myopts):
185
	print ">>> --changelog implies --pretend... adding --pretend to options."
186
	myopts.append("--pretend")
187
188
# Set so that configs will be merged regardless of remembered status
189
if ("--noconfmem" in myopts):
190
	portage.settings["NOCONFMEM"]="1"
191
192
# Set various debug markers... They should be merged somehow.
193
if ("--debug" in myopts):
194
	portage.settings["PORTAGE_DEBUG"]="1"
195
	portage.debug=1
196
197
198
def emergelog(mystr):
199
	if "notitles" not in portage.features:
200
		xtermTitle(mystr)
201
	try:
202
		mylogfile=open("/var/log/emerge.log", "a")
203
		mylogfile.write(str(time.time())[:10]+": "+mystr+"\n")
204
		mylogfile.flush()
205
		mylogfile.close()
206
	except Exception, e:
207
		if edebug:
208
			print "emergelog():",e
209
		pass
210
211
def emergeexit():
212
	"""This gets out final log message in before we quit. As it overrides
213
	any other atexit's we have setup, we need to call them ourself."""
214
	#portage.portageexit()
215
	emergelog(" *** terminating.")
216
	if "notitles" not in portage.features:
217
		xtermTitleReset()
218
atexit.register(emergeexit)
219
220
def emergeexitsig(signum, frame):
221
	emergeexit()
222
	sys.exit(100+signum)
223
signal.signal(signal.SIGINT, emergeexitsig)
224
22
225
def countdown(secs=5, doing="Starting"):
23
def help(myaction,myopts,havecolor=1):
226
	if secs:
24
	if not havecolor:
227
		print ">>> Waiting",secs,"seconds before starting..."
25
		nocolor()
228
		print ">>> (Control-C to abort)...\n"+doing+" in: ",
26
	if not myaction and ("--help" not in myopts):
229
		ticks=range(secs)
27
		shorthelp()
230
		ticks.reverse()
231
		for sec in ticks:
232
			sys.stdout.write(red(str(sec+1)+" "))
233
			sys.stdout.flush()
234
			time.sleep(1)
235
		print
28
		print
236
29
		print "   For more help try 'emerge --help' or consult the man page."
237
def getportageversion():
238
	try:
239
		profilever=os.path.basename(os.path.normpath(os.readlink("/etc/make.profile")))
240
	except:
241
		profilever="unavailable"
242
	glibcver=[]
243
	for x in portage.vardbapi(portage.root).match("glibc"):
244
		xs=portage.pkgsplit(x)
245
		if glibcver:
246
			glibcver+=","+xs[1]+"-"+xs[2]
247
		else:
248
			glibcver=xs[1]+"-"+xs[2]
249
	if glibcver==[]:
250
		glibcver="unavailable"
251
252
	gccout=commands.getstatusoutput("`which gcc` -dumpversion")
253
	if gccout[0]:
254
		print "!!! No gcc found. You probably need to 'source /etc/profile' to update"
255
		print "!!! the environment of this terminal and possibly other terminals also."
256
		print
30
		print
257
		gccver="[unavailable]"
31
	elif not myaction:
258
	else:
32
		shorthelp()
259
		gccver="gcc-"+gccout[1]
260
261
	unameout=commands.getstatusoutput("uname -r")[1]
262
263
	return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", glibc-"+glibcver+", "+unameout+")"
264
265
def help():
266
	# Move all the help stuff out of this file.
267
	emergehelp.help(myaction,myopts,havecolor)
268
269
# check if root user is the current user for the actions where emerge needs this
270
if ("--pretend" in myopts) or (myaction=="search"):
271
	if not portage.secpass:
272
		if portage.wheelgid==portage.portage_gid:
273
			print "emerge: wheel group membership required for \"--pretend\" and search."
274
			print "emerge: wheel group use is being deprecated. Please update group and passwd to"
275
			print "        include the portage user as noted above, and then use group portage."
276
		else:
277
			print "emerge: portage group membership required for \"--pretend\" and search."
278
		sys.exit(1)
279
elif "--version" in myopts:
280
	print getportageversion()
281
	sys.exit(0)
282
elif "--help" in myopts:
283
	help()
284
	sys.exit(0)
285
elif portage.secpass!=2:
286
	if myaction in ["search", "help", "info"]:
287
		pass
288
	elif (not myaction) and (not myfiles):
289
		pass
290
	elif ("--pretend" in myopts) and (myaction in ["world","system","clean","prune","unmerge"]):
291
		pass
292
	else:
293
		print "myaction",myaction
294
		print "myopts",myopts
295
		print "emerge: root access required."
296
		sys.exit(1)
297
298
if not "--pretend" in myopts:
299
	emergelog("Started emerge on: "+time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
300
	myelogstr=""
301
	if myopts:
302
		myelogstr=string.join(myopts, " ")
303
	if myaction:
304
		myelogstr+=" "+myaction
305
	if myfiles:
306
		myelogstr+=" "+string.join(myfiles, " ")
307
	emergelog(" *** emerge "+myelogstr)
308
309
#configure emerge engine parameters
310
#
311
# self:      include _this_ package regardless of if it is merged.
312
# selective: exclude the package if it is merged
313
# recurse:   go into the dependencies
314
# empty:     pretend nothing is merged
315
myparams=["self","recurse"]
316
add=[]
317
sub=[]
318
if "--update" in myopts:
319
	add.extend(["selective","empty"])
320
if "--emptytree" in myopts:
321
	add.extend(["empty"])
322
	sub.extend(["selective"])
323
if "--nodeps" in myopts:
324
	sub.extend(["recurse"])
325
if "--noreplace" in myopts:
326
	add.extend(["selective"])
327
if "--deep" in myopts:
328
	add.extend(["deep"])
329
if "--selective" in myopts:
330
	add.extend(["selective"])
331
if myaction in ["world","system"]:
332
	add.extend(["selective"])
333
elif myaction in ["depclean"]:
334
	add.extend(["empty"])
335
	sub.extend(["selective"])
336
for x in add:
337
	if (x not in myparams) and (x not in sub):
338
		myparams.append(x)
339
for x in sub:
340
	if x in myparams:
341
		myparams.remove(x)
342
343
def update_spinner():
344
	global spinner, spinpos
345
	if sys.stdout.isatty() and not ("--nospinner" in myopts):
346
		sys.stdout.write("\b"+spinner[spinpos])
347
		spinpos=(spinpos+1)%8
348
		sys.stdout.flush()
349
350
# search functionality
351
class search:
352
	
353
	#
354
	# class constants
355
	#
356
	VERSION_SHORT=1
357
	VERSION_RELEASE=2
358
	
359
	#
360
	# public interface
361
	#
362
	def __init__(self):
363
		"""Searches the available and installed packages for the supplied search key.
364
		The list of available and installed packages is created at object instantiation.
365
		This makes successive searches faster."""
366
		self.installcache = portage.db["/"]["vartree"]
367
		
368
	def execute(self,searchkey):
369
		"""Performs the search for the supplied search key"""
370
		global myopts
371
		self.searchkey=searchkey
372
		self.packagematches = []
373
		if "--searchdesc" in myopts:
374
			self.searchdesc=1
375
			self.matches = {"pkg":[], "desc":[]}
376
		else:
377
			self.searchdesc=0
378
			self.matches = {"pkg":[]}
379
		print "Searching...   ",
380
		if self.searchkey=="*":
381
			#hack for people who aren't regular expression gurus
382
			self.searchkey==".*"
383
		if re.search("\+\+", self.searchkey):
384
			#hack for people who aren't regular expression gurus
385
			self.searchkey=re.sub("\+\+","\+\+",self.searchkey)
386
		self.searchre=re.compile(self.searchkey.lower(),re.I)
387
		for package in portage.portdb.cp_all():
388
			update_spinner()
389
			package_parts=package.split("/")
390
			masked=0
391
			if self.searchre.search(package_parts[1]):
392
				if not portage.portdb.xmatch("match-visible",package):
393
					masked=1
394
				self.matches["pkg"].append([package,masked])
395
			elif self.searchdesc: # DESCRIPTION searching
396
				full_package = portage.portdb.xmatch("bestmatch-visible",package)
397
				if not full_package:
398
					#no match found; we don't want to query description
399
					full_package=portage.best(portage.portdb.xmatch("match-all",package))
400
					if not full_package:
401
						continue
402
					else:
403
						masked=1
404
				try:
405
					full_desc = portage.portdb.aux_get(full_package,["DESCRIPTION"])[0]
406
				except KeyError:
407
					print "emerge: search: aux_get() failed, skipping"
408
					continue
409
				if self.searchre.search(full_desc):
410
					self.matches["desc"].append([full_package,masked])
411
		self.mlen=0
412
		for mtype in self.matches.keys():
413
			self.matches[mtype].sort()
414
			self.mlen += len(self.matches[mtype])	
415
416
	def output(self):
417
		"""Outputs the results of the search."""
418
		print "\b\b  \n[ Results for search key : "+white(self.searchkey)+" ]"
419
		print "[ Applications found : "+white(str(self.mlen))+" ]"
420
		print " "
421
		for mtype in self.matches.keys():	
422
			for match,masked in self.matches[mtype]:
423
				if mtype=="pkg":
424
					catpack=match
425
					full_package = portage.portdb.xmatch("bestmatch-visible",match)
426
					if not full_package:
427
						#no match found; we don't want to query description
428
						masked=1
429
						full_package=portage.best(portage.portdb.xmatch("match-all",match))
430
				else:
431
					full_package=match
432
					catpack=portage.pkgsplit(match)[0]
433
				if full_package:
434
					try:
435
						desc, homepage = portage.portdb.aux_get(full_package,["DESCRIPTION","HOMEPAGE"])
436
					except KeyError:
437
						print "emerge: search: aux_get() failed, skipping"
438
						continue
439
					if masked:
440
						print green("*")+"  "+white(match)+" "+red("[ Masked ]")
441
					else:
442
						print green("*")+"  "+white(match)
443
					myversion = self.getVersion(full_package, search.VERSION_RELEASE)
444
445
					mysum = [0,0]
446
					mycat = match.split("/")[0]
447
					mypkg = match.split("/")[1] + "-" + myversion
448
449
					mydigest = portage.db["/"]["porttree"].dbapi.finddigest(mycat+"/"+mypkg)
450
					
451
					try:
452
						myfile = open(mydigest,"r")
453
						for line in myfile.readlines():
454
							mysum[0] += int(line.split(" ")[3])
455
						myfile.close()
456
						mystr = str(mysum[0]/1024)
457
						mycount=len(mystr)
458
						while (mycount > 3):
459
							mycount-=3
460
							mystr=mystr[:mycount]+","+mystr[mycount:]
461
						mysum[0]=mystr+" kB"
462
					except Exception, e:
463
						if edebug:
464
							print "!!! Exception:",e
465
						mysum[0]=" [no/bad digest]"
466
						
467
					if "--quiet" not in myopts:
468
						print "     ", darkgreen("Latest version available:"),myversion
469
						print "     ", self.getInstallationStatus(catpack)
470
						print "     ", darkgreen("Size of downloaded files:"),mysum[0]
471
						print "     ", darkgreen("Homepage:")+"   ",homepage
472
						print "     ", darkgreen("Description:"),desc
473
						print
474
		print
33
		print
475
	#
34
		print turquoise("Help (this screen):")
476
	# private interface
35
		print "       "+green("--help")+" ("+green("-h")+" short option)"
477
	#
36
		print "              Displays this help; an additional argument (see above) will tell"
478
	def getInstallationStatus(self,package):
37
		print "              emerge to display detailed help."
479
		installed_package = self.installcache.dep_bestmatch(package)
480
		result = ""
481
		version = self.getVersion(installed_package,search.VERSION_RELEASE)
482
		if len(version) > 0:
483
			result = darkgreen("Latest version installed:")+" "+version
484
		else:
485
			result = darkgreen("Latest version installed:")+" [ Not Installed ]"
486
		return result
487
488
	def getVersion(self,full_package,detail):
489
		if len(full_package) > 1:
490
			package_parts = portage.catpkgsplit(full_package)
491
			if detail == search.VERSION_RELEASE and package_parts[3] != 'r0':
492
				result = package_parts[2]+ "-" + package_parts[3]
493
			else:
494
				result = package_parts[2]
495
		else:
496
			result = ""
497
		return result
498
499
500
#build our package digraph
501
def getlist(mode):
502
	if mode=="system":
503
		if portage.profiledir:
504
			pfile=portage.profiledir+"/packages"
505
		else:
506
			print "!!! No profile directory; system mode unavailable."
507
			sys.exit(1)
508
	elif mode=="world":
509
		pfile=portage.root+"var/cache/edb/world"
510
	try:
511
		myfile=open(pfile,"r")
512
		mylines=myfile.readlines()
513
		myfile.close()
514
	except OSError:
515
		print "!!! Couldn't open "+pfile+"; exiting."
516
		sys.exit(1)
517
	except IOError:
518
		#world file doesn't exist
519
		mylines=[]
520
	mynewlines=[]
521
	for x in mylines:
522
		myline=string.join(string.split(x))
523
		if not len(myline):
524
			continue
525
		elif myline[0]=="#":
526
			continue
527
		elif mode=="system":
528
			if myline[0]!="*":
529
				continue
530
			myline=myline[1:]
531
		mynewlines.append(myline.strip())
532
	return mynewlines
533
534
def genericdict(mylist):
535
	mynewdict={}
536
	for x in mylist:
537
		mynewdict[portage.dep_getkey(x)]=x
538
	return mynewdict
539
540
olddbapi=None
541
class depgraph:
542
543
	def __init__(self,myaction,myopts):
544
		global olddbapi
545
		self.missingbins=[]
546
		self.myaction=myaction
547
		self.virts=portage.getvirtuals("/")
548
		self.digraph=portage.digraph()
549
		self.orderedkeys=[]
550
		#the following is so we have an empty vartree (used in emerge update calculations)
551
		self.fakedbapi=portage.fakedbapi()
552
		#self.fakedbapi.cpv_inject("sys-libs/glibc-2.3")	
553
		self.outdatedpackages=[]
554
		self.mydbapi={}
555
		if "empty" in myparams:
556
			#for --update, we want to rebuild an entire empty tree of dependencies, and then we won't merge was is already merged.
557
			self.mydbapi["/"]=self.fakedbapi
558
		else:
559
			self.mydbapi["/"]=portage.db["/"]["vartree"].dbapi
560
		if portage.root!="/":
561
			if "empty" in myparams:
562
				self.mydbapi[portage.root]=self.fakedbapi
563
			else:
564
				self.mydbapi[portage.root]=portage.db[portage.root]["vartree"].dbapi
565
			
566
		if "--usepkg" in myopts:
567
			try:
568
				portage.db["/"]["bintree"].populate(("--getbinpkg" in myopts), ("--getbinpkgonly" in myopts))
569
			except ValueError, e:
570
				sys.stderr.write(red("!!! Failed to get all metadata: "+str(e)+"\n"))
571
				sys.exit(1)
572
573
	def create(self,mybigkey,myparent=None,addme=1):
574
		"""creates the actual digraph of packages to merge.  return 1 on success, 0 on failure
575
		mybigkey = specification of package to merge; myparent = parent package (one depending on me);
576
		addme = should I be added to the tree? (for the --onlydeps mode)"""
577
		#stuff to add:
578
		#SLOT-aware emerge
579
		#IUSE-aware emerge
580
		#"no downgrade" emerge
581
		#print "mybigkey:",mybigkey
582
				
583
		jbigkey=string.join(mybigkey)
584
		if self.digraph.hasnode(jbigkey+" merge") or self.digraph.hasnode(jbigkey+" nomerge"):
585
			#this conditional is needed to prevent infinite recursion on already-processed deps
586
			return 1
587
588
		update_spinner()
589
		
590
		mytype,myroot,mykey=mybigkey
591
	
592
		# select the correct /var database that we'll be checking against
593
		vardbapi=portage.db[myroot]["vartree"].dbapi
594
595
		merging=1
596
		# this is where we add the node to the list of packages to merge
597
		if addme:
598
			# if the package is already on the system, we add a "nomerge"
599
			# directive, otherwise we add a "merge" directive.
600
			if mytype=="blocks":
601
				# we've encountered a "blocks" node.  We will totally ignore this
602
				# node and not add it to our digraph if it doesn't apply to us.
603
				if myparent and (self.mydbapi[myroot].match(mykey) or vardbapi.match(mykey)):
604
					# otherwise, encode parent information where we would normally
605
					# write "(no)merge" and continue:
606
					parenttype,parentroot,parentkey,mergeme=string.split(myparent)
607
					mykexp=portage.dep_expand(mykey,self.mydbapi[myroot])
608
					pakexp=portage.dep_expand(parentkey,self.mydbapi[myroot])
609
					myrealkey=portage.dep_getkey(mykexp)
610
					parealkey=portage.dep_getkey(pakexp)
611
					if myrealkey!=parealkey:
612
						mybigkey.append(myparent.split()[2])
613
						self.digraph.addnode(string.join(mybigkey),myparent)
614
					# since our blocks doesn't match any installed packages,
615
					# it doesn't apply to us and we can ignore it.
616
				return 1
617
			if not myparent:
618
				# command-line specified or part of a world list...
619
				if ("self" not in myparams) or (("selective" in myparams) and vardbapi.cpv_exists(mykey)):
620
					# the package is on the system, so don't merge it.
621
					merging=0
622
			elif ("selective" in myparams) and vardbapi.cpv_exists(mykey):
623
				merging=0
624
		else:
625
			#onlydeps mode; don't merge
626
			merging=2
627
		if merging==1:
628
			mybigkey.append("merge")
629
		else:
630
			mybigkey.append("nomerge")
631
			
632
		# whatever the case, we need to add the node to our digraph so
633
		# that children can depend upon it.
634
		self.digraph.addnode(string.join(mybigkey),myparent)
635
		if ("deep" not in myparams) and (not merging):
636
			return 1
637
		elif "recurse" not in myparams:
638
			return 1
639
640
		edepend={}
641
		if mytype=="binary":
642
			mypkgparts=portage.catpkgsplit(mykey)
643
			tbz2name = string.split(mykey, "/")[1]+".tbz2"
644
			if portage.db[portage.root]["bintree"].isremote(mykey) and ("--pretend" in myopts):
645
				# It's remote, and we have the info already. In pretend,
646
				# we don't want to be downloading the tbz2's.
647
				#if not portage.db[portage.root]["bintree"].remotepkgs.has_key(mypkgparts[1]):
648
				#	sys.stderr.write("\nThere are no packages available to satisfy "+str(mykey)+"\n\n")
649
				#	sys.exit(1)
650
				edepend = portage.db[portage.root]["bintree"].remotepkgs[tbz2name]
651
				edepend["DEPEND"] =""
652
				edepend["RDEPEND"]=string.join(string.split(edepend["RDEPEND"])," ")
653
				edepend["PDEPEND"]=string.join(string.split(edepend["PDEPEND"])," ")
654
				edepend["CDEPEND"]=string.join(string.split(edepend["CDEPEND"])," ")
655
				edepend["SLOT"]   =string.strip(edepend["SLOT"])
656
			else:
657
				if portage.db[portage.root]["bintree"].isremote(mykey) or \
658
				   tbz2name in portage.db[portage.root]["bintree"].invalids:
659
					# Get the tbz2
660
					if not portage.db[portage.root]["bintree"].remotepkgs.has_key(tbz2name):
661
						sys.stderr.write("\nThere are no packages available to satisfy "+str(mykey)+"\n\n")
662
						sys.exit(1)
663
					portage.db[portage.root]["bintree"].gettbz2(mykey)
664
				mytbz2=xpak.tbz2(portage.db[portage.root]["bintree"].getname(mykey))
665
				edepend["DEPEND"] =""
666
				edepend["RDEPEND"]=string.join(mytbz2.getelements("RDEPEND")," ")
667
				edepend["PDEPEND"]=string.join(mytbz2.getelements("PDEPEND")," ")
668
				edepend["CDEPEND"]=string.join(mytbz2.getelements("CDEPEND")," ")
669
				edepend["REBUILD"]=string.join(mytbz2.getelements("REBUILD")," ")
670
				edepend["SLOT"]   =mytbz2.getfile("SLOT",mypkgparts[2])
671
		elif mytype=="ebuild":
672
			try:
673
				#edepend=portage.portdb.aux_get(mykey,["DEPEND","RDEPEND"])
674
				for x in ["DEPEND","RDEPEND","PDEPEND","REBUILD"]:
675
					edepend[x]=string.join(portage.portdb.aux_get(mykey,[x]), " ")
676
			except (KeyError,IOError):
677
				print "emerge: create(): aux_get() error on",mykey+"; aborting..."
678
				sys.exit(1)
679
		mydep={}	
680
		mp=string.join(mybigkey)
681
682
		if myroot=="/":
683
			mydep["/"]=edepend["DEPEND"]+" "+edepend["RDEPEND"]
684
			if not self.select_dep("/",mydep["/"],myparent=mp):
685
				return 0
686
		else:
687
			mydep["/"]=edepend["DEPEND"]
688
			mydep[myroot]=edepend["RDEPEND"]
689
			if not self.select_dep("/",mydep["/"],myparent=mp):
690
				return 0
691
			elif not self.select_dep(myroot,mydep[myroot],myparent=mp):
692
				return 0
693
694
		if edepend.has_key("PDEPEND") and edepend["PDEPEND"]:
695
			# Post Depend -- Add to the list without a parent, as it depends
696
			# on a package being present AND must be built after that package.
697
			if not self.select_dep(myroot,edepend["PDEPEND"]):
698
				return 0
699
			
700
		return 1
701
			
702
	def select_files(self,myfiles):
703
		"given a list of .tbz2s, .ebuilds and deps, create the appropriate depgraph and return a favorite list"
704
		myfavorites=[]
705
		for x in myfiles:
706
			if x[-5:]==".tbz2":
707
				if not os.path.exists(x):
708
					if os.path.exists(portage.settings["PKGDIR"]+"/All/"+x):
709
						x=portage.settings["PKGDIR"]+"/All/"+x
710
					elif os.path.exists(portage.settings["PKGDIR"]+"/"+x):
711
						x=portage.settings["PKGDIR"]+"/"+x
712
					else:
713
						print "\n\n!!! Binary package '"+str(x)+"' does not exist."
714
						print "!!! Please ensure the tbz2 exists as specified.\n"
715
						sys.exit(1)
716
				mytbz2=xpak.tbz2(x)
717
				mykey=mytbz2.getelements("CATEGORY")[0]+"/"+os.path.basename(x)[:-5]
718
				if not self.create(["binary",portage.root,mykey],None,"--onlydeps" not in myopts):
719
					return (0,myfavorites)
720
				elif not "--oneshot" in myopts:
721
					myfavorites.append(mykey)
722
			elif x[-7:]==".ebuild":
723
				mykey=os.path.basename(os.path.abspath(x+"/../.."))+"/"+os.path.basename(x)[:-7]
724
				if not self.create(["ebuild",portage.root,mykey],None,"--onlydeps" not in myopts):
725
					return (0,myfavorites)
726
				elif not "--oneshot" in myopts:
727
					myfavorites.append(mykey)
728
			else:
729
				mykey=portage.dep_expand(x,portage.portdb)
730
				# select needs to return 0 on dep_check failure
731
				try:
732
					self.mysd=self.select_dep(portage.root,mykey,arg=x)
733
				except Exception, e:
734
					print "\n!!! Problem in",mykey,"dependencies."
735
					print "!!!",e
736
					sys.exit(1)
737
738
				if not self.mysd:
739
					return (0,myfavorites)
740
				elif not "--oneshot" in myopts:
741
					myfavorites.append(mykey)
742
743
		self.missingbins=0
744
		if "--usepkgonly" in myopts:
745
			for x in self.digraph.dict.keys():
746
				xs=string.split(x," ")
747
				if (xs[0] != "binary") and (xs[3]=="merge"):
748
					if self.missingbins == 0:
749
						print
750
					self.missingbins+=1
751
					print "Missing binary for:",xs[2]
752
753
		# We're true here unless we are missing binaries.
754
		return (not self.missingbins,myfavorites)
755
756
	def is_newer_ver_installed(self,myroot,pkg,pkgver):
757
		"if there is a version of pkg installed newer than pkgver, return it"
758
		vardbapi=portage.db[myroot]["vartree"].dbapi
759
760
		myslot=portage.portdb.aux_get(pkgver,["SLOT"])[0]
761
		alleb=portage.portdb.xmatch("match-all",pkg)
762
		while alleb:
763
			cand=portage.portdb.xmatch("bestmatch-list",pkg,mylist=alleb)
764
			if not cand:
765
				break
766
			curslot=portage.portdb.aux_get(cand,["SLOT"])[0]
767
			if (curslot==myslot) and vardbapi.cpv_exists(cand):
768
				# installed, is this package newer?
769
				if portage.pkgcmp(portage.catpkgsplit(pkgver)[1:], portage.catpkgsplit(cand)[1:]) < 0:
770
					return cand
771
				break
772
			alleb.remove(cand)
773
774
	def select_dep(self,myroot,depstring,myparent=None,arg=None):
775
		"given a dependency string, create the appropriate depgraph and return 1 on success and 0 on failure"
776
		if "--debug" in myopts:
777
			print
778
			print "Parent:   ",myparent
779
			print "Depstring:",depstring
780
		if not arg:
781
			#processing dependencies
782
			mycheck=portage.dep_check(depstring,self.mydbapi[myroot])
783
			if not mycheck[0]:
784
				return 0
785
			mymerge=mycheck[1]
786
		else:
787
			#we're processing a command-line argument; unconditionally merge it even if it's already merged
788
			mymerge=[depstring]
789
		if "--debug" in myopts:
790
			print "Candidates:",mymerge
791
		for x in mymerge:
792
			if x[0]=="!":
793
				#add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example)
794
				myk=["blocks",myroot,x[1:]]
795
			else:
796
				#We are not processing a blocker but a normal dependency
797
				myeb_pkg=None
798
				if ("--usepkg" in myopts):
799
					myeb_pkg=portage.db[portage.root]["bintree"].dep_bestmatch(x)
800
				
801
				myeb=None
802
				if ("--usepkgonly" not in myopts):
803
					myeb=portage.portdb.xmatch("bestmatch-visible",x)
804
				
805
				if (not myeb) and (not myeb_pkg):
806
					if not arg:
807
						xinfo='"'+x+'"'
808
					else:
809
						xinfo='"'+arg+'"'
810
					if myparent:
811
						xfrom = '(dependency required by '+green('"'+myparent.split()[2]+'"')+red(' ['+myparent.split()[0]+"])")
812
					alleb=portage.portdb.xmatch("match-all",x)
813
					if alleb:
814
						if "--usepkgonly" not in myopts:
815
							print "\n!!! "+red("all ebuilds that could satisfy ")+green(xinfo)+red(" have been masked.")
816
							if myparent:
817
								print     "!!!    "+red(xfrom)
818
						else:
819
							print "\n!!! "+red("There are no packages available to satisfy: ")+green(xinfo)
820
							print "!!! Either add a suitable binary package or compile from an ebuild."
821
					else:
822
						print "\nemerge: there are no masked or unmasked ebuilds to satisfy "+xinfo+"."
823
					return 0
824
825
				if "--debug" in myopts:
826
					print "ebuild:",myeb
827
					print "binpkg:",myeb_pkg
828
829
				if myeb and myeb_pkg:
830
					myeb_s     = portage.catpkgsplit(myeb)
831
					myeb_s     = [myeb_s[0]+"/"+myeb_s[1], myeb_s[2], myeb_s[3]]
832
					myeb_pkg_s = portage.catpkgsplit(myeb_pkg)
833
					myeb_pkg_s = [myeb_pkg_s[0]+"/"+myeb_pkg_s[1], myeb_pkg_s[2], myeb_pkg_s[3]]
834
					
835
					if portage.pkgcmp(myeb_s, myeb_pkg_s) > 0: # eb is newer than pkg
836
						myeb_pkg = None
837
					else:
838
						myeb = None
839
840
 				if "--upgradeonly" in myopts:
841
 					# Check that there isn't a newer version of this package already installed
842
 					cand=self.is_newer_ver_installed(myroot,x,myeb)
843
 					if cand:
844
 						myeb=cand
845
				
846
				if myeb:
847
					myk=["ebuild",myroot,myeb]
848
				elif myeb_pkg:
849
					myk=["binary",myroot,myeb_pkg]
850
				else:
851
					sys.stderr.write("!!! Confused... Don't know what I'm using for dependency info. :(\n")
852
					sys.exit(1)
853
854
				#if "--usepkg" in myopts:
855
				#	#If we want to use packages, see if we have a pre-built one...
856
				#	mypk=portage.db["/"]["bintree"].dbapi.match(x)
857
				#	if myeb in mypk:
858
				#		#Use it only if it's exactly the version we want.
859
				#		myk=["binary",myroot,myeb]
860
				#	else:
861
				#		myk=["ebuild",myroot,myeb]
862
				#else:
863
				#	myk=["ebuild",myroot,myeb]
864
			if myparent:
865
				#we are a dependency, so we want to be unconditionally added
866
				if not self.create(myk,myparent):
867
					return 0
868
			else:
869
				#if mysource is not set, then we are a command-line dependency and should not be added
870
				#if --onlydeps is specified.
871
				if not self.create(myk,myparent,"--onlydeps" not in myopts):
872
					return 0
873
874
		if "--debug" in myopts:
875
			print "Exiting...",myparent
876
		return 1
877
		
878
879
	def altlist(self):
880
		mygraph=self.digraph.copy()
881
		dolist=["/"]
882
		retlist=[]
883
		for x in portage.db.keys():
884
			portage.db[x]["merge"]=[]
885
			if x not in dolist:
886
				dolist.append(x)
887
		while (not mygraph.empty()):
888
			mycurkey=mygraph.firstzero()
889
			if not mycurkey:
890
				print "!!! Error: circular dependencies:"
891
				print
892
				for x in mygraph.dict.keys():
893
					for y in mygraph.dict[x][1]:
894
						print y,"depends on",x
895
				print
896
				sys.exit(1)
897
			splitski=string.split(mycurkey)
898
			#I'm not sure of the significance of the following lines (vestigal?) so I'm commenting 'em out.
899
			#These lines remove already-merged things from our alt-list
900
			#if "--update" in myopts:
901
			#	if not portage.db["/"]["vartree"].exists_specific(splitski[2]):
902
			#		portage.db["/"]["merge"].append(splitski)
903
			#else:
904
			portage.db[splitski[1]]["merge"].append(splitski)	
905
			mygraph.delnode(mycurkey)
906
		for x in dolist:
907
			for y in portage.db[x]["merge"]:
908
				retlist.append(y)
909
		return retlist
910
911
	def xcreate(self,mode="system"):
912
		global syslist
913
		if mode=="system":
914
			mylist=syslist
915
		else:
916
			#world mode
917
			worldlist=getlist("world")
918
			sysdict=genericdict(syslist)
919
			worlddict=genericdict(worldlist)
920
			#we're effectively upgrading sysdict to contain all new deps from worlddict
921
			for x in worlddict.keys():
922
				#only add the world node if the package is:
923
				#actually installed -- this prevents the remerging of already unmerged packages when we do a world --update;
924
				#actually available -- this prevents emerge from bombing out due to no match being found (we want a silent ignore)
925
				if "empty" in myparams:
926
					if portage.db["/"]["vartree"].dbapi.match(x):
927
						sysdict[x]=worlddict[x]
928
				elif portage.db[portage.root]["vartree"].dbapi.match(x):
929
					#package is installed
930
					sysdict[x]=worlddict[x]
931
				else:
932
					print "\n*** Package in world file is not installed: "+x
933
			mylist=[]
934
			for x in sysdict.keys():
935
				mylist.append(sysdict[x])
936
937
		for mydep in mylist:	
938
			myeb=portage.portdb.xmatch("bestmatch-visible",mydep)
939
			if not myeb:
940
				#this is an unavailable world entry; just continue
941
				continue
942
943
			if "--upgradeonly" in myopts:
944
				cand=self.is_newer_ver_installed(portage.root,mydep,myeb)
945
				if cand:
946
					myeb=cand
947
948
			#THIS NEXT BUNCH OF CODE NEEDS TO BE REPLACED TO SUPPORT WORLD ANTI-DEPS
949
			#if mydep2[0]=="!":, etc.
950
			if "--usepkg" in myopts:
951
				mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep)
952
				if myeb==mypk:
953
					myk=["binary",portage.root,mypk]
954
				elif "--usepkgonly" in myopts:
955
					self.missingbins += [myeb]
956
					myk=["binary",portage.root,myeb]
957
					#print "mypk:",mypk
958
					#print "myeb:",myeb
959
				else:
960
					myk=["ebuild",portage.root,myeb]
961
			else:
962
				myk=["ebuild",portage.root,myeb]
963
			if not self.create(myk):
964
				print
965
				print "!!! Problem with",myk[0],myk[2]
966
				print "!!! Possibly a DEPEND/*DEPEND problem."
967
				print
968
				return 0
969
		return 1
970
971
	def match(self,mydep,myroot=portage.root,mykey=None):
972
		# support mutual exclusive deps
973
		mydep2=mydep
974
		if mydep2[0]=="!":
975
			mydep2=mydep[1:]
976
977
		if mydep[0]=="!":
978
			#add our blocker; it will be ignored later if necessary (if we are remerging the same pkg, for example)
979
			myk="blocks "+myroot+" "+mydep2
980
		else:
981
			myeb=portage.db[portage.root]["porttree"].dep_bestmatch(mydep2)
982
			if not myeb:
983
				if not mykey:
984
					print "\n!!! Error: couldn't find match for",mydep
985
				else:
986
					print "\n!!! Error: couldn't find match for",mydep,"in",mykey
987
				print
988
				sys.exit(1)
989
990
			if "--usepkg" in myopts:
991
				mypk=portage.db[portage.root]["bintree"].dep_bestmatch(mydep)
992
				if myeb==mypk:
993
					myk="binary "+portage.root+" "+mypk
994
				else:
995
					myk="ebuild "+myroot+" "+myeb
996
			else:
997
				myk="ebuild "+myroot+" "+myeb
998
999
		return myk	
1000
	
1001
	def display(self,mylist):
1002
		changelogs=[]
1003
		for x in mylist:
1004
			#print x
1005
			fetch=" "
1006
			
1007
			if x[0]=="blocks":
1008
				addl=""+red("B")+"  "+fetch+"  "
1009
				resolved=portage.db[x[1]]["vartree"].resolve_key(x[2])
1010
				print "["+x[0]+" "+addl+"]",red(resolved),
1011
				if resolved!=x[2]:
1012
					if x[3]:
1013
						print red("(\""+x[2]+"\" from pkg "+x[3]+")")
1014
					else:
1015
						print red("(\""+x[2]+"\")")
1016
				else:
1017
					if x[3]:
1018
						print red("(from pkg "+x[3]+")")
1019
					else:
1020
						print
1021
			else:
1022
				if x[3]=="nomerge":
1023
					continue
1024
1025
				if ("fetch" in string.split(portage.portdb.aux_get(x[2],["RESTRICT"])[0])):
1026
					fetch = red("F")
1027
1028
				#we need to use "--emptrytree" testing here rather than "empty" param testing because "empty"
1029
				#param is used for -u, where you still *do* want to see when something is being upgraded.
1030
				myoldbest=""
1031
				if (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific(x[2]):
1032
					addl="  "+yellow("R")+fetch+"  "
1033
				elif (not "--emptytree" in myopts) and portage.db[x[1]]["vartree"].exists_specific_cat(x[2]):
1034
					myoldbest=portage.best(portage.db[x[1]]["vartree"].dbapi.match(portage.pkgsplit(x[2])[0]))
1035
1036
					try:
1037
						myoldslot=portage.db[portage.root]["vartree"].getslot(myoldbest)
1038
					except:
1039
						myoldslot=None
1040
					mynewslot=portage.portdb.aux_get(x[2],["SLOT"])[0]
1041
1042
					addl="   "+fetch
1043
					if (myoldslot==mynewslot) and portage.pkgcmp(portage.pkgsplit(x[2]), portage.pkgsplit(myoldbest)) < 0:
1044
						addl+=turquoise("U")+blue("D")
1045
					else:
1046
						if myoldslot:
1047
							addl+=turquoise("U")+" "
1048
						else:
1049
							addl+=turquoise("U")+blue("-")
1050
1051
					if "--changelog" in myopts:
1052
		 				changelogs.extend(self.calc_changelog(
1053
							portage.portdb.findname(x[2]),
1054
							portage.db["/"]["vartree"].dep_bestmatch('/'.join(portage.catpkgsplit(x[2])[:2])),
1055
							x[2]
1056
							))
1057
				else:
1058
					addl=" "+green("N")+" "+fetch+"  "
1059
				if myoldbest:
1060
					myoldbest=portage.pkgsplit(myoldbest)[1]+"-"+portage.pkgsplit(myoldbest)[2]
1061
					if myoldbest[-3:]=="-r0":
1062
						myoldbest=myoldbest[:-3]
1063
					myoldbest=blue("["+myoldbest+"]")
1064
1065
				iuse=""
1066
				if "--verbose" in myopts:
1067
					for ebuild_iuse in string.split(portage.portdb.aux_get(x[2],["IUSE"])[0], " "):
1068
						try:
1069
							if (portage.usesplit.index(ebuild_iuse) >= 0) :
1070
								iuse=iuse+red("+"+ebuild_iuse)+" "
1071
						except ValueError:
1072
							if ebuild_iuse != "":
1073
								iuse=iuse+blue("-"+ebuild_iuse)+" "
1074
1075
				xs=portage.pkgsplit(x[2])
1076
				if xs[2]=="r0":
1077
					xs[2]=""
1078
				else:
1079
					xs[2]="-"+xs[2]
1080
1081
				if portage.settings.has_key("COLUMNWIDTH"):
1082
					mywidth=int(portage.settings["COLUMNWIDTH"])
1083
				else:
1084
					mywidth=130
1085
				oldlp=mywidth-30
1086
				newlp=oldlp-30
1087
				
1088
				if x[1]!="/":
1089
					if "--columns" in myopts:
1090
						myprint="["+x[0]+" "+addl+"] "+darkgreen(xs[0])
1091
						if (newlp-len(myprint)) > 0:
1092
							myprint=myprint+(" "*(newlp-len(myprint)))
1093
						myprint=myprint+"["+darkblue(xs[1]+xs[2])+"] "
1094
						if (oldlp-len(myprint)) > 0:
1095
							myprint=myprint+" "*(oldlp-len(myprint))
1096
						myprint=myprint+myoldbest
1097
						myprint=myprint+darkgreen("  to "+x[1])+" "+iuse
1098
					else:
1099
						myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+darkgreen("to "+x[1])+" "+iuse
1100
				else:
1101
					if "--columns" in myopts:
1102
						myprint="["+x[0]+" "+addl+"] "+darkgreen(xs[0])
1103
						if (newlp-len(myprint)) > 0:
1104
							myprint=myprint+(" "*(newlp-len(myprint)))
1105
						myprint=myprint+green(" ["+xs[1]+xs[2]+"] ")
1106
						if (oldlp-len(myprint)) > 0:
1107
							myprint=myprint+(" "*(oldlp-len(myprint)))
1108
						myprint=myprint+myoldbest+"  "+iuse
1109
					else:
1110
						myprint="["+x[0]+" "+addl+"] "+darkgreen(x[2])+" "+myoldbest+" "+iuse
1111
				print myprint
1112
1113
			mysplit=portage.pkgsplit(x[2])
1114
			# XXX mysplit _can_ be None.... Why?
1115
			if mysplit and (len(mysplit)==3):
1116
				if "--emptytree" not in myopts:
1117
					if mysplit[0]=="sys-apps/portage":
1118
						if mysplit[1]+mysplit[2]!=portage.VERSION:
1119
							if mylist.index(x)<len(mylist)-1:
1120
								print red("*** Portage will stop merging at this point and reload itself,")
1121
								print red("    recalculate dependencies, and complete the merge.")
1122
								if "--update" not in myopts:
1123
									print darkgreen("    You may avoid the remerging of packages by updating portage on its own.")
1124
								print
1125
				else:
1126
					if mysplit[0]=="sys-apps/portage" and ("--emptytree" in myopts):
1127
						if mysplit[1]+mysplit[2]!=portage.VERSION:
1128
							print red("***")+" Please update portage to the above version before proceeding."
1129
							print "    Failure to do so may result in failed or improper merges."
1130
							print "    A simple '"+green("emerge -u portage")+"' is sufficient."
1131
							print
1132
			del mysplit
1133
1134
 		if "--changelog" in myopts:
1135
 			print
1136
 			for revision,text in changelogs:
1137
 				print bold('*'+revision)
1138
 				sys.stdout.write(text)
1139
1140
 	def calc_changelog(self,ebuildpath,current,next):
1141
 		current = '-'.join(portage.catpkgsplit(current)[1:])
1142
 		if current.endswith('-r0'): current = current[:-3]
1143
 		next = '-'.join(portage.catpkgsplit(next)[1:])
1144
 		if next.endswith('-r0'): next = next[:-3]
1145
 		changelogpath = os.path.join(os.path.split(ebuildpath)[0],'ChangeLog')
1146
		try:
1147
	 		changelog = open(changelogpath).read()
1148
		except:
1149
			return []
1150
 		divisions = self.find_changelog_tags(changelog)
1151
 		#print 'XX from',current,'to',next
1152
 		#for div,text in divisions: print 'XX',div
1153
 		# skip entries for all revisions above the one we are about to emerge
1154
 		for i in range(len(divisions)):
1155
 			if divisions[i][0]==next:
1156
 				divisions = divisions[i:]
1157
 				break
1158
 		# find out how many entries we are going to display
1159
 		for i in range(len(divisions)):
1160
 			if divisions[i][0]==current:
1161
 				divisions = divisions[:i]
1162
 				break
1163
 		else:
1164
 		    # couldnt find the current revision in the list. display nothing
1165
 			return []
1166
 		return divisions
1167
 
1168
 	def find_changelog_tags(self,changelog):
1169
 		divs = []
1170
 		release = None
1171
 		while 1:
1172
 			match = re.search(r'^\*\ ?([-a-zA-Z0-9_.]*)(?:\ .*)?\n',changelog,re.M)
1173
 			if match is None:                                                                            
1174
 				if release is not None:
1175
 					divs.append((release,changelog))
1176
 				return divs
1177
 			if release is not None:
1178
 				divs.append((release,changelog[:match.start()]))
1179
 			changelog = changelog[match.end():]
1180
 			release = match.group(1)
1181
 			if release.endswith('.ebuild'):
1182
 				release = release[:-7]
1183
 			if release.endswith('-r0'):
1184
 				release = release[:-3]
1185
1186
	def outdated(self):
1187
		return self.outdatedpackages
1188
				
1189
	def merge(self,mylist):
1190
		returnme=0
1191
		mymergelist=[]
1192
1193
		#check for blocking dependencies
1194
		if ("--fetchonly" not in myopts) and ("--buildpkgonly" not in myopts):
1195
			for x in mylist:
1196
				if x[0]=="blocks":
1197
					print "\n!!! Error: the "+x[2]+" package conflicts with another package."
1198
					print   "!!!        both can't be installed on the same system together."
1199
					print   "!!!        Please use 'emerge --pretend' to determine blockers."
1200
					print
1201
					if ("--pretend" not in myopts):
1202
						sys.exit(1)
1203
1204
		if ("--resume" in myopts):
1205
			# We're resuming.
1206
			print green("*** Resuming merge...")
1207
			emergelog(" *** Resuming merge...")
1208
			mymergelist=portage.mtimedb["resume"]["mergelist"][:]
1209
			if ("--skipfirst" in myopts) and mymergelist:
1210
				del mymergelist[0]
1211
		else:
1212
			myfavs=portage.grabfile(portage.root+"var/cache/edb/world")
1213
			myfavdict=genericdict(myfavs)
1214
			mysysdict=genericdict(syslist)
1215
			for x in range(len(mylist)):
1216
				if mylist[x][3]!="nomerge":
1217
					# Add to the mergelist
1218
					mymergelist.append(mylist[x])
1219
				else:
1220
					# Add to the world file. Since we won't be able to later.
1221
					myfavkey=portage.cpv_getkey(mylist[x][2])
1222
					if (not "--fetchonly" in myopts) and (myfavkey in favorites):
1223
						#don't record if already in system profile or already recorded
1224
						if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
1225
							#we don't have a favorites entry for this package yet; add one
1226
							myfavdict[myfavkey]=myfavkey
1227
							print ">>> Recording",myfavkey,"in \"world\" favorites file..."
1228
			if not "--fetchonly" in myopts:
1229
				portage.writedict(myfavdict,portage.root+"var/cache/edb/world",writekey=0)
1230
1231
			portage.mtimedb["resume"]["mergelist"]=mymergelist[:]
1232
1233
		# We need to yank the harmful-to-new-builds settings from features.
1234
		myorigfeat=portage.settings["FEATURES"]
1235
		myfeat=myorigfeat.split()
1236
		while ("keeptemp" in myfeat):
1237
			del myfeat[myfeat.index("keeptemp")]
1238
		while ("keepwork" in myfeat):
1239
			del myfeat[myfeat.index("keepwork")]
1240
		portage.settings["FEATURES"]=string.join(myfeat)
1241
1242
		mergecount=0
1243
		for x in mymergelist:
1244
			mergecount+=1
1245
			myroot=x[1]
1246
			pkgindex=2
1247
			if x[0]=="blocks":
1248
				pkgindex=3
1249
			y=portage.portdb.findname(x[pkgindex])
1250
			if not "--pretend" in myopts:
1251
				print ">>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+")",x[pkgindex],"to",x[1]
1252
				emergelog(" >>> emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[pkgindex]+" to "+x[1])
1253
			if x[0] in ["ebuild","blocks"]:
1254
				if ("--fetchonly" in myopts) or (x[0]=="blocks"):
1255
					retval=portage.doebuild(y,"fetch",myroot,edebug,("--pretend" in myopts),fetchonly=1)
1256
					if retval:
1257
						print
1258
						print "!!! Fetch for",y,"failed, continuing..."
1259
						print	
1260
						returnme=1
1261
					continue
1262
				elif "--buildpkg" in myopts:
1263
					#create pkg, then merge pkg
1264
					emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+y+")")
1265
					retval=portage.doebuild(y,"clean",myroot,edebug)
1266
					if retval:
1267
						sys.exit(1)
1268
					portage.settings["FEATURES"]=myorigfeat # Put back flags.
1269
					emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Packaging ("+y+")")
1270
					retval=portage.doebuild(y,"package",myroot,edebug)
1271
					if retval:
1272
						sys.exit(1)
1273
					#dynamically update our database
1274
					if "--buildpkgonly" not in myopts:
1275
						portage.db[portage.root]["bintree"].inject(x[2])
1276
						mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
1277
						emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging ("+y+")")
1278
						retval=portage.pkgmerge(mytbz2,myroot)
1279
						if retval==None:
1280
							sys.exit(1)
1281
				else:
1282
					emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Cleaning ("+y+")")
1283
					retval=portage.doebuild(y,"clean",myroot,edebug)
1284
					if retval:
1285
						sys.exit(1)
1286
					portage.settings["FEATURES"]=myorigfeat # Put back flags.
1287
					emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Compiling/Merging ("+y+")")
1288
					retval=portage.doebuild(y,"merge",myroot,edebug)
1289
					if retval:
1290
						sys.exit(1)
1291
					#dynamically update our database	
1292
			elif x[0]=="binary":
1293
				#merge the tbz2
1294
				mytbz2=portage.db[portage.root]["bintree"].getname(x[2])
1295
				emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Merging Binary ("+y+")")
1296
				retval=portage.pkgmerge(mytbz2,x[1])
1297
				if retval==None:
1298
					sys.exit(1)
1299
				#need to check for errors
1300
			if "--buildpkgonly" not in myopts:
1301
				portage.db[x[1]]["vartree"].inject(x[2])
1302
				myfavkey=portage.cpv_getkey(x[2])
1303
				if (not "--fetchonly" in myopts) and (myfavkey in favorites):
1304
					myfavs=portage.grabfile(myroot+"var/cache/edb/world")
1305
					myfavdict=genericdict(myfavs)
1306
					mysysdict=genericdict(syslist)
1307
					#don't record if already in system profile or already recorded
1308
					if (not mysysdict.has_key(myfavkey)) and (not myfavdict.has_key(myfavkey)):
1309
						#we don't have a favorites entry for this package yet; add one
1310
						myfavdict[myfavkey]=myfavkey
1311
						print ">>> Recording",myfavkey,"in \"world\" favorites file..."
1312
						emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Updating world file ("+y+")")
1313
						portage.writedict(myfavdict,myroot+"var/cache/edb/world",writekey=0)
1314
1315
				if ("noclean" not in portage.features) and (x[0] != "binary"):
1316
					emergelog(" === ("+str(mergecount)+" of "+str(len(mymergelist))+") Post-Build Cleaning ("+y+")")
1317
					retval=portage.doebuild(y,"clean",myroot,edebug)
1318
					if retval:
1319
						sys.exit(1)
1320
			
1321
				if ("--pretend" not in myopts) and ("--fetchonly" not in myopts):
1322
					# Clean the old package that we have merged over top of it.
1323
					if portage.settings.has_key("AUTOCLEAN") and (portage.settings["AUTOCLEAN"]=="yes"):
1324
						xsplit=portage.pkgsplit(x[2])
1325
						emergelog(" >>> AUTOCLEAN: "+xsplit[0])
1326
						if not unmerge("clean", [xsplit[0]]):
1327
							emergelog(" --- AUTOCLEAN: Nothing unmerged.")
1328
1329
					# Figure out if we need a restart.
1330
					mysplit=portage.pkgsplit(x[2])
1331
					if mysplit[0]=="sys-apps/portage":
1332
						myver=mysplit[1]+"-"+mysplit[2]
1333
						if myver[-3:]=='-r0':
1334
							myver=myver[:-3]
1335
						if myver!=portage.VERSION:
1336
							if len(mymergelist) > mergecount:
1337
								myargv=sys.argv
1338
								myr=0
1339
								for myra in range(len(myargv)):
1340
									if myargv[myr][0:len("portage")]=="portage":
1341
										del myargv[myr]
1342
										myr-=1
1343
									if myargv[myr][0:len("sys-apps/portage")]=="sys-apps/portage":
1344
										del myargv[myr]
1345
										myr-=1
1346
									myr+=1
1347
								emergelog(" *** RESTARTING emerge via exec() after change of portage version.")
1348
								portage.portageexit()
1349
								os.execv("/usr/lib/portage/bin/emerge", myargv)
1350
1351
			if ("--pretend" not in myopts) and ("--fetchonly" not in myopts):
1352
				emergelog(" ::: completed emerge ("+str(mergecount)+" of "+str(len(mymergelist))+") "+x[2]+" to "+x[1])
1353
			
1354
			# Unsafe for parallel merges
1355
			del portage.mtimedb["resume"]["mergelist"][0]
1356
1357
		emergelog(" *** Finished. Cleaning up...")
1358
1359
		# We're out of the loop... We're done. Delete the resume data.
1360
		if portage.mtimedb.has_key("resume"):
1361
			del portage.mtimedb["resume"]
1362
1363
		if ("--pretend" not in myopts):
1364
			if ("--fetchonly" not in myopts):
1365
				if (mergecount>0):
1366
					portage.env_update()
1367
1368
		#by doing an exit this way, --fetchonly can continue to try to
1369
		#fetch everything even if a particular download fails.
1370
		if "--fetchonly" in myopts:
1371
			if returnme:
1372
				print "\n\n!!! Some fetch errors were encountered.  Please see above for details.\n\n"
1373
				sys.exit(returnme)
1374
			else:
1375
				sys.exit(0)
1376
1377
def unmerge(unmerge_action, unmerge_files):
1378
	candidate_catpkgs=[]
1379
	global_unmerge=0
1380
	
1381
	if not unmerge_files or "world" in unmerge_files or "system" in unmerge_files:
1382
		if "unmerge"==unmerge_action:
1383
			print
1384
			print bold("emerge unmerge")+" can only be used with specific package names, not with "+bold("world")+" or"
1385
			print bold("system")+" targets."
1386
			print
1387
			return 0
1388
		else:
1389
			global_unmerge=1
1390
	
1391
	localtree=portage.db[portage.root]["vartree"]
1392
	# process all arguments and add all valid db entries to candidate_catpkgs
1393
	if global_unmerge:
1394
		if not unmerge_files or "world" in unmerge_files:
1395
			candidate_catpkgs.extend(localtree.getallnodes())	
1396
		elif "system" in unmerge_files:
1397
			candidate_catpkgs.extend(getlist("system"))
1398
	else:
1399
		#we've got command-line arguments
1400
		if not unmerge_files:
1401
			print "\nNo packages to unmerge have been provided.\n"
1402
			return 0
1403
		for x in unmerge_files:
1404
			arg_parts=x.split('/')
1405
			if arg_parts[-1][-7:]!=".ebuild":
1406
				#possible cat/pkg or dep; treat as such
1407
				candidate_catpkgs.append(x)
1408
			elif unmerge_action in ["prune","clean"]:
1409
				print "\n!!! Prune and clean do not accept individual ebuilds as arguments;\n    skipping.\n"
1410
				continue
1411
			else:
1412
				# it appears that the user is specifying an installed ebuild and we're in "unmerge" mode, so it's
1413
				# ok.
1414
				if not os.path.exists(x):
1415
					print "\n!!! The path '"+x+"' doesn't exist.\n"
1416
					return 0
1417
				absx=os.path.abspath(x)
1418
				spabsx=absx.split("/")
1419
				if absx[:12]!="/var/db/pkg/" or len(spabsx)!=7:
1420
					print spabsx
1421
					print absx
1422
					print "\n!!!",x,"is not inside /var/db/pkg; aborting.\n"
1423
					return 0
1424
				candidate_catpkgs.append("="+spabsx[4]+"/"+spabsx[5])
1425
1426
	if "--pretend" in myopts:
1427
		print darkgreen("\n>>> These are the packages that I would unmerge:")
1428
	
1429
	pkgmap={}
1430
	numselected=0
1431
	for x in candidate_catpkgs:
1432
		#cycle through all our candidate deps and determine what will and will not get unmerged
1433
		mymatch=localtree.dep_match(x)
1434
		if not mymatch and x[0] not in "<>=~":
1435
			#add a "=" if missing
1436
			mymatch=localtree.dep_match("="+x)
1437
		if not mymatch:
1438
			print "\n!!! Couldn't find match for",white(x)
1439
			continue
1440
		mykey=portage.key_expand(portage.dep_getkey(mymatch[0]),portage.db["/"]["vartree"].dbapi)
1441
		if not pkgmap.has_key(mykey):
1442
			pkgmap[mykey]={"protected":[], "selected":[], "omitted":[] }
1443
		if unmerge_action=="unmerge":
1444
				for y in mymatch:
1445
					if not y in pkgmap[mykey]["selected"]:
1446
						pkgmap[mykey]["selected"].append(y)
1447
						numselected=numselected+len(mymatch)
1448
		else:
1449
			#unmerge_action in ["prune", clean"]
1450
			slotmap={}
1451
			for mypkg in mymatch:
1452
				if unmerge_action=="clean":
1453
					myslot=localtree.getslot(mypkg)
1454
				else:
1455
					#since we're pruning, we don't care about slots and put all the pkgs in together
1456
					myslot=0
1457
				if not slotmap.has_key(myslot):
1458
					slotmap[myslot]={}
1459
				slotmap[myslot][localtree.dbapi.cpv_counter(mypkg)]=mypkg
1460
			for myslot in slotmap.keys():
1461
				counterkeys=slotmap[myslot].keys()
1462
				counterkeys.sort()
1463
				if not counterkeys:
1464
					continue
1465
				counterkeys.sort()
1466
				pkgmap[mykey]["protected"].append(slotmap[myslot][counterkeys[-1]])
1467
				del counterkeys[-1]
1468
				#be pretty and get them in order of merge:
1469
				for ckey in counterkeys:
1470
					pkgmap[mykey]["selected"].append(slotmap[myslot][ckey])
1471
					numselected=numselected+1
1472
				#ok, now the last-merged package is protected, and the rest are selected
1473
	if global_unmerge and not numselected:
1474
		print "\n>>> No outdated packages were found on your system.\n"
1475
		return 0
1476
1477
	if not numselected:
1478
		print "\n>>>",unmerge_action+": No packages selected for removal.\n"
1479
		return 0
1480
1481
	for x in candidate_catpkgs:
1482
		for y in localtree.dep_nomatch(mymatch[0]):
1483
			if y not in pkgmap[mykey]["omitted"] and \
1484
			   y not in pkgmap[mykey]["selected"] and \
1485
				 y not in pkgmap[mykey]["protected"]:
1486
				pkgmap[mykey]["omitted"].append(y)
1487
1488
	for x in pkgmap.keys():
1489
		if global_unmerge and not pkgmap[x]["selected"]:
1490
			#avoid cluttering the preview printout with stuff that isn't getting unmerged
1491
			continue
1492
		print "\n "+white(x)
1493
		for mytype in ["selected","protected","omitted"]:
1494
			print string.rjust(mytype,12)+":",
1495
			if pkgmap[x][mytype]:
1496
				for mypkg in pkgmap[x][mytype]:
1497
					mysplit=portage.catpkgsplit(mypkg)
1498
					if mysplit[3]=="r0":
1499
						myversion=mysplit[2]
1500
					else:
1501
						myversion=mysplit[2]+"-"+mysplit[3]
1502
					if mytype=="selected":
1503
						print red(myversion),
1504
					else:
1505
						print green(myversion),
1506
			else:
1507
					print "none",
1508
			print
1509
	
1510
	print "\n>>> Packages in",red("red"),"are slated for removal."
1511
	print ">>> Packages in",green("green"),"will not be removed.\n"
1512
	
1513
	if "--pretend" in myopts:
1514
		#we're done... return
1515
		return 0
1516
	#the real unmerging begins, after a short delay....
1517
	
1518
	if portage.settings["CLEAN_DELAY"]:
1519
		secs=string.atoi(portage.settings["CLEAN_DELAY"])
1520
	else:
1521
		secs=5
1522
	countdown(secs, ">>> Unmerging")
1523
1524
	for x in pkgmap.keys():
1525
		for y in pkgmap[x]["selected"]:
1526
			print ">>> Unmerging "+y+"..."
1527
			emergelog("=== Unmerging... ("+y+")")
1528
			mysplit=string.split(y,"/")
1529
			#unmerge...
1530
			retval=portage.unmerge(mysplit[0],mysplit[1],portage.root,unmerge_action not in ["clean","prune"])
1531
			if retval:
1532
				emergelog(" !!! unmerge FAILURE: "+y)
1533
			else:
1534
				emergelog(" >>> unmerge success: "+y)
1535
	#run ldconfig, etc...
1536
	portage.env_update()
1537
	if not numselected:
1538
		return 0
1539
	else:
1540
		return 1
1541
1542
1543
def post_emerge(retval=0):
1544
	auxpat=re.compile('^([^-]*)(-\d+)?\.info(-\d+)?(\.gz)?')	
1545
	os.chdir("/")
1546
	global myopts
1547
	print
1548
	if "--pretend" in myopts:
1549
		sys.exit(retval)
1550
1551
	emergelog(" *** exiting successfully.")
1552
	root=portage.root
1553
1554
	infodirs=[]
1555
	infodirs.extend(string.split(portage.settings["INFOPATH"], ":"))
1556
	infodirs.extend(string.split(portage.settings["INFODIR"], ":"))
1557
1558
	if os.path.exists("/usr/bin/install-info"):
1559
		regen=0
1560
		for z in infodirs:
1561
			if z=='':
1562
				continue
1563
			inforoot=root+z
1564
			if os.path.isdir(inforoot):
1565
				try:
1566
					infomtime=os.stat(inforoot)[ST_MTIME]
1567
				except:
1568
					infomtime=0
1569
1570
				if not portage.mtimedb.has_key("info"):
1571
					portage.mtimedb["info"]={}
1572
				if portage.mtimedb["info"].has_key(inforoot):
1573
					if portage.mtimedb["info"][inforoot]==infomtime:
1574
						pass
1575
					else:
1576
						portage.mtimedb["info"][inforoot]=0
1577
						regen+=1
1578
				else:
1579
					regen+=1
1580
1581
		if not regen:
1582
			print " "+green("*")+" GNU info directory index is up-to-date."
1583
		else:
1584
			print " "+green("*")+" Regenerating GNU info directory index..."
1585
1586
			icount=0
1587
			badcount=0
1588
			for z in infodirs:
1589
				if z=='':
1590
					continue
1591
				inforoot=root+z
1592
				if portage.mtimedb["info"].has_key(inforoot):
1593
					if portage.mtimedb["info"][inforoot]!=0:
1594
						continue
1595
				try:
1596
					os.rename(inforoot+"/dir",inforoot+"/dir.old")
1597
				except:
1598
					pass
1599
				
1600
				if not os.path.isdir(inforoot):
1601
					continue
1602
				for x in os.listdir(inforoot):
1603
					aux=auxpat.search(x)
1604
					if not aux:
1605
						continue
1606
					auxgroups=aux.groups()	
1607
					if not (auxgroups[1] or auxgroups[2]):
1608
						myso=commands.getstatusoutput("/usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
1609
						if myso!="":
1610
							badcount=badcount+1
1611
							if "--verbose" in myopts:
1612
								print myso
1613
						icount=icount+1
1614
				#update mtime so we can potentially avoid regenerating.
1615
				portage.mtimedb["info"][inforoot]=os.stat(inforoot)[ST_MTIME]
1616
1617
			if badcount:
1618
				if "--verbose" not in myopts:
1619
					print " "+yellow("*")+" Processed",icount,"info files:",badcount,"errors; run with "+green("emerge --verbose")+" to view errors."
1620
				else:
1621
					print " "+yellow("*")+" Processed",icount,"info files;",badcount,"errors."
1622
			else:
1623
				print " "+green("*")+" Processed",icount,"info files."
1624
1625
	if portage.settings["CONFIG_PROTECT"]:
1626
		#number of directories with some protect files in them
1627
		procount=0
1628
		for x in string.split(portage.settings["CONFIG_PROTECT"]):
1629
			if os.path.isdir(x):
1630
				a=commands.getstatusoutput("cd "+x+"; find . -iname '._cfg????_*'")
1631
				if a[0]!=0:
1632
					print " "+red("*")+" error scanning",x
1633
				else:
1634
					files=string.split(a[1])
1635
					if files:
1636
						procount=procount+1
1637
						print " "+yellow("* IMPORTANT:")+"",len(files),"config files in",x,"need updating."
1638
		if procount:
1639
			#print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
1640
			print " "+yellow("*")+" Type "+green("emerge --help config")+" to learn how to update config files."
1641
		print
38
		print
1642
	sys.exit(retval)
39
		print turquoise("Actions:")
1643
40
		print "       "+green("clean")+" ("+green("-c")+" short option)"
1644
# general options that should be taken into account before any action
41
		print "              Cleans the system by removing outdated packages which will not"
1645
if "--debug" in myopts:
42
		print "              remove functionalities or prevent your system from working."
1646
	edebug=1
43
		print "              The arguments can be in several different formats :"
1647
44
		print "              * world "
1648
if myaction in ["sync","rsync"] and (not "--help" in myopts):
45
		print "              * system "
1649
	if "--pretend" in myopts:
46
		print "              * /var/db/pkg/category/package-version, or"
1650
		print "emerge: the \"sync\" action does not support \"--pretend.\""
47
		print "              * 'dependency specification' (in single quotes is best.)"
1651
		sys.exit(1)
48
		print "              Here are a few examples of the dependency specification format:"
1652
49
		print "              "+bold("binutils")+" matches"
1653
	emergelog(" === rsync")
50
		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
1654
	myportdir=portage.settings["PORTDIR"]
51
		print "              "+bold(">binutils-2.11.90.0.7")+" matches"
1655
	if myportdir[-1]=="/":
52
		print "                  binutils-2.11.92.0.12.3-r1"
1656
		myportdir=myportdir[:-1]
53
		print "              "+bold("sys-devel/binutils")+" matches"
1657
	if not os.path.exists(myportdir):
54
		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
1658
		print ">>>",myportdir,"not found, creating it."
55
		print "              "+bold("sys-devel/binutils-2.11.90.0.7")+" matches"
1659
		os.makedirs(myportdir,0755)	
56
		print "                  binutils-2.11.90.0.7"
1660
	syncuri=string.rstrip(portage.settings["SYNC"])
57
		print "              "+bold(">sys-devel/binutils-2.11.90.0.7")+" matches"
1661
	os.umask(0022)
58
		print "                  binutils-2.11.92.0.12.3-r1"
1662
	if syncuri[:8]=="rsync://":
59
		print "              "+bold(">=sys-devel/binutils-2.11.90.0.7")+" matches"
1663
		if not os.path.exists("/usr/bin/rsync"):
60
		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
1664
			print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
61
		print "              "+bold("<sys-devel/binutils-2.11.92.0.12.3-r1")+" matches"
1665
			print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
62
		print "                  binutils-2.11.90.0.7"
1666
			sys.exit(1)
63
		print "              "+bold("<=sys-devel/binutils-2.11.92.0.12.3-r1")+" matches"
1667
		mytimeout=180
64
		print "                  binutils-2.11.90.0.7 and binutils-2.11.92.0.12.3-r1"
1668
		if portage.settings.has_key("RSYNC_TIMEOUT"):
1669
			try:
1670
				mytimeout=int(portage.settings["RSYNC_TIMEOUT"])
1671
			except:
1672
				pass
1673
		mycommand="/usr/bin/rsync -rlptDvz --progress --stats --delete --delete-after --timeout="+str(mytimeout)+" --exclude='distfiles/*' --exclude='local/*' --exclude='packages/*' "
1674
		if portage.settings.has_key("RSYNC_EXCLUDEFROM"):
1675
			if os.path.exists(portage.settings["RSYNC_EXCLUDEFROM"]):
1676
				mycommand=mycommand+" --exclude-from "+portage.settings["RSYNC_EXCLUDEFROM"]
1677
			else:
1678
				print "!!! RSYNC_EXCLUDEFROM specified, but file does not exist."
1679
		mycommand=mycommand+" "+syncuri+"/* "+myportdir
1680
		print ">>> starting rsync with "+syncuri+"..."
1681
		exitcode=portage.spawn(mycommand,free=1)
1682
		try:
1683
			maxretries=int(portage.settings["RSYNC_RETRIES"])
1684
		except:
1685
			maxretries=3 #default number of retries
1686
		retries=1
1687
		while (exitcode not in [0,1,2,3,4,11,14,20,21]) and (retries<=maxretries):
1688
			print "\n\n>>> Starting retry %d of %d"% (retries,maxretries)
1689
			time.sleep(11)
1690
			retries=retries+1
1691
			exitcode=portage.spawn(mycommand,free=1)
1692
		if (exitcode>0):
1693
			print
1694
			if exitcode==1:
1695
				print darkred("!!!")+green(" Rsync has reported that there is a syntax error. Please ensure")
1696
				print darkred("!!!")+green(" that your SYNC statement is proper.")
1697
				print darkred("!!!")+green(" SYNC="+portage.settings["SYNC"])
1698
			elif exitcode==11:
1699
				print darkred("!!!")+green(" Rsync has reported that there is a File IO error. Normally")
1700
				print darkred("!!!")+green(" this means your disk is full, but can be caused by corruption")
1701
				print darkred("!!!")+green(" on the filesystem that contains PORTDIR. Please investigate")
1702
				print darkred("!!!")+green(" and try again after the problem has been fixed.")
1703
				print darkred("!!!")+green(" PORTDIR="+portage.settings["PORTDIR"])
1704
			elif exitcode==20:
1705
				print darkred("!!!")+green(" Rsync was killed before it finished.")
1706
			else:
1707
				print darkred("!!!")+green(" Rsync has not successfully finished. It is recommended that you keep")
1708
				print darkred("!!!")+green(" trying or that you use the 'emerge-webrsync' option if you are unable")
1709
				print darkred("!!!")+green(" to use rsync due to firewall or other restrictions. This should be a")
1710
				print darkred("!!!")+green(" temporary problem unless complications exist with your network")
1711
				print darkred("!!!")+green(" (and possibly your system's filesystem) configuration.")
1712
			print
1713
			sys.exit(exitcode)
1714
	elif syncuri[:6]=="cvs://":
1715
		if not os.path.exists("/usr/bin/cvs"):
1716
			print "!!! /usr/bin/cvs does not exist, so rsync support is disabled."
1717
			print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
1718
			sys.exit(1)
1719
		cvsroot=syncuri[6:]
1720
		cvsdir=os.path.dirname(myportdir)
1721
		if not os.path.exists(myportdir+"/CVS"):
1722
			#initial checkout
1723
			print ">>> starting initial cvs checkout with "+syncuri+"..."
1724
			if not portage.spawn("cd "+cvsdir+"; cvs -d "+cvsroot+" login",free=1):
1725
				print "!!! cvs login error; exiting."
1726
				sys.exit(1)
1727
			if os.path.exists(cvsdir+"/gentoo-x86"):
1728
				print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
1729
				sys.exit(1)
1730
			if not portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co gentoo-x86",free=1):
1731
				print "!!! cvs checkout error; exiting."
1732
				sys.exit(1)
1733
			if cvsdir!=myportdir:
1734
				portage.movefile(cvsdir,portage.settings["PORTDIR"])
1735
			sys.exit(0)
1736
		else:
1737
			#cvs update
1738
			print ">>> starting cvs update with "+syncuri+"..."
1739
			sys.exit(portage.spawn("cd "+myportdir+"; cvs -z0 -q update -dP",free=1)) 
1740
	else:
1741
		print "!!! rsync setting: ",syncuri,"not recognized; exiting."
1742
		sys.exit(1)
1743
	if os.path.exists(myportdir+"/metadata/cache"):
1744
		print "\n>>> Updating Portage cache...  ",
1745
		os.umask(0002)
1746
		if os.path.exists(portage.dbcachedir):
1747
			portage.spawn("rm -Rf "+portage.dbcachedir,free=1)
1748
		try:
1749
			os.mkdir(portage.dbcachedir)
1750
			os.chown(portage.dbcachedir, os.getuid(), portage.portage_gid)
1751
			os.chmod(portage.dbcachedir, 06775)
1752
			os.umask(002)
1753
		except:
1754
			pass
1755
		mynodes=portage.portdb.cp_all()
1756
		for x in mynodes:
1757
			myxsplit=x.split("/")
1758
			if not os.path.exists(portage.dbcachedir+"/"+myxsplit[0]):
1759
				os.mkdir(portage.dbcachedir+"/"+myxsplit[0])
1760
				os.chown(portage.dbcachedir+"/"+myxsplit[0], os.getuid(), portage.portage_gid)
1761
				os.chmod(portage.dbcachedir+"/"+myxsplit[0], 06775)
1762
			mymatches=portage.portdb.xmatch("match-all",x)
1763
			for y in mymatches:
1764
				update_spinner()
1765
				try:
1766
					ignored=portage.portdb.aux_get(y,[],metacachedir=myportdir+"/metadata/cache")
1767
				except:
1768
					pass
1769
		portage.spawn("chmod -R g+rw "+portage.dbcachedir, free=1)
1770
		sys.stdout.write("\b\b  ...done!\n\n")
1771
		sys.stdout.flush()
1772
1773
	portage.portageexit()
1774
	reload(portage)
1775
	mybestpv=portage.portdb.xmatch("bestmatch-visible","sys-apps/portage")
1776
	mypvs=portage.best(portage.db[portage.root]["vartree"].dbapi.match("sys-apps/portage"))
1777
1778
	if(mybestpv != mypvs):
1779
		print
65
		print
1780
		print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
66
		print "       "+green("depclean")
1781
		print red(" * ")+"that you update portage now, before any other packages are updated."
67
		print "              Cleans the system by removing packages that are not associated"
1782
		print red(" * ")+"Please do so and then update "+bold("ALL")+" of your configuration files."
68
		print "              with explicitly merged packages. Depclean works by creating the"
69
		print "              full dependency tree from the system list and the world file,"
70
		print "              then comparing it to installed packages. Packages installed, but"
71
		print "              not associated with an explicit merge are listed as candidates"
72
		print "              for unmerging."+turquoise(" WARNING: This can seriously affect your system by")
73
		print "              "+turquoise("removing packages that may have been linked against, but due to")
74
		print "              "+turquoise("changes in USE flags may no longer be part of the dep tree. Use")
75
		print "              "+turquoise("caution when employing this feature.")
1783
		print
76
		print
1784
elif myaction=="regen":
77
		print "       "+green("info")
1785
	emergelog(" === regen")
78
		print "              Displays important portage variables that will be exported to"
1786
	#regenerate cache entries
79
		print "              ebuild.sh when performing merges. This information is useful"
1787
	print "Regenerating cache entries... ",
80
		print "              for bug reports and verification of settings. All settings in"
1788
	sys.stdout.flush()
81
		print "              make.{conf,globals,defaults} and the environment show up if"
1789
	mynodes=portage.portdb.cp_all()
82
		print "              run with the '--verbose' flag."
1790
	for x in mynodes:
1791
		mymatches=portage.portdb.xmatch("list-visible",x)
1792
		if not "--quiet" in myopts:
1793
			print "processing",x
1794
		for y in mymatches:
1795
			try:
1796
				foo=portage.portdb.aux_get(y,["DEPEND"])
1797
			except:
1798
				print "\nerror processing",y+", continuing..."
1799
	print "done!"
1800
# HELP action
1801
elif "config"==myaction:
1802
	emergelog(" === config")
1803
	print
1804
	print "Currently, \'config\' is a help option only."
1805
	print
1806
# INFO action
1807
elif "info"==myaction:
1808
	unameout=commands.getstatusoutput("/bin/uname -mrp")[1]
1809
	print getportageversion()
1810
	print "================================================================="
1811
	print "System uname: "+unameout
1812
1813
	output=commands.getstatusoutput("`which distcc` --version")
1814
	if not output[0]:
1815
		print str(string.split(output[1],"\n",1)[0]),
1816
		if "distcc" in portage.features:
1817
			print "[enabled]"
1818
		else:
1819
			print "[disabled]"
1820
1821
	output=commands.getstatusoutput("`which ccache` -V")
1822
	if not output[0]:
1823
		print str(string.split(output[1],"\n",1)[0]),
1824
		if "ccache" in portage.features:
1825
			print "[enabled]"
1826
		else:
1827
			print "[disabled]"
1828
1829
	if "--verbose" in myopts:
1830
		myvars=portage.settings.keys()
1831
	else:
1832
		myvars=['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
1833
				'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR', 'PORTDIR_OVERLAY',
1834
				'USE', 'COMPILER', 'CHOST', 'CFLAGS', 'CXXFLAGS','ACCEPT_KEYWORDS', 
1835
				'MAKEOPTS', 'AUTOCLEAN', 'SYNC', 'FEATURES']
1836
	myvars.sort()
1837
	for x in myvars:
1838
		print x+'="'+portage.settings[x]+'"'
1839
	#print portage.settings.keys()
1840
	print
1841
# SEARCH action
1842
elif "search"==myaction:
1843
	if not myfiles:
1844
		print "emerge: no search terms provided."
1845
	else:
1846
		searchinstance = search()
1847
		for mysearch in myfiles:
1848
			try:
1849
				searchinstance.execute(mysearch)
1850
			except re.error, comment:
1851
				print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
1852
				sys.exit(1)
1853
			searchinstance.output()
1854
elif "inject"==myaction:
1855
	if not myfiles:
1856
		print "emerge: please specify at least one cat/pkg-ver to inject."
1857
		sys.exit(1)
1858
	if "--pretend" in myopts:
1859
		print "emerge: the \"inject\" action does not support \"--pretend.\""
1860
		sys.exit(1)
1861
	for x in myfiles:
1862
		if x[0] in [">","<","=","!"]:
1863
			print "!!! '"+x+"' is an invalid specification."
1864
			print "!!! Must be 'category/package-version' with no other symbols."
1865
			print
1866
			continue
1867
		mycps=portage.catpkgsplit(x)
1868
		if (not mycps) or (mycps[0]=="null"):
1869
			print "!!!",x,"is not a specific cat/pkg-version, skipping..."
1870
			continue
1871
		if portage.db["/"]["vartree"].exists_specific(x):
1872
			print "!!! Not injecting",x+"; Package already exists."
1873
		else:
1874
			portage.db["/"]["vartree"].dbapi.cpv_inject(x)
1875
			print ">>> Injected",x+"."
1876
			emergelog(" === inject: "+x)
1877
elif "unmerge"==myaction or "prune"==myaction or "clean"==myaction:
1878
	if 1==unmerge(myaction, myfiles):
1879
		post_emerge()
1880
	
1881
elif "depclean"==myaction:
1882
	# Kill packages that aren't explicitly merged or are required as a
1883
	# dependency of another package. World file is explicit.
1884
1885
	print
1886
	print red("*** WARNING ***")+" : DEPCLEAN CAN  SERIOUSLY  IMPAIR YOUR SYSTEM. USE CAUTION."
1887
	print red("*** WARNING ***")+" : (Cancel: CONTROL-C) -- ALWAYS VERIFY ALL PACKAGES IN THE"
1888
	print red("*** WARNING ***")+" : CANDIDATE LIST FOR  SANITY  BEFORE  ALLOWING DEPCLEAN TO"
1889
	print red("*** WARNING ***")+" : UNMERGE ANY PACKAGES."
1890
	print red("*** WARNING ***")+" :"
1891
	print red("*** WARNING ***")+" : USE FLAGS MAY HAVE AN EXTREME EFFECT ON THE OUTPUT."
1892
	print red("*** WARNING ***")+" : SOME LIBRARIES MAY BE USED BY PACKAGES BUT ARE NOT"
1893
	print red("*** WARNING ***")+" : CONSIDERED TO BE A DEPEND DUE TO USE FLAG SETTINGS."
1894
	print red("*** WARNING ***")+" :"
1895
	print red("*** WARNING ***")+" : Packages  in the list  that are  desired  may be added"
1896
	print red("*** WARNING ***")+" : directly to the world file to cause them to be ignored"
1897
	print red("*** WARNING ***")+" : by depclean and maintained in the future. BREAKAGES DUE"
1898
	print red("*** WARNING ***")+" : TO UNMERGING AN  ==IN-USE LIBRARY==  MAY BE REPAIRED BY"
1899
	print red("*** WARNING ***")+" : MERGING  *** THE PACKAGE THAT COMPLAINS ***  ABOUT THE"
1900
	print red("*** WARNING ***")+" : MISSING LIBRARY."
1901
	print
1902
	if not "--pretend" in myopts:
1903
		countdown(10, ">>> Depclean")
1904
		emergelog(" >>> depclean")
1905
1906
	mydepgraph=depgraph(myaction,myopts)
1907
	syslist=getlist("system")
1908
	worldlist=getlist("world")
1909
1910
	print "Calculating",myaction,"dependencies  ",
1911
	if not mydepgraph.xcreate("world"):
1912
		print "\n!!! Failed to create deptree."
1913
		sys.exit(1)
1914
	print "\b\b ... done!"
1915
1916
	if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
1917
		sys.stderr.write(red("The following binaries are not available for merging...\n"))
1918
		for x in mydepgraph.missingbins:
1919
			sys.stderr.write("   "+str(x)+"\n")
1920
		sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
1921
		sys.exit(1)
1922
1923
	alldeps=mydepgraph.digraph.allnodes()
1924
	myvarlist=portage.vardbapi(portage.root).cp_all()
1925
1926
	if not syslist:
1927
		print "!!! You have no system list. Cannot determine system from world."
1928
	if not worldlist:
1929
		print "!!! You have no world file. Cannot determine explicit merges."
1930
	if not myvarlist:
1931
		print "!!! You have no /var/db tree. This is a problem."
1932
	if not alldeps:
1933
		print "!!! You have no dependencies. Impossible. Bug."
1934
1935
	if not (syslist and worldlist and myvarlist and alldeps):
1936
		print
83
		print
1937
		sys.exit(1)
84
		print "       "+green("inject")+" ("+green("-i")+" short option)"
1938
85
		print "              Add a stub entry for a package so that Portage thinks that it's"
1939
	reallist=[]
86
		print "              installed when it really isn't.  Handy if you roll your own"
1940
	for x in alldeps:
87
		print "              packages.  Example: "
1941
		myparts=portage.catpkgsplit(string.split(x)[2])
88
		#NOTE: this next line *needs* the "sys-kernel/"; *please* don't remove it!
1942
		if not myparts:
89
		print "              "+bold("emerge inject sys-kernel/gentoo-sources-2.4.19")
1943
			sys.stderr.write(
90
		print
1944
			  red("!!! There appears to be a problem with the following package:\n")+
91
		print "       "+green("prune")+" ("+green("-P")+" short option)"
1945
				red("!!! "+str(string.split(x)[2])+"\n\n")+
92
		print "              "+turquoise("WARNING: This action can remove important packages!")
1946
				    "!!! Please ensure that blocking/conflicting packages are not merged."+
93
		print "              Removes all older versions of a package from your system."
1947
						"!!! 'emerge -p "+str(string.split(x)[2])+"\n\n")
94
		print "              This action doesn't always verify the possible binary"
1948
			if "--pretend" not in myopts:
95
		print "              incompatibility between versions and can thus remove essential"
1949
				countdown(15, "*** Continuing")
96
		print "              dependencies from your system."
1950
			continue
97
		print "              The argument format is the same as for the "+bold("clean")+" action."
1951
			
98
		print
1952
		catpack=myparts[0]+"/"+myparts[1]
99
		print "       "+green("regen")
1953
		if catpack not in reallist:
100
		print "              Causes portage to check and update the dependency cache of all"
1954
			reallist.append(catpack)
101
		print "              ebuilds in the portage tree. This is not recommended for rsync"
1955
102
		print "              users as rsync updates the cache using server-side caches."
1956
	cleanlist=[]
103
		print "              Rsync users should simply 'emerge sync' to regenerate."
1957
	for x in myvarlist:
104
		print
1958
		if x not in reallist:
105
		print "       "+green("search")+" ("+green("-s")+" short option)"
1959
			if x not in cleanlist:
106
		print "              searches for matches of the supplied string in the current local"
1960
				cleanlist.append(x)
107
		print "              portage tree. The search string is a regular expression."
1961
108
		print "              A few examples: "
1962
	for x in syslist+worldlist:
109
		print "              "+bold("emerge search '^kde'")
1963
		myparts = portage.catpkgsplit(x)
110
		print "                  list all packages starting with kde"
1964
		if myparts:
111
		print "              "+bold("emerge search 'gcc$'")
1965
			if myparts[0][0] in ('<','>','='):
112
		print "                  list all packages ending with gcc"
1966
				myparts[0] = myparts[0][1:]
113
		print "              "+bold("emerge search ''")+" or"
1967
			if myparts[0][0] in ('<','>','='):
114
		print "              "+bold("emerge search '.*'")
1968
				myparts[0] = myparts[0][1:]
115
		print "                  list all available packages "
1969
			catpack=myparts[0]+"/"+myparts[1]
116
		print
1970
		else:
117
		print "       "+green("unmerge")+" ("+green("-C")+" short option)"
1971
			catpack=x
118
		print "              "+turquoise("WARNING: This action can remove important packages!")
1972
		if catpack in cleanlist:
119
		print "              Removes all matching packages without checking for outdated"
1973
			cleanlist.remove(catpack)
120
		print "              versions, effectively removing a package "+bold("completely")+" from"
1974
121
		print "              your system. Specify arguments using the dependency specification"
1975
	#print "\n\n\nCleaning: "
122
		print "              format described in the "+bold("clean")+" action above."
1976
	#for x in cleanlist:
123
		print
1977
	#	print x
124
		print turquoise("Options:")
1978
	#print
125
		print "       "+green("--build-package")+" ("+green("-b")+" short option)"
126
		print "              tell emerge to build binary packages for all ebuilds processed"
127
		print "              (in addition to actually merging the packages.  Useful for"
128
		print "              maintainers or if you administrate multiple Gentoo Linux"
129
		print "              systems (build once, emerge tbz2s everywhere)."
130
		print
131
		print "       "+green("--build-package-only")+" ("+green("-B")+" short option)"
132
		print "              Creates binary a binary package, but does not merge it to the"
133
		print "              system. This has the restriction that unsatisfied dependencies"
134
		print "              must not exist for the desired package as they cannot be used if"
135
		print "              they do not exist on the system."
136
		print
137
		print "       "+green("--changelog")+" ("+green("-l")+" short option)"
138
		print "              When pretending, also display the ChangeLog entries for packages"
139
		print "              that will be upgraded."
140
		print
141
		print "       "+green("--columns")
142
		print "              Display the pretend output in a tabular form. Versions are"
143
		print "              aligned vertically."
144
		print
145
		print "       "+green("--debug")+" ("+green("-d")+" short option)"
146
		print "              Tell emerge to run the ebuild command in --debug mode. In this"
147
		print "              mode, the bash build environment will run with the -x option,"
148
		print "              causing it to output verbose debug information print to stdout."
149
		print "              --debug is great for finding bash syntax errors as providing"
150
		print "              very verbose information about the dependency and build process."
151
		print
152
		print "       "+green("--deep")+" ("+green("-D")+" short option)"
153
		print "              When used in conjunction with --update, this flag forces emerge"
154
		print "              to consider the entire dependency tree of packages, instead of"
155
		print "              checking only the immediate dependencies of the packages.  As an"
156
		print "              example, this catches updates in libraries that are not directly"
157
		print "              listed in the dependencies of a package."
158
		print 
159
		print "       "+green("--empty-tree")+" ("+green("-e")+" short option)"
160
		print "              Virtually tweaks the tree of installed packages to only contain"
161
		print "              glibc, this is great to use together with --pretend. This makes"
162
		print "              it possible for developers to get a complete overview of the"
163
		print "              complete dependency tree of a certain package."
164
		print
165
		print "       "+green("--fetch-only")+" ("+green("-f")+" short option)"
166
		print "              Instead of doing any package building, just perform fetches for"
167
		print "              all packages (main package as well as all dependencies.) When"
168
		print "              used in combination with --pretend all the SRC_URIs will be"
169
		print "              displayed multiple mirrors per line, one line per file."
170
		print
171
		print "       "+green("--get-binary-package")+" ("+green("-g")+" short option)"
172
		print "              Using the server and location defined in PORTAGE_BINHOST, portage"
173
		print "              will download the information from each binary file there and it"
174
		print "              will use that information to help build the dependency list. This"
175
		print "              option implies '-k'. (Use -gK for binary-only merging.)"
176
		print
177
		print "       "+green("--get-binary-package-only")+" ("+green("-G")+" short option)"
178
		print "              This option is identical to -g, as above, except it will not use"
179
		print "              ANY information from the local machine. All binaries will be"
180
		print "              downloaded from the remote server without consulting packages"
181
		print "              existing in the packages directory."
182
		print
183
		print "       "+green("--forget-configuration")
184
		print "              Portage keeps track of files that have been placed into"
185
		print "              CONFIG_PROTECT directories, and normally it will not merge the"
186
		print "              same file more than once, as that would become annoying. This"
187
		print "              can lead to problems when the user wants the file in the case"
188
		print "              of accidental deletion. With this option, files will always be"
189
		print "              merged to the live fs instead of silently dropped."
190
		print
191
		print "       "+green("--no-dependencies")+" ("+green("-O")+" short option)"
192
		print "              Merge specified packages, but don't merge any dependencies."
193
		print "              Note that the build may fail if deps aren't satisfied."
194
		print 
195
		print "       "+green("--no-replace")+" ("+green("-n")+" short option)"
196
		print "              Skip the packages specified on the command-line that have"
197
		print "              already been installed.  Without this option, any packages,"
198
		print "              ebuilds, or deps you specify on the command-line *will* cause"
199
		print "              Portage to remerge the package, even if it is already installed."
200
		print "              Note that Portage won't remerge dependencies by default."
201
		print 
202
		print "       "+green("--no-spinner")
203
		print "              Disables the spinner regardless of terminal type."
204
		print
205
		print "       "+green("--once-only")
206
		print "              Emerge as normal, but don't add packages to the world profile for"
207
		print "              later updating. This prevents consideration of this package"
208
		print "              unless this package is depended upon by another package."
209
		print
210
		print "       "+green("--dependencies-only")+" ("+green("-o")+" short option)"
211
		print "              Only merge (or pretend to merge) the dependencies of the"
212
		print "              specified packages, not the packages themselves."
213
		print
214
		print "       "+green("--pretend")+" ("+green("-p")+" short option)"
215
		print "              instead of actually performing the merge, simply display what"
216
		print "              ebuilds and tbz2s *would* have been installed if --pretend"
217
		print "              weren't used.  Using --pretend is strongly recommended before"
218
		print "              installing an unfamiliar package.  In the printout, N = new,"
219
		print "              U = updating, R = replacing, B = blocked by an already installed"
220
		print "              package, D = possible downgrading. --verbose causes affecting"
221
		print "              use flags to be printed out accompanied by a '+' for enabled"
222
		print "              and a '-' for disabled flags."
223
		print
224
		print "       "+green("--quiet")+" ("+green("-q")+" short option)"
225
		print "              Effects vary, but the general outcome is a reduced or condensed"
226
		print "              output from portage's displays."
227
		print
228
		print "       "+green("--resume")
229
		print "              Resumes the last merge operation. Can be treated just like a"
230
		print "              regular merge as --pretend and other options work along side."
231
		print "              'emerge --resume' only returns an error on failure. Nothing to"
232
		print "              do exits with a message and a success condition."
233
		print
234
		print "       "+green("--search-description")+" ("+green("-S")+" short option)"
235
		print "              Matches the search string against the description field as well"
236
		print "              the package's name. Take caution as the descriptions are also"
237
		print "              matched as regular expressions."
238
		print "                emerge -S html"
239
		print "                emerge -S applet"
240
		print "                emerge -S 'perl.*module'"
241
		print
242
		print "       "+green("--skip-first")
243
		print "              This option is only valid in a resume situation. It removes the"
244
		print "              first package in the resume list so that a merge may continue in"
245
		print "              the presence of an uncorrectable or inconsequential error. This"
246
		print "              should only be used in cases where skipping the package will not"
247
		print "              result in failed dependencies."
248
		print
249
		print "       "+green("--update")+" ("+green("-u")+" short option)"
250
		print "              Updates packages to the best version available, which may not"
251
		print "              always be the highest version number due to masking for testing"
252
		print "              and development."
253
		print
254
		print "       "+green("--upgrade-only")+" ("+green("-U")+" short option)"
255
		print "              Updates packages, but excludes updates that would result in a"
256
		print "              lower version of the package being installed. SLOTs are"
257
		print "              considered at a basic level."
258
		print
259
		print "       "+green("--use-package")+" ("+green("-k")+" short option)"
260
		print "              Tell emerge to use binary packages (from $PKGDIR) if they are"
261
		print "              available, thus possibly avoiding some time-consuming compiles."
262
		print "              This option is useful for CD installs; you can export"
263
		print "              PKGDIR=/mnt/cdrom/packages and then use this option to have"
264
		print "              emerge \"pull\" binary packages from the CD in order to satisfy" 
265
		print "              dependencies."
266
		print
267
		print "       "+green("--use-package-only")+" ("+green("-K")+" short option)"
268
		print "              Like --use-package above, except this only allows the use of binary"
269
		print "              packages, and it will abort the emerge if the package is not"
270
		print "              available at the time of dependency calculation."
271
		print
272
		print "       "+green("--verbose")+" ("+green("-v")+" short option)"
273
		print "              Effects vary, but the general outcome is an increased or expanded"
274
		print "              display of content in portage's displays."
275
		print
276
		print "       "+green("--version")+" ("+green("-V")+" short option)"
277
		print "              Displays the currently installed version of portage along with"
278
		print "              other information useful for quick reference on a system. See"
279
		print "              "+bold("emerge info")+" for more advanced information."
280
		print
281
	elif myaction in ["rsync","sync"]:
282
		print
283
		print bold("Usage: ")+turquoise("emerge")+" "+turquoise("sync")
284
		print
285
		print "       'emerge sync' tells emerge to update the Portage tree as specified in"
286
		print "       The SYNC variable found in /etc/make.conf.  By default, SYNC instructs"
287
		print "       emerge to perform an rsync-style update with rsync.gentoo.org."
288
		#              Available"
289
		#print "       sync methods are rsync and anoncvs.  To use anoncvs rather than rsync,"
290
		#print "       put 'SYNC=\"cvs://:pserver:cvs.gentoo.org:/home/cvsroot\" in your"
291
		#print "       /etc/make.conf.  If you haven't used anoncvs before, you'll be prompted"
292
		#print "       for a password, which for cvs.gentoo.org is empty (just hit enter.)"
293
		print
294
		print "       'emerge-webrsync' exists as a helper app to emerge sync, providing a"
295
		print "       method to receive the entire portage tree as a tarball that can be"
296
		print "       extracted and used. First time syncs would benefit greatly from this."
297
		print
298
		print "       "+turquoise("WARNING:")
299
		print "       If using our rsync server, emerge will clean out all files that do not"
300
		print "       exist on it, including ones that you may have created."
301
		print
302
	elif myaction=="system":
303
		print
304
		print bold("Usage: ")+turquoise("emerge")+" [ "+green("options")+" ] "+turquoise("system")
305
		print
306
		print "       \"emerge system\" is the Portage system update command.  When run, it"
307
		print "       will scan the etc/make.profile/packages file and determine what"
308
		print "       packages need to be installed so that your system meets the minimum"
309
		print "       requirements of your current system profile.  Note that this doesn't"
310
		print "       necessarily bring your system up-to-date at all; instead, it just"
311
		print "       ensures that you have no missing parts.  For example, if your system"
312
		print "       profile specifies that you should have sys-apps/iptables installed"
313
		print "       and you don't, then \"emerge system\" will install it (the most"
314
		print "       recent version that matches the profile spec) for you.  It's always a"
315
		print "       good idea to do an \"emerge --pretend system\" before an \"emerge"
316
		print "       system\", just so you know what emerge is planning to do."
317
		print
318
	elif myaction=="config":
319
		outstuff=green("Config file management support (preliminary)")+"""
1979
320
1980
	if len(cleanlist):
321
Portage has a special feature called "config file protection".  The purpose of
1981
		unmerge("unmerge", cleanlist)
322
this feature is to prevent new package installs from clobbering existing
323
configuration files.  By default, config file protection is turned on for /etc
324
and the KDE configuration dirs; more may be added in the future.
1982
325
1983
	print
326
When Portage installs a file into a protected directory tree like /etc, any
1984
	print "Packages installed:   "+str(len(myvarlist))
327
existing files will not be overwritten.  If a file of the same name already
1985
	print "Packages in world:    "+str(len(worldlist))
328
exists, Portage will change the name of the to-be- installed file from 'foo' to
1986
	print "Packages in system:   "+str(len(syslist))
329
'._cfg0000_foo'.  If '._cfg0000_foo' already exists, this name becomes
1987
	print "Unique package names: "+str(len(reallist))
330
'._cfg0001_foo', etc.  In this way, existing files are not overwritten,
1988
	print "Required packages:    "+str(len(alldeps))
331
allowing the administrator to manually merge the new config files and avoid any
1989
	if "--pretend" in myopts:
332
unexpected changes.
1990
		print "Number to remove:     "+str(len(cleanlist))
1991
	else:
1992
		print "Number removed:       "+str(len(cleanlist))
1993
333
1994
	post_emerge()
334
In addition to protecting overwritten files, Portage will not delete any files
335
from a protected directory when a package is unmerged.  While this may be a
336
little bit untidy, it does prevent potentially valuable config files from being
337
deleted, which is of paramount importance.
1995
338
1996
# "update", "system", or just process files:
339
Protected directories are set using the CONFIG_PROTECT variable, normally
1997
else:
340
defined in /etc/make.globals.  Directory exceptions to the CONFIG_PROTECTed
1998
	favorites=[]
341
directories can be specified using the CONFIG_PROTECT_MASK variable.  To find
1999
	syslist=getlist("system")
342
files that need to be updated in /etc, type:
2000
	if ("--pretend" in myopts) and not ("--fetchonly" in myopts):
2001
		print
2002
		print darkgreen("These are the packages that I would merge, in order:")
2003
		print
2004
	if ("--resume" in myopts) and portage.mtimedb.has_key("resume"):
2005
		myresumeopts=portage.mtimedb["resume"]["myopts"][:]
2006
		for myopt in myopts:
2007
			if myopt not in myresumeopts:
2008
				myresumeopts.append(myopt)
2009
		myopts=myresumeopts
2010
		mydepgraph=depgraph("resume",myopts)
2011
		if "--resume" not in myopts:
2012
			myopts+=["--resume"]
2013
	else:
2014
		if ("--resume" in myopts):
2015
			del myopts[myopts.index("--resume")]
2016
			print darkgreen("emerge: It seems we have nothing to resume...")
2017
			sys.exit(0)
2018
343
2019
		mydepgraph=depgraph(myaction,myopts)
344
# find /etc -iname '._cfg????_*'
2020
		if myaction in ["system","world"]:
2021
			print "Calculating",myaction,"dependencies  ",
2022
			if not mydepgraph.xcreate(myaction):
2023
				print "!!! Depgraph creation failed."
2024
				sys.exit(1)
2025
			print "\b\b ...done!"
2026
		else:
2027
			if not myfiles:
2028
				print "emerge: please tell me what to do."
2029
				help()
2030
				sys.exit(1)
2031
				#we don't have any files to process; skip this step and exit
2032
			print "Calculating dependencies  ",
2033
			retval,favorites=mydepgraph.select_files(myfiles)
2034
			if not retval:
2035
				print "\n!!! Error calculating dependencies. Please correct."
2036
				sys.exit(1)
2037
			print "\b\b ...done!"
2038
345
2039
			if ("--usepkgonly" in myopts) and mydepgraph.missingbins:
346
You can disable this feature by setting CONFIG_PROTECT="-*" in /etc/make.conf.
2040
				sys.stderr.write(red("The following binaries are not available for merging...\n"))
347
Then, Portage will mercilessly auto-update your config files.  Alternatively,
348
you can leave Config File Protection on but tell Portage that it can overwrite
349
files in certain specific /etc subdirectories.  For example, if you wanted
350
Portage to automatically update your rc scripts and your wget configuration,
351
but didn't want any other changes made without your explicit approval, you'd
352
add this to /etc/make.conf:
2041
353
2042
		if mydepgraph.missingbins:
354
CONFIG_PROTECT_MASK="/etc/wget /etc/rc.d"
2043
			for x in mydepgraph.missingbins:
2044
				sys.stderr.write("   "+str(x)+"\n")
2045
			sys.stderr.write("\nThese are required by '--usepkgonly' -- Terminating.\n\n")
2046
			sys.exit(1)
2047
355
2048
	if ("--pretend" in myopts) and ("--fetchonly" not in myopts):
356
etc-update is also available to aid in the merging of these files. It provides
2049
		if ("--resume" in myopts):
357
a vimdiff interactive merging setup and can auto-merge trivial changes.
2050
			mydepgraph.display(portage.mtimedb["resume"]["mergelist"])
2051
		else:
2052
			mydepgraph.display(mydepgraph.altlist())
2053
	else:
2054
		if ("--buildpkgonly" in myopts):
2055
			if not mydepgraph.digraph.hasallzeros():
2056
				print "\n!!! --buildpkgonly requires all dependencies to be merged."
2057
				print "!!! Cannot merge requested packages. Merge deps and try again.\n"
2058
				sys.exit(1)
2059
358
2060
		if ("--resume" in myopts):
359
"""
2061
			favorites=portage.mtimedb["resume"]["favorites"]
360
		print outstuff
2062
			mydepgraph.merge(portage.mtimedb["resume"]["mergelist"])
2063
		else:
2064
			portage.mtimedb["resume"]={}
2065
			portage.mtimedb["resume"]["myopts"]=myopts
2066
			portage.mtimedb["resume"]["favorites"]=favorites
2067
			if ("--digest" in myopts) and not ("--fetchonly" in myopts):
2068
				for pkgline in mydepgraph.altlist():
2069
					if pkgline[0]=="ebuild" and pkgline[3]=="merge":
2070
						y=portage.portdb.findname(pkgline[2])
2071
						retval=portage.doebuild(y,"digest",portage.root,edebug,("--pretend" in myopts))
2072
			mydepgraph.merge(mydepgraph.altlist())
2073
361
2074
		if portage.mtimedb.has_key("resume"):
2075
			del portage.mtimedb["resume"]
2076
		if portage.settings["AUTOCLEAN"] and "yes"==portage.settings["AUTOCLEAN"]:
2077
			print ">>> Auto-cleaning packages ..."
2078
			unmerge("clean", ["world"])
2079
	post_emerge()

Return to bug 2365