Skip to content

Commit f31a522

Browse files
mark987gitster
authored andcommitted
git-submodule - allow a relative path as the subproject url
This allows a subproject's location to be specified and stored as relative to the parent project's location (e.g., ./foo, or ../foo). This url is stored in .gitmodules as given. It is resolved into an absolute url by appending it to the parent project's url when the information is written to .git/config (i.e., during submodule add for the originator, and submodule init for a downstream recipient). This allows cloning of the project to work "as expected" if the project is hosted on a different server than when the subprojects were added. Signed-off-by: Mark Levedahl <mdl123@verizon.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 41ef95a commit f31a522

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

Documentation/git-submodule.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ add::
2121
repository is cloned at the specified path, added to the
2222
changeset and registered in .gitmodules. If no path is
2323
specified, the path is deduced from the repository specification.
24+
If the repository url begins with ./ or ../, it is stored as
25+
given but resolved as a relative path from the main project's
26+
url when cloning.
2427

2528
status::
2629
Show the status of the submodules. This will print the SHA-1 of the

git-submodule.sh

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,32 @@ get_repo_base() {
3939
) 2>/dev/null
4040
}
4141

42+
# Resolve relative url by appending to parent's url
43+
resolve_relative_url ()
44+
{
45+
branch="$(git symbolic-ref HEAD 2>/dev/null)"
46+
remote="$(git config branch.${branch#refs/heads/}.remote)"
47+
remote="${remote:-origin}"
48+
remoteurl="$(git config remote.$remote.url)" ||
49+
die "remote ($remote) does not have a url in .git/config"
50+
url="$1"
51+
while test -n "$url"
52+
do
53+
case "$url" in
54+
../*)
55+
url="${url#../}"
56+
remoteurl="${remoteurl%/*}"
57+
;;
58+
./*)
59+
url="${url#./}"
60+
;;
61+
*)
62+
break;;
63+
esac
64+
done
65+
echo "$remoteurl/$url"
66+
}
67+
4268
#
4369
# Map submodule path to submodule name
4470
#
@@ -103,11 +129,19 @@ module_add()
103129
usage
104130
fi
105131

106-
# Turn the source into an absolute path if
107-
# it is local
108-
if base=$(get_repo_base "$repo"); then
109-
repo="$base"
110-
fi
132+
case "$repo" in
133+
./*|../*)
134+
# dereference source url relative to parent's url
135+
realrepo="$(resolve_relative_url $repo)" ;;
136+
*)
137+
# Turn the source into an absolute path if
138+
# it is local
139+
if base=$(get_repo_base "$repo"); then
140+
repo="$base"
141+
realrepo=$repo
142+
fi
143+
;;
144+
esac
111145

112146
# Guess path from repo if not specified or strip trailing slashes
113147
if test -z "$path"; then
@@ -122,7 +156,7 @@ module_add()
122156
git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
123157
die "'$path' already exists in the index"
124158

125-
module_clone "$path" "$repo" || exit
159+
module_clone "$path" "$realrepo" || exit
126160
(unset GIT_DIR && cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
127161
die "Unable to checkout submodule '$path'"
128162
git add "$path" ||
@@ -153,6 +187,13 @@ modules_init()
153187
test -z "$url" &&
154188
die "No url found for submodule path '$path' in .gitmodules"
155189

190+
# Possibly a url relative to parent
191+
case "$url" in
192+
./*|../*)
193+
url="$(resolve_relative_url "$url")"
194+
;;
195+
esac
196+
156197
git config submodule."$name".url "$url" ||
157198
die "Failed to register url for submodule path '$path'"
158199

0 commit comments

Comments
 (0)