#!/usr/bin/env python
# (c) 2019 Thomas Deutschmann <whissi@gentoo.org>
# Distributed under the terms of the GNU General Public License v2

from __future__ import unicode_literals
from __future__ import print_function

MY_PN = "elicense"
MY_PV = "git.unknown"

import sys
import argparse

import portage.proxy.lazyimport
import portage.proxy as proxy
proxy.lazyimport.lazyimport(globals(),
	'_emerge.RootConfig:RootConfig',
	'portage.package.ebuild.config:best_from_dict,' + \
		'config',
	'portage.package.ebuild._config.LocationsManager:LocationsManager',
	'portage.package.ebuild._config.LicenseManager:LicenseManager',
	'portage.repository.config:load_repository_config',
)

def main(argv):
	opts = process_args(argv)

	eroot=opts.eroot

	settings = config(config_root=None, target_root=eroot)

	if opts.debug:
		print('> EROOT set to "{}" ...'.format(eroot), file=sys.stderr)
		print('> Will scan for installed packages which are not' \
			' covered by ACCEPT_LICENSE="{}" nor have entries' \
			' in the package.license file ...' \
			.format(settings.get("ACCEPT_LICENSE")), file=sys.stderr)

	locations_manager = LocationsManager(config_root=None,
		config_profile_path=None,
		eprefix=None,
		local_config=True,
		target_root=eroot)

	locations_manager.set_port_dirs(settings.get("PORTDIR"),
		settings.get("PORTDIR_OVERLAY"))

	abs_user_config = locations_manager.abs_user_config

	license_manager = LicenseManager(locations_manager.profile_locations,
		abs_user_config,
		user_config=True)

	license_manager.set_accept_license_str(settings.get("ACCEPT_LICENSE"))

	try:
		vardb = portage.db[eroot]["vartree"].dbapi
	except KeyError:
		print('EROOT "{}" is invalid.'.format(eroot), file=sys.stderr)
		return 1

	metakeys = list(vardb._aux_cache_keys)

	packages_with_missing_licenses = {}
	for cpv in sorted(vardb.cpv_all()):
		try:
			metadata = dict(zip(metakeys, vardb.aux_get(cpv, metakeys, myrepo=None)))

			if "?" in metadata["LICENSE"]:
				# Should never be the case because we work on vartree only
				settings.setcpv(cpv, mydb=metadata)
				metadata["USE"] = settings["PORTAGE_USE"]
			else:
				metadata["USE"] = ""

			missing_licenses = license_manager.getMissingLicenses(cpv,
				metadata["USE"],
				metadata["LICENSE"],
				metadata["SLOT"],
				metadata.get('repository'))
		except:
			print('Package DB entry for "{}" seems to be' \
				' broken. Try to reinstall that' \
				' package before calling {} again!'.format(cpv, MY_PN), file=sys.stderr)
			return 1

		if missing_licenses:
			if opts.debug:
				print('> Package ={}:{}::{} is using non-accepted license(s) {}'.format(cpv,
					metadata["SLOT"],
					metadata.get('repository'),
					', '.join('"%s"' % license for license in missing_licenses)), file=sys.stderr)

			pkg = vardb._pkg_str(cpv, None)
			packages_with_missing_licenses.setdefault(pkg.cp, []).extend(missing_licenses)

	if not packages_with_missing_licenses:
		print("# Licenses for all installed packages are already accepted!")
	else:
		print("# The following package(s) are using licenses which aren't covered by")
		print("# ACCEPT_LICENSE=\"{}\" setting nor have entries in the package.license file:".format(settings.get("ACCEPT_LICENSE")))
		for package, missing_licenses in packages_with_missing_licenses.items():
			missing_licenses = sorted(set(missing_licenses))
			print('{} {}'.format(package, ' '.join(missing_licenses)))

def process_args(argv):
	"""Option parsing via argc"""
	parser = argparse.ArgumentParser(prog=MY_PN,
		formatter_class=argparse.ArgumentDefaultsHelpFormatter,
		description='Finds installed packages in Gentoo' \
			' with non-accepted license(s).' \
			' Output can be used for package.license file.')

	parser.add_argument('-V', '--version', action='version', version="{} {}".format(MY_PN, MY_PV),
		help='show program version and exit')

	parser.add_argument('--debug', action='store_true', default=False,
		help='print debug messages to stderr')

	parser.add_argument('--eroot', action='store', default='/',
		help='Set EROOT.')

	return parser.parse_args(args=argv)

if __name__ == '__main__':
	sys.exit(main(sys.argv[1:]))
