#!/usr/bin/python
# Copyright 2009-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

from __future__ import print_function

import signal
import sys
# This block ensures that ^C interrupts are handled quietly.
try:

	def exithandler(signum,frame):
		signal.signal(signal.SIGINT, signal.SIG_IGN)
		signal.signal(signal.SIGTERM, signal.SIG_IGN)
		sys.exit(128 + signum)

	signal.signal(signal.SIGINT, exithandler)
	signal.signal(signal.SIGTERM, exithandler)

except KeyboardInterrupt:
	sys.exit(128 + signal.SIGINT)

import codecs
import logging
import optparse
import subprocess
import time
import textwrap
import re

try:
	import portage
except ImportError:
	from os import path as osp
	sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
	import portage

from portage import os, _encodings, _unicode_encode, _unicode_decode
from _emerge.MetadataRegen import MetadataRegen
from portage.cache.cache_errors import CacheError, StatCollision
from portage.manifest import guessManifestFileType
from portage.util import cmp_sort_key, writemsg_level
from portage import cpv_getkey
from portage.dep import Atom, isjustname
from portage.versions import pkgcmp, pkgsplit, vercmp

try:
	from xml.etree import ElementTree
except ImportError:
	pass
else:
	try:
		from xml.parsers.expat import ExpatError
	except ImportError:
		pass
	else:
		from repoman.utilities import parse_metadata_use

from repoman.utilities import FindVCS

if sys.hexversion >= 0x3000000:
	long = int

def parse_args(args):
	usage = "egencache [options] <action> ... [atom] ..."
	parser = optparse.OptionParser(usage=usage)

	actions = optparse.OptionGroup(parser, 'Actions')
	actions.add_option("--update",
		action="store_true",
		help="update metadata/cache/ (generate as necessary)")
	actions.add_option("--update-use-local-desc",
		action="store_true",
		help="update the use.local.desc file from metadata.xml")
	actions.add_option("--update-changelogs",
		action="store_true",
		help="update the ChangeLog files from SCM logs")
	parser.add_option_group(actions)

	common = optparse.OptionGroup(parser, 'Common options')
	common.add_option("--repo",
		action="store",
		help="name of repo to operate on (default repo is located at $PORTDIR)")
	common.add_option("--config-root",
		help="location of portage config files",
		dest="portage_configroot")
	common.add_option("--portdir",
		help="override the portage tree location",
		dest="portdir")
	common.add_option("--tolerant",
		action="store_true",
		help="exit successfully if only minor errors occurred")
	common.add_option("--ignore-default-opts",
		action="store_true",
		help="do not use the EGENCACHE_DEFAULT_OPTS environment variable")
	parser.add_option_group(common)

	update = optparse.OptionGroup(parser, '--update options')
	update.add_option("--cache-dir",
		help="location of the metadata cache",
		dest="cache_dir")
	update.add_option("--jobs",
		action="store",
		help="max ebuild processes to spawn")
	update.add_option("--load-average",
		action="store",
		help="max load allowed when spawning multiple jobs",
		dest="load_average")
	update.add_option("--rsync",
		action="store_true",
		help="enable rsync stat collision workaround " + \
			"for bug 139134 (use with --update)")
	parser.add_option_group(update)

	uld = optparse.OptionGroup(parser, '--update-use-local-desc options')
	uld.add_option("--preserve-comments",
		action="store_true",
		help="preserve the comments from the existing use.local.desc file")
	uld.add_option("--use-local-desc-output",
		help="output file for use.local.desc data (or '-' for stdout)",
		dest="uld_output")
	parser.add_option_group(uld)

	options, args = parser.parse_args(args)

	if options.jobs:
		jobs = None
		try:
			jobs = int(options.jobs)
		except ValueError:
			jobs = -1

		if jobs < 1:
			parser.error("Invalid: --jobs='%s'" % \
				(options.jobs,))

		options.jobs = jobs

	else:
		options.jobs = None

	if options.load_average:
		try:
			load_average = float(options.load_average)
		except ValueError:
			load_average = 0.0

		if load_average <= 0.0:
			parser.error("Invalid: --load-average='%s'" % \
				(options.load_average,))

		options.load_average = load_average

	else:
		options.load_average = None

	options.config_root = options.portage_configroot
	if options.config_root is not None and \
		not os.path.isdir(options.config_root):
		parser.error("Not a directory: --config-root='%s'" % \
			(options.config_root,))

	if options.cache_dir is not None and not os.path.isdir(options.cache_dir):
		parser.error("Not a directory: --cache-dir='%s'" % \
			(options.cache_dir,))

	for atom in args:
		try:
			atom = portage.dep.Atom(atom)
		except portage.exception.InvalidAtom:
			parser.error('Invalid atom: %s' % (atom,))

		if not isjustname(atom):
			parser.error('Atom is too specific: %s' % (atom,))

	if options.update_use_local_desc:
		try:
			ElementTree
			ExpatError
		except NameError:
			parser.error('--update-use-local-desc requires python with USE=xml!')

	if options.uld_output == '-' and options.preserve_comments:
		parser.error('--preserve-comments can not be used when outputting to stdout')

	return parser, options, args

