Rev 3557: (jam) Implement _walkdirs_win32, in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Thu Jul 17 14:27:23 BST 2008


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

------------------------------------------------------------
revno: 3557
revision-id:pqm at pqm.ubuntu.com-20080717132712-1zbt1asfsuslh1v9
parent: pqm at pqm.ubuntu.com-20080717095800-b6c3hdb60qazu5am
parent: john at arbash-meinel.com-20080717125830-tvrs36uf3x223elx
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Thu 2008-07-17 14:27:12 +0100
message:
  (jam) Implement _walkdirs_win32,
  	going directly to Win32 apis improves status performance 2-6x
added:
  bzrlib/_walkdirs_win32.h       _walkdirs_win32.h-20080716220454-kweh3tgxez5dvw2l-1
  bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
  bzrlib/tests/test__walkdirs_win32.py test__walkdirs_win32-20080716220454-kweh3tgxez5dvw2l-3
modified:
  .bzrignore                     bzrignore-20050311232317-81f7b71efa2db11a
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
  setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
    ------------------------------------------------------------
    revno: 3504.4.15
    revision-id:john at arbash-meinel.com-20080717125830-tvrs36uf3x223elx
    parent: john at arbash-meinel.com-20080717125511-rjpil183ctky8l84
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Thu 2008-07-17 07:58:30 -0500
    message:
      Update NEWS with the performance improvements, and the 1.6b3 release
    modified:
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
    ------------------------------------------------------------
    revno: 3504.4.14
    revision-id:john at arbash-meinel.com-20080717125511-rjpil183ctky8l84
    parent: john at arbash-meinel.com-20080717122119-alnqlevrp4n3td2b
    parent: pqm at pqm.ubuntu.com-20080717095800-b6c3hdb60qazu5am
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Thu 2008-07-17 07:55:11 -0500
    message:
      Merge bzr.dev 3556
    removed:
      bzrlib/store/revision/__init__.py __init__.py-20060303014707-305238f06ae20dae
      bzrlib/store/revision/knit.py  knit.py-20060303020652-de5fa299e941a3c7
      bzrlib/store/revision/text.py  text.py-20060303020652-e49155f0da4d14ab
      bzrlib/tests/interversionedfile_implementations/ interversionedfile_implementations-20060301230427-f1f3ca8ddd5ff482
      bzrlib/tests/interversionedfile_implementations/__init__.py __init__.py-20060302012326-981af525594d02ed
      bzrlib/tests/interversionedfile_implementations/test_join.py test_join.py-20060302012326-9b5e9b0f0a03fedc
      bzrlib/tests/revisionstore_implementations/ revisionstore_implementations-20060303020702-1d2e36b63cef2706
      bzrlib/tests/revisionstore_implementations/__init__.py __init__.py-20060303020702-976c4186a0f99edb
      bzrlib/tests/revisionstore_implementations/test_all.py test_all.py-20060303020702-9b2d4c1d75407f31
      bzrlib/tests/test_escaped_store.py test_escaped_store.py-20060216023929-6bcb9a067344959f
    added:
      bzrlib/help_topics/en/patterns.txt patterns.txt-20080625070357-wx8qm46a19ejwfns-1
      bzrlib/help_topics/en/rules.txt rules.txt-20080516063844-ghr5l6pvvrhiycun-1
      bzrlib/push.py                 push.py-20080606021927-5fe39050e8xne9un-1
      bzrlib/rules.py                properties.py-20080506032617-9k06uqalkf09ck0z-1
      bzrlib/tests/branch_implementations/test_stacking.py test_stacking.py-20080214020755-msjlkb7urobwly0f-1
      bzrlib/tests/repository_implementations/test_add_fallback_repository.py test_add_fallback_re-20080215040003-8w9n4ck9uqdxj18m-1
      bzrlib/tests/test_rules.py     test_properties.py-20080506033501-3p9kmuob25dho8xl-1
      bzrlib/tests/tree_implementations/test_iter_search_rules.py test_iter_search_rul-20080528065532-1ml1ttb12az20cxf-1
      contrib/bash/bzrbashprompt.sh  bzrbashprompt.sh-20080414112733-b78chl4ubylc6775-1
      doc/en/user-guide/stacked.txt  stacked.txt-20080711023247-4uh9oovoka0sze8b-1
      tools/win32/run_script.py      run_script.py-20080717003927-k6itvarbtnwk44o9-1
    modified:
      Makefile                       Makefile-20050805140406-d96e3498bb61c5bb
      NEWS                           NEWS-20050323055033-4e00b5db738777ff
      bzr                            bzr.py-20050313053754-5485f144c7006fa6
      bzrlib/annotate.py             annotate.py-20050922133147-7c60541d2614f022
      bzrlib/branch.py               branch.py-20050309040759-e4baf4e0d046576e
      bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
      bzrlib/bundle/serializer/v4.py v10.py-20070611062757-5ggj7k18s9dej0fr-1
      bzrlib/bzrdir.py               bzrdir.py-20060131065624-156dfea39c4387cb
      bzrlib/check.py                check.py-20050309040759-f3a679400c06bcc1
      bzrlib/commands.py             bzr.py-20050309040720-d10f4714595cf8c3
      bzrlib/config.py               config.py-20051011043216-070c74f4e9e338e8
      bzrlib/directory_service.py    directory_service.py-20080305221044-vr2mkvlsk8jypa2y-1
      bzrlib/errors.py               errors.py-20050309040759-20512168c4e14fbd
      bzrlib/fetch.py                fetch.py-20050818234941-26fea6105696365d
      bzrlib/globbing.py             glob.py-20061113075651-q63o2v35fm2ydk9x-1
      bzrlib/graph.py                graph_walker.py-20070525030359-y852guab65d4wtn0-1
      bzrlib/help_topics/__init__.py help_topics.py-20060920210027-rnim90q9e0bwxvy4-1
      bzrlib/help_topics/en/hooks.txt hooks.txt-20070830033044-xxu2rced13f72dka-1
      bzrlib/ignores.py              ignores.py-20060712153832-2von9l0t7p43ixsv-1
      bzrlib/index.py                index.py-20070712131115-lolkarso50vjr64s-1
      bzrlib/info.py                 info.py-20050323235939-6bbfe7d9700b0b9b
      bzrlib/inventory.py            inventory.py-20050309040759-6648b84ca2005b37
      bzrlib/knit.py                 knit.py-20051212171256-f056ac8f0fbe1bd9
      bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
      bzrlib/mail_client.py          mail_client.py-20070809192806-vuxt3t19srtpjpdn-1
      bzrlib/memorytree.py           memorytree.py-20060906023413-4wlkalbdpsxi2r4y-1
      bzrlib/merge.py                merge.py-20050513021216-953b65a438527106
      bzrlib/multiparent.py          __init__.py-20070410133617-n1jdhcc1n1mibarp-1
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/reconcile.py            reweave_inventory.py-20051108164726-1e5e0934febac06e
      bzrlib/remote.py               remote.py-20060720103555-yeeg2x51vn0rbtdp-1
      bzrlib/repofmt/knitrepo.py     knitrepo.py-20070206081537-pyy4a00xdas0j4pf-1
      bzrlib/repofmt/pack_repo.py    pack_repo.py-20070813041115-gjv5ma7ktfqwsjgn-1
      bzrlib/repofmt/weaverepo.py    presplitout.py-20070125045333-wfav3tsh73oxu3zk-1
      bzrlib/repository.py           rev_storage.py-20051111201905-119e9401e46257e3
      bzrlib/revisiontree.py         revisiontree.py-20060724012533-bg8xyryhxd0o0i0h-1
      bzrlib/smart/branch.py         branch.py-20061124031907-mzh3pla28r83r97f-1
      bzrlib/smart/medium.py         medium.py-20061103051856-rgu2huy59fkz902q-1
      bzrlib/smart/repository.py     repository.py-20061128022038-vr5wy5bubyb8xttk-1
      bzrlib/smart/request.py        request.py-20061108095550-gunadhxmzkdjfeek-1
      bzrlib/smart/server.py         server.py-20061110062051-chzu10y32vx8gvur-1
      bzrlib/store/__init__.py       store.py-20050309040759-164dc5173d6406c2
      bzrlib/store/text.py           text.py-20050928201105-c26468dcb5d9b18b
      bzrlib/store/versioned/__init__.py weavestore.py-20050907094258-88262e0434babab9
      bzrlib/symbol_versioning.py    symbol_versioning.py-20060105104851-9ecf8af605d15a80
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      bzrlib/tests/blackbox/test_branch.py test_branch.py-20060524161337-noms9gmcwqqrfi8y-1
      bzrlib/tests/blackbox/test_check.py test_check.py-20071024054728-mn44rt3z5hnqcbke-1
      bzrlib/tests/blackbox/test_info.py test_info.py-20060215045507-bbdd2d34efab9e0a
      bzrlib/tests/blackbox/test_locale.py test_lang.py-20060824204205-80v50j25qkuop7yn-1
      bzrlib/tests/blackbox/test_log.py test_log.py-20060112090212-78f6ea560c868e24
      bzrlib/tests/blackbox/test_push.py test_push.py-20060329002750-929af230d5d22663
      bzrlib/tests/branch_implementations/__init__.py __init__.py-20060123013057-b12a52c3f361daf4
      bzrlib/tests/branch_implementations/test_branch.py testbranch.py-20050711070244-121d632bc37d7253
      bzrlib/tests/branch_implementations/test_hooks.py test_hooks.py-20070129154855-blhpwxmvjs07waei-1
      bzrlib/tests/bzrdir_implementations/__init__.py __init__.py-20060131065642-34c39b54f42dd048
      bzrlib/tests/bzrdir_implementations/test_bzrdir.py test_bzrdir.py-20060131065642-0ebeca5e30e30866
      bzrlib/tests/commands/test_push.py test_push.py-20070525122003-gc1ob0ea0nueoqgj-1
      bzrlib/tests/ftp_server.py     ftpserver.py-20071019102346-61jbvdkrr70igauv-1
      bzrlib/tests/interrepository_implementations/test_fetch.py test_fetch.py-20080425213627-j60cjh782ufm83ry-1
      bzrlib/tests/interrepository_implementations/test_interrepository.py test_interrepository.py-20060220061411-1ec13fa99e5e3eee
      bzrlib/tests/per_repository_reference/test_add_inventory.py test_add_inventory.p-20080220025549-nnm2s80it1lvcwnc-3
      bzrlib/tests/repository_implementations/__init__.py __init__.py-20060131092037-9564957a7d4a841b
      bzrlib/tests/repository_implementations/helpers.py helpers.py-20070924032407-m460yl9j5gu5ju85-2
      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/repository_implementations/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
      bzrlib/tests/repository_implementations/test_fetch.py test_fetch.py-20070814052151-5cxha9slx4c93uog-1
      bzrlib/tests/repository_implementations/test_reconcile.py test_reconcile.py-20060223022332-572ef70a3288e369
      bzrlib/tests/repository_implementations/test_repository.py test_repository.py-20060131092128-ad07f494f5c9d26c
      bzrlib/tests/repository_implementations/test_statistics.py test_statistics.py-20070203082432-6738e8fl0mm7ikre-1
      bzrlib/tests/test_branch.py    test_branch.py-20060116013032-97819aa07b8ab3b5
      bzrlib/tests/test_bundle.py    test.py-20050630184834-092aa401ab9f039c
      bzrlib/tests/test_bzrdir.py    test_bzrdir.py-20060131065654-deba40eef51cf220
      bzrlib/tests/test_config.py    testconfig.py-20051011041908-742d0c15d8d8c8eb
      bzrlib/tests/test_directory_service.py test_directory_servi-20080305221044-vr2mkvlsk8jypa2y-2
      bzrlib/tests/test_errors.py    test_errors.py-20060210110251-41aba2deddf936a8
      bzrlib/tests/test_fetch.py     testfetch.py-20050825090644-f73e07e7dfb1765a
      bzrlib/tests/test_globbing.py  test_glob.py-20061113075651-q63o2v35fm2ydk9x-2
      bzrlib/tests/test_graph.py     test_graph_walker.py-20070525030405-enq4r60hhi9xrujc-1
      bzrlib/tests/test_http_response.py test_http_response.py-20060628233143-950b2a482a32505d
      bzrlib/tests/test_ignores.py   test_ignores.py-20060712172354-vqq9ln0t8di27v53-1
      bzrlib/tests/test_knit.py      test_knit.py-20051212171302-95d4c00dd5f11f2b
      bzrlib/tests/test_log.py       testlog.py-20050728115707-1a514809d7d49309
      bzrlib/tests/test_merge.py     testmerge.py-20050905070950-c1b5aa49ff911024
      bzrlib/tests/test_merge_core.py test_merge_core.py-20050824132511-eb99b23a0eec641b
      bzrlib/tests/test_remote.py    test_remote.py-20060720103555-yeeg2x51vn0rbtdp-2
      bzrlib/tests/test_repository.py test_repository.py-20060131075918-65c555b881612f4d
      bzrlib/tests/test_selftest.py  test_selftest.py-20051202044319-c110a115d8c0456a
      bzrlib/tests/test_smart.py     test_smart.py-20061122024551-ol0l0o0oofsu9b3t-2
      bzrlib/tests/test_store.py     teststore.py-20050826022702-f6caadb647395769
      bzrlib/tests/test_transform.py test_transaction.py-20060105172520-b3ffb3946550e6c4
      bzrlib/tests/test_transport.py testtransport.py-20050718175618-e5cdb99f4555ddce
      bzrlib/tests/test_tsort.py     testtsort.py-20051025073946-27da871c394d5be4
      bzrlib/tests/test_upgrade.py   test_upgrade.py-20051004040251-555fe1d2bae1bc71
      bzrlib/tests/test_urlutils.py  test_urlutils.py-20060502192900-46b1f9579987cf9c
      bzrlib/tests/test_versionedfile.py test_versionedfile.py-20060222045249-db45c9ed14a1c2e5
      bzrlib/tests/test_weave.py     testknit.py-20050627023648-9833cc5562ffb785
      bzrlib/tests/tree_implementations/__init__.py __init__.py-20060717075546-420s7b0bj9hzeowi-2
      bzrlib/tests/tree_implementations/test_inv.py test_inv.py-20070312023226-0cdvk5uwhutis9vg-1
      bzrlib/tests/tree_implementations/test_tree.py test_tree.py-20061215160206-usu7lwcj8aq2n3br-1
      bzrlib/tests/workingtree_implementations/__init__.py __init__.py-20060203003124-b2aa5aca21a8bfad
      bzrlib/tests/workingtree_implementations/test_workingtree.py test_workingtree.py-20060203003124-817757d3e31444fb
      bzrlib/timestamp.py            timestamp.py-20070306142322-ttbb9oulf3jotljd-1
      bzrlib/trace.py                trace.py-20050309040759-c8ed824bdcd4748a
      bzrlib/transform.py            transform.py-20060105172343-dd99e54394d91687
      bzrlib/transport/__init__.py   transport.py-20050711165921-4978aa7ce1285ad5
      bzrlib/transport/ftp.py        ftp.py-20051116161804-58dc9506548c2a53
      bzrlib/transport/http/response.py _response.py-20060613154423-a2ci7hd4iw5c7fnt-1
      bzrlib/transport/local.py      local_transport.py-20050711165921-9b1f142bfe480c24
      bzrlib/transport/remote.py     ssh.py-20060608202016-c25gvf1ob7ypbus6-1
      bzrlib/transport/trace.py      trace.py-20070828055009-7kt0bbc4t4b92apz-1
      bzrlib/tree.py                 tree.py-20050309040759-9d5f2496be663e77
      bzrlib/tsort.py                tsort.py-20051025073946-7808f6aaf7d07208
      bzrlib/urlutils.py             urlutils.py-20060502195429-e8a161ecf8fac004
      bzrlib/versionedfile.py        versionedfile.py-20060222045106-5039c71ee3b65490
      bzrlib/weave.py                knit.py-20050627021749-759c29984154256b
      bzrlib/weave_commands.py       weave_commands.py-20060320231507-8e9f300bffc1aa19
      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/en/user-guide/browsing_history.txt browsing_history.txt-20071121073725-0corxykv5irjal00-2
      doc/en/user-guide/configuring_bazaar.txt configuring_bazaar.t-20071128000722-ncxiua259xwbdbg7-1
      doc/en/user-guide/index.txt    index.txt-20060622101119-tgwtdci8z769bjb9-2
      doc/en/user-guide/organizing_branches.txt organizing_branches.-20071123154453-dk2mjhrg1vpjm5w2-3
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
      tools/rst2html.py              rst2html.py-20060817120932-gn177u8v0008txhu-1
    ------------------------------------------------------------
    revno: 3504.4.13
    revision-id:john at arbash-meinel.com-20080717122119-alnqlevrp4n3td2b
    parent: john at arbash-meinel.com-20080717044957-xokssio0q76zy0q3
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Thu 2008-07-17 07:21:19 -0500
    message:
      Clean up according to review comments.
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
    ------------------------------------------------------------
    revno: 3504.4.12
    revision-id:john at arbash-meinel.com-20080717044957-xokssio0q76zy0q3
    parent: john at arbash-meinel.com-20080717043518-c1ncnoygo3ppew2f
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 23:49:57 -0500
    message:
      A couple small cleanups, make test_osutils more correct
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
    ------------------------------------------------------------
    revno: 3504.4.11
    revision-id:john at arbash-meinel.com-20080717043518-c1ncnoygo3ppew2f
    parent: john at arbash-meinel.com-20080717042644-rt8ofayxp8849t3s
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 23:35:18 -0500
    message:
      A bit more reorganizing.
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
    ------------------------------------------------------------
    revno: 3504.4.10
    revision-id:john at arbash-meinel.com-20080717042644-rt8ofayxp8849t3s
    parent: john at arbash-meinel.com-20080717040502-ql39j194cvqoy68o
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 23:26:44 -0500
    message:
      Move the helpers to be standalone, rather than members
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
    ------------------------------------------------------------
    revno: 3504.4.9
    revision-id:john at arbash-meinel.com-20080717040502-ql39j194cvqoy68o
    parent: john at arbash-meinel.com-20080717034613-3cqwmu9mfshqwyet
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 23:05:02 -0500
    message:
      Switch to using a cdef object with readonly attributes.
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
    ------------------------------------------------------------
    revno: 3504.4.8
    revision-id:john at arbash-meinel.com-20080717034613-3cqwmu9mfshqwyet
    parent: john at arbash-meinel.com-20080717024305-1odvs9kc7vqd3dum
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 22:46:13 -0500
    message:
      Some code cleanups.
      
      Remove extra comments.
      Use 64 bit integer math when possible.
      Use PyList_Append rather than foo.append()
      Use PyUnicode_AsUTF8String rather than codecs.encode()
      Make sure to raise an exception if the target directory doesn't exist.
      Seems to have made a significant performance impact.
    modified:
      .bzrignore                     bzrignore-20050311232317-81f7b71efa2db11a
      bzrlib/_walkdirs_win32.h       _walkdirs_win32.h-20080716220454-kweh3tgxez5dvw2l-1
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
      bzrlib/tests/test__walkdirs_win32.py test__walkdirs_win32-20080716220454-kweh3tgxez5dvw2l-3
    ------------------------------------------------------------
    revno: 3504.4.7
    revision-id:john at arbash-meinel.com-20080717024305-1odvs9kc7vqd3dum
    parent: john at arbash-meinel.com-20080717023713-832g08rsq7emxh8f
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 21:43:05 -0500
    message:
      Update the comment
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
    ------------------------------------------------------------
    revno: 3504.4.6
    revision-id:john at arbash-meinel.com-20080717023713-832g08rsq7emxh8f
    parent: john at arbash-meinel.com-20080717022133-hcd78dqy2qn60drx
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 21:37:13 -0500
    message:
      Start exposing the times on the stat, this now seems to be a complete walkdirs implementation.
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
    ------------------------------------------------------------
    revno: 3504.4.5
    revision-id:john at arbash-meinel.com-20080717022133-hcd78dqy2qn60drx
    parent: john at arbash-meinel.com-20080716232929-pcyg06005uxpveav
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 21:21:33 -0500
    message:
      Add tests to ensure that you can skip subdirs, start exposing the function.
    modified:
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/tests/test__walkdirs_win32.py test__walkdirs_win32-20080716220454-kweh3tgxez5dvw2l-3
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
    ------------------------------------------------------------
    revno: 3504.4.4
    revision-id:john at arbash-meinel.com-20080716232929-pcyg06005uxpveav
    parent: john at arbash-meinel.com-20080716220622-m6zsz00j08co7l5g
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 18:29:29 -0500
    message:
      We have walkdirs basically working, only without timestamps
    modified:
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/tests/test__walkdirs_win32.py test__walkdirs_win32-20080716220454-kweh3tgxez5dvw2l-3
    ------------------------------------------------------------
    revno: 3504.4.3
    revision-id:john at arbash-meinel.com-20080716220622-m6zsz00j08co7l5g
    parent: john at arbash-meinel.com-20080626211800-mb234d9wpgxklotf
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Wed 2008-07-16 17:06:22 -0500
    message:
      Start working on an extension specifically for win32,
      This will wrap the win32 FindFile code into nice objects for higher levels.
      Mostly, I'm cribbing the code from other places like posixmodule.c
      I'm doing it in Pyrex, though, so I get a couple conveniences, like
      not having to watch all of my allocations, etc.
      I might *want* to do that for performance before all is said and done,
      but for now, get it working.
      
      ATM, it just iterates, but doesn't actually work out any data.
    added:
      bzrlib/_walkdirs_win32.h       _walkdirs_win32.h-20080716220454-kweh3tgxez5dvw2l-1
      bzrlib/_walkdirs_win32.pyx     _walkdirs_win32.pyx-20080716220454-kweh3tgxez5dvw2l-2
      bzrlib/tests/test__walkdirs_win32.py test__walkdirs_win32-20080716220454-kweh3tgxez5dvw2l-3
    modified:
      .bzrignore                     bzrignore-20050311232317-81f7b71efa2db11a
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
      setup.py                       setup.py-20050314065409-02f8a0a6e3f9bc70
    ------------------------------------------------------------
    revno: 3504.4.2
    revision-id:john at arbash-meinel.com-20080626211800-mb234d9wpgxklotf
    parent: john at arbash-meinel.com-20080626164622-s0dpqlxzdybnmcb8
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Thu 2008-06-26 16:18:00 -0500
    message:
      Add a test case that shows the mtime is not being returned correctly.
    modified:
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
    ------------------------------------------------------------
    revno: 3504.4.1
    revision-id:john at arbash-meinel.com-20080626164622-s0dpqlxzdybnmcb8
    parent: pqm at pqm.ubuntu.com-20080619070027-3xv1vy81m3ix2oup
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: win32_find_files
    timestamp: Thu 2008-06-26 11:46:22 -0500
    message:
      Write an alternative 'walkdirs' implementation that uses win32 apis.
      
      Basically, calling nt.lstat() lots of times is really slow, when we can get the
      results right away from the FindFiles api.
      In my tests with ~9000 entries, it changes 'bzr status' from 4+s => 1.2s
    modified:
      bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
      bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
