aboutsummaryrefslogtreecommitdiff
path: root/sh/shrc.d/vr.sh
blob: c7057ec2be6ea8eac1c475b9458d16347d93bdba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Move to the root directory of a VCS working copy
vr() {

    # Set positional parameters to the result of trying to figure out the
    # repository root
    set -- "$(

        # Check we have at most one argument
        if [ "$#" -gt 1 ] ; then
            printf >&2 'vr(): Too many arguments\n'
            exit 2
        fi

        # Get path from first argument
        path=${1:-"$PWD"}

        # Strip a trailing slash
        case $path in
            (/) ;;
            (*) path=${path%/} ;;
        esac

        # Step into the directory
        cd -- "$path" || exit

        # Ask Git the top level (good)
        if git rev-parse --show-toplevel 2>/dev/null ; then
            printf /
            exit
        fi

        # Ask Mercurial the top level (great)
        if hg root 2>/dev/null ; then
            printf /
            exit
        fi

        # If we can get SVN info, iterate upwards until we cannot; hopefully
        # that is the root (bad)
        while svn info >/dev/null 2>&1 ; do
            root=$PWD
            ! [ "$root" = / ] || break
            cd .. || exit
        done
        if [ -n "$root" ] ; then
            printf '%s\n/' "$root"
            exit
        fi

        # Could not find repository root, say so
        printf >&2 'vr(): Failed to find repository root\n'
        exit 1
    )"

    # Chop the trailing newline and slash
    set -- "${1%?/}"

    # Check we figured out a target, or bail
    [ -n "$1" ] || return

    # Try to change into the determined directory
    command cd -- "$@"
}