class GenCache(object):
	def __init__(self, portdb, cp_iter=None, max_jobs=None, max_load=None,
		rsync=False):
		self._portdb = portdb
		# We can globally cleanse stale cache only if we
		# iterate over every single cp.
		self._global_cleanse = cp_iter is None
		if cp_iter is not None:
			self._cp_set = set(cp_iter)
			cp_iter = iter(self._cp_set)
			self._cp_missing = self._cp_set.copy()
		else:
			self._cp_set = None
			self._cp_missing = set()
		self._regen = MetadataRegen(portdb, cp_iter=cp_iter,
			consumer=self._metadata_callback,
			max_jobs=max_jobs, max_load=max_load)
		self.returncode = os.EX_OK
		metadbmodule = portdb.settings.load_best_module("portdbapi.metadbmodule")
		self._trg_cache = metadbmodule(portdb.porttrees[0],
			"metadata/cache", portage.auxdbkeys[:])
		if rsync:
			self._trg_cache.raise_stat_collision = True
		try:
			self._trg_cache.ec = \
				portdb._repo_info[portdb.porttrees[0]].eclass_db
		except AttributeError:
			pass
		self._existing_nodes = set()

	def _metadata_callback(self, cpv, ebuild_path, repo_path, metadata):
		self._existing_nodes.add(cpv)
		self._cp_missing.discard(cpv_getkey(cpv))
		if metadata is not None:
			if metadata.get('EAPI') == '0':
				del metadata['EAPI']
			try:
				try:
					self._trg_cache[cpv] = metadata
				except StatCollision as sc:
					# If the content of a cache entry changes and neither the
					# file mtime nor size changes, it will prevent rsync from
					# detecting changes. Cache backends may raise this
					# exception from _setitem() if they detect this type of stat
					# collision. These exceptions are handled by bumping the
					# mtime on the ebuild (and the corresponding cache entry).
					# See bug #139134.
					max_mtime = sc.mtime
					for ec, (loc, ec_mtime) in metadata['_eclasses_'].items():
						if max_mtime < ec_mtime:
							max_mtime = ec_mtime
					if max_mtime == sc.mtime:
						max_mtime += 1
					max_mtime = long(max_mtime)
					try:
						os.utime(ebuild_path, (max_mtime, max_mtime))
					except OSError as e:
						self.returncode |= 1
						writemsg_level(
							"%s writing target: %s\n" % (cpv, e),
							level=logging.ERROR, noiselevel=-1)
					else:
						metadata['_mtime_'] = max_mtime
						self._trg_cache[cpv] = metadata
						self._portdb.auxdb[repo_path][cpv] = metadata

			except CacheError as ce:
				self.returncode |= 1
				writemsg_level(
					"%s writing target: %s\n" % (cpv, ce),
					level=logging.ERROR, noiselevel=-1)

	def run(self):

		received_signal = []

		def sighandler(signum, frame):
			signal.signal(signal.SIGINT, signal.SIG_IGN)
			signal.signal(signal.SIGTERM, signal.SIG_IGN)
			self._regen.terminate()
			received_signal.append(128 + signum)

		earlier_sigint_handler = signal.signal(signal.SIGINT, sighandler)
		earlier_sigterm_handler = signal.signal(signal.SIGTERM, sighandler)

		try:
			self._regen.run()
		finally:
			# Restore previous handlers
			if earlier_sigint_handler is not None:
				signal.signal(signal.SIGINT, earlier_sigint_handler)
			else:
				signal.signal(signal.SIGINT, signal.SIG_DFL)
			if earlier_sigterm_handler is not None:
				signal.signal(signal.SIGTERM, earlier_sigterm_handler)
			else:
				signal.signal(signal.SIGTERM, signal.SIG_DFL)

		if received_signal:
			sys.exit(received_signal[0])

		self.returncode |= self._regen.returncode
		cp_missing = self._cp_missing

		trg_cache = self._trg_cache
		dead_nodes = set()
		if self._global_cleanse:
			try:
				for cpv in trg_cache:
					cp = cpv_getkey(cpv)
					if cp is None:
						self.returncode |= 1
						writemsg_level(
							"Unable to parse cp for '%s'\n"  % (cpv,),
							level=logging.ERROR, noiselevel=-1)
					else:
						dead_nodes.add(cpv)
			except CacheError as ce:
				self.returncode |= 1
				writemsg_level(
					"Error listing cache entries for " + \
					"'%s/metadata/cache': %s, continuing...\n" % \
					(self._portdb.porttree_root, ce),
					level=logging.ERROR, noiselevel=-1)

		else:
			cp_set = self._cp_set
			try:
				for cpv in trg_cache:
					cp = cpv_getkey(cpv)
					if cp is None:
						self.returncode |= 1
						writemsg_level(
							"Unable to parse cp for '%s'\n"  % (cpv,),
							level=logging.ERROR, noiselevel=-1)
					else:
						cp_missing.discard(cp)
						if cp in cp_set:
							dead_nodes.add(cpv)
			except CacheError as ce:
				self.returncode |= 1
				writemsg_level(
					"Error listing cache entries for " + \
					"'%s/metadata/cache': %s, continuing...\n" % \
					(self._portdb.porttree_root, ce),
					level=logging.ERROR, noiselevel=-1)

		if cp_missing:
			self.returncode |= 1
			for cp in sorted(cp_missing):
				writemsg_level(
					"No ebuilds or cache entries found for '%s'\n"  % (cp,),
					level=logging.ERROR, noiselevel=-1)

		if dead_nodes:
			dead_nodes.difference_update(self._existing_nodes)
			for k in dead_nodes:
				try:
					del trg_cache[k]
				except KeyError:
					pass
				except CacheError as ce:
					self.returncode |= 1
					writemsg_level(
						"%s deleting stale cache: %s\n" % (k, ce),
						level=logging.ERROR, noiselevel=-1)

		if not trg_cache.autocommits:
			try:
				trg_cache.commit()
			except CacheError as ce:
				self.returncode |= 1
				writemsg_level(
					"committing target: %s\n" % (ce,),
					level=logging.ERROR, noiselevel=-1)

