#
# 'git' bash completion 
#
# Copyright (c) Paolo Giarrusso, 2005
# Copyright (c) Ben Clifford, 2005
#

bashdefault="-o bashdefault"
default="-o default"
o_help="-h"

_git ()
{
    local cur cmd cmds
    cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=()

    if [ $COMP_CWORD -eq 1 ]; then
        cmds="$(git help -a | grep --regexp '^ ')"
        COMPREPLY=( $(compgen -W "${cmds}" -- $cur) )
    else
        local cmd=${COMP_WORDS[1]}
        
        case $cmd in
        branch)
            _git_branch
            ;;
        checkout)
            _git_checkout
            ;;
        cherry)
            _git_cherry
            ;;
        diff-tree)
            _git_diff_tree
            ;;
        fetch)
            _git_fetch
            ;;
        ls-tree)
            _git_ls_tree
            ;;
        name-rev)
            _git_name_rev
            ;;
        pull)
            _git_pull
            ;;
        push)
            _git_push
            ;;
        rebase)
            _git_rebase
            ;;
        show-branch)
            _git_show_branch
            ;;
        *)
            _git_default
            ;;
        esac
    fi
}

_git_branch ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    # git branch NEWBRANCHNAME BASE
    # always complete on branch names
    # XXX could probably just complete on the first 2 args
    COMPREPLY=( $(compgen -W "$(__git_refs)" -- $cur) )
}

_git_checkout ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=""
    local opts="-f -b" 

    if [ $COMP_CWORD -gt 1 ]; then
        prev=${COMP_WORDS[COMP_CWORD-1]}
    fi

    # git checkout [-f] [-b <new_branch>] [<branch>] [<paths>...]
    if [ "$prev" = "-b" ]; then 
        # complete on branch name
        COMPREPLY=( $(compgen -W "$(__git_heads)" -- $cur) )
    else
        COMPREPLY=( $(compgen -W "${opts} $(__git_heads)" -- $cur) )
        # XXX actually here, need to detect if it is the first 
        # non-option parameter - if so, complete with git_refs,
        # otherwise complete with filename
    fi
}

_git_cherry ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen -W "$(__git_refs)" -- $cur) )
}

_git_diff_tree ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local opts="--stdin -m -c --cc -s -v --pretty -t -r --root"

    #git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] [<common diff options>] <tree-ish> [<tree-ish>] [<path>...]
    COMPREPLY=( $(compgen -f -W "${opts} $(__git_heads)" -- $cur) )
}

_git_fetch ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen -W "$(__git_remotes)" -- $cur) )
}

_git_ls_tree ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    local opts="-d -r -t -z --name-only --name-status --full-name"
        
    #git ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] [--full-name] <tree-ish> [path...]
    # this is missing some functionality -- we should complete the 
    # first non-opt as a treeish, and the rest as paths but actually
    # what we do is just complete both treeish and paths for everything
    COMPREPLY=( $(compgen -f -W "${opts} $(__git_heads)" -- $cur) )
}

_git_name_rev ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen -W "--tags --all --stdin $(__git_refs)" -- $cur) )
}

_git_pull ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen -W "$(__git_remotes)" -- $cur) )
}

_git_push ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen -W "$(__git_remotes)" -- $cur) )
}

_git_rebase ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen -W "$(__git_refs)" -- $cur) )
}

_git_show_branch ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen -W "--all --heads --tags --topo-order --current --more= --list --independent --merge-base --no-name --sha1-name $(__git_refs)" -- $cur) )
}

_git_default ()
{
    local cur=${COMP_WORDS[COMP_CWORD]}

    COMPREPLY=( $(compgen $default -W "${o_help}" -f -- $cur) )
}

complete $default -F _git git
complete $default -F _git_branch git-branch
complete $default -F _git_checkout git-checkout
complete $default -F _git_cherry git-cherry
complete $default -F _git_diff_tree git-diff-tree
complete $default -F _git_fetch git-fetch
complete $default -F _git_ls_tree git-ls-tree
complete $default -F _git_name_rev git-name-rev
complete $default -F _git_pull git-pull
complete $default -F _git_push git-push
complete $default -F _git_rebase git-rebase
complete $default -F _git_show_branch git-show-branch

# TODO: complete any other git-* commands using _git_default

# vim: syntax=sh sw=4 ts=4 expandtab cindent :
