#!/usr/bin/python3 -s

# Copyright 2017 Delft Robotics BV
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the names of its contributors
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

import os
import os.path
import argparse
from glob import glob

from aprt.alpm import read_package_db_file
from aprt.version import Version

def valid_date(s):
	try:
		return datetime.strptime(s, "%Y-%m-%d")
	except ValueError:
		msg = "Not a valid date: '{0}'.".format(s)
		raise argparse.ArgumentTypeError(msg)

def is_package_file(name):
	return (False
		or name.endswith('.pkg.tar.xz')
		or name.endswith('.pkg.tar.gz')
		or name.endswith('.pkg.tar.bz2')
		or name.endswith('.pkg.tar')
	)

def main():
	parser = argparse.ArgumentParser(description='List or delete all binary packages that are no longer in a repository database.')
	parser.add_argument('-r', '--repository',       dest='repository',    required=True,           help='The repository database.')
	parser.add_argument('-v', '--verbose',          dest='verbose',       action='store_true',     help='Print more information.')
	parser.add_argument('--delete',                 dest='delete',        action='store_true',     help='Delete the package archives that are not in the repository database.')
	options = parser.parse_args()

	packages = filter(is_package_file, os.listdir(os.path.dirname(options.repository)))
	database = read_package_db_file(options.repository)

	for package in packages:
		filename = os.path.basename(package)
		pkgname, pkgver, pkgrel, arch = filename.rsplit('-', 3)
		arch = arch.split('.')[0]

		version = Version.parse('{}-{}'.format(pkgver, pkgrel))
		repo_package = None
		if pkgname in database:
			repo_package = database[pkgname]
		exact_match = repo_package is not None and repo_package.version() == version

		if options.verbose:
			if repo_package is None:
				print('{}-{}: package name not found in repository'.format(pkgname, version))
			elif not exact_match:
				print('{}-{}: found in repository, but wrong version: {}'.format(pkgname, version, repo_package.version()))
			else:
				print('{}-{}: found in repository with same version'.format(pkgname, version))
		elif not exact_match:
			print(package)

		if not exact_match and options.delete:
			os.unlink(package)

if __name__ == '__main__':
	main()
