#!/usr/bin/python
# Copyright 2009-2012 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 io
import logging
import optparse
import subprocess
import time
import textwrap
import re

from os import path as osp
pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")
sys.path.insert(0, pym_path)
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 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("--portdir-overlay",
		help="override the PORTDIR_OVERLAY variable (requires that --repo is also specified)",
		dest="portdir_overlay")
	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("-j", "--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:
		if not os.path.isdir(options.cache_dir):
			parser.error("Not a directory: --cache-dir='%s'" % \
				(options.cache_dir,))
		if not os.access(options.cache_dir, os.W_OK):
			parser.error("Write access denied: --cache-dir='%s'" % \
				(options.cache_dir,))

	if options.portdir_overlay is not None and \
		options.repo is None:
		parser.error("--portdir-overlay option requires --repo option")

	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):
		# The caller must set portdb.porttrees in order to constrain
		# findname, cp_list, and cpv_list to the desired tree.
		tree = portdb.porttrees[0]
		self._portdb = portdb
		self._eclass_db = portdb.repositories.get_repo_for_location(tree).eclass_db
		self._auxdbkeys = portdb._known_keys
		# 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
		conf = portdb.repositories.get_repo_for_location(tree)
		self._trg_caches = tuple(conf.iter_pregenerated_caches(
			self._auxdbkeys, force=True, readonly=False))
		if not self._trg_caches:
			raise Exception("cache formats '%s' aren't supported" %
				(" ".join(conf.cache_formats),))

		if rsync:
			for trg_cache in self._trg_caches:
				if hasattr(trg_cache, 'raise_stat_collision'):
					trg_cache.raise_stat_collision = True
					# Make _metadata_callback write this cache first, in case
					# it raises a StatCollision and triggers mtime
					# modification.
					self._trg_caches = tuple([trg_cache] +
						[x for x in self._trg_caches if x is not trg_cache])

		self._existing_nodes = set()

	def _metadata_callback(self, cpv, repo_path, metadata,
		ebuild_hash, eapi_supported):
		self._existing_nodes.add(cpv)
		self._cp_missing.discard(cpv_getkey(cpv))

		# Since we're supposed to be able to efficiently obtain the
		# EAPI from _parse_eapi_ebuild_head, we don't write cache
		# entries for unsupported EAPIs.
		if metadata is not None and eapi_supported:
			if metadata.get('EAPI') == '0':
				del metadata['EAPI']
			for trg_cache in self._trg_caches:
				self._write_cache(trg_cache,
					cpv, repo_path, metadata, ebuild_hash)

	def _write_cache(self, trg_cache, cpv, repo_path, metadata, ebuild_hash):

			if not hasattr(trg_cache, 'raise_stat_collision'):
				# This cache does not avoid redundant writes automatically,
				# so check for an identical existing entry before writing.
				# This prevents unnecessary disk writes and can also prevent
				# unnecessary rsync transfers.
				try:
					dest = trg_cache[cpv]
				except (KeyError, CacheError):
					pass
				else:
					if trg_cache.validate_entry(dest,
						ebuild_hash, self._eclass_db):
						identical = True
						for k in self._auxdbkeys:
							if dest.get(k, '') != metadata.get(k, ''):
								identical = False
								break
						if identical:
							return

			try:
				chf = trg_cache.validation_chf
				metadata['_%s_' % chf] = getattr(ebuild_hash, chf)
				try:
					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. It is convenient to include checks for
					# redundant writes along with the internal StatCollision
					# detection code, so for caches with the
					# raise_stat_collision attribute, we do not need to
					# explicitly check for redundant writes like we do for the
					# other cache types above.
					max_mtime = sc.mtime
					for ec, ec_hash in metadata['_eclasses_'].items():
						if max_mtime < ec_hash.mtime:
							max_mtime = ec_hash.mtime
					if max_mtime == sc.mtime:
						max_mtime += 1
					max_mtime = long(max_mtime)
					try:
						os.utime(ebuild_hash.location, (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:
						ebuild_hash.mtime = max_mtime
						metadata['_mtime_'] = max_mtime
						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

		for trg_cache in self._trg_caches:
			self._cleanse_cache(trg_cache)

	def _cleanse_cache(self, trg_cache):
		cp_missing = self._cp_missing
		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)

		if hasattr(trg_cache, '_prune_empty_dirs'):
			trg_cache._prune_empty_dirs()

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 = io.open(_unicode_encode(desc_path,
						encoding=_encodings['fs'], errors='strict'),
						mode='w', encoding=_encodings['repo.content'],
						errors='backslashreplace')
			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 = io.open(_unicode_encode(desc_path,
						encoding=_encodings['fs'], errors='strict'),
						mode='w', encoding=_encodings['repo.content'],
						errors='backslashreplace')
				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 = io.open(_unicode_encode(desc_path,
				encoding=_encodings['fs'], errors='strict'),
				mode='a', encoding=_encodings['repo.content'],
				errors='backslashreplace')
			output.write(_unicode_decode('\n'))
		else:
			output.write(textwrap.dedent(_unicode_decode('''\
				# 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 *

				''')))

		# 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)

		class _MetadataTreeBuilder(ElementTree.TreeBuilder):
			"""
			Implements doctype() as required to avoid deprecation warnings
			since Python >=2.7
			"""
			def doctype(self, name, pubid, system):
				pass

		for cp in self._portdb.cp_all():
			metadata_path = os.path.join(repo_path, cp, 'metadata.xml')
			try:
				metadata = ElementTree.parse(metadata_path,
					parser=ElementTree.XMLParser(
					target=_MetadataTreeBuilder()))
			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 vercmp(atoma.version, atomb.version)
							# 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(_unicode_decode(
							'%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 = io.open('ChangeLog',
				mode='w', encoding=_encodings['repo.content'],
				errors='backslashreplace')
		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(textwrap.dedent(_unicode_decode('''\
			# ChangeLog for %s
			# Copyright 1999-%s Gentoo Foundation; Distributed under the GPL v2
			# $Header: $

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

		# 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(_unicode_decode(
						'*%s (%s)\n' % (c[1:-7], date)))
					wroteheader = True
			if wroteheader:
				output.write(_unicode_decode('\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(_unicode_decode(
				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(_unicode_decode(
				'\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

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

	if options.repo is None:
		env['PORTDIR_OVERLAY'] = ''
	elif options.portdir_overlay:
		env['PORTDIR_OVERLAY'] = options.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,
		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.cache_dir is not None:
			env['PORTAGE_DEPCACHEDIR'] = options.cache_dir

		settings = portage.config(config_root=config_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

	repo_path = None
	if options.repo is not None:
		repo_path = settings.repositories.treemap.get(options.repo)
		if repo_path is None:
			parser.error("Unable to locate repository named '%s'" % \
				(options.repo,))
			return 1
	else:
		repo_path = settings.repositories.mainRepoLocation()
		if not repo_path:
			parser.error("PORTDIR is undefined")
			return 1

	if options.update and 'metadata-transfer' not in settings.features:
		# Forcibly enable metadata-transfer if portdbapi has a pregenerated
		# cache that does not support eclass validation.
		repo_config = settings.repositories.get_repo_for_location(repo_path)
		cache = repo_config.get_pregenerated_cache(
			portage.dbapi.dbapi._known_keys, readonly=True)
		if cache is not None and not cache.complete_eclass_entries:
			settings.features.add('metadata-transfer')
		cache = None

	settings.lock()

	portdb = portage.portdbapi(mysettings=settings)

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

	if options.update:
		if options.cache_dir is not None:
			# already validated earlier
			pass
		else:
			# We check write access after the portdbapi constructor
			# has had an opportunity to create it. This ensures that
			# we don't use the cache in the "volatile" mode which is
			# undesirable for egencache.
			if not os.access(settings["PORTAGE_DEPCACHEDIR"], os.W_OK):
				writemsg_level("ecachegen: error: " + \
					"write access denied: %s\n" % (settings["PORTAGE_DEPCACHEDIR"],),
					level=logging.ERROR, noiselevel=-1)
				return 1

	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:]))
