Rev 3036: Avoid using Tree.inventory (even indirectly) from diff command in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Nov 27 14:38:44 GMT 2007


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

------------------------------------------------------------
revno: 3036
revision-id:pqm at pqm.ubuntu.com-20071127143838-lkx79x6q91uptc1o
parent: pqm at pqm.ubuntu.com-20071127101459-zcdf4aia34927kt0
parent: abentley at panoramicfeedback.com-20071127135729-il5et0dxtsu05ceh
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2007-11-27 14:38:38 +0000
message:
  Avoid using Tree.inventory (even indirectly) from diff command
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
  bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
  bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
  bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
  bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
    ------------------------------------------------------------
    revno: 3009.2.29
    revision-id:abentley at panoramicfeedback.com-20071127135729-il5et0dxtsu05ceh
    parent: aaron.bentley at utoronto.ca-20071125215224-44ifs6un0hkvw6x9
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Tue 2007-11-27 08:57:29 -0500
    message:
      Change constants to strings
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.28
    revision-id:aaron.bentley at utoronto.ca-20071125215224-44ifs6un0hkvw6x9
    parent: aaron.bentley at utoronto.ca-20071125172110-fsz9owanvduc6yzx
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Sun 2007-11-25 16:52:24 -0500
    message:
      Add from_diff_tree factories
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.27
    revision-id:aaron.bentley at utoronto.ca-20071125172110-fsz9owanvduc6yzx
    parent: aaron.bentley at utoronto.ca-20071125165321-be29tuiy92fb62l7
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Sun 2007-11-25 12:21:10 -0500
    message:
      Use extra_factories instead of extra_diffs
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.26
    revision-id:aaron.bentley at utoronto.ca-20071125165321-be29tuiy92fb62l7
    parent: aaron.bentley at utoronto.ca-20071125164716-y48cfw87mxrfaok2
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Sun 2007-11-25 11:53:21 -0500
    message:
      Update NEWS
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 3009.2.25
    revision-id:aaron.bentley at utoronto.ca-20071125164716-y48cfw87mxrfaok2
    parent: aaron.bentley at utoronto.ca-20071124001331-74p3la8ucmdfoysz
    parent: aaron.bentley at utoronto.ca-20071124001242-5ipv4t02fzu7pf4q
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Sun 2007-11-25 11:47:16 -0500
    message:
      Merge dirstate fixes to avoid Tree.inventory during diff (#149254)
    modified:
      bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
        ------------------------------------------------------------
        revno: 3016.1.1
        revision-id:aaron.bentley at utoronto.ca-20071124001242-5ipv4t02fzu7pf4q
        parent: pqm at pqm.ubuntu.com-20071123043953-lv68pawzrpa4s9t9
        committer: Aaron Bentley <aaron.bentley at utoronto.ca>
        branch nick: no-inventory-dirstate
        timestamp: Fri 2007-11-23 19:12:42 -0500
        message:
          Update DirStateRevisionTree to avoid using inventory
        modified:
          bzrlib/workingtree_4.py        workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
    ------------------------------------------------------------
    revno: 3009.2.24
    revision-id:aaron.bentley at utoronto.ca-20071124001331-74p3la8ucmdfoysz
    parent: aaron.bentley at utoronto.ca-20071123231449-5d73wnqnf8cqsv09
    parent: pqm at pqm.ubuntu.com-20071123043953-lv68pawzrpa4s9t9
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Fri 2007-11-23 19:13:31 -0500
    message:
      Merge bzr.dev
    added:
      bzrlib/switch.py               switch.py-20071116011000-v5lnw7d2wkng9eux-1
      bzrlib/tests/blackbox/test_switch.py test_switch.py-20071122111948-0c5en6uz92bwl76h-1
      bzrlib/tests/repository_implementations/test__generate_text_key_index.py test__generate_text_-20071114232121-00h9fd8qg8kjfa5k-1
      bzrlib/tests/repository_implementations/test_find_text_key_references.py test_find_text_key_r-20071114033605-v73bakal8x77qlfi-1
      bzrlib/tests/test_switch.py    test_switch.py-20071116011000-v5lnw7d2wkng9eux-2
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/annotate.py             annotate.py-20050922133147-7c60541d2614f022
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/check.py                check.py-20050309040759-f3a679400c06bcc1
      bzrlib/graph.py                graph_walker.py-20070525030359-y852guab65d4wtn0-1
      bzrlib/msgeditor.py            msgeditor.py-20050901111708-ef6d8de98f5d8f2f
      bzrlib/reconcile.py            reweave_inventory.py-20051108164726-1e5e0934febac06e
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/revision.py             revision.py-20050309040759-e77802c08f3999d5
      bzrlib/revisionspec.py         revisionspec.py-20050907152633-17567659fd5c0ddb
      bzrlib/sign_my_commits.py      sign_my_commits.py-20060215152201-5a6363365180e671
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/blackbox/__init__.py __init__.py-20051128053524-eba30d8255e08dc3
      bzrlib/tests/blackbox/test_info.py test_info.py-20060215045507-bbdd2d34efab9e0a
      bzrlib/tests/blackbox/test_reconcile.py test_fix.py-20060223013051-9a188e15a5ee9451
      bzrlib/tests/blackbox/test_versioning.py versioning.py-20050622071821-3ddf5e2e5e93c602
      bzrlib/tests/interrepository_implementations/test_interrepository.py test_interrepository.py-20060220061411-1ec13fa99e5e3eee
      bzrlib/tests/repository_implementations/__init__.py __init__.py-20060131092037-9564957a7d4a841b
      bzrlib/tests/repository_implementations/test_check.py test_check.py-20070824124512-38g4d135gcqxo4zb-1
      bzrlib/tests/repository_implementations/test_check_reconcile.py test_broken.py-20070928125406-62236394w0jpbpd6-2
      bzrlib/tests/test_annotate.py  test_annotate.py-20061213215015-sttc9agsxomls7q0-1
      bzrlib/tests/test_commit.py    test_commit.py-20050914060732-279f057f8c295434
      bzrlib/tests/test_dirstate.py  test_dirstate.py-20060728012006-d6mvoihjb3je9peu-2
      bzrlib/tests/test_fetch.py     testfetch.py-20050825090644-f73e07e7dfb1765a
      bzrlib/tests/test_graph.py     test_graph_walker.py-20070525030405-enq4r60hhi9xrujc-1
      bzrlib/tests/test_memorytree.py test_memorytree.py-20060906023413-4wlkalbdpsxi2r4y-3
      bzrlib/tests/test_merge_core.py test_merge_core.py-20050824132511-eb99b23a0eec641b
      bzrlib/tests/test_merge_directive.py test_merge_directive-20070228184838-ja62280spt1g7f4x-2
      bzrlib/tests/test_msgeditor.py test_msgeditor.py-20051202041359-920315ec6011ee51
      bzrlib/transport/local.py      local_transport.py-20050711165921-9b1f142bfe480c24
    ------------------------------------------------------------
    revno: 3009.2.23
    revision-id:aaron.bentley at utoronto.ca-20071123231449-5d73wnqnf8cqsv09
    parent: aaron.bentley at utoronto.ca-20071123041928-zhoxs1r8onesojut
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Fri 2007-11-23 18:14:49 -0500
    message:
      Renaming fix
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.22
    revision-id:aaron.bentley at utoronto.ca-20071123041928-zhoxs1r8onesojut
    parent: abentley at panoramicfeedback.com-20071122194330-1qjedkozl321kb1s
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 23:19:28 -0500
    message:
      Update names & docstring
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.21
    revision-id:abentley at panoramicfeedback.com-20071122194330-1qjedkozl321kb1s
    parent: abentley at panoramicfeedback.com-20071122194250-nutd7qq7lfqc99am
    parent: pqm at pqm.ubuntu.com-20071122050938-la5hkrql1mag6u7p
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 14:43:30 -0500
    message:
      Merge bzr.dev
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/fetch.py                fetch.py-20050818234941-26fea6105696365d
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/knitrepo.py     knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/tests/blackbox/test_info.py test_info.py-20060215045507-bbdd2d34efab9e0a
      bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
      bzrlib/tests/test_info.py      test_info.py-20070320150933-m0xxm1g7xi9v6noe-1
      bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
    ------------------------------------------------------------
    revno: 3009.2.20
    revision-id:abentley at panoramicfeedback.com-20071122194250-nutd7qq7lfqc99am
    parent: abentley at panoramicfeedback.com-20071122190642-l5bq9d0mkk1cmyzd
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 14:42:50 -0500
    message:
      PEP8
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.19
    revision-id:abentley at panoramicfeedback.com-20071122190642-l5bq9d0mkk1cmyzd
    parent: abentley at panoramicfeedback.com-20071122182348-pbsce06az2i96yd3
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 14:06:42 -0500
    message:
      Implement directory diffing
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.18
    revision-id:abentley at panoramicfeedback.com-20071122182348-pbsce06az2i96yd3
    parent: abentley at panoramicfeedback.com-20071122182117-hs220sdlczwhy8zw
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 13:23:48 -0500
    message:
      Change KindChangeDiffer's anti-recursion to avoid kind pairs with None
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.17
    revision-id:abentley at panoramicfeedback.com-20071122182117-hs220sdlczwhy8zw
    parent: abentley at panoramicfeedback.com-20071122175232-w06vj7ucjl7gfygl
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 13:21:17 -0500
    message:
      Update docs
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.16
    revision-id:abentley at panoramicfeedback.com-20071122175232-w06vj7ucjl7gfygl
    parent: abentley at panoramicfeedback.com-20071122174639-gc0xuf2ws29aneet
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 12:52:32 -0500
    message:
      Test support for extra differs
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.15
    revision-id:abentley at panoramicfeedback.com-20071122174639-gc0xuf2ws29aneet
    parent: abentley at panoramicfeedback.com-20071122154848-jn89dr9kojaln6vu
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 12:46:39 -0500
    message:
      Test differ registration
    modified:
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.14
    revision-id:abentley at panoramicfeedback.com-20071122154848-jn89dr9kojaln6vu
    parent: abentley at panoramicfeedback.com-20071122151502-m9kwy2ums0gddyev
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 10:48:48 -0500
    message:
      Update return type handling
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.13
    revision-id:abentley at panoramicfeedback.com-20071122151502-m9kwy2ums0gddyev
    parent: aaron.bentley at utoronto.ca-20071122041411-xljgvcijantv9cdw
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Thu 2007-11-22 10:15:02 -0500
    message:
      Refactor differ to support registering differ factories
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.12
    revision-id:aaron.bentley at utoronto.ca-20071122041411-xljgvcijantv9cdw
    parent: aaron.bentley at utoronto.ca-20071122024735-4tsl5snv3zi4m3zg
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 23:14:11 -0500
    message:
      Associate labels with text diffing only
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.11
    revision-id:aaron.bentley at utoronto.ca-20071122024735-4tsl5snv3zi4m3zg
    parent: abentley at panoramicfeedback.com-20071121174852-miztj0j1qgkpnk7w
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 21:47:35 -0500
    message:
      Refactor diff to be more pluggable
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.10
    revision-id:abentley at panoramicfeedback.com-20071121174852-miztj0j1qgkpnk7w
    parent: abentley at panoramicfeedback.com-20071121173918-nb1j0nn9cxrfc53w
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 12:48:52 -0500
    message:
      Remove trailing whitespace
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.9
    revision-id:abentley at panoramicfeedback.com-20071121173918-nb1j0nn9cxrfc53w
    parent: abentley at panoramicfeedback.com-20071121161941-6au4zqgr4qgah2xc
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 12:39:18 -0500
    message:
      Add tests for Differ
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tests/test_diff.py      testdiff.py-20050727164403-d1a3496ebb12e339
    ------------------------------------------------------------
    revno: 3009.2.8
    revision-id:abentley at panoramicfeedback.com-20071121161941-6au4zqgr4qgah2xc
    parent: abentley at panoramicfeedback.com-20071121155930-bkgita4crkze2355
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 11:19:41 -0500
    message:
      Support diffing without indirecting through inventory entries
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.7
    revision-id:abentley at panoramicfeedback.com-20071121155930-bkgita4crkze2355
    parent: abentley at panoramicfeedback.com-20071121152730-ttbjijxcc88131zp
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 10:59:30 -0500
    message:
      Move responsibility for generating diff labels into Differ.diff
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.6
    revision-id:abentley at panoramicfeedback.com-20071121152730-ttbjijxcc88131zp
    parent: abentley at panoramicfeedback.com-20071121145546-dsbz0266amz9q1w3
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 10:27:30 -0500
    message:
      Convert show_diff_trees into a Differ method
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.5
    revision-id:abentley at panoramicfeedback.com-20071121145546-dsbz0266amz9q1w3
    parent: abentley at panoramicfeedback.com-20071121140853-yc9zlb4ct58x2j5b
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 09:55:46 -0500
    message:
      Factor symlink and file diffing into differ
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
    ------------------------------------------------------------
    revno: 3009.2.4
    revision-id:abentley at panoramicfeedback.com-20071121140853-yc9zlb4ct58x2j5b
    parent: abentley at panoramicfeedback.com-20071121140303-eil5haph3u2ovwjg
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 09:08:53 -0500
    message:
      Make old_tree/new_tree construction parameters of Differ
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.3
    revision-id:abentley at panoramicfeedback.com-20071121140303-eil5haph3u2ovwjg
    parent: aaron.bentley at utoronto.ca-20071121132138-trbirzab46iqw2np
    committer: Aaron Bentley <abentley at panoramicfeedback.com>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 09:03:03 -0500
    message:
      Detect missing files from inv operation
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
    ------------------------------------------------------------
    revno: 3009.2.2
    revision-id:aaron.bentley at utoronto.ca-20071121132138-trbirzab46iqw2np
    parent: aaron.bentley at utoronto.ca-20071121130300-ml2xmnf5uod3de1q
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 08:21:38 -0500
    message:
      Implement Differ object for abstracting diffing
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
    ------------------------------------------------------------
    revno: 3009.2.1
    revision-id:aaron.bentley at utoronto.ca-20071121130300-ml2xmnf5uod3de1q
    parent: pqm at pqm.ubuntu.com-20071120221348-g9syrz6y7xcannkb
    committer: Aaron Bentley <aaron.bentley at utoronto.ca>
    branch nick: no-inventory
    timestamp: Wed 2007-11-21 08:03:00 -0500
    message:
      Provide Tree interface for diffing files
    modified:
      bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
      bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
=== modified file 'NEWS'
--- a/NEWS	2007-11-27 09:36:33 +0000
+++ b/NEWS	2007-11-27 14:38:38 +0000
@@ -49,6 +49,9 @@
    * Revert takes out an appropriate lock when reverting to a basis tree, and
      does not read the basis inventory twice. (Robert Collins)
 
+   * Diff does not require an inventory to be generated on dirstate trees.
+     (Aaron Bentley, #149254)
+
   IMPROVEMENTS:
 
    * ``bzr tags`` now prints the revision number for each tag, instead of

=== modified file 'bzrlib/diff.py'
--- a/bzrlib/diff.py	2007-10-16 16:02:01 +0000
+++ b/bzrlib/diff.py	2007-11-27 13:57:29 +0000
@@ -371,11 +371,11 @@
                 tree.lock_read()
         new_tree.lock_read()
         try:
-            return _show_diff_trees(old_tree, new_tree, to_file,
-                                    specific_files, external_diff_options,
-                                    old_label=old_label, new_label=new_label,
-                                    extra_trees=extra_trees,
-                                    path_encoding=path_encoding)
+            differ = DiffTree.from_trees_options(old_tree, new_tree, to_file,
+                                                   path_encoding,
+                                                   external_diff_options,
+                                                   old_label, new_label)
+            return differ.show_diff(specific_files, extra_trees)
         finally:
             new_tree.unlock()
             if extra_trees is not None:
@@ -385,87 +385,6 @@
         old_tree.unlock()
 
 
-def _show_diff_trees(old_tree, new_tree, to_file,
-                     specific_files, external_diff_options, path_encoding,
-                     old_label='a/', new_label='b/', extra_trees=None):
-
-    # GNU Patch uses the epoch date to detect files that are being added
-    # or removed in a diff.
-    EPOCH_DATE = '1970-01-01 00:00:00 +0000'
-
-    # TODO: Generation of pseudo-diffs for added/deleted files could
-    # be usefully made into a much faster special case.
-
-    if external_diff_options:
-        assert isinstance(external_diff_options, basestring)
-        opts = external_diff_options.split()
-        def diff_file(olab, olines, nlab, nlines, to_file):
-            external_diff(olab, olines, nlab, nlines, to_file, opts)
-    else:
-        diff_file = internal_diff
-    
-    delta = new_tree.changes_from(old_tree,
-        specific_files=specific_files,
-        extra_trees=extra_trees, require_versioned=True)
-
-    has_changes = 0
-    for path, file_id, kind in delta.removed:
-        has_changes = 1
-        path_encoded = path.encode(path_encoding, "replace")
-        to_file.write("=== removed %s '%s'\n" % (kind, path_encoded))
-        old_name = '%s%s\t%s' % (old_label, path,
-                                 _patch_header_date(old_tree, file_id, path))
-        new_name = '%s%s\t%s' % (new_label, path, EPOCH_DATE)
-        old_tree.inventory[file_id].diff(diff_file, old_name, old_tree,
-                                         new_name, None, None, to_file)
-    for path, file_id, kind in delta.added:
-        has_changes = 1
-        path_encoded = path.encode(path_encoding, "replace")
-        to_file.write("=== added %s '%s'\n" % (kind, path_encoded))
-        old_name = '%s%s\t%s' % (old_label, path, EPOCH_DATE)
-        new_name = '%s%s\t%s' % (new_label, path,
-                                 _patch_header_date(new_tree, file_id, path))
-        new_tree.inventory[file_id].diff(diff_file, new_name, new_tree,
-                                         old_name, None, None, to_file, 
-                                         reverse=True)
-    for (old_path, new_path, file_id, kind,
-         text_modified, meta_modified) in delta.renamed:
-        has_changes = 1
-        prop_str = get_prop_change(meta_modified)
-        oldpath_encoded = old_path.encode(path_encoding, "replace")
-        newpath_encoded = new_path.encode(path_encoding, "replace")
-        to_file.write("=== renamed %s '%s' => '%s'%s\n" % (kind,
-                            oldpath_encoded, newpath_encoded, prop_str))
-        old_name = '%s%s\t%s' % (old_label, old_path,
-                                 _patch_header_date(old_tree, file_id,
-                                                    old_path))
-        new_name = '%s%s\t%s' % (new_label, new_path,
-                                 _patch_header_date(new_tree, file_id,
-                                                    new_path))
-        _maybe_diff_file_or_symlink(old_name, old_tree, file_id,
-                                    new_name, new_tree,
-                                    text_modified, kind, to_file, diff_file)
-    for path, file_id, kind, text_modified, meta_modified in delta.modified:
-        has_changes = 1
-        prop_str = get_prop_change(meta_modified)
-        path_encoded = path.encode(path_encoding, "replace")
-        to_file.write("=== modified %s '%s'%s\n" % (kind,
-                            path_encoded, prop_str))
-        # The file may be in a different location in the old tree (because
-        # the containing dir was renamed, but the file itself was not)
-        old_path = old_tree.id2path(file_id)
-        old_name = '%s%s\t%s' % (old_label, old_path,
-                                 _patch_header_date(old_tree, file_id, old_path))
-        new_name = '%s%s\t%s' % (new_label, path,
-                                 _patch_header_date(new_tree, file_id, path))
-        if text_modified:
-            _maybe_diff_file_or_symlink(old_name, old_tree, file_id,
-                                        new_name, new_tree,
-                                        True, kind, to_file, diff_file)
-
-    return has_changes
-
-
 def _patch_header_date(tree, file_id, path):
     """Returns a timestamp suitable for use in a patch header."""
     mtime = tree.get_file_mtime(file_id, path)
@@ -501,12 +420,338 @@
         return  ""
 
 
-def _maybe_diff_file_or_symlink(old_path, old_tree, file_id,
-                                new_path, new_tree, text_modified,
-                                kind, to_file, diff_file):
-    if text_modified:
-        new_entry = new_tree.inventory[file_id]
-        old_tree.inventory[file_id].diff(diff_file,
-                                         old_path, old_tree,
-                                         new_path, new_entry, 
-                                         new_tree, to_file)
+class DiffPath(object):
+    """Base type for command object that compare files"""
+
+    # The type or contents of the file were unsuitable for diffing
+    CANNOT_DIFF = 'CANNOT_DIFF'
+    # The file has changed in a semantic way
+    CHANGED = 'CHANGED'
+    # The file content may have changed, but there is no semantic change
+    UNCHANGED = 'UNCHANGED'
+
+    def __init__(self, old_tree, new_tree, to_file, path_encoding='utf-8'):
+        """Constructor.
+
+        :param old_tree: The tree to show as the old tree in the comparison
+        :param new_tree: The tree to show as new in the comparison
+        :param to_file: The file to write comparison data to
+        :param path_encoding: The character encoding to write paths in
+        """
+        self.old_tree = old_tree
+        self.new_tree = new_tree
+        self.to_file = to_file
+        self.path_encoding = path_encoding
+
+    @classmethod
+    def from_diff_tree(klass, diff_tree):
+        return klass(diff_tree.old_tree, diff_tree.new_tree,
+                     diff_tree.to_file, diff_tree.path_encoding)
+
+    @staticmethod
+    def _diff_many(differs, file_id, old_path, new_path, old_kind, new_kind):
+        for file_differ in differs:
+            result = file_differ.diff(file_id, old_path, new_path, old_kind,
+                                      new_kind)
+            if result is not DiffPath.CANNOT_DIFF:
+                return result
+        else:
+            return DiffPath.CANNOT_DIFF
+
+
+class DiffKindChange(object):
+    """Special differ for file kind changes.
+
+    Represents kind change as deletion + creation.  Uses the other differs
+    to do this.
+    """
+    def __init__(self, differs):
+        self.differs = differs
+
+    @classmethod
+    def from_diff_tree(klass, diff_tree):
+        return klass(diff_tree.differs)
+
+    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
+        """Perform comparison
+
+        :param file_id: The file_id of the file to compare
+        :param old_path: Path of the file in the old tree
+        :param new_path: Path of the file in the new tree
+        :param old_kind: Old file-kind of the file
+        :param new_kind: New file-kind of the file
+        """
+        if None in (old_kind, new_kind):
+            return DiffPath.CANNOT_DIFF
+        result = DiffPath._diff_many(self.differs, file_id, old_path,
+                                       new_path, old_kind, None)
+        if result is DiffPath.CANNOT_DIFF:
+            return result
+        return DiffPath._diff_many(self.differs, file_id, old_path, new_path,
+                                     None, new_kind)
+
+
+class DiffDirectory(DiffPath):
+
+    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
+        """Perform comparison between two directories.  (dummy)
+
+        """
+        if 'directory' not in (old_kind, new_kind):
+            return self.CANNOT_DIFF
+        if old_kind not in ('directory', None):
+            return self.CANNOT_DIFF
+        if new_kind not in ('directory', None):
+            return self.CANNOT_DIFF
+        return self.CHANGED
+
+
+class DiffSymlink(DiffPath):
+
+    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
+        """Perform comparison between two symlinks
+
+        :param file_id: The file_id of the file to compare
+        :param old_path: Path of the file in the old tree
+        :param new_path: Path of the file in the new tree
+        :param old_kind: Old file-kind of the file
+        :param new_kind: New file-kind of the file
+        """
+        if 'symlink' not in (old_kind, new_kind):
+            return self.CANNOT_DIFF
+        if old_kind == 'symlink':
+            old_target = self.old_tree.get_symlink_target(file_id)
+        elif old_kind is None:
+            old_target = None
+        else:
+            return self.CANNOT_DIFF
+        if new_kind == 'symlink':
+            new_target = self.new_tree.get_symlink_target(file_id)
+        elif new_kind is None:
+            new_target = None
+        else:
+            return self.CANNOT_DIFF
+        return self.diff_symlink(old_target, new_target)
+
+    def diff_symlink(self, old_target, new_target):
+        if old_target is None:
+            self.to_file.write('=== target is %r\n' % new_target)
+        elif new_target is None:
+            self.to_file.write('=== target was %r\n' % old_target)
+        else:
+            self.to_file.write('=== target changed %r => %r\n' %
+                              (old_target, new_target))
+        return self.CHANGED
+
+
+class DiffText(DiffPath):
+
+    # GNU Patch uses the epoch date to detect files that are being added
+    # or removed in a diff.
+    EPOCH_DATE = '1970-01-01 00:00:00 +0000'
+
+    def __init__(self, old_tree, new_tree, to_file, path_encoding='utf-8',
+                 old_label='', new_label='', text_differ=internal_diff):
+        DiffPath.__init__(self, old_tree, new_tree, to_file, path_encoding)
+        self.text_differ = text_differ
+        self.old_label = old_label
+        self.new_label = new_label
+        self.path_encoding = path_encoding
+
+    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
+        """Compare two files in unified diff format
+
+        :param file_id: The file_id of the file to compare
+        :param old_path: Path of the file in the old tree
+        :param new_path: Path of the file in the new tree
+        :param old_kind: Old file-kind of the file
+        :param new_kind: New file-kind of the file
+        """
+        if 'file' not in (old_kind, new_kind):
+            return self.CANNOT_DIFF
+        from_file_id = to_file_id = file_id
+        if old_kind == 'file':
+            old_date = _patch_header_date(self.old_tree, file_id, old_path)
+        elif old_kind is None:
+            old_date = self.EPOCH_DATE
+            from_file_id = None
+        else:
+            return self.CANNOT_DIFF
+        if new_kind == 'file':
+            new_date = _patch_header_date(self.new_tree, file_id, new_path)
+        elif new_kind is None:
+            new_date = self.EPOCH_DATE
+            to_file_id = None
+        else:
+            return self.CANNOT_DIFF
+        from_label = '%s%s\t%s' % (self.old_label, old_path, old_date)
+        to_label = '%s%s\t%s' % (self.new_label, new_path, new_date)
+        return self.diff_text(from_file_id, to_file_id, from_label, to_label)
+
+    def diff_text(self, from_file_id, to_file_id, from_label, to_label):
+        """Diff the content of given files in two trees
+
+        :param from_file_id: The id of the file in the from tree.  If None,
+            the file is not present in the from tree.
+        :param to_file_id: The id of the file in the to tree.  This may refer
+            to a different file from from_file_id.  If None,
+            the file is not present in the to tree.
+        """
+        def _get_text(tree, file_id):
+            if file_id is not None:
+                return tree.get_file(file_id).readlines()
+            else:
+                return []
+        try:
+            from_text = _get_text(self.old_tree, from_file_id)
+            to_text = _get_text(self.new_tree, to_file_id)
+            self.text_differ(from_label, from_text, to_label, to_text,
+                             self.to_file)
+        except errors.BinaryFile:
+            self.to_file.write(
+                  ("Binary files %s and %s differ\n" %
+                  (from_label, to_label)).encode(self.path_encoding))
+        return self.CHANGED
+
+
+class DiffTree(object):
+    """Provides textual representations of the difference between two trees.
+
+    A DiffTree examines two trees and where a file-id has altered
+    between them, generates a textual representation of the difference.
+    DiffTree uses a sequence of DiffPath objects which are each
+    given the opportunity to handle a given altered fileid. The list
+    of DiffPath objects can be extended globally by appending to
+    DiffTree.diff_factories, or for a specific diff operation by
+    supplying the extra_factories option to the appropriate method.
+    """
+
+    # list of factories that can provide instances of DiffPath objects
+    # may be extended by plugins.
+    diff_factories = [DiffSymlink.from_diff_tree,
+                      DiffDirectory.from_diff_tree]
+
+    def __init__(self, old_tree, new_tree, to_file, path_encoding='utf-8',
+                 diff_text=None, extra_factories=None):
+        """Constructor
+
+        :param old_tree: Tree to show as old in the comparison
+        :param new_tree: Tree to show as new in the comparison
+        :param to_file: File to write comparision to
+        :param path_encoding: Character encoding to write paths in
+        :param diff_text: DiffPath-type object to use as a last resort for
+            diffing text files.
+        :param extra_factories: Factories of DiffPaths to try before any other
+            DiffPaths"""
+        if diff_text is None:
+            diff_text = DiffText(old_tree, new_tree, to_file, path_encoding,
+                                 '', '',  internal_diff)
+        self.old_tree = old_tree
+        self.new_tree = new_tree
+        self.to_file = to_file
+        self.path_encoding = path_encoding
+        self.differs = []
+        if extra_factories is not None:
+            self.differs.extend(f(self) for f in extra_factories)
+        self.differs.extend(f(self) for f in self.diff_factories)
+        self.differs.extend([diff_text, DiffKindChange.from_diff_tree(self)])
+
+    @classmethod
+    def from_trees_options(klass, old_tree, new_tree, to_file,
+                           path_encoding, external_diff_options, old_label,
+                           new_label):
+        """Factory for producing a DiffTree.
+
+        Designed to accept options used by show_diff_trees.
+        :param old_tree: The tree to show as old in the comparison
+        :param new_tree: The tree to show as new in the comparison
+        :param to_file: File to write comparisons to
+        :param path_encoding: Character encoding to use for writing paths
+        :param external_diff_options: If supplied, use the installed diff
+            binary to perform file comparison, using supplied options.
+        :param old_label: Prefix to use for old file labels
+        :param new_label: Prefix to use for new file labels
+        """
+        if external_diff_options:
+            assert isinstance(external_diff_options, basestring)
+            opts = external_diff_options.split()
+            def diff_file(olab, olines, nlab, nlines, to_file):
+                external_diff(olab, olines, nlab, nlines, to_file, opts)
+        else:
+            diff_file = internal_diff
+        diff_text = DiffText(old_tree, new_tree, to_file, path_encoding,
+                             old_label, new_label, diff_file)
+        return klass(old_tree, new_tree, to_file, path_encoding, diff_text)
+
+    def show_diff(self, specific_files, extra_trees=None):
+        """Write tree diff to self.to_file
+
+        :param sepecific_files: the specific files to compare (recursive)
+        :param extra_trees: extra trees to use for mapping paths to file_ids
+        """
+        # TODO: Generation of pseudo-diffs for added/deleted files could
+        # be usefully made into a much faster special case.
+
+        delta = self.new_tree.changes_from(self.old_tree,
+            specific_files=specific_files,
+            extra_trees=extra_trees, require_versioned=True)
+
+        has_changes = 0
+        for path, file_id, kind in delta.removed:
+            has_changes = 1
+            path_encoded = path.encode(self.path_encoding, "replace")
+            self.to_file.write("=== removed %s '%s'\n" % (kind, path_encoded))
+            self.diff(file_id, path, path)
+
+        for path, file_id, kind in delta.added:
+            has_changes = 1
+            path_encoded = path.encode(self.path_encoding, "replace")
+            self.to_file.write("=== added %s '%s'\n" % (kind, path_encoded))
+            self.diff(file_id, path, path)
+        for (old_path, new_path, file_id, kind,
+             text_modified, meta_modified) in delta.renamed:
+            has_changes = 1
+            prop_str = get_prop_change(meta_modified)
+            oldpath_encoded = old_path.encode(self.path_encoding, "replace")
+            newpath_encoded = new_path.encode(self.path_encoding, "replace")
+            self.to_file.write("=== renamed %s '%s' => '%s'%s\n" % (kind,
+                                oldpath_encoded, newpath_encoded, prop_str))
+            if text_modified:
+                self.diff(file_id, old_path, new_path)
+        for path, file_id, kind, text_modified, meta_modified in\
+            delta.modified:
+            has_changes = 1
+            prop_str = get_prop_change(meta_modified)
+            path_encoded = path.encode(self.path_encoding, "replace")
+            self.to_file.write("=== modified %s '%s'%s\n" % (kind,
+                                path_encoded, prop_str))
+            # The file may be in a different location in the old tree (because
+            # the containing dir was renamed, but the file itself was not)
+            if text_modified:
+                old_path = self.old_tree.id2path(file_id)
+                self.diff(file_id, old_path, path)
+        return has_changes
+
+    def diff(self, file_id, old_path, new_path):
+        """Perform a diff of a single file
+
+        :param file_id: file-id of the file
+        :param old_path: The path of the file in the old tree
+        :param new_path: The path of the file in the new tree
+        """
+        try:
+            old_kind = self.old_tree.kind(file_id)
+        except errors.NoSuchId:
+            old_kind = None
+        try:
+            new_kind = self.new_tree.kind(file_id)
+        except errors.NoSuchId:
+            new_kind = None
+
+        result = DiffPath._diff_many(self.differs, file_id, old_path,
+                                       new_path, old_kind, new_kind)
+        if result is DiffPath.CANNOT_DIFF:
+            error_path = new_path
+            if error_path is None:
+                error_path = old_path
+            raise errors.NoDiffFound(error_path)

=== modified file 'bzrlib/errors.py'
--- a/bzrlib/errors.py	2007-11-23 08:31:24 +0000
+++ b/bzrlib/errors.py	2007-11-27 14:38:38 +0000
@@ -1846,6 +1846,14 @@
         self.format = format
 
 
+class NoDiffFound(BzrError):
+
+    _fmt = 'Could not find an appropriate Differ for file "%(path)s"'
+
+    def __init__(self, path):
+        BzrError.__init__(self, path)
+
+
 class NoDiff(BzrError):
 
     _fmt = "Diff is not installed on this machine: %(msg)s"

=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py	2007-10-24 20:38:50 +0000
+++ b/bzrlib/inventory.py	2007-11-23 04:19:28 +0000
@@ -619,25 +619,19 @@
     def _diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
              output_to, reverse=False):
         """See InventoryEntry._diff."""
-        try:
-            from_text = tree.get_file(self.file_id).readlines()
-            if to_entry:
-                to_text = to_tree.get_file(to_entry.file_id).readlines()
-            else:
-                to_text = []
-            if not reverse:
-                text_diff(from_label, from_text,
-                          to_label, to_text, output_to)
-            else:
-                text_diff(to_label, to_text,
-                          from_label, from_text, output_to)
-        except errors.BinaryFile:
-            if reverse:
-                label_pair = (to_label, from_label)
-            else:
-                label_pair = (from_label, to_label)
-            output_to.write(
-                  ("Binary files %s and %s differ\n" % label_pair).encode('utf8'))
+        from bzrlib.diff import DiffText
+        from_file_id = self.file_id
+        if to_entry:
+            to_file_id = to_entry.file_id
+        else:
+            to_file_id = None
+        if reverse:
+            to_file_id, from_file_id = from_file_id, to_file_id
+            tree, to_tree = to_tree, tree
+            from_label, to_label = to_label, from_label
+        differ = DiffText(tree, to_tree, output_to, 'utf-8', '', '',
+                          text_diff)
+        return differ.diff_text(from_file_id, to_file_id, from_label, to_label)
 
     def has_text(self):
         """See InventoryEntry.has_text."""
@@ -735,19 +729,21 @@
     def _diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
              output_to, reverse=False):
         """See InventoryEntry._diff."""
