Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | # |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 3 | # git-submodules.sh: add, init, update or list git submodules |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 4 | # |
| 5 | # Copyright (c) 2007 Lars Hjemli |
| 6 | |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 7 | USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]' |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 8 | . git-sh-setup |
| 9 | require_work_tree |
| 10 | |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 11 | add= |
| 12 | branch= |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 13 | init= |
| 14 | update= |
| 15 | status= |
| 16 | quiet= |
| 17 | cached= |
| 18 | |
| 19 | # |
| 20 | # print stuff on stdout unless -q was specified |
| 21 | # |
| 22 | say() |
| 23 | { |
| 24 | if test -z "$quiet" |
| 25 | then |
| 26 | echo "$@" |
| 27 | fi |
| 28 | } |
| 29 | |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 30 | # NEEDSWORK: identical function exists in get_repo_base in clone.sh |
| 31 | get_repo_base() { |
| 32 | ( |
| 33 | cd "`/bin/pwd`" && |
| 34 | cd "$1" || cd "$1.git" && |
| 35 | { |
| 36 | cd .git |
| 37 | pwd |
| 38 | } |
| 39 | ) 2>/dev/null |
| 40 | } |
| 41 | |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 42 | # |
| 43 | # Map submodule path to submodule name |
| 44 | # |
| 45 | # $1 = path |
| 46 | # |
| 47 | module_name() |
| 48 | { |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 49 | name=$(GIT_CONFIG=.gitmodules git config --get-regexp '^submodule\..*\.path$' "$1" | |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 50 | sed -nre 's/^submodule\.(.+)\.path .+$/\1/p') |
| 51 | test -z "$name" && |
| 52 | die "No submodule mapping found in .gitmodules for path '$path'" |
| 53 | echo "$name" |
| 54 | } |
Lars Hjemli | 33aa6ff | 2007-06-06 11:13:01 +0200 | [diff] [blame] | 55 | |
| 56 | # |
| 57 | # Clone a submodule |
| 58 | # |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 59 | # Prior to calling, modules_update checks that a possibly existing |
| 60 | # path is not a git repository. |
| 61 | # Likewise, module_add checks that path does not exist at all, |
| 62 | # since it is the location of a new submodule. |
| 63 | # |
Lars Hjemli | 33aa6ff | 2007-06-06 11:13:01 +0200 | [diff] [blame] | 64 | module_clone() |
| 65 | { |
| 66 | path=$1 |
| 67 | url=$2 |
| 68 | |
| 69 | # If there already is a directory at the submodule path, |
| 70 | # expect it to be empty (since that is the default checkout |
| 71 | # action) and try to remove it. |
| 72 | # Note: if $path is a symlink to a directory the test will |
| 73 | # succeed but the rmdir will fail. We might want to fix this. |
| 74 | if test -d "$path" |
| 75 | then |
| 76 | rmdir "$path" 2>/dev/null || |
| 77 | die "Directory '$path' exist, but is neither empty nor a git repository" |
| 78 | fi |
| 79 | |
| 80 | test -e "$path" && |
| 81 | die "A file already exist at path '$path'" |
| 82 | |
| 83 | git-clone -n "$url" "$path" || |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 84 | die "Clone of '$url' into submodule path '$path' failed" |
Lars Hjemli | 33aa6ff | 2007-06-06 11:13:01 +0200 | [diff] [blame] | 85 | } |
| 86 | |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 87 | # |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 88 | # Add a new submodule to the working tree, .gitmodules and the index |
| 89 | # |
| 90 | # $@ = repo [path] |
| 91 | # |
| 92 | # optional branch is stored in global branch variable |
| 93 | # |
| 94 | module_add() |
| 95 | { |
| 96 | repo=$1 |
| 97 | path=$2 |
| 98 | |
| 99 | if test -z "$repo"; then |
| 100 | usage |
| 101 | fi |
| 102 | |
| 103 | # Turn the source into an absolute path if |
| 104 | # it is local |
| 105 | if base=$(get_repo_base "$repo"); then |
| 106 | repo="$base" |
| 107 | fi |
| 108 | |
| 109 | # Guess path from repo if not specified or strip trailing slashes |
| 110 | if test -z "$path"; then |
| 111 | path=$(echo "$repo" | sed -e 's|/*$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g') |
| 112 | else |
| 113 | path=$(echo "$path" | sed -e 's|/*$||') |
| 114 | fi |
| 115 | |
| 116 | test -e "$path" && |
| 117 | die "'$path' already exists" |
| 118 | |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 119 | git ls-files --error-unmatch "$path" > /dev/null 2>&1 && |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 120 | die "'$path' already exists in the index" |
| 121 | |
| 122 | module_clone "$path" "$repo" || exit |
| 123 | (unset GIT_DIR && cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) || |
| 124 | die "Unable to checkout submodule '$path'" |
| 125 | git add "$path" || |
| 126 | die "Failed to add submodule '$path'" |
| 127 | |
| 128 | GIT_CONFIG=.gitmodules git config submodule."$path".path "$path" && |
| 129 | GIT_CONFIG=.gitmodules git config submodule."$path".url "$repo" && |
| 130 | git add .gitmodules || |
| 131 | die "Failed to register submodule '$path'" |
| 132 | } |
| 133 | |
| 134 | # |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 135 | # Register submodules in .git/config |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 136 | # |
| 137 | # $@ = requested paths (default to all) |
| 138 | # |
| 139 | modules_init() |
| 140 | { |
| 141 | git ls-files --stage -- "$@" | grep -e '^160000 ' | |
| 142 | while read mode sha1 stage path |
| 143 | do |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 144 | # Skip already registered paths |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 145 | name=$(module_name "$path") || exit |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 146 | url=$(git config submodule."$name".url) |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 147 | test -z "$url" || continue |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 148 | |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 149 | url=$(GIT_CONFIG=.gitmodules git config submodule."$name".url) |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 150 | test -z "$url" && |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 151 | die "No url found for submodule path '$path' in .gitmodules" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 152 | |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 153 | git config submodule."$name".url "$url" || |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 154 | die "Failed to register url for submodule path '$path'" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 155 | |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 156 | say "Submodule '$name' ($url) registered for path '$path'" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 157 | done |
| 158 | } |
| 159 | |
| 160 | # |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 161 | # Update each submodule path to correct revision, using clone and checkout as needed |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 162 | # |
| 163 | # $@ = requested paths (default to all) |
| 164 | # |
| 165 | modules_update() |
| 166 | { |
| 167 | git ls-files --stage -- "$@" | grep -e '^160000 ' | |
| 168 | while read mode sha1 stage path |
| 169 | do |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 170 | name=$(module_name "$path") || exit |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 171 | url=$(git config submodule."$name".url) |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 172 | if test -z "$url" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 173 | then |
| 174 | # Only mention uninitialized submodules when its |
| 175 | # path have been specified |
| 176 | test "$#" != "0" && |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 177 | say "Submodule path '$path' not initialized" |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 178 | continue |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 179 | fi |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 180 | |
| 181 | if ! test -d "$path"/.git |
| 182 | then |
| 183 | module_clone "$path" "$url" || exit |
Lars Hjemli | bf2d824 | 2007-06-11 21:12:22 +0200 | [diff] [blame] | 184 | subsha1= |
| 185 | else |
| 186 | subsha1=$(unset GIT_DIR && cd "$path" && |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 187 | git rev-parse --verify HEAD) || |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 188 | die "Unable to find current revision in submodule path '$path'" |
Lars Hjemli | 211b7f1 | 2007-06-06 11:13:02 +0200 | [diff] [blame] | 189 | fi |
| 190 | |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 191 | if test "$subsha1" != "$sha1" |
| 192 | then |
| 193 | (unset GIT_DIR && cd "$path" && git-fetch && |
| 194 | git-checkout -q "$sha1") || |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 195 | die "Unable to checkout '$sha1' in submodule path '$path'" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 196 | |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 197 | say "Submodule path '$path': checked out '$sha1'" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 198 | fi |
| 199 | done |
| 200 | } |
| 201 | |
Emil Medve | bffe71f | 2007-06-26 18:40:58 -0500 | [diff] [blame] | 202 | set_name_rev () { |
| 203 | revname=$( ( |
| 204 | unset GIT_DIR && |
| 205 | cd "$1" && { |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 206 | git describe "$2" 2>/dev/null || |
| 207 | git describe --tags "$2" 2>/dev/null || |
| 208 | git describe --contains --tags "$2" |
Emil Medve | bffe71f | 2007-06-26 18:40:58 -0500 | [diff] [blame] | 209 | } |
| 210 | ) ) |
| 211 | test -z "$revname" || revname=" ($revname)" |
| 212 | } |
| 213 | |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 214 | # |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 215 | # List all submodules, prefixed with: |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 216 | # - submodule not initialized |
| 217 | # + different revision checked out |
| 218 | # |
| 219 | # If --cached was specified the revision in the index will be printed |
| 220 | # instead of the currently checked out revision. |
| 221 | # |
| 222 | # $@ = requested paths (default to all) |
| 223 | # |
| 224 | modules_list() |
| 225 | { |
| 226 | git ls-files --stage -- "$@" | grep -e '^160000 ' | |
| 227 | while read mode sha1 stage path |
| 228 | do |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 229 | name=$(module_name "$path") || exit |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 230 | url=$(git config submodule."$name".url) |
Lars Hjemli | 941987a | 2007-06-11 21:12:24 +0200 | [diff] [blame] | 231 | if test -z "url" || ! test -d "$path"/.git |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 232 | then |
| 233 | say "-$sha1 $path" |
| 234 | continue; |
| 235 | fi |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 236 | revname=$(unset GIT_DIR && cd "$path" && git describe --tags $sha1) |
CJ van den Berg | 41c7c1b | 2007-07-04 18:22:14 +0200 | [diff] [blame] | 237 | set_name_rev "$path" "$sha1" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 238 | if git diff-files --quiet -- "$path" |
| 239 | then |
Emil Medve | bffe71f | 2007-06-26 18:40:58 -0500 | [diff] [blame] | 240 | say " $sha1 $path$revname" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 241 | else |
| 242 | if test -z "$cached" |
| 243 | then |
Junio C Hamano | 5be6007 | 2007-07-02 22:52:14 -0700 | [diff] [blame] | 244 | sha1=$(unset GIT_DIR && cd "$path" && git rev-parse --verify HEAD) |
CJ van den Berg | 41c7c1b | 2007-07-04 18:22:14 +0200 | [diff] [blame] | 245 | set_name_rev "$path" "$sha1" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 246 | fi |
Emil Medve | bffe71f | 2007-06-26 18:40:58 -0500 | [diff] [blame] | 247 | say "+$sha1 $path$revname" |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 248 | fi |
| 249 | done |
| 250 | } |
| 251 | |
| 252 | while case "$#" in 0) break ;; esac |
| 253 | do |
| 254 | case "$1" in |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 255 | add) |
| 256 | add=1 |
| 257 | ;; |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 258 | init) |
| 259 | init=1 |
| 260 | ;; |
| 261 | update) |
| 262 | update=1 |
| 263 | ;; |
| 264 | status) |
| 265 | status=1 |
| 266 | ;; |
| 267 | -q|--quiet) |
| 268 | quiet=1 |
| 269 | ;; |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 270 | -b|--branch) |
| 271 | case "$2" in |
| 272 | '') |
| 273 | usage |
| 274 | ;; |
| 275 | esac |
| 276 | branch="$2"; shift |
| 277 | ;; |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 278 | --cached) |
| 279 | cached=1 |
| 280 | ;; |
| 281 | --) |
| 282 | break |
| 283 | ;; |
| 284 | -*) |
| 285 | usage |
| 286 | ;; |
| 287 | *) |
| 288 | break |
| 289 | ;; |
| 290 | esac |
| 291 | shift |
| 292 | done |
| 293 | |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 294 | case "$add,$branch" in |
| 295 | 1,*) |
| 296 | ;; |
| 297 | ,) |
| 298 | ;; |
| 299 | ,*) |
| 300 | usage |
| 301 | ;; |
| 302 | esac |
| 303 | |
| 304 | case "$add,$init,$update,$status,$cached" in |
| 305 | 1,,,,) |
| 306 | module_add "$@" |
| 307 | ;; |
| 308 | ,1,,,) |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 309 | modules_init "$@" |
| 310 | ;; |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 311 | ,,1,,) |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 312 | modules_update "$@" |
| 313 | ;; |
Sven Verdoolaege | ecda072 | 2007-06-24 23:06:07 +0200 | [diff] [blame] | 314 | ,,,1,*) |
Lars Hjemli | 70c7ac2 | 2007-05-26 15:56:40 +0200 | [diff] [blame] | 315 | modules_list "$@" |
| 316 | ;; |
| 317 | *) |
| 318 | usage |
| 319 | ;; |
| 320 | esac |