class GenUseLocalDesc(object):
	def __init__(self, portdb, output=None,
			preserve_comments=False):
		self.returncode = os.EX_OK
		self._portdb = portdb
		self._output = output
		self._preserve_comments = preserve_comments
	
	def run(self):
		repo_path = self._portdb.porttrees[0]
		ops = {'<':0, '<=':1, '=':2, '>=':3, '>':4}

		if self._output is None or self._output != '-':
			if self._output is None:
				prof_path = os.path.join(repo_path, 'profiles')
				desc_path = os.path.join(prof_path, 'use.local.desc')
				try:
					os.mkdir(prof_path)
				except OSError:
					pass
			else:
				desc_path = self._output

			try:
				if self._preserve_comments:
					# Probe in binary mode, in order to avoid
					# potential character encoding issues.
					output = open(_unicode_encode(desc_path,
						encoding=_encodings['fs'], errors='strict'), 'r+b')
				else:
					output = codecs.open(_unicode_encode(desc_path,
						encoding=_encodings['fs'], errors='strict'),
						mode='w', encoding=_encodings['repo.content'],
						errors='replace')
			except IOError as e:
				if not self._preserve_comments or \
					os.path.isfile(desc_path):
					writemsg_level(
						"ERROR: failed to open output file %s: %s\n" \
						% (desc_path, e), level=logging.ERROR, noiselevel=-1)
					self.returncode |= 2
					return

				# Open in r+b mode failed because the file doesn't
				# exist yet. We can probably recover if we disable
				# preserve_comments mode now.
				writemsg_level(
					"WARNING: --preserve-comments enabled, but " + \
					"output file not found: %s\n" % (desc_path,),
					level=logging.WARNING, noiselevel=-1)
				self._preserve_comments = False
				try:
					output = codecs.open(_unicode_encode(desc_path,
						encoding=_encodings['fs'], errors='strict'),
						mode='w', encoding=_encodings['repo.content'],
						errors='replace')
				except IOError as e:
					writemsg_level(
						"ERROR: failed to open output file %s: %s\n" \
						% (desc_path, e), level=logging.ERROR, noiselevel=-1)
					self.returncode |= 2
					return
		else:
			output = sys.stdout

		if self._preserve_comments:
			while True:
				pos = output.tell()
				if not output.readline().startswith(b'#'):
					break
			output.seek(pos)
			output.truncate()
			output.close()

			# Finished probing comments in binary mode, now append
			# in text mode.
			output = codecs.open(_unicode_encode(desc_path,
				encoding=_encodings['fs'], errors='strict'),
				mode='a', encoding=_encodings['repo.content'],
				errors='replace')
			output.write('\n')
		else:
			output.write('''
# This file is deprecated as per GLEP 56 in favor of metadata.xml. Please add
# your descriptions to your package's metadata.xml ONLY.
# * generated automatically using egencache *

'''.lstrip())

		# The cmp function no longer exists in python3, so we'll
		# implement our own here under a slightly different name
		# since we don't want any confusion given that we never
		# want to rely on the builtin cmp function.
		def cmp_func(a, b):
			if a is None or b is None:
				# None can't be compared with other types in python3.
				if a is None and b is None:
					return 0
				elif a is None:
					return -1
				else:
					return 1
			return (a > b) - (a < b)

		for cp in self._portdb.cp_all():
			metadata_path = os.path.join(repo_path, cp, 'metadata.xml')
			try:
				metadata = ElementTree.parse(metadata_path)
			except IOError:
				pass
			except (ExpatError, EnvironmentError) as e:
				writemsg_level(
					"ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e),
					level=logging.ERROR, noiselevel=-1)
				self.returncode |= 1
			else:
				try:
					usedict = parse_metadata_use(metadata)
				except portage.exception.ParseError as e:
					writemsg_level(
						"ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e),
						level=logging.ERROR, noiselevel=-1)
					self.returncode |= 1
				else:
					for flag in sorted(usedict):
						def atomcmp(atoma, atomb):
							# None is better than an atom, that's why we reverse the args
							if atoma is None or atomb is None:
								return cmp_func(atomb, atoma)
							# Same for plain PNs (.operator is None then)
							elif atoma.operator is None or atomb.operator is None:
								return cmp_func(atomb.operator, atoma.operator)
							# Version matching
							elif atoma.cpv != atomb.cpv:
								return pkgcmp(pkgsplit(atoma.cpv), pkgsplit(atomb.cpv))
							# Versions match, let's fallback to operator matching
							else:
								return cmp_func(ops.get(atoma.operator, -1),
									ops.get(atomb.operator, -1))

						def _Atom(key):
							if key is not None:
								return Atom(key)
							return None

						resdict = usedict[flag]
						if len(resdict) == 1:
							resdesc = next(iter(resdict.items()))[1]
						else:
							try:
								reskeys = dict((_Atom(k), k) for k in resdict)
							except portage.exception.InvalidAtom as e:
								writemsg_level(
									"ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e),
									level=logging.ERROR, noiselevel=-1)
								self.returncode |= 1
								resdesc = next(iter(resdict.items()))[1]
							else:
								resatoms = sorted(reskeys, key=cmp_sort_key(atomcmp))
								resdesc = resdict[reskeys[resatoms[-1]]]

						output.write('%s:%s - %s\n' % (cp, flag, resdesc))

		output.close()

