Rev 3708: (vila) Fix bug 233817 by adding an '--include-merges' option to bzr in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Fri Sep 12 15:21:11 BST 2008


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 3708
revision-id: pqm at pqm.ubuntu.com-20080912142101-kj49buaas8zsqf5x
parent: pqm at pqm.ubuntu.com-20080912135247-pyukwwmlmz79d61r
parent: v.ladeuil+lp at free.fr-20080912093943-57d3v5ubt5ajnfuo
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Fri 2008-09-12 15:21:01 +0100
message:
  (vila) Fix bug 233817 by adding an '--include-merges' option to bzr
  	missing
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
  bzrlib/missing.py              missing.py-20050812153334-097f7097e2a8bcd1
  bzrlib/tests/test_missing.py   test_missing.py-20051212000028-694fa4f658a81f48
    ------------------------------------------------------------
    revno: 3705.1.1
    revision-id: v.ladeuil+lp at free.fr-20080912093943-57d3v5ubt5ajnfuo
    parent: pqm at pqm.ubuntu.com-20080912075746-kg3w6klh2bufrjd6
    parent: v.ladeuil+lp at free.fr-20080912084407-wepmepg1fvbpqzly
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: trunk2
    timestamp: Fri 2008-09-12 11:39:43 +0200
    message:
      Fix bug 233817 by adding an '--include-merges' option to bzr missing
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
      bzrlib/missing.py              missing.py-20050812153334-097f7097e2a8bcd1
      bzrlib/tests/test_missing.py   test_missing.py-20051212000028-694fa4f658a81f48
    ------------------------------------------------------------
    revno: 3677.1.8
    revision-id: v.ladeuil+lp at free.fr-20080912084407-wepmepg1fvbpqzly
    parent: v.ladeuil+lp at free.fr-20080911193904-7qb81wbo10l4nbfs
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Fri 2008-09-12 10:44:07 +0200
    message:
      Fixed as per jam's review.
      
      * tests/test_missing.py:
      (TestMissing.assertUnmerged): Add the 'backward' parameter.
      (TestMissing.test_find_unmerged): Test 'backward' for mainline
      revisions.
      (TestFindUnmerged): Add the 'backward' parameter.
      (TestFindUnmerged.test_include_merges): Test 'backward' for merged
      revisions.
    modified:
      bzrlib/tests/test_missing.py   test_missing.py-20051212000028-694fa4f658a81f48
    ------------------------------------------------------------
    revno: 3677.1.7
    revision-id: v.ladeuil+lp at free.fr-20080911193904-7qb81wbo10l4nbfs
    parent: v.ladeuil+lp at free.fr-20080911193638-wtjyc1kcmacc6t1f
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Thu 2008-09-11 21:39:04 +0200
    message:
      Update NEWS.
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 3677.1.6
    revision-id: v.ladeuil+lp at free.fr-20080911193638-wtjyc1kcmacc6t1f
    parent: v.ladeuil+lp at free.fr-20080911193541-ihmjsp1azp1tq1o1
    parent: pqm at pqm.ubuntu.com-20080911061059-svzqfejar17ui4zw
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Thu 2008-09-11 21:36:38 +0200
    message:
      merge bzr.dev
    added:
      bzrlib/_readdir_py.py          readdir.py-20060609152855-rm6v321vuaqyh9tu-3
      bzrlib/_readdir_pyx.pyx        readdir.pyx-20060609152855-rm6v321vuaqyh9tu-1
      bzrlib/readdir.h               readdir.h-20060609152855-rm6v321vuaqyh9tu-2
      bzrlib/tests/test_transport_log.py test_transport_log.p-20080902041816-vh8x5yt5nvdzvew3-3
      bzrlib/transport/log.py        log.py-20080902041816-vh8x5yt5nvdzvew3-5
      doc/developers/overview.txt    overview.txt-20080904022501-ww2ggomrs5elxfm0-1
    renamed:
      bzrlib/tests/repository_implementations => bzrlib/tests/per_repository repository_implementations-20060131092037-ec97814745cc6128
    modified:
      .bzrignore                     bzrignore-20050311232317-81f7b71efa2db11a
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzr                            bzr.py-20050313053754-5485f144c7006fa6
      bzr.ico                        bzr.ico-20060629083000-q18ip0hk7lq55i4y-1
      bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
      bzrlib/_dirstate_helpers_c.pyx dirstate_helpers.pyx-20070503201057-u425eni465q4idwn-3
      bzrlib/_dirstate_helpers_py.py _dirstate_helpers_py-20070710145033-90nz6cqglsk150jy-1
      bzrlib/atomicfile.py           atomicfile.py-20050509044450-dbd24e6c564f7c66
      bzrlib/benchmarks/bench_osutils.py bench_osutils.py-20060608153714-apso8cyz1bu2z1ig-1
      bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
      bzrlib/btree_index.py          index.py-20080624222253-p0x5f92uyh5hw734-7
      bzrlib/bundle/bundle_data.py   read_changeset.py-20050619171944-c0d95aa685537640
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
      bzrlib/lockdir.py              lockdir.py-20060220222025-98258adf27fbdda3
      bzrlib/memorytree.py           memorytree.py-20060906023413-4wlkalbdpsxi2r4y-1
      bzrlib/merge.py                merge.py-20050513021216-953b65a438527106
      bzrlib/missing.py              missing.py-20050812153334-097f7097e2a8bcd1
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/push.py                 push.py-20080606021927-5fe39050e8xne9un-1
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/smart/message.py        message.py-20080222013625-ncqmh3nrxjkxab87-1
      bzrlib/smart/repository.py     repository.py-20061128022038-vr5wy5bubyb8xttk-1
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
      bzrlib/tests/blackbox/test_outside_wt.py test_outside_wt.py-20060116200058-98edd33e7db8bdde
      bzrlib/tests/branch_implementations/test_locking.py test_locking.py-20060707151933-tav3o2hpibwi53u4-4
      bzrlib/tests/bzrdir_implementations/test_bzrdir.py test_bzrdir.py-20060131065642-0ebeca5e30e30866
      bzrlib/tests/per_repository/__init__.py __init__.py-20060131092037-9564957a7d4a841b
      bzrlib/tests/per_repository/helpers.py helpers.py-20070924032407-m460yl9j5gu5ju85-2
      bzrlib/tests/per_repository/test__generate_text_key_index.py test__generate_text_-20071114232121-00h9fd8qg8kjfa5k-1
      bzrlib/tests/per_repository/test_add_fallback_repository.py test_add_fallback_re-20080215040003-8w9n4ck9uqdxj18m-1
      bzrlib/tests/per_repository/test_break_lock.py test_break_lock.py-20060504111704-ee09a107f9f42e43
      bzrlib/tests/per_repository/test_check.py test_check.py-20070824124512-38g4d135gcqxo4zb-1
      bzrlib/tests/per_repository/test_check_reconcile.py test_broken.py-20070928125406-62236394w0jpbpd6-2
      bzrlib/tests/per_repository/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
      bzrlib/tests/per_repository/test_fetch.py test_fetch.py-20070814052151-5cxha9slx4c93uog-1
      bzrlib/tests/per_repository/test_fileid_involved.py test_file_involved.py-20051215205901-728a172d1014daaa
      bzrlib/tests/per_repository/test_find_text_key_references.py test_find_text_key_r-20071114033605-v73bakal8x77qlfi-1
      bzrlib/tests/per_repository/test_get_parent_map.py test_get_parent_map.-20080421172708-x1z6ot341osr0jq1-1
      bzrlib/tests/per_repository/test_has_revisions.py test_has_revisions.p-20080111035443-xaupgdsx5fw1q54b-1
      bzrlib/tests/per_repository/test_has_same_location.py test_has_same_locati-20070807074648-2i2ah82fbe83iys7-1
      bzrlib/tests/per_repository/test_is_write_locked.py test_is_write_locked-20071012063748-vk062lmu683qgbc3-1
      bzrlib/tests/per_repository/test_iter_reverse_revision_history.py test_iter_reverse_re-20070217015036-spu7j5ggch7pbpyd-1
      bzrlib/tests/per_repository/test_pack.py test_pack.py-20070712120702-0c7585lh56p894mo-2
      bzrlib/tests/per_repository/test_reconcile.py test_reconcile.py-20060223022332-572ef70a3288e369
      bzrlib/tests/per_repository/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
      bzrlib/tests/per_repository/test_revision.py testrevprops.py-20051013073044-92bc3c68302ce1bf
      bzrlib/tests/per_repository/test_statistics.py test_statistics.py-20070203082432-6738e8fl0mm7ikre-1
      bzrlib/tests/per_repository/test_write_group.py test_write_group.py-20070716105516-89n34xtogq5frn0m-1
      bzrlib/tests/per_repository_reference/__init__.py __init__.py-20080220025549-nnm2s80it1lvcwnc-2
      bzrlib/tests/test__dirstate_helpers.py test_dirstate_helper-20070504035751-jsbn00xodv0y1eve-2
      bzrlib/tests/test_annotate.py  test_annotate.py-20061213215015-sttc9agsxomls7q0-1
      bzrlib/tests/test_btree_index.py test_index.py-20080624222253-p0x5f92uyh5hw734-13
      bzrlib/tests/test_bzrdir.py    test_bzrdir.py-20060131065654-deba40eef51cf220
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
      bzrlib/tests/test_dirstate.py  test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
      bzrlib/tests/test_errors.py    test_errors.py-20060210110251-41aba2deddf936a8
      bzrlib/tests/test_index.py     test_index.py-20070712131115-lolkarso50vjr64s-2
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
      bzrlib/tests/test_reconcile.py test_reconcile.py-20060225054842-50aa618584a86f26
      bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
      bzrlib/tests/test_revisiontree.py test_revisiontree.py-20060615095324-aij44ndxbv1h4c9f-1
      bzrlib/tests/test_selftest.py  test_selftest.py-20051202044319-c110a115d8c0456a
      bzrlib/tests/test_sftp_transport.py testsftp.py-20051027032739-247570325fec7e7e
      bzrlib/tests/test_transport.py testtransport.py-20050718175618-e5cdb99f4555ddce
      bzrlib/tests/test_transport_implementations.py test_transport_implementations.py-20051227111451-f97c5c7d5c49fce7
      bzrlib/tests/workingtree_implementations/test_parents.py test_set_parents.py-20060807231740-yicmnlci1mj8smu1-1
      bzrlib/tests/workingtree_implementations/test_workingtree.py test_workingtree.py-20060203003124-817757d3e31444fb
      bzrlib/transport/__init__.py   transport.py-20050711165921-4978aa7ce1285ad5
      bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
      bzrlib/transport/sftp.py       sftp.py-20051019050329-ab48ce71b7e32dfe
      bzrlib/transport/trace.py      trace.py-20070828055009-7kt0bbc4t4b92apz-1
      bzrlib/win32utils.py           win32console.py-20051021033308-123c6c929d04973d
      bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
      bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
      doc/developers/HACKING.txt     HACKING-20050805200004-2a5dc975d870f78c
      doc/developers/index.txt       index.txt-20070508041241-qznziunkg0nffhiw-1
      doc/en/user-guide/undoing_mistakes.txt undoing_mistakes.txt-20071121092300-8fyacngt1w98e5mp-1
      profile_imports.py             profile_imports.py-20060618020306-k5uw80achysrokj9-1
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
    ------------------------------------------------------------
    revno: 3677.1.5
    revision-id: v.ladeuil+lp at free.fr-20080911193541-ihmjsp1azp1tq1o1
    parent: v.ladeuil+lp at free.fr-20080911171346-f411nupzrv0iwerb
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Thu 2008-09-11 21:35:41 +0200
    message:
      Indent merge revisions correctly.
      
      * tests/test_missing.py:
      (TestFindUnmerged.test_include_merges): Update test.
      
      * missing.py:
      (iter_log_revisions): Work around wrong API while maintaining
      backward compatibility (this should be in log.py and hopefully
      will be soon).
    modified:
      bzrlib/missing.py              missing.py-20050812153334-097f7097e2a8bcd1
      bzrlib/tests/test_missing.py   test_missing.py-20051212000028-694fa4f658a81f48
    ------------------------------------------------------------
    revno: 3677.1.4
    revision-id: v.ladeuil+lp at free.fr-20080911171346-f411nupzrv0iwerb
    parent: v.ladeuil+lp at free.fr-20080910144915-ul6dhgtzd80ut9kb
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Thu 2008-09-11 19:13:46 +0200
    message:
      Replace 'reverse' by 'backward' when talking about revision order.
      
      * tests/test_missing.py:
      (TestMissing.assertUnmerged): Use default value for order.
      (TestFindUnmerged.test_include_merges): Respect default order to
      keep all related tests coherent.
      
      * builtins.py:
      (cmd_missing.run): Reverse means forward.
      
      * missing.py:
      (find_unmerged, _enumerate_mainline, _enumerate_with_merges):
      Revert the 'reverse' parameter addition, renaming it
      'backward'. 'reverse' is too confusing, just re-read the previous
      sentence if you disagree (and I put quotes to help the reader...).
      
      * log.py:
      (get_view_revisions): Revert noisy cleanup.
    modified:
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
      bzrlib/missing.py              missing.py-20050812153334-097f7097e2a8bcd1
      bzrlib/tests/test_missing.py   test_missing.py-20051212000028-694fa4f658a81f48
    ------------------------------------------------------------
    revno: 3677.1.3
    revision-id: v.ladeuil+lp at free.fr-20080910144915-ul6dhgtzd80ut9kb
    parent: v.ladeuil+lp at free.fr-20080909160741-h6i2u5l3ntfq2ntr
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Wed 2008-09-10 16:49:15 +0200
    message:
      Fix incorrect revnos based on jam's feedback.
      
      * missing.py:
      (_enumerate_with_merges): We need full history to get correct
      revnos, let's do that :-( A 'branch' parameter is now needed.
    modified:
      bzrlib/missing.py              missing.py-20050812153334-097f7097e2a8bcd1
    ------------------------------------------------------------
    revno: 3677.1.2
    revision-id: v.ladeuil+lp at free.fr-20080909160741-h6i2u5l3ntfq2ntr
    parent: v.ladeuil+lp at free.fr-20080903163327-hpgcpvx2ziit96og
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Tue 2008-09-09 18:07:41 +0200
    message:
      Fix tests broken by previous commit.
      
      * tests/test_missing.py:
      (TestMissing.test_iter_log_revisions, TestMissing.assertUnmerged):
      Oops, we need 'reverse=True' when calling missing.find_unmerged
      since the previous commit made it False by default.
    modified:
      bzrlib/tests/test_missing.py   test_missing.py-20051212000028-694fa4f658a81f48
    ------------------------------------------------------------
    revno: 3677.1.1
    revision-id: v.ladeuil+lp at free.fr-20080903163327-hpgcpvx2ziit96og
    parent: pqm at pqm.ubuntu.com-20080902062416-dxdxccqki90bcynl
    committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
    branch nick: 233817-missing
    timestamp: Wed 2008-09-03 18:33:27 +0200
    message:
      Begin fixing bug #233817.
      
      * tests/test_missing.py:
      revnos returned by fin_unmerged are strings, update tests.
      (TestFindUnmerged.test_include_merges): Check that we get the
      merged revisions too.
      
      * missing.py:
      (find_unmerged): Add 'reverse' and 'include_merges' parameters.
      (_enumerate_mainline): Add reverse parameter so that we reverse
      the mainline revision list only when needed.
      (_enumerate_with_merges): When including merges, building the
      revision list is a bit more work.
      (_find_unmerged): Build the revision list depending on
      include_merges.
      
      * log.py:
      (LineLogFormatter.log_string): Fix doc string, the revno may be a
      string.
      
      * builtins.py:
      (cmd_missing): Add an '--include-merges' option. Let fin_unmerged
      handles the ordering.
    modified:
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
      bzrlib/missing.py              missing.py-20050812153334-097f7097e2a8bcd1
      bzrlib/tests/test_missing.py   test_missing.py-20051212000028-694fa4f658a81f48
