#!/usr/bin/python
# dul-daemon - Simple git smart server client
# Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.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; version 2
# or (at your option) a later version of the License.
# 
# 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., 51 Franklin Street, Fifth Floor, Boston,
# MA  02110-1301, USA.

import sys
from getopt import getopt

def cmd_fetch_pack(args):
	from dulwich.client import TCPGitClient, SimpleFetchGraphWalker
	from dulwich.repo import Repo
	opts, args = getopt(args, "", ["all"])
	opts = dict(opts)
	if not ":" in args[0]:
		print "Usage: dulwich fetch-pack [--all] host:path [REF...]"
		sys.exit(1)
	(host, path) = args.pop(0).split(":", 1)
	client = TCPGitClient(host)
	if "--all" in opts:
		determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
	else:
		determine_wants = lambda x: [y for y in args if not y in r.object_store]
	r = Repo(".")
	graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
	f, commit = r.object_store.add_pack()
	try:
		client.fetch_pack(path, determine_wants, graphwalker, f.write, sys.stdout.write)
		f.close()
		commit()
	except:
		f.close()
		raise


def cmd_log(args):
	from dulwich.repo import Repo
	opts, args = getopt(args, "", [])
	r = Repo(".")
	todo = [r.head()]
	done = set()
	while todo:
		sha = todo.pop()
		assert isinstance(sha, str)
		if sha in done:
			continue
		done.add(sha)
		commit = r.commit(sha)
		print "-" * 50
		print "commit: %s" % sha
		if len(commit.parents) > 1:
			print "merge: %s" % "...".join(commit.parents[1:])
		print "author: %s" % commit.author
		print "committer: %s" % commit.committer
		print ""
		print commit.message
		print ""
		todo.extend([p for p in commit.parents if p not in done])


def cmd_dump_pack(args):
	from dulwich.errors import ApplyDeltaError
	from dulwich.pack import Pack, sha_to_hex
	import os
	import sys

	opts, args = getopt(args, "", [])

	if args == []:
		print "Usage: dulwich dump-pack FILENAME"
		sys.exit(1)

	basename, _ = os.path.splitext(args[0])
	x = Pack(basename)
	print "Object names checksum: %s" % x.name()
	print "Checksum: %s" % sha_to_hex(x.get_stored_checksum())
	if not x.check():
		print "CHECKSUM DOES NOT MATCH"
	print "Length: %d" % len(x)
	for name in x:
		try:
			print "\t%s" % x[name]
		except KeyError, k:
			print "\t%s: Unable to resolve base %s" % (name, k)
		except ApplyDeltaError, e:
			print "\t%s: Unable to apply delta: %r" % (name, e)

def cmd_init(args):
	from dulwich.repo import Repo
	import os
	import sys
	opts, args = getopt(args, "", ["--bare"])
	opts = dict(opts)

	if args == []:
		path = os.getcwd()
	else:
		path = args[0]

	if not os.path.exists(path):
		os.mkdir(path)

	if "--bare" in opts:
		Repo.init_bare(path)
	else:
		Repo.init(path)


def cmd_clone(args):
	from dulwich.client import TCPGitClient, SimpleFetchGraphWalker
	from dulwich.repo import Repo
	import os
	import sys
	opts, args = getopt(args, "", [])
	opts = dict(opts)

	if args == []:
		print "usage: dulwich clone host:path [PATH]"
		sys.exit(1)

	if not ":" in args[0]:
		print "Usage: dulwich clone host:path [PATH]"
		sys.exit(1)
	(host, host_path) = args.pop(0).split(":", 1)
	client = TCPGitClient(host)

	if len(args) > 0:
		path = args.pop(0)
	else:
		path = host_path.split("/")[-1]

	if not os.path.exists(path):
		os.mkdir(path)
	Repo.init(path)
	r = Repo(path)
	determine_wants = lambda x: [y for y in x.values() if not y in r.object_store]
	graphwalker = SimpleFetchGraphWalker(r.heads().values(), r.get_parents)
	f, commit = r.object_store.add_pack()
	try:
		client.fetch_pack(host_path, determine_wants, graphwalker, f.write, 
				          sys.stdout.write)
		f.close()
		commit()
	except:
		f.close()
		raise


commands = {
	"fetch-pack": cmd_fetch_pack,
	"dump-pack": cmd_dump_pack,
	"init": cmd_init,
	"log": cmd_log,
	"clone": cmd_clone,
	}

if len(sys.argv) < 2:
	print "Usage: %s <%s> [OPTIONS...]" % (sys.argv[0], "|".join(commands.keys()))
	sys.exit(1)

cmd = sys.argv[1]
if not cmd in commands:
	print "No such subcommand: %s" % cmd
	sys.exit(1)
commands[cmd](sys.argv[2:])
