Merge lp:~vila/bzr/552922-plugins-at into lp:bzr/2.2

Proposed by Vincent Ladeuil
Status: Merged
Merged at revision: not available
Proposed branch: lp:~vila/bzr/552922-plugins-at
Merge into: lp:bzr/2.2
Diff against target: 8039 lines (+2585/-1104)
269 files modified
.testr.conf (+3/-0)
NEWS (+207/-41)
NEWS-template.txt (+31/-0)
bzrlib/_annotator_pyx.pyx (+1/-1)
bzrlib/_bencode_pyx.pyx (+1/-1)
bzrlib/_btree_serializer_py.py (+1/-1)
bzrlib/_btree_serializer_pyx.pyx (+1/-1)
bzrlib/_chk_map_py.py (+1/-1)
bzrlib/_chk_map_pyx.pyx (+1/-1)
bzrlib/_groupcompress_pyx.pyx (+1/-1)
bzrlib/_knit_load_data_pyx.pyx (+1/-1)
bzrlib/_known_graph_py.py (+1/-1)
bzrlib/_known_graph_pyx.pyx (+1/-1)
bzrlib/_readdir_pyx.pyx (+1/-1)
bzrlib/_rio_pyx.pyx (+1/-1)
bzrlib/_simple_set_pyx.pxd (+1/-1)
bzrlib/_simple_set_pyx.pyx (+1/-1)
bzrlib/_static_tuple_c.c (+1/-1)
bzrlib/_static_tuple_c.pxd (+1/-1)
bzrlib/_static_tuple_py.py (+1/-1)
bzrlib/_walkdirs_win32.pyx (+1/-1)
bzrlib/atomicfile.py (+1/-1)
bzrlib/benchmarks/bench_dirstate.py (+1/-1)
bzrlib/benchmarks/tree_creator/kernel_like.py (+2/-1)
bzrlib/branch.py (+47/-37)
bzrlib/branchbuilder.py (+8/-5)
bzrlib/btree_index.py (+1/-1)
bzrlib/bugtracker.py (+1/-1)
bzrlib/builtins.py (+46/-35)
bzrlib/bundle/__init__.py (+1/-1)
bzrlib/bzrdir.py (+44/-23)
bzrlib/chk_serializer.py (+1/-1)
bzrlib/cleanup.py (+1/-1)
bzrlib/cmd_version_info.py (+1/-1)
bzrlib/cmdline.py (+8/-8)
bzrlib/commands.py (+33/-23)
bzrlib/commit.py (+1/-1)
bzrlib/conflicts.py (+35/-7)
bzrlib/decorators.py (+1/-1)
bzrlib/delta.py (+1/-1)
bzrlib/diff.py (+1/-1)
bzrlib/doc_generate/autodoc_rstx.py (+1/-1)
bzrlib/errors.py (+12/-2)
bzrlib/export/__init__.py (+10/-5)
bzrlib/export/dir_exporter.py (+7/-3)
bzrlib/export/tar_exporter.py (+17/-10)
bzrlib/export/zip_exporter.py (+10/-5)
bzrlib/globbing.py (+1/-1)
bzrlib/graph.py (+1/-1)
bzrlib/groupcompress.py (+1/-1)
bzrlib/help.py (+1/-1)
bzrlib/help_topics/en/authentication.txt (+4/-4)
bzrlib/help_topics/en/configuration.txt (+43/-1)
bzrlib/hooks.py (+1/-1)
bzrlib/index.py (+1/-1)
bzrlib/info.py (+1/-1)
bzrlib/inventory.py (+1/-1)
bzrlib/lockdir.py (+19/-8)
bzrlib/merge.py (+2/-1)
bzrlib/merge_directive.py (+1/-1)
bzrlib/msgeditor.py (+1/-1)
bzrlib/osutils.py (+85/-9)
bzrlib/patches.py (+54/-9)
bzrlib/plugin.py (+181/-69)
bzrlib/plugins/launchpad/__init__.py (+2/-2)
bzrlib/plugins/launchpad/lp_api.py (+1/-1)
bzrlib/plugins/launchpad/lp_directory.py (+1/-1)
bzrlib/plugins/launchpad/test_lp_api.py (+1/-1)
bzrlib/plugins/launchpad/test_lp_directory.py (+1/-1)
bzrlib/plugins/launchpad/test_lp_open.py (+1/-1)
bzrlib/progress.py (+0/-5)
bzrlib/reconcile.py (+1/-1)
bzrlib/reconfigure.py (+1/-1)
bzrlib/remote.py (+39/-27)
bzrlib/revisionspec.py (+1/-1)
bzrlib/revisiontree.py (+1/-1)
bzrlib/serializer.py (+1/-1)
bzrlib/shellcomplete.py (+1/-1)
bzrlib/smart/bzrdir.py (+1/-1)
bzrlib/smart/client.py (+1/-1)
bzrlib/smart/medium.py (+1/-1)
bzrlib/smart/protocol.py (+1/-1)
bzrlib/smart/repository.py (+1/-1)
bzrlib/smart/request.py (+1/-1)
bzrlib/smart/server.py (+1/-1)
bzrlib/smart/vfs.py (+1/-1)
bzrlib/static_tuple.py (+1/-1)
bzrlib/status.py (+1/-1)
bzrlib/switch.py (+1/-1)
bzrlib/tests/TestUtil.py (+1/-1)
bzrlib/tests/__init__.py (+29/-1)
bzrlib/tests/blackbox/test_annotate.py (+1/-1)
bzrlib/tests/blackbox/test_branch.py (+1/-1)
bzrlib/tests/blackbox/test_break_lock.py (+1/-1)
bzrlib/tests/blackbox/test_cat.py (+1/-1)
bzrlib/tests/blackbox/test_checkout.py (+1/-1)
bzrlib/tests/blackbox/test_debug.py (+1/-1)
bzrlib/tests/blackbox/test_exceptions.py (+1/-1)
bzrlib/tests/blackbox/test_export.py (+11/-1)
bzrlib/tests/blackbox/test_filtered_view_ops.py (+1/-1)
bzrlib/tests/blackbox/test_help.py (+1/-1)
bzrlib/tests/blackbox/test_ignore.py (+1/-1)
bzrlib/tests/blackbox/test_info.py (+2/-1)
bzrlib/tests/blackbox/test_init.py (+1/-1)
bzrlib/tests/blackbox/test_ls.py (+1/-1)
bzrlib/tests/blackbox/test_merge.py (+1/-1)
bzrlib/tests/blackbox/test_mv.py (+1/-1)
bzrlib/tests/blackbox/test_nick.py (+19/-19)
bzrlib/tests/blackbox/test_non_ascii.py (+1/-1)
bzrlib/tests/blackbox/test_pull.py (+1/-1)
bzrlib/tests/blackbox/test_push.py (+1/-1)
bzrlib/tests/blackbox/test_remerge.py (+1/-1)
bzrlib/tests/blackbox/test_send.py (+1/-1)
bzrlib/tests/blackbox/test_serve.py (+1/-1)
bzrlib/tests/blackbox/test_shared_repository.py (+1/-1)
bzrlib/tests/blackbox/test_shelve.py (+1/-1)
bzrlib/tests/blackbox/test_status.py (+2/-1)
bzrlib/tests/blackbox/test_switch.py (+1/-1)
bzrlib/tests/blackbox/test_too_much.py (+1/-1)
bzrlib/tests/blackbox/test_uncommit.py (+1/-1)
bzrlib/tests/blackbox/test_update.py (+4/-3)
bzrlib/tests/blackbox/test_versioning.py (+19/-6)
bzrlib/tests/commands/test_branch.py (+1/-1)
bzrlib/tests/commands/test_cat.py (+1/-1)
bzrlib/tests/commands/test_checkout.py (+1/-1)
bzrlib/tests/commands/test_commit.py (+2/-3)
bzrlib/tests/commands/test_init.py (+1/-1)
bzrlib/tests/commands/test_init_repository.py (+1/-1)
bzrlib/tests/commands/test_merge.py (+1/-1)
bzrlib/tests/commands/test_missing.py (+1/-1)
bzrlib/tests/commands/test_pull.py (+1/-1)
bzrlib/tests/commands/test_push.py (+1/-1)
bzrlib/tests/commands/test_update.py (+1/-1)
bzrlib/tests/ftp_server/__init__.py (+1/-1)
bzrlib/tests/ftp_server/medusa_based.py (+1/-1)
bzrlib/tests/ftp_server/pyftpdlib_based.py (+1/-1)
bzrlib/tests/http_server.py (+1/-1)
bzrlib/tests/http_utils.py (+1/-1)
bzrlib/tests/per_branch/test_branch.py (+17/-0)
bzrlib/tests/per_branch/test_iter_merge_sorted_revisions.py (+1/-1)
bzrlib/tests/per_branch/test_parent.py (+1/-1)
bzrlib/tests/per_bzrdir/test_bzrdir.py (+39/-11)
bzrlib/tests/per_foreign_vcs/__init__.py (+1/-1)
bzrlib/tests/per_foreign_vcs/test_repository.py (+1/-1)
bzrlib/tests/per_interbranch/test_push.py (+1/-1)
bzrlib/tests/per_intertree/__init__.py (+1/-1)
bzrlib/tests/per_pack_repository.py (+1/-1)
bzrlib/tests/per_repository/test_check.py (+1/-1)
bzrlib/tests/per_repository/test_check_reconcile.py (+1/-1)
bzrlib/tests/per_repository_reference/test_check.py (+1/-1)
bzrlib/tests/per_transport.py (+47/-1)
bzrlib/tests/per_tree/test_get_file_with_stat.py (+1/-1)
bzrlib/tests/per_tree/test_iter_search_rules.py (+1/-1)
bzrlib/tests/per_tree/test_path_content_summary.py (+1/-1)
bzrlib/tests/per_tree/test_revision_tree.py (+9/-6)
bzrlib/tests/per_workingtree/test_content_filters.py (+1/-1)
bzrlib/tests/per_workingtree/test_is_ignored.py (+1/-1)
bzrlib/tests/per_workingtree/test_revision_tree.py (+57/-6)
bzrlib/tests/per_workingtree/test_workingtree.py (+6/-3)
bzrlib/tests/script.py (+1/-1)
bzrlib/tests/stub_sftp.py (+9/-7)
bzrlib/tests/test__annotator.py (+1/-1)
bzrlib/tests/test__bencode.py (+1/-1)
bzrlib/tests/test__chk_map.py (+1/-1)
bzrlib/tests/test__chunks_to_lines.py (+1/-1)
bzrlib/tests/test__dirstate_helpers.py (+1/-1)
bzrlib/tests/test__groupcompress.py (+1/-1)
bzrlib/tests/test__known_graph.py (+1/-1)
bzrlib/tests/test__rio.py (+1/-1)
bzrlib/tests/test__simple_set.py (+1/-1)
bzrlib/tests/test__static_tuple.py (+1/-1)
bzrlib/tests/test__walkdirs_win32.py (+1/-1)
bzrlib/tests/test_branch.py (+4/-4)
bzrlib/tests/test_branchbuilder.py (+9/-0)
bzrlib/tests/test_btree_index.py (+1/-1)
bzrlib/tests/test_bzrdir.py (+7/-3)
bzrlib/tests/test_cleanup.py (+1/-1)
bzrlib/tests/test_cmdline.py (+1/-1)
bzrlib/tests/test_commands.py (+32/-11)
bzrlib/tests/test_commit.py (+1/-1)
bzrlib/tests/test_config.py (+1/-1)
bzrlib/tests/test_conflicts.py (+115/-52)
bzrlib/tests/test_diff.py (+1/-1)
bzrlib/tests/test_directory_service.py (+1/-1)
bzrlib/tests/test_errors.py (+1/-1)
bzrlib/tests/test_export.py (+22/-1)
bzrlib/tests/test_fetch.py (+1/-84)
bzrlib/tests/test_foreign.py (+6/-4)
bzrlib/tests/test_ftp_transport.py (+19/-1)
bzrlib/tests/test_globbing.py (+1/-1)
bzrlib/tests/test_graph.py (+1/-1)
bzrlib/tests/test_groupcompress.py (+1/-1)
bzrlib/tests/test_hooks.py (+1/-1)
bzrlib/tests/test_http_response.py (+1/-1)
bzrlib/tests/test_ignores.py (+1/-1)
bzrlib/tests/test_index.py (+1/-1)
bzrlib/tests/test_info.py (+1/-1)
bzrlib/tests/test_knit.py (+1/-1)
bzrlib/tests/test_lockable_files.py (+1/-1)
bzrlib/tests/test_lockdir.py (+20/-1)
bzrlib/tests/test_log.py (+1/-1)
bzrlib/tests/test_merge.py (+5/-0)
bzrlib/tests/test_merge_core.py (+19/-3)
bzrlib/tests/test_msgeditor.py (+1/-1)
bzrlib/tests/test_patches.py (+9/-2)
bzrlib/tests/test_plugins.py (+270/-96)
bzrlib/tests/test_progress.py (+1/-1)
bzrlib/tests/test_remote.py (+1/-1)
bzrlib/tests/test_revisionspec.py (+1/-1)
bzrlib/tests/test_revisiontree.py (+1/-1)
bzrlib/tests/test_script.py (+1/-1)
bzrlib/tests/test_shelf_ui.py (+1/-1)
bzrlib/tests/test_smart.py (+1/-1)
bzrlib/tests/test_source.py (+1/-1)
bzrlib/tests/test_ssh_transport.py (+1/-1)
bzrlib/tests/test_trace.py (+22/-1)
bzrlib/tests/test_transport_log.py (+1/-1)
bzrlib/tests/test_urlutils.py (+1/-1)
bzrlib/tests/test_version.py (+1/-1)
bzrlib/tests/test_win32utils.py (+1/-1)
bzrlib/tests/test_xml.py (+1/-1)
bzrlib/tests/transport_util.py (+1/-1)
bzrlib/trace.py (+1/-1)
bzrlib/transport/__init__.py (+14/-2)
bzrlib/transport/chroot.py (+1/-1)
bzrlib/transport/decorator.py (+1/-1)
bzrlib/transport/ftp/__init__.py (+21/-15)
bzrlib/transport/http/__init__.py (+1/-1)
bzrlib/transport/http/_urllib.py (+1/-1)
bzrlib/transport/http/_urllib2_wrappers.py (+1/-1)
bzrlib/transport/http/wsgi.py (+1/-1)
bzrlib/transport/local.py (+33/-6)
bzrlib/transport/memory.py (+1/-1)
bzrlib/transport/pathfilter.py (+1/-1)
bzrlib/transport/sftp.py (+24/-2)
bzrlib/transport/ssh.py (+6/-3)
bzrlib/ui/text.py (+5/-1)
bzrlib/urlutils.py (+1/-1)
bzrlib/version_info_formats/format_rio.py (+1/-1)
bzrlib/versionedfile.py (+1/-1)
bzrlib/workingtree.py (+2/-1)
bzrlib/workingtree_4.py (+4/-2)
bzrlib/xml4.py (+1/-1)
bzrlib/xml5.py (+1/-1)
bzrlib/xml7.py (+1/-1)
bzrlib/xml8.py (+1/-1)
bzrlib/xml_serializer.py (+1/-1)
doc/developers/_templates/layout.html (+0/-19)
doc/developers/bug-handling.txt (+2/-0)
doc/developers/contribution-quickstart.txt (+117/-56)
doc/developers/index-plain.txt (+2/-2)
doc/developers/index.txt (+18/-5)
doc/developers/plugin-api.txt (+5/-5)
doc/developers/process.txt (+0/-39)
doc/developers/testing.txt (+36/-3)
doc/en/_templates/index.html (+16/-4)
doc/en/_templates/layout.html (+0/-19)
doc/en/admin-guide/hooks-plugins.txt (+1/-1)
doc/en/conf.py (+6/-0)
doc/en/index.txt (+1/-0)
doc/en/user-guide/http_smart_server.txt (+79/-15)
doc/en/whats-new/whats-new-in-2.1.txt (+202/-0)
doc/es/_templates/layout.html (+0/-19)
doc/index.es.txt (+1/-1)
doc/index.ja.txt (+1/-1)
doc/index.ru.txt (+1/-1)
doc/index.txt (+1/-1)
doc/ru/_templates/layout.html (+0/-19)
setup.py (+23/-7)
To merge this branch: bzr merge lp:~vila/bzr/552922-plugins-at
Reviewer Review Type Date Requested Status
Vincent Ladeuil Needs Resubmitting
Review via email: mp+22694@code.launchpad.net

Description of the change

@Reviewers: this is targeted at lp:bzr/2.2 but I'm afraid the branch (2.2)
is not up-to-date, so if the diff looks awfully wrong, you'll know why.

This patch fixes the BZR_PLUGINS_AT handling to not depend on os.listdir() order.
The automated tests couldn't catch the problem and I was lucky enough to not encounter
it before (and neither was Gary).

Unlike _find_module_plugin() which scan the 'plugins' directories and deduce the plugin
names from the loadable files, BZR_PLUGINS_AT *knows* the plugin names and can (and should)
try some file names explicitly.

Tests added.

To post a comment you must log in.
Revision history for this message
Vincent Ladeuil (vila) wrote :

Bah. It's even worse than I thought, I'll resubmit against bzr.dev.

