#!/usr/local/bin/python2.6
# dulwich - Simple command-line interface to Dulwich
# 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.

"""Simple command-line interface to Dulwich>

This is a very simple command-line wrapper for Dulwich. It is by 
no means intended to be a full-blown Git command-line interface but just 
a way to test Dulwich.
"""

import os
import sys
from getopt import getopt

from dulwich.client import get_transport_and_path
from dulwich.errors import ApplyDeltaError
from dulwich.index import Index
from dulwich.pack import Pack, sha_to_hex
from dulwich.repo import Repo


def cmd_fetch_pack(args):
    opts, args = getopt(args, "", ["all"])
    opts = dict(opts)
    client, path = get_transport_and_path(args.pop(0))
    r = Repo(".")
    if "--all" in opts:
        determine_wants = r.object_store.determine_wants_all
    else:
        determine_wants = lambda x: [y for y in args if not y in r.object_store]
    graphwalker = r.get_graph_walker()
    client.fetch(path, r.object_store, determine_wants)


def cmd_log(args):
    opts, args = getopt(args, "", [])
    if len(args) > 0:
        path = args.pop(0)
    else:
        path = "."
    r = Repo(path)
    todo = [r.head()]
    done = set()
    while todo:
        sha = todo.pop()
        assert isinstance(sha, str)
        if sha in done:
            continue
        done.add(sha)
        commit = r[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):
    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_dump_index(args):
    opts, args = getopt(args, "", [])

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

    filename = args[0]
    idx = Index(filename)

    for o in idx:
        print o, idx[o]


def cmd_init(args):
    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):
    opts, args = getopt(args, "", [])
    opts = dict(opts)

    if args == []:
        print "usage: dulwich clone host:path [PATH]"
        sys.exit(1)
    client, host_path = get_transport_and_path(args.pop(0))

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

    if not os.path.exists(path):
        os.mkdir(path)
    r = Repo.init(path)
    remote_refs = client.fetch(host_path, r,
        determine_wants=r.object_store.determine_wants_all,
        progress=sys.stdout.write)
    r["HEAD"] = remote_refs["HEAD"]


def cmd_commit(args):
    opts, args = getopt(args, "", ["message"])
    opts = dict(opts)
    r = Repo(".")
    committer = "%s <%s>" % (os.getenv("GIT_COMMITTER_NAME"), 
                             os.getenv("GIT_COMMITTER_EMAIL"))
    author = "%s <%s>" % (os.getenv("GIT_AUTHOR_NAME"), 
                          os.getenv("GIT_AUTHOR_EMAIL"))
    r.do_commit(committer=committer, author=author, message=opts["--message"])


commands = {
    "commit": cmd_commit,
    "fetch-pack": cmd_fetch_pack,
    "dump-pack": cmd_dump_pack,
    "dump-index": cmd_dump_index,
    "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:])