=== modified file 'NEWS'
--- a/NEWS	2008-09-12 08:02:18 +0000
+++ b/NEWS	2008-09-12 14:21:01 +0000
@@ -15,6 +15,9 @@
 
   BUG FIXES:
 
+    * ``bzr missing`` now accepts an ``--include-merges`` option.
+      (Vincent Ladeuil, #233817)
+
     * Fix '_in_buffer' AttributeError when using the -Dhpss debug flag.
       (Andrew Bennetts)
 

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2008-09-01 23:49:18 +0000
+++ b/bzrlib/builtins.py	2008-09-11 17:13:46 +0000
@@ -3318,14 +3318,17 @@
             Option('other', 'Same as --theirs-only.'),
             'log-format',
             'show-ids',
-            'verbose'
+            'verbose',
+            Option('include-merges', 'Show merged revisions.'),
             ]
     encoding_type = 'replace'
 
     @display_command
     def run(self, other_branch=None, reverse=False, mine_only=False,
-            theirs_only=False, log_format=None, long=False, short=False, line=False, 
-            show_ids=False, verbose=False, this=False, other=False):
+            theirs_only=False,
+            log_format=None, long=False, short=False, line=False,
+            show_ids=False, verbose=False, this=False, other=False,
+            include_merges=False):
         from bzrlib.missing import find_unmerged, iter_log_revisions
 
         if this:
@@ -3361,7 +3364,9 @@
             remote_branch.lock_read()
             try:
                 local_extra, remote_extra = find_unmerged(
-                    local_branch, remote_branch, restrict)
+                    local_branch, remote_branch, restrict,
+                    backward=not reverse,
+                    include_merges=include_merges)
 
                 if log_format is None:
                     registry = log.log_formatter_registry
@@ -3369,11 +3374,6 @@
                 lf = log_format(to_file=self.outf,
                                 show_ids=show_ids,
                                 show_timezone='original')
-                if reverse is False:
-                    if local_extra is not None:
-                        local_extra.reverse()
-                    if remote_extra is not None:
-                        remote_extra.reverse()
 
                 status_code = 0
                 if local_extra and not theirs_only:

=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py	2008-09-01 00:56:53 +0000
+++ b/bzrlib/log.py	2008-09-11 17:13:46 +0000
@@ -865,7 +865,7 @@
 
     def log_string(self, revno, rev, max_chars):
         """Format log info into one string. Truncate tail of string
-        :param  revno:      revision number (int) or None.
+        :param  revno:      revision number or None.
                             Revision numbers counts from 1.
         :param  rev:        revision info object
         :param  max_chars:  maximum length of resulting string

=== modified file 'bzrlib/missing.py'
--- a/bzrlib/missing.py	2008-09-01 14:03:34 +0000
+++ b/bzrlib/missing.py	2008-09-11 19:36:38 +0000
@@ -16,8 +16,10 @@
 
 """Display what revisions are missing in 'other' from 'this' and vice versa."""
 
-from bzrlib.log import (
-    LogRevision,
+from bzrlib import (
+    log,
+    repository as _mod_repository,
+    tsort,
     )
 import bzrlib.revision as _mod_revision
 
@@ -25,7 +27,14 @@
 def iter_log_revisions(revisions, revision_source, verbose):
     last_tree = revision_source.revision_tree(_mod_revision.NULL_REVISION)
     last_rev_id = None
-    for revno, rev_id in revisions:
+    for rev in revisions:
+        # We need the following for backward compatibilty (hopefully
+        # this will be deprecated soon :-/) -- vila 080911
+        if len(rev) == 2:
+            revno, rev_id = rev
+            merge_depth = 0
+        else:
+            revno, rev_id, merge_depth = rev
         rev = revision_source.get_revision(rev_id)
         if verbose:
             remote_tree = revision_source.revision_tree(rev_id)
@@ -40,10 +49,11 @@
             delta = revision_tree.changes_from(parent_tree)
         else:
             delta = None
-        yield LogRevision(rev, revno, delta=delta)
-
-
-def find_unmerged(local_branch, remote_branch, restrict='all'):
+        yield log.LogRevision(rev, revno, merge_depth, delta=delta)
+
+
+def find_unmerged(local_branch, remote_branch, restrict='all',
+                  include_merges=False, backward=False):
     """Find revisions from each side that have not been merged.
 
     :param local_branch: Compare the history of local_branch
@@ -53,6 +63,10 @@
         unique revisions from both sides. If 'local', we will return None
         for the remote revisions, similarly if 'remote' we will return None for
         the local revisions.
+    :param include_merges: Show mainline revisions only if False,
+        all revisions otherwise.
+    :param backward: Show oldest versions first when True, newest versions
+        first when False. 
 
     :return: A list of [(revno, revision_id)] for the mainline revisions on
         each side.
@@ -61,21 +75,24 @@
     try:
         remote_branch.lock_read()
         try:
-            return _find_unmerged(local_branch,
-                remote_branch, restrict=restrict)
+            return _find_unmerged(
+                local_branch, remote_branch, restrict=restrict,
+                include_merges=include_merges, backward=backward)
         finally:
             remote_branch.unlock()
     finally:
         local_branch.unlock()
 
 
-def _enumerate_mainline(ancestry, graph, tip_revno, tip):
+def _enumerate_mainline(ancestry, graph, tip_revno, tip, backward=True):
     """Enumerate the mainline revisions for these revisions.
 
     :param ancestry: A set of revisions that we care about
     :param graph: A Graph which lets us find the parents for a revision
     :param tip_revno: The revision number for the tip revision
     :param tip: The tip of mainline
+    :param backward: Show oldest versions first when True, newest versions
+        first when False. 
     :return: [(revno, revision_id)] for all revisions in ancestry that
         are left-hand parents from tip, or None if ancestry is None.
     """
