#!/usr/bin/env python
"""
Tool to build partial debian mirrors (and more)
"""

# debpartial-mirror - partial debian mirror package tool
# (c) 2004 Otavio Salvador <otavio@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA	02111-1307	USA

# -------
# Imports
# -------
import getopt
import os
import signal
import sys

from debpartial_mirror import Config
from debpartial_mirror import Controller
from debpartial_mirror import Download

# ---------
# Variables
# ---------

# Defaults
version_str = '0.3.0'

conffile  = "/etc/debpartial-mirror.conf"

# User command descriptions
cmnds_desc = {
  'all':	 'Update, upgrade, merge the selected mirror(s)',
  'update':	 'Update selected mirror(s) (download Package and Source lists)',
  'upgrade': 'Upgrade selected mirror(s) (download binary and source packages)',
  'merge': 'Merge selected mirror(s)',
  'clean': 'Clean selected mirror(s)',
}

# Sorted list of user commands
cmnds_list = cmnds_desc.keys()
cmnds_list.sort()

# ---------
# Functions
# ---------

def version():
	"""Print package version"""
	print """debpartial-mirror %s - Partial mirroring tool for Debian
This program is free software and was released under the terms of the GNU General Public License
""" % (version_str)


def usage(ret=2):
	"""Print program usage message"""
	global conffile
	global cmnds_desc
	global cmnds_list

	cmnds_string = ""
	for c in cmnds_list:
		cmnds_string += "  %-27s %s\n" % (c, cmnds_desc[c])

	print """Usage: debpartial-mirror [OPTIONS] COMMAND [MIRROR ..]

Where OPTIONS is one of:
  -h, --help				 Display this help end exit
  -c, --configfile=FILE		 Select a config file (currently '%s')
  -v, --version				 Show program version

COMMAND is one of:
%s
And MIRROR selects which mirrors we should work with (all by default).
""" % (conffile, cmnds_string)
	sys.exit(ret)


def sigint_handler(signum, frame):
	d = Download.Download()
	if len (d.d_fetchers_list) > 0:
		d.wait_all()
	print "\n\rInterrupting download due a user request ..."
	sys.exit(1)


def main():
	"""Main program"""
	global conffile
	global cmnds_list
	global mirrors
	global merges

	cmnd = None

	# Parse options
	try:
		opts, args = getopt.getopt(sys.argv[1:], 'hvdc:',
								   ["help", "version", "debug", "configfile="])
	except getopt.GetoptError:
		print "ERROR reading program options\n"
		usage()

	for o, v in opts:
		if o in ("-h", "--help"):
			usage()
		if o in ("-v", "--version"):
			version()
			sys.exit(0)
		if o in ("-d", "--debug"):
			import logging
			logger = logging.getLogger()
			logger.setLevel(logging.DEBUG)
			logger.addHandler(logging.StreamHandler(sys.stderr))

		if o in ("-c", "--configfile"):
			if v == '':
				usage()
			conffile = v

	if not os.path.exists(conffile):
		print "ERROR: no configuration file %s" % conffile
		sys.exit(1)
		
	if not os.path.isfile(conffile):
		print "ERROR: %s is not a file" % conffile
		sys.exit(1)
		
	if len(args) > 0:
		cmnd = args[0]
	if cmnd not in cmnds_list:
		print "ERROR: Unknown command '%s'" % cmnd
		usage()

	mirrorNames = []
	if len(args) > 1:
		for i in range(1, len(args)):
			mirrorNames.append(args[i])

	# Load configuration file
	try:
		cnf = Config.Config(conffile)
	except Config.ConfigException, ex:
		print "ERROR: %s in file '%s'." % (ex.getErrorMessage(), conffile)
		sys.exit(1)

	# Verify if mirror names valid
	for mirror in mirrorNames:
		if not cnf.has_section(mirror):
			print("Unknown MIRROR [%s] on '%s'." % (mirrorNames, conffile))
			sys.exit(1)

	controller = Controller.Controller(cnf, mirrorNames)
	if not controller.isValidCommand(cmnd):
		usage()
	controller.executeCommand(cmnd)


# ------------
# Main Program
# ------------
if __name__ == '__main__':
	signal.signal(signal.SIGINT, sigint_handler)
	main()
