[PATCH v6 09/10] replace: check mergetags when using --graft

2014-07-07 Thread Christian Couder
When using --graft, with a mergetag in the original
commit, we should check that the commit pointed to by
the mergetag is still a parent of then new commit we
create, otherwise the mergetag could be misleading.

If the commit pointed to by the mergetag is no more
a parent of the new commit, we could remove the
mergetag, but in this case there is a good chance
that the title or other elements of the commit might
also be misleading. So let's just error out and
suggest to use --edit instead on the commit.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 builtin/replace.c | 47 +++
 1 file changed, 47 insertions(+)

diff --git a/builtin/replace.c b/builtin/replace.c
index cc29ef2..2290529 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -13,6 +13,7 @@
 #include refs.h
 #include parse-options.h
 #include run-command.h
+#include tag.h
 
 static const char * const git_replace_usage[] = {
N_(git replace [-f] object replacement),
@@ -325,6 +326,50 @@ static void replace_parents(struct strbuf *buf, int argc, 
const char **argv)
strbuf_release(new_parents);
 }
 
+struct check_mergetag_data {
+   int argc;
+   const char **argv;
+};
+
+static void check_one_mergetag(struct commit *commit,
+  struct commit_extra_header *extra,
+  void *data)
+{
+   struct check_mergetag_data *mergetag_data = (struct check_mergetag_data 
*)data;
+   const char *ref = mergetag_data-argv[0];
+   unsigned char tag_sha1[20];
+   struct tag *tag;
+   int i;
+
+   hash_sha1_file(extra-value, extra-len, typename(OBJ_TAG), tag_sha1);
+   tag = lookup_tag(tag_sha1);
+   if (!tag)
+   die(_(bad mergetag in commit '%s'), ref);
+   if (parse_tag_buffer(tag, extra-value, extra-len))
+   die(_(malformed mergetag in commit '%s'), ref);
+
+   /* iterate over new parents */
+   for (i = 1; i  mergetag_data-argc; i++) {
+   unsigned char sha1[20];
+   if (get_sha1(mergetag_data-argv[i], sha1)  0)
+   die(_(Not a valid object name: '%s'), 
mergetag_data-argv[i]);
+   if (!hashcmp(tag-tagged-sha1, sha1))
+   return; /* found */
+   }
+
+   die(_(original commit '%s' contains mergetag '%s' that is discarded; 
+ use --edit instead of --graft), ref, sha1_to_hex(tag_sha1));
+}
+
+static void check_mergetags(struct commit *commit, int argc, const char **argv)
+{
+   struct check_mergetag_data mergetag_data;
+
+   mergetag_data.argc = argc;
+   mergetag_data.argv = argv;
+   for_each_mergetag(check_one_mergetag, commit, mergetag_data);
+}
+
 static int create_graft(int argc, const char **argv, int force)
 {
unsigned char old[20], new[20];
@@ -349,6 +394,8 @@ static int create_graft(int argc, const char **argv, int 
force)
warning(_(the signature will be removed in the replacement 
commit!));
}
 
+   check_mergetags(commit, argc, argv);
+
if (write_sha1_file(buf.buf, buf.len, commit_type, new))
die(_(could not write replacement commit for: '%s'), old_ref);
 
-- 
2.0.0.421.g786a89d.dirty


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 09/10] replace: check mergetags when using --graft

2014-07-07 Thread Junio C Hamano
Christian Couder chrisc...@tuxfamily.org writes:

 When using --graft, with a mergetag in the original
 commit, we should check that the commit pointed to by
 the mergetag is still a parent of then new commit we
 create, otherwise the mergetag could be misleading.

 If the commit pointed to by the mergetag is no more
 a parent of the new commit, we could remove the
 mergetag, but in this case there is a good chance
 that the title or other elements of the commit might
 also be misleading. So let's just error out and
 suggest to use --edit instead on the commit.

I do not quite understand the reasoning.  If you have a merge you
earlier made with a signed tag, and then want to redo the merge with
an updated tip of that branch (perhaps the side branch was earlier
based on maint but now was rebased on master), it will perfectly be
normal to expect that the title or other elements of the resulting
merge to stay the same.  Why is it a good idea to error it out?

If the argument were 'replace --graft that changes the parents is
likely to affect merge summary message, so error out and suggest to
use --edit instead', regardless of the 'mergetag', I'd understand
it, but that would essentially mean that 'replace --graft' should
never be used, so...

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 09/10] replace: check mergetags when using --graft

2014-07-07 Thread Christian Couder
From: Junio C Hamano gits...@pobox.com

 Christian Couder chrisc...@tuxfamily.org writes:
 
 When using --graft, with a mergetag in the original
 commit, we should check that the commit pointed to by
 the mergetag is still a parent of then new commit we
 create, otherwise the mergetag could be misleading.

 If the commit pointed to by the mergetag is no more
 a parent of the new commit, we could remove the
 mergetag, but in this case there is a good chance
 that the title or other elements of the commit might
 also be misleading. So let's just error out and
 suggest to use --edit instead on the commit.
 
 I do not quite understand the reasoning.  If you have a merge you
 earlier made with a signed tag, and then want to redo the merge with
 an updated tip of that branch (perhaps the side branch was earlier
 based on maint but now was rebased on master), it will perfectly be
 normal to expect that the title or other elements of the resulting
 merge to stay the same.  

Yeah, but then you might also want to have a mergetag for the updated
tip of the branch and --graft will not put it in the new commit, so it
would be better to use --edit in this case.

 Why is it a good idea to error it out?

Because sometimes, in complex cases, it is misleading to do as if you
can do the right thing, when there is a good chance you cannot.

 If the argument were 'replace --graft that changes the parents is
 likely to affect merge summary message, so error out and suggest to
 use --edit instead', regardless of the 'mergetag', I'd understand
 it, but that would essentially mean that 'replace --graft' should
 never be used, so...

I think that when replace --graft is used on a regular commit there
is much better chance that the resulting replacement commit will be as
the user expect it to be.

Thanks,
Christian.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html