review: Needs Resubmitting

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.testr.conf'
2--- .testr.conf 1970-01-01 00:00:00 +0000
3+++ .testr.conf 2010-04-06 07:24:41 +0000
4@@ -0,0 +1,3 @@
5+[DEFAULT]
6+test_command=./bzr selftest --subunit $IDOPTION
7+test_id_option=--load-list $IDFILE
8
9=== modified file 'NEWS'
10--- NEWS 2010-02-18 04:59:30 +0000
11+++ NEWS 2010-04-06 07:24:41 +0000
12@@ -8,7 +8,6 @@
13 bzr 2.2.0b1
14 ###########
15
16-:Codename: ???
17 :2.2.0b1: Not released yet
18
19 Compatibility Breaks
20@@ -31,9 +30,17 @@
21 ``bzrlib.tests.test_server``.
22 (Vincent Ladeuil)
23
24+* ``BranchReferenceFormat.initialize()`` now takes an optional name argument
25+ as its second parameter, for consistency with the initialize() method of
26+ other formats. (Jelmer Vernooij)
27+
28 New Features
29 ************
30
31+* ``bzr export`` now takes an optional argument ``--per-file-timestamps``
32+ to set file mtimes to the last timestamp of the last revision in which
33+ they were changed rather than the current time. (Jelmer Vernooij)
34+
35 * If the Apport crash-reporting tool is available, bzr crashes are now
36 stored into the ``/var/crash`` apport spool directory, and the user is
37 invited to report them to the developers from there, either
38@@ -44,6 +51,17 @@
39 treats backslash as an escape character on Windows. (Gordon Tyler,
40 #392248)
41
42+* Plugins can be disabled by defining ``BZR_DISABLE_PLUGINS`` as
43+ a list of plugin names separated by ':' (';' on windows).
44+ (Vincent Ladeuil, #411413)
45+
46+* Plugins can be loaded from arbitrary locations by defining
47+ ``BZR_PLUGINS_AT`` as a list of name@path separated by ':' (';' on
48+ windows). This takes precedence over ``BZR_PLUGIN_PATH`` for the
49+ specified plugins. This is targeted at plugin developers for punctual
50+ needs and *not* intended to replace ``BZR_PLUGIN_PATH``.
51+ (Vincent Ladeuil, #82693)
52+
53 * Tree-shape conflicts can be resolved by providing ``--take-this`` and
54 ``--take-other`` to the ``bzr resolve`` command. Just marking the conflict
55 as resolved is still accessible via the ``--done`` default action.
56@@ -61,6 +79,11 @@
57 * Allow exporting a single file using ``bzr export``.
58 (Michal Junák, #511987)
59
60+* Allow syscalls to automatically restart when ``TextUIFactory``'s
61+ SIGWINCH handler is invoked, avoiding ``EINTR`` errors during blocking
62+ IO, which are often poorly handled by Python's libraries and parts of
63+ bzrlib. (Andrew Bennetts, #496813)
64+
65 * Avoid infinite recursion when probing for apport.
66 (Vincent Ladeuil, #516934)
67
68@@ -70,9 +93,39 @@
69 * ``bzr add`` will not add conflict related files unless explicitly required.
70 (Vincent Ladeuil, #322767, #414589)
71
72+* ``bzr help`` will no longer trigger the get_missing_command hook when
73+ doing a topic lookup. This avoids prompting (like 'no command plugins/loom,
74+ did you mean log?') when getting help. In future we may trigger the hook
75+ deliberately when no help topics match from any help index.
76+ (Robert Collins, #396261)
77+
78 * ``bzr remove-tree`` can now remove multiple working trees.
79 (Jared Hance, Andrew Bennetts, #253137)
80
81+* ``bzr resolve --take-this`` and ``--take-other`` now correctly renames
82+ the kept file on content conflicts where one side deleted the file.
83+ (Vincent Ladeuil, #529968)
84+
85+* ``bzr upgrade`` now names backup directory as ``backup.bzr.~N~`` instead
86+ of ``backup.bzr``. This directory is ignored by bzr commands such as
87+ ``add``.
88+ (Parth Malwankar, #335033, #300001)
89+
90+* Correctly interpret "451 Rename/move failure: Directory not empty" from
91+ ftp servers while trying to take a lock.
92+ (Martin Pool, #528722)
93+
94+* DirStateRevisionTree.kind() was returning wrong result when 'kind'
95+ changes occured between the workingtree and one of its parents.
96+ (Vincent Ladeuil, #533437)
97+
98+* Fix stub sftp test server to call os.getcwdu().
99+ (Vincent Ladeuil, #526211, #526353)
100+
101+* Loading a plugin from a given path with ``BZR_PLUGINS_AT`` doesn't depend
102+ on os.lisdir() order and is now reliable.
103+ (Vincent Ladeuil, #552922).
104+
105 * Network transfer amounts and rates are now displayed in SI units according
106 to the Ubuntu Units Policy <https://wiki.ubuntu.com/UnitsPolicy>.
107 (Gordon Tyler, #514399)
108@@ -81,26 +134,85 @@
109 prevents ``bzr status --short`` from crashing when those files are
110 present. (John Arbash Meinel, #303275)
111
112-* ``bzr upgrade`` now names backup directory as ``backup.bzr.~N~`` instead
113- of ``backup.bzr``. This directory is ignored by bzr commands such as
114- ``add``.
115- (Parth Malwankar, #335033, #300001)
116+* ``bzr mkdir DIR`` will not create DIR unless DIR's parent is a versioned
117+ directory. (Parth Malwankar, #138600)
118+
119+* SSH child processes will now ignore SIGQUIT on nix systems so breaking into
120+ the debugger won't kill the session.
121+ (Martin <gzlist@googlemail.com>, #162502)
122+
123+* Allow additional arguments to
124+ ``RemoteRepository.add_inventory_by_delta()``. (Jelmer Vernooij, #532631)
125+
126+* Tolerate patches with leading noise in ``bzr-handle-patch``.
127+ (Toshio Kuratomi, Martin Pool, #502076)
128
129 API Changes
130 ***********
131
132+* ``BranchFormat.initialize`` now takes an optional ``name`` of the colocated
133+ branch to create. (Jelmer Vernooij)
134+
135+* ``BzrDir.get_branch_transport`` now takes an optional ``name`` of the
136+ colocated branch to open. (Jelmer Vernooij)
137+
138+* Added ``bzrlib.osutils.set_signal_handler``, a convenience function that
139+ can set a signal handler and call ``signal.siginterrupt(signum,
140+ False)`` for it, if the platform and Python version supports it.
141+ (Andrew Bennetts, #496813)
142+
143 * New ``bzrlib.initialize`` is recommended for programs using bzrlib to
144 run when starting up; it sets up several things that previously needed
145 to be done separately.
146 (Martin Pool, #507710)
147
148+* Exporters now support a ``per_file_timestamps`` argument to write out the
149+ timestamp of the commit in which a file revision was introduced.
150+ (Jelmer Vernooij)
151+
152+* New method ``BzrDir.list_branches()`` that returns a sequence of branches
153+ present in a control directory. (Jelmer Vernooij)
154+
155+* New transport methods ``readlink``, ``symlink`` and ``hardlink``.
156+ (Neil Santos)
157+
158 * Remove unused ``CommandFailed`` exception.
159 (Martin Pool)
160
161+Internals
162+*********
163+
164+* ``bzrlib.branchbuilder.BranchBuilder.build_snapshot`` now accepts a
165+ ``message_callback`` in the same way that commit does. (Robert Collins)
166+
167+* ``bzrlib.builtins.Commit.run`` raises ``bzrlib.errors.BoundBranchOutOfDate``
168+ rather than ``bzrlib.errors.BzrCommandError`` when the bound branch is out
169+ of date. (Gary van der Merwe)
170+
171+* ``bzrlib.commands.run_bzr`` is more extensible: callers can supply the
172+ functions to load or disable plugins if they wish to use a different
173+ plugin mechanism; the --help, --version and no-command name code paths
174+ now use the generic pluggable command lookup infrastructure.
175+ (Robert Collins)
176+
177+* ``bzrlib.errors.BoundBranchOutOfDate`` has a new field ``extra_help``
178+ which can be set to add extra help to the error. (Gary van der Merwe)
179+
180+* The methods ``BzrDir.create_branch()``, ``BzrDir.destroy_branch()`` and
181+ ``BzrDir.open_branch()`` now take an optional ``name`` argument.
182+ (Jelmer Vernooij)
183+
184 Testing
185 *******
186
187-* New `bzrlib.tests.test_import_tariff` can make assertions about what
188+* bzr now has a ``.testr.conf`` file in its source tree configured
189+ appropriately for running tests with Testrepository
190+ (``https://launchpad.net/testrepository``). (Robert Collins)
191+
192+* Documentation about testing with ``subunit`` has been tweaked.
193+ (Robert Collins)
194+
195+* New ``bzrlib.tests.test_import_tariff`` can make assertions about what
196 Python modules are loaded, to guard against startup time or library
197 dependency regressions.
198 (Martin Pool)
199@@ -108,6 +220,70 @@
200 * Stop sending apport crash files to ``.cache`` in the directory from
201 which ``bzr selftest`` was run. (Martin Pool, #422350)
202
203+* Tests no longer fail if "close() called during concurrent
204+ operation on the same file object" occurs when closing the log file
205+ (which can happen if a thread tries to write to the log file at the
206+ wrong moment). An warning will be written to ``stderr`` when this
207+ happens, and another warning will be written if the log file could not
208+ be closed after retrying 100 times. (Andrew Bennetts, #531746)
209+
210+bzr 2.1.1
211+#########
212+
213+:2.1.1: not released yet
214+
215+Bug Fixes
216+*********
217+
218+* Allow syscalls to automatically restart when ``TextUIFactory``'s
219+ SIGWINCH handler is invoked, avoiding ``EINTR`` errors during blocking
220+ IO, which are often poorly handled by Python's libraries and parts of
221+ bzrlib. (Andrew Bennetts, #496813)
222+
223+* Avoid ``malloc(0)`` in ``patiencediff``, which is non-portable.
224+ (Martin Pool, #331095)
225+
226+* Fix plugin packaging on Windows. (Ian Clatworthy, #524162)
227+
228+* Fix stub sftp test server to call os.getcwdu().
229+ (Vincent Ladeuil, #526211, #526353)
230+
231+* Fixed CHM generation by moving the NEWS section template into
232+ a separate file. (Ian Clatworthy, #524184)
233+
234+* Merge correctly when this_tree is not a WorkingTree. (Aaron Bentley)
235+
236+* Register SIGWINCH handler only when creating a ``TextUIFactory``; avoids
237+ problems importing bzrlib from a non-main thread.
238+ (Elliot Murphy, #521989)
239+
240+* Standardize the error handling when creating a new ``StaticTuple``
241+ (problems will raise TypeError). (Matt Nordhoff, #457979)
242+
243+* Warn if pyrex is too old to compile the new ``SimpleSet`` and
244+ ``StaticTuple`` extensions, rather than having the build fail randomly.
245+ (John Arbash Meinel, #449776)
246+
247+
248+Documentation
249+*************
250+
251+* Added a link to the Desktop Guide. (Ian Clatworthy)
252+
253+* Added What's New in Bazaar 2.1 document. (Ian Clatworthy)
254+
255+* Drop Google Analytics from the core docs as they caused problems
256+ in the CHM files. (Ian Clatworthy, #502010)
257+
258+API Changes
259+***********
260+
261+* Added ``bzrlib.osutils.set_signal_handler``, a convenience function that
262+ can set a signal handler and call ``signal.siginterrupt(signum,
263+ False)`` for it, if the platform and Python version supports it.
264+ (Andrew Bennetts, #496813)
265+
266+
267 bzr 2.1.0
268 #########
269
270@@ -465,18 +641,36 @@
271 (Martin Pool)
272
273
274-bzr 2.0.5 (not released yet)
275-############################
276+bzr 2.0.5
277+#########
278
279 :Codename:
280-:2.0.5:
281+:2.0.5: NOT RELEASED YET
282
283 Bug Fixes
284 *********
285
286+* Avoid ``malloc(0)`` in ``patiencediff``, which is non-portable.
287+ (Martin Pool, #331095)
288+
289+* Concurrent autopacking is more resilient to already-renamed pack files.
290+ If we find that a file we are about to obsolete is already obsoleted, we
291+ do not try to rename it, and we leave the file in ``obsolete_packs``.
292+ The code is also fault tolerant if a file goes missing, assuming that
293+ another process already removed the file.
294+ (John Arbash Meinel, Gareth White, #507557)
295+
296+* Cope with the lockdir ``held/info`` file being empty, which seems to
297+ happen fairly often if the process is suddenly interrupted while taking
298+ a lock.
299+ (Martin Pool, #185103)
300+
301 * Handle renames correctly when there are files or directories that
302 differ only in case. (Chris Jones, Martin Pool, #368931)
303
304+* Fixed CHM generation by moving the NEWS section template into
305+ a separate file. (Ian Clatworthy, #524184)
306+
307 * If ``bzr push --create-prefix`` triggers an unexpected ``NoSuchFile``
308 error, report that error rather than failing with an unhelpful
309 ``UnboundLocalError``.
310@@ -486,6 +680,10 @@
311 version number along with rest of the help text.
312 (Parth Malwankar, #369501)
313
314+* Use osutils.O_NOINHERIT for some files on win32 to avoid PermissionDenied
315+ errors.
316+ (Inada Naoki, #524560)
317+
318 Documentation
319 *************
320
321@@ -11972,37 +12170,5 @@
322 diff, status, etc.
323
324
325-bzr ?.?.? (not released yet)
326-############################
327-
328-:Codename: template
329-:2.0.2: ???
330-
331-Compatibility Breaks
332-********************
333-
334-New Features
335-************
336-
337-Bug Fixes
338-*********
339-
340-Improvements
341-************
342-
343-Documentation
344-*************
345-
346-API Changes
347-***********
348-
349-Internals
350-*********
351-
352-Testing
353-*******
354-
355-
356-
357 ..
358 vim: tw=74 ft=rst ff=unix encoding=utf-8
359
360=== added file 'NEWS-template.txt'
361--- NEWS-template.txt 1970-01-01 00:00:00 +0000
362+++ NEWS-template.txt 2010-04-06 07:24:41 +0000
363@@ -0,0 +1,31 @@
364+bzr ?.?.?
365+#########
366+
367+:Codename: Nirvana
368+:2.x.y: NOT RELEASED YET
369+
370+Compatibility Breaks
371+********************
372+
373+New Features
374+************
375+
376+Bug Fixes
377+*********
378+
379+Improvements
380+************
381+
382+Documentation
383+*************
384+
385+API Changes
386+***********
387+
388+Internals
389+*********
390+
391+Testing
392+*******
393+
394+
395
396=== modified file 'bzrlib/_annotator_pyx.pyx'
397--- bzrlib/_annotator_pyx.pyx 2010-01-05 04:59:57 +0000
398+++ bzrlib/_annotator_pyx.pyx 2010-04-06 07:24:41 +0000
399@@ -1,4 +1,4 @@
400-# Copyright (C) 2009 Canonical Ltd
401+# Copyright (C) 2009, 2010 Canonical Ltd
402 #
403 # This program is free software; you can redistribute it and/or modify
404 # it under the terms of the GNU General Public License as published by
405
406=== modified file 'bzrlib/_bencode_pyx.pyx'
407--- bzrlib/_bencode_pyx.pyx 2010-01-04 02:25:11 +0000
408+++ bzrlib/_bencode_pyx.pyx 2010-04-06 07:24:41 +0000
409@@ -1,4 +1,4 @@
410-# Copyright (C) 2007,2009 Canonical Ltd
411+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
412 #
413 # This program is free software; you can redistribute it and/or modify
414 # it under the terms of the GNU General Public License as published by
415
416=== modified file 'bzrlib/_btree_serializer_py.py'
417--- bzrlib/_btree_serializer_py.py 2009-11-07 00:28:26 +0000
418+++ bzrlib/_btree_serializer_py.py 2010-04-06 07:24:41 +0000
419@@ -1,4 +1,4 @@
420-# Copyright (C) 2008 Canonical Ltd
421+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
422 #
423 # This program is free software; you can redistribute it and/or modify
424 # it under the terms of the GNU General Public License as published by
425
426=== modified file 'bzrlib/_btree_serializer_pyx.pyx'
427--- bzrlib/_btree_serializer_pyx.pyx 2010-01-05 05:09:45 +0000
428+++ bzrlib/_btree_serializer_pyx.pyx 2010-04-06 07:24:41 +0000
429@@ -1,4 +1,4 @@
430-# Copyright (C) 2008, 2009 Canonical Ltd
431+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
432 #
433 # This program is free software; you can redistribute it and/or modify
434 # it under the terms of the GNU General Public License as published by
435
436=== modified file 'bzrlib/_chk_map_py.py'
437--- bzrlib/_chk_map_py.py 2009-10-21 21:27:19 +0000
438+++ bzrlib/_chk_map_py.py 2010-04-06 07:24:41 +0000
439@@ -1,4 +1,4 @@
440-# Copyright (C) 2009 Canonical Ltd
441+# Copyright (C) 2009, 2010 Canonical Ltd
442 #
443 # This program is free software; you can redistribute it and/or modify
444 # it under the terms of the GNU General Public License as published by
445
446=== modified file 'bzrlib/_chk_map_pyx.pyx'
447--- bzrlib/_chk_map_pyx.pyx 2010-01-05 05:09:45 +0000
448+++ bzrlib/_chk_map_pyx.pyx 2010-04-06 07:24:41 +0000
449@@ -1,4 +1,4 @@
450-# Copyright (C) 2009 Canonical Ltd
451+# Copyright (C) 2009, 2010 Canonical Ltd
452 #
453 # This program is free software; you can redistribute it and/or modify
454 # it under the terms of the GNU General Public License as published by
455
456=== modified file 'bzrlib/_groupcompress_pyx.pyx'
457--- bzrlib/_groupcompress_pyx.pyx 2010-01-05 05:09:45 +0000
458+++ bzrlib/_groupcompress_pyx.pyx 2010-04-06 07:24:41 +0000
459@@ -1,4 +1,4 @@
460-# Copyright (C) 2009 Canonical Ltd
461+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
462 #
463 # This program is free software; you can redistribute it and/or modify
464 # it under the terms of the GNU General Public License as published by
465
466=== modified file 'bzrlib/_knit_load_data_pyx.pyx'
467--- bzrlib/_knit_load_data_pyx.pyx 2010-01-04 23:13:20 +0000
468+++ bzrlib/_knit_load_data_pyx.pyx 2010-04-06 07:24:41 +0000
469@@ -1,4 +1,4 @@
470-# Copyright (C) 2007 Canonical Ltd
471+# Copyright (C) 2007-2010 Canonical Ltd
472 #
473 # This program is free software; you can redistribute it and/or modify
474 # it under the terms of the GNU General Public License as published by
475
476=== modified file 'bzrlib/_known_graph_py.py'
477--- bzrlib/_known_graph_py.py 2009-11-30 17:25:22 +0000
478+++ bzrlib/_known_graph_py.py 2010-04-06 07:24:41 +0000
479@@ -1,4 +1,4 @@
480-# Copyright (C) 2009 Canonical Ltd
481+# Copyright (C) 2009, 2010 Canonical Ltd
482 #
483 # This program is free software; you can redistribute it and/or modify
484 # it under the terms of the GNU General Public License as published by
485
486=== modified file 'bzrlib/_known_graph_pyx.pyx'
487--- bzrlib/_known_graph_pyx.pyx 2010-01-05 05:09:45 +0000
488+++ bzrlib/_known_graph_pyx.pyx 2010-04-06 07:24:41 +0000
489@@ -1,4 +1,4 @@
490-# Copyright (C) 2009 Canonical Ltd
491+# Copyright (C) 2009, 2010 Canonical Ltd
492 #
493 # This program is free software; you can redistribute it and/or modify
494 # it under the terms of the GNU General Public License as published by
495
496=== modified file 'bzrlib/_readdir_pyx.pyx'
497--- bzrlib/_readdir_pyx.pyx 2010-01-06 22:17:10 +0000
498+++ bzrlib/_readdir_pyx.pyx 2010-04-06 07:24:41 +0000
499@@ -1,4 +1,4 @@
500-# Copyright (C) 2006, 2008, 2009 Canonical Ltd
501+# Copyright (C) 2006, 2008, 2009, 2010 Canonical Ltd
502 #
503 # This program is free software; you can redistribute it and/or modify
504 # it under the terms of the GNU General Public License as published by
505
506=== modified file 'bzrlib/_rio_pyx.pyx'
507--- bzrlib/_rio_pyx.pyx 2010-01-05 04:59:57 +0000
508+++ bzrlib/_rio_pyx.pyx 2010-04-06 07:24:41 +0000
509@@ -1,4 +1,4 @@
510-# Copyright (C) 2009 Canonical Ltd
511+# Copyright (C) 2009, 2010 Canonical Ltd
512 #
513 # This program is free software; you can redistribute it and/or modify
514 # it under the terms of the GNU General Public License as published by
515
516=== modified file 'bzrlib/_simple_set_pyx.pxd'
517--- bzrlib/_simple_set_pyx.pxd 2010-01-05 05:28:42 +0000
518+++ bzrlib/_simple_set_pyx.pxd 2010-04-06 07:24:41 +0000
519@@ -1,4 +1,4 @@
520-# Copyright (C) 2009 Canonical Ltd
521+# Copyright (C) 2009, 2010 Canonical Ltd
522 #
523 # This program is free software; you can redistribute it and/or modify
524 # it under the terms of the GNU General Public License as published by
525
526=== modified file 'bzrlib/_simple_set_pyx.pyx'
527--- bzrlib/_simple_set_pyx.pyx 2010-01-05 05:28:42 +0000
528+++ bzrlib/_simple_set_pyx.pyx 2010-04-06 07:24:41 +0000
529@@ -1,4 +1,4 @@
530-# Copyright (C) 2009 Canonical Ltd
531+# Copyright (C) 2009, 2010 Canonical Ltd
532 #
533 # This program is free software; you can redistribute it and/or modify
534 # it under the terms of the GNU General Public License as published by
535
536=== modified file 'bzrlib/_static_tuple_c.c'
537--- bzrlib/_static_tuple_c.c 2010-02-18 01:10:16 +0000
538+++ bzrlib/_static_tuple_c.c 2010-04-06 07:24:41 +0000
539@@ -1,4 +1,4 @@
540-/* Copyright (C) 2009 Canonical Ltd
541+/* Copyright (C) 2009, 2010 Canonical Ltd
542 *
543 * This program is free software; you can redistribute it and/or modify
544 * it under the terms of the GNU General Public License as published by
545
546=== modified file 'bzrlib/_static_tuple_c.pxd'
547--- bzrlib/_static_tuple_c.pxd 2009-10-21 21:27:19 +0000
548+++ bzrlib/_static_tuple_c.pxd 2010-04-06 07:24:41 +0000
549@@ -1,4 +1,4 @@
550-# Copyright (C) 2009 Canonical Ltd
551+# Copyright (C) 2009, 2010 Canonical Ltd
552 #
553 # This program is free software; you can redistribute it and/or modify
554 # it under the terms of the GNU General Public License as published by
555
556=== modified file 'bzrlib/_static_tuple_py.py'
557--- bzrlib/_static_tuple_py.py 2010-02-18 01:10:16 +0000
558+++ bzrlib/_static_tuple_py.py 2010-04-06 07:24:41 +0000
559@@ -1,4 +1,4 @@
560-# Copyright (C) 2009 Canonical Ltd
561+# Copyright (C) 2009, 2010 Canonical Ltd
562 #
563 # This program is free software; you can redistribute it and/or modify
564 # it under the terms of the GNU General Public License as published by
565
566=== modified file 'bzrlib/_walkdirs_win32.pyx'
567--- bzrlib/_walkdirs_win32.pyx 2010-01-07 17:02:44 +0000
568+++ bzrlib/_walkdirs_win32.pyx 2010-04-06 07:24:41 +0000
569@@ -1,4 +1,4 @@
570-# Copyright (C) 2008 Canonical Ltd
571+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
572 #
573 # This program is free software; you can redistribute it and/or modify
574 # it under the terms of the GNU General Public License as published by
575
576=== modified file 'bzrlib/atomicfile.py'
577--- bzrlib/atomicfile.py 2009-03-23 14:59:43 +0000
578+++ bzrlib/atomicfile.py 2010-04-06 07:24:41 +0000
579@@ -60,7 +60,7 @@
580
581 self.realfilename = filename
582
583- flags = os.O_EXCL | os.O_CREAT | os.O_WRONLY
584+ flags = os.O_EXCL | os.O_CREAT | os.O_WRONLY | osutils.O_NOINHERIT
585 if mode == 'wb':
586 flags |= osutils.O_BINARY
587 elif mode != 'wt':
588
589=== modified file 'bzrlib/benchmarks/bench_dirstate.py'
590--- bzrlib/benchmarks/bench_dirstate.py 2009-12-22 17:05:47 +0000
591+++ bzrlib/benchmarks/bench_dirstate.py 2010-04-06 07:24:41 +0000
592@@ -1,4 +1,4 @@
593-# Copyright (C) 2007, 2009 Canonical Ltd
594+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
595 #
596 # This program is free software; you can redistribute it and/or modify
597 # it under the terms of the GNU General Public License as published by
598
599=== modified file 'bzrlib/benchmarks/tree_creator/kernel_like.py'
600--- bzrlib/benchmarks/tree_creator/kernel_like.py 2009-03-23 14:59:43 +0000
601+++ bzrlib/benchmarks/tree_creator/kernel_like.py 2010-04-06 07:24:41 +0000
602@@ -48,7 +48,8 @@
603 if self._url is not None:
604 b = bzrdir.BzrDir.create_branch_convenience(self._url)
605 d = bzrdir.BzrDir.create(root)
606- bzrlib.branch.BranchReferenceFormat().initialize(d, b)
607+ bzrlib.branch.BranchReferenceFormat().initialize(d,
608+ target_branch=b)
609 tree = d.create_workingtree()
610 else:
611 tree = bzrdir.BzrDir.create_standalone_workingtree(root)
612
613=== modified file 'bzrlib/branch.py'
614--- bzrlib/branch.py 2010-01-12 02:48:41 +0000
615+++ bzrlib/branch.py 2010-04-06 07:24:41 +0000
616@@ -1,4 +1,4 @@
617-# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
618+# Copyright (C) 2005-2010 Canonical Ltd
619 #
620 # This program is free software; you can redistribute it and/or modify
621 # it under the terms of the GNU General Public License as published by
622@@ -167,13 +167,13 @@
623 """
624 control = bzrdir.BzrDir.open(base, _unsupported,
625 possible_transports=possible_transports)
626- return control.open_branch(_unsupported)
627+ return control.open_branch(unsupported=_unsupported)
628
629 @staticmethod
630- def open_from_transport(transport, _unsupported=False):
631+ def open_from_transport(transport, name=None, _unsupported=False):
632 """Open the branch rooted at transport"""
633 control = bzrdir.BzrDir.open_from_transport(transport, _unsupported)
634- return control.open_branch(_unsupported)
635+ return control.open_branch(name=name, unsupported=_unsupported)
636
637 @staticmethod
638 def open_containing(url, possible_transports=None):
639@@ -217,9 +217,9 @@
640 def _get_fallback_repository(self, url):
641 """Get the repository we fallback to at url."""
642 url = urlutils.join(self.base, url)
643- a_bzrdir = bzrdir.BzrDir.open(url,
644+ a_branch = Branch.open(url,
645 possible_transports=[self.bzrdir.root_transport])
646- return a_bzrdir.open_branch().repository
647+ return a_branch.repository
648
649 def _get_tags_bytes(self):
650 """Get the bytes of a serialised tags dict.
651@@ -1317,7 +1317,8 @@
652 if lightweight:
653 format = self._get_checkout_format()
654 checkout = format.initialize_on_transport(t)
655- from_branch = BranchReferenceFormat().initialize(checkout, self)
656+ from_branch = BranchReferenceFormat().initialize(checkout,
657+ target_branch=self)
658 else:
659 format = self._get_checkout_format()
660 checkout_branch = bzrdir.BzrDir.create_branch_convenience(
661@@ -1434,10 +1435,10 @@
662 return not (self == other)
663
664 @classmethod
665- def find_format(klass, a_bzrdir):
666+ def find_format(klass, a_bzrdir, name=None):
667 """Return the format for the branch object in a_bzrdir."""
668 try:
669- transport = a_bzrdir.get_branch_transport(None)
670+ transport = a_bzrdir.get_branch_transport(None, name=name)
671 format_string = transport.get_bytes("format")
672 return klass._formats[format_string]
673 except errors.NoSuchFile:
674@@ -1483,20 +1484,21 @@
675 """Return the short format description for this format."""
676 raise NotImplementedError(self.get_format_description)
677
678- def _initialize_helper(self, a_bzrdir, utf8_files, lock_type='metadir',
679- set_format=True):
680+ def _initialize_helper(self, a_bzrdir, utf8_files, name=None,
681+ lock_type='metadir', set_format=True):
682 """Initialize a branch in a bzrdir, with specified files
683
684 :param a_bzrdir: The bzrdir to initialize the branch in
685 :param utf8_files: The files to create as a list of
686 (filename, content) tuples
687+ :param name: Name of colocated branch to create, if any
688 :param set_format: If True, set the format with
689 self.get_format_string. (BzrBranch4 has its format set
690 elsewhere)
691 :return: a branch in this format
692 """
693 mutter('creating branch %r in %s', self, a_bzrdir.transport.base)
694- branch_transport = a_bzrdir.get_branch_transport(self)
695+ branch_transport = a_bzrdir.get_branch_transport(self, name=name)
696 lock_map = {
697 'metadir': ('lock', lockdir.LockDir),
698 'branch4': ('branch-lock', lockable_files.TransportLock),
699@@ -1523,10 +1525,13 @@
700 finally:
701 if lock_taken:
702 control_files.unlock()
703- return self.open(a_bzrdir, _found=True)
704+ return self.open(a_bzrdir, name, _found=True)
705
706- def initialize(self, a_bzrdir):
707- """Create a branch of this format in a_bzrdir."""
708+ def initialize(self, a_bzrdir, name=None):
709+ """Create a branch of this format in a_bzrdir.
710+
711+ :param name: Name of the colocated branch to create.
712+ """
713 raise NotImplementedError(self.initialize)
714
715 def is_supported(self):
716@@ -1562,10 +1567,11 @@
717 """
718 raise NotImplementedError(self.network_name)
719
720- def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
721+ def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
722 """Return the branch object for a_bzrdir
723
724 :param a_bzrdir: A BzrDir that contains a branch.
725+ :param name: Name of colocated branch to open
726 :param _found: a private parameter, do not use it. It is used to
727 indicate if format probing has already be done.
728 :param ignore_fallbacks: when set, no fallback branches will be opened
729@@ -1735,12 +1741,12 @@
730 """See BranchFormat.get_format_description()."""
731 return "Branch format 4"
732
733- def initialize(self, a_bzrdir):
734+ def initialize(self, a_bzrdir, name=None):
735 """Create a branch of this format in a_bzrdir."""
736 utf8_files = [('revision-history', ''),
737 ('branch-name', ''),
738 ]
739- return self._initialize_helper(a_bzrdir, utf8_files,
740+ return self._initialize_helper(a_bzrdir, utf8_files, name=name,
741 lock_type='branch4', set_format=False)
742
743 def __init__(self):
744@@ -1751,8 +1757,10 @@
745 """The network name for this format is the control dirs disk label."""
746 return self._matchingbzrdir.get_format_string()
747
748- def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
749+ def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
750 """See BranchFormat.open()."""
751+ if name is not None:
752+ raise errors.NoColocatedBranchSupport(a_bzrdir)
753 if not _found:
754 # we are being called directly and must probe.
755 raise NotImplementedError
756@@ -1779,15 +1787,15 @@
757 """
758 return self.get_format_string()
759
760- def open(self, a_bzrdir, _found=False, ignore_fallbacks=False):
761+ def open(self, a_bzrdir, name=None, _found=False, ignore_fallbacks=False):
762 """See BranchFormat.open()."""
763 if not _found:
764- format = BranchFormat.find_format(a_bzrdir)
765+ format = BranchFormat.find_format(a_bzrdir, name=name)
766 if format.__class__ != self.__class__:
767 raise AssertionError("wrong format %r found for %r" %
768 (format, self))
769 try:
770- transport = a_bzrdir.get_branch_transport(None)
771+ transport = a_bzrdir.get_branch_transport(None, name=name)
772 control_files = lockable_files.LockableFiles(transport, 'lock',
773 lockdir.LockDir)
774 return self._branch_class()(_format=self,
775@@ -1831,12 +1839,12 @@
776 """See BranchFormat.get_format_description()."""
777 return "Branch format 5"
778
779- def initialize(self, a_bzrdir):
780+ def initialize(self, a_bzrdir, name=None):
781 """Create a branch of this format in a_bzrdir."""
782 utf8_files = [('revision-history', ''),
783 ('branch-name', ''),
784 ]
785- return self._initialize_helper(a_bzrdir, utf8_files)
786+ return self._initialize_helper(a_bzrdir, utf8_files, name)
787
788 def supports_tags(self):
789 return False
790@@ -1864,13 +1872,13 @@
791 """See BranchFormat.get_format_description()."""
792 return "Branch format 6"
793
794- def initialize(self, a_bzrdir):
795+ def initialize(self, a_bzrdir, name=None):
796 """Create a branch of this format in a_bzrdir."""
797 utf8_files = [('last-revision', '0 null:\n'),
798 ('branch.conf', ''),
799 ('tags', ''),
800 ]
801- return self._initialize_helper(a_bzrdir, utf8_files)
802+ return self._initialize_helper(a_bzrdir, utf8_files, name)
803
804 def make_tags(self, branch):
805 """See bzrlib.branch.BranchFormat.make_tags()."""
806@@ -1894,14 +1902,14 @@
807 """See BranchFormat.get_format_description()."""
808 return "Branch format 8"
809
810- def initialize(self, a_bzrdir):
811+ def initialize(self, a_bzrdir, name=None):
812 """Create a branch of this format in a_bzrdir."""
813 utf8_files = [('last-revision', '0 null:\n'),
814 ('branch.conf', ''),
815 ('tags', ''),
816 ('references', '')
817 ]
818- return self._initialize_helper(a_bzrdir, utf8_files)
819+ return self._initialize_helper(a_bzrdir, utf8_files, name)
820
821 def __init__(self):
822 super(BzrBranchFormat8, self).__init__()
823@@ -1930,13 +1938,13 @@
824 This format was introduced in bzr 1.6.
825 """
826
827- def initialize(self, a_bzrdir):
828+ def initialize(self, a_bzrdir, name=None):
829 """Create a branch of this format in a_bzrdir."""
830 utf8_files = [('last-revision', '0 null:\n'),
831 ('branch.conf', ''),
832 ('tags', ''),
833 ]
834- return self._initialize_helper(a_bzrdir, utf8_files)
835+ return self._initialize_helper(a_bzrdir, utf8_files, name)
836
837 def _branch_class(self):
838 return BzrBranch7
839@@ -1984,19 +1992,19 @@
840 transport = a_bzrdir.get_branch_transport(None)
841 location = transport.put_bytes('location', to_branch.base)
842
843- def initialize(self, a_bzrdir, target_branch=None):
844+ def initialize(self, a_bzrdir, name=None, target_branch=None):
845 """Create a branch of this format in a_bzrdir."""
846 if target_branch is None:
847 # this format does not implement branch itself, thus the implicit
848 # creation contract must see it as uninitializable
849 raise errors.UninitializableFormat(self)
850 mutter('creating branch reference in %s', a_bzrdir.transport.base)
851- branch_transport = a_bzrdir.get_branch_transport(self)
852+ branch_transport = a_bzrdir.get_branch_transport(self, name=name)
853 branch_transport.put_bytes('location',
854 target_branch.bzrdir.root_transport.base)
855 branch_transport.put_bytes('format', self.get_format_string())
856 return self.open(
857- a_bzrdir, _found=True,
858+ a_bzrdir, name, _found=True,
859 possible_transports=[target_branch.bzrdir.root_transport])
860
861 def __init__(self):
862@@ -2009,17 +2017,18 @@
863 def clone(to_bzrdir, revision_id=None,
864 repository_policy=None):
865 """See Branch.clone()."""
866- return format.initialize(to_bzrdir, a_branch)
867+ return format.initialize(to_bzrdir, target_branch=a_branch)
868 # cannot obey revision_id limits when cloning a reference ...
869 # FIXME RBC 20060210 either nuke revision_id for clone, or
870 # emit some sort of warning/error to the caller ?!
871 return clone
872
873- def open(self, a_bzrdir, _found=False, location=None,
874+ def open(self, a_bzrdir, name=None, _found=False, location=None,
875 possible_transports=None, ignore_fallbacks=False):
876 """Return the branch that the branch reference in a_bzrdir points at.
877
878 :param a_bzrdir: A BzrDir that contains a branch.
879+ :param name: Name of colocated branch to open, if any
880 :param _found: a private parameter, do not use it. It is used to
881 indicate if format probing has already be done.
882 :param ignore_fallbacks: when set, no fallback branches will be opened
883@@ -2030,7 +2039,7 @@
884 :param possible_transports: An optional reusable transports list.
885 """
886 if not _found:
887- format = BranchFormat.find_format(a_bzrdir)
888+ format = BranchFormat.find_format(a_bzrdir, name=name)
889 if format.__class__ != self.__class__:
890 raise AssertionError("wrong format %r found for %r" %
891 (format, self))
892@@ -2038,7 +2047,8 @@
893 location = self.get_reference(a_bzrdir)
894 real_bzrdir = bzrdir.BzrDir.open(
895 location, possible_transports=possible_transports)
896- result = real_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
897+ result = real_bzrdir.open_branch(name=name,
898+ ignore_fallbacks=ignore_fallbacks)
899 # this changes the behaviour of result.clone to create a new reference
900 # rather than a copy of the content of the branch.
901 # I did not use a proxy object because that needs much more extensive
902
903=== modified file 'bzrlib/branchbuilder.py'
904--- bzrlib/branchbuilder.py 2009-08-05 02:12:22 +0000
905+++ bzrlib/branchbuilder.py 2010-04-06 07:24:41 +0000
906@@ -103,11 +103,11 @@
907 finally:
908 tree.unlock()
909
910- def _do_commit(self, tree, message=None, **kwargs):
911+ def _do_commit(self, tree, message=None, message_callback=None, **kwargs):
912 reporter = commit.NullCommitReporter()
913- if message is None:
914+ if message is None and message_callback is None:
915 message = u'commit %d' % (self._branch.revno() + 1,)
916- return tree.commit(message,
917+ return tree.commit(message, message_callback=message_callback,
918 reporter=reporter,
919 **kwargs)
920
921@@ -162,7 +162,7 @@
922
923 def build_snapshot(self, revision_id, parent_ids, actions,
924 message=None, timestamp=None, allow_leftmost_as_ghost=False,
925- committer=None, timezone=None):
926+ committer=None, timezone=None, message_callback=None):
927 """Build a commit, shaped in a specific way.
928
929 :param revision_id: The handle for the new commit, can be None
930@@ -175,6 +175,8 @@
931 ('rename', ('orig-path', 'new-path'))
932 :param message: An optional commit message, if not supplied, a default
933 commit message will be written.
934+ :param message_callback: A message callback to use for the commit, as
935+ per mutabletree.commit.
936 :param timestamp: If non-None, set the timestamp of the commit to this
937 value.
938 :param timezone: An optional timezone for timestamp.
939@@ -244,7 +246,8 @@
940 for file_id, content in new_contents.iteritems():
941 tree.put_file_bytes_non_atomic(file_id, content)
942 return self._do_commit(tree, message=message, rev_id=revision_id,
943- timestamp=timestamp, timezone=timezone, committer=committer)
944+ timestamp=timestamp, timezone=timezone, committer=committer,
945+ message_callback=message_callback)
946 finally:
947 tree.unlock()
948
949
950=== modified file 'bzrlib/btree_index.py'
951--- bzrlib/btree_index.py 2009-11-07 01:58:11 +0000
952+++ bzrlib/btree_index.py 2010-04-06 07:24:41 +0000
953@@ -1,4 +1,4 @@
954-# Copyright (C) 2008 Canonical Ltd
955+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
956 #
957 # This program is free software; you can redistribute it and/or modify
958 # it under the terms of the GNU General Public License as published by
959
960=== modified file 'bzrlib/bugtracker.py'
961--- bzrlib/bugtracker.py 2010-01-08 07:37:25 +0000
962+++ bzrlib/bugtracker.py 2010-04-06 07:24:41 +0000
963@@ -1,4 +1,4 @@
964-# Copyright (C) 2007 Canonical Ltd
965+# Copyright (C) 2007-2010 Canonical Ltd
966 #
967 # This program is free software; you can redistribute it and/or modify
968 # it under the terms of the GNU General Public License as published by
969
970=== modified file 'bzrlib/builtins.py'
971--- bzrlib/builtins.py 2010-02-15 20:23:34 +0000
972+++ bzrlib/builtins.py 2010-04-06 07:24:41 +0000
973@@ -699,10 +699,15 @@
974
975 def run(self, dir_list):
976 for d in dir_list:
977- os.mkdir(d)
978 wt, dd = WorkingTree.open_containing(d)
979- wt.add([dd])
980- self.outf.write('added %s\n' % d)
981+ base = os.path.dirname(dd)
982+ id = wt.path2id(base)
983+ if id != None:
984+ os.mkdir(d)
985+ wt.add([dd])
986+ self.outf.write('added %s\n' % d)
987+ else:
988+ raise errors.NotVersionedError(path=base)
989
990
991 class cmd_relpath(Command):
992@@ -2684,7 +2689,7 @@
993 if old_default_rules is not None:
994 # dump the rules and exit
995 for pattern in ignores.OLD_DEFAULTS:
996- print pattern
997+ self.outf.write("%s\n" % pattern)
998 return
999 if not name_pattern_list:
1000 raise errors.BzrCommandError("ignore requires at least one "
1001@@ -2706,13 +2711,13 @@
1002 if id is not None:
1003 filename = entry[0]
1004 if ignored.match(filename):
1005- matches.append(filename.encode('utf-8'))
1006+ matches.append(filename)
1007 tree.unlock()
1008 if len(matches) > 0:
1009- print "Warning: the following files are version controlled and" \
1010- " match your ignore pattern:\n%s" \
1011- "\nThese files will continue to be version controlled" \
1012- " unless you 'bzr remove' them." % ("\n".join(matches),)
1013+ self.outf.write("Warning: the following files are version controlled and"
1014+ " match your ignore pattern:\n%s"
1015+ "\nThese files will continue to be version controlled"
1016+ " unless you 'bzr remove' them.\n" % ("\n".join(matches),))
1017
1018
1019 class cmd_ignored(Command):
1020@@ -2756,9 +2761,10 @@
1021 try:
1022 revno = int(revno)
1023 except ValueError:
1024- raise errors.BzrCommandError("not a valid revision-number: %r" % revno)
1025-
1026- print WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1027+ raise errors.BzrCommandError("not a valid revision-number: %r"
1028+ % revno)
1029+ revid = WorkingTree.open_containing(u'.')[0].branch.get_rev_id(revno)
1030+ self.outf.write("%s\n" % revid)
1031
1032
1033 class cmd_export(Command):
1034@@ -2800,9 +2806,12 @@
1035 Option('root',
1036 type=str,
1037 help="Name of the root directory inside the exported file."),
1038+ Option('per-file-timestamps',
1039+ help='Set modification time of files to that of the last '
1040+ 'revision in which it was changed.'),
1041 ]
1042 def run(self, dest, branch_or_subdir=None, revision=None, format=None,
1043- root=None, filters=False):
1044+ root=None, filters=False, per_file_timestamps=False):
1045 from bzrlib.export import export
1046
1047 if branch_or_subdir is None:
1048@@ -2815,7 +2824,8 @@
1049
1050 rev_tree = _get_one_revision_tree('export', revision, branch=b, tree=tree)
1051 try:
1052- export(rev_tree, dest, format, root, subdir, filtered=filters)
1053+ export(rev_tree, dest, format, root, subdir, filtered=filters,
1054+ per_file_timestamps=per_file_timestamps)
1055 except errors.NoSuchExportFormat, e:
1056 raise errors.BzrCommandError('Unsupported export format: %s' % e.format)
1057
1058@@ -2911,7 +2921,7 @@
1059 hidden = True
1060 @display_command
1061 def run(self):
1062- print osutils.local_time_offset()
1063+ self.outf.write("%s\n" % osutils.local_time_offset())
1064
1065
1066
1067@@ -3168,10 +3178,11 @@
1068 raise errors.BzrCommandError("Commit refused because there are"
1069 " unknown files in the working tree.")
1070 except errors.BoundBranchOutOfDate, e:
1071- raise errors.BzrCommandError(str(e) + "\n"
1072- 'To commit to master branch, run update and then commit.\n'
1073- 'You can also pass --local to commit to continue working '
1074- 'disconnected.')
1075+ e.extra_help = ("\n"
1076+ 'To commit to master branch, run update and then commit.\n'
1077+ 'You can also pass --local to commit to continue working '
1078+ 'disconnected.')
1079+ raise
1080
1081
1082 class cmd_check(Command):
1083@@ -3339,7 +3350,7 @@
1084
1085 @display_command
1086 def printme(self, branch):
1087- print branch.nick
1088+ self.outf.write('%s\n' % branch.nick)
1089
1090
1091 class cmd_alias(Command):
1092@@ -3619,7 +3630,7 @@
1093
1094 @display_command
1095 def run(self):
1096- print "It sure does!"
1097+ self.outf.write("It sure does!\n")
1098
1099
1100 class cmd_find_merge_base(Command):
1101@@ -3645,7 +3656,7 @@
1102 graph = branch1.repository.get_graph(branch2.repository)
1103 base_rev_id = graph.find_unique_lca(last1, last2)
1104
1105- print 'merge base is revision %s' % base_rev_id
1106+ self.outf.write('merge base is revision %s\n' % base_rev_id)
1107
1108
1109 class cmd_merge(Command):
1110@@ -4444,11 +4455,11 @@
1111 doc = '(no description)'
1112 result.append((name_ver, doc, plugin.path()))
1113 for name_ver, doc, path in sorted(result):
1114- print name_ver
1115- print ' ', doc
1116+ self.outf.write("%s\n" % name_ver)
1117+ self.outf.write(" %s\n" % doc)
1118 if verbose:
1119- print ' ', path
1120- print
1121+ self.outf.write(" %s\n" % path)
1122+ self.outf.write("\n")
1123
1124
1125 class cmd_testament(Command):
1126@@ -4734,12 +4745,11 @@
1127 rev_id = b.get_rev_id(revno)
1128
1129 if rev_id is None or _mod_revision.is_null(rev_id):
1130- ui.ui_factory.note('No revisions to uncommit.')
1131+ self.outf.write('No revisions to uncommit.\n')
1132 return 1
1133
1134- log_collector = ui.ui_factory.make_output_stream()
1135 lf = log_formatter('short',
1136- to_file=log_collector,
1137+ to_file=self.outf,
1138 show_timezone='original')
1139
1140 show_log(b,
1141@@ -4750,21 +4760,22 @@
1142 end_revision=last_revno)
1143
1144 if dry_run:
1145- ui.ui_factory.note('Dry-run, pretending to remove the above revisions.')
1146+ self.outf.write('Dry-run, pretending to remove'
1147+ ' the above revisions.\n')
1148 else:
1149- ui.ui_factory.note('The above revision(s) will be removed.')
1150+ self.outf.write('The above revision(s) will be removed.\n')
1151
1152 if not force:
1153- if not ui.ui_factory.get_boolean('Are you sure [y/N]? '):
1154- ui.ui_factory.note('Canceled')
1155+ if not ui.ui_factory.get_boolean('Are you sure'):
1156+ self.outf.write('Canceled')
1157 return 0
1158
1159 mutter('Uncommitting from {%s} to {%s}',
1160 last_rev_id, rev_id)
1161 uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose,
1162 revno=revno, local=local)
1163- ui.ui_factory.note('You can restore the old tip by running:\n'
1164- ' bzr pull . -r revid:%s' % last_rev_id)
1165+ self.outf.write('You can restore the old tip by running:\n'
1166+ ' bzr pull . -r revid:%s\n' % last_rev_id)
1167
1168
1169 class cmd_break_lock(Command):
1170
1171=== modified file 'bzrlib/bundle/__init__.py'
1172--- bzrlib/bundle/__init__.py 2009-11-28 00:48:03 +0000
1173+++ bzrlib/bundle/__init__.py 2010-04-06 07:24:41 +0000
1174@@ -1,4 +1,4 @@
1175-# Copyright (C) 2005, 2006 Canonical Ltd
1176+# Copyright (C) 2005-2010 Canonical Ltd
1177 #
1178 # This program is free software; you can redistribute it and/or modify
1179 # it under the terms of the GNU General Public License as published by
1180
1181=== modified file 'bzrlib/bzrdir.py'
1182--- bzrlib/bzrdir.py 2010-02-18 04:04:19 +0000
1183+++ bzrlib/bzrdir.py 2010-04-06 07:24:41 +0000
1184@@ -396,16 +396,23 @@
1185 """Destroy the repository in this BzrDir"""
1186 raise NotImplementedError(self.destroy_repository)
1187
1188- def create_branch(self):
1189+ def create_branch(self, name=None):
1190 """Create a branch in this BzrDir.
1191
1192+ :param name: Name of the colocated branch to create, None for
1193+ the default branch.
1194+
1195 The bzrdir's format will control what branch format is created.
1196 For more control see BranchFormatXX.create(a_bzrdir).
1197 """
1198 raise NotImplementedError(self.create_branch)
1199
1200- def destroy_branch(self):
1201- """Destroy the branch in this BzrDir"""
1202+ def destroy_branch(self, name=None):
1203+ """Destroy a branch in this BzrDir.
1204+
1205+ :param name: Name of the branch to destroy, None for the default
1206+ branch.
1207+ """
1208 raise NotImplementedError(self.destroy_branch)
1209
1210 @staticmethod
1211@@ -708,7 +715,7 @@
1212 """
1213 return None
1214
1215- def get_branch_transport(self, branch_format):
1216+ def get_branch_transport(self, branch_format, name=None):
1217 """Get the transport for use by branch format in this BzrDir.
1218
1219 Note that bzr dirs that do not support format strings will raise
1220@@ -892,7 +899,8 @@
1221 BzrDir._check_supported(format, _unsupported)
1222 return format.open(transport, _found=True)
1223
1224- def open_branch(self, unsupported=False, ignore_fallbacks=False):
1225+ def open_branch(self, name=None, unsupported=False,
1226+ ignore_fallbacks=False):
1227 """Open the branch object at this BzrDir if one is present.
1228
1229 If unsupported is True, then no longer supported branch formats can
1230@@ -1036,7 +1044,7 @@
1231 """
1232 raise NotImplementedError(self.open_workingtree)
1233
1234- def has_branch(self):
1235+ def has_branch(self, name=None):
1236 """Tell if this bzrdir contains a branch.
1237
1238 Note: if you're going to open the branch, you should just go ahead
1239@@ -1044,7 +1052,7 @@
1240 branch and discards it, and that's somewhat expensive.)
1241 """
1242 try:
1243- self.open_branch()
1244+ self.open_branch(name)
1245 return True
1246 except errors.NotBranchError:
1247 return False
1248@@ -1373,11 +1381,11 @@
1249 tree.clone(result)
1250 return result
1251
1252- def create_branch(self):
1253+ def create_branch(self, name=None):
1254 """See BzrDir.create_branch."""
1255- return self._format.get_branch_format().initialize(self)
1256+ return self._format.get_branch_format().initialize(self, name=name)
1257
1258- def destroy_branch(self):
1259+ def destroy_branch(self, name=None):
1260 """See BzrDir.destroy_branch."""
1261 raise errors.UnsupportedOperation(self.destroy_branch, self)
1262
1263@@ -1439,8 +1447,10 @@
1264 raise errors.UnsupportedOperation(self.destroy_workingtree_metadata,
1265 self)
1266
1267- def get_branch_transport(self, branch_format):
1268+ def get_branch_transport(self, branch_format, name=None):
1269 """See BzrDir.get_branch_transport()."""
1270+ if name is not None:
1271+ raise errors.NoColocatedBranchSupport(self)
1272 if branch_format is None:
1273 return self.transport
1274 try:
1275@@ -1479,12 +1489,13 @@
1276 format = BzrDirFormat.get_default_format()
1277 return not isinstance(self._format, format.__class__)
1278
1279- def open_branch(self, unsupported=False, ignore_fallbacks=False):
1280+ def open_branch(self, name=None, unsupported=False,
1281+ ignore_fallbacks=False):
1282 """See BzrDir.open_branch."""
1283 from bzrlib.branch import BzrBranchFormat4
1284 format = BzrBranchFormat4()
1285 self._check_supported(format, unsupported)
1286- return format.open(self, _found=True)
1287+ return format.open(self, name, _found=True)
1288
1289 def sprout(self, url, revision_id=None, force_new_repo=False,
1290 possible_transports=None, accelerator_tree=None,
1291@@ -1607,12 +1618,14 @@
1292 """See BzrDir.can_convert_format()."""
1293 return True
1294
1295- def create_branch(self):
1296+ def create_branch(self, name=None):
1297 """See BzrDir.create_branch."""
1298- return self._format.get_branch_format().initialize(self)
1299+ return self._format.get_branch_format().initialize(self, name=name)
1300
1301- def destroy_branch(self):
1302+ def destroy_branch(self, name=None):
1303 """See BzrDir.create_branch."""
1304+ if name is not None:
1305+ raise errors.NoColocatedBranchSupport(self)
1306 self.transport.delete_tree('branch')
1307
1308 def create_repository(self, shared=False):
1309@@ -1661,8 +1674,10 @@
1310 format = BranchFormat.find_format(self)
1311 return format.get_reference(self)
1312
1313- def get_branch_transport(self, branch_format):
1314+ def get_branch_transport(self, branch_format, name=None):
1315 """See BzrDir.get_branch_transport()."""
1316+ if name is not None:
1317+ raise errors.NoColocatedBranchSupport(self)
1318 # XXX: this shouldn't implicitly create the directory if it's just
1319 # promising to get a transport -- mbp 20090727
1320 if branch_format is None:
1321@@ -1739,13 +1754,11 @@
1322 return True
1323 except errors.NoRepositoryPresent:
1324 pass
1325- try:
1326- if not isinstance(self.open_branch()._format,
1327+ for branch in self.list_branches():
1328+ if not isinstance(branch._format,
1329 format.get_branch_format().__class__):
1330 # the branch needs an upgrade.
1331 return True
1332- except errors.NotBranchError:
1333- pass
1334 try:
1335 my_wt = self.open_workingtree(recommend_upgrade=False)
1336 if not isinstance(my_wt._format,
1337@@ -1756,11 +1769,13 @@
1338 pass
1339 return False
1340
1341- def open_branch(self, unsupported=False, ignore_fallbacks=False):
1342+ def open_branch(self, name=None, unsupported=False,
1343+ ignore_fallbacks=False):
1344 """See BzrDir.open_branch."""
1345 format = self.find_branch_format()
1346 self._check_supported(format, unsupported)
1347- return format.open(self, _found=True, ignore_fallbacks=ignore_fallbacks)
1348+ return format.open(self, name=name,
1349+ _found=True, ignore_fallbacks=ignore_fallbacks)
1350
1351 def open_repository(self, unsupported=False):
1352 """See BzrDir.open_repository."""
1353@@ -1798,6 +1813,8 @@
1354 Once a format is deprecated, just deprecate the initialize and open
1355 methods on the format class. Do not deprecate the object, as the
1356 object will be created every system load.
1357+
1358+ :cvar colocated_branches: Whether this formats supports colocated branches.
1359 """
1360
1361 _default_format = None
1362@@ -1820,6 +1837,10 @@
1363
1364 _lock_file_name = 'branch-lock'
1365
1366+ colocated_branches = False
1367+ """Whether co-located branches are supported for this control dir format.
1368+ """
1369+
1370 # _lock_class must be set in subclasses to the lock type, typ.
1371 # TransportLock or LockDir
1372
1373
1374=== modified file 'bzrlib/chk_serializer.py'
1375--- bzrlib/chk_serializer.py 2009-12-03 04:55:02 +0000
1376+++ bzrlib/chk_serializer.py 2010-04-06 07:24:41 +0000
1377@@ -1,4 +1,4 @@
1378-# Copyright (C) 2008, 2009 Canonical Ltd
1379+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
1380 #
1381 # This program is free software; you can redistribute it and/or modify
1382 # it under the terms of the GNU General Public License as published by
1383
1384=== modified file 'bzrlib/cleanup.py'
1385--- bzrlib/cleanup.py 2010-02-05 03:37:52 +0000
1386+++ bzrlib/cleanup.py 2010-04-06 07:24:41 +0000
1387@@ -1,4 +1,4 @@
1388-# Copyright (C) 2009 Canonical Ltd
1389+# Copyright (C) 2009, 2010 Canonical Ltd
1390 #
1391 # This program is free software; you can redistribute it and/or modify
1392 # it under the terms of the GNU General Public License as published by
1393
1394=== modified file 'bzrlib/cmd_version_info.py'
1395--- bzrlib/cmd_version_info.py 2009-11-16 02:26:32 +0000
1396+++ bzrlib/cmd_version_info.py 2010-04-06 07:24:41 +0000
1397@@ -1,4 +1,4 @@
1398-# Copyright (C) 2005, 2006, 2009 Canonical Ltd
1399+# Copyright (C) 2005-2010 Canonical Ltd
1400 #
1401 # This program is free software; you can redistribute it and/or modify
1402 # it under the terms of the GNU General Public License as published by
1403
1404=== modified file 'bzrlib/cmdline.py'
1405--- bzrlib/cmdline.py 2010-02-12 05:40:17 +0000
1406+++ bzrlib/cmdline.py 2010-04-06 07:24:41 +0000
1407@@ -26,16 +26,16 @@
1408 def __init__(self, orig):
1409 self._iter = iter(orig)
1410 self._pushback_buffer = []
1411-
1412+
1413 def next(self):
1414 if len(self._pushback_buffer) > 0:
1415 return self._pushback_buffer.pop()
1416 else:
1417 return self._iter.next()
1418-
1419+
1420 def pushback(self, char):
1421 self._pushback_buffer.append(char)
1422-
1423+
1424 def __iter__(self):
1425 return self
1426
1427@@ -77,7 +77,7 @@
1428 def __init__(self, exit_state):
1429 self.exit_state = exit_state
1430 self.count = 1
1431-
1432+
1433 def process(self, next_char, context):
1434 if next_char == u'\\':
1435 self.count += 1
1436@@ -104,7 +104,7 @@
1437 # let exit_state handle next_char
1438 context.seq.pushback(next_char)
1439 return self.exit_state
1440-
1441+
1442 def finish(self, context):
1443 if self.count > 0:
1444 context.token.append(u'\\' * self.count)
1445@@ -129,16 +129,16 @@
1446 self.allowed_quote_chars = u'"'
1447 if single_quotes_allowed:
1448 self.allowed_quote_chars += u"'"
1449-
1450+
1451 def __iter__(self):
1452 return self
1453-
1454+
1455 def next(self):
1456 quoted, token = self._get_token()
1457 if token is None:
1458 raise StopIteration
1459 return quoted, token
1460-
1461+
1462 def _get_token(self):
1463 self.quoted = False
1464 self.token = []
1465
1466=== modified file 'bzrlib/commands.py'
1467--- bzrlib/commands.py 2010-02-12 04:02:50 +0000
1468+++ bzrlib/commands.py 2010-04-06 07:24:41 +0000
1469@@ -55,6 +55,7 @@
1470 from bzrlib.hooks import HookPoint, Hooks
1471 # Compatibility - Option used to be in commands.
1472 from bzrlib.option import Option
1473+from bzrlib.plugin import disable_plugins, load_plugins
1474 from bzrlib import registry
1475 from bzrlib.symbol_versioning import (
1476 deprecated_function,
1477@@ -198,11 +199,13 @@
1478 raise errors.BzrCommandError('unknown command "%s"' % cmd_name)
1479
1480
1481-def _get_cmd_object(cmd_name, plugins_override=True):
1482+def _get_cmd_object(cmd_name, plugins_override=True, check_missing=True):
1483 """Get a command object.
1484
1485 :param cmd_name: The name of the command.
1486 :param plugins_override: Allow plugins to override builtins.
1487+ :param check_missing: Look up commands not found in the regular index via
1488+ the get_missing_command hook.
1489 :return: A Command object instance
1490 :raises KeyError: If no command is found.
1491 """
1492@@ -218,7 +221,7 @@
1493 # We've found a non-plugin command, don't permit it to be
1494 # overridden.
1495 break
1496- if cmd is None:
1497+ if cmd is None and check_missing:
1498 for hook in Command.hooks['get_missing_command']:
1499 cmd = hook(cmd_name)
1500 if cmd is not None:
1501@@ -369,7 +372,7 @@
1502 # List of standard options directly supported
1503 self.supported_std_options = []
1504 self._operation = cleanup.OperationWithCleanups(self.run)
1505-
1506+
1507 def add_cleanup(self, cleanup_func, *args, **kwargs):
1508 """Register a function to call after self.run returns or raises.
1509
1510@@ -389,7 +392,7 @@
1511 resources (such as writing results to self.outf).
1512 """
1513 self._operation.cleanup_now()
1514-
1515+
1516 @deprecated_method(deprecated_in((2, 1, 0)))
1517 def _maybe_expand_globs(self, file_list):
1518 """Glob expand file_list if the platform does not do that itself.
1519@@ -874,6 +877,11 @@
1520 return ret
1521
1522
1523+@deprecated_function(deprecated_in((2, 2, 0)))
1524+def shlex_split_unicode(unsplit):
1525+ return cmdline.split(unsplit)
1526+
1527+
1528 def get_alias(cmd, config=None):
1529 """Return an expanded alias, or None if no alias exists.
1530
1531@@ -893,15 +901,21 @@
1532 return None
1533
1534
1535-def run_bzr(argv):
1536+def run_bzr(argv, load_plugins=load_plugins, disable_plugins=disable_plugins):
1537 """Execute a command.
1538
1539- argv
1540- The command-line arguments, without the program name from argv[0]
1541- These should already be decoded. All library/test code calling
1542- run_bzr should be passing valid strings (don't need decoding).
1543-
1544- Returns a command status or raises an exception.
1545+ :param argv: The command-line arguments, without the program name from
1546+ argv[0] These should already be decoded. All library/test code calling
1547+ run_bzr should be passing valid strings (don't need decoding).
1548+ :param load_plugins: What function to call when triggering plugin loading.
1549+ This function should take no arguments and cause all plugins to be
1550+ loaded.
1551+ :param disable_plugins: What function to call when disabling plugin
1552+ loading. This function should take no arguments and cause all plugin
1553+ loading to be prohibited (so that code paths in your application that
1554+ know about some plugins possibly being present will fail to import
1555+ those plugins even if they are installed.)
1556+ :return: Returns a command exit code or raises an exception.
1557
1558 Special master options: these must come before the command because
1559 they control how the command is interpreted.
1560@@ -972,24 +986,20 @@
1561
1562 debug.set_debug_flags_from_config()
1563
1564+ if not opt_no_plugins:
1565+ load_plugins()
1566+ else:
1567+ disable_plugins()
1568+
1569 argv = argv_copy
1570 if (not argv):
1571- from bzrlib.builtins import cmd_help
1572- cmd_help().run_argv_aliases([])
1573+ get_cmd_object('help').run_argv_aliases([])
1574 return 0
1575
1576 if argv[0] == '--version':
1577- from bzrlib.builtins import cmd_version
1578- cmd_version().run_argv_aliases([])
1579+ get_cmd_object('version').run_argv_aliases([])
1580 return 0
1581
1582- if not opt_no_plugins:
1583- from bzrlib.plugin import load_plugins
1584- load_plugins()
1585- else:
1586- from bzrlib.plugin import disable_plugins
1587- disable_plugins()
1588-
1589 alias_argv = None
1590
1591 if not opt_no_aliases:
1592@@ -1159,7 +1169,7 @@
1593 if topic and topic.startswith(self.prefix):
1594 topic = topic[len(self.prefix):]
1595 try:
1596- cmd = _get_cmd_object(topic)
1597+ cmd = _get_cmd_object(topic, check_missing=False)
1598 except KeyError:
1599 return []
1600 else:
1601
1602=== modified file 'bzrlib/commit.py'
1603--- bzrlib/commit.py 2009-10-15 02:53:30 +0000
1604+++ bzrlib/commit.py 2010-04-06 07:24:41 +0000
1605@@ -1,4 +1,4 @@
1606-# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
1607+# Copyright (C) 2005-2010 Canonical Ltd
1608 #
1609 # This program is free software; you can redistribute it and/or modify
1610 # it under the terms of the GNU General Public License as published by
1611
1612=== modified file 'bzrlib/conflicts.py'
1613--- bzrlib/conflicts.py 2010-02-11 09:51:03 +0000
1614+++ bzrlib/conflicts.py 2010-04-06 07:24:41 +0000
1615@@ -26,6 +26,7 @@
1616
1617 from bzrlib import (
1618 builtins,
1619+ cleanup,
1620 commands,
1621 errors,
1622 osutils,
1623@@ -479,16 +480,43 @@
1624 def associated_filenames(self):
1625 return [self.path + suffix for suffix in ('.BASE', '.OTHER')]
1626
1627- # FIXME: I smell something weird here and it seems we should be able to be
1628- # more coherent with some other conflict ? bzr *did* a choice there but
1629- # neither action_take_this nor action_take_other reflect that...
1630- # -- vila 20091224
1631+ def _take_it(self, tt, suffix_to_remove):
1632+ """Resolve the conflict.
1633+
1634+ :param tt: The TreeTransform where the conflict is resolved.
1635+ :param suffix_to_remove: Either 'THIS' or 'OTHER'
1636+
1637+ The resolution is symmetric, when taking THIS, OTHER is deleted and
1638+ item.THIS is renamed into item and vice-versa.
1639+ """
1640+ try:
1641+ # Delete 'item.THIS' or 'item.OTHER' depending on
1642+ # suffix_to_remove
1643+ tt.delete_contents(
1644+ tt.trans_id_tree_path(self.path + '.' + suffix_to_remove))
1645+ except errors.NoSuchFile:
1646+ # There are valid cases where 'item.suffix_to_remove' either
1647+ # never existed or was already deleted (including the case
1648+ # where the user deleted it)
1649+ pass
1650+ # Rename 'item.suffix_to_remove' (note that if
1651+ # 'item.suffix_to_remove' has been deleted, this is a no-op)
1652+ this_tid = tt.trans_id_file_id(self.file_id)
1653+ parent_tid = tt.get_tree_parent(this_tid)
1654+ tt.adjust_path(self.path, parent_tid, this_tid)
1655+ tt.apply()
1656+
1657+ def _take_it_with_cleanups(self, tree, suffix_to_remove):
1658+ tt = transform.TreeTransform(tree)
1659+ op = cleanup.OperationWithCleanups(self._take_it)
1660+ op.add_cleanup(tt.finalize)
1661+ op.run_simple(tt, suffix_to_remove)
1662+
1663 def action_take_this(self, tree):
1664- tree.remove([self.path + '.OTHER'], force=True, keep_files=False)
1665+ self._take_it_with_cleanups(tree, 'OTHER')
1666
1667 def action_take_other(self, tree):
1668- tree.remove([self.path], force=True, keep_files=False)
1669-
1670+ self._take_it_with_cleanups(tree, 'THIS')
1671
1672
1673 # FIXME: TextConflict is about a single file-id, there never is a conflict_path
1674
1675=== modified file 'bzrlib/decorators.py'
1676--- bzrlib/decorators.py 2010-01-20 16:05:28 +0000
1677+++ bzrlib/decorators.py 2010-04-06 07:24:41 +0000
1678@@ -1,4 +1,4 @@
1679-# Copyright (C) 2005 Canonical Ltd
1680+# Copyright (C) 2006-2010 Canonical Ltd
1681 #
1682 # This program is free software; you can redistribute it and/or modify
1683 # it under the terms of the GNU General Public License as published by
1684
1685=== modified file 'bzrlib/delta.py'
1686--- bzrlib/delta.py 2009-10-29 05:54:49 +0000
1687+++ bzrlib/delta.py 2010-04-06 07:24:41 +0000
1688@@ -1,4 +1,4 @@
1689-# Copyright (C) 2005, 2006 Canonical Ltd
1690+# Copyright (C) 2005-2010 Canonical Ltd
1691 #
1692 # This program is free software; you can redistribute it and/or modify
1693 # it under the terms of the GNU General Public License as published by
1694
1695=== modified file 'bzrlib/diff.py'
1696--- bzrlib/diff.py 2010-02-02 06:30:43 +0000
1697+++ bzrlib/diff.py 2010-04-06 07:24:41 +0000
1698@@ -1,4 +1,4 @@
1699-# Copyright (C) 2004, 2005, 2006 Canonical Ltd.
1700+# Copyright (C) 2005-2010 Canonical Ltd.
1701 #
1702 # This program is free software; you can redistribute it and/or modify
1703 # it under the terms of the GNU General Public License as published by
1704
1705=== modified file 'bzrlib/doc_generate/autodoc_rstx.py'
1706--- bzrlib/doc_generate/autodoc_rstx.py 2010-01-08 07:34:31 +0000
1707+++ bzrlib/doc_generate/autodoc_rstx.py 2010-04-06 07:24:41 +0000
1708@@ -1,4 +1,4 @@
1709-# Copyright (C) 2006-2007 Canonical Ltd
1710+# Copyright (C) 2006-2010 Canonical Ltd
1711 #
1712 # This program is free software; you can redistribute it and/or modify
1713 # it under the terms of the GNU General Public License as published by
1714
1715=== modified file 'bzrlib/errors.py'
1716--- bzrlib/errors.py 2010-01-20 22:32:07 +0000
1717+++ bzrlib/errors.py 2010-04-06 07:24:41 +0000
1718@@ -1,4 +1,4 @@
1719-# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
1720+# Copyright (C) 2005-2010 Canonical Ltd
1721 #
1722 # This program is free software; you can redistribute it and/or modify
1723 # it under the terms of the GNU General Public License as published by
1724@@ -1297,12 +1297,13 @@
1725 class BoundBranchOutOfDate(BzrError):
1726
1727 _fmt = ("Bound branch %(branch)s is out of date with master branch"
1728- " %(master)s.")
1729+ " %(master)s.%(extra_help)s")
1730
1731 def __init__(self, branch, master):
1732 BzrError.__init__(self)
1733 self.branch = branch
1734 self.master = master
1735+ self.extra_help = ''
1736
1737
1738 class CommitToDoubleBoundBranch(BzrError):
1739@@ -3124,3 +3125,12 @@
1740
1741 def __init__(self, path):
1742 self.path = path
1743+
1744+
1745+class NoColocatedBranchSupport(BzrError):
1746+
1747+ _fmt = ("%(bzrdir)r does not support co-located branches.")
1748+
1749+ def __init__(self, bzrdir):
1750+ self.bzrdir = bzrdir
1751+
1752
1753=== modified file 'bzrlib/export/__init__.py'
1754--- bzrlib/export/__init__.py 2010-01-29 12:04:38 +0000
1755+++ bzrlib/export/__init__.py 2010-04-06 07:24:41 +0000
1756@@ -19,7 +19,6 @@
1757 Such as non-controlled directories, tarfiles, zipfiles, etc.
1758 """
1759
1760-from bzrlib.trace import mutter
1761 import os
1762 import bzrlib.errors as errors
1763
1764@@ -55,14 +54,16 @@
1765
1766 When requesting a specific type of export, load the respective path.
1767 """
1768- def _loader(tree, dest, root, subdir, filtered):
1769+ def _loader(tree, dest, root, subdir, filtered, per_file_timestamps):
1770 mod = __import__(module, globals(), locals(), [funcname])
1771 func = getattr(mod, funcname)
1772- return func(tree, dest, root, subdir, filtered=filtered)
1773+ return func(tree, dest, root, subdir, filtered=filtered,
1774+ per_file_timestamps=per_file_timestamps)
1775 register_exporter(scheme, extensions, _loader)
1776
1777
1778-def export(tree, dest, format=None, root=None, subdir=None, filtered=False):
1779+def export(tree, dest, format=None, root=None, subdir=None, filtered=False,
1780+ per_file_timestamps=False):
1781 """Export the given Tree to the specific destination.
1782
1783 :param tree: A Tree (such as RevisionTree) to export
1784@@ -81,6 +82,9 @@
1785 a directory to start exporting from.
1786 :param filtered: If True, content filtering is applied to the
1787 files exported.
1788+ :param per_file_timestamps: Whether to use the timestamp stored in the
1789+ tree rather than now(). This will do a revision lookup
1790+ for every file so will be significantly slower.
1791 """
1792 global _exporters, _exporter_extensions
1793
1794@@ -99,7 +103,8 @@
1795 raise errors.NoSuchExportFormat(format)
1796 tree.lock_read()
1797 try:
1798- return _exporters[format](tree, dest, root, subdir, filtered=filtered)
1799+ return _exporters[format](tree, dest, root, subdir, filtered=filtered,
1800+ per_file_timestamps=per_file_timestamps)
1801 finally:
1802 tree.unlock()
1803
1804
1805=== modified file 'bzrlib/export/dir_exporter.py'
1806--- bzrlib/export/dir_exporter.py 2010-02-04 16:06:36 +0000
1807+++ bzrlib/export/dir_exporter.py 2010-04-06 07:24:41 +0000
1808@@ -18,7 +18,6 @@
1809
1810 import errno
1811 import os
1812-import StringIO
1813 import time
1814
1815 from bzrlib import errors, osutils
1816@@ -30,7 +29,8 @@
1817 from bzrlib.trace import mutter
1818
1819
1820-def dir_exporter(tree, dest, root, subdir, filtered=False):
1821+def dir_exporter(tree, dest, root, subdir, filtered=False,
1822+ per_file_timestamps=False):
1823 """Export this tree to a new directory.
1824
1825 `dest` should either not exist or should be empty. If it does not exist it
1826@@ -92,4 +92,8 @@
1827 out.writelines(chunks)
1828 finally:
1829 out.close()
1830- os.utime(fullpath, (now, now))
1831+ if per_file_timestamps:
1832+ mtime = tree.get_file_mtime(tree.path2id(relpath), relpath)
1833+ else:
1834+ mtime = now
1835+ os.utime(fullpath, (mtime, mtime))
1836
1837=== modified file 'bzrlib/export/tar_exporter.py'
1838--- bzrlib/export/tar_exporter.py 2009-03-23 14:59:43 +0000
1839+++ bzrlib/export/tar_exporter.py 2010-04-06 07:24:41 +0000
1840@@ -17,13 +17,12 @@
1841 """Export a Tree to a non-versioned directory.
1842 """
1843
1844-import os
1845 import StringIO
1846 import sys
1847 import tarfile
1848 import time
1849
1850-from bzrlib import errors, export, osutils
1851+from bzrlib import export, osutils
1852 from bzrlib.export import _export_iter_entries
1853 from bzrlib.filters import (
1854 ContentFilterContext,
1855@@ -32,7 +31,8 @@
1856 from bzrlib.trace import mutter
1857
1858
1859-def tar_exporter(tree, dest, root, subdir, compression=None, filtered=False):
1860+def tar_exporter(tree, dest, root, subdir, compression=None, filtered=False,
1861+ per_file_timestamps=False):
1862 """Export this tree to a new tar file.
1863
1864 `dest` will be created holding the contents of this tree; if it
1865@@ -52,7 +52,10 @@
1866 for dp, ie in _export_iter_entries(tree, subdir):
1867 filename = osutils.pathjoin(root, dp).encode('utf8')
1868 item = tarfile.TarInfo(filename)
1869- item.mtime = now
1870+ if per_file_timestamps:
1871+ item.mtime = tree.get_file_mtime(ie.file_id, dp)
1872+ else:
1873+ item.mtime = now
1874 if ie.kind == "file":
1875 item.type = tarfile.REGTYPE
1876 if tree.is_executable(ie.file_id):
1877@@ -89,9 +92,13 @@
1878 ball.close()
1879
1880
1881-def tgz_exporter(tree, dest, root, subdir, filtered=False):
1882- tar_exporter(tree, dest, root, subdir, compression='gz', filtered=filtered)
1883-
1884-
1885-def tbz_exporter(tree, dest, root, subdir, filtered=False):
1886- tar_exporter(tree, dest, root, subdir, compression='bz2', filtered=filtered)
1887+def tgz_exporter(tree, dest, root, subdir, filtered=False,
1888+ per_file_timestamps=False):
1889+ tar_exporter(tree, dest, root, subdir, compression='gz',
1890+ filtered=filtered, per_file_timestamps=per_file_timestamps)
1891+
1892+
1893+def tbz_exporter(tree, dest, root, subdir, filtered=False,
1894+ per_file_timestamps=False):
1895+ tar_exporter(tree, dest, root, subdir, compression='bz2',
1896+ filtered=filtered, per_file_timestamps=per_file_timestamps)
1897
1898=== modified file 'bzrlib/export/zip_exporter.py'
1899--- bzrlib/export/zip_exporter.py 2009-11-25 00:14:05 +0000
1900+++ bzrlib/export/zip_exporter.py 2010-04-06 07:24:41 +0000
1901@@ -1,4 +1,4 @@
1902-# Copyright (C) 2005 Canonical Ltd
1903+# Copyright (C) 2005, 2006, 2008, 2009, 2010 Canonical Ltd
1904 #
1905 # This program is free software; you can redistribute it and/or modify
1906 # it under the terms of the GNU General Public License as published by
1907@@ -42,7 +42,8 @@
1908 _DIR_ATTR = stat.S_IFDIR | ZIP_DIRECTORY_BIT
1909
1910
1911-def zip_exporter(tree, dest, root, subdir, filtered=False):
1912+def zip_exporter(tree, dest, root, subdir, filtered=False,
1913+ per_file_timestamps=False):
1914 """ Export this tree to a new zip file.
1915
1916 `dest` will be created holding the contents of this tree; if it
1917@@ -62,11 +63,15 @@
1918
1919 # zipfile.ZipFile switches all paths to forward
1920 # slashes anyway, so just stick with that.
1921+ if per_file_timestamps:
1922+ mtime = tree.get_file_mtime(ie.file_id, dp)
1923+ else:
1924+ mtime = now
1925 filename = osutils.pathjoin(root, dp).encode('utf8')
1926 if ie.kind == "file":
1927 zinfo = zipfile.ZipInfo(
1928 filename=filename,
1929- date_time=now)
1930+ date_time=mtime)
1931 zinfo.compress_type = compression
1932 zinfo.external_attr = _FILE_ATTR
1933 if filtered:
1934@@ -84,14 +89,14 @@
1935 # not just empty files.
1936 zinfo = zipfile.ZipInfo(
1937 filename=filename + '/',
1938- date_time=now)
1939+ date_time=mtime)
1940 zinfo.compress_type = compression
1941 zinfo.external_attr = _DIR_ATTR
1942 zipf.writestr(zinfo,'')
1943 elif ie.kind == "symlink":
1944 zinfo = zipfile.ZipInfo(
1945 filename=(filename + '.lnk'),
1946- date_time=now)
1947+ date_time=mtime)
1948 zinfo.compress_type = compression
1949 zinfo.external_attr = _FILE_ATTR
1950 zipf.writestr(zinfo, ie.symlink_target)
1951
1952=== modified file 'bzrlib/globbing.py'
1953--- bzrlib/globbing.py 2010-01-11 16:44:02 +0000
1954+++ bzrlib/globbing.py 2010-04-06 07:24:41 +0000
1955@@ -1,4 +1,4 @@
1956-# Copyright (C) 2006, 2008 Canonical Ltd
1957+# Copyright (C) 2006-2010 Canonical Ltd
1958
1959 # This program is free software; you can redistribute it and/or modify
1960 # it under the terms of the GNU General Public License as published by
1961
1962=== modified file 'bzrlib/graph.py'
1963--- bzrlib/graph.py 2009-11-30 03:16:22 +0000
1964+++ bzrlib/graph.py 2010-04-06 07:24:41 +0000
1965@@ -1,4 +1,4 @@
1966-# Copyright (C) 2007, 2008, 2009 Canonical Ltd
1967+# Copyright (C) 2007-2010 Canonical Ltd
1968 #
1969 # This program is free software; you can redistribute it and/or modify
1970 # it under the terms of the GNU General Public License as published by
1971
1972=== modified file 'bzrlib/groupcompress.py'
1973--- bzrlib/groupcompress.py 2009-12-01 03:35:25 +0000
1974+++ bzrlib/groupcompress.py 2010-04-06 07:24:41 +0000
1975@@ -1,4 +1,4 @@
1976-# Copyright (C) 2008, 2009 Canonical Ltd
1977+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
1978 #
1979 # This program is free software; you can redistribute it and/or modify
1980 # it under the terms of the GNU General Public License as published by
1981
1982=== modified file 'bzrlib/help.py'
1983--- bzrlib/help.py 2009-12-02 15:24:34 +0000
1984+++ bzrlib/help.py 2010-04-06 07:24:41 +0000
1985@@ -1,4 +1,4 @@
1986-# Copyright (C) 2004, 2005, 2006 Canonical Ltd
1987+# Copyright (C) 2005-2010 Canonical Ltd
1988 #
1989 # This program is free software; you can redistribute it and/or modify
1990 # it under the terms of the GNU General Public License as published by
1991
1992=== modified file 'bzrlib/help_topics/en/authentication.txt'
1993--- bzrlib/help_topics/en/authentication.txt 2010-01-03 03:33:10 +0000
1994+++ bzrlib/help_topics/en/authentication.txt 2010-04-06 07:24:41 +0000
1995@@ -58,10 +58,10 @@
1996 against a host. But, by using ``.htaccess`` files, for example, it is possible
1997 to define several (``user, realm, password``) for a given ``host``. So what is
1998 really needed is (``user``, ``password``, ``host``, ``path``). The ``realm`` is
1999-not taken into account in the defitions, but will displayed if bzr prompts you
2000-for a password.
2001+not taken into account in the definitions, but will displayed if bzr prompts
2002+you for a password.
2003
2004-``HTTP proxy`` can be handled as ``HTTP`` (or ``HTTPS``) by explicitely
2005+``HTTP proxy`` can be handled as ``HTTP`` (or ``HTTPS``) by explicitly
2006 specifying the appropriate port.
2007
2008 To take all schemes into account, the password will be deduced from a set of
2009@@ -165,7 +165,7 @@
2010 Source hosting provider
2011 ~~~~~~~~~~~~~~~~~~~~~~~
2012
2013-In the shp.net (fictious) domain, each project has its own site::
2014+In the shp.net (fictitious) domain, each project has its own site::
2015
2016 [shpnet domain]
2017 # we use sftp, but ssh is the scheme used for authentication
2018
2019=== modified file 'bzrlib/help_topics/en/configuration.txt'
2020--- bzrlib/help_topics/en/configuration.txt 2010-01-03 03:33:10 +0000
2021+++ bzrlib/help_topics/en/configuration.txt 2010-04-06 07:24:41 +0000
2022@@ -116,7 +116,49 @@
2023 Overriding the default site plugin directory:
2024 ``BZR_PLUGIN_PATH='/path/to/my/site/plugins:-site':+user``
2025
2026-
2027+BZR_DISABLE_PLUGINS
2028+~~~~~~~~~~~~~~~~~~~
2029+
2030+Under special circumstances (mostly when trying to diagnose a
2031+bug), it's better to disable a plugin (or several) rather than
2032+uninstalling them completely. Such plugins can be specified in
2033+the ``BZR_DISABLE_PLUGINS`` environment variable.
2034+
2035+In that case, ``bzr`` will stop loading the specified plugins and
2036+will raise an import error if you try to import them explicitly.
2037+
2038+Example:
2039+~~~~~~~~
2040+
2041+Disabling ``myplugin`` and ``yourplugin``:
2042+``BZR_DISABLE_PLUGINS='myplugin:yourplugin'``
2043+
2044+BZR_PLUGINS_AT
2045+~~~~~~~~~~~~~~
2046+
2047+When adding a new feature or working on a bug in a plugin,
2048+developers often need to use a specific version of a given
2049+plugin. Since python requires that the directory containing the
2050+code is named like the plugin itself this make it impossible to
2051+use arbitrary directory names (using a two-level directory scheme
2052+is inconvenient). ``BZR_PLUGINS_AT`` allows such directories even
2053+if they don't appear in ``BZR_PLUGIN_PATH`` .
2054+
2055+Plugins specified in this environment variable takes precedence
2056+over the ones in ``BZR_PLUGIN_PATH``.
2057+
2058+The variable specified a list of ``plugin_name@plugin path``,
2059+``plugin_name`` being the name of the plugin as it appears in
2060+python module paths, ``plugin_path`` being the path to the
2061+directory containing the plugin code itself
2062+(i.e. ``plugins/myplugin`` not ``plugins``). Use ':' as the list
2063+separator, use ';' on windows.
2064+
2065+Example:
2066+~~~~~~~~
2067+
2068+Using a specific version of ``myplugin``:
2069+``BZR_PLUGINS_AT='myplugin@/home/me/bugfixes/123456-myplugin``
2070
2071 BZRPATH
2072 ~~~~~~~
2073
2074=== modified file 'bzrlib/hooks.py'
2075--- bzrlib/hooks.py 2010-01-15 03:58:20 +0000
2076+++ bzrlib/hooks.py 2010-04-06 07:24:41 +0000
2077@@ -1,4 +1,4 @@
2078-# Copyright (C) 2007, 2008 Canonical Ltd
2079+# Copyright (C) 2007-2010 Canonical Ltd
2080 #
2081 # This program is free software; you can redistribute it and/or modify
2082 # it under the terms of the GNU General Public License as published by
2083
2084=== modified file 'bzrlib/index.py'
2085--- bzrlib/index.py 2009-12-02 17:59:15 +0000
2086+++ bzrlib/index.py 2010-04-06 07:24:41 +0000
2087@@ -1,4 +1,4 @@
2088-# Copyright (C) 2007, 2008, 2009 Canonical Ltd
2089+# Copyright (C) 2007-2010 Canonical Ltd
2090 #
2091 # This program is free software; you can redistribute it and/or modify
2092 # it under the terms of the GNU General Public License as published by
2093
2094=== modified file 'bzrlib/info.py'
2095--- bzrlib/info.py 2009-11-03 09:32:17 +0000
2096+++ bzrlib/info.py 2010-04-06 07:24:41 +0000
2097@@ -1,4 +1,4 @@
2098-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2099+# Copyright (C) 2005-2010 Canonical Ltd
2100 #
2101 # This program is free software; you can redistribute it and/or modify
2102 # it under the terms of the GNU General Public License as published by
2103
2104=== modified file 'bzrlib/inventory.py'
2105--- bzrlib/inventory.py 2009-11-13 19:19:11 +0000
2106+++ bzrlib/inventory.py 2010-04-06 07:24:41 +0000
2107@@ -1,4 +1,4 @@
2108-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2109+# Copyright (C) 2005-2010 Canonical Ltd
2110 #
2111 # This program is free software; you can redistribute it and/or modify
2112 # it under the terms of the GNU General Public License as published by
2113
2114=== modified file 'bzrlib/lockdir.py'
2115--- bzrlib/lockdir.py 2010-01-15 02:27:31 +0000
2116+++ bzrlib/lockdir.py 2010-04-06 07:24:41 +0000
2117@@ -1,4 +1,4 @@
2118-# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
2119+# Copyright (C) 2006-2010 Canonical Ltd
2120 #
2121 # This program is free software; you can redistribute it and/or modify
2122 # it under the terms of the GNU General Public License as published by
2123@@ -252,7 +252,7 @@
2124 if info is None:
2125 raise LockFailed(self, "lock was renamed into place, but "
2126 "now is missing!")
2127- if info['nonce'] != self.nonce:
2128+ if info.get('nonce') != self.nonce:
2129 self._trace("rename succeeded, "
2130 "but lock is still held by someone else")
2131 raise LockContention(self)
2132@@ -430,7 +430,7 @@
2133 def peek(self):
2134 """Check if the lock is held by anyone.
2135
2136- If it is held, this returns the lock info structure as a rio Stanza,
2137+ If it is held, this returns the lock info structure as a dict
2138 which contains some information about the current lock holder.
2139 Otherwise returns None.
2140 """
2141@@ -459,8 +459,14 @@
2142 return s.to_string()
2143
2144 def _parse_info(self, info_bytes):
2145- # TODO: Handle if info_bytes is empty
2146- return rio.read_stanza(osutils.split_lines(info_bytes)).as_dict()
2147+ stanza = rio.read_stanza(osutils.split_lines(info_bytes))
2148+ if stanza is None:
2149+ # see bug 185013; we fairly often end up with the info file being
2150+ # empty after an interruption; we could log a message here but
2151+ # there may not be much we can say
2152+ return {}
2153+ else:
2154+ return stanza.as_dict()
2155
2156 def attempt_lock(self):
2157 """Take the lock; fail if it's already held.
2158@@ -611,11 +617,16 @@
2159 def _format_lock_info(self, info):
2160 """Turn the contents of peek() into something for the user"""
2161 lock_url = self.transport.abspath(self.path)
2162- delta = time.time() - int(info['start_time'])
2163+ start_time = info.get('start_time')
2164+ if start_time is None:
2165+ time_ago = '(unknown)'
2166+ else:
2167+ time_ago = format_delta(time.time() - int(info['start_time']))
2168 return [
2169 'lock %s' % (lock_url,),
2170- 'held by %(user)s on host %(hostname)s [process #%(pid)s]' % info,
2171- 'locked %s' % (format_delta(delta),),
2172+ 'held by %s on host %s [process #%s]' %
2173+ tuple([info.get(x, '<unknown>') for x in ['user', 'hostname', 'pid']]),
2174+ 'locked %s' % (time_ago,),
2175 ]
2176
2177 def validate_token(self, token):
2178
2179=== modified file 'bzrlib/merge.py'
2180--- bzrlib/merge.py 2010-02-12 12:22:11 +0000
2181+++ bzrlib/merge.py 2010-04-06 07:24:41 +0000
2182@@ -130,7 +130,7 @@
2183 """
2184 affected_files = self.affected_files
2185 if affected_files is None:
2186- config = self.merger.this_tree.branch.get_config()
2187+ config = self.merger.this_branch.get_config()
2188 # Until bzr provides a better policy for caching the config, we
2189 # just add the part we're interested in to the params to avoid
2190 # reading the config files repeatedly (bazaar.conf, location.conf,
2191@@ -1173,6 +1173,7 @@
2192 return 'conflict'
2193
2194 @staticmethod
2195+ @deprecated_method(deprecated_in((2, 2, 0)))
2196 def scalar_three_way(this_tree, base_tree, other_tree, file_id, key):
2197 """Do a three-way test on a scalar.
2198 Return "this", "other" or "conflict", depending whether a value wins.
2199
2200=== modified file 'bzrlib/merge_directive.py'
2201--- bzrlib/merge_directive.py 2009-11-28 00:48:03 +0000
2202+++ bzrlib/merge_directive.py 2010-04-06 07:24:41 +0000
2203@@ -1,4 +1,4 @@
2204-# Copyright (C) 2007 Canonical Ltd
2205+# Copyright (C) 2007-2010 Canonical Ltd
2206 #
2207 # This program is free software; you can redistribute it and/or modify
2208 # it under the terms of the GNU General Public License as published by
2209
2210=== modified file 'bzrlib/msgeditor.py'
2211--- bzrlib/msgeditor.py 2010-01-12 04:31:02 +0000
2212+++ bzrlib/msgeditor.py 2010-04-06 07:24:41 +0000
2213@@ -1,4 +1,4 @@
2214-# Copyright (C) 2005, 2006, 2009 Canonical Ltd
2215+# Copyright (C) 2005-2010 Canonical Ltd
2216 #
2217 # This program is free software; you can redistribute it and/or modify
2218 # it under the terms of the GNU General Public License as published by
2219
2220=== modified file 'bzrlib/osutils.py'
2221--- bzrlib/osutils.py 2010-02-11 16:32:32 +0000
2222+++ bzrlib/osutils.py 2010-04-06 07:24:41 +0000
2223@@ -21,11 +21,11 @@
2224 S_ISCHR, S_ISBLK, S_ISFIFO, S_ISSOCK)
2225 import sys
2226 import time
2227+import codecs
2228 import warnings
2229
2230 from bzrlib.lazy_import import lazy_import
2231 lazy_import(globals(), """
2232-import codecs
2233 from datetime import datetime
2234 import errno
2235 from ntpath import (abspath as _nt_abspath,
2236@@ -85,8 +85,11 @@
2237 # be opened in binary mode, rather than text mode.
2238 # On other platforms, O_BINARY doesn't exist, because
2239 # they always open in binary mode, so it is okay to
2240-# OR with 0 on those platforms
2241+# OR with 0 on those platforms.
2242+# O_NOINHERIT and O_TEXT exists only on win32 too.
2243 O_BINARY = getattr(os, 'O_BINARY', 0)
2244+O_TEXT = getattr(os, 'O_TEXT', 0)
2245+O_NOINHERIT = getattr(os, 'O_NOINHERIT', 0)
2246
2247
2248 def get_unicode_argv():
2249@@ -663,7 +666,7 @@
2250 def sha_file_by_name(fname):
2251 """Calculate the SHA1 of a file by reading the full text"""
2252 s = sha()
2253- f = os.open(fname, os.O_RDONLY | O_BINARY)
2254+ f = os.open(fname, os.O_RDONLY | O_BINARY | O_NOINHERIT)
2255 try:
2256 while True:
2257 b = os.read(f, 1<<16)
2258@@ -1346,6 +1349,27 @@
2259 normalized_filename = _inaccessible_normalized_filename
2260
2261
2262+def set_signal_handler(signum, handler, restart_syscall=True):
2263+ """A wrapper for signal.signal that also calls siginterrupt(signum, False)
2264+ on platforms that support that.
2265+
2266+ :param restart_syscall: if set, allow syscalls interrupted by a signal to
2267+ automatically restart (by calling `signal.siginterrupt(signum,
2268+ False)`). May be ignored if the feature is not available on this
2269+ platform or Python version.
2270+ """
2271+ old_handler = signal.signal(signum, handler)
2272+ if restart_syscall:
2273+ try:
2274+ siginterrupt = signal.siginterrupt
2275+ except AttributeError: # siginterrupt doesn't exist on this platform, or for this version of
2276+ # Python.
2277+ pass
2278+ else:
2279+ siginterrupt(signum, False)
2280+ return old_handler
2281+
2282+
2283 default_terminal_width = 80
2284 """The default terminal width for ttys.
2285
2286@@ -1440,12 +1464,21 @@
2287 if width is not None:
2288 os.environ['COLUMNS'] = str(width)
2289
2290-if sys.platform == 'win32':
2291- # Martin (gz) mentioned WINDOW_BUFFER_SIZE_RECORD from ReadConsoleInput but
2292- # I've no idea how to plug that in the current design -- vila 20091216
2293- pass
2294-else:
2295- signal.signal(signal.SIGWINCH, _terminal_size_changed)
2296+
2297+_registered_sigwinch = False
2298+
2299+def watch_sigwinch():
2300+ """Register for SIGWINCH, once and only once."""
2301+ global _registered_sigwinch
2302+ if not _registered_sigwinch:
2303+ if sys.platform == 'win32':
2304+ # Martin (gz) mentioned WINDOW_BUFFER_SIZE_RECORD from
2305+ # ReadConsoleInput but I've no idea how to plug that in
2306+ # the current design -- vila 20091216
2307+ pass
2308+ else:
2309+ set_signal_handler(signal.SIGWINCH, _terminal_size_changed)
2310+ _registered_sigwinch = True
2311
2312
2313 def supports_executable():
2314@@ -2108,3 +2141,46 @@
2315 else:
2316 data, _ = self.encode(object, self.errors)
2317 self.stream.write(data)
2318+
2319+if sys.platform == 'win32':
2320+ def open_file(filename, mode='r', bufsize=-1):
2321+ """This function is used to override the ``open`` builtin.
2322+
2323+ But it uses O_NOINHERIT flag so the file handle is not inherited by
2324+ child processes. Deleting or renaming a closed file opened with this
2325+ function is not blocking child processes.
2326+ """
2327+ writing = 'w' in mode
2328+ appending = 'a' in mode
2329+ updating = '+' in mode
2330+ binary = 'b' in mode
2331+
2332+ flags = O_NOINHERIT
2333+ # see http://msdn.microsoft.com/en-us/library/yeby3zcb%28VS.71%29.aspx
2334+ # for flags for each modes.
2335+ if binary:
2336+ flags |= O_BINARY
2337+ else:
2338+ flags |= O_TEXT
2339+
2340+ if writing:
2341+ if updating:
2342+ flags |= os.O_RDWR
2343+ else:
2344+ flags |= os.O_WRONLY
2345+ flags |= os.O_CREAT | os.O_TRUNC
2346+ elif appending:
2347+ if updating:
2348+ flags |= os.O_RDWR
2349+ else:
2350+ flags |= os.O_WRONLY
2351+ flags |= os.O_CREAT | os.O_APPEND
2352+ else: #reading
2353+ if updating:
2354+ flags |= os.O_RDWR
2355+ else:
2356+ flags |= os.O_RDONLY
2357+
2358+ return os.fdopen(os.open(filename, flags), mode, bufsize)
2359+else:
2360+ open_file = open
2361
2362=== modified file 'bzrlib/patches.py'
2363--- bzrlib/patches.py 2009-11-03 15:45:56 +0000
2364+++ bzrlib/patches.py 2010-04-06 07:24:41 +0000
2365@@ -1,4 +1,4 @@
2366-# Copyright (C) 2004 - 2006, 2008 Aaron Bentley, Canonical Ltd
2367+# Copyright (C) 2005-2010 Aaron Bentley, Canonical Ltd
2368 # <aaron.bentley@utoronto.ca>
2369 #
2370 # This program is free software; you can redistribute it and/or modify
2371@@ -250,7 +250,13 @@
2372 return shift
2373
2374
2375-def iter_hunks(iter_lines):
2376+def iter_hunks(iter_lines, allow_dirty=False):
2377+ '''
2378+ :arg iter_lines: iterable of lines to parse for hunks
2379+ :kwarg allow_dirty: If True, when we encounter something that is not
2380+ a hunk header when we're looking for one, assume the rest of the lines
2381+ are not part of the patch (comments or other junk). Default False
2382+ '''
2383 hunk = None
2384 for line in iter_lines:
2385 if line == "\n":
2386@@ -260,7 +266,15 @@
2387 continue
2388 if hunk is not None:
2389 yield hunk
2390- hunk = hunk_from_header(line)
2391+ try:
2392+ hunk = hunk_from_header(line)
2393+ except MalformedHunkHeader:
2394+ if allow_dirty:
2395+ # If the line isn't a hunk header, then we've reached the end
2396+ # of this patch and there's "junk" at the end. Ignore the
2397+ # rest of this patch.
2398+ return
2399+ raise
2400 orig_size = 0
2401 mod_size = 0
2402 while orig_size < hunk.orig_range or mod_size < hunk.mod_range:
2403@@ -339,7 +353,12 @@
2404 pos += 1
2405
2406
2407-def parse_patch(iter_lines):
2408+def parse_patch(iter_lines, allow_dirty=False):
2409+ '''
2410+ :arg iter_lines: iterable of lines to parse
2411+ :kwarg allow_dirty: If True, allow the patch to have trailing junk.
2412+ Default False
2413+ '''
2414 iter_lines = iter_lines_handle_nl(iter_lines)
2415 try:
2416 (orig_name, mod_name) = get_patch_names(iter_lines)
2417@@ -347,15 +366,29 @@
2418 return BinaryPatch(e.orig_name, e.mod_name)
2419 else:
2420 patch = Patch(orig_name, mod_name)
2421- for hunk in iter_hunks(iter_lines):
2422+ for hunk in iter_hunks(iter_lines, allow_dirty):
2423 patch.hunks.append(hunk)
2424 return patch
2425
2426
2427-def iter_file_patch(iter_lines):
2428+def iter_file_patch(iter_lines, allow_dirty=False):
2429+ '''
2430+ :arg iter_lines: iterable of lines to parse for patches
2431+ :kwarg allow_dirty: If True, allow comments and other non-patch text
2432+ before the first patch. Note that the algorithm here can only find
2433+ such text before any patches have been found. Comments after the
2434+ first patch are stripped away in iter_hunks() if it is also passed
2435+ allow_dirty=True. Default False.
2436+ '''
2437+ ### FIXME: Docstring is not quite true. We allow certain comments no
2438+ # matter what, If they startwith '===', '***', or '#' Someone should
2439+ # reexamine this logic and decide if we should include those in
2440+ # allow_dirty or restrict those to only being before the patch is found
2441+ # (as allow_dirty does).
2442 regex = re.compile(binary_files_re)
2443 saved_lines = []
2444 orig_range = 0
2445+ beginning = True
2446 for line in iter_lines:
2447 if line.startswith('=== ') or line.startswith('*** '):
2448 continue
2449@@ -365,7 +398,12 @@
2450 if line.startswith('-') or line.startswith(' '):
2451 orig_range -= 1
2452 elif line.startswith('--- ') or regex.match(line):
2453- if len(saved_lines) > 0:
2454+ if allow_dirty and beginning:
2455+ # Patches can have "junk" at the beginning
2456+ # Stripping junk from the end of patches is handled when we
2457+ # parse the patch
2458+ beginning = False
2459+ elif len(saved_lines) > 0:
2460 yield saved_lines
2461 saved_lines = []
2462 elif line.startswith('@@'):
2463@@ -397,8 +435,15 @@
2464 yield last_line
2465
2466
2467-def parse_patches(iter_lines):
2468- return [parse_patch(f.__iter__()) for f in iter_file_patch(iter_lines)]
2469+def parse_patches(iter_lines, allow_dirty=False):
2470+ '''
2471+ :arg iter_lines: iterable of lines to parse for patches
2472+ :kwarg allow_dirty: If True, allow text that's not part of the patch at
2473+ selected places. This includes comments before and after a patch
2474+ for instance. Default False.
2475+ '''
2476+ return [parse_patch(f.__iter__(), allow_dirty) for f in
2477+ iter_file_patch(iter_lines, allow_dirty)]
2478
2479
2480 def difference_index(atext, btext):
2481
2482=== modified file 'bzrlib/plugin.py'
2483--- bzrlib/plugin.py 2010-02-10 02:03:20 +0000
2484+++ bzrlib/plugin.py 2010-04-06 07:24:41 +0000
2485@@ -1,4 +1,4 @@
2486-# Copyright (C) 2004, 2005, 2007, 2008, 2010 Canonical Ltd
2487+# Copyright (C) 2005-2010 Canonical Ltd
2488 #
2489 # This program is free software; you can redistribute it and/or modify
2490 # it under the terms of the GNU General Public License as published by
2491@@ -67,15 +67,6 @@
2492 return _plugins_disabled
2493
2494
2495-@deprecated_function(deprecated_in((2, 0, 0)))
2496-def get_default_plugin_path():
2497- """Get the DEFAULT_PLUGIN_PATH"""
2498- global DEFAULT_PLUGIN_PATH
2499- if DEFAULT_PLUGIN_PATH is None:
2500- DEFAULT_PLUGIN_PATH = osutils.pathjoin(config.config_dir(), 'plugins')
2501- return DEFAULT_PLUGIN_PATH
2502-
2503-
2504 def disable_plugins():
2505 """Disable loading plugins.
2506
2507@@ -100,6 +91,19 @@
2508 if path is None:
2509 path = get_standard_plugins_path()
2510 _mod_plugins.__path__ = path
2511+ PluginImporter.reset()
2512+ # Set up a blacklist for disabled plugins
2513+ disabled_plugins = os.environ.get('BZR_DISABLE_PLUGINS', None)
2514+ if disabled_plugins is not None:
2515+ for name in disabled_plugins.split(os.pathsep):
2516+ PluginImporter.blacklist.add('bzrlib.plugins.' + name)
2517+ # Set up a the specific paths for plugins
2518+ specific_plugins = os.environ.get('BZR_PLUGINS_AT', None)
2519+ if specific_plugins is not None:
2520+ for spec in specific_plugins.split(os.pathsep):
2521+ plugin_name, plugin_path = spec.split('@')
2522+ PluginImporter.specific_paths[
2523+ 'bzrlib.plugins.%s' % plugin_name] = plugin_path
2524 return path
2525
2526
2527@@ -188,12 +192,12 @@
2528 paths = []
2529 for p in env_paths + defaults:
2530 if p.startswith('+'):
2531- # Resolve reference if they are known
2532+ # Resolve references if they are known
2533 try:
2534 p = refs[p[1:]]
2535 except KeyError:
2536- # Leave them untouched otherwise, user may have paths starting
2537- # with '+'...
2538+ # Leave them untouched so user can still use paths starting
2539+ # with '+'
2540 pass
2541 _append_new_path(paths, p)
2542
2543@@ -211,7 +215,7 @@
2544 files (and whatever other extensions are used in the platform,
2545 such as *.pyd).
2546
2547- load_from_dirs() provides the underlying mechanism and is called with
2548+ load_from_path() provides the underlying mechanism and is called with
2549 the default directory list to provide the normal behaviour.
2550
2551 :param path: The list of paths to search for plugins. By default,
2552@@ -240,6 +244,11 @@
2553
2554 The python module path for bzrlib.plugins will be modified to be 'dirs'.
2555 """
2556+ # Explicitly load the plugins with a specific path
2557+ for fullname, path in PluginImporter.specific_paths.iteritems():
2558+ name = fullname[len('bzrlib.plugins.'):]
2559+ _load_plugin_module(name, path)
2560+
2561 # We need to strip the trailing separators here as well as in the
2562 # set_plugins_path function because calling code can pass anything in to
2563 # this function, and since it sets plugins.__path__, it should set it to
2564@@ -259,70 +268,99 @@
2565 load_from_dirs = load_from_path
2566
2567
2568+def _find_plugin_module(dir, name):
2569+ """Check if there is a valid python module that can be loaded as a plugin.
2570+
2571+ :param dir: The directory where the search is performed.
2572+ :param path: An existing file path, either a python file or a package
2573+ directory.
2574+
2575+ :return: (name, path, description) name is the module name, path is the
2576+ file to load and description is the tuple returned by
2577+ imp.get_suffixes().
2578+ """
2579+ path = osutils.pathjoin(dir, name)
2580+ if os.path.isdir(path):
2581+ # Check for a valid __init__.py file, valid suffixes depends on -O and
2582+ # can be .py, .pyc and .pyo
2583+ for suffix, mode, kind in imp.get_suffixes():
2584+ if kind not in (imp.PY_SOURCE, imp.PY_COMPILED):
2585+ # We don't recognize compiled modules (.so, .dll, etc)
2586+ continue
2587+ init_path = osutils.pathjoin(path, '__init__' + suffix)
2588+ if os.path.isfile(init_path):
2589+ return name, init_path, (suffix, mode, kind)
2590+ else:
2591+ for suffix, mode, kind in imp.get_suffixes():
2592+ if name.endswith(suffix):
2593+ # Clean up the module name
2594+ name = name[:-len(suffix)]
2595+ if kind == imp.C_EXTENSION and name.endswith('module'):
2596+ name = name[:-len('module')]
2597+ return name, path, (suffix, mode, kind)
2598+ # There is no python module here
2599+ return None, None, (None, None, None)
2600+
2601+
2602+def _load_plugin_module(name, dir):
2603+ """Load plugin name from dir.
2604+
2605+ :param name: The plugin name in the bzrlib.plugins namespace.
2606+ :param dir: The directory the plugin is loaded from for error messages.
2607+ """
2608+ if ('bzrlib.plugins.%s' % name) in PluginImporter.blacklist:
2609+ return
2610+ try:
2611+ exec "import bzrlib.plugins.%s" % name in {}
2612+ except KeyboardInterrupt:
2613+ raise
2614+ except errors.IncompatibleAPI, e:
2615+ trace.warning("Unable to load plugin %r. It requested API version "
2616+ "%s of module %s but the minimum exported version is %s, and "
2617+ "the maximum is %s" %
2618+ (name, e.wanted, e.api, e.minimum, e.current))
2619+ except Exception, e:
2620+ trace.warning("%s" % e)
2621+ if re.search('\.|-| ', name):
2622+ sanitised_name = re.sub('[-. ]', '_', name)
2623+ if sanitised_name.startswith('bzr_'):
2624+ sanitised_name = sanitised_name[len('bzr_'):]
2625+ trace.warning("Unable to load %r in %r as a plugin because the "
2626+ "file path isn't a valid module name; try renaming "
2627+ "it to %r." % (name, dir, sanitised_name))
2628+ else:
2629+ trace.warning('Unable to load plugin %r from %r' % (name, dir))
2630+ trace.log_exception_quietly()
2631+ if 'error' in debug.debug_flags:
2632+ trace.print_exception(sys.exc_info(), sys.stderr)
2633+
2634+
2635 def load_from_dir(d):
2636 """Load the plugins in directory d.
2637
2638 d must be in the plugins module path already.
2639+ This function is called once for each directory in the module path.
2640 """
2641- # Get the list of valid python suffixes for __init__.py?
2642- # this includes .py, .pyc, and .pyo (depending on if we are running -O)
2643- # but it doesn't include compiled modules (.so, .dll, etc)
2644- valid_suffixes = [suffix for suffix, mod_type, flags in imp.get_suffixes()
2645- if flags in (imp.PY_SOURCE, imp.PY_COMPILED)]
2646- package_entries = ['__init__'+suffix for suffix in valid_suffixes]
2647 plugin_names = set()
2648- for f in os.listdir(d):
2649- path = osutils.pathjoin(d, f)
2650- if os.path.isdir(path):
2651- for entry in package_entries:
2652- # This directory should be a package, and thus added to
2653- # the list
2654- if os.path.isfile(osutils.pathjoin(path, entry)):
2655- break
2656- else: # This directory is not a package
2657- continue
2658- else:
2659- for suffix_info in imp.get_suffixes():
2660- if f.endswith(suffix_info[0]):
2661- f = f[:-len(suffix_info[0])]
2662- if suffix_info[2] == imp.C_EXTENSION and f.endswith('module'):
2663- f = f[:-len('module')]
2664- break
2665+ for p in os.listdir(d):
2666+ name, path, desc = _find_plugin_module(d, p)
2667+ if name is not None:
2668+ if name == '__init__':
2669+ # We do nothing with the __init__.py file in directories from
2670+ # the bzrlib.plugins module path, we may want to, one day
2671+ # -- vila 20100316.
2672+ continue # We don't load __init__.py in the plugins dirs
2673+ elif getattr(_mod_plugins, name, None) is not None:
2674+ # The module has already been loaded from another directory
2675+ # during a previous call.
2676+ # FIXME: There should be a better way to report masked plugins
2677+ # -- vila 20100316
2678+ trace.mutter('Plugin name %s already loaded', name)
2679 else:
2680- continue
2681- if f == '__init__':
2682- continue # We don't load __init__.py again in the plugin dir
2683- elif getattr(_mod_plugins, f, None):
2684- trace.mutter('Plugin name %s already loaded', f)
2685- else:
2686- # trace.mutter('add plugin name %s', f)
2687- plugin_names.add(f)
2688+ plugin_names.add(name)
2689
2690 for name in plugin_names:
2691- try:
2692- exec "import bzrlib.plugins.%s" % name in {}
2693- except KeyboardInterrupt:
2694- raise
2695- except errors.IncompatibleAPI, e:
2696- trace.warning("Unable to load plugin %r. It requested API version "
2697- "%s of module %s but the minimum exported version is %s, and "
2698- "the maximum is %s" %
2699- (name, e.wanted, e.api, e.minimum, e.current))
2700- except Exception, e:
2701- trace.warning("%s" % e)
2702- ## import pdb; pdb.set_trace()
2703- if re.search('\.|-| ', name):
2704- sanitised_name = re.sub('[-. ]', '_', name)
2705- if sanitised_name.startswith('bzr_'):
2706- sanitised_name = sanitised_name[len('bzr_'):]
2707- trace.warning("Unable to load %r in %r as a plugin because the "
2708- "file path isn't a valid module name; try renaming "
2709- "it to %r." % (name, d, sanitised_name))
2710- else:
2711- trace.warning('Unable to load plugin %r from %r' % (name, d))
2712- trace.log_exception_quietly()
2713- if 'error' in debug.debug_flags:
2714- trace.print_exception(sys.exc_info(), sys.stderr)
2715+ _load_plugin_module(name, d)
2716
2717
2718 def plugins():
2719@@ -485,3 +523,77 @@
2720 return version_string
2721
2722 __version__ = property(_get__version__)
2723+
2724+
2725+class _PluginImporter(object):
2726+ """An importer tailored to bzr specific needs.
2727+
2728+ This is a singleton that takes care of:
2729+ - disabled plugins specified in 'blacklist',
2730+ - plugins that needs to be loaded from specific directories.
2731+ """
2732+
2733+ def __init__(self):
2734+ self.reset()
2735+
2736+ def reset(self):
2737+ self.blacklist = set()
2738+ self.specific_paths = {}
2739+
2740+ def find_module(self, fullname, parent_path=None):
2741+ """Search a plugin module.
2742+
2743+ Disabled plugins raise an import error, plugins with specific paths
2744+ returns a specific loader.
2745+
2746+ :return: None if the plugin doesn't need special handling, self
2747+ otherwise.
2748+ """
2749+ if not fullname.startswith('bzrlib.plugins.'):
2750+ return None
2751+ if fullname in self.blacklist:
2752+ raise ImportError('%s is disabled' % fullname)
2753+ if fullname in self.specific_paths:
2754+ return self
2755+ return None
2756+
2757+ def load_module(self, fullname):
2758+ """Load a plugin from a specific directory."""
2759+ # We are called only for specific paths
2760+ plugin_path = self.specific_paths[fullname]
2761+ loading_path = None
2762+ package = False
2763+ if os.path.isdir(plugin_path):
2764+ for suffix, mode, kind in imp.get_suffixes():
2765+ if kind not in (imp.PY_SOURCE, imp.PY_COMPILED):
2766+ # We don't recognize compiled modules (.so, .dll, etc)
2767+ continue
2768+ init_path = osutils.pathjoin(plugin_path, '__init__' + suffix)
2769+ if os.path.isfile(init_path):
2770+ loading_path = init_path
2771+ package = True
2772+ break
2773+ else:
2774+ for suffix, mode, kind in imp.get_suffixes():
2775+ if plugin_path.endswith(suffix):
2776+ loading_path = plugin_path
2777+ break
2778+ if loading_path is None:
2779+ raise ImportError('%s cannot be loaded from %s'
2780+ % (fullname, plugin_path))
2781+ f = open(loading_path, mode)
2782+ try:
2783+ mod = imp.load_module(fullname, f, loading_path,
2784+ (suffix, mode, kind))
2785+ if package:
2786+ # The plugin can contain modules, so be ready
2787+ mod.__path__ = [plugin_path]
2788+ mod.__package__ = fullname
2789+ return mod
2790+ finally:
2791+ f.close()
2792+
2793+
2794+# Install a dedicated importer for plugins requiring special handling
2795+PluginImporter = _PluginImporter()
2796+sys.meta_path.append(PluginImporter)
2797
2798=== modified file 'bzrlib/plugins/launchpad/__init__.py'
2799--- bzrlib/plugins/launchpad/__init__.py 2010-02-18 04:10:53 +0000
2800+++ bzrlib/plugins/launchpad/__init__.py 2010-04-06 07:24:41 +0000
2801@@ -1,4 +1,4 @@
2802-# Copyright (C) 2006 - 2010 Canonical Ltd
2803+# Copyright (C) 2006-2010 Canonical Ltd
2804 #
2805 # This program is free software; you can redistribute it and/or modify
2806 # it under the terms of the GNU General Public License as published by
2807@@ -17,7 +17,7 @@
2808 """Launchpad.net integration plugin for Bazaar."""
2809
2810 # The XMLRPC server address can be overridden by setting the environment
2811-# variable $BZR_LP_XMLRPL_URL
2812+# variable $BZR_LP_XMLRPC_URL
2813
2814 # see http://bazaar-vcs.org/Specs/BranchRegistrationTool
2815
2816
2817=== modified file 'bzrlib/plugins/launchpad/lp_api.py'
2818--- bzrlib/plugins/launchpad/lp_api.py 2010-02-18 03:44:44 +0000
2819+++ bzrlib/plugins/launchpad/lp_api.py 2010-04-06 07:24:41 +0000
2820@@ -1,4 +1,4 @@
2821-# Copyright (C) 2009 Canonical Ltd
2822+# Copyright (C) 2009, 2010 Canonical Ltd
2823 #
2824 # This program is free software; you can redistribute it and/or modify
2825 # it under the terms of the GNU General Public License as published by
2826
2827=== modified file 'bzrlib/plugins/launchpad/lp_directory.py'
2828--- bzrlib/plugins/launchpad/lp_directory.py 2009-07-03 14:24:23 +0000
2829+++ bzrlib/plugins/launchpad/lp_directory.py 2010-04-06 07:24:41 +0000
2830@@ -1,4 +1,4 @@
2831-# Copyright (C) 2007, 2008 Canonical Ltd
2832+# Copyright (C) 2007-2010 Canonical Ltd
2833 #
2834 # This program is free software; you can redistribute it and/or modify
2835 # it under the terms of the GNU General Public License as published by
2836
2837=== modified file 'bzrlib/plugins/launchpad/test_lp_api.py'
2838--- bzrlib/plugins/launchpad/test_lp_api.py 2010-01-25 17:48:22 +0000
2839+++ bzrlib/plugins/launchpad/test_lp_api.py 2010-04-06 07:24:41 +0000
2840@@ -1,4 +1,4 @@
2841-# Copyright (C) 2009 Canonical Ltd
2842+# Copyright (C) 2009, 2010 Canonical Ltd
2843 #
2844 # This program is free software; you can redistribute it and/or modify
2845 # it under the terms of the GNU General Public License as published by
2846
2847=== modified file 'bzrlib/plugins/launchpad/test_lp_directory.py'
2848--- bzrlib/plugins/launchpad/test_lp_directory.py 2010-01-25 15:55:48 +0000
2849+++ bzrlib/plugins/launchpad/test_lp_directory.py 2010-04-06 07:24:41 +0000
2850@@ -1,4 +1,4 @@
2851-# Copyright (C) 2007, 2008 Canonical Ltd
2852+# Copyright (C) 2007-2010 Canonical Ltd
2853 #
2854 # This program is free software; you can redistribute it and/or modify
2855 # it under the terms of the GNU General Public License as published by
2856
2857=== modified file 'bzrlib/plugins/launchpad/test_lp_open.py'
2858--- bzrlib/plugins/launchpad/test_lp_open.py 2009-12-08 10:04:18 +0000
2859+++ bzrlib/plugins/launchpad/test_lp_open.py 2010-04-06 07:24:41 +0000
2860@@ -1,4 +1,4 @@
2861-# Copyright (C) 2009 Canonical Ltd
2862+# Copyright (C) 2009, 2010 Canonical Ltd
2863 #
2864 # This program is free software; you can redistribute it and/or modify
2865 # it under the terms of the GNU General Public License as published by
2866
2867=== modified file 'bzrlib/progress.py'
2868--- bzrlib/progress.py 2010-02-10 17:52:08 +0000
2869+++ bzrlib/progress.py 2010-04-06 07:24:41 +0000
2870@@ -316,8 +316,3 @@
2871 else:
2872 self.cur_phase += 1
2873 self.pb.update(self.message, self.cur_phase, self.total)
2874-
2875-
2876-_progress_bar_types = {}
2877-_progress_bar_types['dummy'] = DummyProgress
2878-_progress_bar_types['none'] = DummyProgress
2879
2880=== modified file 'bzrlib/reconcile.py'
2881--- bzrlib/reconcile.py 2010-01-07 01:30:20 +0000
2882+++ bzrlib/reconcile.py 2010-04-06 07:24:41 +0000
2883@@ -1,4 +1,4 @@
2884-# Copyright (C) 2005, 2006 Canonical Ltd
2885+# Copyright (C) 2006-2010 Canonical Ltd
2886 #
2887 # This program is free software; you can redistribute it and/or modify
2888 # it under the terms of the GNU General Public License as published by
2889
2890=== modified file 'bzrlib/reconfigure.py'
2891--- bzrlib/reconfigure.py 2009-10-06 14:40:37 +0000
2892+++ bzrlib/reconfigure.py 2010-04-06 07:24:41 +0000
2893@@ -368,7 +368,7 @@
2894 local_branch = self.local_branch
2895 if self._create_reference:
2896 format = branch.BranchReferenceFormat().initialize(self.bzrdir,
2897- reference_branch)
2898+ target_branch=reference_branch)
2899 if self._destroy_tree:
2900 self.bzrdir.destroy_workingtree()
2901 if self._create_tree:
2902
2903=== modified file 'bzrlib/remote.py'
2904--- bzrlib/remote.py 2010-02-13 02:15:58 +0000
2905+++ bzrlib/remote.py 2010-04-06 07:24:41 +0000
2906@@ -242,12 +242,14 @@
2907 self._ensure_real()
2908 self._real_bzrdir.destroy_repository()
2909
2910- def create_branch(self):
2911+ def create_branch(self, name=None):
2912 # as per meta1 formats - just delegate to the format object which may
2913 # be parameterised.
2914- real_branch = self._format.get_branch_format().initialize(self)
2915+ real_branch = self._format.get_branch_format().initialize(self,
2916+ name=name)
2917 if not isinstance(real_branch, RemoteBranch):
2918- result = RemoteBranch(self, self.find_repository(), real_branch)
2919+ result = RemoteBranch(self, self.find_repository(), real_branch,
2920+ name=name)
2921 else:
2922 result = real_branch
2923 # BzrDir.clone_on_transport() uses the result of create_branch but does
2924@@ -259,10 +261,10 @@
2925 self._next_open_branch_result = result
2926 return result
2927
2928- def destroy_branch(self):
2929+ def destroy_branch(self, name=None):
2930 """See BzrDir.destroy_branch"""
2931 self._ensure_real()
2932- self._real_bzrdir.destroy_branch()
2933+ self._real_bzrdir.destroy_branch(name=name)
2934 self._next_open_branch_result = None
2935
2936 def create_workingtree(self, revision_id=None, from_branch=None):
2937@@ -318,8 +320,9 @@
2938 """See BzrDir._get_tree_branch()."""
2939 return None, self.open_branch()
2940
2941- def open_branch(self, _unsupported=False, ignore_fallbacks=False):
2942- if _unsupported:
2943+ def open_branch(self, name=None, unsupported=False,
2944+ ignore_fallbacks=False):
2945+ if unsupported:
2946 raise NotImplementedError('unsupported flag support not implemented yet.')
2947 if self._next_open_branch_result is not None:
2948 # See create_branch for details.
2949@@ -330,14 +333,14 @@
2950 if response[0] == 'ref':
2951 # a branch reference, use the existing BranchReference logic.
2952 format = BranchReferenceFormat()
2953- return format.open(self, _found=True, location=response[1],
2954- ignore_fallbacks=ignore_fallbacks)
2955+ return format.open(self, name=name, _found=True,
2956+ location=response[1], ignore_fallbacks=ignore_fallbacks)
2957 branch_format_name = response[1]
2958 if not branch_format_name:
2959 branch_format_name = None
2960 format = RemoteBranchFormat(network_name=branch_format_name)
2961 return RemoteBranch(self, self.find_repository(), format=format,
2962- setup_stacking=not ignore_fallbacks)
2963+ setup_stacking=not ignore_fallbacks, name=name)
2964
2965 def _open_repo_v1(self, path):
2966 verb = 'BzrDir.find_repository'
2967@@ -420,9 +423,9 @@
2968 """Return the path to be used for this bzrdir in a remote call."""
2969 return client.remote_path_from_transport(self.root_transport)
2970
2971- def get_branch_transport(self, branch_format):
2972+ def get_branch_transport(self, branch_format, name=None):
2973 self._ensure_real()
2974- return self._real_bzrdir.get_branch_transport(branch_format)
2975+ return self._real_bzrdir.get_branch_transport(branch_format, name=name)
2976
2977 def get_repository_transport(self, repository_format):
2978 self._ensure_real()
2979@@ -1229,10 +1232,11 @@
2980 return self._real_repository.add_inventory(revid, inv, parents)
2981
2982 def add_inventory_by_delta(self, basis_revision_id, delta, new_revision_id,
2983- parents):
2984+ parents, basis_inv=None, propagate_caches=False):
2985 self._ensure_real()
2986 return self._real_repository.add_inventory_by_delta(basis_revision_id,
2987- delta, new_revision_id, parents)
2988+ delta, new_revision_id, parents, basis_inv=basis_inv,
2989+ propagate_caches=propagate_caches)
2990
2991 def add_revision(self, rev_id, rev, inv=None, config=None):
2992 self._ensure_real()
2993@@ -2021,26 +2025,29 @@
2994 def network_name(self):
2995 return self._network_name
2996
2997- def open(self, a_bzrdir, ignore_fallbacks=False):
2998- return a_bzrdir.open_branch(ignore_fallbacks=ignore_fallbacks)
2999+ def open(self, a_bzrdir, name=None, ignore_fallbacks=False):
3000+ return a_bzrdir.open_branch(name=name,
3001+ ignore_fallbacks=ignore_fallbacks)
3002
3003- def _vfs_initialize(self, a_bzrdir):
3004+ def _vfs_initialize(self, a_bzrdir, name):
3005 # Initialisation when using a local bzrdir object, or a non-vfs init
3006 # method is not available on the server.
3007 # self._custom_format is always set - the start of initialize ensures
3008 # that.
3009 if isinstance(a_bzrdir, RemoteBzrDir):
3010 a_bzrdir._ensure_real()
3011- result = self._custom_format.initialize(a_bzrdir._real_bzrdir)
3012+ result = self._custom_format.initialize(a_bzrdir._real_bzrdir,
3013+ name)
3014 else:
3015 # We assume the bzrdir is parameterised; it may not be.
3016- result = self._custom_format.initialize(a_bzrdir)
3017+ result = self._custom_format.initialize(a_bzrdir, name)
3018 if (isinstance(a_bzrdir, RemoteBzrDir) and
3019 not isinstance(result, RemoteBranch)):
3020- result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result)
3021+ result = RemoteBranch(a_bzrdir, a_bzrdir.find_repository(), result,
3022+ name=name)
3023 return result
3024
3025- def initialize(self, a_bzrdir):
3026+ def initialize(self, a_bzrdir, name=None):
3027 # 1) get the network name to use.
3028 if self._custom_format:
3029 network_name = self._custom_format.network_name()
3030@@ -2052,20 +2059,23 @@
3031 network_name = reference_format.network_name()
3032 # Being asked to create on a non RemoteBzrDir:
3033 if not isinstance(a_bzrdir, RemoteBzrDir):
3034- return self._vfs_initialize(a_bzrdir)
3035+ return self._vfs_initialize(a_bzrdir, name=name)
3036 medium = a_bzrdir._client._medium
3037 if medium._is_remote_before((1, 13)):
3038- return self._vfs_initialize(a_bzrdir)
3039+ return self._vfs_initialize(a_bzrdir, name=name)
3040 # Creating on a remote bzr dir.
3041 # 2) try direct creation via RPC
3042 path = a_bzrdir._path_for_remote_call(a_bzrdir._client)
3043+ if name is not None:
3044+ # XXX JRV20100304: Support creating colocated branches
3045+ raise errors.NoColocatedBranchSupport(self)
3046 verb = 'BzrDir.create_branch'
3047 try:
3048 response = a_bzrdir._call(verb, path, network_name)
3049 except errors.UnknownSmartMethod:
3050 # Fallback - use vfs methods
3051 medium._remember_remote_is_before((1, 13))
3052- return self._vfs_initialize(a_bzrdir)
3053+ return self._vfs_initialize(a_bzrdir, name=name)
3054 if response[0] != 'ok':
3055 raise errors.UnexpectedSmartServerResponse(response)
3056 # Turn the response into a RemoteRepository object.
3057@@ -2079,7 +2089,7 @@
3058 a_bzrdir._client)
3059 remote_repo = RemoteRepository(repo_bzrdir, repo_format)
3060 remote_branch = RemoteBranch(a_bzrdir, remote_repo,
3061- format=format, setup_stacking=False)
3062+ format=format, setup_stacking=False, name=name)
3063 # XXX: We know this is a new branch, so it must have revno 0, revid
3064 # NULL_REVISION. Creating the branch locked would make this be unable
3065 # to be wrong; here its simply very unlikely to be wrong. RBC 20090225
3066@@ -2112,7 +2122,7 @@
3067 """
3068
3069 def __init__(self, remote_bzrdir, remote_repository, real_branch=None,
3070- _client=None, format=None, setup_stacking=True):
3071+ _client=None, format=None, setup_stacking=True, name=None):
3072 """Create a RemoteBranch instance.
3073
3074 :param real_branch: An optional local implementation of the branch
3075@@ -2124,6 +2134,7 @@
3076 :param setup_stacking: If True make an RPC call to determine the
3077 stacked (or not) status of the branch. If False assume the branch
3078 is not stacked.
3079+ :param name: Colocated branch name
3080 """
3081 # We intentionally don't call the parent class's __init__, because it
3082 # will try to assign to self.tags, which is a property in this subclass.
3083@@ -2149,6 +2160,7 @@
3084 # Fill out expected attributes of branch for bzrlib API users.
3085 self._clear_cached_state()
3086 self.base = self.bzrdir.root_transport.base
3087+ self._name = name
3088 self._control_files = None
3089 self._lock_mode = None
3090 self._lock_token = None
3091@@ -2219,7 +2231,7 @@
3092 'to use vfs implementation')
3093 self.bzrdir._ensure_real()
3094 self._real_branch = self.bzrdir._real_bzrdir.open_branch(
3095- ignore_fallbacks=self._real_ignore_fallbacks)
3096+ ignore_fallbacks=self._real_ignore_fallbacks, name=self._name)
3097 if self.repository._real_repository is None:
3098 # Give the remote repository the matching real repo.
3099 real_repo = self._real_branch.repository
3100
3101=== modified file 'bzrlib/revisionspec.py'
3102--- bzrlib/revisionspec.py 2009-10-27 14:04:29 +0000
3103+++ bzrlib/revisionspec.py 2010-04-06 07:24:41 +0000
3104@@ -1,4 +1,4 @@
3105-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
3106+# Copyright (C) 2005-2010 Canonical Ltd
3107 #
3108 # This program is free software; you can redistribute it and/or modify
3109 # it under the terms of the GNU General Public License as published by
3110
3111=== modified file 'bzrlib/revisiontree.py'
3112--- bzrlib/revisiontree.py 2010-01-20 23:21:35 +0000
3113+++ bzrlib/revisiontree.py 2010-04-06 07:24:41 +0000
3114@@ -1,4 +1,4 @@
3115-# Copyright (C) 2005, 2007 Canonical Ltd
3116+# Copyright (C) 2006-2010 Canonical Ltd
3117 #
3118 # This program is free software; you can redistribute it and/or modify
3119 # it under the terms of the GNU General Public License as published by
3120
3121=== modified file 'bzrlib/serializer.py'
3122--- bzrlib/serializer.py 2009-12-03 04:55:02 +0000
3123+++ bzrlib/serializer.py 2010-04-06 07:24:41 +0000
3124@@ -1,4 +1,4 @@
3125-# Copyright (C) 2005, 2006, 2009 Canonical Ltd
3126+# Copyright (C) 2009, 2010 Canonical Ltd
3127 #
3128 # This program is free software; you can redistribute it and/or modify
3129 # it under the terms of the GNU General Public License as published by
3130
3131=== modified file 'bzrlib/shellcomplete.py'
3132--- bzrlib/shellcomplete.py 2009-11-02 22:24:29 +0000
3133+++ bzrlib/shellcomplete.py 2010-04-06 07:24:41 +0000
3134@@ -1,4 +1,4 @@
3135-# Copyright (C) 2005, 2006 Canonical Ltd
3136+# Copyright (C) 2005, 2006, 2007, 2009, 2010 Canonical Ltd
3137 #
3138 # This program is free software; you can redistribute it and/or modify
3139 # it under the terms of the GNU General Public License as published by
3140
3141=== modified file 'bzrlib/smart/bzrdir.py'
3142--- bzrlib/smart/bzrdir.py 2010-01-12 01:10:03 +0000
3143+++ bzrlib/smart/bzrdir.py 2010-04-06 07:24:41 +0000
3144@@ -1,4 +1,4 @@
3145-# Copyright (C) 2006 Canonical Ltd
3146+# Copyright (C) 2006-2010 Canonical Ltd
3147 #
3148 # This program is free software; you can redistribute it and/or modify
3149 # it under the terms of the GNU General Public License as published by
3150
3151=== modified file 'bzrlib/smart/client.py'
3152--- bzrlib/smart/client.py 2010-01-15 06:55:33 +0000
3153+++ bzrlib/smart/client.py 2010-04-06 07:24:41 +0000
3154@@ -1,4 +1,4 @@
3155-# Copyright (C) 2006-2008 Canonical Ltd
3156+# Copyright (C) 2006-2010 Canonical Ltd
3157 #
3158 # This program is free software; you can redistribute it and/or modify
3159 # it under the terms of the GNU General Public License as published by
3160
3161=== modified file 'bzrlib/smart/medium.py'
3162--- bzrlib/smart/medium.py 2010-01-15 07:26:46 +0000
3163+++ bzrlib/smart/medium.py 2010-04-06 07:24:41 +0000
3164@@ -1,4 +1,4 @@
3165-# Copyright (C) 2006 Canonical Ltd
3166+# Copyright (C) 2006-2010 Canonical Ltd
3167 #
3168 # This program is free software; you can redistribute it and/or modify
3169 # it under the terms of the GNU General Public License as published by
3170
3171=== modified file 'bzrlib/smart/protocol.py'
3172--- bzrlib/smart/protocol.py 2009-12-21 17:00:29 +0000
3173+++ bzrlib/smart/protocol.py 2010-04-06 07:24:41 +0000
3174@@ -1,4 +1,4 @@
3175-# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
3176+# Copyright (C) 2006-2010 Canonical Ltd
3177 #
3178 # This program is free software; you can redistribute it and/or modify
3179 # it under the terms of the GNU General Public License as published by
3180
3181=== modified file 'bzrlib/smart/repository.py'
3182--- bzrlib/smart/repository.py 2010-02-10 02:17:15 +0000
3183+++ bzrlib/smart/repository.py 2010-04-06 07:24:41 +0000
3184@@ -1,4 +1,4 @@
3185-# Copyright (C) 2006, 2007, 2010 Canonical Ltd
3186+# Copyright (C) 2006-2010 Canonical Ltd
3187 #
3188 # This program is free software; you can redistribute it and/or modify
3189 # it under the terms of the GNU General Public License as published by
3190
3191=== modified file 'bzrlib/smart/request.py'
3192--- bzrlib/smart/request.py 2010-01-11 05:58:22 +0000
3193+++ bzrlib/smart/request.py 2010-04-06 07:24:41 +0000
3194@@ -1,4 +1,4 @@
3195-# Copyright (C) 2006, 2007 Canonical Ltd
3196+# Copyright (C) 2006-2010 Canonical Ltd
3197 #
3198 # This program is free software; you can redistribute it and/or modify
3199 # it under the terms of the GNU General Public License as published by
3200
3201=== modified file 'bzrlib/smart/server.py'
3202--- bzrlib/smart/server.py 2010-02-09 20:28:26 +0000
3203+++ bzrlib/smart/server.py 2010-04-06 07:24:41 +0000
3204@@ -1,4 +1,4 @@
3205-# Copyright (C) 2006, 2007, 2008 Canonical Ltd
3206+# Copyright (C) 2006-2010 Canonical Ltd
3207 #
3208 # This program is free software; you can redistribute it and/or modify
3209 # it under the terms of the GNU General Public License as published by
3210
3211=== modified file 'bzrlib/smart/vfs.py'
3212--- bzrlib/smart/vfs.py 2009-10-23 04:22:05 +0000
3213+++ bzrlib/smart/vfs.py 2010-04-06 07:24:41 +0000
3214@@ -1,4 +1,4 @@
3215-# Copyright (C) 2006, 2007 Canonical Ltd
3216+# Copyright (C) 2006-2010 Canonical Ltd
3217 #
3218 # This program is free software; you can redistribute it and/or modify
3219 # it under the terms of the GNU General Public License as published by
3220
3221=== modified file 'bzrlib/static_tuple.py'
3222--- bzrlib/static_tuple.py 2009-11-28 21:54:08 +0000
3223+++ bzrlib/static_tuple.py 2010-04-06 07:24:41 +0000
3224@@ -1,4 +1,4 @@
3225-# Copyright (C) 2009 Canonical Ltd
3226+# Copyright (C) 2009, 2010 Canonical Ltd
3227 #
3228 # This program is free software; you can redistribute it and/or modify
3229 # it under the terms of the GNU General Public License as published by
3230
3231=== modified file 'bzrlib/status.py'
3232--- bzrlib/status.py 2009-12-02 15:24:34 +0000
3233+++ bzrlib/status.py 2010-04-06 07:24:41 +0000
3234@@ -1,4 +1,4 @@
3235-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
3236+# Copyright (C) 2005-2010 Canonical Ltd
3237 #
3238 # This program is free software; you can redistribute it and/or modify
3239 # it under the terms of the GNU General Public License as published by
3240
3241=== modified file 'bzrlib/switch.py'
3242--- bzrlib/switch.py 2010-01-12 03:53:21 +0000
3243+++ bzrlib/switch.py 2010-04-06 07:24:41 +0000
3244@@ -1,4 +1,4 @@
3245-# Copyright (C) 2006, 2007 Canonical Ltd.
3246+# Copyright (C) 2007, 2009, 2010 Canonical Ltd.
3247 #
3248 # This program is free software; you can redistribute it and/or modify
3249 # it under the terms of the GNU General Public License as published by
3250
3251=== modified file 'bzrlib/tests/TestUtil.py'
3252--- bzrlib/tests/TestUtil.py 2009-12-05 09:04:19 +0000
3253+++ bzrlib/tests/TestUtil.py 2010-04-06 07:24:41 +0000
3254@@ -1,4 +1,4 @@
3255-# Copyright (C) 2004, 2005, 2006 Canonical Ltd
3256+# Copyright (C) 2005-2010 Canonical Ltd
3257 # Author: Robert Collins <robert.collins@canonical.com>
3258 #
3259 # This program is free software; you can redistribute it and/or modify
3260
3261=== modified file 'bzrlib/tests/__init__.py'
3262--- bzrlib/tests/__init__.py 2010-02-18 02:15:48 +0000
3263+++ bzrlib/tests/__init__.py 2010-04-06 07:24:41 +0000
3264@@ -1519,6 +1519,8 @@
3265 'BZR_PROGRESS_BAR': None,
3266 'BZR_LOG': None,
3267 'BZR_PLUGIN_PATH': None,
3268+ 'BZR_DISABLE_PLUGINS': None,
3269+ 'BZR_PLUGINS_AT': None,
3270 'BZR_CONCURRENCY': None,
3271 # Make sure that any text ui tests are consistent regardless of
3272 # the environment the test case is run in; you may want tests that
3273@@ -1671,7 +1673,33 @@
3274 unicodestr = log_contents.decode('utf8', 'replace')
3275 log_contents = unicodestr.encode('utf8')
3276 if not keep_log_file:
3277- self._log_file.close()
3278+ close_attempts = 0
3279+ max_close_attempts = 100
3280+ first_close_error = None
3281+ while close_attempts < max_close_attempts:
3282+ close_attempts += 1
3283+ try:
3284+ self._log_file.close()
3285+ except IOError, ioe:
3286+ if ioe.errno is None:
3287+ # No errno implies 'close() called during
3288+ # concurrent operation on the same file object', so
3289+ # retry. Probably a thread is trying to write to
3290+ # the log file.
3291+ if first_close_error is None:
3292+ first_close_error = ioe
3293+ continue
3294+ raise
3295+ else:
3296+ break
3297+ if close_attempts > 1:
3298+ sys.stderr.write(
3299+ 'Unable to close log file on first attempt, '
3300+ 'will retry: %s\n' % (first_close_error,))
3301+ if close_attempts == max_close_attempts:
3302+ sys.stderr.write(
3303+ 'Unable to close log file after %d attempts.\n'
3304+ % (max_close_attempts,))
3305 self._log_file = None
3306 # Permit multiple calls to get_log until we clean it up in
3307 # finishLogFile
3308
3309=== modified file 'bzrlib/tests/blackbox/test_annotate.py'
3310--- bzrlib/tests/blackbox/test_annotate.py 2010-01-07 12:32:37 +0000
3311+++ bzrlib/tests/blackbox/test_annotate.py 2010-04-06 07:24:41 +0000
3312@@ -1,4 +1,4 @@
3313-# Copyright (C) 2005 Canonical Ltd
3314+# Copyright (C) 2005-2010 Canonical Ltd
3315 # -*- coding: utf-8 -*-
3316 #
3317 # This program is free software; you can redistribute it and/or modify
3318
3319=== modified file 'bzrlib/tests/blackbox/test_branch.py'
3320--- bzrlib/tests/blackbox/test_branch.py 2010-02-09 21:29:20 +0000
3321+++ bzrlib/tests/blackbox/test_branch.py 2010-04-06 07:24:41 +0000
3322@@ -1,4 +1,4 @@
3323-# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
3324+# Copyright (C) 2006-2010 Canonical Ltd
3325 #
3326 # This program is free software; you can redistribute it and/or modify
3327 # it under the terms of the GNU General Public License as published by
3328
3329=== modified file 'bzrlib/tests/blackbox/test_break_lock.py'
3330--- bzrlib/tests/blackbox/test_break_lock.py 2009-03-23 14:59:43 +0000
3331+++ bzrlib/tests/blackbox/test_break_lock.py 2010-04-06 07:24:41 +0000
3332@@ -60,7 +60,7 @@
3333 local_branch.bind(self.master_branch)
3334 checkoutdir = bzrlib.bzrdir.BzrDir.create('checkout')
3335 bzrlib.branch.BranchReferenceFormat().initialize(
3336- checkoutdir, local_branch)
3337+ checkoutdir, target_branch=local_branch)
3338 self.wt = checkoutdir.create_workingtree()
3339
3340 def test_break_lock_help(self):
3341
3342=== modified file 'bzrlib/tests/blackbox/test_cat.py'
3343--- bzrlib/tests/blackbox/test_cat.py 2010-02-11 09:21:45 +0000
3344+++ bzrlib/tests/blackbox/test_cat.py 2010-04-06 07:24:41 +0000
3345@@ -1,4 +1,4 @@
3346-# Copyright (C) 2005 Canonical Ltd
3347+# Copyright (C) 2005-2010 Canonical Ltd
3348 # -*- coding: utf-8 -*-
3349 #
3350 # This program is free software; you can redistribute it and/or modify
3351
3352=== modified file 'bzrlib/tests/blackbox/test_checkout.py'
3353--- bzrlib/tests/blackbox/test_checkout.py 2009-12-01 06:07:41 +0000
3354+++ bzrlib/tests/blackbox/test_checkout.py 2010-04-06 07:24:41 +0000
3355@@ -1,4 +1,4 @@
3356-# Copyright (C) 2005, 2006, 2009 Canonical Ltd
3357+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
3358 #
3359 # This program is free software; you can redistribute it and/or modify
3360 # it under the terms of the GNU General Public License as published by
3361
3362=== modified file 'bzrlib/tests/blackbox/test_debug.py'
3363--- bzrlib/tests/blackbox/test_debug.py 2009-12-16 22:29:31 +0000
3364+++ bzrlib/tests/blackbox/test_debug.py 2010-04-06 07:24:41 +0000
3365@@ -1,4 +1,4 @@
3366-# Copyright (C) 2006, 2007 Canonical Ltd
3367+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
3368 #
3369 # This program is free software; you can redistribute it and/or modify
3370 # it under the terms of the GNU General Public License as published by
3371
3372=== modified file 'bzrlib/tests/blackbox/test_exceptions.py'
3373--- bzrlib/tests/blackbox/test_exceptions.py 2009-12-22 23:09:50 +0000
3374+++ bzrlib/tests/blackbox/test_exceptions.py 2010-04-06 07:24:41 +0000
3375@@ -1,4 +1,4 @@
3376-# Copyright (C) 2006, 2007 Canonical Ltd
3377+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
3378 #
3379 # This program is free software; you can redistribute it and/or modify
3380 # it under the terms of the GNU General Public License as published by
3381
3382=== modified file 'bzrlib/tests/blackbox/test_export.py'
3383--- bzrlib/tests/blackbox/test_export.py 2009-11-25 00:14:05 +0000
3384+++ bzrlib/tests/blackbox/test_export.py 2010-04-06 07:24:41 +0000
3385@@ -1,4 +1,4 @@
3386-# Copyright (C) 2005, 2006, 2008 Canonical Ltd
3387+# Copyright (C) 2005-2010 Canonical Ltd
3388 #
3389 # This program is free software; you can redistribute it and/or modify
3390 # it under the terms of the GNU General Public License as published by
3391@@ -293,3 +293,13 @@
3392 tree.commit('more setup')
3393 out, err = self.run_bzr('export exported branch/subdir')
3394 self.assertEqual(['foo.txt'], os.listdir('exported'))
3395+
3396+ def test_dir_export_per_file_timestamps(self):
3397+ tree = self.example_branch()
3398+ self.build_tree_contents([('branch/har', 'foo')])
3399+ tree.add('har')
3400+ tree.commit('setup', timestamp=42)
3401+ self.run_bzr('export --per-file-timestamps t branch')
3402+ har_st = os.stat('t/har')
3403+ self.assertEquals(42, har_st.st_mtime)
3404+
3405
3406=== modified file 'bzrlib/tests/blackbox/test_filtered_view_ops.py'
3407--- bzrlib/tests/blackbox/test_filtered_view_ops.py 2009-12-14 15:51:36 +0000
3408+++ bzrlib/tests/blackbox/test_filtered_view_ops.py 2010-04-06 07:24:41 +0000
3409@@ -1,4 +1,4 @@
3410-# Copyright (C) 2008 Canonical Ltd
3411+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
3412 #
3413 # This program is free software; you can redistribute it and/or modify
3414 # it under the terms of the GNU General Public License as published by
3415
3416=== modified file 'bzrlib/tests/blackbox/test_help.py'
3417--- bzrlib/tests/blackbox/test_help.py 2010-01-14 16:41:04 +0000
3418+++ bzrlib/tests/blackbox/test_help.py 2010-04-06 07:24:41 +0000
3419@@ -1,4 +1,4 @@
3420-# Copyright (C) 2005, 2006 Canonical Ltd
3421+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
3422 #
3423 # This program is free software; you can redistribute it and/or modify
3424 # it under the terms of the GNU General Public License as published by
3425
3426=== modified file 'bzrlib/tests/blackbox/test_ignore.py'
3427--- bzrlib/tests/blackbox/test_ignore.py 2009-10-23 10:41:15 +0000
3428+++ bzrlib/tests/blackbox/test_ignore.py 2010-04-06 07:24:41 +0000
3429@@ -1,4 +1,4 @@
3430-# Copyright (C) 2005, 2006 Canonical Ltd
3431+# Copyright (C) 2006-2010 Canonical Ltd
3432 #
3433 # This program is free software; you can redistribute it and/or modify
3434 # it under the terms of the GNU General Public License as published by
3435
3436=== modified file 'bzrlib/tests/blackbox/test_info.py'
3437--- bzrlib/tests/blackbox/test_info.py 2010-02-18 02:39:23 +0000
3438+++ bzrlib/tests/blackbox/test_info.py 2010-04-06 07:24:41 +0000
3439@@ -1228,7 +1228,8 @@
3440 # Do a light checkout of the heavy one
3441 transport.mkdir('tree/lightcheckout')
3442 lco_dir = bzrdir.BzrDirMetaFormat1().initialize('tree/lightcheckout')
3443- branch.BranchReferenceFormat().initialize(lco_dir, co_branch)
3444+ branch.BranchReferenceFormat().initialize(lco_dir,
3445+ target_branch=co_branch)
3446 lco_dir.create_workingtree()
3447 lco_tree = lco_dir.open_workingtree()
3448
3449
3450=== modified file 'bzrlib/tests/blackbox/test_init.py'
3451--- bzrlib/tests/blackbox/test_init.py 2009-11-08 02:23:13 +0000
3452+++ bzrlib/tests/blackbox/test_init.py 2010-04-06 07:24:41 +0000
3453@@ -1,4 +1,4 @@
3454-# Copyright (C) 2006, 2007, 2009 Canonical Ltd
3455+# Copyright (C) 2006-2010 Canonical Ltd
3456 #
3457 # This program is free software; you can redistribute it and/or modify
3458 # it under the terms of the GNU General Public License as published by
3459
3460=== modified file 'bzrlib/tests/blackbox/test_ls.py'
3461--- bzrlib/tests/blackbox/test_ls.py 2009-11-30 00:33:52 +0000
3462+++ bzrlib/tests/blackbox/test_ls.py 2010-04-06 07:24:41 +0000
3463@@ -1,4 +1,4 @@
3464-# Copyright (C) 2006 Canonical Ltd
3465+# Copyright (C) 2006-2010 Canonical Ltd
3466 #
3467 # This program is free software; you can redistribute it and/or modify
3468 # it under the terms of the GNU General Public License as published by
3469
3470=== modified file 'bzrlib/tests/blackbox/test_merge.py'
3471--- bzrlib/tests/blackbox/test_merge.py 2009-12-10 17:16:19 +0000
3472+++ bzrlib/tests/blackbox/test_merge.py 2010-04-06 07:24:41 +0000
3473@@ -1,4 +1,4 @@
3474-# Copyright (C) 2006, 2007 Canonical Ltd
3475+# Copyright (C) 2006-2010 Canonical Ltd
3476 #
3477 # This program is free software; you can redistribute it and/or modify
3478 # it under the terms of the GNU General Public License as published by
3479
3480=== modified file 'bzrlib/tests/blackbox/test_mv.py'
3481--- bzrlib/tests/blackbox/test_mv.py 2009-11-17 01:08:08 +0000
3482+++ bzrlib/tests/blackbox/test_mv.py 2010-04-06 07:24:41 +0000
3483@@ -1,4 +1,4 @@
3484-# Copyright (C) 2006 Canonical Ltd
3485+# Copyright (C) 2006-2010 Canonical Ltd
3486 #
3487 # This program is free software; you can redistribute it and/or modify
3488 # it under the terms of the GNU General Public License as published by
3489
3490=== modified file 'bzrlib/tests/blackbox/test_nick.py'
3491--- bzrlib/tests/blackbox/test_nick.py 2009-03-23 14:59:43 +0000
3492+++ bzrlib/tests/blackbox/test_nick.py 2010-04-06 07:24:41 +0000
3493@@ -30,11 +30,11 @@
3494 self.make_branch_and_tree('me.dev')
3495 os.chdir('me.dev')
3496 nick = self.run_bzr('nick')[0]
3497- self.assertEqual(nick, 'me.dev\n')
3498+ self.assertEqual('me.dev\n', nick)
3499 # set the nickname
3500 self.run_bzr("nick moo")
3501 nick = self.run_bzr('nick')[0]
3502- self.assertEqual(nick, 'moo\n')
3503+ self.assertEqual('moo\n', nick)
3504
3505 def test_autonick_urlencoded(self):
3506 # https://bugs.launchpad.net/bzr/+bug/66857 -- nick was printed
3507@@ -42,30 +42,30 @@
3508 self.make_branch_and_tree('!repo')
3509 os.chdir('!repo')
3510 nick = self.run_bzr('nick')[0]
3511- self.assertEqual(nick, '!repo\n')
3512+ self.assertEqual('!repo\n', nick)
3513
3514 def test_bound_nick(self):
3515 """Check that nick works well for checkouts."""
3516 base = self.make_branch_and_tree('base')
3517 child = self.make_branch_and_tree('child')
3518 os.chdir('child')
3519- self.assertEqual(self.run_bzr('nick')[0][:-1], 'child')
3520- self.assertEqual(child.branch.get_config().has_explicit_nickname(),
3521- False)
3522+ self.assertEqual('child', self.run_bzr('nick')[0][:-1])
3523+ self.assertEqual(False,
3524+ child.branch.get_config().has_explicit_nickname())
3525 self.run_bzr('bind ../base')
3526- self.assertEqual(self.run_bzr('nick')[0][:-1], base.branch.nick)
3527- self.assertEqual(child.branch.get_config().has_explicit_nickname(),
3528- False)
3529+ self.assertEqual(base.branch.nick, self.run_bzr('nick')[0][:-1])
3530+ self.assertEqual(False,
3531+ child.branch.get_config().has_explicit_nickname())
3532
3533 self.run_bzr('unbind')
3534 self.run_bzr("nick explicit_nick")
3535- self.assertEqual(self.run_bzr('nick')[0][:-1], "explicit_nick")
3536- self.assertEqual(child.branch.get_config()._get_explicit_nickname(),
3537- "explicit_nick")
3538+ self.assertEqual("explicit_nick", self.run_bzr('nick')[0][:-1])
3539+ self.assertEqual("explicit_nick",
3540+ child.branch.get_config()._get_explicit_nickname())
3541 self.run_bzr('bind ../base')
3542- self.assertEqual(self.run_bzr('nick')[0][:-1], base.branch.nick)
3543- self.assertEqual(child.branch.get_config()._get_explicit_nickname(),
3544- base.branch.nick)
3545+ self.assertEqual(base.branch.nick, self.run_bzr('nick')[0][:-1])
3546+ self.assertEqual(base.branch.nick,
3547+ child.branch.get_config()._get_explicit_nickname())
3548
3549 def test_boundless_nick(self):
3550 """Nick defaults to implicit local nick when bound branch is AWOL"""
3551@@ -73,8 +73,8 @@
3552 child = self.make_branch_and_tree('child')
3553 os.chdir('child')
3554 self.run_bzr('bind ../base')
3555- self.assertEqual(self.run_bzr('nick')[0][:-1], base.branch.nick)
3556- self.assertEqual(child.branch.get_config().has_explicit_nickname(),
3557- False)
3558+ self.assertEqual(base.branch.nick, self.run_bzr('nick')[0][:-1])
3559+ self.assertEqual(False,
3560+ child.branch.get_config().has_explicit_nickname())
3561 osutils.rmtree('../base')
3562- self.assertEqual(self.run_bzr('nick')[0][:-1], 'child')
3563+ self.assertEqual('child', self.run_bzr('nick')[0][:-1])
3564
3565=== modified file 'bzrlib/tests/blackbox/test_non_ascii.py'
3566--- bzrlib/tests/blackbox/test_non_ascii.py 2010-01-25 17:48:22 +0000
3567+++ bzrlib/tests/blackbox/test_non_ascii.py 2010-04-06 07:24:41 +0000
3568@@ -1,4 +1,4 @@
3569-# Copyright (C) 2006, 2007 Canonical Ltd
3570+# Copyright (C) 2006-2010 Canonical Ltd
3571 #
3572 # This program is free software; you can redistribute it and/or modify
3573 # it under the terms of the GNU General Public License as published by
3574
3575=== modified file 'bzrlib/tests/blackbox/test_pull.py'
3576--- bzrlib/tests/blackbox/test_pull.py 2010-01-29 11:17:16 +0000
3577+++ bzrlib/tests/blackbox/test_pull.py 2010-04-06 07:24:41 +0000
3578@@ -1,4 +1,4 @@
3579-# Copyright (C) 2005, 2006, 2010 Canonical Ltd
3580+# Copyright (C) 2005-2010 Canonical Ltd
3581 #
3582 # This program is free software; you can redistribute it and/or modify
3583 # it under the terms of the GNU General Public License as published by
3584
3585=== modified file 'bzrlib/tests/blackbox/test_push.py'
3586--- bzrlib/tests/blackbox/test_push.py 2010-02-11 09:21:45 +0000
3587+++ bzrlib/tests/blackbox/test_push.py 2010-04-06 07:24:41 +0000
3588@@ -1,4 +1,4 @@
3589-# Copyright (C) 2005, 2007, 2008 Canonical Ltd
3590+# Copyright (C) 2006-2010 Canonical Ltd
3591 #
3592 # This program is free software; you can redistribute it and/or modify
3593 # it under the terms of the GNU General Public License as published by
3594
3595=== modified file 'bzrlib/tests/blackbox/test_remerge.py'
3596--- bzrlib/tests/blackbox/test_remerge.py 2009-12-10 23:11:35 +0000
3597+++ bzrlib/tests/blackbox/test_remerge.py 2010-04-06 07:24:41 +0000
3598@@ -1,4 +1,4 @@
3599-# Copyright (C) 2005, 2006 Canonical Ltd
3600+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
3601 #
3602 # This program is free software; you can redistribute it and/or modify
3603 # it under the terms of the GNU General Public License as published by
3604
3605=== modified file 'bzrlib/tests/blackbox/test_send.py'
3606--- bzrlib/tests/blackbox/test_send.py 2010-02-11 09:21:45 +0000
3607+++ bzrlib/tests/blackbox/test_send.py 2010-04-06 07:24:41 +0000
3608@@ -1,4 +1,4 @@
3609-# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
3610+# Copyright (C) 2006-2010 Canonical Ltd
3611 # Authors: Aaron Bentley
3612 #
3613 # This program is free software; you can redistribute it and/or modify
3614
3615=== modified file 'bzrlib/tests/blackbox/test_serve.py'
3616--- bzrlib/tests/blackbox/test_serve.py 2010-01-07 03:03:01 +0000
3617+++ bzrlib/tests/blackbox/test_serve.py 2010-04-06 07:24:41 +0000
3618@@ -1,4 +1,4 @@
3619-# Copyright (C) 2006 Canonical Ltd
3620+# Copyright (C) 2006-2010 Canonical Ltd
3621 #
3622 # This program is free software; you can redistribute it and/or modify
3623 # it under the terms of the GNU General Public License as published by
3624
3625=== modified file 'bzrlib/tests/blackbox/test_shared_repository.py'
3626--- bzrlib/tests/blackbox/test_shared_repository.py 2010-01-12 01:10:03 +0000
3627+++ bzrlib/tests/blackbox/test_shared_repository.py 2010-04-06 07:24:41 +0000
3628@@ -1,4 +1,4 @@
3629-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
3630+# Copyright (C) 2006-2010 Canonical Ltd
3631 #
3632 # This program is free software; you can redistribute it and/or modify
3633 # it under the terms of the GNU General Public License as published by
3634
3635=== modified file 'bzrlib/tests/blackbox/test_shelve.py'
3636--- bzrlib/tests/blackbox/test_shelve.py 2009-12-11 05:48:21 +0000
3637+++ bzrlib/tests/blackbox/test_shelve.py 2010-04-06 07:24:41 +0000
3638@@ -1,4 +1,4 @@
3639-# Copyright (C) 2008, 2009 Canonical Ltd
3640+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
3641 #
3642 # This program is free software; you can redistribute it and/or modify
3643 # it under the terms of the GNU General Public License as published by
3644
3645=== modified file 'bzrlib/tests/blackbox/test_status.py'
3646--- bzrlib/tests/blackbox/test_status.py 2009-07-08 14:37:25 +0000
3647+++ bzrlib/tests/blackbox/test_status.py 2010-04-06 07:24:41 +0000
3648@@ -498,7 +498,8 @@
3649 def make_branch_and_tree(self, relpath):
3650 source = self.make_branch(pathjoin('..', relpath))
3651 checkout = bzrdir.BzrDirMetaFormat1().initialize(relpath)
3652- bzrlib.branch.BranchReferenceFormat().initialize(checkout, source)
3653+ bzrlib.branch.BranchReferenceFormat().initialize(checkout,
3654+ target_branch=source)
3655 return checkout.create_workingtree()
3656
3657
3658
3659=== modified file 'bzrlib/tests/blackbox/test_switch.py'
3660--- bzrlib/tests/blackbox/test_switch.py 2010-01-12 03:53:21 +0000
3661+++ bzrlib/tests/blackbox/test_switch.py 2010-04-06 07:24:41 +0000
3662@@ -1,4 +1,4 @@
3663-# Copyright (C) 2007, 2008, 2009 Canonical Ltd
3664+# Copyright (C) 2007-2010 Canonical Ltd
3665 # -*- coding: utf-8 -*-
3666 #
3667 # This program is free software; you can redistribute it and/or modify
3668
3669=== modified file 'bzrlib/tests/blackbox/test_too_much.py'
3670--- bzrlib/tests/blackbox/test_too_much.py 2009-12-02 15:24:34 +0000
3671+++ bzrlib/tests/blackbox/test_too_much.py 2010-04-06 07:24:41 +0000
3672@@ -1,4 +1,4 @@
3673-# Copyright (C) 2005, 2007 Canonical Ltd
3674+# Copyright (C) 2005-2010 Canonical Ltd
3675 #
3676 # This program is free software; you can redistribute it and/or modify
3677 # it under the terms of the GNU General Public License as published by
3678
3679=== modified file 'bzrlib/tests/blackbox/test_uncommit.py'
3680--- bzrlib/tests/blackbox/test_uncommit.py 2010-02-10 17:52:08 +0000
3681+++ bzrlib/tests/blackbox/test_uncommit.py 2010-04-06 07:24:41 +0000
3682@@ -216,7 +216,7 @@
3683
3684 def test_uncommit_shows_log_with_revision_id(self):
3685 wt = self.create_simple_tree()
3686-
3687+
3688 script = ScriptRunner()
3689 script.run_script(self, """
3690 $ cd tree
3691
3692=== modified file 'bzrlib/tests/blackbox/test_update.py'
3693--- bzrlib/tests/blackbox/test_update.py 2010-02-10 17:52:08 +0000
3694+++ bzrlib/tests/blackbox/test_update.py 2010-04-06 07:24:41 +0000
3695@@ -1,5 +1,4 @@
3696 # Copyright (C) 2006-2010 Canonical Ltd
3697-# -*- coding: utf-8 -*-
3698 #
3699 # This program is free software; you can redistribute it and/or modify
3700 # it under the terms of the GNU General Public License as published by
3701@@ -196,7 +195,8 @@
3702
3703 self.build_tree(['checkout1/'])
3704 checkout_dir = bzrdir.BzrDirMetaFormat1().initialize('checkout1')
3705- branch.BranchReferenceFormat().initialize(checkout_dir, master.branch)
3706+ branch.BranchReferenceFormat().initialize(checkout_dir,
3707+ target_branch=master.branch)
3708 checkout1 = checkout_dir.create_workingtree('m1')
3709
3710 # Create a second branch, with an extra commit
3711@@ -341,6 +341,7 @@
3712 # now update (and get conflicts)
3713 out, err = self.run_bzr('update lightweight', retcode=1)
3714 self.assertEqual('', out)
3715+ # NB: these conflicts are actually in the source code
3716 self.assertFileEqual('''\
3717 <<<<<<< TREE
3718 lightweight local changes
3719@@ -358,6 +359,7 @@
3720 # check we get the second conflict
3721 out, err = self.run_bzr('update lightweight', retcode=1)
3722 self.assertEqual('', out)
3723+ # NB: these conflicts are actually in the source code
3724 self.assertFileEqual('''\
3725 <<<<<<< TREE
3726 lightweight+checkout
3727@@ -366,4 +368,3 @@
3728 >>>>>>> MERGE-SOURCE
3729 ''',
3730 'lightweight/file')
3731-
3732
3733=== modified file 'bzrlib/tests/blackbox/test_versioning.py'
3734--- bzrlib/tests/blackbox/test_versioning.py 2009-08-28 05:00:33 +0000
3735+++ bzrlib/tests/blackbox/test_versioning.py 2010-04-06 07:24:41 +0000
3736@@ -1,4 +1,4 @@
3737-# Copyright (C) 2005 Canonical Ltd
3738+# Copyright (C) 2005, 2006, 2007, 2009, 2010 Canonical Ltd
3739 #
3740 # This program is free software; you can redistribute it and/or modify
3741 # it under the terms of the GNU General Public License as published by
3742@@ -29,16 +29,29 @@
3743 from bzrlib.workingtree import WorkingTree
3744
3745
3746+class TestMkdir(TestCaseWithTransport):
3747+
3748+ def test_mkdir_fails_cleanly(self):
3749+ """'mkdir' fails cleanly when no working tree is available.
3750+ https://bugs.edge.launchpad.net/bzr/+bug/138600
3751+ """
3752+ # Since there is a safety working tree above us, we create a bare repo
3753+ # here locally.
3754+ shared_repo = self.make_repository('.')
3755+ self.run_bzr(['mkdir', 'abc'], retcode=3)
3756+ self.failIfExists('abc')
3757+
3758+
3759 class TestVersioning(TestCaseInTempDir):
3760
3761 def test_mkdir(self):
3762 """Basic 'bzr mkdir' operation"""
3763
3764 self.run_bzr('init')
3765- self.run_bzr('mkdir foo')
3766+ self.run_bzr(['mkdir', 'foo'])
3767 self.assert_(os.path.isdir('foo'))
3768
3769- self.run_bzr('mkdir foo', retcode=3)
3770+ self.run_bzr(['mkdir', 'foo'], retcode=3)
3771
3772 wt = WorkingTree.open('.')
3773
3774@@ -54,12 +67,12 @@
3775 """'bzr mkdir' operation in subdirectory"""
3776
3777 self.run_bzr('init')
3778- self.run_bzr('mkdir dir')
3779+ self.run_bzr(['mkdir', 'dir'])
3780 self.assert_(os.path.isdir('dir'))
3781
3782 os.chdir('dir')
3783 self.log('Run mkdir in subdir')
3784- self.run_bzr('mkdir subdir')
3785+ self.run_bzr(['mkdir', 'subdir'])
3786 self.assert_(os.path.isdir('subdir'))
3787 os.chdir('..')
3788
3789@@ -86,7 +99,7 @@
3790 self.run_bzr('init')
3791 os.chdir('../..')
3792
3793- self.run_bzr('mkdir dir a/dir a/b/dir')
3794+ self.run_bzr(['mkdir', 'dir', 'a/dir', 'a/b/dir'])
3795 self.failUnless(os.path.isdir('dir'))
3796 self.failUnless(os.path.isdir('a/dir'))
3797 self.failUnless(os.path.isdir('a/b/dir'))
3798
3799=== modified file 'bzrlib/tests/commands/test_branch.py'
3800--- bzrlib/tests/commands/test_branch.py 2010-01-11 12:37:53 +0000
3801+++ bzrlib/tests/commands/test_branch.py 2010-04-06 07:24:41 +0000
3802@@ -1,4 +1,4 @@
3803-# Copyright (C) 2007 Canonical Ltd
3804+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
3805 #
3806 # This program is free software; you can redistribute it and/or modify
3807 # it under the terms of the GNU General Public License as published by
3808
3809=== modified file 'bzrlib/tests/commands/test_cat.py'
3810--- bzrlib/tests/commands/test_cat.py 2010-01-25 17:48:22 +0000
3811+++ bzrlib/tests/commands/test_cat.py 2010-04-06 07:24:41 +0000
3812@@ -1,4 +1,4 @@
3813-# Copyright (C) 2007 Canonical Ltd
3814+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
3815 #
3816 # This program is free software; you can redistribute it and/or modify
3817 # it under the terms of the GNU General Public License as published by
3818
3819=== modified file 'bzrlib/tests/commands/test_checkout.py'
3820--- bzrlib/tests/commands/test_checkout.py 2010-01-11 12:37:53 +0000
3821+++ bzrlib/tests/commands/test_checkout.py 2010-04-06 07:24:41 +0000
3822@@ -1,4 +1,4 @@
3823-# Copyright (C) 2007 Canonical Ltd
3824+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
3825 #
3826 # This program is free software; you can redistribute it and/or modify
3827 # it under the terms of the GNU General Public License as published by
3828
3829=== modified file 'bzrlib/tests/commands/test_commit.py'
3830--- bzrlib/tests/commands/test_commit.py 2010-01-11 12:37:53 +0000
3831+++ bzrlib/tests/commands/test_commit.py 2010-04-06 07:24:41 +0000
3832@@ -1,4 +1,4 @@
3833-# Copyright (C) 2007 Canonical Ltd
3834+# Copyright (C) 2007-2010 Canonical Ltd
3835 #
3836 # This program is free software; you can redistribute it and/or modify
3837 # it under the terms of the GNU General Public License as published by
3838@@ -53,8 +53,7 @@
3839 # commit do not provide a directory parameter, we have to change dir
3840 # manually
3841 os.chdir('local')
3842- # cmd_commit translates BoundBranchOutOfDate into BzrCommandError
3843- self.assertRaises(errors.BzrCommandError, commit.run,
3844+ self.assertRaises(errors.BoundBranchOutOfDate, commit.run,
3845 message=u'empty commit', unchanged=True)
3846 self.assertEquals(1, len(self.connections))
3847
3848
3849=== modified file 'bzrlib/tests/commands/test_init.py'
3850--- bzrlib/tests/commands/test_init.py 2010-01-11 12:37:53 +0000
3851+++ bzrlib/tests/commands/test_init.py 2010-04-06 07:24:41 +0000
3852@@ -1,4 +1,4 @@
3853-# Copyright (C) 2007 Canonical Ltd
3854+# Copyright (C) 2007-2010 Canonical Ltd
3855 #
3856 # This program is free software; you can redistribute it and/or modify
3857 # it under the terms of the GNU General Public License as published by
3858
3859=== modified file 'bzrlib/tests/commands/test_init_repository.py'
3860--- bzrlib/tests/commands/test_init_repository.py 2010-01-11 12:37:53 +0000
3861+++ bzrlib/tests/commands/test_init_repository.py 2010-04-06 07:24:41 +0000
3862@@ -1,4 +1,4 @@
3863-# Copyright (C) 2007 Canonical Ltd
3864+# Copyright (C) 2007-2010 Canonical Ltd
3865 #
3866 # This program is free software; you can redistribute it and/or modify
3867 # it under the terms of the GNU General Public License as published by
3868
3869=== modified file 'bzrlib/tests/commands/test_merge.py'
3870--- bzrlib/tests/commands/test_merge.py 2010-01-11 12:37:53 +0000
3871+++ bzrlib/tests/commands/test_merge.py 2010-04-06 07:24:41 +0000
3872@@ -1,4 +1,4 @@
3873-# Copyright (C) 2007 Canonical Ltd
3874+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
3875 #
3876 # This program is free software; you can redistribute it and/or modify
3877 # it under the terms of the GNU General Public License as published by
3878
3879=== modified file 'bzrlib/tests/commands/test_missing.py'
3880--- bzrlib/tests/commands/test_missing.py 2010-01-11 12:37:53 +0000
3881+++ bzrlib/tests/commands/test_missing.py 2010-04-06 07:24:41 +0000
3882@@ -1,4 +1,4 @@
3883-# Copyright (C) 2007 Canonical Ltd
3884+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
3885 #
3886 # This program is free software; you can redistribute it and/or modify
3887 # it under the terms of the GNU General Public License as published by
3888
3889=== modified file 'bzrlib/tests/commands/test_pull.py'
3890--- bzrlib/tests/commands/test_pull.py 2010-01-11 12:37:53 +0000
3891+++ bzrlib/tests/commands/test_pull.py 2010-04-06 07:24:41 +0000
3892@@ -1,4 +1,4 @@
3893-# Copyright (C) 2007 Canonical Ltd
3894+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
3895 #
3896 # This program is free software; you can redistribute it and/or modify
3897 # it under the terms of the GNU General Public License as published by
3898
3899=== modified file 'bzrlib/tests/commands/test_push.py'
3900--- bzrlib/tests/commands/test_push.py 2010-01-11 12:37:53 +0000
3901+++ bzrlib/tests/commands/test_push.py 2010-04-06 07:24:41 +0000
3902@@ -1,4 +1,4 @@
3903-# Copyright (C) 2007 Canonical Ltd
3904+# Copyright (C) 2007-2010 Canonical Ltd
3905 #
3906 # This program is free software; you can redistribute it and/or modify
3907 # it under the terms of the GNU General Public License as published by
3908
3909=== modified file 'bzrlib/tests/commands/test_update.py'
3910--- bzrlib/tests/commands/test_update.py 2010-01-11 12:37:53 +0000
3911+++ bzrlib/tests/commands/test_update.py 2010-04-06 07:24:41 +0000
3912@@ -1,4 +1,4 @@
3913-# Copyright (C) 2007 Canonical Ltd
3914+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
3915 #
3916 # This program is free software; you can redistribute it and/or modify
3917 # it under the terms of the GNU General Public License as published by
3918
3919=== modified file 'bzrlib/tests/ftp_server/__init__.py'
3920--- bzrlib/tests/ftp_server/__init__.py 2010-01-07 03:03:01 +0000
3921+++ bzrlib/tests/ftp_server/__init__.py 2010-04-06 07:24:41 +0000
3922@@ -1,4 +1,4 @@
3923-# Copyright (C) 2009 Canonical Ltd
3924+# Copyright (C) 2009, 2010 Canonical Ltd
3925 #
3926 # This program is free software; you can redistribute it and/or modify
3927 # it under the terms of the GNU General Public License as published by
3928
3929=== modified file 'bzrlib/tests/ftp_server/medusa_based.py'
3930--- bzrlib/tests/ftp_server/medusa_based.py 2010-02-09 17:35:07 +0000
3931+++ bzrlib/tests/ftp_server/medusa_based.py 2010-04-06 07:24:41 +0000
3932@@ -1,4 +1,4 @@
3933-# Copyright (C) 2007, 2008, 2009 Canonical Ltd
3934+# Copyright (C) 2007-2010 Canonical Ltd
3935 #
3936 # This program is free software; you can redistribute it and/or modify
3937 # it under the terms of the GNU General Public License as published by
3938
3939=== modified file 'bzrlib/tests/ftp_server/pyftpdlib_based.py'
3940--- bzrlib/tests/ftp_server/pyftpdlib_based.py 2010-02-09 17:33:44 +0000
3941+++ bzrlib/tests/ftp_server/pyftpdlib_based.py 2010-04-06 07:24:41 +0000
3942@@ -1,4 +1,4 @@
3943-# Copyright (C) 2009 Canonical Ltd
3944+# Copyright (C) 2009, 2010 Canonical Ltd
3945 #
3946 # This program is free software; you can redistribute it and/or modify
3947 # it under the terms of the GNU General Public License as published by
3948
3949=== modified file 'bzrlib/tests/http_server.py'
3950--- bzrlib/tests/http_server.py 2010-02-09 20:49:50 +0000
3951+++ bzrlib/tests/http_server.py 2010-04-06 07:24:41 +0000
3952@@ -1,4 +1,4 @@
3953-# Copyright (C) 2006, 2007 Canonical Ltd
3954+# Copyright (C) 2006-2010 Canonical Ltd
3955 #
3956 # This program is free software; you can redistribute it and/or modify
3957 # it under the terms of the GNU General Public License as published by
3958
3959=== modified file 'bzrlib/tests/http_utils.py'
3960--- bzrlib/tests/http_utils.py 2010-01-07 03:03:01 +0000
3961+++ bzrlib/tests/http_utils.py 2010-04-06 07:24:41 +0000
3962@@ -1,4 +1,4 @@
3963-# Copyright (C) 2005 Canonical Ltd
3964+# Copyright (C) 2005-2010 Canonical Ltd
3965 #
3966 # This program is free software; you can redistribute it and/or modify
3967 # it under the terms of the GNU General Public License as published by
3968
3969=== modified file 'bzrlib/tests/per_branch/test_branch.py'
3970--- bzrlib/tests/per_branch/test_branch.py 2010-02-11 09:27:55 +0000
3971+++ bzrlib/tests/per_branch/test_branch.py 2010-04-06 07:24:41 +0000
3972@@ -379,6 +379,23 @@
3973 self.assertEqual(committed.properties["branch-nick"],
3974 "My happy branch")
3975
3976+ def test_create_colocated(self):
3977+ try:
3978+ repo = self.make_repository('.', shared=True)
3979+ except errors.IncompatibleFormat:
3980+ return
3981+ self.assertEquals(0, len(repo.bzrdir.list_branches()))
3982+ try:
3983+ child_branch1 = self.branch_format.initialize(repo.bzrdir,
3984+ name='branch1')
3985+ except (errors.UninitializableFormat, errors.NoColocatedBranchSupport):
3986+ # branch references are not default init'able and
3987+ # not all bzrdirs support colocated branches.
3988+ return
3989+ self.assertEquals(1, len(repo.bzrdir.list_branches()))
3990+ self.branch_format.initialize(repo.bzrdir, name='branch2')
3991+ self.assertEquals(2, len(repo.bzrdir.list_branches()))
3992+
3993 def test_create_open_branch_uses_repository(self):
3994 try:
3995 repo = self.make_repository('.', shared=True)
3996
3997=== modified file 'bzrlib/tests/per_branch/test_iter_merge_sorted_revisions.py'
3998--- bzrlib/tests/per_branch/test_iter_merge_sorted_revisions.py 2009-12-03 23:34:38 +0000
3999+++ bzrlib/tests/per_branch/test_iter_merge_sorted_revisions.py 2010-04-06 07:24:41 +0000
4000@@ -1,4 +1,4 @@
4001-# Copyright (C) 2007 Canonical Ltd
4002+# Copyright (C) 2009, 2010 Canonical Ltd
4003 #
4004 # This program is free software; you can redistribute it and/or modify
4005 # it under the terms of the GNU General Public License as published by
4006
4007=== modified file 'bzrlib/tests/per_branch/test_parent.py'
4008--- bzrlib/tests/per_branch/test_parent.py 2009-11-08 03:00:33 +0000
4009+++ bzrlib/tests/per_branch/test_parent.py 2010-04-06 07:24:41 +0000
4010@@ -1,4 +1,4 @@
4011-# Copyright (C) 2004, 2005, 2006 Canonical Ltd
4012+# Copyright (C) 2005, 2006, 2007, 2009, 2010 Canonical Ltd
4013 #
4014 # This program is free software; you can redistribute it and/or modify
4015 # it under the terms of the GNU General Public License as published by
4016
4017=== modified file 'bzrlib/tests/per_bzrdir/test_bzrdir.py'
4018--- bzrlib/tests/per_bzrdir/test_bzrdir.py 2010-02-15 22:58:59 +0000
4019+++ bzrlib/tests/per_bzrdir/test_bzrdir.py 2010-04-06 07:24:41 +0000
4020@@ -1,4 +1,4 @@
4021-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
4022+# Copyright (C) 2006-2010 Canonical Ltd
4023 #
4024 # This program is free software; you can redistribute it and/or modify
4025 # it under the terms of the GNU General Public License as published by
4026@@ -247,11 +247,22 @@
4027 try:
4028 bzrdir.destroy_branch()
4029 except (errors.UnsupportedOperation, errors.TransportNotPossible):
4030- raise TestNotApplicable('Format does not support destroying tree')
4031+ raise TestNotApplicable('Format does not support destroying branch')
4032 self.assertRaises(errors.NotBranchError, bzrdir.open_branch)
4033 bzrdir.create_branch()
4034 bzrdir.open_branch()
4035
4036+ def test_destroy_colocated_branch(self):
4037+ branch = self.make_branch('branch')
4038+ bzrdir = branch.bzrdir
4039+ try:
4040+ colo_branch = bzrdir.create_branch('colo')
4041+ except errors.NoColocatedBranchSupport:
4042+ raise TestNotApplicable('BzrDir does not do colocated branches')
4043+ bzrdir.destroy_branch("colo")
4044+ self.assertRaises(errors.NotBranchError, bzrdir.open_branch,
4045+ "colo")
4046+
4047 def test_destroy_repository(self):
4048 repo = self.make_repository('repository')
4049 bzrdir = repo.bzrdir
4050@@ -523,7 +534,7 @@
4051 dir = self.make_bzrdir('source')
4052 try:
4053 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4054- referenced_branch)
4055+ target_branch=referenced_branch)
4056 except errors.IncompatibleFormat:
4057 # this is ok too, not all formats have to support references.
4058 return
4059@@ -626,7 +637,7 @@
4060 dir = self.make_bzrdir('source')
4061 try:
4062 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4063- referenced_branch)
4064+ target_branch=referenced_branch)
4065 except errors.IncompatibleFormat:
4066 # this is ok too, not all formats have to support references.
4067 return
4068@@ -691,7 +702,7 @@
4069 dir = self.make_bzrdir('source')
4070 try:
4071 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4072- referenced_branch)
4073+ target_branch=referenced_branch)
4074 except errors.IncompatibleFormat:
4075 # this is ok too, not all formats have to support references.
4076 return
4077@@ -966,7 +977,7 @@
4078 dir = self.make_bzrdir('source')
4079 try:
4080 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4081- referenced_branch)
4082+ target_branch=referenced_branch)
4083 except errors.IncompatibleFormat:
4084 # this is ok too, not all formats have to support references.
4085 return
4086@@ -986,7 +997,7 @@
4087 dir = self.make_bzrdir('source')
4088 try:
4089 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4090- referenced_tree.branch)
4091+ target_branch=referenced_tree.branch)
4092 except errors.IncompatibleFormat:
4093 # this is ok too, not all formats have to support references.
4094 return
4095@@ -1012,7 +1023,7 @@
4096 dir = self.make_bzrdir('source')
4097 try:
4098 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4099- referenced_tree.branch)
4100+ target_branch=referenced_tree.branch)
4101 except errors.IncompatibleFormat:
4102 # this is ok too, not all formats have to support references.
4103 return
4104@@ -1077,7 +1088,7 @@
4105 dir = self.make_bzrdir('source')
4106 try:
4107 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4108- referenced_branch)
4109+ target_branch=referenced_branch)
4110 except errors.IncompatibleFormat:
4111 # this is ok too, not all formats have to support references.
4112 return
4113@@ -1103,7 +1114,7 @@
4114 dir = self.make_bzrdir('source')
4115 try:
4116 reference = bzrlib.branch.BranchReferenceFormat().initialize(dir,
4117- referenced_branch)
4118+ target_branch=referenced_branch)
4119 except errors.IncompatibleFormat:
4120 # this is ok too, not all formats have to support references.
4121 return
4122@@ -1410,6 +1421,23 @@
4123 self.failUnless(isinstance(made_branch, bzrlib.branch.Branch))
4124 self.assertEqual(made_control, made_branch.bzrdir)
4125
4126+ def test_create_colo_branch(self):
4127+ # a bzrdir can construct a branch and repository for itself.
4128+ if not self.bzrdir_format.is_supported():
4129+ # unsupported formats are not loopback testable
4130+ # because the default open will not open them and
4131+ # they may not be initializable.
4132+ raise TestNotApplicable('Control dir format not supported')
4133+ t = get_transport(self.get_url())
4134+ made_control = self.bzrdir_format.initialize(t.base)
4135+ made_repo = made_control.create_repository()
4136+ try:
4137+ made_branch = made_control.create_branch("colo")
4138+ except errors.NoColocatedBranchSupport:
4139+ raise TestNotApplicable('Colocated branches not supported')
4140+ self.failUnless(isinstance(made_branch, bzrlib.branch.Branch))
4141+ self.assertEqual(made_control, made_branch.bzrdir)
4142+
4143 def test_open_branch(self):
4144 if not self.bzrdir_format.is_supported():
4145 # unsupported formats are not loopback testable
4146@@ -1858,7 +1886,7 @@
4147 thisdir = self.make_bzrdir('this')
4148 try:
4149 bzrlib.branch.BranchReferenceFormat().initialize(
4150- thisdir, master)
4151+ thisdir, target_branch=master)
4152 except errors.IncompatibleFormat:
4153 return
4154 unused_repo = thisdir.create_repository()
4155
4156=== modified file 'bzrlib/tests/per_foreign_vcs/__init__.py'
4157--- bzrlib/tests/per_foreign_vcs/__init__.py 2009-11-12 22:57:55 +0000
4158+++ bzrlib/tests/per_foreign_vcs/__init__.py 2010-04-06 07:24:41 +0000
4159@@ -1,4 +1,4 @@
4160-# Copyright (C) 2009 Canonical Ltd
4161+# Copyright (C) 2009, 2010 Canonical Ltd
4162 #
4163 # This program is free software; you can redistribute it and/or modify
4164 # it under the terms of the GNU General Public License as published by
4165
4166=== modified file 'bzrlib/tests/per_foreign_vcs/test_repository.py'
4167--- bzrlib/tests/per_foreign_vcs/test_repository.py 2009-11-27 03:25:07 +0000
4168+++ bzrlib/tests/per_foreign_vcs/test_repository.py 2010-04-06 07:24:41 +0000
4169@@ -1,4 +1,4 @@
4170-# Copyright (C) 2009 Canonical Ltd
4171+# Copyright (C) 2009, 2010 Canonical Ltd
4172 #
4173 # This program is free software; you can redistribute it and/or modify
4174 # it under the terms of the GNU General Public License as published by
4175
4176=== modified file 'bzrlib/tests/per_interbranch/test_push.py'
4177--- bzrlib/tests/per_interbranch/test_push.py 2010-02-09 21:31:52 +0000
4178+++ bzrlib/tests/per_interbranch/test_push.py 2010-04-06 07:24:41 +0000
4179@@ -1,4 +1,4 @@
4180-# Copyright (C) 2004, 2005, 2007, 2009 Canonical Ltd
4181+# Copyright (C) 2009, 2010 Canonical Ltd
4182 #
4183 # This program is free software; you can redistribute it and/or modify
4184 # it under the terms of the GNU General Public License as published by
4185
4186=== modified file 'bzrlib/tests/per_intertree/__init__.py'
4187--- bzrlib/tests/per_intertree/__init__.py 2009-11-12 23:10:43 +0000
4188+++ bzrlib/tests/per_intertree/__init__.py 2010-04-06 07:24:41 +0000
4189@@ -1,4 +1,4 @@
4190-# Copyright (C) 2006, 2009 Canonical Ltd
4191+# Copyright (C) 2006-2010 Canonical Ltd
4192 #
4193 # This program is free software; you can redistribute it and/or modify
4194 # it under the terms of the GNU General Public License as published by
4195
4196=== modified file 'bzrlib/tests/per_pack_repository.py'
4197--- bzrlib/tests/per_pack_repository.py 2010-02-11 09:21:45 +0000
4198+++ bzrlib/tests/per_pack_repository.py 2010-04-06 07:24:41 +0000
4199@@ -1,4 +1,4 @@
4200-# Copyright (C) 2008, 2009 Canonical Ltd
4201+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4202 #
4203 # This program is free software; you can redistribute it and/or modify
4204 # it under the terms of the GNU General Public License as published by
4205
4206=== modified file 'bzrlib/tests/per_repository/test_check.py'
4207--- bzrlib/tests/per_repository/test_check.py 2009-12-16 22:29:31 +0000
4208+++ bzrlib/tests/per_repository/test_check.py 2010-04-06 07:24:41 +0000
4209@@ -1,4 +1,4 @@
4210-# Copyright (C) 2007 Canonical Ltd
4211+# Copyright (C) 2007-2010 Canonical Ltd
4212 #
4213 # This program is free software; you can redistribute it and/or modify
4214 # it under the terms of the GNU General Public License as published by
4215
4216=== modified file 'bzrlib/tests/per_repository/test_check_reconcile.py'
4217--- bzrlib/tests/per_repository/test_check_reconcile.py 2009-12-16 22:29:31 +0000
4218+++ bzrlib/tests/per_repository/test_check_reconcile.py 2010-04-06 07:24:41 +0000
4219@@ -1,4 +1,4 @@
4220-# Copyright (C) 2007 Canonical Ltd
4221+# Copyright (C) 2007-2010 Canonical Ltd
4222 #
4223 # This program is free software; you can redistribute it and/or modify
4224 # it under the terms of the GNU General Public License as published by
4225
4226=== modified file 'bzrlib/tests/per_repository_reference/test_check.py'
4227--- bzrlib/tests/per_repository_reference/test_check.py 2009-12-16 22:29:31 +0000
4228+++ bzrlib/tests/per_repository_reference/test_check.py 2010-04-06 07:24:41 +0000
4229@@ -1,4 +1,4 @@
4230-# Copyright (C) 2008 Canonical Ltd
4231+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4232 #
4233 # This program is free software; you can redistribute it and/or modify
4234 # it under the terms of the GNU General Public License as published by
4235
4236=== modified file 'bzrlib/tests/per_transport.py'
4237--- bzrlib/tests/per_transport.py 2010-02-09 20:44:50 +0000
4238+++ bzrlib/tests/per_transport.py 2010-04-06 07:24:41 +0000
4239@@ -1,4 +1,4 @@
4240-# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
4241+# Copyright (C) 2005-2010 Canonical Ltd
4242 #
4243 # This program is free software; you can redistribute it and/or modify
4244 # it under the terms of the GNU General Public License as published by
4245@@ -1083,6 +1083,52 @@
4246 subdir.stat('./file')
4247 subdir.stat('.')
4248
4249+ def test_hardlink(self):
4250+ from stat import ST_NLINK
4251+
4252+ t = self.get_transport()
4253+
4254+ source_name = "original_target"
4255+ link_name = "target_link"
4256+
4257+ self.build_tree([source_name], transport=t)
4258+
4259+ try:
4260+ t.hardlink(source_name, link_name)
4261+
4262+ self.failUnless(t.has(source_name))
4263+ self.failUnless(t.has(link_name))
4264+
4265+ st = t.stat(link_name)
4266+ self.failUnlessEqual(st[ST_NLINK], 2)
4267+ except TransportNotPossible:
4268+ raise TestSkipped("Transport %s does not support hardlinks." %
4269+ self._server.__class__)
4270+
4271+ def test_symlink(self):
4272+ from stat import S_ISLNK
4273+
4274+ t = self.get_transport()
4275+
4276+ source_name = "original_target"
4277+ link_name = "target_link"
4278+
4279+ self.build_tree([source_name], transport=t)
4280+
4281+ try:
4282+ t.symlink(source_name, link_name)
4283+
4284+ self.failUnless(t.has(source_name))
4285+ self.failUnless(t.has(link_name))
4286+
4287+ st = t.stat(link_name)
4288+ self.failUnless(S_ISLNK(st.st_mode))
4289+ except TransportNotPossible:
4290+ raise TestSkipped("Transport %s does not support symlinks." %
4291+ self._server.__class__)
4292+ except IOError:
4293+ raise tests.KnownFailure("Paramiko fails to create symlinks during tests")
4294+
4295 def test_list_dir(self):
4296 # TODO: Test list_dir, just try once, and if it throws, stop testing
4297 t = self.get_transport()
4298
4299=== modified file 'bzrlib/tests/per_tree/test_get_file_with_stat.py'
4300--- bzrlib/tests/per_tree/test_get_file_with_stat.py 2009-11-18 15:47:16 +0000
4301+++ bzrlib/tests/per_tree/test_get_file_with_stat.py 2010-04-06 07:24:41 +0000
4302@@ -1,4 +1,4 @@
4303-# Copyright (C) 2008 Canonical Ltd
4304+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4305 #
4306 # This program is free software; you can redistribute it and/or modify
4307 # it under the terms of the GNU General Public License as published by
4308
4309=== modified file 'bzrlib/tests/per_tree/test_iter_search_rules.py'
4310--- bzrlib/tests/per_tree/test_iter_search_rules.py 2009-12-03 05:21:09 +0000
4311+++ bzrlib/tests/per_tree/test_iter_search_rules.py 2010-04-06 07:24:41 +0000
4312@@ -1,4 +1,4 @@
4313-# Copyright (C) 2008 Canonical Ltd
4314+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4315 #
4316 # This program is free software; you can redistribute it and/or modify
4317 # it under the terms of the GNU General Public License as published by
4318
4319=== modified file 'bzrlib/tests/per_tree/test_path_content_summary.py'
4320--- bzrlib/tests/per_tree/test_path_content_summary.py 2009-11-10 19:38:37 +0000
4321+++ bzrlib/tests/per_tree/test_path_content_summary.py 2010-04-06 07:24:41 +0000
4322@@ -1,4 +1,4 @@
4323-# Copyright (C) 2007, 2009 Canonical Ltd
4324+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
4325 #
4326 # This program is free software; you can redistribute it and/or modify
4327 # it under the terms of the GNU General Public License as published by
4328
4329=== modified file 'bzrlib/tests/per_tree/test_revision_tree.py'
4330--- bzrlib/tests/per_tree/test_revision_tree.py 2009-07-10 07:14:02 +0000
4331+++ bzrlib/tests/per_tree/test_revision_tree.py 2010-04-06 07:24:41 +0000
4332@@ -1,4 +1,4 @@
4333-# Copyright (C) 2006 Canonical Ltd
4334+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
4335 #
4336 # This program is free software; you can redistribute it and/or modify
4337 # it under the terms of the GNU General Public License as published by
4338@@ -16,11 +16,14 @@
4339
4340 """Tests for Tree.revision_tree."""
4341
4342-from bzrlib import errors
4343-from bzrlib.tests.per_tree import TestCaseWithTree
4344-
4345-
4346-class TestRevisionTree(TestCaseWithTree):
4347+from bzrlib import (
4348+ errors,
4349+ tests,
4350+ )
4351+from bzrlib.tests import per_tree
4352+
4353+
4354+class TestRevisionTree(per_tree.TestCaseWithTree):
4355
4356 def create_tree_no_parents_no_content(self):
4357 tree = self.make_branch_and_tree('.')
4358
4359=== modified file 'bzrlib/tests/per_workingtree/test_content_filters.py'
4360--- bzrlib/tests/per_workingtree/test_content_filters.py 2010-01-25 17:48:22 +0000
4361+++ bzrlib/tests/per_workingtree/test_content_filters.py 2010-04-06 07:24:41 +0000
4362@@ -1,4 +1,4 @@
4363-# Copyright (C) 2008 Canonical Ltd
4364+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4365 #
4366 # This program is free software; you can redistribute it and/or modify
4367 # it under the terms of the GNU General Public License as published by
4368
4369=== modified file 'bzrlib/tests/per_workingtree/test_is_ignored.py'
4370--- bzrlib/tests/per_workingtree/test_is_ignored.py 2010-01-01 21:26:25 +0000
4371+++ bzrlib/tests/per_workingtree/test_is_ignored.py 2010-04-06 07:24:41 +0000
4372@@ -1,4 +1,4 @@
4373-# Copyright (C) 2006 Canonical Ltd
4374+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
4375 # Authors: Robert Collins <robert.collins@canonical.com>
4376 #
4377 # This program is free software; you can redistribute it and/or modify
4378
4379=== modified file 'bzrlib/tests/per_workingtree/test_revision_tree.py'
4380--- bzrlib/tests/per_workingtree/test_revision_tree.py 2009-07-10 07:14:02 +0000
4381+++ bzrlib/tests/per_workingtree/test_revision_tree.py 2010-04-06 07:24:41 +0000
4382@@ -1,4 +1,4 @@
4383-# Copyright (C) 2006 Canonical Ltd
4384+# Copyright (C) 2006, 2007, 2009, 2010 Canonical Ltd
4385 #
4386 # This program is free software; you can redistribute it and/or modify
4387 # it under the terms of the GNU General Public License as published by
4388@@ -23,11 +23,15 @@
4389 so these tests are testing that when there is a cache, it performs correctly.
4390 """
4391
4392-from bzrlib import errors
4393-from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
4394-
4395-
4396-class TestRevisionTree(TestCaseWithWorkingTree):
4397+from bzrlib import (
4398+ branchbuilder,
4399+ errors,
4400+ tests,
4401+ )
4402+from bzrlib.tests import per_workingtree
4403+
4404+
4405+class TestRevisionTree(per_workingtree.TestCaseWithWorkingTree):
4406
4407 def test_get_zeroth_basis_tree_via_revision_tree(self):
4408 tree = self.make_branch_and_tree('.')
4409@@ -83,3 +87,50 @@
4410 return
4411 repository_revision_tree = tree.branch.repository.revision_tree(rev1)
4412 self.assertTreesEqual(repository_revision_tree, cached_revision_tree)
4413+
4414+
4415+class TestRevisionTreeKind(per_workingtree.TestCaseWithWorkingTree):
4416+
4417+ def make_branch_with_merged_deletions(self, relpath='tree'):
4418+ tree = self.make_branch_and_tree(relpath)
4419+ files = ['a', 'b/', 'b/c']
4420+ self.build_tree(files, line_endings='binary',
4421+ transport=tree.bzrdir.root_transport)
4422+ tree.set_root_id('root-id')
4423+ tree.add(files, ['a-id', 'b-id', 'c-id'])
4424+ tree.commit('a, b and b/c', rev_id='base')
4425+ tree2 = tree.bzrdir.sprout(relpath + '2').open_workingtree()
4426+ # Delete 'a' in tree
4427+ tree.remove('a', keep_files=False)
4428+ tree.commit('remove a', rev_id='this')
4429+ # Delete 'c' in tree2
4430+ tree2.remove('b/c', keep_files=False)
4431+ tree2.remove('b', keep_files=False)
4432+ tree2.commit('remove b/c', rev_id='other')
4433+ # Merge tree2 into tree
4434+ tree.merge_from_branch(tree2.branch)
4435+ return tree
4436+
4437+ def test_kind_parent_tree(self):
4438+ tree = self.make_branch_with_merged_deletions()
4439+ tree.lock_read()
4440+ self.addCleanup(tree.unlock)
4441+ parents = tree.get_parent_ids()
4442+ self.assertEqual(['this', 'other'], parents)
4443+ basis = tree.revision_tree(parents[0])
4444+ basis.lock_read()
4445+ self.addCleanup(basis.unlock)
4446+ self.assertRaises(errors.NoSuchId, basis.kind, 'a-id')
4447+ self.assertEqual(['directory', 'file'],
4448+ [basis.kind('b-id'), basis.kind('c-id')])
4449+ try:
4450+ other = tree.revision_tree(parents[1])
4451+ except errors.NoSuchRevisionInTree:
4452+ raise tests.TestNotApplicable(
4453+ 'Tree type %s caches only the basis revision tree.'
4454+ % type(tree))
4455+ other.lock_read()
4456+ self.addCleanup(other.unlock)
4457+ self.assertRaises(errors.NoSuchId, other.kind, 'b-id')
4458+ self.assertRaises(errors.NoSuchId, other.kind, 'c-id')
4459+ self.assertEqual('file', other.kind('a-id'))
4460
4461=== modified file 'bzrlib/tests/per_workingtree/test_workingtree.py'
4462--- bzrlib/tests/per_workingtree/test_workingtree.py 2010-02-13 01:50:29 +0000
4463+++ bzrlib/tests/per_workingtree/test_workingtree.py 2010-04-06 07:24:41 +0000
4464@@ -423,7 +423,8 @@
4465 made_control = self.bzrdir_format.initialize('new')
4466 source.branch.repository.clone(made_control)
4467 source.branch.clone(made_control)
4468- made_tree = self.workingtree_format.initialize(made_control, revision_id='a')
4469+ made_tree = self.workingtree_format.initialize(made_control,
4470+ revision_id='a')
4471 self.assertEqual(['a'], made_tree.get_parent_ids())
4472
4473 def test_update_sets_last_revision(self):
4474@@ -447,7 +448,8 @@
4475 # current format
4476 self.build_tree(['checkout/', 'tree/file'])
4477 checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
4478- branch.BranchReferenceFormat().initialize(checkout, main_branch)
4479+ branch.BranchReferenceFormat().initialize(checkout,
4480+ target_branch=main_branch)
4481 old_tree = self.workingtree_format.initialize(checkout)
4482 # now commit to 'tree'
4483 wt.add('file')
4484@@ -514,7 +516,8 @@
4485 # current format
4486 self.build_tree(['checkout/', 'tree/file'])
4487 checkout = bzrdir.BzrDirMetaFormat1().initialize('checkout')
4488- branch.BranchReferenceFormat().initialize(checkout, main_branch)
4489+ branch.BranchReferenceFormat().initialize(checkout,
4490+ target_branch=main_branch)
4491 old_tree = self.workingtree_format.initialize(checkout)
4492 # now commit to 'tree'
4493 wt.add('file')
4494
4495=== modified file 'bzrlib/tests/script.py'
4496--- bzrlib/tests/script.py 2010-01-16 10:06:21 +0000
4497+++ bzrlib/tests/script.py 2010-04-06 07:24:41 +0000
4498@@ -1,4 +1,4 @@
4499-# Copyright (C) 2009 Canonical Ltd
4500+# Copyright (C) 2009, 2010 Canonical Ltd
4501 #
4502 # This program is free software; you can redistribute it and/or modify
4503 # it under the terms of the GNU General Public License as published by
4504
4505=== modified file 'bzrlib/tests/stub_sftp.py'
4506--- bzrlib/tests/stub_sftp.py 2010-02-11 09:27:55 +0000
4507+++ bzrlib/tests/stub_sftp.py 2010-04-06 07:24:41 +0000
4508@@ -297,14 +297,14 @@
4509 threading.Thread(target=self._callback, args=(s,)).start()
4510 except socket.error, x:
4511 sys.excepthook(*sys.exc_info())
4512- warning('Socket error during accept() within unit test server'
4513- ' thread: %r' % x)
4514+ trace.warning('Socket error during accept() '
4515+ 'within unit test server thread: %r' % x)
4516 except Exception, x:
4517 # probably a failed test; unit test thread will log the
4518 # failure/error
4519 sys.excepthook(*sys.exc_info())
4520- warning('Exception from within unit test server thread: %r' %
4521- x)
4522+ trace.warning(
4523+ 'Exception from within unit test server thread: %r' % x)
4524
4525
4526 class SocketDelay(object):
4527@@ -438,13 +438,15 @@
4528 if not (backing_server is None or
4529 isinstance(backing_server, test_server.LocalURLServer)):
4530 raise AssertionError(
4531- "backing_server should not be %r, because this can only serve the "
4532- "local current working directory." % (backing_server,))
4533+ 'backing_server should not be %r, because this can only serve '
4534+ 'the local current working directory.' % (backing_server,))
4535 self._original_vendor = ssh._ssh_vendor_manager._cached_ssh_vendor
4536 ssh._ssh_vendor_manager._cached_ssh_vendor = self._vendor
4537+ # FIXME: the following block should certainly just be self._homedir =
4538+ # osutils.getcwd() but that fails badly on Unix -- vila 20100224
4539 if sys.platform == 'win32':
4540 # Win32 needs to use the UNICODE api
4541- self._homedir = getcwd()
4542+ self._homedir = os.getcwdu()
4543 else:
4544 # But Linux SFTP servers should just deal in bytestreams
4545 self._homedir = os.getcwd()
4546
4547=== modified file 'bzrlib/tests/test__annotator.py'
4548--- bzrlib/tests/test__annotator.py 2009-12-22 16:47:36 +0000
4549+++ bzrlib/tests/test__annotator.py 2010-04-06 07:24:41 +0000
4550@@ -1,4 +1,4 @@
4551-# Copyright (C) 2009 Canonical Ltd
4552+# Copyright (C) 2009, 2010 Canonical Ltd
4553 #
4554 # This program is free software; you can redistribute it and/or modify
4555 # it under the terms of the GNU General Public License as published by
4556
4557=== modified file 'bzrlib/tests/test__bencode.py'
4558--- bzrlib/tests/test__bencode.py 2009-12-23 04:19:34 +0000
4559+++ bzrlib/tests/test__bencode.py 2010-04-06 07:24:41 +0000
4560@@ -1,4 +1,4 @@
4561-# Copyright (C) 2007, 2009 Canonical Ltd
4562+# Copyright (C) 2007, 2009, 2010 Canonical Ltd
4563 #
4564 # This program is free software; you can redistribute it and/or modify
4565 # it under the terms of the GNU General Public License as published by
4566
4567=== modified file 'bzrlib/tests/test__chk_map.py'
4568--- bzrlib/tests/test__chk_map.py 2009-12-22 16:28:47 +0000
4569+++ bzrlib/tests/test__chk_map.py 2010-04-06 07:24:41 +0000
4570@@ -1,4 +1,4 @@
4571-# Copyright (C) 2009 Canonical Ltd
4572+# Copyright (C) 2009, 2010 Canonical Ltd
4573 #
4574 # This program is free software; you can redistribute it and/or modify
4575 # it under the terms of the GNU General Public License as published by
4576
4577=== modified file 'bzrlib/tests/test__chunks_to_lines.py'
4578--- bzrlib/tests/test__chunks_to_lines.py 2009-12-22 17:14:45 +0000
4579+++ bzrlib/tests/test__chunks_to_lines.py 2010-04-06 07:24:41 +0000
4580@@ -1,4 +1,4 @@
4581-# Copyright (C) 2008 Canonical Ltd
4582+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4583 #
4584 # This program is free software; you can redistribute it and/or modify
4585 # it under the terms of the GNU General Public License as published by
4586
4587=== modified file 'bzrlib/tests/test__dirstate_helpers.py'
4588--- bzrlib/tests/test__dirstate_helpers.py 2010-01-25 17:48:22 +0000
4589+++ bzrlib/tests/test__dirstate_helpers.py 2010-04-06 07:24:41 +0000
4590@@ -1,4 +1,4 @@
4591-# Copyright (C) 2007, 2008, 2009 Canonical Ltd
4592+# Copyright (C) 2007-2010 Canonical Ltd
4593 #
4594 # This program is free software; you can redistribute it and/or modify
4595 # it under the terms of the GNU General Public License as published by
4596
4597=== modified file 'bzrlib/tests/test__groupcompress.py'
4598--- bzrlib/tests/test__groupcompress.py 2009-12-22 15:50:40 +0000
4599+++ bzrlib/tests/test__groupcompress.py 2010-04-06 07:24:41 +0000
4600@@ -1,4 +1,4 @@
4601-# Copyright (C) 2008, 2009 Canonical Ltd
4602+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4603 #
4604 # This program is free software; you can redistribute it and/or modify
4605 # it under the terms of the GNU General Public License as published by
4606
4607=== modified file 'bzrlib/tests/test__known_graph.py'
4608--- bzrlib/tests/test__known_graph.py 2009-12-22 15:50:40 +0000
4609+++ bzrlib/tests/test__known_graph.py 2010-04-06 07:24:41 +0000
4610@@ -1,4 +1,4 @@
4611-# Copyright (C) 2009 Canonical Ltd
4612+# Copyright (C) 2009, 2010 Canonical Ltd
4613 #
4614 # This program is free software; you can redistribute it and/or modify
4615 # it under the terms of the GNU General Public License as published by
4616
4617=== modified file 'bzrlib/tests/test__rio.py'
4618--- bzrlib/tests/test__rio.py 2009-12-22 16:28:47 +0000
4619+++ bzrlib/tests/test__rio.py 2010-04-06 07:24:41 +0000
4620@@ -1,4 +1,4 @@
4621-# Copyright (C) 2009 Canonical Ltd
4622+# Copyright (C) 2009, 2010 Canonical Ltd
4623 #
4624 # This program is free software; you can redistribute it and/or modify
4625 # it under the terms of the GNU General Public License as published by
4626
4627=== modified file 'bzrlib/tests/test__simple_set.py'
4628--- bzrlib/tests/test__simple_set.py 2009-12-22 15:50:40 +0000
4629+++ bzrlib/tests/test__simple_set.py 2010-04-06 07:24:41 +0000
4630@@ -1,4 +1,4 @@
4631-# Copyright (C) 2009 Canonical Ltd
4632+# Copyright (C) 2009, 2010 Canonical Ltd
4633 #
4634 # This program is free software; you can redistribute it and/or modify
4635 # it under the terms of the GNU General Public License as published by
4636
4637=== modified file 'bzrlib/tests/test__static_tuple.py'
4638--- bzrlib/tests/test__static_tuple.py 2010-02-18 01:10:16 +0000
4639+++ bzrlib/tests/test__static_tuple.py 2010-04-06 07:24:41 +0000
4640@@ -1,4 +1,4 @@
4641-# Copyright (C) 2009 Canonical Ltd
4642+# Copyright (C) 2009, 2010 Canonical Ltd
4643 #
4644 # This program is free software; you can redistribute it and/or modify
4645 # it under the terms of the GNU General Public License as published by
4646
4647=== modified file 'bzrlib/tests/test__walkdirs_win32.py'
4648--- bzrlib/tests/test__walkdirs_win32.py 2009-12-21 18:03:49 +0000
4649+++ bzrlib/tests/test__walkdirs_win32.py 2010-04-06 07:24:41 +0000
4650@@ -1,4 +1,4 @@
4651-# Copyright (C) 2008 Canonical Ltd
4652+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4653 #
4654 # This program is free software; you can redistribute it and/or modify
4655 # it under the terms of the GNU General Public License as published by
4656
4657=== modified file 'bzrlib/tests/test_branch.py'
4658--- bzrlib/tests/test_branch.py 2010-02-10 17:52:08 +0000
4659+++ bzrlib/tests/test_branch.py 2010-04-06 07:24:41 +0000
4660@@ -123,16 +123,16 @@
4661 """See BzrBranchFormat.get_format_string()."""
4662 return "Sample branch format."
4663
4664- def initialize(self, a_bzrdir):
4665+ def initialize(self, a_bzrdir, name=None):
4666 """Format 4 branches cannot be created."""
4667- t = a_bzrdir.get_branch_transport(self)
4668+ t = a_bzrdir.get_branch_transport(self, name=name)
4669 t.put_bytes('format', self.get_format_string())
4670 return 'A branch'
4671
4672 def is_supported(self):
4673 return False
4674
4675- def open(self, transport, _found=False, ignore_fallbacks=False):
4676+ def open(self, transport, name=None, _found=False, ignore_fallbacks=False):
4677 return "opened branch."
4678
4679
4680@@ -438,7 +438,7 @@
4681 t.mkdir('branch')
4682 branch_dir = bzrdirformat.initialize(self.get_url('branch'))
4683 made_branch = _mod_branch.BranchReferenceFormat().initialize(
4684- branch_dir, target_branch)
4685+ branch_dir, target_branch=target_branch)
4686 self.assertEqual(made_branch.base, target_branch.base)
4687 opened_branch = branch_dir.open_branch()
4688 self.assertEqual(opened_branch.base, target_branch.base)
4689
4690=== modified file 'bzrlib/tests/test_branchbuilder.py'
4691--- bzrlib/tests/test_branchbuilder.py 2009-05-07 05:08:46 +0000
4692+++ bzrlib/tests/test_branchbuilder.py 2010-04-06 07:24:41 +0000
4693@@ -171,6 +171,15 @@
4694 rev = branch.repository.get_revision(rev_id)
4695 self.assertEqual(u'Foo', rev.message)
4696
4697+ def test_commit_message_callback(self):
4698+ builder = BranchBuilder(self.get_transport().clone('foo'))
4699+ rev_id = builder.build_snapshot(None, None,
4700+ [('add', (u'', None, 'directory', None))],
4701+ message_callback=lambda x:u'Foo')
4702+ branch = builder.get_branch()
4703+ rev = branch.repository.get_revision(rev_id)
4704+ self.assertEqual(u'Foo', rev.message)
4705+
4706 def test_modify_file(self):
4707 builder = self.build_a_rev()
4708 rev_id2 = builder.build_snapshot('B-id', None,
4709
4710=== modified file 'bzrlib/tests/test_btree_index.py'
4711--- bzrlib/tests/test_btree_index.py 2010-01-25 17:48:22 +0000
4712+++ bzrlib/tests/test_btree_index.py 2010-04-06 07:24:41 +0000
4713@@ -1,4 +1,4 @@
4714-# Copyright (C) 2008, 2009 Canonical Ltd
4715+# Copyright (C) 2008, 2009, 2010 Canonical Ltd
4716 #
4717 # This program is free software; you can redistribute it and/or modify
4718 # it under the terms of the GNU General Public License as published by
4719
4720=== modified file 'bzrlib/tests/test_bzrdir.py'
4721--- bzrlib/tests/test_bzrdir.py 2010-02-11 09:21:45 +0000
4722+++ bzrlib/tests/test_bzrdir.py 2010-04-06 07:24:41 +0000
4723@@ -1,4 +1,4 @@
4724-# Copyright (C) 2005, 2006, 2007 Canonical Ltd
4725+# Copyright (C) 2006-2010 Canonical Ltd
4726 #
4727 # This program is free software; you can redistribute it and/or modify
4728 # it under the terms of the GNU General Public License as published by
4729@@ -36,6 +36,7 @@
4730 )
4731 import bzrlib.branch
4732 from bzrlib.errors import (NotBranchError,
4733+ NoColocatedBranchSupport,
4734 UnknownFormatError,
4735 UnsupportedFormatError,
4736 )
4737@@ -206,8 +207,10 @@
4738 """See BzrDir.open_repository."""
4739 return SampleRepository(self)
4740
4741- def create_branch(self):
4742+ def create_branch(self, name=None):
4743 """See BzrDir.create_branch."""
4744+ if name is not None:
4745+ raise NoColocatedBranchSupport(self)
4746 return SampleBranch(self)
4747
4748 def create_workingtree(self):
4749@@ -468,7 +471,8 @@
4750 # Make stackable source branch with an unstackable repo format.
4751 source_bzrdir = self.make_bzrdir('source')
4752 pack_repo.RepositoryFormatKnitPack1().initialize(source_bzrdir)
4753- source_branch = bzrlib.branch.BzrBranchFormat7().initialize(source_bzrdir)
4754+ source_branch = bzrlib.branch.BzrBranchFormat7().initialize(
4755+ source_bzrdir)
4756 # Make a directory with a default stacking policy
4757 parent_bzrdir = self.make_bzrdir('parent')
4758 stacked_on = self.make_branch('parent/stacked-on', format='pack-0.92')
4759
4760=== modified file 'bzrlib/tests/test_cleanup.py'
4761--- bzrlib/tests/test_cleanup.py 2009-12-16 22:29:31 +0000
4762+++ bzrlib/tests/test_cleanup.py 2010-04-06 07:24:41 +0000
4763@@ -1,4 +1,4 @@
4764-# Copyright (C) 2009 Canonical Ltd
4765+# Copyright (C) 2009, 2010 Canonical Ltd
4766 #
4767 # This program is free software; you can redistribute it and/or modify
4768 # it under the terms of the GNU General Public License as published by
4769
4770=== modified file 'bzrlib/tests/test_cmdline.py'
4771--- bzrlib/tests/test_cmdline.py 2010-02-18 02:15:48 +0000
4772+++ bzrlib/tests/test_cmdline.py 2010-04-06 07:24:41 +0000
4773@@ -85,7 +85,7 @@
4774 def test_double_escape(self):
4775 self.assertAsTokens([(True, u'foo\\\\bar')], u'"foo\\\\bar"')
4776 self.assertAsTokens([(False, u'foo\\\\bar')], u"foo\\\\bar")
4777-
4778+
4779 def test_multiple_quoted_args(self):
4780 self.assertAsTokens([(True, u'x x'), (True, u'y y')],
4781 u'"x x" "y y"')
4782
4783=== modified file 'bzrlib/tests/test_commands.py'
4784--- bzrlib/tests/test_commands.py 2010-01-14 13:17:33 +0000
4785+++ bzrlib/tests/test_commands.py 2010-04-06 07:24:41 +0000
4786@@ -24,6 +24,7 @@
4787 config,
4788 errors,
4789 option,
4790+ symbol_versioning,
4791 tests,
4792 )
4793 from bzrlib.commands import display_command
4794@@ -276,32 +277,45 @@
4795
4796 class TestGetMissingCommandHook(tests.TestCase):
4797
4798- def test_fires_on_get_cmd_object(self):
4799- # The get_missing_command(cmd) hook fires when commands are delivered to the
4800- # ui.
4801- hook_calls = []
4802+ def hook_missing(self):
4803+ """Hook get_missing_command for testing."""
4804+ self.hook_calls = []
4805 class ACommand(commands.Command):
4806 """A sample command."""
4807 def get_missing_cmd(cmd_name):
4808- hook_calls.append(('called', cmd_name))
4809+ self.hook_calls.append(('called', cmd_name))
4810 if cmd_name in ('foo', 'info'):
4811 return ACommand()
4812 commands.Command.hooks.install_named_hook(
4813 "get_missing_command", get_missing_cmd, None)
4814+ self.ACommand = ACommand
4815+
4816+ def test_fires_on_get_cmd_object(self):
4817+ # The get_missing_command(cmd) hook fires when commands are delivered to the
4818+ # ui.
4819+ self.hook_missing()
4820 # create a command directly, should not fire
4821- cmd = ACommand()
4822- self.assertEqual([], hook_calls)
4823+ self.cmd = self.ACommand()
4824+ self.assertEqual([], self.hook_calls)
4825 # ask by name, should fire and give us our command
4826 cmd = commands.get_cmd_object('foo')
4827- self.assertEqual([('called', 'foo')], hook_calls)
4828- self.assertIsInstance(cmd, ACommand)
4829- del hook_calls[:]
4830+ self.assertEqual([('called', 'foo')], self.hook_calls)
4831+ self.assertIsInstance(cmd, self.ACommand)
4832+ del self.hook_calls[:]
4833 # ask by a name that is supplied by a builtin - the hook should not
4834 # fire and we still get our object.
4835 commands.install_bzr_command_hooks()
4836 cmd = commands.get_cmd_object('info')
4837 self.assertNotEqual(None, cmd)
4838- self.assertEqual(0, len(hook_calls))
4839+ self.assertEqual(0, len(self.hook_calls))
4840+
4841+ def test_skipped_on_HelpCommandIndex_get_topics(self):
4842+ # The get_missing_command(cmd_name) hook is not fired when
4843+ # looking up help topics.
4844+ self.hook_missing()
4845+ topic = commands.HelpCommandIndex()
4846+ topics = topic.get_topics('foo')
4847+ self.assertEqual([], self.hook_calls)
4848
4849
4850 class TestListCommandHook(tests.TestCase):
4851@@ -323,3 +337,10 @@
4852 cmds = list(commands.all_command_names())
4853 self.assertEqual(['called'], hook_calls)
4854 self.assertSubset(['foo', 'bar'], cmds)
4855+
4856+class TestDeprecations(tests.TestCase):
4857+
4858+ def test_shlex_split_unicode_deprecation(self):
4859+ res = self.applyDeprecated(
4860+ symbol_versioning.deprecated_in((2, 2, 0)),
4861+ commands.shlex_split_unicode, 'whatever')
4862
4863=== modified file 'bzrlib/tests/test_commit.py'
4864--- bzrlib/tests/test_commit.py 2010-02-13 01:50:29 +0000
4865+++ bzrlib/tests/test_commit.py 2010-04-06 07:24:41 +0000
4866@@ -1,4 +1,4 @@
4867-# Copyright (C) 2005, 2006, 2008 Canonical Ltd
4868+# Copyright (C) 2005-2010 Canonical Ltd
4869 #
4870 # This program is free software; you can redistribute it and/or modify
4871 # it under the terms of the GNU General Public License as published by
4872
4873=== modified file 'bzrlib/tests/test_config.py'
4874--- bzrlib/tests/test_config.py 2010-01-25 17:48:22 +0000
4875+++ bzrlib/tests/test_config.py 2010-04-06 07:24:41 +0000
4876@@ -1,4 +1,4 @@
4877-# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
4878+# Copyright (C) 2005-2010 Canonical Ltd
4879 #
4880 # This program is free software; you can redistribute it and/or modify
4881 # it under the terms of the GNU General Public License as published by
4882
4883=== modified file 'bzrlib/tests/test_conflicts.py'
4884--- bzrlib/tests/test_conflicts.py 2010-02-10 17:52:08 +0000
4885+++ bzrlib/tests/test_conflicts.py 2010-04-06 07:24:41 +0000
4886@@ -18,15 +18,32 @@
4887 import os
4888
4889 from bzrlib import (
4890+ branchbuilder,
4891 bzrdir,
4892 conflicts,
4893 errors,
4894 option,
4895 tests,
4896+ workingtree,
4897 )
4898 from bzrlib.tests import script
4899
4900
4901+def load_tests(standard_tests, module, loader):
4902+ result = loader.suiteClass()
4903+
4904+ sp_tests, remaining_tests = tests.split_suite_by_condition(
4905+ standard_tests, tests.condition_isinstance((
4906+ TestResolveContentConflicts,
4907+ )))
4908+ tests.multiply_tests(sp_tests, content_conflict_scenarios(), result)
4909+
4910+ # No parametrization for the remaining tests
4911+ result.addTests(remaining_tests)
4912+
4913+ return result
4914+
4915+
4916 # TODO: Test commit with some added, and added-but-missing files
4917 # RBC 20060124 is that not tested in test_commit.py ?
4918
4919@@ -69,15 +86,15 @@
4920 ('hello.sploo.OTHER', 'yellowworld2'),
4921 ])
4922 tree.lock_read()
4923- self.assertEqual(6, len(list(tree.list_files())))
4924+ self.assertLength(6, list(tree.list_files()))
4925 tree.unlock()
4926 tree_conflicts = tree.conflicts()
4927- self.assertEqual(2, len(tree_conflicts))
4928+ self.assertLength(2, tree_conflicts)
4929 self.assertTrue('hello' in tree_conflicts[0].path)
4930 self.assertTrue('hello.sploo' in tree_conflicts[1].path)
4931 conflicts.restore('hello')
4932 conflicts.restore('hello.sploo')
4933- self.assertEqual(0, len(tree.conflicts()))
4934+ self.assertLength(0, tree.conflicts())
4935 self.assertFileEqual('hello world2', 'hello')
4936 self.assertFalse(os.path.lexists('hello.sploo'))
4937 self.assertRaises(errors.NotConflicted, conflicts.restore, 'hello')
4938@@ -192,59 +209,99 @@
4939 pass
4940
4941
4942-class TestResolveContentConflicts(TestResolveConflicts):
4943-
4944- # FIXME: We need to add the reverse case (delete in trunk, modify in
4945- # branch) but that could wait until the resolution mechanism is implemented.
4946-
4947- preamble = """
4948-$ bzr init trunk
4949-$ cd trunk
4950-$ echo 'trunk content' >file
4951-$ bzr add file
4952-$ bzr commit -m 'Create trunk'
4953-
4954-$ bzr branch . ../branch
4955-$ cd ../branch
4956-$ bzr rm file
4957-$ bzr commit -m 'Delete file'
4958-
4959-$ cd ../trunk
4960-$ echo 'more content' >>file
4961-$ bzr commit -m 'Modify file'
4962-
4963-$ cd ../branch
4964-$ bzr merge ../trunk
4965-2>+N file.OTHER
4966-2>Contents conflict in file
4967-2>1 conflicts encountered.
4968-"""
4969-
4970- def test_take_this(self):
4971- self.run_script("""
4972-$ bzr rm file.OTHER --force # a simple rm file.OTHER is valid too
4973-$ bzr resolve file
4974-$ bzr commit --strict -m 'No more conflicts nor unknown files'
4975-""")
4976-
4977- def test_take_other(self):
4978- self.run_script("""
4979-$ bzr mv file.OTHER file
4980-$ bzr resolve file
4981-$ bzr commit --strict -m 'No more conflicts nor unknown files'
4982-""")
4983+def content_conflict_scenarios():
4984+ return [('file,None', dict(_this_actions='modify_file',
4985+ _check_this='file_has_more_content',
4986+ _other_actions='delete_file',
4987+ _check_other='file_doesnt_exist',
4988+ )),
4989+ ('None,file', dict(_this_actions='delete_file',
4990+ _check_this='file_doesnt_exist',
4991+ _other_actions='modify_file',
4992+ _check_other='file_has_more_content',
4993+ )),
4994+ ]
4995+
4996+
4997+class TestResolveContentConflicts(tests.TestCaseWithTransport):
4998+
4999+ # Set by load_tests
5000+ this_actions = None
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches