#!/scratchbox/tools/bin/python

# Copyright 2005  Movial
#
# 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.

# lib/apt.py -- This is an interface to the apt-get command.  It's
# intended to be used by other Python modules (especially build.py).  It
# also uses custom dir::etc::sourcelist and dir::state::lists settings.
# A command-line interface is provided for convenience.

import os, sys
import util

##
## Actions

sourcelist = "etc/sources.list"
listdir    = "work/lists"
builddir   = "work/build"

apt_command = "apt-get"
apt_options = ["-o", "dir::etc::sourcelist=" + os.path.join(os.getcwd(), sourcelist),
               "-o", "dir::state::lists="    + os.path.join(os.getcwd(), listdir)]

def update(architecture = None):
	"""Update the package lists (in work/lists) using the sources
	   specified in etc/sources.list.  ARCHITECTURE will be used for
	   binary packages (defaults to Scratchbox's target architecture)."""

	partial = "%s/partial" % listdir
	if not os.path.exists(partial):
		os.makedirs(partial)

	args = [apt_command] + apt_options + ["update"]

	if architecture:
		env = os.environ.copy()
		env["SBOX_DPKG_INST_ARCH"] = architecture

		return os.spawnvpe(os.P_WAIT, apt_command, args, env)
	else:
		return os.spawnvp(os.P_WAIT, apt_command, args)

def source(name, version = None):
	"""Downloads, extracts and patches a Debian source package (using
	   work/lists).  The package will be extracted under the work/build
	   directory."""

	if not os.path.exists(builddir):
		os.makedirs(builddir)

	if version:
		package = "%s=%s" % (name, version)
	else:
		package = name

	args = [apt_command] + apt_options + ["source", package]
	return util.spawn(apt_command, args, builddir)

def satisfy(name):
	"""check build dependencies"""
	args = [apt_command] + apt_options + ["--arch-only","-y","--force-yes"]  +["build-dep",name]
	return util.spawn(apt_command, args, builddir)

##
## Main

actions = {
	"update": (update, "[<architecture>]"),
	"source": (source, "<name>"),
	"satisfy": (satisfy, "<name>")
}

def usage():
	print >>sys.stderr, "Usage:",

	for action in actions:
		func, params = actions[action]
		print >>sys.stderr, "\t%s %s %s" % (sys.argv[0], action, params)

	sys.exit(1)

def main(args):
	"""Parses ARGS and invokes one of the "action" functions defined
	   in this module."""

	if len(args) < 1:
		usage()

	action = args[0]
	if action == "-h" or action.endswith("help"):
		usage()

	func, params = actions.get(action)
	if not func:
		usage()

	try:
		# The following is based on the assumption that function
		# invokation will throw TypeError when passing wrong
		# number of arguments.  It also assumes that all function
		# arguments are strings.  Should be fixed.

		status = eval("%s(%s)" % (func.__name__, str(args[1:])[1:-1]))

	except TypeError, e:
		print >>sys.stderr, e
		print >>sys.stderr
		usage()

	except KeyboardInterrupt:
		sys.exit(1)

	if status != 0:
		sys.exit(status)

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