-        from_text = self.symlink_target
+        from bzrlib.diff import DiffSymlink
+        old_target = self.symlink_target
         if to_entry is not None:
-            to_text = to_entry.symlink_target
-            if reverse:
-                temp = from_text
-                from_text = to_text
-                to_text = temp
-            output_to.write('=== target changed %r => %r\n' % (from_text, to_text))
-        else:
-            if not reverse:
-                output_to.write('=== target was %r\n' % self.symlink_target)
-            else:
-                output_to.write('=== target is %r\n' % self.symlink_target)
+            new_target = to_entry.symlink_target
+        else:
+            new_target = None
+        if not reverse:
+            old_tree = tree
+            new_tree = to_tree
+        else:
+            old_tree = to_tree
+            new_tree = tree
+            new_target, old_target = old_target, new_target
+        differ = DiffSymlink(old_tree, new_tree, output_to)
+        return differ.diff_symlink(old_target, new_target)
 
     def __init__(self, file_id, name, parent_id):
         super(InventoryLink, self).__init__(file_id, name, parent_id)

=== modified file 'bzrlib/tests/test_diff.py'
--- a/bzrlib/tests/test_diff.py	2007-09-04 09:10:35 +0000
+++ b/bzrlib/tests/test_diff.py	2007-11-25 21:52:24 +0000
@@ -20,7 +20,15 @@
 import subprocess
 from tempfile import TemporaryFile
 