if sys.hexversion < 0x3000000:
	_filename_base = unicode
else:
	_filename_base = str

class _special_filename(_filename_base):
	"""
	Helps to sort file names by file type and other criteria.
	"""
	def __new__(cls, status_change, file_name):
		return _filename_base.__new__(cls, status_change + file_name)

	def __init__(self, status_change, file_name):
		_filename_base.__init__(status_change + file_name)
		self.status_change = status_change
		self.file_name = file_name
		self.file_type = guessManifestFileType(file_name)

	def file_type_lt(self, a, b):
		"""
		Defines an ordering between file types.
		"""
		first = a.file_type
		second = b.file_type
		if first == second:
			return False

		if first == "EBUILD":
			return True
		elif first == "MISC":
			return second in ("EBUILD",)
		elif first == "AUX":
			return second in ("EBUILD", "MISC")
		elif first == "DIST":
			return second in ("EBUILD", "MISC", "AUX")
		elif first is None:
			return False
		else:
			raise ValueError("Unknown file type '%s'" % first)

	def __lt__(self, other):
		"""
		Compare different file names, first by file type and then
		for ebuilds by version and lexicographically for others.
		EBUILD < MISC < AUX < DIST < None
		"""
		if self.__class__ != other.__class__:
			raise NotImplementedError

		# Sort by file type as defined by file_type_lt().
		if self.file_type_lt(self, other):
			return True
		elif self.file_type_lt(other, self):
			return False

		# Files have the same type.
		if self.file_type == "EBUILD":
			# Sort by version. Lowest first.
			ver = "-".join(pkgsplit(self.file_name[:-7])[1:3])
			other_ver = "-".join(pkgsplit(other.file_name[:-7])[1:3])
			return vercmp(ver, other_ver) < 0
		else:
			# Sort lexicographically.
			return self.file_name < other.file_name

class GenChangeLogs(object):
	def __init__(self, portdb):
		self.returncode = os.EX_OK
		self._portdb = portdb
		self._wrapper = textwrap.TextWrapper(
				width = 78,
				initial_indent = '  ',
				subsequent_indent = '  '
			)

	@staticmethod
	def grab(cmd):
		p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
		return _unicode_decode(p.communicate()[0],
				encoding=_encodings['stdio'], errors='strict')

	def generate_changelog(self, cp):
		try:
			output = codecs.open('ChangeLog',
				mode='w', encoding=_encodings['repo.content'],
				errors='replace')
		except IOError as e:
			writemsg_level(
				"ERROR: failed to open ChangeLog for %s: %s\n" % (cp,e,),
				level=logging.ERROR, noiselevel=-1)
			self.returncode |= 2
			return

		output.write(('''
# ChangeLog for %s
# Copyright 1999-%s Gentoo Foundation; Distributed under the GPL v2
# $Header: $

''' % (cp, time.strftime('%Y'))).lstrip())

		# now grab all the commits
		commits = self.grab(['git', 'rev-list', 'HEAD', '--', '.']).split()

		for c in commits:
			# Explaining the arguments:
			# --name-status to get a list of added/removed files
			# --no-renames to avoid getting more complex records on the list
			# --format to get the timestamp, author and commit description
			# --root to make it work fine even with the initial commit
			# --relative to get paths relative to ebuilddir
			# -r (recursive) to get per-file changes
			# then the commit-id and path.

			cinfo = self.grab(['git', 'diff-tree', '--name-status', '--no-renames',
					'--format=%ct %cN <%cE>%n%B', '--root', '--relative', '-r',
					c, '--', '.']).rstrip('\n').split('\n')

			# Expected output:
			# timestamp Author Name <author@email>
			# commit message l1
			# ...
			# commit message ln
			#
			# status1	filename1
			# ...
			# statusn	filenamen

			changed = []
			for n, l in enumerate(reversed(cinfo)):
				if not l:
					body = cinfo[1:-n-1]
					break
				else:
					f = l.split()
					if f[1] == 'Manifest':
						pass # XXX: remanifest commits?
					elif f[1] == 'ChangeLog':
						pass
					elif f[0].startswith('A'):
						changed.append(_special_filename("+", f[1]))
					elif f[0].startswith('D'):
						changed.append(_special_filename("-", f[1]))
					elif f[0].startswith('M'):
						changed.append(_special_filename("", f[1]))
					else:
						writemsg_level(
							"ERROR: unexpected git file status for %s: %s\n" % (cp,f,),
							level=logging.ERROR, noiselevel=-1)
						self.returncode |= 1

			if not changed:
				continue

			(ts, author) = cinfo[0].split(' ', 1)
			date = time.strftime('%d %b %Y', time.gmtime(float(ts)))

			changed = [str(x) for x in sorted(changed)]

			wroteheader = False
			# Reverse the sort order for headers.
			for c in reversed(changed):
				if c.startswith('+') and c.endswith('.ebuild'):
					output.write('*%s (%s)\n' % (c[1:-7], date))
					wroteheader = True
			if wroteheader:
				output.write('\n')

			# strip '<cp>: ', '[<cp>] ', and similar
			body[0] = re.sub(r'^\W*' + re.escape(cp) + r'\W+', '', body[0])
			# strip trailing newline
			if not body[-1]:
				body = body[:-1]
			# strip git-svn id
			if body[-1].startswith('git-svn-id:') and not body[-2]:
				body = body[:-2]
			# strip the repoman version/manifest note
			if body[-1] == ' (Signed Manifest commit)' or body[-1] == ' (Unsigned Manifest commit)':
				body = body[:-1]
			if body[-1].startswith('(Portage version:') and body[-1].endswith(')'):
				body = body[:-1]
				if not body[-1]:
					body = body[:-1]

			# don't break filenames on hyphens
			self._wrapper.break_on_hyphens = False
			output.write(self._wrapper.fill('%s; %s %s:' % (date, author, ', '.join(changed))))
			# but feel free to break commit messages there
			self._wrapper.break_on_hyphens = True
			output.write('\n%s\n\n' % '\n'.join([self._wrapper.fill(x) for x in body]))

		output.close()

	def run(self):
		repo_path = self._portdb.porttrees[0]
		os.chdir(repo_path)

		if 'git' not in FindVCS():
			writemsg_level(
				"ERROR: --update-changelogs supported only in git repos\n",
				level=logging.ERROR, noiselevel=-1)
			self.returncode = 127
			return

		for cp in self._portdb.cp_all():
			os.chdir(os.path.join(repo_path, cp))
			# Determine whether ChangeLog is up-to-date by comparing
			# the newest commit timestamp with the ChangeLog timestamp.
			lmod = self.grab(['git', 'log', '--format=%ct', '-1', '.'])
			if not lmod:
				# This cp has not been added to the repo.
				continue

			try:
				cmod = os.stat('ChangeLog').st_mtime
			except OSError:
				cmod = 0

			if float(cmod) < float(lmod):
				self.generate_changelog(cp)

