X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=git-submodule.sh;h=3320998c76ba72094755ec60369a6266751889ff;hb=b3abdd9d216c578383b66bb10b95edb3380640e7;hp=89a388535026258d65ecba3c0dd6de68e2b06cb4;hpb=fe5e7f332c8a95680a869eaca8033213676cbc7b;p=git.git diff --git a/git-submodule.sh b/git-submodule.sh index 89a388535..3320998c7 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -1,13 +1,15 @@ #!/bin/sh # -# git-submodules.sh: init, update or list git submodules +# git-submodules.sh: add, init, update or list git submodules # # Copyright (c) 2007 Lars Hjemli -USAGE='[--quiet] [--cached] [status|init|update] [--] [...]' +USAGE='[--quiet] [--cached] [add [-b branch]|status|init|update] [--] [...]' . git-sh-setup require_work_tree +add= +branch= init= update= status= @@ -25,6 +27,18 @@ say() fi } +# NEEDSWORK: identical function exists in get_repo_base in clone.sh +get_repo_base() { + ( + cd "`/bin/pwd`" && + cd "$1" || cd "$1.git" && + { + cd .git + pwd + } + ) 2>/dev/null +} + # # Map submodule path to submodule name # @@ -32,8 +46,11 @@ say() # module_name() { - name=$(GIT_CONFIG=.gitmodules git-config --get-regexp '^submodule\..*\.path$' "$1" | - sed -nre 's/^submodule\.(.+)\.path .+$/\1/p') + # Do we have "submodule..path = $1" defined in .gitmodules file? + re=$(printf '%s' "$1" | sed -e 's/\([^a-zA-Z0-9_]\)/\\\1/g') + name=$( GIT_CONFIG=.gitmodules \ + git config --get-regexp '^submodule\..*\.path$' | + sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' ) test -z "$name" && die "No submodule mapping found in .gitmodules for path '$path'" echo "$name" @@ -42,6 +59,11 @@ module_name() # # Clone a submodule # +# Prior to calling, modules_update checks that a possibly existing +# path is not a git repository. +# Likewise, module_add checks that path does not exist at all, +# since it is the location of a new submodule. +# module_clone() { path=$1 @@ -65,6 +87,53 @@ module_clone() die "Clone of '$url' into submodule path '$path' failed" } +# +# Add a new submodule to the working tree, .gitmodules and the index +# +# $@ = repo [path] +# +# optional branch is stored in global branch variable +# +module_add() +{ + repo=$1 + path=$2 + + if test -z "$repo"; then + usage + fi + + # Turn the source into an absolute path if + # it is local + if base=$(get_repo_base "$repo"); then + repo="$base" + fi + + # Guess path from repo if not specified or strip trailing slashes + if test -z "$path"; then + path=$(echo "$repo" | sed -e 's|/*$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g') + else + path=$(echo "$path" | sed -e 's|/*$||') + fi + + test -e "$path" && + die "'$path' already exists" + + git ls-files --error-unmatch "$path" > /dev/null 2>&1 && + die "'$path' already exists in the index" + + module_clone "$path" "$repo" || exit + (unset GIT_DIR && cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) || + die "Unable to checkout submodule '$path'" + git add "$path" || + die "Failed to add submodule '$path'" + + GIT_CONFIG=.gitmodules git config submodule."$path".path "$path" && + GIT_CONFIG=.gitmodules git config submodule."$path".url "$repo" && + git add .gitmodules || + die "Failed to register submodule '$path'" +} + # # Register submodules in .git/config # @@ -77,14 +146,14 @@ modules_init() do # Skip already registered paths name=$(module_name "$path") || exit - url=$(git-config submodule."$name".url) + url=$(git config submodule."$name".url) test -z "$url" || continue - url=$(GIT_CONFIG=.gitmodules git-config submodule."$name".url) + url=$(GIT_CONFIG=.gitmodules git config submodule."$name".url) test -z "$url" && die "No url found for submodule path '$path' in .gitmodules" - git-config submodule."$name".url "$url" || + git config submodule."$name".url "$url" || die "Failed to register url for submodule path '$path'" say "Submodule '$name' ($url) registered for path '$path'" @@ -102,7 +171,7 @@ modules_update() while read mode sha1 stage path do name=$(module_name "$path") || exit - url=$(git-config submodule."$name".url) + url=$(git config submodule."$name".url) if test -z "$url" then # Only mention uninitialized submodules when its @@ -118,7 +187,7 @@ modules_update() subsha1= else subsha1=$(unset GIT_DIR && cd "$path" && - git-rev-parse --verify HEAD) || + git rev-parse --verify HEAD) || die "Unable to find current revision in submodule path '$path'" fi @@ -133,6 +202,18 @@ modules_update() done } +set_name_rev () { + revname=$( ( + unset GIT_DIR && + cd "$1" && { + git describe "$2" 2>/dev/null || + git describe --tags "$2" 2>/dev/null || + git describe --contains --tags "$2" + } + ) ) + test -z "$revname" || revname=" ($revname)" +} + # # List all submodules, prefixed with: # - submodule not initialized @@ -149,23 +230,23 @@ modules_list() while read mode sha1 stage path do name=$(module_name "$path") || exit - url=$(git-config submodule."$name".url) + url=$(git config submodule."$name".url) if test -z "url" || ! test -d "$path"/.git then say "-$sha1 $path" continue; fi - revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1) + set_name_rev "$path" "$sha1" if git diff-files --quiet -- "$path" then - say " $sha1 $path ($revname)" + say " $sha1 $path$revname" else if test -z "$cached" then - sha1=$(unset GIT_DIR && cd "$path" && git-rev-parse --verify HEAD) - revname=$(unset GIT_DIR && cd "$path" && git-describe $sha1) + sha1=$(unset GIT_DIR && cd "$path" && git rev-parse --verify HEAD) + set_name_rev "$path" "$sha1" fi - say "+$sha1 $path ($revname)" + say "+$sha1 $path$revname" fi done } @@ -173,6 +254,9 @@ modules_list() while case "$#" in 0) break ;; esac do case "$1" in + add) + add=1 + ;; init) init=1 ;; @@ -185,6 +269,14 @@ do -q|--quiet) quiet=1 ;; + -b|--branch) + case "$2" in + '') + usage + ;; + esac + branch="$2"; shift + ;; --cached) cached=1 ;; @@ -201,14 +293,27 @@ do shift done -case "$init,$update,$status,$cached" in -1,,,) +case "$add,$branch" in +1,*) + ;; +,) + ;; +,*) + usage + ;; +esac + +case "$add,$init,$update,$status,$cached" in +1,,,,) + module_add "$@" + ;; +,1,,,) modules_init "$@" ;; -,1,,) +,,1,,) modules_update "$@" ;; -,,*,*) +,,,*,*) modules_list "$@" ;; *)