* [PATCH 1/3] git-am: record full index line in the patch used while rebasing
2013-02-01 4:32 ` [PATCH 0/3] rebasing changes that update submodules Junio C Hamano
@ 2013-02-01 4:32 ` Junio C Hamano
2013-02-01 6:25 ` Martin von Zweigbergk
2013-02-01 4:32 ` [PATCH 2/3] apply: simplify build_fake_ancestor() Junio C Hamano
2013-02-01 4:32 ` [PATCH 3/3] apply: diagnose incomplete submodule object name better Junio C Hamano
2 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2013-02-01 4:32 UTC (permalink / raw)
To: git; +Cc: Heiko Voigt, Martin von Zweigbergk
Earlier, a230949 (am --rebasing: get patch body from commit, not
from mailbox, 2012-06-26) learned to regenerate patch body from the
commit object while rebasing, instead of reading from the rebase-am
front-end. While doing so, it used "git diff-tree" but without
giving it the "--full-index" option.
This does not matter for in-repository objects; during rebasing, any
abbreviated object name should uniquely identify them.
But we may be rebasing a commit that contains a change to a gitlink,
in which case we usually should not have the object (it names a
commit in the submodule). A full object name is necessary to later
reconstruct a fake ancestor index for them.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
git-am.sh | 2 +-
t/t7402-submodule-rebase.sh | 30 ++++++++++++++++++++++++++++--
2 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/git-am.sh b/git-am.sh
index c682d34..0e0a096 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -664,7 +664,7 @@ do
sed -e '1,/^$/d' >"$dotest/msg-clean"
echo "$commit" >"$dotest/original-commit"
get_author_ident_from_commit "$commit" >"$dotest/author-script"
- git diff-tree --root --binary "$commit" >"$dotest/patch"
+ git diff-tree --root --binary --full-index "$commit" >"$dotest/patch"
else
git mailinfo $keep $no_inbody_headers $scissors $utf8 "$dotest/msg" "$dotest/patch" \
<"$dotest/$msgnum" >"$dotest/info" ||
diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh
index f919c8d..8e32f19 100755
--- a/t/t7402-submodule-rebase.sh
+++ b/t/t7402-submodule-rebase.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2008 Johannes Schindelin
#
-test_description='Test rebasing and stashing with dirty submodules'
+test_description='Test rebasing, stashing, etc. with submodules'
. ./test-lib.sh
@@ -20,7 +20,8 @@ test_expect_success setup '
echo second line >> file &&
(cd submodule && git pull) &&
test_tick &&
- git commit -m file-and-submodule -a
+ git commit -m file-and-submodule -a &&
+ git branch added-submodule
'
@@ -89,4 +90,29 @@ test_expect_success 'stash with a dirty submodule' '
'
+test_expect_success 'rebasing submodule that should conflict' '
+ git reset --hard &&
+ git checkout added-submodule &&
+ git add submodule &&
+ test_tick &&
+ git commit -m third &&
+ (
+ cd submodule &&
+ git commit --allow-empty -m extra
+ ) &&
+ git add submodule &&
+ test_tick &&
+ git commit -m fourth &&
+
+ test_must_fail git rebase --onto HEAD^^ HEAD^ HEAD^0 &&
+ git ls-files -s submodule >actual &&
+ (
+ cd submodule &&
+ echo "160000 $(git rev-parse HEAD^) 1 submodule" &&
+ echo "160000 $(git rev-parse HEAD^^) 2 submodule" &&
+ echo "160000 $(git rev-parse HEAD) 3 submodule"
+ ) >expect &&
+ test_cmp expect actual
+'
+
test_done
--
1.8.1.2.612.g09f4be5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/3] git-am: record full index line in the patch used while rebasing
2013-02-01 4:32 ` [PATCH 1/3] git-am: record full index line in the patch used while rebasing Junio C Hamano
@ 2013-02-01 6:25 ` Martin von Zweigbergk
0 siblings, 0 replies; 11+ messages in thread
From: Martin von Zweigbergk @ 2013-02-01 6:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Heiko Voigt
On Thu, Jan 31, 2013 at 8:32 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Earlier, a230949 (am --rebasing: get patch body from commit, not
> from mailbox, 2012-06-26) learned to regenerate patch body from the
> commit object while rebasing, instead of reading from the rebase-am
> front-end. While doing so, it used "git diff-tree" but without
> giving it the "--full-index" option.
>
> This does not matter for in-repository objects; during rebasing, any
> abbreviated object name should uniquely identify them.
>
> But we may be rebasing a commit that contains a change to a gitlink,
> in which case we usually should not have the object (it names a
> commit in the submodule). A full object name is necessary to later
> reconstruct a fake ancestor index for them.
>From what I can understand, this all makes sense. I didn't notice the
emails about the breakage until now, but I wouldn't have known where
to even start looking anyway, so thanks a lot for taking care of it.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/3] apply: simplify build_fake_ancestor()
2013-02-01 4:32 ` [PATCH 0/3] rebasing changes that update submodules Junio C Hamano
2013-02-01 4:32 ` [PATCH 1/3] git-am: record full index line in the patch used while rebasing Junio C Hamano
@ 2013-02-01 4:32 ` Junio C Hamano
2013-02-01 4:32 ` [PATCH 3/3] apply: diagnose incomplete submodule object name better Junio C Hamano
2 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2013-02-01 4:32 UTC (permalink / raw)
To: git; +Cc: Heiko Voigt, Martin von Zweigbergk
The local variable sha1_ptr in the build_fake_ancestor() function
used to either point at the null_sha1[] (if the ancestor did not
have the path) or at sha1[] (if we read the object name into the
local array), but 7a98869 (apply: get rid of --index-info in favor
of --build-fake-ancestor, 2007-09-17) made the "missing in the
ancestor" case unnecessary, hence sha1_ptr, when used, always points
at the local array.
Get rid of the unneeded variable, and restructure the if/else
cascade a bit to make it easier to read. There should be no
behaviour change.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/apply.c | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 156b3ce..a1db7b4 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3598,7 +3598,6 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
* worth showing the new sha1 prefix, but until then...
*/
for (patch = list; patch; patch = patch->next) {
- const unsigned char *sha1_ptr;
unsigned char sha1[20];
struct cache_entry *ce;
const char *name;
@@ -3606,20 +3605,19 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
name = patch->old_name ? patch->old_name : patch->new_name;
if (0 < patch->is_new)
continue;
- else if (get_sha1_blob(patch->old_sha1_prefix, sha1))
- /* git diff has no index line for mode/type changes */
- if (!patch->lines_added && !patch->lines_deleted) {
- if (get_current_sha1(patch->old_name, sha1))
- die("mode change for %s, which is not "
- "in current HEAD", name);
- sha1_ptr = sha1;
- } else
- die("sha1 information is lacking or useless "
- "(%s).", name);
- else
- sha1_ptr = sha1;
- ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
+ if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
+ ; /* ok */
+ } else if (!patch->lines_added && !patch->lines_deleted) {
+ /* mode-only change: update the current */
+ if (get_current_sha1(patch->old_name, sha1))
+ die("mode change for %s, which is not "
+ "in current HEAD", name);
+ } else
+ die("sha1 information is lacking or useless "
+ "(%s).", name);
+
+ ce = make_cache_entry(patch->old_mode, sha1, name, 0, 0);
if (!ce)
die(_("make_cache_entry failed for path '%s'"), name);
if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
--
1.8.1.2.612.g09f4be5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/3] apply: diagnose incomplete submodule object name better
2013-02-01 4:32 ` [PATCH 0/3] rebasing changes that update submodules Junio C Hamano
2013-02-01 4:32 ` [PATCH 1/3] git-am: record full index line in the patch used while rebasing Junio C Hamano
2013-02-01 4:32 ` [PATCH 2/3] apply: simplify build_fake_ancestor() Junio C Hamano
@ 2013-02-01 4:32 ` Junio C Hamano
2013-02-05 19:19 ` Re* " Junio C Hamano
2 siblings, 1 reply; 11+ messages in thread
From: Junio C Hamano @ 2013-02-01 4:32 UTC (permalink / raw)
To: git; +Cc: Heiko Voigt, Martin von Zweigbergk
"git am -3" uses this function to build a tree that records how the
preimage the patch was created from would have looked like. An
abbreviated object name on the index line is ordinarily sufficient
for us to figure out the object name the preimage tree would have
contained, but a change to a submodule by definition shows an object
name of a submodule commit which our repository should not have, and
get_sha1_blob() is not an appropriate way to read it (or get_sha1()
for that matter).
Use get_sha1_hex() and complain if we do not find a full object name
there.
We could read from the payload part of the patch to learn the full
object name of the commit, but the primary user "git rebase" has
been fixed to give us a full object name, so this should suffice
for now.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/apply.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index a1db7b4..1f78e2c 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3606,7 +3606,11 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
if (0 < patch->is_new)
continue;
- if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
+ if (S_ISGITLINK(patch->old_mode)) {
+ if (get_sha1_hex(patch->old_sha1_prefix, sha1))
+ die("submoule change for %s without full index name",
+ name);
+ } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
; /* ok */
} else if (!patch->lines_added && !patch->lines_deleted) {
/* mode-only change: update the current */
--
1.8.1.2.612.g09f4be5
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re* [PATCH 3/3] apply: diagnose incomplete submodule object name better
2013-02-01 4:32 ` [PATCH 3/3] apply: diagnose incomplete submodule object name better Junio C Hamano
@ 2013-02-05 19:19 ` Junio C Hamano
0 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2013-02-05 19:19 UTC (permalink / raw)
To: git; +Cc: Heiko Voigt, Martin von Zweigbergk
Junio C Hamano <gitster@pobox.com> writes:
> We could read from the payload part of the patch to learn the full
> object name of the commit, but the primary user "git rebase" has
> been fixed to give us a full object name, so this should suffice
> for now.
And the patch on top to do so looks like this. With this patch in
place, we could drop 1/3 of this series, but there is no strong
reason to do so. After all, 1/3 is all about internal implementation
details.
-- >8 --
Subject: [PATCH 4/3] apply: verify submodule commit object name better
A textual patch also records the submodule commit object name in
full. Make the parsing more robust by reading from there and
verifying the (possibly abbreviated) name on the index line matches.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/apply.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 1f78e2c..e0f1474 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -3587,6 +3587,40 @@ static int get_current_sha1(const char *path, unsigned char *sha1)
return 0;
}
+static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20])
+{
+ /*
+ * A usable gitlink patch has only one fragment (hunk) that looks like:
+ * @@ -1 +1 @@
+ * -Subproject commit <old sha1>
+ * +Subproject commit <new sha1>
+ * or
+ * @@ -1 +0,0 @@
+ * -Subproject commit <old sha1>
+ * for a removal patch.
+ */
+ struct fragment *hunk = p->fragments;
+ static const char heading[] = "-Subproject commit ";
+ char *preimage;
+
+ if (/* does the patch have only one hunk? */
+ hunk && !hunk->next &&
+ /* is its preimage one line? */
+ hunk->oldpos == 1 && hunk->oldlines == 1 &&
+ /* does preimage begin with the heading? */
+ (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL &&
+ !prefixcmp(++preimage, heading) &&
+ /* does it record full SHA-1? */
+ !get_sha1_hex(preimage + sizeof(heading) - 1, sha1) &&
+ preimage[sizeof(heading) + 40 - 1] == '\n' &&
+ /* does the abbreviated name on the index line agree with it? */
+ !prefixcmp(preimage + sizeof(heading) - 1, p->old_sha1_prefix))
+ return 0; /* it all looks fine */
+
+ /* we may have full object name on the index line */
+ return get_sha1_hex(p->old_sha1_prefix, sha1);
+}
+
/* Build an index that contains the just the files needed for a 3way merge */
static void build_fake_ancestor(struct patch *list, const char *filename)
{
@@ -3607,8 +3641,10 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
continue;
if (S_ISGITLINK(patch->old_mode)) {
- if (get_sha1_hex(patch->old_sha1_prefix, sha1))
- die("submoule change for %s without full index name",
+ if (!preimage_sha1_in_gitlink_patch(patch, sha1))
+ ; /* ok, the textual part looks sane */
+ else
+ die("sha1 information is lacking or useless for submoule %s",
name);
} else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
; /* ok */
--
1.8.1.2.639.g9428735
^ permalink raw reply related [flat|nested] 11+ messages in thread