def egencache_main(args):
	parser, options, atoms = parse_args(args)

	config_root = options.config_root
	if config_root is None:
		config_root = '/'

	# The calling environment is ignored, so the program is
	# completely controlled by commandline arguments.
	env = {}

	if options.repo is None:
		env['PORTDIR_OVERLAY'] = ''

	if options.cache_dir is not None:
		env['PORTAGE_DEPCACHEDIR'] = options.cache_dir

	if options.portdir is not None:
		env['PORTDIR'] = options.portdir

	settings = portage.config(config_root=config_root,
		target_root='/', local_config=False, env=env)

	default_opts = None
	if not options.ignore_default_opts:
		default_opts = settings.get('EGENCACHE_DEFAULT_OPTS', '').split()

	if default_opts:
		parser, options, args = parse_args(default_opts + args)

		if options.config_root is not None:
			config_root = options.config_root

		if options.cache_dir is not None:
			env['PORTAGE_DEPCACHEDIR'] = options.cache_dir

		settings = portage.config(config_root=config_root,
			target_root='/', local_config=False, env=env)

	if not options.update and not options.update_use_local_desc \
			and not options.update_changelogs:
		parser.error('No action specified')
		return 1

	if options.update and 'metadata-transfer' not in settings.features:
		writemsg_level("ecachegen: warning: " + \
			"automatically enabling FEATURES=metadata-transfer\n",
			level=logging.WARNING, noiselevel=-1)
		settings.features.add('metadata-transfer')

	settings.lock()

	portdb = portage.portdbapi(mysettings=settings)
	if options.repo is not None:
		repo_path = portdb.getRepositoryPath(options.repo)
		if repo_path is None:
			parser.error("Unable to locate repository named '%s'" % \
				(options.repo,))
			return 1

		# Limit ebuilds to the specified repo.
		portdb.porttrees = [repo_path]

	ret = [os.EX_OK]

	if options.update:
		cp_iter = None
		if atoms:
			cp_iter = iter(atoms)

		gen_cache = GenCache(portdb, cp_iter=cp_iter,
			max_jobs=options.jobs,
			max_load=options.load_average,
			rsync=options.rsync)
		gen_cache.run()
		if options.tolerant:
			ret.append(os.EX_OK)
		else:
			ret.append(gen_cache.returncode)

	if options.update_use_local_desc:
		gen_desc = GenUseLocalDesc(portdb,
			output=options.uld_output,
			preserve_comments=options.preserve_comments)
		gen_desc.run()
		ret.append(gen_desc.returncode)

	if options.update_changelogs:
		gen_clogs = GenChangeLogs(portdb)
		gen_clogs.run()
		ret.append(gen_clogs.returncode)

	return max(ret)

if __name__ == "__main__":
	portage._disable_legacy_globals()
	portage.util.noiselimit = -1
	sys.exit(egencache_main(sys.argv[1:]))
