mirror of
https://github.com/git/git.git
synced 2024-11-24 18:33:43 +08:00
Merge branch 'py/submodule'
* py/submodule: git-submodule summary: fix that some "wc" flavors produce leading spaces git-submodule summary: test git-submodule summary: documentation git-submodule summary: limit summary size git-submodule summary: show commit summary git-submodule summary: code framework
This commit is contained in:
commit
37bd6c5a2a
@ -12,6 +12,7 @@ SYNOPSIS
|
|||||||
'git-submodule' [--quiet] add [-b branch] [--] <repository> [<path>]
|
'git-submodule' [--quiet] add [-b branch] [--] <repository> [<path>]
|
||||||
'git-submodule' [--quiet] status [--cached] [--] [<path>...]
|
'git-submodule' [--quiet] status [--cached] [--] [<path>...]
|
||||||
'git-submodule' [--quiet] [init|update] [--] [<path>...]
|
'git-submodule' [--quiet] [init|update] [--] [<path>...]
|
||||||
|
'git-submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
|
||||||
|
|
||||||
|
|
||||||
COMMANDS
|
COMMANDS
|
||||||
@ -47,6 +48,11 @@ update::
|
|||||||
checkout the commit specified in the index of the containing repository.
|
checkout the commit specified in the index of the containing repository.
|
||||||
This will make the submodules HEAD be detached.
|
This will make the submodules HEAD be detached.
|
||||||
|
|
||||||
|
summary::
|
||||||
|
Show commit summary between the given commit (defaults to HEAD) and
|
||||||
|
working tree/index. For a submodule in question, a series of commits
|
||||||
|
in the submodule between the given super project commit and the
|
||||||
|
index or working tree (switched by --cached) are shown.
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
@ -57,9 +63,16 @@ OPTIONS
|
|||||||
Branch of repository to add as submodule.
|
Branch of repository to add as submodule.
|
||||||
|
|
||||||
--cached::
|
--cached::
|
||||||
Display the SHA-1 stored in the index, not the SHA-1 of the currently
|
This option is only valid for status and summary commands. These
|
||||||
checked out submodule commit. This option is only valid for the
|
commands typically use the commit found in the submodule HEAD, but
|
||||||
status command.
|
with this option, the commit stored in the index is used instead.
|
||||||
|
|
||||||
|
-n, --summary-limit::
|
||||||
|
This option is only valid for the summary command.
|
||||||
|
Limit the summary size (number of commits shown in total).
|
||||||
|
Giving 0 will disable the summary; a negative number means unlimted
|
||||||
|
(the default). This limit only applies to modified submodules. The
|
||||||
|
size is always limited to 1 for added/deleted/typechanged submodules.
|
||||||
|
|
||||||
<path>::
|
<path>::
|
||||||
Path to submodule(s). When specified this will restrict the command
|
Path to submodule(s). When specified this will restrict the command
|
||||||
|
180
git-submodule.sh
180
git-submodule.sh
@ -4,7 +4,9 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2007 Lars Hjemli
|
# Copyright (c) 2007 Lars Hjemli
|
||||||
|
|
||||||
USAGE='[--quiet] [--cached] [add <repo> [-b branch]|status|init|update] [--] [<path>...]'
|
USAGE="[--quiet] [--cached] \
|
||||||
|
[add <repo> [-b branch]|status|init|update|summary [-n|--summary-limit <n>] [<commit>]] \
|
||||||
|
[--] [<path>...]"
|
||||||
OPTIONS_SPEC=
|
OPTIONS_SPEC=
|
||||||
. git-sh-setup
|
. git-sh-setup
|
||||||
require_work_tree
|
require_work_tree
|
||||||
@ -330,7 +332,175 @@ set_name_rev () {
|
|||||||
) )
|
) )
|
||||||
test -z "$revname" || revname=" ($revname)"
|
test -z "$revname" || revname=" ($revname)"
|
||||||
}
|
}
|
||||||
|
#
|
||||||
|
# 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() {
|
||||||
|
summary_limit=-1
|
||||||
|
|
||||||
|
# parse $args after "submodule ... summary".
|
||||||
|
while test $# -ne 0
|
||||||
|
do
|
||||||
|
case "$1" in
|
||||||
|
--cached)
|
||||||
|
cached="$1"
|
||||||
|
;;
|
||||||
|
-n|--summary-limit)
|
||||||
|
if summary_limit=$(($2 + 0)) 2>/dev/null && test "$summary_limit" = "$2"
|
||||||
|
then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
test $summary_limit = 0 && return
|
||||||
|
|
||||||
|
if rev=$(git rev-parse --verify "$1^0" 2>/dev/null)
|
||||||
|
then
|
||||||
|
head=$rev
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
head=HEAD
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd_to_toplevel
|
||||||
|
# Get modified modules cared by user
|
||||||
|
modules=$(git diff-index $cached --raw $head -- "$@" |
|
||||||
|
grep -e '^:160000' -e '^:[0-7]* 160000' |
|
||||||
|
while read mod_src mod_dst sha1_src sha1_dst status name
|
||||||
|
do
|
||||||
|
# Always show modules deleted or type-changed (blob<->module)
|
||||||
|
test $status = D -o $status = T && echo "$name" && continue
|
||||||
|
# Also show added or modified modules which are checked out
|
||||||
|
GIT_DIR="$name/.git" git-rev-parse --git-dir >/dev/null 2>&1 &&
|
||||||
|
echo "$name"
|
||||||
|
done
|
||||||
|
)
|
||||||
|
|
||||||
|
test -n "$modules" &&
|
||||||
|
git diff-index $cached --raw $head -- $modules |
|
||||||
|
grep -e '^:160000' -e '^:[0-7]* 160000' |
|
||||||
|
cut -c2- |
|
||||||
|
while read mod_src mod_dst sha1_src sha1_dst status name
|
||||||
|
do
|
||||||
|
if test -z "$cached" &&
|
||||||
|
test $sha1_dst = 0000000000000000000000000000000000000000
|
||||||
|
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
|
||||||
|
echo >&2 "unexpected mode $mod_dst"
|
||||||
|
continue ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
missing_src=
|
||||||
|
missing_dst=
|
||||||
|
|
||||||
|
test $mod_src = 160000 &&
|
||||||
|
! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_src^0 >/dev/null 2>&1 &&
|
||||||
|
missing_src=t
|
||||||
|
|
||||||
|
test $mod_dst = 160000 &&
|
||||||
|
! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_dst^0 >/dev/null 2>&1 &&
|
||||||
|
missing_dst=t
|
||||||
|
|
||||||
|
total_commits=
|
||||||
|
case "$missing_src,$missing_dst" in
|
||||||
|
t,)
|
||||||
|
errmsg=" Warn: $name doesn't contain commit $sha1_src"
|
||||||
|
;;
|
||||||
|
,t)
|
||||||
|
errmsg=" Warn: $name doesn't contain commit $sha1_dst"
|
||||||
|
;;
|
||||||
|
t,t)
|
||||||
|
errmsg=" Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
errmsg=
|
||||||
|
total_commits=$(
|
||||||
|
if test $mod_src = 160000 -a $mod_dst = 160000
|
||||||
|
then
|
||||||
|
range="$sha1_src...$sha1_dst"
|
||||||
|
elif test $mod_src = 160000
|
||||||
|
then
|
||||||
|
range=$sha1_src
|
||||||
|
else
|
||||||
|
range=$sha1_dst
|
||||||
|
fi
|
||||||
|
GIT_DIR="$name/.git" \
|
||||||
|
git log --pretty=oneline --first-parent $range | wc -l
|
||||||
|
)
|
||||||
|
total_commits=" ($(($total_commits + 0)))"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
sha1_abbr_src=$(echo $sha1_src | cut -c1-7)
|
||||||
|
sha1_abbr_dst=$(echo $sha1_dst | cut -c1-7)
|
||||||
|
if test $status = T
|
||||||
|
then
|
||||||
|
if test $mod_dst = 160000
|
||||||
|
then
|
||||||
|
echo "* $name $sha1_abbr_src(blob)->$sha1_abbr_dst(submodule)$total_commits:"
|
||||||
|
else
|
||||||
|
echo "* $name $sha1_abbr_src(submodule)->$sha1_abbr_dst(blob)$total_commits:"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
|
||||||
|
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
|
||||||
|
if test $mod_src = 160000 -a $mod_dst = 160000
|
||||||
|
then
|
||||||
|
limit=
|
||||||
|
test $summary_limit -gt 0 && limit="-$summary_limit"
|
||||||
|
GIT_DIR="$name/.git" \
|
||||||
|
git log $limit --pretty='format: %m %s' \
|
||||||
|
--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
|
||||||
|
done
|
||||||
|
}
|
||||||
#
|
#
|
||||||
# List all submodules, prefixed with:
|
# List all submodules, prefixed with:
|
||||||
# - submodule not initialized
|
# - submodule not initialized
|
||||||
@ -401,7 +571,7 @@ cmd_status()
|
|||||||
while test $# != 0 && test -z "$command"
|
while test $# != 0 && test -z "$command"
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
add | init | update | status)
|
add | init | update | status | summary)
|
||||||
command=$1
|
command=$1
|
||||||
;;
|
;;
|
||||||
-q|--quiet)
|
-q|--quiet)
|
||||||
@ -416,7 +586,7 @@ do
|
|||||||
branch="$2"; shift
|
branch="$2"; shift
|
||||||
;;
|
;;
|
||||||
--cached)
|
--cached)
|
||||||
cached=1
|
cached="$1"
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
break
|
break
|
||||||
@ -440,8 +610,8 @@ then
|
|||||||
usage
|
usage
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# "--cached" is accepted only by "status"
|
# "--cached" is accepted only by "status" and "summary"
|
||||||
if test -n "$cached" && test "$command" != status
|
if test -n "$cached" && test "$command" != status -a "$command" != summary
|
||||||
then
|
then
|
||||||
usage
|
usage
|
||||||
fi
|
fi
|
||||||
|
195
t/t7401-submodule-summary.sh
Executable file
195
t/t7401-submodule-summary.sh
Executable file
@ -0,0 +1,195 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Ping Yin
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='Summary support for submodules
|
||||||
|
|
||||||
|
This test tries to verify the sanity of summary subcommand of git-submodule.
|
||||||
|
'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
add_file () {
|
||||||
|
sm=$1
|
||||||
|
shift
|
||||||
|
owd=$(pwd)
|
||||||
|
cd "$sm"
|
||||||
|
for name; do
|
||||||
|
echo "$name" > "$name" &&
|
||||||
|
git add "$name" &&
|
||||||
|
test_tick &&
|
||||||
|
git commit -m "Add $name"
|
||||||
|
done >/dev/null
|
||||||
|
git rev-parse --verify HEAD | cut -c1-7
|
||||||
|
cd "$owd"
|
||||||
|
}
|
||||||
|
commit_file () {
|
||||||
|
test_tick &&
|
||||||
|
git commit "$@" -m "Commit $*" >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
test_create_repo sm1 &&
|
||||||
|
add_file . foo
|
||||||
|
|
||||||
|
head1=$(add_file sm1 foo1 foo2)
|
||||||
|
|
||||||
|
test_expect_success 'added submodule' "
|
||||||
|
git add sm1 &&
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 0000000...$head1 (2):
|
||||||
|
> Add foo2
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
commit_file sm1 &&
|
||||||
|
head2=$(add_file sm1 foo3)
|
||||||
|
|
||||||
|
test_expect_success 'modified submodule(forward)' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head1...$head2 (1):
|
||||||
|
> Add foo3
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
commit_file sm1 &&
|
||||||
|
cd sm1 &&
|
||||||
|
git reset --hard HEAD~2 >/dev/null &&
|
||||||
|
head3=$(git rev-parse --verify HEAD | cut -c1-7) &&
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
test_expect_success 'modified submodule(backward)' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head2...$head3 (2):
|
||||||
|
< Add foo3
|
||||||
|
< Add foo2
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
head4=$(add_file sm1 foo4 foo5) &&
|
||||||
|
head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD)
|
||||||
|
test_expect_success 'modified submodule(backward and forward)' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head2...$head4 (4):
|
||||||
|
> Add foo5
|
||||||
|
> Add foo4
|
||||||
|
< Add foo3
|
||||||
|
< Add foo2
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
test_expect_success '--summary-limit' "
|
||||||
|
git submodule summary -n 3 >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head2...$head4 (4):
|
||||||
|
> Add foo5
|
||||||
|
> Add foo4
|
||||||
|
< Add foo3
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
commit_file sm1 &&
|
||||||
|
mv sm1 sm1-bak &&
|
||||||
|
echo sm1 >sm1 &&
|
||||||
|
head5=$(git hash-object sm1 | cut -c1-7) &&
|
||||||
|
git add sm1 &&
|
||||||
|
rm -f sm1 &&
|
||||||
|
mv sm1-bak sm1
|
||||||
|
|
||||||
|
test_expect_success 'typechanged submodule(submodule->blob), --cached' "
|
||||||
|
git submodule summary --cached >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head4(submodule)->$head5(blob) (3):
|
||||||
|
< Add foo5
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
rm -rf sm1 &&
|
||||||
|
git checkout-index sm1
|
||||||
|
test_expect_success 'typechanged submodule(submodule->blob)' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head4(submodule)->$head5(blob):
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
rm -f sm1 &&
|
||||||
|
test_create_repo sm1 &&
|
||||||
|
head6=$(add_file sm1 foo6 foo7)
|
||||||
|
test_expect_success 'nonexistent commit' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head4...$head6:
|
||||||
|
Warn: sm1 doesn't contain commit $head4_full
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
commit_file
|
||||||
|
test_expect_success 'typechanged submodule(blob->submodule)' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head5(blob)->$head6(submodule) (2):
|
||||||
|
> Add foo7
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
commit_file sm1 &&
|
||||||
|
rm -rf sm1
|
||||||
|
test_expect_success 'deleted submodule' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head6...0000000:
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
test_create_repo sm2 &&
|
||||||
|
head7=$(add_file sm2 foo8 foo9) &&
|
||||||
|
git add sm2
|
||||||
|
|
||||||
|
test_expect_success 'multiple submodules' "
|
||||||
|
git submodule summary >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head6...0000000:
|
||||||
|
|
||||||
|
* sm2 0000000...$head7 (2):
|
||||||
|
> Add foo9
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
test_expect_success 'path filter' "
|
||||||
|
git submodule summary sm2 >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm2 0000000...$head7 (2):
|
||||||
|
> Add foo9
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
commit_file sm2
|
||||||
|
test_expect_success 'given commit' "
|
||||||
|
git submodule summary HEAD^ >actual &&
|
||||||
|
diff actual - <<-EOF
|
||||||
|
* sm1 $head6...0000000:
|
||||||
|
|
||||||
|
* sm2 0000000...$head7 (2):
|
||||||
|
> Add foo9
|
||||||
|
|
||||||
|
EOF
|
||||||
|
"
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user