Rev 3119: diff on branches without working trees (Ian Clatworthy, #6700) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Mon Dec 17 03:47:04 GMT 2007


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

------------------------------------------------------------
revno: 3119
revision-id:pqm at pqm.ubuntu.com-20071217034652-jime7u7tuudfvy18
parent: pqm at pqm.ubuntu.com-20071215210020-m28kk1qmbcc9n6qs
parent: ian.clatworthy at internode.on.net-20071217024823-4u1b49p5ls91c39e
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2007-12-17 03:46:52 +0000
message:
  diff on branches without working trees (Ian Clatworthy, #6700)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
  bzrlib/tests/blackbox/test_diff.py test_diff.py-20060110203741-aa99ac93e633d971
  bzrlib/tests/blackbox/test_outside_wt.py test_outside_wt.py-20060116200058-98edd33e7db8bdde
    ------------------------------------------------------------
    revno: 3118.1.2
    revision-id:ian.clatworthy at internode.on.net-20071217024823-4u1b49p5ls91c39e
    parent: ian.clatworthy at internode.on.net-20071217004025-2w84tony0wqaemvf
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: ianc-integration
    timestamp: Mon 2007-12-17 12:48:23 +1000
    message:
      diff on branches without working trees (Ian Clatworthy, #6700)
    modified:
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
    ------------------------------------------------------------
    revno: 3118.1.1
    revision-id:ian.clatworthy at internode.on.net-20071217004025-2w84tony0wqaemvf
    parent: pqm at pqm.ubuntu.com-20071215210020-m28kk1qmbcc9n6qs
    parent: ian.clatworthy at internode.on.net-20071217002228-o1kx14mbls2btbft
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: ianc-integration
    timestamp: Mon 2007-12-17 10:40:25 +1000
    message:
      diff on branches without working trees (Ian Clatworthy, #6700)
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tests/blackbox/test_diff.py test_diff.py-20060110203741-aa99ac93e633d971
      bzrlib/tests/blackbox/test_outside_wt.py test_outside_wt.py-20060116200058-98edd33e7db8bdde
    ------------------------------------------------------------
    revno: 3072.1.7
    revision-id:ian.clatworthy at internode.on.net-20071217002228-o1kx14mbls2btbft
    parent: ian.clatworthy at internode.on.net-20071212071439-vqrvm1lm8vjw5br0
    parent: pqm at pqm.ubuntu.com-20071215210020-m28kk1qmbcc9n6qs
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.diff-no-wt
    timestamp: Mon 2007-12-17 10:22:28 +1000
    message:
      merge bzr.dev
    removed:
      doc/en/user-reference/index.txt index.txt-20070830033353-ud9e03xsh24053oo-1
    added:
      doc/en/quick-reference/quick-start-summary.pdf quickstartsummary.pd-20071207005239-it6xmdjml8nxvzgt-1
      doc/en/quick-reference/quick-start-summary.png quickstartsummary.pn-20071203142852-hsiybkmh37q5owwe-1
      doc/en/user-guide/adv_merging.txt adv_merging.txt-20071213070245-d7u7150lb2hhnvby-1
      index.txt                      index.txt-20071121073725-0corxykv5irjal00-1
    modified:
      Makefile                       Makefile-20050805140406-d96e3498bb61c5bb
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      README                         README-20050309040720-8f368abf9f346b9d
      bzr                            bzr.py-20050313053754-5485f144c7006fa6
      bzrlib/__init__.py             __init__.py-20050309040759-33e65acf91bbcd5d
      bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
      bzrlib/bugtracker.py           bugtracker.py-20070410073305-vu1vu1qosjurg8kb-1
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/config.py               config.py-20051011043216-070c74f4e9e338e8
      bzrlib/debug.py                debug.py-20061102062349-vdhrw9qdpck8cl35-1
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/graph.py                graph_walker.py-20070525030359-y852guab65d4wtn0-1
      bzrlib/help_topics.py          help_topics.py-20060920210027-rnim90q9e0bwxvy4-1
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
      bzrlib/merge.py                merge.py-20050513021216-953b65a438527106
      bzrlib/merge_directive.py      merge_directive.py-20070228184838-ja62280spt1g7f4x-1
      bzrlib/plugins/launchpad/lp_indirect.py lp_indirect.py-20070126012204-de5rugwlt22c7u7e-1
      bzrlib/plugins/launchpad/test_lp_indirect.py test_lp_indirect.py-20070126002743-oyle362tzv9cd8mi-1
      bzrlib/reconfigure.py          reconfigure.py-20070908040425-6ykgo7escxhyrg9p-1
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/switch.py               switch.py-20071116011000-v5lnw7d2wkng9eux-1
      bzrlib/tests/HttpServer.py     httpserver.py-20061012142527-m1yxdj1xazsf8d7s-1
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/blackbox/test_bound_branches.py test_bound_branches.py-20051109215527-2373188ad566c205
      bzrlib/tests/blackbox/test_cat.py test_cat.py-20051201162916-f0937e4e19ea24b3
      bzrlib/tests/blackbox/test_commit.py test_commit.py-20060212094538-ae88fc861d969db0
      bzrlib/tests/blackbox/test_exceptions.py test_exceptions.py-20060604211237-yi2cxg0ose3xk4id-1
      bzrlib/tests/blackbox/test_info.py test_info.py-20060215045507-bbdd2d34efab9e0a
      bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
      bzrlib/tests/blackbox/test_merge.py test_merge.py-20060323225809-9bc0459c19917f41
      bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
      bzrlib/tests/blackbox/test_send.py test_bundle.py-20060616222707-c21c8b7ea5ef57b1
      bzrlib/tests/blackbox/test_uncommit.py test_uncommit.py-20051027212835-84944b63adae51be
      bzrlib/tests/branch_implementations/test_branch.py testbranch.py-20050711070244-121d632bc37d7253
      bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
      bzrlib/tests/test_bugtracker.py test_bugtracker.py-20070410073305-vu1vu1qosjurg8kb-2
      bzrlib/tests/test_config.py    testconfig.py-20051011041908-742d0c15d8d8c8eb
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
      bzrlib/tests/test_errors.py    test_errors.py-20060210110251-41aba2deddf936a8
      bzrlib/tests/test_graph.py     test_graph_walker.py-20070525030405-enq4r60hhi9xrujc-1
      bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
      bzrlib/tests/test_http_response.py test_http_response.py-20060628233143-950b2a482a32505d
      bzrlib/tests/test_log.py       testlog.py-20050728115707-1a514809d7d49309
      bzrlib/tests/test_merge.py     testmerge.py-20050905070950-c1b5aa49ff911024
      bzrlib/tests/test_merge_directive.py test_merge_directive-20070228184838-ja62280spt1g7f4x-2
      bzrlib/tests/test_msgeditor.py test_msgeditor.py-20051202041359-920315ec6011ee51
      bzrlib/tests/test_reconfigure.py test_reconfigure.py-20070908040425-6ykgo7escxhyrg9p-2
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
      bzrlib/tests/test_revision.py  testrevision.py-20050804210559-46f5e1eb67b01289
      bzrlib/tests/test_switch.py    test_switch.py-20071116011000-v5lnw7d2wkng9eux-2
      bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
      bzrlib/tests/test_transport.py testtransport.py-20050718175618-e5cdb99f4555ddce
      bzrlib/tests/test_transport_implementations.py test_transport_implementations.py-20051227111451-f97c5c7d5c49fce7
      bzrlib/tests/test_versionedfile.py test_versionedfile.py-20060222045249-db45c9ed14a1c2e5
      bzrlib/trace.py                trace.py-20050309040759-c8ed824bdcd4748a
      bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
      bzrlib/transport/__init__.py   transport.py-20050711165921-4978aa7ce1285ad5
      bzrlib/transport/http/__init__.py http_transport.py-20050711212304-506c5fd1059ace96
      bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
      bzrlib/transport/http/_urllib.py _urlgrabber.py-20060113083826-0bbf7d992fbf090c
      bzrlib/transport/http/_urllib2_wrappers.py _urllib2_wrappers.py-20060913231729-ha9ugi48ktx481ao-1
      bzrlib/transport/http/response.py _response.py-20060613154423-a2ci7hd4iw5c7fnt-1
      bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
      bzrlib/versionedfile.py        versionedfile.py-20060222045106-5039c71ee3b65490
      doc/developers/bundles.txt     bundles.txt-20070621030528-qkjnugd7iyud6ow3-1
      doc/developers/index.txt       index.txt-20070508041241-qznziunkg0nffhiw-1
      doc/developers/packrepo.txt    knitpack.txt-20071023074744-q0g5u8me8gk5zbtb-1
      doc/en/mini-tutorial/index.txt index.txt-20070813141352-2u64ooqzo0or4hss-2
      doc/en/quick-reference/quick-start-summary.svg quickstartsummary.sv-20070813143223-5i7bgw7w8s7l3ae2-3
      doc/en/user-guide/authentication_conf.txt authentication_conf.-20071104135035-glfv0ri355tyg1nf-1
      doc/en/user-guide/bug_trackers.txt bug_trackers.txt-20070713223459-khxdlcudraii95uv-1
      doc/en/user-guide/configuration.txt configuration.txt-20060314161707-868350809502af01
      doc/en/user-guide/core_concepts.txt core_concepts.txt-20071114035000-q36a9h57ps06uvnl-2
      doc/en/user-guide/http_smart_server.txt fastcgi.txt-20061005091552-rz8pva0olkxv0sd8-3
      doc/en/user-guide/index.txt    index.txt-20060622101119-tgwtdci8z769bjb9-2
      doc/en/user-guide/installing_bazaar.txt installing_bazaar.tx-20071114035000-q36a9h57ps06uvnl-4
      doc/en/user-guide/introducing_bazaar.txt introducing_bazaar.t-20071114035000-q36a9h57ps06uvnl-5
      doc/en/user-guide/merging_changes.txt merging_changes.txt-20071122141511-0knao2lklsdsvb1q-3
      doc/en/user-guide/plugins.txt  plugins.txt-20060314145616-525099a747f3ffdd
      doc/en/user-guide/publishing_a_branch.txt publishing_a_branch.-20071123055134-k5x4ekduci2lbn36-2
      doc/en/user-guide/resolving_conflicts.txt resolving_conflicts.-20071122141511-0knao2lklsdsvb1q-5
      doc/en/user-guide/reusing_a_checkout.txt reusing_a_checkout.t-20071123055134-k5x4ekduci2lbn36-3
      doc/en/user-guide/server.txt   server.txt-20060913044801-h939fvbwzz39gf7g-1
      doc/en/user-guide/setting_up_email.txt setting_up_email.txt-20060314161707-fd242c8944346173
      doc/en/user-guide/specifying_revisions.txt specifying_revisions.txt-20060314161707-19deb139101bea33
      doc/en/user-guide/undoing_mistakes.txt undoing_mistakes.txt-20071121092300-8fyacngt1w98e5mp-1
      doc/en/user-guide/version_info.txt version_info.txt-20060921215543-gju6o5xdic8w25np-1
      doc/en/user-guide/working_offline_central.txt working_offline_cent-20071123055134-k5x4ekduci2lbn36-5
      doc/index.txt                  index.txt-20070813101924-07gd9i9d2jt124bf-1
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
      tools/doc_generate/autodoc_rstx.py autodoc_rstx.py-20060420024836-3e0d4a526452193c
      tools/rst2html.py              rst2html.py-20060817120932-gn177u8v0008txhu-1
    ------------------------------------------------------------
    revno: 3072.1.6
    revision-id:ian.clatworthy at internode.on.net-20071212071439-vqrvm1lm8vjw5br0
    parent: ian.clatworthy at internode.on.net-20071212070552-ru9mosc8f6g7elay
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.diff-no-wt
    timestamp: Wed 2007-12-12 17:14:39 +1000
    message:
      Fix docstring for _relative_paths_in_tree
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3072.1.5
    revision-id:ian.clatworthy at internode.on.net-20071212070552-ru9mosc8f6g7elay
    parent: ian.clatworthy at internode.on.net-20071204064436-suk6zps11j01u5xx
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.diff-no-wt
    timestamp: Wed 2007-12-12 17:05:52 +1000
    message:
      more good ideas from abentley
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tests/blackbox/test_outside_wt.py test_outside_wt.py-20060116200058-98edd33e7db8bdde
    ------------------------------------------------------------
    revno: 3072.1.4
    revision-id:ian.clatworthy at internode.on.net-20071204064436-suk6zps11j01u5xx
    parent: ian.clatworthy at internode.on.net-20071204063955-350y8zg4sdvd24qe
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.diff-no-wt
    timestamp: Tue 2007-12-04 16:44:36 +1000
    message:
      Tweak help
    modified:
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
    ------------------------------------------------------------
    revno: 3072.1.3
    revision-id:ian.clatworthy at internode.on.net-20071204063955-350y8zg4sdvd24qe
    parent: ian.clatworthy at internode.on.net-20071204063126-vifma88qptj13pyk
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.diff-no-wt
    timestamp: Tue 2007-12-04 16:39:55 +1000
    message:
      Test more --old and --new combinations
    modified:
      bzrlib/tests/blackbox/test_diff.py test_diff.py-20060110203741-aa99ac93e633d971
    ------------------------------------------------------------
    revno: 3072.1.2
    revision-id:ian.clatworthy at internode.on.net-20071204063126-vifma88qptj13pyk
    parent: ian.clatworthy at internode.on.net-20071204054937-6v169ypv0lclbyuj
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.diff-no-wt
    timestamp: Tue 2007-12-04 16:31:26 +1000
    message:
      Test various --old and --new combinations
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tests/blackbox/test_diff.py test_diff.py-20060110203741-aa99ac93e633d971
    ------------------------------------------------------------
    revno: 3072.1.1
    revision-id:ian.clatworthy at internode.on.net-20071204054937-6v169ypv0lclbyuj
    parent: pqm at pqm.ubuntu.com-20071203222135-gjk2xshgdfgxje6m
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.diff-no-wt
    timestamp: Tue 2007-12-04 15:49:37 +1000
    message:
      Improved diff based on feedback from abentley
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tests/blackbox/test_diff.py test_diff.py-20060110203741-aa99ac93e633d971
=== modified file 'NEWS'
--- a/NEWS	2007-12-15 16:37:13 +0000
+++ b/NEWS	2007-12-17 00:22:28 +0000
@@ -9,10 +9,21 @@
 
   CHANGES:
    
+   * The syntax ``bzr diff branch1 branch2`` is no longer supported.
+     Use ``bzr diff branch1 --new branch2`` instead. This change has
+     been made to remove the ambiguity where ``branch2`` is in fact a
+     specific file to diff within ``branch1``.
+
   FEATURES:
 
   IMPROVEMENTS:
 
+   * ``bzr diff`` now works on branches without working trees. Tree-less
+     branches can also be compared to each other and to working trees using
+     the new diff options ``--old`` and ``--new``. Diffing between branches,
+     with or without trees, now supports specific file filtering as well.
+     (Ian Clatworthy, #6700)
+
    * ``bzr pack`` now orders revision texts in topological order, with newest
      at the start of the file, promoting linear reads for ``bzr log`` and the
      like. This partially fixes #154129. (Robert Collins)
@@ -26,8 +37,6 @@
 
   BUGFIXES:
 
-   * Fix Makefile rules for doc generation. (Ian Clatworthy, #175207)
-
    * Transform failures no longer cause ImmortalLimbo errors (Aaron Bentley,
      #137681)
 

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2007-12-15 16:35:40 +0000
+++ b/bzrlib/builtins.py	2007-12-17 02:48:23 +0000
@@ -1390,10 +1390,14 @@
 
 
 class cmd_diff(Command):
-    """Show differences in the working tree or between revisions.
+    """Show differences in the working tree, between revisions or branches.
     
-    If files are listed, only the changes in those files are listed.
-    Otherwise, all changes for the tree are listed.
+    If no arguments are given, all changes for the current tree are listed.
+    If files are given, only the changes in those files are listed.
+    Remote and multiple branches can be compared by using the --old and
+    --new options. If not provided, the default for both is derived from
+    the first argument, if any, or the current tree if no arguments are
+    given.
 
     "bzr diff -p1" is equivalent to "bzr diff --prefix old/:new/", and
     produces patches suitable for "patch -p1".
@@ -1417,17 +1421,29 @@
 
             bzr diff -r1..2
 
+        Difference between revision 2 and revision 1 for branch xxx::
+
+            bzr diff -r1..2 xxx
+
+        Show just the differences for file NEWS::
+
+            bzr diff NEWS
+
+        Show the differences in working tree xxx for file NEWS::
+
+            bzr diff xxx/NEWS
+
+        Show the differences from branch xxx to this working tree:
+
+            bzr diff --old xxx
+
+        Show the differences between two branches for file NEWS::
+
+            bzr diff --old xxx --new yyy NEWS
+
         Same as 'bzr diff' but prefix paths with old/ and new/::
 
             bzr diff --prefix old/:new/
-
-        Show the differences between the two working trees::
-
-            bzr diff bzr.mine bzr.dev
-
-        Show just the differences for 'foo.c'::
-
-            bzr diff foo.c
     """
     # TODO: Option to use external diff command; could be GNU diff, wdiff,
     #       or a graphical diff.
@@ -1449,6 +1465,14 @@
                short_name='p',
                help='Set prefixes added to old and new filenames, as '
                     'two values separated by a colon. (eg "old/:new/").'),
+        Option('old',
+            help='Branch/tree to compare from.',
+            type=unicode,
+            ),
+        Option('new',
+            help='Branch/tree to compare to.',
+            type=unicode,
+            ),
         'revision',
         'change',
         ]
@@ -1457,8 +1481,8 @@
 
     @display_command
     def run(self, revision=None, file_list=None, diff_options=None,
-            prefix=None):
-        from bzrlib.diff import diff_cmd_helper, show_diff_trees
+            prefix=None, old=None, new=None):
+        from bzrlib.diff import _get_trees_to_diff, show_diff_trees
 
         if (prefix is None) or (prefix == '0'):
             # diff -p0 format
@@ -1478,47 +1502,13 @@
             raise errors.BzrCommandError('bzr diff --revision takes exactly'
                                          ' one or two revision specifiers')
 
-        try:
-            tree1, file_list = internal_tree_files(file_list)
-            tree2 = None
-            b = None
-            b2 = None
-        except errors.FileInWrongBranch:
-            if len(file_list) != 2:
-                raise errors.BzrCommandError("Files are in different branches")
-
-            tree1, file1 = WorkingTree.open_containing(file_list[0])
-            tree2, file2 = WorkingTree.open_containing(file_list[1])
-            if file1 != "" or file2 != "":
-                # FIXME diff those two files. rbc 20051123
-                raise errors.BzrCommandError("Files are in different branches")
-            file_list = None
-        except errors.NotBranchError:
-            if (revision is not None and len(revision) == 2
-                and not revision[0].needs_branch()
-                and not revision[1].needs_branch()):
-                # If both revision specs include a branch, we can
-                # diff them without needing a local working tree
-                tree1, tree2 = None, None
-            else:
-                raise
-
-        if tree2 is not None:
-            if revision is not None:
-                # FIXME: but there should be a clean way to diff between
-                # non-default versions of two trees, it's not hard to do
-                # internally...
-                raise errors.BzrCommandError(
-                        "Sorry, diffing arbitrary revisions across branches "
-                        "is not implemented yet")
-            return show_diff_trees(tree1, tree2, sys.stdout, 
-                                   specific_files=file_list,
-                                   external_diff_options=diff_options,
-                                   old_label=old_label, new_label=new_label)
-
-        return diff_cmd_helper(tree1, file_list, diff_options,
-                               revision_specs=revision,
-                               old_label=old_label, new_label=new_label)
+        old_tree, new_tree, specific_files, extra_trees = \
+                _get_trees_to_diff(file_list, revision, old, new)
+        return show_diff_trees(old_tree, new_tree, sys.stdout, 
+                               specific_files=specific_files,
+                               external_diff_options=diff_options,
+                               old_label=old_label, new_label=new_label,
+                               extra_trees=extra_trees)
 
 
 class cmd_deleted(Command):

=== modified file 'bzrlib/diff.py'
--- a/bzrlib/diff.py	2007-12-06 18:20:35 +0000
+++ b/bzrlib/diff.py	2007-12-17 00:22:28 +0000
@@ -27,6 +27,7 @@
 import time
 
 from bzrlib import (
+    bzrdir,
     errors,
     osutils,
     patiencediff,
@@ -37,6 +38,7 @@
 
 from bzrlib.symbol_versioning import (
         deprecated_function,
+        zero_ninetythree,
         )
 from bzrlib.trace import mutter, warning
 
@@ -270,6 +272,7 @@
                         new_abspath, e)
 
 
+ at deprecated_function(zero_ninetythree)
 def diff_cmd_helper(tree, specific_files, external_diff_options, 
                     old_revision_spec=None, new_revision_spec=None,
                     revision_specs=None,
@@ -346,6 +349,120 @@
                            extra_trees=extra_trees)
 
 
+def _get_trees_to_diff(path_list, revision_specs, old_url, new_url):
+    """Get the trees and specific files to diff given a list of paths.
+
+    This method works out the trees to be diff'ed and the files of
+    interest within those trees.
+
+    :param path_list:
+        the list of arguments passed to the diff command
+    :param revision_specs:
+        Zero, one or two RevisionSpecs from the diff command line,
+        saying what revisions to compare.
+    :param old_url:
+        The url of the old branch or tree. If None, the tree to use is
+        taken from the first path, if any, or the current working tree.
+    :param new_url:
+        The url of the new branch or tree. If None, the tree to use is
+        taken from the first path, if any, or the current working tree.
+    :returns:
+        a tuple of (old_tree, new_tree, specific_files, extra_trees) where
+        extra_trees is a sequence of additional trees to search in for
+        file-ids.
+    """
+    # Get the old and new revision specs
+    old_revision_spec = None
+    new_revision_spec = None
+    if revision_specs is not None:
+        if len(revision_specs) > 0:
+            old_revision_spec = revision_specs[0]
+            if old_url is None:
+                old_url = old_revision_spec.get_branch()
+        if len(revision_specs) > 1:
+            new_revision_spec = revision_specs[1]
+            if new_url is None:
+                new_url = new_revision_spec.get_branch()
+
+    other_paths = []
+    make_paths_wt_relative = True
+    if path_list is None or len(path_list) == 0:
+        # If no path is given, assume the current directory
+        default_location = u'.'
+    elif old_url is not None and new_url is not None:
+        other_paths = path_list
+        make_paths_wt_relative = False
+    else:
+        default_location = path_list[0]
+        other_paths = path_list[1:]
+
+    # Get the old location
+    specific_files = []
+    if old_url is None:
+        old_url = default_location
+    working_tree, branch, relpath = \
+        bzrdir.BzrDir.open_containing_tree_or_branch(old_url)
+    if relpath != '':
+        specific_files.append(relpath)
+    old_tree = _get_tree_to_diff(old_revision_spec, working_tree, branch)
+
+    # Get the new location
+    if new_url is None:
+        new_url = default_location
+    if new_url != old_url:
+        working_tree, branch, relpath = \
+            bzrdir.BzrDir.open_containing_tree_or_branch(new_url)
+        if relpath != '':
+            specific_files.append(relpath)
+    new_tree = _get_tree_to_diff(new_revision_spec, working_tree, branch,
+        basis_is_default=working_tree is None)
+
+    # Get the specific files (all files is None, no files is [])
+    if make_paths_wt_relative and working_tree is not None:
+        other_paths = _relative_paths_in_tree(working_tree, other_paths)
+    specific_files.extend(other_paths)
+    if len(specific_files) == 0:
+        specific_files = None
+
+    # Get extra trees that ought to be searched for file-ids
+    extra_trees = None
+    if working_tree is not None and working_tree not in (old_tree, new_tree):
+        extra_trees = (working_tree,)
+    return old_tree, new_tree, specific_files, extra_trees
+
+
+def _get_tree_to_diff(spec, tree=None, branch=None, basis_is_default=True):
+    if branch is None and tree is not None:
+        branch = tree.branch
+    if spec is None or spec.spec is None:
+        if basis_is_default:
+            if tree is not None:
+                return tree.basis_tree()
+            else:
+                return branch.basis_tree()
+        else:
+            return tree
+    revision = spec.in_store(branch)
+    revision_id = revision.rev_id
+    rev_branch = revision.branch
+    return rev_branch.repository.revision_tree(revision_id)
+
+
+def _relative_paths_in_tree(tree, paths):
+    """Get the relative paths within a working tree.
+
+    Each path may be either an absolute path or a path relative to the
+    current working directory.
+    """
+    result = []
+    for filename in paths:
+        try:
+            result.append(tree.relpath(osutils.dereference_path(filename)))
+        except errors.PathNotChild:
+            raise errors.BzrCommandError("Files are in different branches")
+    return result
+
+
 def show_diff_trees(old_tree, new_tree, to_file, specific_files=None,
                     external_diff_options=None,
                     old_label='a/', new_label='b/',
@@ -353,8 +470,11 @@
                     path_encoding='utf8'):
     """Show in text form the changes from one tree to another.
 
-    to_files
-        If set, include only changes to these files.
+    to_file
+        The output stream.
+
+    specific_files
+        Include only changes to these files - None for all changes.
 
     external_diff_options
         If set, use an external GNU diff and pass these options.

=== modified file 'bzrlib/tests/blackbox/test_diff.py'
--- a/bzrlib/tests/blackbox/test_diff.py	2007-09-01 16:04:44 +0000
+++ b/bzrlib/tests/blackbox/test_diff.py	2007-12-04 06:39:55 +0000
@@ -146,18 +146,18 @@
     def example_branches(self):
         branch1_tree = self.make_branch_and_tree('branch1')
         self.build_tree(['branch1/file'], line_endings='binary')
+        self.build_tree(['branch1/file2'], line_endings='binary')
         branch1_tree.add('file')
-        branch1_tree.commit(message='add file')
+        branch1_tree.add('file2')
+        branch1_tree.commit(message='add file and file2')
         branch2_tree = branch1_tree.bzrdir.sprout('branch2').open_workingtree()
         self.build_tree_contents([('branch2/file', 'new content\n')])
         branch2_tree.commit(message='update file')
         return branch1_tree, branch2_tree
 
-    def test_diff_branches(self):
-        self.example_branches()
-        # should open branch1 and diff against branch2, 
-        out, err = self.run_bzr('diff -r branch:branch2 branch1',
-                                retcode=1)
+    def check_b2_vs_b1(self, cmd):
+        # Compare branch2 vs branch1 using cmd and check the result
+        out, err = self.run_bzr(cmd, retcode=1)
         self.assertEquals('', err)
         self.assertEquals("=== modified file 'file'\n"
                           "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
@@ -166,17 +166,63 @@
                           "-new content\n"
                           "+contents of branch1/file\n"
                           "\n", subst_dates(out))
-        out, err = self.run_bzr('diff branch2 branch1',
-                                         retcode=1)
+
+    def check_b1_vs_b2(self, cmd):
+        # Compare branch1 vs branch2 using cmd and check the result
+        out, err = self.run_bzr(cmd, retcode=1)
         self.assertEquals('', err)
         self.assertEqualDiff("=== modified file 'file'\n"
                               "--- file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
                               "+++ file\tYYYY-MM-DD HH:MM:SS +ZZZZ\n"
                               "@@ -1,1 +1,1 @@\n"
-                              "-new content\n"
-                              "+contents of branch1/file\n"
+                              "-contents of branch1/file\n"
+                              "+new content\n"
                               "\n", subst_dates(out))
 
+    def check_no_diffs(self, cmd):
+        # Check that running cmd returns an empty diff
+        out, err = self.run_bzr(cmd, retcode=0)
+        self.assertEquals('', err)
+        self.assertEquals('', out)
+
+    def test_diff_branches(self):
+        self.example_branches()
+        # should open branch1 and diff against branch2, 
+        self.check_b2_vs_b1('diff -r branch:branch2 branch1')
+        # Compare two working trees using various syntax forms
+        self.check_b2_vs_b1('diff --old branch2 --new branch1')
+        self.check_b2_vs_b1('diff --old branch2 branch1')
+        self.check_b2_vs_b1('diff branch2 --new branch1')
+        # Test with a selected file that was changed
+        self.check_b2_vs_b1('diff --old branch2 --new branch1 file')
+        self.check_b2_vs_b1('diff --old branch2 branch1/file')
+        self.check_b2_vs_b1('diff branch2/file --new branch1')
+        # Test with a selected file that was not changed
+        self.check_no_diffs('diff --old branch2 --new branch1 file2')
+        self.check_no_diffs('diff --old branch2 branch1/file2')
+        self.check_no_diffs('diff branch2/file2 --new branch1')
+
+    def test_diff_branches_no_working_trees(self):
+        branch1_tree, branch2_tree = self.example_branches()
+        # Compare a working tree to a branch without a WT
+        dir1 = branch1_tree.bzrdir
+        dir1.destroy_workingtree()
+        self.assertFalse(dir1.has_workingtree())
+        self.check_b2_vs_b1('diff --old branch2 --new branch1')
+        self.check_b2_vs_b1('diff --old branch2 branch1')
+        self.check_b2_vs_b1('diff branch2 --new branch1')
+        # Compare a branch without a WT to one with a WT
+        self.check_b1_vs_b2('diff --old branch1 --new branch2')
+        self.check_b1_vs_b2('diff --old branch1 branch2')
+        self.check_b1_vs_b2('diff branch1 --new branch2')
+        # Compare a branch with a WT against another without a WT
+        dir2 = branch2_tree.bzrdir
+        dir2.destroy_workingtree()
+        self.assertFalse(dir2.has_workingtree())
+        self.check_b1_vs_b2('diff --old branch1 --new branch2')
+        self.check_b1_vs_b2('diff --old branch1 branch2')
+        self.check_b1_vs_b2('diff branch1 --new branch2')
+
     def test_diff_revno_branches(self):
         self.example_branches()
         branch2_tree = workingtree.WorkingTree.open_containing('branch2')[0]
@@ -221,6 +267,14 @@
         self.run_bzr('diff hello1', retcode=1)
         self.run_bzr('diff -r 0..1 hello1', retcode=1)
 
+    def test_diff_to_branch_no_working_tree(self):
+        branch1_tree = self.example_branch2()
+        dir1 = branch1_tree.bzrdir
+        dir1.destroy_workingtree()
+        self.assertFalse(dir1.has_workingtree())
+        output = self.run_bzr('diff -r 1.. branch1', retcode=1)
+        self.assertContainsRe(output[0], '\n\\-original line\n\\+repo line\n')
+
 
 class TestCheckoutDiff(TestDiff):
 

=== modified file 'bzrlib/tests/blackbox/test_outside_wt.py'
--- a/bzrlib/tests/blackbox/test_outside_wt.py	2007-08-23 14:10:48 +0000
+++ b/bzrlib/tests/blackbox/test_outside_wt.py	2007-12-12 07:05:52 +0000
@@ -48,25 +48,25 @@
                                '--unchanged', 'branch1'])
         self.run_bzr(['commit', '-m', 'nothing',
                                '--unchanged', 'branch1'])
+        this_dir = getcwd()
+        branch2 = "%s/branch2" % (this_dir,)
         # -r X..Y
         out, err = self.run_bzr('diff -r revno:2:branch2..revno:1', retcode=3)
         self.assertEquals('', out)
-        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (getcwd(),),
+        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (branch2,),
                          err)
         # -r X
         out, err = self.run_bzr('diff -r revno:2:branch2', retcode=3)
         self.assertEquals('', out)
-        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (getcwd(),),
+        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (branch2,),
                          err)
         # -r X..
         out, err = self.run_bzr('diff -r revno:2:branch2..', retcode=3)
         self.assertEquals('', out)
-        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (getcwd(),),
+        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (branch2,),
                          err)
         # no -r at all.
         out, err = self.run_bzr('diff', retcode=3)
         self.assertEquals('', out)
-        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (getcwd(),),
+        self.assertEqual(u'bzr: ERROR: Not a branch: "%s/".\n' % (this_dir,),
                          err)
-
-




More information about the bazaar-commits mailing list