=== added file 'bzrlib/_walkdirs_win32.h'
--- a/bzrlib/_walkdirs_win32.h	1970-01-01 00:00:00 +0000
+++ b/bzrlib/_walkdirs_win32.h	2008-07-17 03:46:13 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2007 Canonical Ltd
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Header includes, etc for _walkdirs_win32
+ * Pyrex doesn't support #define, and defining WIN32_LEAN_AND_MEAN makes
+ * importing windows.h a lot less painful.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>

=== added file 'bzrlib/_walkdirs_win32.pyx'
--- a/bzrlib/_walkdirs_win32.pyx	1970-01-01 00:00:00 +0000
+++ b/bzrlib/_walkdirs_win32.pyx	2008-07-17 12:21:19 +0000
@@ -0,0 +1,283 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Helper functions for Walkdirs on win32."""
+
+
+cdef extern from "_walkdirs_win32.h":
+    cdef struct _HANDLE:
+        pass
+    ctypedef _HANDLE *HANDLE
+    ctypedef unsigned long DWORD
+    ctypedef long long __int64
+    ctypedef unsigned short WCHAR
+    cdef struct _FILETIME:
+        DWORD dwHighDateTime
+        DWORD dwLowDateTime
+    ctypedef _FILETIME FILETIME
+
+    cdef struct _WIN32_FIND_DATAW:
+        DWORD dwFileAttributes
+        FILETIME ftCreationTime
+        FILETIME ftLastAccessTime
+        FILETIME ftLastWriteTime
+        DWORD nFileSizeHigh
+        DWORD nFileSizeLow
+        # Some reserved stuff here
+        WCHAR cFileName[260] # MAX_PATH
+        WCHAR cAlternateFilename[14]
+
+    # We have to use the typedef trick, otherwise pyrex uses:
+    #  struct WIN32_FIND_DATAW
+    # which fails due to 'incomplete type'
+    ctypedef _WIN32_FIND_DATAW WIN32_FIND_DATAW
+
+    cdef HANDLE INVALID_HANDLE_VALUE
+    cdef HANDLE FindFirstFileW(WCHAR *path, WIN32_FIND_DATAW *data)
+    cdef int FindNextFileW(HANDLE search, WIN32_FIND_DATAW *data)
+    cdef int FindClose(HANDLE search)
+
+    cdef DWORD FILE_ATTRIBUTE_READONLY
+    cdef DWORD FILE_ATTRIBUTE_DIRECTORY
+    cdef int ERROR_NO_MORE_FILES
+
+    cdef int GetLastError()
+
+    # Wide character functions
+    DWORD wcslen(WCHAR *)
+
+
+cdef extern from "Python.h":
+    WCHAR *PyUnicode_AS_UNICODE(object)
+    Py_ssize_t PyUnicode_GET_SIZE(object)
+    object PyUnicode_FromUnicode(WCHAR *, Py_ssize_t)
+    int PyList_Append(object, object) except -1
+    object PyUnicode_AsUTF8String(object)
+
+
+import operator
+import stat
+
+from bzrlib import osutils
+
+
+cdef class _Win32Stat:
+    """Represent a 'stat' result generated from WIN32_FIND_DATA"""
+
+    cdef readonly int st_mode
+    cdef readonly double st_ctime
+    cdef readonly double st_mtime
+    cdef readonly double st_atime
+    cdef readonly __int64 st_size
+
+    # os.stat always returns 0, so we hard code it here
+    cdef readonly int st_dev
+    cdef readonly int st_ino
+
+    def __repr__(self):
+        """Repr is the same as a Stat object.
+
+        (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)
+        """
+        return repr((self.st_mode, 0, 0, 0, 0, 0, self.st_size, self.st_atime,
+                     self.st_mtime, self.st_ctime))
+
+
+cdef object _get_name(WIN32_FIND_DATAW *data):
+    """Extract the Unicode name for this file/dir."""
+    return PyUnicode_FromUnicode(data.cFileName,
+                                 wcslen(data.cFileName))
+
+
+cdef int _get_mode_bits(WIN32_FIND_DATAW *data):
+    cdef int mode_bits
+
+    mode_bits = 0100666 # writeable file, the most common
+    if data.dwFileAttributes & FILE_ATTRIBUTE_READONLY == FILE_ATTRIBUTE_READONLY:
+        mode_bits ^= 0222 # remove the write bits
+    if data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY:
+        # Remove the FILE bit, set the DIR bit, and set the EXEC bits
+        mode_bits ^= 0140111
+    return mode_bits
+
+
+cdef __int64 _get_size(WIN32_FIND_DATAW *data):
+    # Pyrex casts a DWORD into a PyLong anyway, so it is safe to do << 32
+    # on a DWORD
+    return ((<__int64>data.nFileSizeHigh) << 32) + data.nFileSizeLow
+
+
+cdef double _ftime_to_timestamp(FILETIME *ft):
+    """Convert from a FILETIME struct into a floating point timestamp.
+
+    The fields of a FILETIME structure are the hi and lo part
+    of a 64-bit value expressed in 100 nanosecond units.
+    1e7 is one second in such units; 1e-7 the inverse.
+    429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
+    It also uses the epoch 1601-01-01 rather than 1970-01-01
+    (taken from posixmodule.c)
+    """
+    cdef __int64 val
+    # NB: This gives slightly different results versus casting to a 64-bit
+    #     integer and doing integer math before casting into a floating
+    #     point number. But the difference is in the sub millisecond range,
+    #     which doesn't seem critical here.
+    # secs between epochs: 11,644,473,600
+    val = ((<__int64>ft.dwHighDateTime) << 32) + ft.dwLowDateTime
+    return (val * 1.0e-7) - 11644473600.0
+
+
+cdef int _should_skip(WIN32_FIND_DATAW *data):
+    """Is this '.' or '..' so we should skip it?"""
+    if (data.cFileName[0] != c'.'):
+        return 0
+    if data.cFileName[1] == c'\0':
+        return 1
+    if data.cFileName[1] == c'.' and data.cFileName[2] == c'\0':
+        return 1
+    return 0
+
+
+cdef class Win32Finder:
+    """A class which encapsulates the search of files in a given directory"""
+
+    cdef object _top
+    cdef object _prefix
+
+    cdef object _directory_kind
+    cdef object _file_kind
+
+    cdef object _pending
+    cdef object _last_dirblock
+
+    def __init__(self, top, prefix=""):
+        self._top = top
+        self._prefix = prefix
+
+        self._directory_kind = osutils._directory_kind
+        self._file_kind = osutils._formats[stat.S_IFREG]
+
+        self._pending = [(osutils.safe_utf8(prefix), osutils.safe_unicode(top))]
+        self._last_dirblock = None
+
+    def __iter__(self):
+        return self
+
+    cdef object _get_kind(self, WIN32_FIND_DATAW *data):
+        if data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY:
+            return self._directory_kind
+        return self._file_kind
+
+    cdef _Win32Stat _get_stat_value(self, WIN32_FIND_DATAW *data):
+        """Get the filename and the stat information."""
+        cdef _Win32Stat statvalue
+
+        statvalue = _Win32Stat()
+        statvalue.st_mode = _get_mode_bits(data)
+        statvalue.st_ctime = _ftime_to_timestamp(&data.ftCreationTime)
+        statvalue.st_mtime = _ftime_to_timestamp(&data.ftLastWriteTime)
+        statvalue.st_atime = _ftime_to_timestamp(&data.ftLastAccessTime)
+        statvalue.st_size = _get_size(data)
+        statvalue.st_ino = 0
+        statvalue.st_dev = 0
+        return statvalue
+
+    def _get_files_in(self, directory, relprefix):
+        cdef WIN32_FIND_DATAW search_data
+        cdef HANDLE hFindFile
+        cdef int last_err
+        cdef WCHAR *query
+        cdef int result
+
+        top_star = directory + '*'
+
+        dirblock = []
+
+        query = PyUnicode_AS_UNICODE(top_star)
+        hFindFile = FindFirstFileW(query, &search_data)
+        if hFindFile == INVALID_HANDLE_VALUE:
+            # Raise an exception? This path doesn't seem to exist
+            raise WindowsError(GetLastError(), top_star)
+
+        try:
+            result = 1
+            while result:
+                # Skip '.' and '..'
+                if _should_skip(&search_data):
+                    result = FindNextFileW(hFindFile, &search_data)
+                    continue
+                name_unicode = _get_name(&search_data)
+                name_utf8 = PyUnicode_AsUTF8String(name_unicode)
+                relpath = relprefix + name_utf8
+                abspath = directory + name_unicode
+                PyList_Append(dirblock, 
+                    (relpath, name_utf8, 
+                     self._get_kind(&search_data),
+                     self._get_stat_value(&search_data),
+                     abspath))
+
+                result = FindNextFileW(hFindFile, &search_data)
+            # FindNextFileW sets GetLastError() == ERROR_NO_MORE_FILES when it
+            # actually finishes. If we have anything else, then we have a
+            # genuine problem
+            last_err = GetLastError()
+            if last_err != ERROR_NO_MORE_FILES:
+                raise WindowsError(last_err)
+        finally:
+            result = FindClose(hFindFile)
+            if result == 0:
+                last_err = GetLastError()
+                pass
+        return dirblock
+
+    cdef _update_pending(self):
+        """If we had a result before, add the subdirs to pending."""
+        if self._last_dirblock is not None:
+            # push the entries left in the dirblock onto the pending queue
+            # we do this here, because we allow the user to modified the
+            # queue before the next iteration
+            for d in reversed(self._last_dirblock):
+                if d[2] == self._directory_kind:
+                    self._pending.append((d[0], d[-1]))
+            self._last_dirblock = None
+        
+    def __next__(self):
+        self._update_pending()
+        if not self._pending:
+            raise StopIteration()
+        relroot, top = self._pending.pop()
+        # NB: At the moment Pyrex doesn't support Unicode literals, which means
+        # that all of these string literals are going to be upcasted to Unicode
+        # at runtime... :(
+        # Maybe we could use unicode(x) during __init__?
+        if relroot:
+            relprefix = relroot + '/'
+        else:
+            relprefix = ''
+        top_slash = top + '/'
+
+        dirblock = self._get_files_in(top_slash, relprefix)
+        dirblock.sort(key=operator.itemgetter(1))
+        self._last_dirblock = dirblock
+        return (relroot, top), dirblock
+
+
+def _walkdirs_utf8_win32_find_file(top, prefix=""):
+    """Implement a version of walkdirs_utf8 for win32.
+
+    This uses the find files api to both list the files and to stat them.
+    """
+    return Win32Finder(top, prefix=prefix)

=== added file 'bzrlib/tests/test__walkdirs_win32.py'
--- a/bzrlib/tests/test__walkdirs_win32.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/test__walkdirs_win32.py	2008-07-17 03:46:13 +0000
@@ -0,0 +1,122 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+"""Tests for the win32 walkdir extension."""
+
+import errno
+
+from bzrlib import tests
+
+
+class _WalkdirsWin32Feature(tests.Feature):
+
+    def _probe(self):
+        try:
+            import bzrlib._walkdirs_win32
+        except ImportError:
+            return False
+        else:
+            return True
+
+    def feature_name(self):
+        return 'bzrlib._walkdirs_win32'
+
+WalkdirsWin32Feature = _WalkdirsWin32Feature()
+
+
+class TestWin32Finder(tests.TestCaseInTempDir):
+
+    _test_needs_features = [WalkdirsWin32Feature]
+
+    def setUp(self):
+        super(TestWin32Finder, self).setUp()
+        from bzrlib._walkdirs_win32 import (
+            _walkdirs_utf8_win32_find_file
+            )
+        self.walkdirs_utf8 = _walkdirs_utf8_win32_find_file
+
+    def _remove_stat_from_dirblock(self, dirblock):
+        return [info[:3] + info[4:] for info in dirblock]
+
+    def assertWalkdirs(self, expected, top, prefix=''):
+        finder = self.walkdirs_utf8(top, prefix=prefix)
+        result = []
+        for dirname, dirblock in finder:
+            result.append((dirname, self._remove_stat_from_dirblock(dirblock)))
+        self.assertEqual(expected, result)
+
+    def test_empty_directory(self):
+        self.assertWalkdirs([(('', u'.'), [])], u'.')
+
+    def test_file_in_dir(self):
+        self.build_tree(['foo'])
+        self.assertWalkdirs([
+            (('', u'.'), [('foo', 'foo', 'file', u'./foo')])
+            ], u'.')
+
+    def test_subdir(self):
+        self.build_tree(['foo', 'bar/', 'bar/baz'])
+        self.assertWalkdirs([
+            (('', u'.'), [('bar', 'bar', 'directory', u'./bar'),
+                          ('foo', 'foo', 'file', u'./foo'),
+                         ]),
+            (('bar', u'./bar'), [('bar/baz', 'baz', 'file', u'./bar/baz')]),
+            ], '.')
+        self.assertWalkdirs([
+            (('xxx', u'.'), [('xxx/bar', 'bar', 'directory', u'./bar'),
+                             ('xxx/foo', 'foo', 'file', u'./foo'),
+                            ]),
+            (('xxx/bar', u'./bar'), [('xxx/bar/baz', 'baz', 'file', u'./bar/baz')]),
+            ], '.', prefix='xxx')
+        self.assertWalkdirs([
+            (('', u'bar'), [('baz', 'baz', 'file', u'bar/baz')]),
+            ], 'bar')
+
+    def test_skip_subdir(self): 
+        self.build_tree(['a/', 'b/', 'c/', 'a/aa', 'b/bb', 'c/cc'])
+        base_dirblock = [('a', 'a', 'directory', u'./a'),
+                          ('b', 'b', 'directory', u'./b'),
+                          ('c', 'c', 'directory', u'./c'),
+                         ]
+        self.assertWalkdirs([
+            (('', u'.'), base_dirblock),
+            (('a', u'./a'), [('a/aa', 'aa', 'file', u'./a/aa')]),
+            (('b', u'./b'), [('b/bb', 'bb', 'file', u'./b/bb')]),
+            (('c', u'./c'), [('c/cc', 'cc', 'file', u'./c/cc')]),
+            ], '.')
+
+        walker = self.walkdirs_utf8('.')
+        dir_info, first_dirblock = walker.next()
+        self.assertEqual(('', u'.'), dir_info)
+        self.assertEqual(base_dirblock,
+                         self._remove_stat_from_dirblock(first_dirblock))
+        # Now, remove 'b' and it should be skipped on the next round
+        del first_dirblock[1]
+        dir_info, second_dirblock = walker.next()
+        second_dirblock = self._remove_stat_from_dirblock(second_dirblock)
+        self.assertEqual(('a', u'./a'), dir_info)
+        self.assertEqual([('a/aa', 'aa', 'file', u'./a/aa')], second_dirblock)
+        dir_info, third_dirblock = walker.next()
+        third_dirblock = self._remove_stat_from_dirblock(third_dirblock)
+        self.assertEqual(('c', u'./c'), dir_info)
+        self.assertEqual([('c/cc', 'cc', 'file', u'./c/cc')], third_dirblock)
+
+    def test_missing_dir(self):
+        e = self.assertRaises(WindowsError, list,
+                                self.walkdirs_utf8(u'no_such_dir'))
+        self.assertEqual(errno.ENOENT, e.errno)
+        self.assertEqual(3, e.winerror)
+        self.assertEqual((3, u'no_such_dir/*'), e.args)

=== modified file '.bzrignore'
--- a/.bzrignore	2008-02-18 21:17:42 +0000
+++ b/.bzrignore	2008-07-17 03:46:13 +0000
@@ -40,6 +40,7 @@
 doc/developers/performance.png
 bzrlib/_dirstate_helpers_c.c
 bzrlib/_knit_load_data_c.c
+bzrlib/_walkdirs_win32.c
 doc/en/release-notes/NEWS.txt
 doc/en/developer-guide/HACKING.txt
 doc/en/user-reference/bzr_man.txt

=== modified file 'NEWS'
--- a/NEWS	2008-07-17 09:58:00 +0000
+++ b/NEWS	2008-07-17 12:58:30 +0000
@@ -10,6 +10,39 @@
 
   FEATURES:
 
+
+  IMPROVEMENTS:
+
+    * Implemented a custom ``walkdirs_utf8`` implementation for win32.
+      This uses a pyrex extension to get direct access to the
+      ``FindFirstFileW`` style apis, rather than using ``listdir`` +
+      ``lstat``. Shows a very strong improvement in commands like
+      ``status`` and ``diff`` which have to iterate the working tree.
+      Anywhere from 2x-6x faster depending on the size of the tree (bigger
+      trees, bigger benefit.) (John Arbash Meinel)
+
+
+  BUG FIXES:
+
+
+  DOCUMENTATION:
+
+
+  TESTING:
+
+
+  API CHANGES:
+
+
+  INTERNALS:
+
+
+
+bzr 1.6beta3 2008-07-17
+-----------------------
+
+  FEATURES:
+
     * New ``pre_change_branch_tip`` hook that is called before the
       branch tip is moved, while the branch is write-locked.  See the User
       Reference for signature details.  (Andrew Bennetts)

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2008-06-26 17:18:55 +0000
+++ b/bzrlib/osutils.py	2008-07-17 12:55:11 +0000
@@ -53,6 +53,7 @@
     )
 """)
 
