git-submodule.shon commit git-submodule: move cloning into a separate function (33aa6ff)
   1#!/bin/sh
   2#
   3# git-submodules.sh: init, update or list git submodules
   4#
   5# Copyright (c) 2007 Lars Hjemli
   6
   7USAGE='[--quiet] [--cached] [status|init|update] [--] [<path>...]'
   8. git-sh-setup
   9require_work_tree
  10
  11init=
  12update=
  13status=
  14quiet=
  15cached=
  16
  17#
  18# print stuff on stdout unless -q was specified
  19#
  20say()
  21{
  22        if test -z "$quiet"
  23        then
  24                echo "$@"
  25        fi
  26}
  27
  28
  29#
  30# Clone a submodule
  31#
  32module_clone()
  33{
  34        path=$1
  35        url=$2
  36
  37        # If there already is a directory at the submodule path,
  38        # expect it to be empty (since that is the default checkout
  39        # action) and try to remove it.
  40        # Note: if $path is a symlink to a directory the test will
  41        # succeed but the rmdir will fail. We might want to fix this.
  42        if test -d "$path"
  43        then
  44                rmdir "$path" 2>/dev/null ||
  45                die "Directory '$path' exist, but is neither empty nor a git repository"
  46        fi
  47
  48        test -e "$path" &&
  49        die "A file already exist at path '$path'"
  50
  51        git-clone -n "$url" "$path" ||
  52        die "Clone of submodule '$path' failed"
  53}
  54
  55#
  56# Run clone + checkout on missing submodules
  57#
  58# $@ = requested paths (default to all)
  59#
  60modules_init()
  61{
  62        git ls-files --stage -- "$@" | grep -e '^160000 ' |
  63        while read mode sha1 stage path
  64        do
  65                # Skip submodule paths that already contain a .git directory.
  66                # This will also trigger if $path is a symlink to a git
  67                # repository
  68                test -d "$path"/.git && continue
  69
  70                url=$(GIT_CONFIG=.gitmodules git-config module."$path".url)
  71                test -z "$url" &&
  72                die "No url found for submodule '$path' in .gitmodules"
  73
  74                # MAYBE FIXME: this would be the place to check GIT_CONFIG
  75                # for a preferred url for this submodule, possibly like this:
  76                #
  77                # modname=$(GIT_CONFIG=.gitmodules git-config module."$path".name)
  78                # alturl=$(git-config module."$modname".url)
  79                #
  80                # This would let the versioned .gitmodules file use the submodule
  81                # path as key, while the unversioned GIT_CONFIG would use the
  82                # logical modulename (if present) as key. But this would need
  83                # another fallback mechanism if the module wasn't named.
  84
  85                module_clone "$path" "$url" || exit
  86
  87                (unset GIT_DIR && cd "$path" && git-checkout -q "$sha1") ||
  88                die "Checkout of submodule '$path' failed"
  89
  90                say "Submodule '$path' initialized"
  91        done
  92}
  93
  94#
  95# Checkout correct revision of each initialized submodule
  96#
  97# $@ = requested paths (default to all)
  98#
  99modules_update()
 100{
 101        git ls-files --stage -- "$@" | grep -e '^160000 ' |
 102        while read mode sha1 stage path
 103        do
 104                if ! test -d "$path"/.git
 105                then
 106                        # Only mention uninitialized submodules when its
 107                        # path have been specified
 108                        test "$#" != "0" &&
 109                        say "Submodule '$path' not initialized"
 110                        continue;
 111                fi
 112                subsha1=$(unset GIT_DIR && cd "$path" &&
 113                        git-rev-parse --verify HEAD) ||
 114                die "Unable to find current revision of submodule '$path'"
 115
 116                if test "$subsha1" != "$sha1"
 117                then
 118                        (unset GIT_DIR && cd "$path" && git-fetch &&
 119                                git-checkout -q "$sha1") ||
 120                        die "Unable to checkout '$sha1' in submodule '$path'"
 121
 122                        say "Submodule '$path': checked out '$sha1'"
 123                fi
 124        done
 125}
 126
 127#
 128# List all registered submodules, prefixed with:
 129#  - submodule not initialized
 130#  + different revision checked out
 131#
 132# If --cached was specified the revision in the index will be printed
 133# instead of the currently checked out revision.
 134#
 135# $@ = requested paths (default to all)
 136#
 137modules_list()
 138{
 139        git ls-files --stage -- "$@" | grep -e '^160000 ' |
 140        while read mode sha1 stage path
 141        do
 142                if ! test -d "$path"/.git
 143                then
 144                        say "-$sha1 $path"
 145                        continue;
 146                fi
 147                revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1)
 148                if git diff-files --quiet -- "$path"
 149                then
 150                        say " $sha1 $path ($revname)"
 151                else
 152                        if test -z "$cached"
 153                        then
 154                                sha1=$(unset GIT_DIR && cd "$path" && git-rev-parse --verify HEAD)
 155                                revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1)
 156                        fi
 157                        say "+$sha1 $path ($revname)"
 158                fi
 159        done
 160}
 161
 162while case "$#" in 0) break ;; esac
 163do
 164        case "$1" in
 165        init)
 166                init=1
 167                ;;
 168        update)
 169                update=1
 170                ;;
 171        status)
 172                status=1
 173                ;;
 174        -q|--quiet)
 175                quiet=1
 176                ;;
 177        --cached)
 178                cached=1
 179                ;;
 180        --)
 181                break
 182                ;;
 183        -*)
 184                usage
 185                ;;
 186        *)
 187                break
 188                ;;
 189        esac
 190        shift
 191done
 192
 193case "$init,$update,$status,$cached" in
 1941,,,)
 195        modules_init "$@"
 196        ;;
 197,1,,)
 198        modules_update "$@"
 199        ;;
 200,,*,*)
 201        modules_list "$@"
 202        ;;
 203*)
 204        usage
 205        ;;
 206esac