fast-export: don't handle uninteresting refs
authorFelipe Contreras <felipe.contreras@gmail.com>
Wed, 28 Nov 2012 22:23:59 +0000 (23:23 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 3 Dec 2012 17:52:08 +0000 (09:52 -0800)
They have been marked as UNINTERESTING for a reason, lets respect
that.  Currently the first ref is handled properly, but not the
rest.  Assuming that all the refs point at the same commit in the
following example:

  % git fast-export master ^uninteresting ^foo ^bar
  reset refs/heads/bar
  from :0

  reset refs/heads/foo
  from :0

  reset refs/heads/uninteresting
  from :0

  % git fast-export ^uninteresting ^foo ^bar master
  reset refs/heads/master
  from :0

  reset refs/heads/bar
  from :0

  reset refs/heads/foo
  from :0

Clearly this is wrong; the negative refs should be ignored.

After this patch:

  % git fast-export ^uninteresting ^foo ^bar master
  # nothing
  % git fast-export master ^uninteresting ^foo ^bar
  # nothing

And even more, it would only happen if the ref is pointing to exactly
the same commit, but not otherwise:

 % git fast-export ^next next
 reset refs/heads/next
 from :0

 % git fast-export ^next next^{commit}
 # nothing
 % git fast-export ^next next~0
 # nothing
 % git fast-export ^next next~1
 # nothing
 % git fast-export ^next next~2
 # nothing

The reason this happens is that before traversing the commits,
fast-export checks if any of the refs point to the same object, and any
duplicated ref gets added to a list in order to issue 'reset' commands
after the traversing. Unfortunately, it's not even checking if the
commit is flagged as UNINTERESTING. The fix of course, is to check it.

However, in order to do it properly we need to get the UNINTERESTING
flag from the command line, not from the commit object, because
"^foo bar" will mark the commit 'bar' uninteresting if foo and bar
points at the same commit.  rev_cmdline_info, which was introduced
exactly to handle this situation, contains all the information we
need for get_tags_and_duplicates(), plus the ref flag. This way the
rest of the positive refs will remain untouched; it's only the
negative ones that change in behavior.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fast-export.c
t/t5801-remote-helpers.sh
t/t9350-fast-export.sh

index 191936c179bcf9c6657453a7415feb9e1f8d5b30..2547e6cb52d8301568e6e1ea71c9e403a82f13a0 100644 (file)
@@ -474,18 +474,21 @@ static void handle_tag(const char *name, struct tag *tag)
               (int)message_size, (int)message_size, message ? message : "");
 }
 
-static void get_tags_and_duplicates(struct object_array *pending,
+static void get_tags_and_duplicates(struct rev_cmdline_info *info,
                                    struct string_list *extra_refs)
 {
        struct tag *tag;
        int i;
 
-       for (i = 0; i < pending->nr; i++) {
-               struct object_array_entry *e = pending->objects + i;
+       for (i = 0; i < info->nr; i++) {
+               struct rev_cmdline_entry *e = info->rev + i;
                unsigned char sha1[20];
                struct commit *commit;
                char *full_name;
 
+               if (e->flags & UNINTERESTING)
+                       continue;
+
                if (dwim_ref(e->name, strlen(e->name), sha1, &full_name) != 1)
                        continue;
 
@@ -681,7 +684,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
        if (import_filename && revs.prune_data.nr)
                full_tree = 1;
 
-       get_tags_and_duplicates(&revs.pending, &extra_refs);
+       get_tags_and_duplicates(&revs.cmdline, &extra_refs);
 
        if (prepare_revision_walk(&revs))
                die("revision walk setup failed");
index 12ae2566408a07ee4d56a49908ad5d5751b460de..ece8fd5ab8523b087cbcd032100fda68a085adf1 100755 (executable)
@@ -162,4 +162,12 @@ test_expect_failure 'pushing without marks' '
        compare_refs local2 HEAD server HEAD
 '
 
+test_expect_success 'push all with existing object' '
+       (cd local &&
+       git branch dup2 master &&
+       git push origin --all
+       ) &&
+       compare_refs local dup2 server dup2
+'
+
 test_done
index 1f598622a66f747a39f8750cce7efed72af698df..c8e41c1d42b5a5be84fad5508c71d33885962a51 100755 (executable)
@@ -454,4 +454,34 @@ test_expect_success 'test bidirectionality' '
        git fast-import --export-marks=marks-cur --import-marks=marks-cur
 '
 
+cat > expected << EOF
+blob
+mark :13
+data 5
+bump
+
+commit refs/heads/master
+mark :14
+author A U Thor <author@example.com> 1112912773 -0700
+committer C O Mitter <committer@example.com> 1112912773 -0700
+data 5
+bump
+from :12
+M 100644 :13 file
+
+EOF
+
+test_expect_success 'avoid uninteresting refs' '
+       > tmp-marks &&
+       git fast-export --import-marks=tmp-marks \
+               --export-marks=tmp-marks master > /dev/null &&
+       git tag v1.0 &&
+       git branch uninteresting &&
+       echo bump > file &&
+       git commit -a -m bump &&
+       git fast-export --import-marks=tmp-marks \
+               --export-marks=tmp-marks ^uninteresting ^v1.0 master > actual &&
+       test_cmp expected actual
+'
+
 test_done