2007-05-26 17:56:40 +04:00
|
|
|
#!/bin/sh
|
|
|
|
#
|
2012-06-25 14:56:59 +04:00
|
|
|
# git-submodule.sh: add, init, update or list git submodules
|
2007-05-26 17:56:40 +04:00
|
|
|
#
|
|
|
|
# Copyright (c) 2007 Lars Hjemli
|
|
|
|
|
2009-08-19 05:45:19 +04:00
|
|
|
dashless=$(basename "$0" | sed -e 's/-/ /')
|
2019-02-15 12:26:41 +03:00
|
|
|
USAGE="[--quiet] [--cached]
|
|
|
|
or: $dashless [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
|
2009-08-19 05:45:24 +04:00
|
|
|
or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
|
2009-08-19 05:45:19 +04:00
|
|
|
or: $dashless [--quiet] init [--] [<path>...]
|
2016-05-05 22:52:32 +03:00
|
|
|
or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
|
2016-05-27 00:59:43 +03:00
|
|
|
or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]
|
2019-02-08 14:21:34 +03:00
|
|
|
or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>
|
2019-10-29 20:01:52 +03:00
|
|
|
or: $dashless [--quiet] set-url [--] <path> <newurl>
|
2009-08-28 03:59:25 +04:00
|
|
|
or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
|
2009-08-19 05:45:22 +04:00
|
|
|
or: $dashless [--quiet] foreach [--recursive] <command>
|
2017-01-11 23:59:17 +03:00
|
|
|
or: $dashless [--quiet] sync [--recursive] [--] [<path>...]
|
|
|
|
or: $dashless [--quiet] absorbgitdirs [--] [<path>...]"
|
2007-11-06 12:50:02 +03:00
|
|
|
OPTIONS_SPEC=
|
2013-06-16 18:18:18 +04:00
|
|
|
SUBDIRECTORY_OK=Yes
|
2007-05-26 17:56:40 +04:00
|
|
|
. git-sh-setup
|
2008-08-24 22:46:10 +04:00
|
|
|
. git-parse-remote
|
2007-05-26 17:56:40 +04:00
|
|
|
require_work_tree
|
2013-06-16 18:18:18 +04:00
|
|
|
wt_prefix=$(git rev-parse --show-prefix)
|
|
|
|
cd_to_toplevel
|
2007-05-26 17:56:40 +04:00
|
|
|
|
2016-12-15 01:39:52 +03:00
|
|
|
# Tell the rest of git that any URLs we get don't come
|
|
|
|
# directly from the user, so it can apply policy as appropriate.
|
|
|
|
GIT_PROTOCOL_FROM_USER=0
|
|
|
|
export GIT_PROTOCOL_FROM_USER
|
2015-09-16 20:13:12 +03:00
|
|
|
|
2008-01-15 13:48:45 +03:00
|
|
|
command=
|
2007-06-25 01:06:07 +04:00
|
|
|
branch=
|
2010-07-17 19:11:43 +04:00
|
|
|
force=
|
2009-05-04 23:30:01 +04:00
|
|
|
reference=
|
2007-05-26 17:56:40 +04:00
|
|
|
cached=
|
2010-04-26 13:50:39 +04:00
|
|
|
recursive=
|
|
|
|
init=
|
clone --recurse-submodules: prevent name squatting on Windows
In addition to preventing `.git` from being tracked by Git, on Windows
we also have to prevent `git~1` from being tracked, as the default NTFS
short name (also known as the "8.3 filename") for the file name `.git`
is `git~1`, otherwise it would be possible for malicious repositories to
write directly into the `.git/` directory, e.g. a `post-checkout` hook
that would then be executed _during_ a recursive clone.
When we implemented appropriate protections in 2b4c6efc821 (read-cache:
optionally disallow NTFS .git variants, 2014-12-16), we had analyzed
carefully that the `.git` directory or file would be guaranteed to be
the first directory entry to be written. Otherwise it would be possible
e.g. for a file named `..git` to be assigned the short name `git~1` and
subsequently, the short name generated for `.git` would be `git~2`. Or
`git~3`. Or even `~9999999` (for a detailed explanation of the lengths
we have to go to protect `.gitmodules`, see the commit message of
e7cb0b4455c (is_ntfs_dotgit: match other .git files, 2018-05-11)).
However, by exploiting two issues (that will be addressed in a related
patch series close by), it is currently possible to clone a submodule
into a non-empty directory:
- On Windows, file names cannot end in a space or a period (for
historical reasons: the period separating the base name from the file
extension was not actually written to disk, and the base name/file
extension was space-padded to the full 8/3 characters, respectively).
Helpfully, when creating a directory under the name, say, `sub.`, that
trailing period is trimmed automatically and the actual name on disk
is `sub`.
This means that while Git thinks that the submodule names `sub` and
`sub.` are different, they both access `.git/modules/sub/`.
- While the backslash character is a valid file name character on Linux,
it is not so on Windows. As Git tries to be cross-platform, it
therefore allows backslash characters in the file names stored in tree
objects.
Which means that it is totally possible that a submodule `c` sits next
to a file `c\..git`, and on Windows, during recursive clone a file
called `..git` will be written into `c/`, of course _before_ the
submodule is cloned.
Note that the actual exploit is not quite as simple as having a
submodule `c` next to a file `c\..git`, as we have to make sure that the
directory `.git/modules/b` already exists when the submodule is checked
out, otherwise a different code path is taken in `module_clone()` that
does _not_ allow a non-empty submodule directory to exist already.
Even if we will address both issues nearby (the next commit will
disallow backslash characters in tree entries' file names on Windows,
and another patch will disallow creating directories/files with trailing
spaces or periods), it is a wise idea to defend in depth against this
sort of attack vector: when submodules are cloned recursively, we now
_require_ the directory to be empty, addressing CVE-2019-1349.
Note: the code path we patch is shared with the code path of `git
submodule update --init`, which must not expect, in general, that the
directory is empty. Hence we have to introduce the new option
`--force-init` and hand it all the way down from `git submodule` to the
actual `git submodule--helper` process that performs the initial clone.
Reported-by: Nicolas Joly <Nicolas.Joly@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-12 15:20:39 +03:00
|
|
|
require_init=
|
2009-08-13 23:32:50 +04:00
|
|
|
files=
|
submodule update: add --remote for submodule's upstream changes
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 20:03:32 +04:00
|
|
|
remote=
|
2009-02-06 01:18:32 +03:00
|
|
|
nofetch=
|
Rename submodule.<name>.rebase to submodule.<name>.update
The addition of "submodule.<name>.rebase" demonstrates the usefulness of
alternatives to the default behaviour of "git submodule update". However,
by naming the config variable "submodule.<name>.rebase", and making it a
boolean choice, we are artificially constraining future git versions that
may want to add _more_ alternatives than just "rebase".
Therefore, while "submodule.<name>.rebase" is not yet in a stable git
release, future-proof it, by changing it from
submodule.<name>.rebase = true/false
to
submodule.<name>.update = rebase/checkout
where "checkout" specifies the default behaviour of "git submodule update"
(checking out the new commit to a detached HEAD), and "rebase" specifies
the --rebase behaviour (where the current local branch in the submodule is
rebase onto the new commit). Thus .update == checkout is equivalent to
.rebase == false, and .update == rebase is equivalent to .rebase == true.
Finally, leaving .update unset is equivalent to leaving .rebase unset.
In future git versions, other alternatives to "git submodule update"
behaviour can be included by adding them to the list of allowable values
for the submodule.<name>.update variable.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-03 10:27:06 +04:00
|
|
|
update=
|
2009-08-19 05:45:22 +04:00
|
|
|
prefix=
|
2012-09-30 03:05:58 +04:00
|
|
|
custom_name=
|
2013-07-03 01:42:56 +04:00
|
|
|
depth=
|
clone: pass --progress decision to recursive submodules
When cloning with "--recursive", we'd generally expect
submodules to show progress reports if the main clone did,
too.
In older versions of git, this mostly worked out of the
box. Since we show progress by default when stderr is a tty,
and since the child clones inherit the parent stderr, then
both processes would come to the same decision by default.
If the parent clone was asked for "--quiet", we passed down
"--quiet" to the child. However, if stderr was not a tty and
the user specified "--progress", we did not propagate this
to the child.
That's a minor bug, but things got much worse when we
switched recently to submodule--helper's update_clone
command. With that change, the stderr of the child clones
are always connected to a pipe, and we never output
progress at all.
This patch teaches git-submodule and git-submodule--helper
how to pass down an explicit "--progress" flag when cloning.
The clone command then decides to propagate that flag based
on the cloning decision made earlier (which takes into
account isatty(2) of the parent process, existing --progress
or --quiet flags, etc). Since the child processes always run
without a tty on stderr, we don't have to worry about
passing an explicit "--no-progress"; it's the default for
them.
This fixes the recent loss of progress during recursive
clones. And as a bonus, it makes:
git clone --recursive --progress ... 2>&1 | cat
work by triggering progress explicitly in the children.
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-22 08:24:46 +03:00
|
|
|
progress=
|
2018-05-03 13:53:46 +03:00
|
|
|
dissociate=
|
2007-05-26 17:56:40 +04:00
|
|
|
|
2012-08-15 00:35:27 +04:00
|
|
|
die_if_unmatched ()
|
|
|
|
{
|
|
|
|
if test "$1" = "#unmatched"
|
|
|
|
then
|
2016-07-22 22:14:38 +03:00
|
|
|
exit ${2:-1}
|
2012-08-15 00:35:27 +04:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2012-12-11 22:58:15 +04:00
|
|
|
#
|
|
|
|
# Print a submodule configuration setting
|
|
|
|
#
|
|
|
|
# $1 = submodule name
|
|
|
|
# $2 = option name
|
|
|
|
# $3 = default value
|
|
|
|
#
|
|
|
|
# Checks in the usual git-config places first (for overrides),
|
|
|
|
# otherwise it falls back on .gitmodules. This allows you to
|
|
|
|
# distribute project-wide defaults in .gitmodules, while still
|
|
|
|
# customizing individual repositories if necessary. If the option is
|
|
|
|
# not in .gitmodules either, print a default value.
|
|
|
|
#
|
|
|
|
get_submodule_config () {
|
|
|
|
name="$1"
|
|
|
|
option="$2"
|
|
|
|
default="$3"
|
|
|
|
value=$(git config submodule."$name"."$option")
|
|
|
|
if test -z "$value"
|
|
|
|
then
|
2018-10-05 16:05:57 +03:00
|
|
|
value=$(git submodule--helper config submodule."$name"."$option")
|
2012-12-11 22:58:15 +04:00
|
|
|
fi
|
|
|
|
printf '%s' "${value:-$default}"
|
|
|
|
}
|
|
|
|
|
2013-04-01 17:06:27 +04:00
|
|
|
isnumber()
|
|
|
|
{
|
|
|
|
n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
|
|
|
|
}
|
|
|
|
|
2018-10-15 03:02:01 +03:00
|
|
|
# Given a full hex object ID, is this the zero OID?
|
|
|
|
is_zero_oid () {
|
|
|
|
echo "$1" | sane_egrep '^0+$' >/dev/null 2>&1
|
|
|
|
}
|
|
|
|
|
2016-03-01 01:58:35 +03:00
|
|
|
# Sanitize the local git environment for use within a submodule. We
|
|
|
|
# can't simply use clear_local_git_env since we want to preserve some
|
|
|
|
# of the settings from GIT_CONFIG_PARAMETERS.
|
|
|
|
sanitize_submodule_env()
|
|
|
|
{
|
submodule: stop sanitizing config options
The point of having a whitelist of command-line config
options to pass to submodules was two-fold:
1. It prevented obvious nonsense like using core.worktree
for multiple repos.
2. It could prevent surprise when the user did not mean
for the options to leak to the submodules (e.g.,
http.sslverify=false).
For case 1, the answer is mostly "if it hurts, don't do
that". For case 2, we can note that any such example has a
matching inverted surprise (e.g., a user who meant
http.sslverify=true to apply everywhere, but it didn't).
So this whitelist is probably not giving us any benefit, and
is already creating a hassle as people propose things to put
on it. Let's just drop it entirely.
Note that we still need to keep a special code path for
"prepare the submodule environment", because we still have
to take care to pass through $GIT_CONFIG_PARAMETERS (and
block the rest of the repo-specific environment variables).
We can do this easily from within the submodule shell
script, which lets us drop the submodule--helper option
entirely (and it's OK to do so because as a "--" program, it
is entirely a private implementation detail).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-05-05 04:22:19 +03:00
|
|
|
save_config=$GIT_CONFIG_PARAMETERS
|
2016-03-01 01:58:35 +03:00
|
|
|
clear_local_git_env
|
submodule: stop sanitizing config options
The point of having a whitelist of command-line config
options to pass to submodules was two-fold:
1. It prevented obvious nonsense like using core.worktree
for multiple repos.
2. It could prevent surprise when the user did not mean
for the options to leak to the submodules (e.g.,
http.sslverify=false).
For case 1, the answer is mostly "if it hurts, don't do
that". For case 2, we can note that any such example has a
matching inverted surprise (e.g., a user who meant
http.sslverify=true to apply everywhere, but it didn't).
So this whitelist is probably not giving us any benefit, and
is already creating a hassle as people propose things to put
on it. Let's just drop it entirely.
Note that we still need to keep a special code path for
"prepare the submodule environment", because we still have
to take care to pass through $GIT_CONFIG_PARAMETERS (and
block the rest of the repo-specific environment variables).
We can do this easily from within the submodule shell
script, which lets us drop the submodule--helper option
entirely (and it's OK to do so because as a "--" program, it
is entirely a private implementation detail).
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-05-05 04:22:19 +03:00
|
|
|
GIT_CONFIG_PARAMETERS=$save_config
|
2016-04-28 16:37:44 +03:00
|
|
|
export GIT_CONFIG_PARAMETERS
|
2016-03-01 01:58:35 +03:00
|
|
|
}
|
|
|
|
|
2007-06-25 01:06:07 +04:00
|
|
|
#
|
|
|
|
# Add a new submodule to the working tree, .gitmodules and the index
|
|
|
|
#
|
git-submodule - make "submodule add" more strict, and document it
This change makes "submodule add" much more strict in the arguments it
takes, and is intended to address confusion as recently noted on the
git-list. With this change, the required syntax is:
$ git submodule add URL path
Specifically, this eliminates the form
$ git submodule add URL
which was confused by more than one person as
$ git submodule add path
With this patch, the URL locating the submodule's origin repository can be
either an absolute URL, or (if it begins with ./ or ../) can express the
submodule's repository location relative to the superproject's origin.
This patch also eliminates a third form of URL, which was relative to the
superproject's top-level directory (not its repository). Any URL that was
neither absolute nor matched ./*|../* was assumed to point to a
subdirectory of the superproject as the location of the submodule's origin
repository. This URL form was confusing and does not seem to correspond
to an important use-case. Specifically, no-one has identified the need to
clone from a repository already in the superproject's tree, but if this is
needed it is easily done using an absolute URL: $(pwd)/relative-path. So,
no functionality is lost with this patch. (t6008-rev-list-submodule.sh did
rely upon this relative URL, fixed by using $(pwd).)
Following this change, there are exactly four variants of
submodule-add, as both arguments have two flavors:
URL can be absolute, or can begin with ./|../ and thus names the
submodule's origin relative to the superproject's origin.
Note: With this patch, "submodule add" discerns an absolute URL as
matching /*|*:*: e.g., URL begins with /, or it contains a :. This works
for all valid URLs, an absolute path in POSIX, as well as an absolute path
on Windows).
path can either already exist as a valid git repo, or will be cloned from
the given URL. The first form here eases creation of a new submodule in
an existing superproject as the submodule can be added and tested in-tree
before pushing to the public repository. However, the more usual form is
the second, where the repo is cloned from the given URL.
This specifically addresses the issue of
$ git submodule add a/b/c
attempting to clone from a repository at "a/b/c" to create a new module
in "c". This also simplifies description of "relative URL" as there is now
exactly *one* form: a URL relative to the parent's origin repo.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-10 05:05:40 +04:00
|
|
|
# $@ = repo path
|
2007-06-25 01:06:07 +04:00
|
|
|
#
|
|
|
|
# optional branch is stored in global branch variable
|
|
|
|
#
|
2008-01-15 13:35:49 +03:00
|
|
|
cmd_add()
|
2007-06-25 01:06:07 +04:00
|
|
|
{
|
2008-01-15 13:48:45 +03:00
|
|
|
# parse $args after "submodule ... add".
|
2013-06-16 18:18:18 +04:00
|
|
|
reference_path=
|
2008-01-15 13:48:45 +03:00
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-b | --branch)
|
|
|
|
case "$2" in '') usage ;; esac
|
|
|
|
branch=$2
|
|
|
|
shift
|
|
|
|
;;
|
2010-07-17 19:11:43 +04:00
|
|
|
-f | --force)
|
|
|
|
force=$1
|
|
|
|
;;
|
2008-01-15 13:48:45 +03:00
|
|
|
-q|--quiet)
|
2009-06-17 02:33:00 +04:00
|
|
|
GIT_QUIET=1
|
2008-01-15 13:48:45 +03:00
|
|
|
;;
|
2018-05-03 13:53:45 +03:00
|
|
|
--progress)
|
|
|
|
progress=1
|
|
|
|
;;
|
2009-05-04 23:30:01 +04:00
|
|
|
--reference)
|
|
|
|
case "$2" in '') usage ;; esac
|
2013-06-16 18:18:18 +04:00
|
|
|
reference_path=$2
|
2009-05-04 23:30:01 +04:00
|
|
|
shift
|
|
|
|
;;
|
|
|
|
--reference=*)
|
2013-06-16 18:18:18 +04:00
|
|
|
reference_path="${1#--reference=}"
|
2009-05-04 23:30:01 +04:00
|
|
|
;;
|
2018-05-03 13:53:46 +03:00
|
|
|
--dissociate)
|
|
|
|
dissociate=1
|
|
|
|
;;
|
2012-09-30 03:05:58 +04:00
|
|
|
--name)
|
|
|
|
case "$2" in '') usage ;; esac
|
|
|
|
custom_name=$2
|
|
|
|
shift
|
|
|
|
;;
|
2013-07-03 01:42:56 +04:00
|
|
|
--depth)
|
|
|
|
case "$2" in '') usage ;; esac
|
|
|
|
depth="--depth=$2"
|
|
|
|
shift
|
|
|
|
;;
|
|
|
|
--depth=*)
|
|
|
|
depth=$1
|
|
|
|
;;
|
2008-01-15 13:48:45 +03:00
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
2018-10-25 19:18:12 +03:00
|
|
|
if ! git submodule--helper config --check-writeable >/dev/null 2>&1
|
|
|
|
then
|
|
|
|
die "$(eval_gettext "please make sure that the .gitmodules file is in the working tree")"
|
|
|
|
fi
|
|
|
|
|
2013-06-16 18:18:18 +04:00
|
|
|
if test -n "$reference_path"
|
|
|
|
then
|
|
|
|
is_absolute_path "$reference_path" ||
|
|
|
|
reference_path="$wt_prefix$reference_path"
|
|
|
|
|
|
|
|
reference="--reference=$reference_path"
|
|
|
|
fi
|
|
|
|
|
2007-06-25 01:06:07 +04:00
|
|
|
repo=$1
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
sm_path=$2
|
2007-06-25 01:06:07 +04:00
|
|
|
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
if test -z "$sm_path"; then
|
2014-06-10 19:33:39 +04:00
|
|
|
sm_path=$(printf '%s\n' "$repo" |
|
2009-09-22 19:10:12 +04:00
|
|
|
sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
|
|
|
|
fi
|
|
|
|
|
2014-06-10 16:28:33 +04:00
|
|
|
if test -z "$repo" || test -z "$sm_path"; then
|
2007-06-25 01:06:07 +04:00
|
|
|
usage
|
|
|
|
fi
|
|
|
|
|
2013-06-16 18:18:18 +04:00
|
|
|
is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
|
|
|
|
|
git-submodule - make "submodule add" more strict, and document it
This change makes "submodule add" much more strict in the arguments it
takes, and is intended to address confusion as recently noted on the
git-list. With this change, the required syntax is:
$ git submodule add URL path
Specifically, this eliminates the form
$ git submodule add URL
which was confused by more than one person as
$ git submodule add path
With this patch, the URL locating the submodule's origin repository can be
either an absolute URL, or (if it begins with ./ or ../) can express the
submodule's repository location relative to the superproject's origin.
This patch also eliminates a third form of URL, which was relative to the
superproject's top-level directory (not its repository). Any URL that was
neither absolute nor matched ./*|../* was assumed to point to a
subdirectory of the superproject as the location of the submodule's origin
repository. This URL form was confusing and does not seem to correspond
to an important use-case. Specifically, no-one has identified the need to
clone from a repository already in the superproject's tree, but if this is
needed it is easily done using an absolute URL: $(pwd)/relative-path. So,
no functionality is lost with this patch. (t6008-rev-list-submodule.sh did
rely upon this relative URL, fixed by using $(pwd).)
Following this change, there are exactly four variants of
submodule-add, as both arguments have two flavors:
URL can be absolute, or can begin with ./|../ and thus names the
submodule's origin relative to the superproject's origin.
Note: With this patch, "submodule add" discerns an absolute URL as
matching /*|*:*: e.g., URL begins with /, or it contains a :. This works
for all valid URLs, an absolute path in POSIX, as well as an absolute path
on Windows).
path can either already exist as a valid git repo, or will be cloned from
the given URL. The first form here eases creation of a new submodule in
an existing superproject as the submodule can be added and tested in-tree
before pushing to the public repository. However, the more usual form is
the second, where the repo is cloned from the given URL.
This specifically addresses the issue of
$ git submodule add a/b/c
attempting to clone from a repository at "a/b/c" to create a new module
in "c". This also simplifies description of "relative URL" as there is now
exactly *one* form: a URL relative to the parent's origin repo.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-10 05:05:40 +04:00
|
|
|
# assure repo is absolute or relative to parent
|
|
|
|
case "$repo" in
|
|
|
|
./*|../*)
|
2013-06-16 18:18:18 +04:00
|
|
|
test -z "$wt_prefix" ||
|
|
|
|
die "$(gettext "Relative path can only be used from the toplevel of the working tree")"
|
|
|
|
|
git-submodule - make "submodule add" more strict, and document it
This change makes "submodule add" much more strict in the arguments it
takes, and is intended to address confusion as recently noted on the
git-list. With this change, the required syntax is:
$ git submodule add URL path
Specifically, this eliminates the form
$ git submodule add URL
which was confused by more than one person as
$ git submodule add path
With this patch, the URL locating the submodule's origin repository can be
either an absolute URL, or (if it begins with ./ or ../) can express the
submodule's repository location relative to the superproject's origin.
This patch also eliminates a third form of URL, which was relative to the
superproject's top-level directory (not its repository). Any URL that was
neither absolute nor matched ./*|../* was assumed to point to a
subdirectory of the superproject as the location of the submodule's origin
repository. This URL form was confusing and does not seem to correspond
to an important use-case. Specifically, no-one has identified the need to
clone from a repository already in the superproject's tree, but if this is
needed it is easily done using an absolute URL: $(pwd)/relative-path. So,
no functionality is lost with this patch. (t6008-rev-list-submodule.sh did
rely upon this relative URL, fixed by using $(pwd).)
Following this change, there are exactly four variants of
submodule-add, as both arguments have two flavors:
URL can be absolute, or can begin with ./|../ and thus names the
submodule's origin relative to the superproject's origin.
Note: With this patch, "submodule add" discerns an absolute URL as
matching /*|*:*: e.g., URL begins with /, or it contains a :. This works
for all valid URLs, an absolute path in POSIX, as well as an absolute path
on Windows).
path can either already exist as a valid git repo, or will be cloned from
the given URL. The first form here eases creation of a new submodule in
an existing superproject as the submodule can be added and tested in-tree
before pushing to the public repository. However, the more usual form is
the second, where the repo is cloned from the given URL.
This specifically addresses the issue of
$ git submodule add a/b/c
attempting to clone from a repository at "a/b/c" to create a new module
in "c". This also simplifies description of "relative URL" as there is now
exactly *one* form: a URL relative to the parent's origin repo.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-10 05:05:40 +04:00
|
|
|
# dereference source url relative to parent's url
|
2016-04-16 03:50:12 +03:00
|
|
|
realrepo=$(git submodule--helper resolve-relative-url "$repo") || exit
|
git-submodule - make "submodule add" more strict, and document it
This change makes "submodule add" much more strict in the arguments it
takes, and is intended to address confusion as recently noted on the
git-list. With this change, the required syntax is:
$ git submodule add URL path
Specifically, this eliminates the form
$ git submodule add URL
which was confused by more than one person as
$ git submodule add path
With this patch, the URL locating the submodule's origin repository can be
either an absolute URL, or (if it begins with ./ or ../) can express the
submodule's repository location relative to the superproject's origin.
This patch also eliminates a third form of URL, which was relative to the
superproject's top-level directory (not its repository). Any URL that was
neither absolute nor matched ./*|../* was assumed to point to a
subdirectory of the superproject as the location of the submodule's origin
repository. This URL form was confusing and does not seem to correspond
to an important use-case. Specifically, no-one has identified the need to
clone from a repository already in the superproject's tree, but if this is
needed it is easily done using an absolute URL: $(pwd)/relative-path. So,
no functionality is lost with this patch. (t6008-rev-list-submodule.sh did
rely upon this relative URL, fixed by using $(pwd).)
Following this change, there are exactly four variants of
submodule-add, as both arguments have two flavors:
URL can be absolute, or can begin with ./|../ and thus names the
submodule's origin relative to the superproject's origin.
Note: With this patch, "submodule add" discerns an absolute URL as
matching /*|*:*: e.g., URL begins with /, or it contains a :. This works
for all valid URLs, an absolute path in POSIX, as well as an absolute path
on Windows).
path can either already exist as a valid git repo, or will be cloned from
the given URL. The first form here eases creation of a new submodule in
an existing superproject as the submodule can be added and tested in-tree
before pushing to the public repository. However, the more usual form is
the second, where the repo is cloned from the given URL.
This specifically addresses the issue of
$ git submodule add a/b/c
attempting to clone from a repository at "a/b/c" to create a new module
in "c". This also simplifies description of "relative URL" as there is now
exactly *one* form: a URL relative to the parent's origin repo.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-10 05:05:40 +04:00
|
|
|
;;
|
|
|
|
*:*|/*)
|
|
|
|
# absolute url
|
|
|
|
realrepo=$repo
|
|
|
|
;;
|
|
|
|
*)
|
2011-05-21 22:44:01 +04:00
|
|
|
die "$(eval_gettext "repo URL: '\$repo' must be absolute or begin with ./|../")"
|
git-submodule - make "submodule add" more strict, and document it
This change makes "submodule add" much more strict in the arguments it
takes, and is intended to address confusion as recently noted on the
git-list. With this change, the required syntax is:
$ git submodule add URL path
Specifically, this eliminates the form
$ git submodule add URL
which was confused by more than one person as
$ git submodule add path
With this patch, the URL locating the submodule's origin repository can be
either an absolute URL, or (if it begins with ./ or ../) can express the
submodule's repository location relative to the superproject's origin.
This patch also eliminates a third form of URL, which was relative to the
superproject's top-level directory (not its repository). Any URL that was
neither absolute nor matched ./*|../* was assumed to point to a
subdirectory of the superproject as the location of the submodule's origin
repository. This URL form was confusing and does not seem to correspond
to an important use-case. Specifically, no-one has identified the need to
clone from a repository already in the superproject's tree, but if this is
needed it is easily done using an absolute URL: $(pwd)/relative-path. So,
no functionality is lost with this patch. (t6008-rev-list-submodule.sh did
rely upon this relative URL, fixed by using $(pwd).)
Following this change, there are exactly four variants of
submodule-add, as both arguments have two flavors:
URL can be absolute, or can begin with ./|../ and thus names the
submodule's origin relative to the superproject's origin.
Note: With this patch, "submodule add" discerns an absolute URL as
matching /*|*:*: e.g., URL begins with /, or it contains a :. This works
for all valid URLs, an absolute path in POSIX, as well as an absolute path
on Windows).
path can either already exist as a valid git repo, or will be cloned from
the given URL. The first form here eases creation of a new submodule in
an existing superproject as the submodule can be added and tested in-tree
before pushing to the public repository. However, the more usual form is
the second, where the repo is cloned from the given URL.
This specifically addresses the issue of
$ git submodule add a/b/c
attempting to clone from a repository at "a/b/c" to create a new module
in "c". This also simplifies description of "relative URL" as there is now
exactly *one* form: a URL relative to the parent's origin repo.
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-10 05:05:40 +04:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
2009-03-03 18:08:21 +03:00
|
|
|
# normalize path:
|
|
|
|
# multiple //; leading ./; /./; /../; trailing /
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
sm_path=$(printf '%s/\n' "$sm_path" |
|
2009-03-03 18:08:21 +03:00
|
|
|
sed -e '
|
|
|
|
s|//*|/|g
|
|
|
|
s|^\(\./\)*||
|
2015-01-30 18:14:03 +03:00
|
|
|
s|/\(\./\)*|/|g
|
2009-03-03 18:08:21 +03:00
|
|
|
:start
|
|
|
|
s|\([^/]*\)/\.\./||
|
|
|
|
tstart
|
|
|
|
s|/*$||
|
|
|
|
')
|
2016-10-06 22:37:24 +03:00
|
|
|
if test -z "$force"
|
|
|
|
then
|
|
|
|
git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
|
|
|
|
die "$(eval_gettext "'\$sm_path' already exists in the index")"
|
|
|
|
else
|
|
|
|
git ls-files -s "$sm_path" | sane_grep -v "^160000" > /dev/null 2>&1 &&
|
|
|
|
die "$(eval_gettext "'\$sm_path' already exists in the index and is not a submodule")"
|
|
|
|
fi
|
2007-06-25 01:06:07 +04:00
|
|
|
|
2019-04-10 02:07:35 +03:00
|
|
|
if test -d "$sm_path" &&
|
|
|
|
test -z $(git -C "$sm_path" rev-parse --show-cdup 2>/dev/null)
|
|
|
|
then
|
|
|
|
git -C "$sm_path" rev-parse --verify -q HEAD >/dev/null ||
|
|
|
|
die "$(eval_gettext "'\$sm_path' does not have a commit checked out")"
|
|
|
|
fi
|
|
|
|
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 13:58:22 +03:00
|
|
|
if test -z "$force" &&
|
|
|
|
! git add --dry-run --ignore-missing --no-warn-embedded-repo "$sm_path" > /dev/null 2>&1
|
2010-07-17 19:11:43 +04:00
|
|
|
then
|
2011-08-07 15:58:17 +04:00
|
|
|
eval_gettextln "The following path is ignored by one of your .gitignore files:
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
\$sm_path
|
2011-08-07 15:58:17 +04:00
|
|
|
Use -f if you really want to add it." >&2
|
2010-07-17 19:11:43 +04:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2012-09-30 03:05:58 +04:00
|
|
|
if test -n "$custom_name"
|
|
|
|
then
|
|
|
|
sm_name="$custom_name"
|
|
|
|
else
|
|
|
|
sm_name="$sm_path"
|
|
|
|
fi
|
|
|
|
|
submodule-config: verify submodule names as paths
Submodule "names" come from the untrusted .gitmodules file,
but we blindly append them to $GIT_DIR/modules to create our
on-disk repo paths. This means you can do bad things by
putting "../" into the name (among other things).
Let's sanity-check these names to avoid building a path that
can be exploited. There are two main decisions:
1. What should the allowed syntax be?
It's tempting to reuse verify_path(), since submodule
names typically come from in-repo paths. But there are
two reasons not to:
a. It's technically more strict than what we need, as
we really care only about breaking out of the
$GIT_DIR/modules/ hierarchy. E.g., having a
submodule named "foo/.git" isn't actually
dangerous, and it's possible that somebody has
manually given such a funny name.
b. Since we'll eventually use this checking logic in
fsck to prevent downstream repositories, it should
be consistent across platforms. Because
verify_path() relies on is_dir_sep(), it wouldn't
block "foo\..\bar" on a non-Windows machine.
2. Where should we enforce it? These days most of the
.gitmodules reads go through submodule-config.c, so
I've put it there in the reading step. That should
cover all of the C code.
We also construct the name for "git submodule add"
inside the git-submodule.sh script. This is probably
not a big deal for security since the name is coming
from the user anyway, but it would be polite to remind
them if the name they pick is invalid (and we need to
expose the name-checker to the shell anyway for our
test scripts).
This patch issues a warning when reading .gitmodules
and just ignores the related config entry completely.
This will generally end up producing a sensible error,
as it works the same as a .gitmodules file which is
missing a submodule entry (so "submodule update" will
barf, but "git clone --recurse-submodules" will print
an error but not abort the clone.
There is one minor oddity, which is that we print the
warning once per malformed config key (since that's how
the config subsystem gives us the entries). So in the
new test, for example, the user would see three
warnings. That's OK, since the intent is that this case
should never come up outside of malicious repositories
(and then it might even benefit the user to see the
message multiple times).
Credit for finding this vulnerability and the proof of
concept from which the test script was adapted goes to
Etienne Stalmans.
Signed-off-by: Jeff King <peff@peff.net>
2018-04-30 10:25:25 +03:00
|
|
|
if ! git submodule--helper check-name "$sm_name"
|
|
|
|
then
|
|
|
|
die "$(eval_gettext "'$sm_name' is not a valid submodule name")"
|
|
|
|
fi
|
|
|
|
|
2008-03-05 04:15:02 +03:00
|
|
|
# perhaps the path exists and is already a git repo, else clone it
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
if test -e "$sm_path"
|
2008-03-05 04:15:02 +03:00
|
|
|
then
|
2014-06-10 16:28:33 +04:00
|
|
|
if test -d "$sm_path"/.git || test -f "$sm_path"/.git
|
2008-03-05 04:15:02 +03:00
|
|
|
then
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
eval_gettextln "Adding existing repo at '\$sm_path' to the index"
|
2008-03-05 04:15:02 +03:00
|
|
|
else
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
die "$(eval_gettext "'\$sm_path' already exists and is not a valid git repo")"
|
2008-03-05 04:15:02 +03:00
|
|
|
fi
|
2008-07-10 05:05:41 +04:00
|
|
|
|
2008-03-05 04:15:02 +03:00
|
|
|
else
|
2012-10-01 01:01:29 +04:00
|
|
|
if test -d ".git/modules/$sm_name"
|
|
|
|
then
|
|
|
|
if test -z "$force"
|
|
|
|
then
|
2016-06-18 00:54:12 +03:00
|
|
|
eval_gettextln >&2 "A git directory for '\$sm_name' is found locally with remote(s):"
|
2012-10-01 01:01:29 +04:00
|
|
|
GIT_DIR=".git/modules/$sm_name" GIT_WORK_TREE=. git remote -v | grep '(fetch)' | sed -e s,^," ", -e s,' (fetch)',, >&2
|
2016-06-18 00:54:12 +03:00
|
|
|
die "$(eval_gettextln "\
|
|
|
|
If you want to reuse this local git directory instead of cloning again from
|
|
|
|
\$realrepo
|
|
|
|
use the '--force' option. If the local git directory is not the correct repo
|
|
|
|
or you are unsure what this means choose another name with the '--name' option.")"
|
2012-10-01 01:01:29 +04:00
|
|
|
else
|
2016-06-18 00:54:12 +03:00
|
|
|
eval_gettextln "Reactivating local git directory for submodule '\$sm_name'."
|
2012-10-01 01:01:29 +04:00
|
|
|
fi
|
|
|
|
fi
|
2018-05-03 13:53:46 +03:00
|
|
|
git submodule--helper clone ${GIT_QUIET:+--quiet} ${progress:+"--progress"} --prefix "$wt_prefix" --path "$sm_path" --name "$sm_name" --url "$realrepo" ${reference:+"$reference"} ${dissociate:+"--dissociate"} ${depth:+"$depth"} || exit
|
2014-04-03 01:15:36 +04:00
|
|
|
(
|
2016-03-01 01:58:35 +03:00
|
|
|
sanitize_submodule_env
|
2014-04-03 01:15:36 +04:00
|
|
|
cd "$sm_path" &&
|
|
|
|
# ash fails to wordsplit ${branch:+-b "$branch"...}
|
|
|
|
case "$branch" in
|
|
|
|
'') git checkout -f -q ;;
|
|
|
|
?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
|
|
|
|
esac
|
|
|
|
) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
|
2008-03-05 04:15:02 +03:00
|
|
|
fi
|
2012-09-30 03:05:58 +04:00
|
|
|
git config submodule."$sm_name".url "$realrepo"
|
2008-03-05 04:15:02 +03:00
|
|
|
|
add: warn when adding an embedded repository
It's an easy mistake to add a repository inside another
repository, like:
git clone $url
git add .
The resulting entry is a gitlink, but there's no matching
.gitmodules entry. Trying to use "submodule init" (or clone
with --recursive) doesn't do anything useful. Prior to
v2.13, such an entry caused git-submodule to barf entirely.
In v2.13, the entry is considered "inactive" and quietly
ignored. Either way, no clone of your repository can do
anything useful with the gitlink without the user manually
adding the submodule config.
In most cases, the user probably meant to either add a real
submodule, or they forgot to put the embedded repository in
their .gitignore file.
Let's issue a warning when we see this case. There are a few
things to note:
- the warning will go in the git-add porcelain; anybody
wanting to do low-level manipulation of the index is
welcome to create whatever funny states they want.
- we detect the case by looking for a newly added gitlink;
updates via "git add submodule" are perfectly reasonable,
and this avoids us having to investigate .gitmodules
entirely
- there's a command-line option to suppress the warning.
This is needed for git-submodule itself (which adds the
entry before adding any submodule config), but also
provides a mechanism for other scripts doing
submodule-like things.
We could make this a hard error instead of a warning.
However, we do add lots of sub-repos in our test suite. It's
not _wrong_ to do so. It just creates a state where users
may be surprised. Pointing them in the right direction with
a gentle hint is probably the best option.
There is a config knob that can disable the (long) hint. But
I intentionally omitted a config knob to disable the warning
entirely. Whether the warning is sensible or not is
generally about context, not about the user's preferences.
If there's a tool or workflow that adds gitlinks without
matching .gitmodules, it should probably be taught about the
new command-line option, rather than blanket-disabling the
warning.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-06-14 13:58:22 +03:00
|
|
|
git add --no-warn-embedded-repo $force "$sm_path" ||
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
|
2007-06-25 01:06:07 +04:00
|
|
|
|
2018-10-05 16:05:57 +03:00
|
|
|
git submodule--helper config submodule."$sm_name".path "$sm_path" &&
|
|
|
|
git submodule--helper config submodule."$sm_name".url "$repo" &&
|
2012-12-19 20:03:33 +04:00
|
|
|
if test -n "$branch"
|
|
|
|
then
|
2018-10-05 16:05:57 +03:00
|
|
|
git submodule--helper config submodule."$sm_name".branch "$branch"
|
2012-12-19 20:03:33 +04:00
|
|
|
fi &&
|
2010-07-05 21:33:03 +04:00
|
|
|
git add --force .gitmodules ||
|
git-submodule.sh: Don't use $path variable in eval_gettext string
The eval_gettext (and eval_gettextln) i18n shell functions call
git-sh-i18n--envsubst to process the variable references in the
string parameter. Unfortunately, environment variables are case
insensitive on windows, which leads to failure on cygwin when
eval_gettext exports $path.
Commit df599e9 (Windows: teach getenv to do a case-sensitive search,
06-06-2011) attempts to solve this problem on MinGW by overriding
the system getenv() function to allow git-sh-i18n--envsubst to read
$path rather than $PATH from the environment. However, this commit
does not address cygwin at all and, furthermore, does not fix all
problems on MinGW.
In particular, when executing test #38 in t7400-submodule-basic.sh,
an 'git-sh-i18n-envsubst.exe - Unable To Locate Component' dialog
pops up saying that the application "failed to start because
libiconv2.dll was not found." After studying the voluminous trace
output from the process monitor, it is clear that the system is
attempting to use $path, rather than $PATH, to search for the DLL
file. (Note that, after dismissing the dialog, the test passes
anyway!)
As an alternative, we finesse the problem by renaming the $path
variable to $sm_path (submodule path). This fixes the problem on
MinGW along with all test failures on cygwin (t7400.{7,32,34},
t7406.3 and t7407.{2,6}). We note that the foreach subcommand
provides $path to user scripts (ie it is part of the API), so we
can't simply rename it to $sm_path.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Acked-by: Jens Lehmann <Jens.Lehmann@web.de>
Tested-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-04-17 22:00:58 +04:00
|
|
|
die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
|
2017-03-18 01:38:05 +03:00
|
|
|
|
|
|
|
# NEEDSWORK: In a multi-working-tree world, this needs to be
|
|
|
|
# set in the per-worktree config.
|
|
|
|
if git config --get submodule.active >/dev/null
|
|
|
|
then
|
|
|
|
# If the submodule being adding isn't already covered by the
|
|
|
|
# current configured pathspec, set the submodule's active flag
|
|
|
|
if ! git submodule--helper is-active "$sm_path"
|
|
|
|
then
|
|
|
|
git config submodule."$sm_name".active "true"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
git config submodule."$sm_name".active "true"
|
|
|
|
fi
|
2007-06-25 01:06:07 +04:00
|
|
|
}
|
|
|
|
|
2008-08-11 03:10:04 +04:00
|
|
|
#
|
|
|
|
# Execute an arbitrary command sequence in each checked out
|
|
|
|
# submodule
|
|
|
|
#
|
|
|
|
# $@ = command to execute
|
|
|
|
#
|
|
|
|
cmd_foreach()
|
|
|
|
{
|
2009-08-19 05:45:19 +04:00
|
|
|
# parse $args after "submodule ... foreach".
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-q|--quiet)
|
|
|
|
GIT_QUIET=1
|
|
|
|
;;
|
2009-08-19 05:45:22 +04:00
|
|
|
--recursive)
|
|
|
|
recursive=1
|
|
|
|
;;
|
2009-08-19 05:45:19 +04:00
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
2019-04-12 13:08:19 +03:00
|
|
|
git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
|
2008-08-11 03:10:04 +04:00
|
|
|
}
|
|
|
|
|
2007-05-26 17:56:40 +04:00
|
|
|
#
|
2007-06-06 13:13:02 +04:00
|
|
|
# Register submodules in .git/config
|
2007-05-26 17:56:40 +04:00
|
|
|
#
|
|
|
|
# $@ = requested paths (default to all)
|
|
|
|
#
|
2008-01-15 13:35:49 +03:00
|
|
|
cmd_init()
|
2007-05-26 17:56:40 +04:00
|
|
|
{
|
2008-01-15 13:48:45 +03:00
|
|
|
# parse $args after "submodule ... init".
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-q|--quiet)
|
2009-06-17 02:33:00 +04:00
|
|
|
GIT_QUIET=1
|
2008-01-15 13:48:45 +03:00
|
|
|
;;
|
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
2019-04-12 13:08:19 +03:00
|
|
|
git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} -- "$@"
|
2007-05-26 17:56:40 +04:00
|
|
|
}
|
|
|
|
|
2013-03-05 01:20:24 +04:00
|
|
|
#
|
|
|
|
# Unregister submodules from .git/config and remove their work tree
|
|
|
|
#
|
|
|
|
cmd_deinit()
|
|
|
|
{
|
|
|
|
# parse $args after "submodule ... deinit".
|
2016-05-05 22:52:32 +03:00
|
|
|
deinit_all=
|
2013-03-05 01:20:24 +04:00
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-f|--force)
|
|
|
|
force=$1
|
|
|
|
;;
|
|
|
|
-q|--quiet)
|
|
|
|
GIT_QUIET=1
|
|
|
|
;;
|
2016-05-05 22:52:32 +03:00
|
|
|
--all)
|
|
|
|
deinit_all=t
|
|
|
|
;;
|
2013-03-05 01:20:24 +04:00
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
2019-04-12 13:08:19 +03:00
|
|
|
git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${prefix:+--prefix "$prefix"} ${force:+--force} ${deinit_all:+--all} -- "$@"
|
2013-03-05 01:20:24 +04:00
|
|
|
}
|
|
|
|
|
2016-02-24 06:32:13 +03:00
|
|
|
is_tip_reachable () (
|
2016-04-06 21:39:12 +03:00
|
|
|
sanitize_submodule_env &&
|
2016-02-24 06:32:13 +03:00
|
|
|
cd "$1" &&
|
|
|
|
rev=$(git rev-list -n 1 "$2" --not --all 2>/dev/null) &&
|
|
|
|
test -z "$rev"
|
|
|
|
)
|
|
|
|
|
|
|
|
fetch_in_submodule () (
|
2016-04-06 21:39:12 +03:00
|
|
|
sanitize_submodule_env &&
|
2016-02-24 06:32:13 +03:00
|
|
|
cd "$1" &&
|
|
|
|
case "$2" in
|
|
|
|
'')
|
|
|
|
git fetch ;;
|
|
|
|
*)
|
2016-07-29 03:44:04 +03:00
|
|
|
shift
|
|
|
|
git fetch $(get_default_remote) "$@" ;;
|
2016-02-24 06:32:13 +03:00
|
|
|
esac
|
|
|
|
)
|
|
|
|
|
2007-05-26 17:56:40 +04:00
|
|
|
#
|
2007-06-06 13:13:02 +04:00
|
|
|
# Update each submodule path to correct revision, using clone and checkout as needed
|
2007-05-26 17:56:40 +04:00
|
|
|
#
|
|
|
|
# $@ = requested paths (default to all)
|
|
|
|
#
|
2008-01-15 13:35:49 +03:00
|
|
|
cmd_update()
|
2007-05-26 17:56:40 +04:00
|
|
|
{
|
2008-01-15 13:48:45 +03:00
|
|
|
# parse $args after "submodule ... update".
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-q|--quiet)
|
2009-06-17 02:33:00 +04:00
|
|
|
GIT_QUIET=1
|
2008-01-15 13:48:45 +03:00
|
|
|
;;
|
2018-08-14 21:22:02 +03:00
|
|
|
-v)
|
|
|
|
GIT_QUIET=0
|
|
|
|
;;
|
clone: pass --progress decision to recursive submodules
When cloning with "--recursive", we'd generally expect
submodules to show progress reports if the main clone did,
too.
In older versions of git, this mostly worked out of the
box. Since we show progress by default when stderr is a tty,
and since the child clones inherit the parent stderr, then
both processes would come to the same decision by default.
If the parent clone was asked for "--quiet", we passed down
"--quiet" to the child. However, if stderr was not a tty and
the user specified "--progress", we did not propagate this
to the child.
That's a minor bug, but things got much worse when we
switched recently to submodule--helper's update_clone
command. With that change, the stderr of the child clones
are always connected to a pipe, and we never output
progress at all.
This patch teaches git-submodule and git-submodule--helper
how to pass down an explicit "--progress" flag when cloning.
The clone command then decides to propagate that flag based
on the cloning decision made earlier (which takes into
account isatty(2) of the parent process, existing --progress
or --quiet flags, etc). Since the child processes always run
without a tty on stderr, we don't have to worry about
passing an explicit "--no-progress"; it's the default for
them.
This fixes the recent loss of progress during recursive
clones. And as a bonus, it makes:
git clone --recursive --progress ... 2>&1 | cat
work by triggering progress explicitly in the children.
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-22 08:24:46 +03:00
|
|
|
--progress)
|
2018-05-03 13:53:44 +03:00
|
|
|
progress=1
|
clone: pass --progress decision to recursive submodules
When cloning with "--recursive", we'd generally expect
submodules to show progress reports if the main clone did,
too.
In older versions of git, this mostly worked out of the
box. Since we show progress by default when stderr is a tty,
and since the child clones inherit the parent stderr, then
both processes would come to the same decision by default.
If the parent clone was asked for "--quiet", we passed down
"--quiet" to the child. However, if stderr was not a tty and
the user specified "--progress", we did not propagate this
to the child.
That's a minor bug, but things got much worse when we
switched recently to submodule--helper's update_clone
command. With that change, the stderr of the child clones
are always connected to a pipe, and we never output
progress at all.
This patch teaches git-submodule and git-submodule--helper
how to pass down an explicit "--progress" flag when cloning.
The clone command then decides to propagate that flag based
on the cloning decision made earlier (which takes into
account isatty(2) of the parent process, existing --progress
or --quiet flags, etc). Since the child processes always run
without a tty on stderr, we don't have to worry about
passing an explicit "--no-progress"; it's the default for
them.
This fixes the recent loss of progress during recursive
clones. And as a bonus, it makes:
git clone --recursive --progress ... 2>&1 | cat
work by triggering progress explicitly in the children.
Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-09-22 08:24:46 +03:00
|
|
|
;;
|
2008-05-16 14:23:03 +04:00
|
|
|
-i|--init)
|
2009-05-04 23:30:01 +04:00
|
|
|
init=1
|
2008-05-16 14:23:03 +04:00
|
|
|
;;
|
clone --recurse-submodules: prevent name squatting on Windows
In addition to preventing `.git` from being tracked by Git, on Windows
we also have to prevent `git~1` from being tracked, as the default NTFS
short name (also known as the "8.3 filename") for the file name `.git`
is `git~1`, otherwise it would be possible for malicious repositories to
write directly into the `.git/` directory, e.g. a `post-checkout` hook
that would then be executed _during_ a recursive clone.
When we implemented appropriate protections in 2b4c6efc821 (read-cache:
optionally disallow NTFS .git variants, 2014-12-16), we had analyzed
carefully that the `.git` directory or file would be guaranteed to be
the first directory entry to be written. Otherwise it would be possible
e.g. for a file named `..git` to be assigned the short name `git~1` and
subsequently, the short name generated for `.git` would be `git~2`. Or
`git~3`. Or even `~9999999` (for a detailed explanation of the lengths
we have to go to protect `.gitmodules`, see the commit message of
e7cb0b4455c (is_ntfs_dotgit: match other .git files, 2018-05-11)).
However, by exploiting two issues (that will be addressed in a related
patch series close by), it is currently possible to clone a submodule
into a non-empty directory:
- On Windows, file names cannot end in a space or a period (for
historical reasons: the period separating the base name from the file
extension was not actually written to disk, and the base name/file
extension was space-padded to the full 8/3 characters, respectively).
Helpfully, when creating a directory under the name, say, `sub.`, that
trailing period is trimmed automatically and the actual name on disk
is `sub`.
This means that while Git thinks that the submodule names `sub` and
`sub.` are different, they both access `.git/modules/sub/`.
- While the backslash character is a valid file name character on Linux,
it is not so on Windows. As Git tries to be cross-platform, it
therefore allows backslash characters in the file names stored in tree
objects.
Which means that it is totally possible that a submodule `c` sits next
to a file `c\..git`, and on Windows, during recursive clone a file
called `..git` will be written into `c/`, of course _before_ the
submodule is cloned.
Note that the actual exploit is not quite as simple as having a
submodule `c` next to a file `c\..git`, as we have to make sure that the
directory `.git/modules/b` already exists when the submodule is checked
out, otherwise a different code path is taken in `module_clone()` that
does _not_ allow a non-empty submodule directory to exist already.
Even if we will address both issues nearby (the next commit will
disallow backslash characters in tree entries' file names on Windows,
and another patch will disallow creating directories/files with trailing
spaces or periods), it is a wise idea to defend in depth against this
sort of attack vector: when submodules are cloned recursively, we now
_require_ the directory to be empty, addressing CVE-2019-1349.
Note: the code path we patch is shared with the code path of `git
submodule update --init`, which must not expect, in general, that the
directory is empty. Hence we have to introduce the new option
`--force-init` and hand it all the way down from `git submodule` to the
actual `git submodule--helper` process that performs the initial clone.
Reported-by: Nicolas Joly <Nicolas.Joly@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-12 15:20:39 +03:00
|
|
|
--require-init)
|
|
|
|
init=1
|
|
|
|
require_init=1
|
|
|
|
;;
|
submodule update: add --remote for submodule's upstream changes
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 20:03:32 +04:00
|
|
|
--remote)
|
|
|
|
remote=1
|
|
|
|
;;
|
2009-02-06 01:18:32 +03:00
|
|
|
-N|--no-fetch)
|
|
|
|
nofetch=1
|
|
|
|
;;
|
2011-04-01 13:42:03 +04:00
|
|
|
-f|--force)
|
|
|
|
force=$1
|
|
|
|
;;
|
2009-04-24 03:06:38 +04:00
|
|
|
-r|--rebase)
|
Rename submodule.<name>.rebase to submodule.<name>.update
The addition of "submodule.<name>.rebase" demonstrates the usefulness of
alternatives to the default behaviour of "git submodule update". However,
by naming the config variable "submodule.<name>.rebase", and making it a
boolean choice, we are artificially constraining future git versions that
may want to add _more_ alternatives than just "rebase".
Therefore, while "submodule.<name>.rebase" is not yet in a stable git
release, future-proof it, by changing it from
submodule.<name>.rebase = true/false
to
submodule.<name>.update = rebase/checkout
where "checkout" specifies the default behaviour of "git submodule update"
(checking out the new commit to a detached HEAD), and "rebase" specifies
the --rebase behaviour (where the current local branch in the submodule is
rebase onto the new commit). Thus .update == checkout is equivalent to
.rebase == false, and .update == rebase is equivalent to .rebase == true.
Finally, leaving .update unset is equivalent to leaving .rebase unset.
In future git versions, other alternatives to "git submodule update"
behaviour can be included by adding them to the list of allowable values
for the submodule.<name>.update variable.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-03 10:27:06 +04:00
|
|
|
update="rebase"
|
2009-04-24 03:06:38 +04:00
|
|
|
;;
|
2009-05-04 23:30:01 +04:00
|
|
|
--reference)
|
|
|
|
case "$2" in '') usage ;; esac
|
|
|
|
reference="--reference=$2"
|
2010-11-03 09:26:25 +03:00
|
|
|
shift
|
2009-05-04 23:30:01 +04:00
|
|
|
;;
|
|
|
|
--reference=*)
|
|
|
|
reference="$1"
|
|
|
|
;;
|
2018-05-03 13:53:46 +03:00
|
|
|
--dissociate)
|
|
|
|
dissociate=1
|
|
|
|
;;
|
2009-06-03 02:59:12 +04:00
|
|
|
-m|--merge)
|
|
|
|
update="merge"
|
|
|
|
;;
|
2009-08-19 05:45:23 +04:00
|
|
|
--recursive)
|
|
|
|
recursive=1
|
|
|
|
;;
|
2011-10-11 02:56:16 +04:00
|
|
|
--checkout)
|
|
|
|
update="checkout"
|
|
|
|
;;
|
2016-05-27 00:59:43 +03:00
|
|
|
--recommend-shallow)
|
|
|
|
recommend_shallow="--recommend-shallow"
|
|
|
|
;;
|
|
|
|
--no-recommend-shallow)
|
|
|
|
recommend_shallow="--no-recommend-shallow"
|
|
|
|
;;
|
2013-07-03 01:42:56 +04:00
|
|
|
--depth)
|
|
|
|
case "$2" in '') usage ;; esac
|
|
|
|
depth="--depth=$2"
|
|
|
|
shift
|
|
|
|
;;
|
|
|
|
--depth=*)
|
|
|
|
depth=$1
|
|
|
|
;;
|
2016-03-01 05:07:19 +03:00
|
|
|
-j|--jobs)
|
|
|
|
case "$2" in '') usage ;; esac
|
|
|
|
jobs="--jobs=$2"
|
|
|
|
shift
|
|
|
|
;;
|
|
|
|
--jobs=*)
|
|
|
|
jobs=$1
|
|
|
|
;;
|
2008-01-15 13:48:45 +03:00
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
2010-11-03 09:26:25 +03:00
|
|
|
shift
|
2008-01-15 13:48:45 +03:00
|
|
|
done
|
|
|
|
|
2009-05-04 23:30:01 +04:00
|
|
|
if test -n "$init"
|
|
|
|
then
|
|
|
|
cmd_init "--" "$@" || return
|
|
|
|
fi
|
|
|
|
|
2016-03-01 05:07:17 +03:00
|
|
|
{
|
|
|
|
git submodule--helper update-clone ${GIT_QUIET:+--quiet} \
|
2018-05-03 13:53:44 +03:00
|
|
|
${progress:+"--progress"} \
|
2016-03-01 05:07:17 +03:00
|
|
|
${wt_prefix:+--prefix "$wt_prefix"} \
|
|
|
|
${prefix:+--recursive-prefix "$prefix"} \
|
|
|
|
${update:+--update "$update"} \
|
2016-08-12 02:14:01 +03:00
|
|
|
${reference:+"$reference"} \
|
2018-05-03 13:53:46 +03:00
|
|
|
${dissociate:+"--dissociate"} \
|
2016-03-01 05:07:17 +03:00
|
|
|
${depth:+--depth "$depth"} \
|
clone --recurse-submodules: prevent name squatting on Windows
In addition to preventing `.git` from being tracked by Git, on Windows
we also have to prevent `git~1` from being tracked, as the default NTFS
short name (also known as the "8.3 filename") for the file name `.git`
is `git~1`, otherwise it would be possible for malicious repositories to
write directly into the `.git/` directory, e.g. a `post-checkout` hook
that would then be executed _during_ a recursive clone.
When we implemented appropriate protections in 2b4c6efc821 (read-cache:
optionally disallow NTFS .git variants, 2014-12-16), we had analyzed
carefully that the `.git` directory or file would be guaranteed to be
the first directory entry to be written. Otherwise it would be possible
e.g. for a file named `..git` to be assigned the short name `git~1` and
subsequently, the short name generated for `.git` would be `git~2`. Or
`git~3`. Or even `~9999999` (for a detailed explanation of the lengths
we have to go to protect `.gitmodules`, see the commit message of
e7cb0b4455c (is_ntfs_dotgit: match other .git files, 2018-05-11)).
However, by exploiting two issues (that will be addressed in a related
patch series close by), it is currently possible to clone a submodule
into a non-empty directory:
- On Windows, file names cannot end in a space or a period (for
historical reasons: the period separating the base name from the file
extension was not actually written to disk, and the base name/file
extension was space-padded to the full 8/3 characters, respectively).
Helpfully, when creating a directory under the name, say, `sub.`, that
trailing period is trimmed automatically and the actual name on disk
is `sub`.
This means that while Git thinks that the submodule names `sub` and
`sub.` are different, they both access `.git/modules/sub/`.
- While the backslash character is a valid file name character on Linux,
it is not so on Windows. As Git tries to be cross-platform, it
therefore allows backslash characters in the file names stored in tree
objects.
Which means that it is totally possible that a submodule `c` sits next
to a file `c\..git`, and on Windows, during recursive clone a file
called `..git` will be written into `c/`, of course _before_ the
submodule is cloned.
Note that the actual exploit is not quite as simple as having a
submodule `c` next to a file `c\..git`, as we have to make sure that the
directory `.git/modules/b` already exists when the submodule is checked
out, otherwise a different code path is taken in `module_clone()` that
does _not_ allow a non-empty submodule directory to exist already.
Even if we will address both issues nearby (the next commit will
disallow backslash characters in tree entries' file names on Windows,
and another patch will disallow creating directories/files with trailing
spaces or periods), it is a wise idea to defend in depth against this
sort of attack vector: when submodules are cloned recursively, we now
_require_ the directory to be empty, addressing CVE-2019-1349.
Note: the code path we patch is shared with the code path of `git
submodule update --init`, which must not expect, in general, that the
directory is empty. Hence we have to introduce the new option
`--force-init` and hand it all the way down from `git submodule` to the
actual `git submodule--helper` process that performs the initial clone.
Reported-by: Nicolas Joly <Nicolas.Joly@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-09-12 15:20:39 +03:00
|
|
|
${require_init:+--require-init} \
|
2018-05-03 13:53:44 +03:00
|
|
|
$recommend_shallow \
|
|
|
|
$jobs \
|
2019-04-12 13:08:19 +03:00
|
|
|
-- \
|
2016-07-22 22:14:38 +03:00
|
|
|
"$@" || echo "#unmatched" $?
|
2016-03-01 05:07:17 +03:00
|
|
|
} | {
|
2011-06-13 21:15:26 +04:00
|
|
|
err=
|
2018-08-04 01:23:17 +03:00
|
|
|
while read -r quickabort sha1 just_cloned sm_path
|
2007-05-26 17:56:40 +04:00
|
|
|
do
|
2018-08-04 01:23:17 +03:00
|
|
|
die_if_unmatched "$quickabort" "$sha1"
|
2016-03-01 05:07:17 +03:00
|
|
|
|
2019-01-19 00:55:19 +03:00
|
|
|
git submodule--helper ensure-core-worktree "$sm_path" || exit 1
|
2018-08-14 01:42:34 +03:00
|
|
|
|
2018-08-14 01:42:35 +03:00
|
|
|
update_module=$(git submodule--helper update-module-mode $just_cloned "$sm_path" $update)
|
2011-10-11 02:56:16 +04:00
|
|
|
|
2016-06-01 03:27:59 +03:00
|
|
|
displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
|
2013-06-16 18:18:18 +04:00
|
|
|
|
2016-03-01 05:07:17 +03:00
|
|
|
if test $just_cloned -eq 1
|
2014-04-03 01:15:36 +04:00
|
|
|
then
|
2007-06-11 23:12:22 +04:00
|
|
|
subsha1=
|
|
|
|
else
|
2016-03-01 01:58:35 +03:00
|
|
|
subsha1=$(sanitize_submodule_env; cd "$sm_path" &&
|
2007-07-03 09:52:14 +04:00
|
|
|
git rev-parse --verify HEAD) ||
|
2013-06-16 18:18:18 +04:00
|
|
|
die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
|
2007-05-26 17:56:40 +04:00
|
|
|
fi
|
2007-06-06 13:13:02 +04:00
|
|
|
|
submodule update: add --remote for submodule's upstream changes
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 20:03:32 +04:00
|
|
|
if test -n "$remote"
|
|
|
|
then
|
2016-08-03 23:44:03 +03:00
|
|
|
branch=$(git submodule--helper remote-branch "$sm_path")
|
submodule update: add --remote for submodule's upstream changes
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 20:03:32 +04:00
|
|
|
if test -z "$nofetch"
|
|
|
|
then
|
|
|
|
# Fetch remote before determining tracking $sha1
|
2016-07-29 03:44:04 +03:00
|
|
|
fetch_in_submodule "$sm_path" $depth ||
|
submodule update: add --remote for submodule's upstream changes
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 20:03:32 +04:00
|
|
|
die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
|
|
|
|
fi
|
2016-03-01 01:58:35 +03:00
|
|
|
remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
|
|
|
|
sha1=$(sanitize_submodule_env; cd "$sm_path" &&
|
submodule update: add --remote for submodule's upstream changes
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 20:03:32 +04:00
|
|
|
git rev-parse --verify "${remote_name}/${branch}") ||
|
2016-06-18 00:54:13 +03:00
|
|
|
die "$(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
|
submodule update: add --remote for submodule's upstream changes
The current `update` command incorporates the superproject's gitlinked
SHA-1 ($sha1) into the submodule HEAD ($subsha1). Depending on the
options you use, it may checkout $sha1, rebase the $subsha1 onto
$sha1, or merge $sha1 into $subsha1. This helps you keep up with
changes in the upstream superproject.
However, it's also useful to stay up to date with changes in the
upstream subproject. Previous workflows for incorporating such
changes include the ungainly:
$ git submodule foreach 'git checkout $(git config --file $toplevel/.gitmodules submodule.$name.branch) && git pull'
With this patch, all of the useful functionality for incorporating
superproject changes can be reused to incorporate upstream subproject
updates. When you specify --remote, the target $sha1 is replaced with
a $sha1 of the submodule's origin/master tracking branch. If you want
to merge a different tracking branch, you can configure the
`submodule.<name>.branch` option in `.gitmodules`. You can override
the `.gitmodules` configuration setting for a particular superproject
by configuring the option in that superproject's default configuration
(using the usual configuration hierarchy, e.g. `.git/config`,
`~/.gitconfig`, etc.).
Previous use of submodule.<name>.branch
=======================================
Because we're adding a new configuration option, it's a good idea to
check if anyone else is already using the option. The foreach-pull
example above was described by Ævar in
commit f030c96d8643fa0a1a9b2bd9c2f36a77721fb61f
Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date: Fri May 21 16:10:10 2010 +0000
git-submodule foreach: Add $toplevel variable
Gerrit uses the same interpretation for the setting, but because
Gerrit has direct access to the subproject repositories, it updates
the superproject repositories automatically when a subproject changes.
Gerrit also accepts the special value '.', which it expands into the
superproject's branch name.
Although the --remote functionality is using `submodule.<name>.branch`
slightly differently, the effect is the same. The foreach-pull
example uses the option to record the name of the local branch to
checkout before pulls. The tracking branch to be pulled is recorded
in `.git/modules/<name>/config`, which was initialized by the module
clone during `submodule add` or `submodule init`. Because the branch
name stored in `submodule.<name>.branch` was likely the same as the
branch name used during the initial `submodule add`, the same branch
will be pulled in each workflow.
Implementation details
======================
In order to ensure a current tracking branch state, `update --remote`
fetches the submodule's remote repository before calculating the
SHA-1. However, I didn't change the logic guarding the existing fetch:
if test -z "$nofetch"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
(clear_local_git_env; cd "$path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
fi
There will not be a double-fetch, because the new $sha1 determined
after the `--remote` triggered fetch should always exist in the
repository. If it doesn't, it's because some racy process removed it
from the submodule's repository and we *should* be re-fetching.
Signed-off-by: W. Trevor King <wking@tremily.us>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-12-19 20:03:32 +04:00
|
|
|
fi
|
|
|
|
|
2014-06-10 16:28:33 +04:00
|
|
|
if test "$subsha1" != "$sha1" || test -n "$force"
|
2007-05-26 17:56:40 +04:00
|
|
|
then
|
2011-04-01 13:42:03 +04:00
|
|
|
subforce=$force
|
|
|
|
# If we don't already have a -f flag and the submodule has never been checked out
|
2014-06-10 16:28:33 +04:00
|
|
|
if test -z "$subsha1" && test -z "$force"
|
2008-09-26 19:33:23 +04:00
|
|
|
then
|
2011-04-01 13:42:03 +04:00
|
|
|
subforce="-f"
|
2008-09-26 19:33:23 +04:00
|
|
|
fi
|
2009-02-06 01:18:32 +03:00
|
|
|
|
|
|
|
if test -z "$nofetch"
|
|
|
|
then
|
2011-03-07 01:13:36 +03:00
|
|
|
# Run fetch only if $sha1 isn't present or it
|
|
|
|
# is not reachable from a ref.
|
2016-02-24 06:32:13 +03:00
|
|
|
is_tip_reachable "$sm_path" "$sha1" ||
|
2016-07-29 03:44:04 +03:00
|
|
|
fetch_in_submodule "$sm_path" $depth ||
|
submodule: explain first attempt failure clearly
When cloning with --recurse-submodules a superproject with at least one
submodule with HEAD pointing to an unborn branch, the clone goes
something like this:
Cloning into 'test'...
<messages about cloning of superproject>
Submodule '<name>' (<uri>) registered for path '<submodule path>'
Cloning into '<submodule path>'...
fatal: Couldn't find remote ref HEAD
Unable to fetch in submodule path '<submodule path>'
<messages about fetching with SHA-1>
From <uri>
* branch <hash> -> FETCH_HEAD
Submodule path '<submodule path>': checked out '<hash>'
In other words, first, a fetch is done with no hash arguments (that is,
a fetch of HEAD) resulting in a "Couldn't find remote ref HEAD" error;
then, a fetch is done given a hash, which succeeds.
The fetch given a hash was added in fb43e31f2b ("submodule: try harder
to fetch needed sha1 by direct fetching sha1", 2016-02-24), and the
"Unable to fetch..." message was downgraded from a fatal error to a
notice in e30d833671 ("git-submodule.sh: try harder to fetch a
submodule", 2018-05-16).
This commit improves the notice to be clearer that we are retrying the
fetch, and that the previous messages (in particular, the fatal errors
from fetch) do not necessarily indicate that the whole command fails. In
other words:
- If the HEAD-fetch succeeds and we then have the commit we want,
git-submodule prints no explanation.
- If the HEAD-fetch succeeds and we do not have the commit we want, but
the hash-fetch succeeds, git-submodule prints no explanation.
- If the HEAD-fetch succeeds and we do not have the commit we want, but
the hash-fetch fails, git-submodule prints a fatal error.
- If the HEAD-fetch fails, fetch prints a fatal error, and
git-submodule informs the user that it will retry by fetching
specific commits by hash.
- If the hash-fetch then succeeds, git-submodule prints no
explanation (besides the ones already printed).
- If the HEAD-fetch then fails, git-submodule prints a fatal error.
It could be said that we should just eliminate the HEAD-fetch
altogether, but that changes some behavior (in particular, some refs
that were opportunistically updated would no longer be), so I have left
that alone for now.
There is an analogous situation with the fetching code in fetch_finish()
and surrounding functions. For now, I have added a NEEDSWORK.
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-03-13 20:57:38 +03:00
|
|
|
say "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'; trying to directly fetch \$sha1:")"
|
2016-02-24 06:32:13 +03:00
|
|
|
|
|
|
|
# Now we tried the usual fetch, but $sha1 may
|
|
|
|
# not be reachable from any of the refs
|
|
|
|
is_tip_reachable "$sm_path" "$sha1" ||
|
2016-07-29 03:44:04 +03:00
|
|
|
fetch_in_submodule "$sm_path" $depth "$sha1" ||
|
2016-06-18 00:54:13 +03:00
|
|
|
die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain \$sha1. Direct fetching of that commit failed.")"
|
2009-02-06 01:18:32 +03:00
|
|
|
fi
|
|
|
|
|
2011-06-13 23:17:52 +04:00
|
|
|
must_die_on_failure=
|
Rename submodule.<name>.rebase to submodule.<name>.update
The addition of "submodule.<name>.rebase" demonstrates the usefulness of
alternatives to the default behaviour of "git submodule update". However,
by naming the config variable "submodule.<name>.rebase", and making it a
boolean choice, we are artificially constraining future git versions that
may want to add _more_ alternatives than just "rebase".
Therefore, while "submodule.<name>.rebase" is not yet in a stable git
release, future-proof it, by changing it from
submodule.<name>.rebase = true/false
to
submodule.<name>.update = rebase/checkout
where "checkout" specifies the default behaviour of "git submodule update"
(checking out the new commit to a detached HEAD), and "rebase" specifies
the --rebase behaviour (where the current local branch in the submodule is
rebase onto the new commit). Thus .update == checkout is equivalent to
.rebase == false, and .update == rebase is equivalent to .rebase == true.
Finally, leaving .update unset is equivalent to leaving .rebase unset.
In future git versions, other alternatives to "git submodule update"
behaviour can be included by adding them to the list of allowable values
for the submodule.<name>.update variable.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-03 10:27:06 +04:00
|
|
|
case "$update_module" in
|
2014-01-16 08:10:22 +04:00
|
|
|
checkout)
|
|
|
|
command="git checkout $subforce -q"
|
|
|
|
die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
|
|
|
|
say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
|
|
|
|
;;
|
Rename submodule.<name>.rebase to submodule.<name>.update
The addition of "submodule.<name>.rebase" demonstrates the usefulness of
alternatives to the default behaviour of "git submodule update". However,
by naming the config variable "submodule.<name>.rebase", and making it a
boolean choice, we are artificially constraining future git versions that
may want to add _more_ alternatives than just "rebase".
Therefore, while "submodule.<name>.rebase" is not yet in a stable git
release, future-proof it, by changing it from
submodule.<name>.rebase = true/false
to
submodule.<name>.update = rebase/checkout
where "checkout" specifies the default behaviour of "git submodule update"
(checking out the new commit to a detached HEAD), and "rebase" specifies
the --rebase behaviour (where the current local branch in the submodule is
rebase onto the new commit). Thus .update == checkout is equivalent to
.rebase == false, and .update == rebase is equivalent to .rebase == true.
Finally, leaving .update unset is equivalent to leaving .rebase unset.
In future git versions, other alternatives to "git submodule update"
behaviour can be included by adding them to the list of allowable values
for the submodule.<name>.update variable.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-03 10:27:06 +04:00
|
|
|
rebase)
|
|
|
|
command="git rebase"
|
2013-06-16 18:18:18 +04:00
|
|
|
die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
|
|
|
|
say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
|
2011-06-13 23:17:52 +04:00
|
|
|
must_die_on_failure=yes
|
Rename submodule.<name>.rebase to submodule.<name>.update
The addition of "submodule.<name>.rebase" demonstrates the usefulness of
alternatives to the default behaviour of "git submodule update". However,
by naming the config variable "submodule.<name>.rebase", and making it a
boolean choice, we are artificially constraining future git versions that
may want to add _more_ alternatives than just "rebase".
Therefore, while "submodule.<name>.rebase" is not yet in a stable git
release, future-proof it, by changing it from
submodule.<name>.rebase = true/false
to
submodule.<name>.update = rebase/checkout
where "checkout" specifies the default behaviour of "git submodule update"
(checking out the new commit to a detached HEAD), and "rebase" specifies
the --rebase behaviour (where the current local branch in the submodule is
rebase onto the new commit). Thus .update == checkout is equivalent to
.rebase == false, and .update == rebase is equivalent to .rebase == true.
Finally, leaving .update unset is equivalent to leaving .rebase unset.
In future git versions, other alternatives to "git submodule update"
behaviour can be included by adding them to the list of allowable values
for the submodule.<name>.update variable.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-03 10:27:06 +04:00
|
|
|
;;
|
2009-06-03 02:59:12 +04:00
|
|
|
merge)
|
|
|
|
command="git merge"
|
2013-06-16 18:18:18 +04:00
|
|
|
die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
|
|
|
|
say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
|
2011-06-13 23:17:52 +04:00
|
|
|
must_die_on_failure=yes
|
2009-06-03 02:59:12 +04:00
|
|
|
;;
|
2013-07-03 13:02:02 +04:00
|
|
|
!*)
|
|
|
|
command="${update_module#!}"
|
2016-03-30 04:27:44 +03:00
|
|
|
die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$displaypath'")"
|
|
|
|
say_msg="$(eval_gettext "Submodule path '\$displaypath': '\$command \$sha1'")"
|
2013-07-03 13:02:02 +04:00
|
|
|
must_die_on_failure=yes
|
|
|
|
;;
|
Rename submodule.<name>.rebase to submodule.<name>.update
The addition of "submodule.<name>.rebase" demonstrates the usefulness of
alternatives to the default behaviour of "git submodule update". However,
by naming the config variable "submodule.<name>.rebase", and making it a
boolean choice, we are artificially constraining future git versions that
may want to add _more_ alternatives than just "rebase".
Therefore, while "submodule.<name>.rebase" is not yet in a stable git
release, future-proof it, by changing it from
submodule.<name>.rebase = true/false
to
submodule.<name>.update = rebase/checkout
where "checkout" specifies the default behaviour of "git submodule update"
(checking out the new commit to a detached HEAD), and "rebase" specifies
the --rebase behaviour (where the current local branch in the submodule is
rebase onto the new commit). Thus .update == checkout is equivalent to
.rebase == false, and .update == rebase is equivalent to .rebase == true.
Finally, leaving .update unset is equivalent to leaving .rebase unset.
In future git versions, other alternatives to "git submodule update"
behaviour can be included by adding them to the list of allowable values
for the submodule.<name>.update variable.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-03 10:27:06 +04:00
|
|
|
*)
|
2018-08-04 01:23:16 +03:00
|
|
|
die "$(eval_gettext "Invalid update mode '$update_module' for submodule path '$path'")"
|
Rename submodule.<name>.rebase to submodule.<name>.update
The addition of "submodule.<name>.rebase" demonstrates the usefulness of
alternatives to the default behaviour of "git submodule update". However,
by naming the config variable "submodule.<name>.rebase", and making it a
boolean choice, we are artificially constraining future git versions that
may want to add _more_ alternatives than just "rebase".
Therefore, while "submodule.<name>.rebase" is not yet in a stable git
release, future-proof it, by changing it from
submodule.<name>.rebase = true/false
to
submodule.<name>.update = rebase/checkout
where "checkout" specifies the default behaviour of "git submodule update"
(checking out the new commit to a detached HEAD), and "rebase" specifies
the --rebase behaviour (where the current local branch in the submodule is
rebase onto the new commit). Thus .update == checkout is equivalent to
.rebase == false, and .update == rebase is equivalent to .rebase == true.
Finally, leaving .update unset is equivalent to leaving .rebase unset.
In future git versions, other alternatives to "git submodule update"
behaviour can be included by adding them to the list of allowable values
for the submodule.<name>.update variable.
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-03 10:27:06 +04:00
|
|
|
esac
|
2007-05-26 17:56:40 +04:00
|
|
|
|
2016-03-01 01:58:35 +03:00
|
|
|
if (sanitize_submodule_env; cd "$sm_path" && $command "$sha1")
|
2011-06-13 21:15:26 +04:00
|
|
|
then
|
2011-07-14 01:31:35 +04:00
|
|
|
say "$say_msg"
|
2011-06-13 23:17:52 +04:00
|
|
|
elif test -n "$must_die_on_failure"
|
|
|
|
then
|
2011-07-14 01:31:35 +04:00
|
|
|
die_with_status 2 "$die_msg"
|
2011-06-13 21:15:26 +04:00
|
|
|
else
|
2011-07-14 01:31:35 +04:00
|
|
|
err="${err};$die_msg"
|
2011-06-13 23:17:52 +04:00
|
|
|
continue
|
2011-06-13 21:15:26 +04:00
|
|
|
fi
|
2007-05-26 17:56:40 +04:00
|
|
|
fi
|
2009-08-19 05:45:23 +04:00
|
|
|
|
|
|
|
if test -n "$recursive"
|
|
|
|
then
|
2013-03-02 23:44:59 +04:00
|
|
|
(
|
2016-06-01 03:27:59 +03:00
|
|
|
prefix=$(git submodule--helper relative-path "$prefix$sm_path/" "$wt_prefix")
|
submodule: port init from shell to C
By having the `submodule init` functionality in C, we can reference it
easier from other parts in the code in later patches. The code is split
up to have one function to initialize one submodule and a calling function
that takes care of the rest, such as argument handling and translating the
arguments to the paths of the submodules.
This is the first submodule subcommand that is fully converted to C
except for the usage string, so this is actually removing a call to
the `submodule--helper list` function, which is supposed to be used in
this transition. Instead we'll make a direct call to `module_list_compute`.
An explanation why we need to edit the prefixes in cmd_update in
git-submodule.sh in this patch:
By having no processing in the shell part, we need to convey the notion
of wt_prefix and prefix to the C parts, which former patches punted on
and did the processing of displaying path in the shell.
`wt_prefix` used to hold the path from the repository root to the current
directory, e.g. wt_prefix would be t/ if the user invoked the
`git submodule` command in ~/repo/t and ~repo is the GIT_DIR.
`prefix` used to hold the relative path from the repository root to the
operation, e.g. if you have recursive submodules, the shell script would
modify the `prefix` in each recursive step by adding the submodule path.
We will pass `wt_prefix` into the C helper via `git -C <dir>` as that
will setup git in the directory the user actually called git-submodule.sh
from. The `prefix` will be passed in via the `--prefix` option.
Having `prefix` and `wt_prefix` relative to the GIT_DIR of the
calling superproject is unfortunate with this patch as the C code doesn't
know about a possible recursion from a superproject via `submodule update
--init --recursive`.
To fix this, we change the meaning of `wt_prefix` to point to the current
project instead of the superproject and `prefix` to include any relative
paths issues in the superproject. That way `prefix` will become the leading
part for displaying paths and `wt_prefix` will be empty in recursive
calls for now.
The new notion of `wt_prefix` and `prefix` still allows us to reconstruct
the calling directory in the superproject by just traveling reverse of
`prefix`.
Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-04-16 03:50:13 +03:00
|
|
|
wt_prefix=
|
2016-03-01 01:58:35 +03:00
|
|
|
sanitize_submodule_env
|
2013-03-02 23:44:59 +04:00
|
|
|
cd "$sm_path" &&
|
2013-11-12 00:55:52 +04:00
|
|
|
eval cmd_update
|
2013-03-02 23:44:59 +04:00
|
|
|
)
|
2011-06-13 21:15:26 +04:00
|
|
|
res=$?
|
|
|
|
if test $res -gt 0
|
|
|
|
then
|
2013-06-16 18:18:18 +04:00
|
|
|
die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
|
2016-06-09 22:06:37 +03:00
|
|
|
if test $res -ne 2
|
2011-06-13 21:15:26 +04:00
|
|
|
then
|
2011-07-14 01:31:35 +04:00
|
|
|
err="${err};$die_msg"
|
2011-06-13 21:15:26 +04:00
|
|
|
continue
|
|
|
|
else
|
2011-07-14 01:31:35 +04:00
|
|
|
die_with_status $res "$die_msg"
|
2011-06-13 21:15:26 +04:00
|
|
|
fi
|
|
|
|
fi
|
2009-08-19 05:45:23 +04:00
|
|
|
fi
|
2007-05-26 17:56:40 +04:00
|
|
|
done
|
2011-06-13 21:15:26 +04:00
|
|
|
|
|
|
|
if test -n "$err"
|
|
|
|
then
|
|
|
|
OIFS=$IFS
|
|
|
|
IFS=';'
|
|
|
|
for e in $err
|
|
|
|
do
|
|
|
|
if test -n "$e"
|
|
|
|
then
|
|
|
|
echo >&2 "$e"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
IFS=$OIFS
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
2007-05-26 17:56:40 +04:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:21:34 +03:00
|
|
|
#
|
|
|
|
# Configures a submodule's default branch
|
|
|
|
#
|
|
|
|
# $@ = requested path
|
|
|
|
#
|
|
|
|
cmd_set_branch() {
|
|
|
|
unset_branch=false
|
|
|
|
branch=
|
|
|
|
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-q|--quiet)
|
|
|
|
# we don't do anything with this but we need to accept it
|
|
|
|
;;
|
|
|
|
-d|--default)
|
|
|
|
unset_branch=true
|
|
|
|
;;
|
|
|
|
-b|--branch)
|
|
|
|
case "$2" in '') usage ;; esac
|
|
|
|
branch=$2
|
|
|
|
shift
|
|
|
|
;;
|
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
|
|
|
if test $# -ne 1
|
|
|
|
then
|
|
|
|
usage
|
|
|
|
fi
|
|
|
|
|
|
|
|
# we can't use `git submodule--helper name` here because internally, it
|
|
|
|
# hashes the path so a trailing slash could lead to an unintentional no match
|
|
|
|
name="$(git submodule--helper list "$1" | cut -f2)"
|
|
|
|
if test -z "$name"
|
|
|
|
then
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
test -n "$branch"; has_branch=$?
|
|
|
|
test "$unset_branch" = true; has_unset_branch=$?
|
|
|
|
|
|
|
|
if test $((!$has_branch != !$has_unset_branch)) -eq 0
|
|
|
|
then
|
|
|
|
usage
|
|
|
|
fi
|
|
|
|
|
|
|
|
if test $has_branch -eq 0
|
|
|
|
then
|
|
|
|
git submodule--helper config submodule."$name".branch "$branch"
|
|
|
|
else
|
|
|
|
git submodule--helper config --unset submodule."$name".branch
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2019-10-29 20:01:52 +03:00
|
|
|
#
|
|
|
|
# Configures a submodule's remote url
|
|
|
|
#
|
|
|
|
# $@ = requested path, requested url
|
|
|
|
#
|
|
|
|
cmd_set_url() {
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-q|--quiet)
|
|
|
|
GIT_QUIET=1
|
|
|
|
;;
|
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
|
|
|
if test $# -ne 2
|
|
|
|
then
|
|
|
|
usage
|
|
|
|
fi
|
|
|
|
|
|
|
|
# we can't use `git submodule--helper name` here because internally, it
|
|
|
|
# hashes the path so a trailing slash could lead to an unintentional no match
|
|
|
|
name="$(git submodule--helper list "$1" | cut -f2)"
|
|
|
|
if test -z "$name"
|
|
|
|
then
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
url="$2"
|
|
|
|
if test -z "$url"
|
|
|
|
then
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
git submodule--helper config submodule."$name".url "$url"
|
|
|
|
git submodule--helper sync ${GIT_QUIET:+--quiet} "$name"
|
|
|
|
}
|
|
|
|
|
2008-03-11 16:52:15 +03:00
|
|
|
#
|
|
|
|
# Show commit summary for submodules in index or working tree
|
|
|
|
#
|
|
|
|
# If '--cached' is given, show summary between index and given commit,
|
|
|
|
# or between working tree and given commit
|
|
|
|
#
|
|
|
|
# $@ = [commit (default 'HEAD'),] requested paths (default all)
|
|
|
|
#
|
|
|
|
cmd_summary() {
|
2008-03-11 16:52:17 +03:00
|
|
|
summary_limit=-1
|
2008-04-12 19:05:31 +04:00
|
|
|
for_status=
|
2009-08-13 23:32:50 +04:00
|
|
|
diff_cmd=diff-index
|
2008-03-11 16:52:17 +03:00
|
|
|
|
2008-03-11 16:52:15 +03:00
|
|
|
# parse $args after "submodule ... summary".
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
--cached)
|
|
|
|
cached="$1"
|
|
|
|
;;
|
2009-08-13 23:32:50 +04:00
|
|
|
--files)
|
|
|
|
files="$1"
|
|
|
|
;;
|
2008-04-12 19:05:31 +04:00
|
|
|
--for-status)
|
|
|
|
for_status="$1"
|
|
|
|
;;
|
2008-03-11 16:52:17 +03:00
|
|
|
-n|--summary-limit)
|
2013-04-01 17:06:27 +04:00
|
|
|
summary_limit="$2"
|
|
|
|
isnumber "$summary_limit" || usage
|
2008-03-11 16:52:17 +03:00
|
|
|
shift
|
|
|
|
;;
|
2013-04-01 17:06:27 +04:00
|
|
|
--summary-limit=*)
|
|
|
|
summary_limit="${1#--summary-limit=}"
|
|
|
|
isnumber "$summary_limit" || usage
|
|
|
|
;;
|
2008-03-11 16:52:15 +03:00
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
2007-06-27 03:40:58 +04:00
|
|
|
|
2008-03-11 16:52:17 +03:00
|
|
|
test $summary_limit = 0 && return
|
|
|
|
|
2010-02-16 13:21:14 +03:00
|
|
|
if rev=$(git rev-parse -q --verify --default HEAD ${1+"$1"})
|
2008-03-11 16:52:15 +03:00
|
|
|
then
|
|
|
|
head=$rev
|
2010-03-04 01:19:09 +03:00
|
|
|
test $# = 0 || shift
|
2014-06-10 16:28:33 +04:00
|
|
|
elif test -z "$1" || test "$1" = "HEAD"
|
2010-02-16 13:21:14 +03:00
|
|
|
then
|
2010-03-04 01:19:10 +03:00
|
|
|
# before the first commit: compare with an empty tree
|
|
|
|
head=$(git hash-object -w -t tree --stdin </dev/null)
|
2010-03-09 17:55:32 +03:00
|
|
|
test -z "$1" || shift
|
2008-03-11 16:52:15 +03:00
|
|
|
else
|
2010-02-16 13:21:14 +03:00
|
|
|
head="HEAD"
|
2008-03-11 16:52:15 +03:00
|
|
|
fi
|
|
|
|
|
2009-08-13 23:32:50 +04:00
|
|
|
if [ -n "$files" ]
|
|
|
|
then
|
|
|
|
test -n "$cached" &&
|
2012-07-25 18:53:09 +04:00
|
|
|
die "$(gettext "The --cached option cannot be used with the --files option")"
|
2009-08-13 23:32:50 +04:00
|
|
|
diff_cmd=diff-files
|
|
|
|
head=
|
|
|
|
fi
|
|
|
|
|
2008-03-11 16:52:15 +03:00
|
|
|
cd_to_toplevel
|
2013-06-16 18:18:18 +04:00
|
|
|
eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
|
2008-03-11 16:52:15 +03:00
|
|
|
# Get modified modules cared by user
|
2010-06-25 18:56:02 +04:00
|
|
|
modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
|
2009-11-24 02:56:32 +03:00
|
|
|
sane_egrep '^:([0-7]* )?160000' |
|
2017-04-07 20:23:06 +03:00
|
|
|
while read -r mod_src mod_dst sha1_src sha1_dst status sm_path
|
2008-03-11 16:52:15 +03:00
|
|
|
do
|
|
|
|
# Always show modules deleted or type-changed (blob<->module)
|
2014-06-10 16:28:33 +04:00
|
|
|
if test "$status" = D || test "$status" = T
|
|
|
|
then
|
2014-06-10 19:33:39 +04:00
|
|
|
printf '%s\n' "$sm_path"
|
2014-06-10 16:28:33 +04:00
|
|
|
continue
|
|
|
|
fi
|
2013-09-02 00:06:49 +04:00
|
|
|
# Respect the ignore setting for --for-status.
|
|
|
|
if test -n "$for_status"
|
|
|
|
then
|
2015-09-03 00:42:25 +03:00
|
|
|
name=$(git submodule--helper name "$sm_path")
|
2013-09-02 00:06:49 +04:00
|
|
|
ignore_config=$(get_submodule_config "$name" ignore none)
|
2014-06-10 16:28:33 +04:00
|
|
|
test $status != A && test $ignore_config = all && continue
|
2013-09-02 00:06:49 +04:00
|
|
|
fi
|
2008-03-11 16:52:15 +03:00
|
|
|
# Also show added or modified modules which are checked out
|
2017-08-05 09:49:05 +03:00
|
|
|
GIT_DIR="$sm_path/.git" git rev-parse --git-dir >/dev/null 2>&1 &&
|
2014-06-10 19:33:39 +04:00
|
|
|
printf '%s\n' "$sm_path"
|
2008-03-11 16:52:15 +03:00
|
|
|
done
|
|
|
|
)
|
2008-03-11 16:52:16 +03:00
|
|
|
|
2008-04-12 19:05:31 +04:00
|
|
|
test -z "$modules" && return
|
|
|
|
|
2010-06-25 18:56:02 +04:00
|
|
|
git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- $modules |
|
2009-11-24 02:56:32 +03:00
|
|
|
sane_egrep '^:([0-7]* )?160000' |
|
2008-03-11 16:52:16 +03:00
|
|
|
cut -c2- |
|
2017-04-07 20:23:06 +03:00
|
|
|
while read -r mod_src mod_dst sha1_src sha1_dst status name
|
2008-03-11 16:52:16 +03:00
|
|
|
do
|
|
|
|
if test -z "$cached" &&
|
2018-10-15 03:02:01 +03:00
|
|
|
is_zero_oid $sha1_dst
|
2008-03-11 16:52:16 +03:00
|
|
|
then
|
|
|
|
case "$mod_dst" in
|
|
|
|
160000)
|
|
|
|
sha1_dst=$(GIT_DIR="$name/.git" git rev-parse HEAD)
|
|
|
|
;;
|
|
|
|
100644 | 100755 | 120000)
|
|
|
|
sha1_dst=$(git hash-object $name)
|
|
|
|
;;
|
|
|
|
000000)
|
|
|
|
;; # removed
|
|
|
|
*)
|
|
|
|
# unexpected type
|
2011-08-07 15:58:17 +04:00
|
|
|
eval_gettextln "unexpected mode \$mod_dst" >&2
|
2008-03-11 16:52:16 +03:00
|
|
|
continue ;;
|
|
|
|
esac
|
|
|
|
fi
|
|
|
|
missing_src=
|
|
|
|
missing_dst=
|
|
|
|
|
|
|
|
test $mod_src = 160000 &&
|
2017-08-05 09:49:05 +03:00
|
|
|
! GIT_DIR="$name/.git" git rev-parse -q --verify $sha1_src^0 >/dev/null &&
|
2008-03-11 16:52:16 +03:00
|
|
|
missing_src=t
|
|
|
|
|
|
|
|
test $mod_dst = 160000 &&
|
2017-08-05 09:49:05 +03:00
|
|
|
! GIT_DIR="$name/.git" git rev-parse -q --verify $sha1_dst^0 >/dev/null &&
|
2008-03-11 16:52:16 +03:00
|
|
|
missing_dst=t
|
2007-06-27 03:40:58 +04:00
|
|
|
|
2016-06-01 03:27:59 +03:00
|
|
|
display_name=$(git submodule--helper relative-path "$name" "$wt_prefix")
|
2013-06-16 18:18:18 +04:00
|
|
|
|
2008-03-11 16:52:16 +03:00
|
|
|
total_commits=
|
|
|
|
case "$missing_src,$missing_dst" in
|
|
|
|
t,)
|
2013-06-16 18:18:18 +04:00
|
|
|
errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_src")"
|
2008-03-11 16:52:16 +03:00
|
|
|
;;
|
|
|
|
,t)
|
2013-06-16 18:18:18 +04:00
|
|
|
errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commit \$sha1_dst")"
|
2008-03-11 16:52:16 +03:00
|
|
|
;;
|
|
|
|
t,t)
|
2013-06-16 18:18:18 +04:00
|
|
|
errmsg="$(eval_gettext " Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"
|
2008-03-11 16:52:16 +03:00
|
|
|
;;
|
|
|
|
*)
|
|
|
|
errmsg=
|
|
|
|
total_commits=$(
|
2014-06-10 16:28:33 +04:00
|
|
|
if test $mod_src = 160000 && test $mod_dst = 160000
|
2008-03-11 16:52:16 +03:00
|
|
|
then
|
|
|
|
range="$sha1_src...$sha1_dst"
|
|
|
|
elif test $mod_src = 160000
|
|
|
|
then
|
|
|
|
range=$sha1_src
|
|
|
|
else
|
|
|
|
range=$sha1_dst
|
|
|
|
fi
|
|
|
|
GIT_DIR="$name/.git" \
|
2010-04-08 23:42:37 +04:00
|
|
|
git rev-list --first-parent $range -- | wc -l
|
2008-03-11 16:52:16 +03:00
|
|
|
)
|
2008-03-12 11:30:01 +03:00
|
|
|
total_commits=" ($(($total_commits + 0)))"
|
2008-03-11 16:52:16 +03:00
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
2019-02-04 00:00:27 +03:00
|
|
|
sha1_abbr_src=$(GIT_DIR="$name/.git" git rev-parse --short $sha1_src 2>/dev/null ||
|
|
|
|
echo $sha1_src | cut -c1-7)
|
|
|
|
sha1_abbr_dst=$(GIT_DIR="$name/.git" git rev-parse --short $sha1_dst 2>/dev/null ||
|
|
|
|
echo $sha1_dst | cut -c1-7)
|
|
|
|
|
2008-03-11 16:52:16 +03:00
|
|
|
if test $status = T
|
|
|
|
then
|
2011-05-21 22:44:09 +04:00
|
|
|
blob="$(gettext "blob")"
|
|
|
|
submodule="$(gettext "submodule")"
|
2008-03-11 16:52:16 +03:00
|
|
|
if test $mod_dst = 160000
|
|
|
|
then
|
2013-06-16 18:18:18 +04:00
|
|
|
echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
|
2008-03-11 16:52:16 +03:00
|
|
|
else
|
2013-06-16 18:18:18 +04:00
|
|
|
echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
|
2008-03-11 16:52:16 +03:00
|
|
|
fi
|
|
|
|
else
|
2013-06-16 18:18:18 +04:00
|
|
|
echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
|
2008-03-11 16:52:16 +03:00
|
|
|
fi
|
|
|
|
if test -n "$errmsg"
|
|
|
|
then
|
|
|
|
# Don't give error msg for modification whose dst is not submodule
|
|
|
|
# i.e. deleted or changed to blob
|
|
|
|
test $mod_dst = 160000 && echo "$errmsg"
|
|
|
|
else
|
2014-06-10 16:28:33 +04:00
|
|
|
if test $mod_src = 160000 && test $mod_dst = 160000
|
2008-03-11 16:52:16 +03:00
|
|
|
then
|
2008-03-11 16:52:17 +03:00
|
|
|
limit=
|
|
|
|
test $summary_limit -gt 0 && limit="-$summary_limit"
|
2008-03-11 16:52:16 +03:00
|
|
|
GIT_DIR="$name/.git" \
|
2008-03-11 16:52:17 +03:00
|
|
|
git log $limit --pretty='format: %m %s' \
|
2008-03-11 16:52:16 +03:00
|
|
|
--first-parent $sha1_src...$sha1_dst
|
|
|
|
elif test $mod_dst = 160000
|
|
|
|
then
|
|
|
|
GIT_DIR="$name/.git" \
|
|
|
|
git log --pretty='format: > %s' -1 $sha1_dst
|
|
|
|
else
|
|
|
|
GIT_DIR="$name/.git" \
|
|
|
|
git log --pretty='format: < %s' -1 $sha1_src
|
|
|
|
fi
|
|
|
|
echo
|
|
|
|
fi
|
|
|
|
echo
|
2013-09-06 21:43:06 +04:00
|
|
|
done
|
2008-03-11 16:52:15 +03:00
|
|
|
}
|
2007-05-26 17:56:40 +04:00
|
|
|
#
|
2007-06-11 23:12:24 +04:00
|
|
|
# List all submodules, prefixed with:
|
2007-05-26 17:56:40 +04:00
|
|
|
# - submodule not initialized
|
|
|
|
# + different revision checked out
|
|
|
|
#
|
|
|
|
# If --cached was specified the revision in the index will be printed
|
|
|
|
# instead of the currently checked out revision.
|
|
|
|
#
|
|
|
|
# $@ = requested paths (default to all)
|
|
|
|
#
|
2008-01-15 13:35:49 +03:00
|
|
|
cmd_status()
|
2007-05-26 17:56:40 +04:00
|
|
|
{
|
2008-01-15 13:48:45 +03:00
|
|
|
# parse $args after "submodule ... status".
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-q|--quiet)
|
2009-06-17 02:33:00 +04:00
|
|
|
GIT_QUIET=1
|
2008-01-15 13:48:45 +03:00
|
|
|
;;
|
|
|
|
--cached)
|
|
|
|
cached=1
|
|
|
|
;;
|
2009-08-19 05:45:24 +04:00
|
|
|
--recursive)
|
|
|
|
recursive=1
|
|
|
|
;;
|
2008-01-15 13:48:45 +03:00
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
2019-04-12 13:08:19 +03:00
|
|
|
git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@"
|
2007-05-26 17:56:40 +04:00
|
|
|
}
|
2008-08-24 23:43:37 +04:00
|
|
|
#
|
|
|
|
# Sync remote urls for submodules
|
|
|
|
# This makes the value for remote.$remote.url match the value
|
|
|
|
# specified in .gitmodules.
|
|
|
|
#
|
|
|
|
cmd_sync()
|
|
|
|
{
|
|
|
|
while test $# -ne 0
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-q|--quiet)
|
2009-06-17 02:33:00 +04:00
|
|
|
GIT_QUIET=1
|
2008-08-24 23:43:37 +04:00
|
|
|
shift
|
|
|
|
;;
|
2012-10-26 23:44:42 +04:00
|
|
|
--recursive)
|
|
|
|
recursive=1
|
|
|
|
shift
|
|
|
|
;;
|
2008-08-24 23:43:37 +04:00
|
|
|
--)
|
|
|
|
shift
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
2017-03-17 01:29:45 +03:00
|
|
|
|
2019-04-12 13:08:19 +03:00
|
|
|
git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
|
2008-08-24 23:43:37 +04:00
|
|
|
}
|
2007-05-26 17:56:40 +04:00
|
|
|
|
2016-12-12 22:04:35 +03:00
|
|
|
cmd_absorbgitdirs()
|
|
|
|
{
|
|
|
|
git submodule--helper absorb-git-dirs --prefix "$wt_prefix" "$@"
|
|
|
|
}
|
|
|
|
|
2008-01-15 13:48:45 +03:00
|
|
|
# This loop parses the command line arguments to find the
|
|
|
|
# subcommand name to dispatch. Parsing of the subcommand specific
|
|
|
|
# options are primarily done by the subcommand implementations.
|
|
|
|
# Subcommand specific options such as --branch and --cached are
|
|
|
|
# parsed here as well, for backward compatibility.
|
|
|
|
|
|
|
|
while test $# != 0 && test -z "$command"
|
2007-05-26 17:56:40 +04:00
|
|
|
do
|
|
|
|
case "$1" in
|
2019-10-29 20:01:52 +03:00
|
|
|
add | foreach | init | deinit | update | set-branch | set-url | status | summary | sync | absorbgitdirs)
|
2008-01-15 13:48:45 +03:00
|
|
|
command=$1
|
2007-05-26 17:56:40 +04:00
|
|
|
;;
|
|
|
|
-q|--quiet)
|
2009-06-17 02:33:00 +04:00
|
|
|
GIT_QUIET=1
|
2007-05-26 17:56:40 +04:00
|
|
|
;;
|
2007-06-25 01:06:07 +04:00
|
|
|
-b|--branch)
|
|
|
|
case "$2" in
|
|
|
|
'')
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
branch="$2"; shift
|
|
|
|
;;
|
2007-05-26 17:56:40 +04:00
|
|
|
--cached)
|
2008-03-11 16:52:15 +03:00
|
|
|
cached="$1"
|
2007-05-26 17:56:40 +04:00
|
|
|
;;
|
|
|
|
--)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
usage
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
2008-01-15 13:48:45 +03:00
|
|
|
# No command word defaults to "status"
|
2012-09-22 15:27:59 +04:00
|
|
|
if test -z "$command"
|
|
|
|
then
|
|
|
|
if test $# = 0
|
|
|
|
then
|
|
|
|
command=status
|
|
|
|
else
|
|
|
|
usage
|
|
|
|
fi
|
|
|
|
fi
|
2008-01-15 13:48:45 +03:00
|
|
|
|
2019-02-08 14:21:34 +03:00
|
|
|
# "-b branch" is accepted only by "add" and "set-branch"
|
|
|
|
if test -n "$branch" && (test "$command" != add || test "$command" != set-branch)
|
2008-01-15 13:48:45 +03:00
|
|
|
then
|
2007-06-25 01:06:07 +04:00
|
|
|
usage
|
2008-01-15 13:48:45 +03:00
|
|
|
fi
|
|
|
|
|
2008-03-11 16:52:15 +03:00
|
|
|
# "--cached" is accepted only by "status" and "summary"
|
2014-06-10 16:28:33 +04:00
|
|
|
if test -n "$cached" && test "$command" != status && test "$command" != summary
|
2008-01-15 13:48:45 +03:00
|
|
|
then
|
2007-05-26 17:56:40 +04:00
|
|
|
usage
|
2008-01-15 13:48:45 +03:00
|
|
|
fi
|
|
|
|
|
2019-02-08 14:21:34 +03:00
|
|
|
"cmd_$(echo $command | sed -e s/-/_/g)" "$@"
|