提交 fe3623c6 编写于 作者: J Junio C Hamano

Merge branch 'lt/request-pull'

Discard the accumulated "heuristics" to guess from which branch the
result wants to be pulled from and make sure what the end user
specified is not second-guessed by "git request-pull", to avoid
mistakes.

* lt/request-pull:
  request-pull: documentation updates
  request-pull: resurrect "pretty refname" feature
  request-pull: test updates
  request-pull: pick up tag message as before
  request-pull: allow "local:remote" to specify names on both ends
  request-pull: more strictly match local/remote branches
......@@ -13,22 +13,65 @@ SYNOPSIS
DESCRIPTION
-----------
Summarizes the changes between two commits to the standard output, and includes
the given URL in the generated summary.
Generate a request asking your upstream project to pull changes into
their tree. The request, printed to the standard output, summarizes
the changes and indicates from where they can be pulled.
The upstream project is expected to have the commit named by
`<start>` and the output asks it to integrate the changes you made
since that commit, up to the commit named by `<end>`, by visiting
the repository named by `<url>`.
OPTIONS
-------
-p::
Show patch text
Include patch text in the output.
<start>::
Commit to start at.
Commit to start at. This names a commit that is already in
the upstream history.
<url>::
URL to include in the summary.
The repository URL to be pulled from.
<end>::
Commit to end at; defaults to HEAD.
Commit to end at (defaults to HEAD). This names the commit
at the tip of the history you are asking to be pulled.
+
When the repository named by `<url>` has the commit at a tip of a
ref that is different from the ref you have locally, you can use the
`<local>:<remote>` syntax, to have its local name, a colon `:`, and
its remote name.
EXAMPLE
-------
Imagine that you built your work on your `master` branch on top of
the `v1.0` release, and want it to be integrated to the project.
First you push that change to your public repository for others to
see:
git push https://git.ko.xz/project master
Then, you run this command:
git request-pull v1.0 https://git.ko.xz/project master
which will produce a request to the upstream, summarizing the
changes between the `v1.0` release and your `master`, to pull it
from your public repository.
If you pushed your change to a branch whose name is different from
the one you have locally, e.g.
git push https://git.ko.xz/project master:for-linus
then you can ask that to be pulled with
git request-pull v1.0 https://git.ko.xz/project master:for-linus
GIT
---
......
......@@ -36,20 +36,7 @@ do
shift
done
base=$1 url=$2 head=${3-HEAD} status=0 branch_name=
headref=$(git symbolic-ref -q "$head")
if git show-ref -q --verify "$headref"
then
branch_name=${headref#refs/heads/}
if test "z$branch_name" = "z$headref" ||
! git config "branch.$branch_name.description" >/dev/null
then
branch_name=
fi
fi
tag_name=$(git describe --exact "$head^0" 2>/dev/null)
base=$1 url=$2 status=0
test -n "$base" && test -n "$url" || usage
......@@ -59,55 +46,78 @@ then
die "fatal: Not a valid revision: $base"
fi
#
# $3 must be a symbolic ref, a unique ref, or
# a SHA object expression. It can also be of
# the format 'local-name:remote-name'.
#
local=${3%:*}
local=${local:-HEAD}
remote=${3#*:}
pretty_remote=${remote#refs/}
pretty_remote=${pretty_remote#heads/}
head=$(git symbolic-ref -q "$local")
head=${head:-$(git show-ref --heads --tags "$local" | cut -d' ' -f2)}
head=${head:-$(git rev-parse --quiet --verify "$local")}
# None of the above? Bad.
test -z "$head" && die "fatal: Not a valid revision: $local"
# This also verifies that the resulting head is unique:
# "git show-ref" could have shown multiple matching refs..
headrev=$(git rev-parse --verify --quiet "$head"^0)
if test -z "$headrev"
test -z "$headrev" && die "fatal: Ambiguous revision: $local"
# Was it a branch with a description?
branch_name=${head#refs/heads/}
if test "z$branch_name" = "z$headref" ||
! git config "branch.$branch_name.description" >/dev/null
then
die "fatal: Not a valid revision: $head"
branch_name=
fi
merge_base=$(git merge-base $baserev $headrev) ||
die "fatal: No commits in common between $base and $head"
# $head is the token given from the command line, and $tag_name, if
# exists, is the tag we are going to show the commit information for.
# If that tag exists at the remote and it points at the commit, use it.
# Otherwise, if a branch with the same name as $head exists at the remote
# and their values match, use that instead.
# $head is the refname from the command line.
# If a ref with the same name as $head exists at the remote
# and their values match, use that.
#
# Otherwise find a random ref that matches $headrev.
find_matching_ref='
sub abbr {
my $ref = shift;
if ($ref =~ s|^refs/heads/|| || $ref =~ s|^refs/tags/|tags/|) {
return $ref;
} else {
return $ref;
}
}
my ($head,$headrev) = (@ARGV);
my ($found);
my ($tagged, $branch, $found);
while (<STDIN>) {
my ($sha1, $ref, $deref) = /^(\S+)\s+(\S+?)(\^\{\})?$/;
next unless ($sha1 eq $ARGV[1]);
$found = abbr($ref);
if ($deref && $ref eq "tags/$ARGV[2]") {
$tagged = $found;
last;
chomp;
my ($sha1, $ref, $deref) = /^(\S+)\s+([^^]+)(\S*)$/;
my ($pattern);
next unless ($sha1 eq $headrev);
$pattern="/$head\$";
if ($ref eq $head) {
$found = $ref;
}
if ($ref =~ /$pattern/) {
$found = $ref;
}
if ($ref =~ m|/\Q$ARGV[0]\E$|) {
$exact = $found;
if ($sha1 eq $head) {
$found = $sha1;
}
}
if ($tagged) {
print "$tagged\n";
} elsif ($exact) {
print "$exact\n";
} elsif ($found) {
if ($found) {
print "$found\n";
}
'
ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "$head" "$headrev" "$tag_name")
ref=$(git ls-remote "$url" | @@PERL@@ -e "$find_matching_ref" "${remote:-HEAD}" "$headrev")
if test -z "$ref"
then
echo "warn: No match for commit $headrev found at $url" >&2
echo "warn: Are you sure you pushed '${remote:-HEAD}' there?" >&2
status=1
fi
url=$(git ls-remote --get-url "$url")
......@@ -117,7 +127,7 @@ git show -s --format='The following changes since commit %H:
are available in the git repository at:
' $merge_base &&
echo " $url${ref+ $ref}" &&
echo " $url $pretty_remote" &&
git show -s --format='
for you to fetch changes up to %H:
......@@ -125,39 +135,23 @@ for you to fetch changes up to %H:
----------------------------------------------------------------' $headrev &&
if test -n "$branch_name"
if test $(git cat-file -t "$head") = tag
then
echo "(from the branch description for $branch_name local branch)"
echo
git config "branch.$branch_name.description"
fi &&
if test -n "$tag_name"
then
if test -z "$ref" || test "$ref" != "tags/$tag_name"
then
echo >&2 "warn: You locally have $tag_name but it does not (yet)"
echo >&2 "warn: appear to be at $url"
echo >&2 "warn: Do you want to push it there, perhaps?"
fi
git cat-file tag "$tag_name" |
git cat-file tag "$head" |
sed -n -e '1,/^$/d' -e '/^-----BEGIN PGP /q' -e p
echo
echo "----------------------------------------------------------------"
fi &&
if test -n "$branch_name" || test -n "$tag_name"
if test -n "$branch_name"
then
echo "(from the branch description for $branch_name local branch)"
echo
git config "branch.$branch_name.description"
echo "----------------------------------------------------------------"
fi &&
git shortlog ^$baserev $headrev &&
git diff -M --stat --summary $patch $merge_base..$headrev || status=1
if test -z "$ref"
then
echo "warn: No branch of $url is at:" >&2
git show -s --format='warn: %h: %s' $headrev >&2
echo "warn: Are you sure you pushed '$head' there?" >&2
status=1
fi
exit $status
......@@ -86,7 +86,7 @@ test_expect_success 'setup: two scripts for reading pull requests' '
s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g
s/ [^ ].*/ SUBJECT/g
s/ [^ ].* (DATE)/ SUBJECT (DATE)/g
s/for-upstream/BRANCH/g
s|tags/full|BRANCH|g
s/mnemonic.txt/FILENAME/g
s/^version [0-9]/VERSION/
/^ FILENAME | *[0-9]* [-+]*\$/ b diffstat
......@@ -127,7 +127,7 @@ test_expect_success 'pull request when forgot to push' '
test_must_fail git request-pull initial "$downstream_url" \
2>../err
) &&
grep "No branch of.*is at:\$" err &&
grep "No match for commit .*" err &&
grep "Are you sure you pushed" err
'
......@@ -141,7 +141,7 @@ test_expect_success 'pull request after push' '
git checkout initial &&
git merge --ff-only master &&
git push origin master:for-upstream &&
git request-pull initial origin >../request
git request-pull initial origin master:for-upstream >../request
) &&
sed -nf read-request.sed <request >digest &&
cat digest &&
......@@ -160,7 +160,7 @@ test_expect_success 'pull request after push' '
'
test_expect_success 'request names an appropriate branch' '
test_expect_success 'request asks HEAD to be pulled' '
rm -fr downstream.git &&
git init --bare downstream.git &&
......@@ -179,7 +179,7 @@ test_expect_success 'request names an appropriate branch' '
read repository &&
read branch
} <digest &&
test "$branch" = tags/full
test -z "$branch"
'
......@@ -212,12 +212,18 @@ test_expect_success 'pull request format' '
cd local &&
git checkout initial &&
git merge --ff-only master &&
git push origin master:for-upstream &&
git request-pull initial "$downstream_url" >../request
git push origin tags/full &&
git request-pull initial "$downstream_url" tags/full >../request
) &&
<request sed -nf fuzz.sed >request.fuzzy &&
test_i18ncmp expect request.fuzzy
test_i18ncmp expect request.fuzzy &&
(
cd local &&
git request-pull initial "$downstream_url" tags/full:refs/tags/full
) >request &&
sed -nf fuzz.sed <request >request.fuzzy &&
test_i18ncmp expect request.fuzzy
'
test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
......@@ -229,7 +235,7 @@ test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' '
git checkout initial &&
git merge --ff-only master &&
git push origin master:for-upstream &&
git request-pull -- initial "$downstream_url" >../request
git request-pull -- initial "$downstream_url" master:for-upstream >../request
)
'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册