git-submodule.shon commit Merge branch 'jk/add-empty' into ei/oneline+add-empty (1a15fed)
   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# Register submodules in .git/config
  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 already registered paths
  66                url=$(git-config submodule."$path".url)
  67                test -z "$url" || continue
  68
  69                url=$(GIT_CONFIG=.gitmodules git-config module."$path".url)
  70                test -z "$url" &&
  71                die "No url found for submodule '$path' in .gitmodules"
  72
  73                git-config submodule."$path".url "$url" ||
  74                die "Failed to register url for submodule '$path'"
  75
  76                say "Submodule '$path' registered with url '$url'"
  77        done
  78}
  79
  80#
  81# Update each submodule path to correct revision, using clone and checkout as needed
  82#
  83# $@ = requested paths (default to all)
  84#
  85modules_update()
  86{
  87        git ls-files --stage -- "$@" | grep -e '^160000 ' |
  88        while read mode sha1 stage path
  89        do
  90                url=$(git-config submodule."$path".url)
  91                if test -z "$url"
  92                then
  93                        # Only mention uninitialized submodules when its
  94                        # path have been specified
  95                        test "$#" != "0" &&
  96                        say "Submodule '$path' not initialized"
  97                        continue
  98                fi
  99
 100                if ! test -d "$path"/.git
 101                then
 102                        module_clone "$path" "$url" || exit
 103                fi
 104
 105                subsha1=$(unset GIT_DIR && cd "$path" &&
 106                        git-rev-parse --verify HEAD) ||
 107                die "Unable to find current revision of submodule '$path'"
 108
 109                if test "$subsha1" != "$sha1"
 110                then
 111                        (unset GIT_DIR && cd "$path" && git-fetch &&
 112                                git-checkout -q "$sha1") ||
 113                        die "Unable to checkout '$sha1' in submodule '$path'"
 114
 115                        say "Submodule '$path': checked out '$sha1'"
 116                fi
 117        done
 118}
 119
 120#
 121# List all registered submodules, prefixed with:
 122#  - submodule not initialized
 123#  + different revision checked out
 124#
 125# If --cached was specified the revision in the index will be printed
 126# instead of the currently checked out revision.
 127#
 128# $@ = requested paths (default to all)
 129#
 130modules_list()
 131{
 132        git ls-files --stage -- "$@" | grep -e '^160000 ' |
 133        while read mode sha1 stage path
 134        do
 135                if ! test -d "$path"/.git
 136                then
 137                        say "-$sha1 $path"
 138                        continue;
 139                fi
 140                revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1)
 141                if git diff-files --quiet -- "$path"
 142                then
 143                        say " $sha1 $path ($revname)"
 144                else
 145                        if test -z "$cached"
 146                        then
 147                                sha1=$(unset GIT_DIR && cd "$path" && git-rev-parse --verify HEAD)
 148                                revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1)
 149                        fi
 150                        say "+$sha1 $path ($revname)"
 151                fi
 152        done
 153}
 154
 155while case "$#" in 0) break ;; esac
 156do
 157        case "$1" in
 158        init)
 159                init=1
 160                ;;
 161        update)
 162                update=1
 163                ;;
 164        status)
 165                status=1
 166                ;;
 167        -q|--quiet)
 168                quiet=1
 169                ;;
 170        --cached)
 171                cached=1
 172                ;;
 173        --)
 174                break
 175                ;;
 176        -*)
 177                usage
 178                ;;
 179        *)
 180                break
 181                ;;
 182        esac
 183        shift
 184done
 185
 186case "$init,$update,$status,$cached" in
 1871,,,)
 188        modules_init "$@"
 189        ;;
 190,1,,)
 191        modules_update "$@"
 192        ;;
 193,,*,*)
 194        modules_list "$@"
 195        ;;
 196*)
 197        usage
 198        ;;
 199esac