-from bzrlib.diff import internal_diff, external_diff, show_diff_trees
+from bzrlib.diff import (
+    internal_diff,
+    external_diff,
+    DiffPath,
+    show_diff_trees,
+    DiffSymlink,
+    DiffTree,
+    DiffText,
+    )
 from bzrlib.errors import BinaryFile, NoDiff
 import bzrlib.osutils as osutils
 import bzrlib.patiencediff
@@ -544,6 +552,148 @@
         self.assertContainsRe(diff, "=== modified file 'mod_%s'"%autf8)
         self.assertContainsRe(diff, "=== removed file 'del_%s'"%autf8)
 
+
+class DiffWasIs(DiffPath):
+
+    def diff(self, file_id, old_path, new_path, old_kind, new_kind):
+        self.to_file.write('was: ')
+        self.to_file.write(self.old_tree.get_file(file_id).read())
+        self.to_file.write('is: ')
+        self.to_file.write(self.new_tree.get_file(file_id).read())
+        pass
+
+
+class TestDiffTree(TestCaseWithTransport):
+
+    def setUp(self):
+        TestCaseWithTransport.setUp(self)
+        self.old_tree = self.make_branch_and_tree('old-tree')
+        self.old_tree.lock_write()
+        self.addCleanup(self.old_tree.unlock)
+        self.new_tree = self.make_branch_and_tree('new-tree')
+        self.new_tree.lock_write()
+        self.addCleanup(self.new_tree.unlock)
+        self.differ = DiffTree(self.old_tree, self.new_tree, StringIO())
+
+    def test_diff_text(self):
+        self.build_tree_contents([('old-tree/olddir/',),
+                                  ('old-tree/olddir/oldfile', 'old\n')])
+        self.old_tree.add('olddir')
+        self.old_tree.add('olddir/oldfile', 'file-id')
+        self.build_tree_contents([('new-tree/newdir/',),
+                                  ('new-tree/newdir/newfile', 'new\n')])
+        self.new_tree.add('newdir')
+        self.new_tree.add('newdir/newfile', 'file-id')
+        differ = DiffText(self.old_tree, self.new_tree, StringIO())
+        differ.diff_text('file-id', None, 'old label', 'new label')
+        self.assertEqual(
+            '--- old label\n+++ new label\n@@ -1,1 +0,0 @@\n-old\n\n',
+            differ.to_file.getvalue())
+        differ.to_file.seek(0)
+        differ.diff_text(None, 'file-id', 'old label', 'new label')
+        self.assertEqual(
+            '--- old label\n+++ new label\n@@ -0,0 +1,1 @@\n+new\n\n',
+            differ.to_file.getvalue())
+        differ.to_file.seek(0)
+        differ.diff_text('file-id', 'file-id', 'old label', 'new label')
+        self.assertEqual(
+            '--- old label\n+++ new label\n@@ -1,1 +1,1 @@\n-old\n+new\n\n',
+            differ.to_file.getvalue())
+
+    def test_diff_symlink(self):
+        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
+        differ.diff_symlink('old target', None)
+        self.assertEqual("=== target was 'old target'\n",
+                         differ.to_file.getvalue())
+
+        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
+        differ.diff_symlink(None, 'new target')
+        self.assertEqual("=== target is 'new target'\n",
+                         differ.to_file.getvalue())
+
+        differ = DiffSymlink(self.old_tree, self.new_tree, StringIO())
+        differ.diff_symlink('old target', 'new target')
+        self.assertEqual("=== target changed 'old target' => 'new target'\n",
+                         differ.to_file.getvalue())
+
+    def test_diff(self):
+        self.build_tree_contents([('old-tree/olddir/',),
+                                  ('old-tree/olddir/oldfile', 'old\n')])
+        self.old_tree.add('olddir')
+        self.old_tree.add('olddir/oldfile', 'file-id')
+        self.build_tree_contents([('new-tree/newdir/',),
+                                  ('new-tree/newdir/newfile', 'new\n')])
+        self.new_tree.add('newdir')
+        self.new_tree.add('newdir/newfile', 'file-id')
+        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
+        self.assertContainsRe(
+            self.differ.to_file.getvalue(),
+            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
+             ' \@\@\n-old\n\+new\n\n')
+
+    def test_diff_kind_change(self):
+        self.build_tree_contents([('old-tree/olddir/',),
+                                  ('old-tree/olddir/oldfile', 'old\n')])
+        self.old_tree.add('olddir')
+        self.old_tree.add('olddir/oldfile', 'file-id')
+        self.build_tree(['new-tree/newdir/'])
+        os.symlink('new', 'new-tree/newdir/newfile')
+        self.new_tree.add('newdir')
+        self.new_tree.add('newdir/newfile', 'file-id')
+        self.differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
+        self.assertContainsRe(
+            self.differ.to_file.getvalue(),
+            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+0,0'
+             ' \@\@\n-old\n\n')
+        self.assertContainsRe(self.differ.to_file.getvalue(),
+                              "=== target is 'new'\n")
+
+    def test_diff_directory(self):
+        self.build_tree(['new-tree/new-dir/'])
+        self.new_tree.add('new-dir', 'new-dir-id')
+        self.differ.diff('new-dir-id', None, 'new-dir')
+        self.assertEqual(self.differ.to_file.getvalue(), '')
+
+    def create_old_new(self):
+        self.build_tree_contents([('old-tree/olddir/',),
+                                  ('old-tree/olddir/oldfile', 'old\n')])
+        self.old_tree.add('olddir')
+        self.old_tree.add('olddir/oldfile', 'file-id')
+        self.build_tree_contents([('new-tree/newdir/',),
+                                  ('new-tree/newdir/newfile', 'new\n')])
+        self.new_tree.add('newdir')
+        self.new_tree.add('newdir/newfile', 'file-id')
+
+    def test_register_diff(self):
+        self.create_old_new()
+        old_diff_factories = DiffTree.diff_factories
+        DiffTree.diff_factories=old_diff_factories[:]
+        DiffTree.diff_factories.insert(0, DiffWasIs.from_diff_tree)
+        try:
+            differ = DiffTree(self.old_tree, self.new_tree, StringIO())
+        finally:
+            DiffTree.diff_factories = old_diff_factories
+        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
+        self.assertNotContainsRe(
+            differ.to_file.getvalue(),
+            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
+             ' \@\@\n-old\n\+new\n\n')
+        self.assertContainsRe(differ.to_file.getvalue(),
+                              'was: old\nis: new\n')
+
+    def test_extra_factories(self):
+        self.create_old_new()
+        differ = DiffTree(self.old_tree, self.new_tree, StringIO(),
+                            extra_factories=[DiffWasIs.from_diff_tree])
+        differ.diff('file-id', 'olddir/oldfile', 'newdir/newfile')
+        self.assertNotContainsRe(
+            differ.to_file.getvalue(),
+            r'--- olddir/oldfile.*\n\+\+\+ newdir/newfile.*\n\@\@ -1,1 \+1,1'
+             ' \@\@\n-old\n\+new\n\n')
+        self.assertContainsRe(differ.to_file.getvalue(),
+                              'was: old\nis: new\n')
+
+
 class TestPatienceDiffLib(TestCase):
 
     def setUp(self):