@@ -96,14 +113,69 @@
         parents = parent_map.get(cur)
         if not parents:
             break # Ghost, we are done
-        mainline.append((cur_revno, cur))
+        mainline.append((str(cur_revno), cur))
         cur = parents[0]
         cur_revno -= 1
-    mainline.reverse()
+    if not backward:
+        mainline.reverse()
     return mainline
 
 
-def _find_unmerged(local_branch, remote_branch, restrict):
+def _enumerate_with_merges(branch, ancestry, graph, tip_revno, tip,
+                           backward=True):
+    """Enumerate the revisions for the ancestry.
+
+    :param branch: The branch we care about
+    :param ancestry: A set of revisions that we care about
+    :param graph: A Graph which lets us find the parents for a revision
+    :param tip_revno: The revision number for the tip revision
+    :param tip: The tip of the ancsetry
+    :param backward: Show oldest versions first when True, newest versions
+        first when False. 
+    :return: [(revno, revision_id)] for all revisions in ancestry that
+        are parents from tip, or None if ancestry is None.
+    """
+    if ancestry is None:
+        return None
+    if not ancestry: #Empty ancestry, no need to do any work
+        return []
+
+    mainline_revs, rev_nos, start_rev_id, end_rev_id = log._get_mainline_revs(
+        branch, None, tip_revno)
+    if not mainline_revs:
+        return []
+
+    # This asks for all mainline revisions, which is size-of-history and
+    # should be addressed (but currently the only way to get correct
+    # revnos).
+
+    # mainline_revisions always includes an extra revision at the
+    # beginning, so don't request it.
+    parent_map = dict(((key, value) for key, value
+                       in graph.iter_ancestry(mainline_revs[1:])
+                       if value is not None))
+    # filter out ghosts; merge_sort errors on ghosts. 
+    # XXX: is this needed here ? -- vila080910
+    rev_graph = _mod_repository._strip_NULL_ghosts(parent_map)
+    # XXX: what if rev_graph is empty now ? -- vila080910
+    merge_sorted_revisions = tsort.merge_sort(rev_graph, tip,
+                                              mainline_revs,
+                                              generate_revno=True)
+    # Now that we got the correct revnos, keep only the relevant
+    # revisions.
+    merge_sorted_revisions = [
+        (s, revid, n, d, e) for s, revid, n, d, e in merge_sorted_revisions
+        if revid in ancestry]
+    if not backward:
+        merge_sorted_revisions = log.reverse_by_depth(merge_sorted_revisions)
+    revline = []
+    for seq, rev_id, merge_depth, revno, end_of_merge in merge_sorted_revisions:
+        revline.append(('.'.join(map(str, revno)), rev_id, merge_depth))
+    return revline
+
+
+def _find_unmerged(local_branch, remote_branch, restrict,
+                   include_merges, backward):
     """See find_unmerged.
 
     The branches should already be locked before entering.
@@ -113,29 +185,36 @@
     if local_revno == remote_revno and local_revision_id == remote_revision_id:
         # A simple shortcut when the tips are at the same point
         return [], []
-    graph = local_branch.repository.get_graph(
-                remote_branch.repository)
+    graph = local_branch.repository.get_graph(remote_branch.repository)
     if restrict == 'remote':
         local_extra = None
-        remote_extra = graph.find_unique_ancestors(
-            remote_revision_id, [local_revision_id])
+        remote_extra = graph.find_unique_ancestors(remote_revision_id,
+                                                   [local_revision_id])
     elif restrict == 'local':
         remote_extra = None
-        local_extra = graph.find_unique_ancestors(
-            local_revision_id, [remote_revision_id])
+        local_extra = graph.find_unique_ancestors(local_revision_id,
+                                                  [remote_revision_id])
     else:
         if restrict != 'all':
             raise ValueError('param restrict not one of "all", "local",'
                              ' "remote": %r' % (restrict,))
-        local_extra, remote_extra = graph.find_difference(
-            local_revision_id, remote_revision_id)
-    # Now that we have unique ancestors, compute just the mainline, and
-    # generate revnos for them.
-    local_mainline = _enumerate_mainline(local_extra, graph, local_revno,
-                                         local_revision_id)
-    remote_mainline = _enumerate_mainline(remote_extra, graph, remote_revno,
-                                          remote_revision_id)
-    return local_mainline, remote_mainline
+        local_extra, remote_extra = graph.find_difference(local_revision_id,
+                                                          remote_revision_id)
+    if include_merges:
+        locals = _enumerate_with_merges(local_branch, local_extra,
+                                        graph, local_revno,
+                                        local_revision_id, backward)
+        remotes = _enumerate_with_merges(remote_branch, remote_extra,
+                                         graph, remote_revno,
+                                         remote_revision_id, backward)
+    else:
+        # Now that we have unique ancestors, compute just the mainline, and
+        # generate revnos for them.
+        locals = _enumerate_mainline(local_extra, graph, local_revno,
+                                     local_revision_id, backward)
+        remotes = _enumerate_mainline(remote_extra, graph, remote_revno,
+                                      remote_revision_id, backward)
+    return locals, remotes
 
 
 def sorted_revisions(revisions, history_map):

=== modified file 'bzrlib/tests/test_missing.py'
--- a/bzrlib/tests/test_missing.py	2008-05-19 21:35:52 +0000
+++ b/bzrlib/tests/test_missing.py	2008-09-12 08:44:07 +0000
@@ -30,10 +30,12 @@
 
 class TestMissing(TestCaseWithTransport):
 
-    def assertUnmerged(self, expected, source, target, restrict='all'):
-        unmerged = missing.find_unmerged(source, target, restrict=restrict)
+    def assertUnmerged(self, expected, source, target, restrict='all',
+                       backward=False):
+        unmerged = missing.find_unmerged(source, target, restrict=restrict,
+                                         backward=backward)
         self.assertEqual(expected, unmerged)
-            
+
     def test_find_unmerged(self):
         original_tree = self.make_branch_and_tree('original')
         original = original_tree.branch
@@ -43,24 +45,26 @@
         merger = merger_tree.branch
         self.assertUnmerged(([], []), original, puller)
         original_tree.commit('a', rev_id='a')
-        self.assertUnmerged(([(1, 'a')], []), original, puller)
+        self.assertUnmerged(([('1', 'a')], []), original, puller)
         puller_tree.pull(original)
         self.assertUnmerged(([], []), original, puller)
         merger_tree.pull(original)
         original_tree.commit('b', rev_id='b')
         original_tree.commit('c', rev_id='c')
-        self.assertUnmerged(([(2, 'b'), (3, 'c')], []),
+        self.assertUnmerged(([('2', 'b'), ('3', 'c')], []),
                             original, puller)
+        self.assertUnmerged(([('3', 'c'), ('2', 'b')], []),
+                            original, puller, backward=True)
 
         puller_tree.pull(original)
         self.assertUnmerged(([], []), original, puller)
-        self.assertUnmerged(([(2, 'b'), (3, 'c')], []),
+        self.assertUnmerged(([('2', 'b'), ('3', 'c')], []),
                             original, merger)
         merger_tree.merge_from_branch(original)
-        self.assertUnmerged(([(2, 'b'), (3, 'c')], []),
+        self.assertUnmerged(([('2', 'b'), ('3', 'c')], []),
                             original, merger)
         merger_tree.commit('d', rev_id='d')
-        self.assertUnmerged(([], [(2, 'd')]), original, merger)
+        self.assertUnmerged(([], [('2', 'd')]), original, merger)
 
     def test_iter_log_revisions(self):
         base_tree = self.make_branch_and_tree('base')
@@ -85,7 +89,7 @@
 
         base_extra, child_extra = missing.find_unmerged(base_tree.branch,
                                                         child_tree.branch)
-        results = list(iter_log_revisions(base_extra, 
+        results = list(iter_log_revisions(base_extra,
                             base_tree.branch.repository,
                             verbose=True))
         self.assertEqual([], results)
@@ -97,10 +101,9 @@
 
         r0,r1,r2,r3 = results
 
-        self.assertEqual((2, 'c-2'), (r0.revno, r0.rev.revision_id))
-        self.assertEqual((3, 'c-3'), (r1.revno, r1.rev.revision_id))
-        self.assertEqual((4, 'c-4'), (r2.revno, r2.rev.revision_id))
-        self.assertEqual((5, 'c-5'), (r3.revno, r3.rev.revision_id))
+        self.assertEqual([('2', 'c-2'), ('3', 'c-3'),
+                          ('4', 'c-4'), ('5', 'c-5'),],
+                         [(r.revno, r.rev.revision_id) for r in results])
 
         delta0 = r0.delta
         self.assertNotEqual(None, delta0)
@@ -135,10 +138,13 @@
 class TestFindUnmerged(tests.TestCaseWithTransport):
 
     def assertUnmerged(self, local, remote, local_branch, remote_branch,
-                       restrict):
+                       restrict, include_merges=False,
+                       backward=False):
         """Check the output of find_unmerged_mainline_revisions"""
         local_extra, remote_extra = missing.find_unmerged(
-                                        local_branch, remote_branch, restrict)
+                                        local_branch, remote_branch, restrict,
+                                        include_merges=include_merges,
+                                        backward=backward)
         self.assertEqual(local, local_extra)
         self.assertEqual(remote, remote_extra)
 
@@ -154,25 +160,17 @@
         rev1 = tree.commit('one')
         tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
         rev2 = tree2.commit('two')
-        tree.lock_read()
-        self.addCleanup(tree.unlock)
-        tree2.lock_read()
-        self.addCleanup(tree2.unlock)
-        self.assertUnmerged([], [(2, rev2)], tree.branch, tree2.branch, 'all')
-        self.assertUnmerged([(2, rev2)], [], tree2.branch, tree.branch, 'all')
+        self.assertUnmerged([], [('2', rev2)], tree.branch, tree2.branch, 'all')
+        self.assertUnmerged([('2', rev2)], [], tree2.branch, tree.branch, 'all')
 
     def test_restrict(self):
         tree = self.make_branch_and_tree('tree')
         rev1 = tree.commit('one')
         tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
         rev2 = tree2.commit('two')
-        tree.lock_read()
-        self.addCleanup(tree.unlock)
-        tree2.lock_read()
-        self.addCleanup(tree2.unlock)
-        self.assertUnmerged([], [(2, rev2)], tree.branch, tree2.branch, 'all')
+        self.assertUnmerged([], [('2', rev2)], tree.branch, tree2.branch, 'all')
         self.assertUnmerged([], None, tree.branch, tree2.branch, 'local')
-        self.assertUnmerged(None, [(2, rev2)], tree.branch, tree2.branch,
+        self.assertUnmerged(None, [('2', rev2)], tree.branch, tree2.branch,
                                                'remote')
 
     def test_merged(self):
@@ -184,9 +182,34 @@
         tree.merge_from_branch(tree2.branch)
         rev4 = tree.commit('four')
 
-        tree.lock_read()
-        self.addCleanup(tree.unlock)
-        tree2.lock_read()
-        self.addCleanup(tree2.unlock)
-
-        self.assertUnmerged([(2, rev4)], [], tree.branch, tree2.branch, 'all')
+        self.assertUnmerged([('2', rev4)], [], tree.branch, tree2.branch, 'all')
+
+    def test_include_merges(self):
+        tree = self.make_branch_and_tree('tree')
+        rev1 = tree.commit('one', rev_id='rev1')
+
+        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
+        rev2 = tree2.commit('two', rev_id='rev2')
+        rev3 = tree2.commit('three', rev_id='rev3')
+
+        tree3 = tree2.bzrdir.sprout('tree3').open_workingtree()
+        rev4 = tree3.commit('four', rev_id='rev4')
+        rev5 = tree3.commit('five', rev_id='rev5')
+
+        tree2.merge_from_branch(tree3.branch)
+        rev6 = tree2.commit('six', rev_id='rev6')
+
+        self.assertUnmerged([], [('2', 'rev2', 0), ('3', 'rev3',0 ),
+                                 ('4', 'rev6', 0),
+                                 ('3.1.1', 'rev4', 1), ('3.1.2', 'rev5', 1),
+                                 ],
+                            tree.branch, tree2.branch, 'all',
+                            include_merges=True)
+
+        self.assertUnmerged([], [('4', 'rev6', 0),
+                                 ('3.1.2', 'rev5', 1), ('3.1.1', 'rev4', 1),
+                                 ('3', 'rev3',0 ), ('2', 'rev2', 0),
+                                 ],
+                            tree.branch, tree2.branch, 'all',
+                            include_merges=True,
+                            backward=True)




More information about the bazaar-commits mailing list