+
 import bzrlib
 from bzrlib import symbol_versioning
 from bzrlib.symbol_versioning import (
@@ -1193,8 +1194,14 @@
         pass to os functions to affect the file in question. (such as os.lstat)
     """
     fs_encoding = _fs_enc.upper()
-    if (sys.platform == 'win32' or
-        fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968')): # ascii
+    if sys.platform == 'win32':
+        try:
+            from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+        except ImportError:
+            return _walkdirs_unicode_to_utf8(top, prefix=prefix)
+        else:
+            return _walkdirs_utf8_win32_find_file(top, prefix=prefix)
+    if fs_encoding not in ('UTF-8', 'US-ASCII', 'ANSI_X3.4-1968'): # ascii
         return _walkdirs_unicode_to_utf8(top, prefix=prefix)
     else:
         return _walkdirs_fs_utf8(top, prefix=prefix)

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2008-07-14 07:47:45 +0000
+++ b/bzrlib/tests/__init__.py	2008-07-17 12:55:11 +0000
@@ -2796,6 +2796,7 @@
                    'bzrlib.tests.test_versionedfile',
                    'bzrlib.tests.test_version',
                    'bzrlib.tests.test_version_info',
+                   'bzrlib.tests.test__walkdirs_win32',
                    'bzrlib.tests.test_weave',
                    'bzrlib.tests.test_whitebox',
                    'bzrlib.tests.test_win32utils',

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2008-06-11 03:56:46 +0000
+++ b/bzrlib/tests/test_osutils.py	2008-07-17 12:21:19 +0000
@@ -16,16 +16,19 @@
 
 """Tests for the osutils wrapper."""
 
+from cStringIO import StringIO
 import errno
 import os
 import socket
 import stat
 import sys
+import time
 
 import bzrlib
 from bzrlib import (
     errors,
     osutils,
+    tests,
     win32utils,
     )
 from bzrlib.errors import BzrBadParameterNotUnicode, InvalidURL
@@ -46,7 +49,8 @@
 from bzrlib.tests.file_utils import (
     FakeReadFile,
     )
-from cStringIO import StringIO
+from bzrlib.tests.test__walkdirs_win32 import WalkdirsWin32Feature
+
 
 class TestOSUtils(TestCaseInTempDir):
 
@@ -974,6 +978,99 @@
         self._filter_out_stat(result)
         self.assertEqual(expected_dirblocks, result)
 
+    def test__walkdirs_utf_win32_find_file(self):
+        self.requireFeature(WalkdirsWin32Feature)
+        self.requireFeature(tests.UnicodeFilenameFeature)
+        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+        name0u = u'0file-\xb6'
+        name1u = u'1dir-\u062c\u0648'
+        name2u = u'2file-\u0633'
+        tree = [
+            name0u,
+            name1u + '/',
+            name1u + '/' + name0u,
+            name1u + '/' + name1u + '/',
+            name2u,
+            ]
+        self.build_tree(tree)
+        name0 = name0u.encode('utf8')
+        name1 = name1u.encode('utf8')
+        name2 = name2u.encode('utf8')
+
+        # All of the abspaths should be in unicode, all of the relative paths
+        # should be in utf8
+        expected_dirblocks = [
+                (('', '.'),
+                 [(name0, name0, 'file', './' + name0u),
+                  (name1, name1, 'directory', './' + name1u),
+                  (name2, name2, 'file', './' + name2u),
+                 ]
+                ),
+                ((name1, './' + name1u),
+                 [(name1 + '/' + name0, name0, 'file', './' + name1u
+                                                        + '/' + name0u),
+                  (name1 + '/' + name1, name1, 'directory', './' + name1u
+                                                            + '/' + name1u),
+                 ]
+                ),
+                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
+                 [
+                 ]
+                ),
+            ]
+        result = list(_walkdirs_utf8_win32_find_file(u'.'))
+        self._filter_out_stat(result)
+        self.assertEqual(expected_dirblocks, result)
+
+    def assertStatIsCorrect(self, path, win32stat):
+        os_stat = os.stat(path)
+        self.assertEqual(os_stat.st_size, win32stat.st_size)
+        self.assertAlmostEqual(os_stat.st_mtime, win32stat.st_mtime, places=4)
+        self.assertAlmostEqual(os_stat.st_ctime, win32stat.st_ctime, places=4)
+        self.assertAlmostEqual(os_stat.st_atime, win32stat.st_atime, places=4)
+        self.assertEqual(os_stat.st_dev, win32stat.st_dev)
+        self.assertEqual(os_stat.st_ino, win32stat.st_ino)
+        self.assertEqual(os_stat.st_mode, win32stat.st_mode)
+
+    def test__walkdirs_utf_win32_find_file_stat_file(self):
+        """make sure our Stat values are valid"""
+        self.requireFeature(WalkdirsWin32Feature)
+        self.requireFeature(tests.UnicodeFilenameFeature)
+        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+        name0u = u'0file-\xb6'
+        name0 = name0u.encode('utf8')
+        self.build_tree([name0u])
+        # I hate to sleep() here, but I'm trying to make the ctime different
+        # from the mtime
+        time.sleep(2)
+        f = open(name0u, 'ab')
+        try:
+            f.write('just a small update')
+        finally:
+            f.close()
+
+        result = list(_walkdirs_utf8_win32_find_file(u'.'))
+        entry = result[0][1][0]
+        self.assertEqual((name0, name0, 'file'), entry[:3])
+        self.assertEqual(u'./' + name0u, entry[4])
+        self.assertStatIsCorrect(entry[4], entry[3])
+        self.assertNotEqual(entry[3].st_mtime, entry[3].st_ctime)
+
+    def test__walkdirs_utf_win32_find_file_stat_directory(self):
+        """make sure our Stat values are valid"""
+        self.requireFeature(WalkdirsWin32Feature)
+        self.requireFeature(tests.UnicodeFilenameFeature)
+        from bzrlib._walkdirs_win32 import _walkdirs_utf8_win32_find_file
+        name0u = u'0dir-\u062c\u0648'
+        name0 = name0u.encode('utf8')
+        self.build_tree([name0u + '/'])
+
+        result = list(_walkdirs_utf8_win32_find_file(u'.'))
+        entry = result[0][1][0]
+        self.assertEqual((name0, name0, 'directory'), entry[:3])
+        self.assertEqual(u'./' + name0u, entry[4])
+        self.assertStatIsCorrect(entry[4], entry[3])
+
     def assertPathCompare(self, path_less, path_greater):
         """check that path_less and path_greater compare correctly."""
         self.assertEqual(0, osutils.compare_paths_prefix_order(

=== modified file 'setup.py'
--- a/setup.py	2008-07-02 16:52:12 +0000
+++ b/setup.py	2008-07-17 12:55:11 +0000
@@ -226,6 +226,8 @@
 
 add_pyrex_extension('bzrlib._dirstate_helpers_c')
 add_pyrex_extension('bzrlib._knit_load_data_c')
+if sys.platform == 'win32':
+    add_pyrex_extension('bzrlib._walkdirs_win32')
 ext_modules.append(Extension('bzrlib._patiencediff_c', ['bzrlib/_patiencediff_c.c']))
 
 




More information about the bazaar-commits mailing list