git-submodule: provide easy way of adding new submodules
authorSven Verdoolaege <skimo@kotnet.org>
Sun, 24 Jun 2007 21:06:07 +0000 (23:06 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 2 Jul 2007 08:33:44 +0000 (01:33 -0700)
To make a submodule effectively usable, the path and
a URL where the submodule can be cloned need to be stored
in .gitmodules.  This subcommand takes care of setting
this information after cloning the new submodule.
Only the index is updated, so, if needed, the user may still
change the URL or switch to a different branch of the submodule
before committing.

Signed-off-by: Sven Verdoolaege <skimo@kotnet.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-submodule.txt
git-submodule.sh

index f8fb80f18b91fc7a7044da261e54ef25988ced99..7f0904e2933613e1da2312bec28682d3accf2a1d 100644 (file)
@@ -8,11 +8,19 @@ git-submodule - Initialize, update or inspect submodules
 
 SYNOPSIS
 --------
+'git-submodule' [--quiet] [-b branch] add <repository> [<path>]
 'git-submodule' [--quiet] [--cached] [status|init|update] [--] [<path>...]
 
 
 COMMANDS
 --------
+add::
+       Add the given repository as a submodule at the given path
+       to the changeset to be committed next.  In particular, the
+       repository is cloned at the specified path, added to the
+       changeset and registered in .gitmodules.   If no path is
+       specified, the path is deduced from the repository specification.
+
 status::
        Show the status of the submodules. This will print the SHA-1 of the
        currently checked out commit for each submodule, along with the
@@ -39,6 +47,9 @@ OPTIONS
 -q, --quiet::
        Only print error messages.
 
+-b, --branch::
+       Branch of repository to add as submodule.
+
 --cached::
        Display the SHA-1 stored in the index, not the SHA-1 of the currently
        checked out submodule commit. This option is only valid for the
index 89a388535026258d65ecba3c0dd6de68e2b06cb4..67c78f2d3d9b867dd5e9c989aa6f9c4da1fbd301 100755 (executable)
@@ -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] [--] [<path>...]'
+USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]'
 . 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
 #
@@ -42,6 +56,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 +84,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
 #
@@ -173,6 +239,9 @@ modules_list()
 while case "$#" in 0) break ;; esac
 do
        case "$1" in
+       add)
+               add=1
+               ;;
        init)
                init=1
                ;;
@@ -185,6 +254,14 @@ do
        -q|--quiet)
                quiet=1
                ;;
+       -b|--branch)
+               case "$2" in
+               '')
+                       usage
+                       ;;
+               esac
+               branch="$2"; shift
+               ;;
        --cached)
                cached=1
                ;;
@@ -201,14 +278,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 "$@"
        ;;
-,,*,*)
+,,,1,*)
        modules_list "$@"
        ;;
 *)