#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention Updater
#  repository addpackage
#
# Copyright 2004-2014 Univention GmbH
#
# http://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

import exceptions
import os
import shutil, sys
import getopt, time
import re

from univention.config_registry import ConfigRegistry
import univention.updater.repository as urepo
import univention.updater.tools

def usage(fd=sys.stdout):
	""" Print usage message """
	print >>fd, 'univention-repository-addpackage: tool for adding packages to local repository'
	print >>fd, 'copyright (c) 2004-@%@copyright_lastyear@%@ Univention GmbH, Germany'
	print >>fd, ''
	print >>fd, 'Syntax:'
	print >>fd, '  univention-repository-addpackage --dest <destination_dir> --file <debian_package> <debian_package>'
	print >>fd, '  univention-repository-addpackage [--help] '
	print >>fd, ''

def rewrite_url(url):
    """ Replace illegal characters in url with underscores """
    tmp = url
    illegal_chars = [',', '%', ' ']

    for i in illegal_chars:
        tmp = tmp.replace(i, '_')

    return tmp

# parse options
if __name__ == '__main__':

	if len(sys.argv) < 2:
		usage()
		sys.exit(1)

	if sys.argv[1] in ['-h', '-?', '--help']:
		usage()
		sys.exit(0)

	longopts=['dest=', 'file=' ]
	try:
		opts, args=getopt.getopt(sys.argv[1:], '', longopts)
	except getopt.error, msg:
		print msg
		sys.exit(1)

	files=[]
	packages_dir=''
	for opt, val in opts:
		if opt == '--dest':
			packages_dir=val
		elif opt == '--file':
			files.append(val)

	if len(files) > 0:
		for i in args:
			files.append(i)

	if not packages_dir:
		print >> sys.stderr, "Error: Destination directory not specified."
		sys.exit(1)

	# check if destination directory exists
	if not os.path.isdir(packages_dir):
		print >> sys.stderr, "Error: Destination either does not exist or is no directory."
		sys.exit(1)

	if len(files) < 1:
		print >> sys.stderr, "Error: No Debian packages specified."
		sys.exit(1)

	ucr = ConfigRegistry()
	ucr.load()

	if ucr.is_false('local/repository', True):
		print >> sys.stderr, 'Error: The local repository is disabled. Check if univention-debmirror ist installed.'
		sys.exit(1)

	try:
		lock = univention.updater.tools.updater_lock_acquire()
	except univention.updater.tools.LockingError, e:
		print >>sys.stderr, e
		sys.exit(5)
	try:
		packages_path = urepo.get_repo_basedir( packages_dir )

		# if file expansion is used (as in --file /tmp/*.deb), and no such file exists,
		# we should issue a warning
		fileProcessed = False

		regexp_arch = re.compile( '.*_([a-z0-9]*).deb' )
		for file in files:
			if file.endswith('.deb') and os.path.exists(file):
				fileProcessed = True
				match = regexp_arch.match( file )
				if not match:
					print >> sys.stderr, 'Warning: Could not determine architecture of package %s. It will not be added' % file
					continue
				arch = match.groups()
				targetfilename = os.path.join( packages_path, arch[ 0 ], rewrite_url( file.split( '/' )[ -1 ] ) )
				try:
					shutil.copyfile( os.path.join( file ), targetfilename )
				except Exception, e:
					print >> sys.stderr, "Warning: copying of %s failed: %s" % (file, str(e))
					if os.path.exists(targetfilename):
						os.remove(targetfilename) #remove incomplete package file
						print >>sys.stderr, "Warning: Removed incomplete file"
					if isinstance(e,exceptions.KeyboardInterrupt):
						out=os.popen('touch Packages.lock')
						print >>sys.stdout, "Interrupted by user."
						sys.exit(1)

		os.chdir(packages_dir)

		if not fileProcessed and not os.path.exists('Packages.lock'):
			print >>sys.stdout, "Warning: No packages found, no packages added"
			# shortcut exit, since there's nothing left to be done
			sys.exit(0)

		count=0
		if os.path.exists('Packages.lock') and count < 300:
			time.sleep(1)
			count=count+1

		# these might not exist if creating a new repository
		urepo.create_packages( packages_path, '.' )
		if packages_path[ -1 ] == '/':
			packages_path = packages_path[ : -1 ]

		head, tail = os.path.split( packages_path )
		for arch in urepo.ARCHITECTURES:
			urepo.create_packages( head, '%s/%s' % ( tail, arch ) )
	finally:
		if not univention.updater.tools.updater_lock_release(lock):
			print 'WARNING: updater-lock already released!'