=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py	2007-11-14 08:20:59 +0000
+++ b/bzrlib/workingtree_4.py	2007-11-24 00:12:42 +0000
@@ -1379,6 +1379,14 @@
     def get_root_id(self):
         return self.path2id('')
 
+    def id2path(self, file_id):
+        "Convert a file-id to a path."
+        entry = self._get_entry(file_id=file_id)
+        if entry == (None, None):
+            raise errors.NoSuchId(tree=self, file_id=file_id)
+        path_utf8 = osutils.pathjoin(entry[0][0], entry[0][1])
+        return path_utf8.decode('utf8')
+
     def _get_parent_index(self):
         """Return the index in the dirstate referenced by this tree."""
         return self._dirstate.get_parent_ids().index(self._revision_id) + 1
@@ -1506,8 +1514,10 @@
         return StringIO(self.get_file_text(file_id))
 
     def get_file_lines(self, file_id):
-        ie = self.inventory[file_id]
-        return self._get_weave(file_id).get_lines(ie.revision)
+        entry = self._get_entry(file_id=file_id)[1]
+        if entry == None:
+            raise errors.NoSuchId(tree=self, file_id=file_id)
+        return self._get_weave(file_id).get_lines(entry[1][4])
 
     def get_file_size(self, file_id):
         return self.inventory[file_id].text_size
@@ -1565,7 +1575,10 @@
         return bool(self.path2id(filename))
 
     def kind(self, file_id):
-        return self.inventory[file_id].kind
+        entry = self._get_entry(file_id=file_id)[1]
+        if entry == None:
+            raise errors.NoSuchId(tree=self, file_id=file_id)
+        return dirstate.DirState._minikind_to_kind[entry[1][0]]
 
     def path_content_summary(self, path):
         """See Tree.path_content_summary."""




More information about the bazaar-commits mailing list