Status: | Merged |
---|---|
Merged at revision: | 7311 |
Proposed branch: | lp:~jelmer/brz/appveyor |
Merge into: | lp:brz |
Diff against target: |
1691 lines (+551/-192) 42 files modified
appveyor.yml (+92/-0) breezy/_patiencediff_c.c (+41/-8) breezy/builtins.py (+35/-26) breezy/git/cache.py (+1/-3) breezy/git/git-remote-bzr (+7/-2) breezy/git/git_remote_helper.py (+1/-1) breezy/git/memorytree.py (+4/-0) breezy/git/object_store.py (+2/-2) breezy/git/tests/test_blackbox.py (+9/-0) breezy/git/tests/test_branch.py (+7/-1) breezy/git/tests/test_git_remote_helper.py (+31/-2) breezy/git/tests/test_object_store.py (+32/-2) breezy/globbing.py (+3/-1) breezy/ignores.py (+1/-1) breezy/memorytree.py (+18/-4) breezy/plugins/propose/launchpad.py (+1/-0) breezy/python-compat.h (+4/-0) breezy/tests/blackbox/test_bisect.py (+1/-0) breezy/tests/blackbox/test_push.py (+20/-0) breezy/tests/blackbox/test_remove.py (+2/-1) breezy/tests/blackbox/test_uncommit.py (+14/-0) breezy/tests/features.py (+14/-0) breezy/tests/test_memorytree.py (+65/-70) breezy/tests/test_script.py (+2/-2) breezy/tests/test_urlutils.py (+3/-0) breezy/transport/memory.py (+50/-32) breezy/urlutils.py (+4/-1) build.cmd (+21/-0) byov.conf (+4/-2) doc/developers/apport.txt (+1/-1) doc/developers/configuration.txt (+0/-14) doc/developers/contribution-quickstart.txt (+1/-1) doc/developers/plugin-development.txt (+1/-1) doc/en/admin-guide/hooks-plugins.txt (+4/-4) doc/en/admin-guide/migration.txt (+1/-1) doc/en/release-notes/brz-3.0.txt (+10/-0) doc/en/user-guide/controlling_registration.txt (+3/-3) doc/en/user-guide/git_limitations.txt (+18/-0) doc/en/user-guide/index-plain.txt (+1/-0) doc/en/user-guide/installing_breezy.txt (+1/-1) doc/en/user-guide/plugins.txt (+2/-2) setup.py (+19/-3) |
To merge this branch: | bzr merge lp:~jelmer/brz/appveyor |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Breezy developers | Pending | ||
Review via email: mp+363947@code.launchpad.net |
Commit message
Description of the change
Add appveyor configuration.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'appveyor.yml' | |||
2 | --- appveyor.yml 1970-01-01 00:00:00 +0000 | |||
3 | +++ appveyor.yml 2019-03-06 06:08:28 +0000 | |||
4 | @@ -0,0 +1,92 @@ | |||
5 | 1 | environment: | ||
6 | 2 | |||
7 | 3 | matrix: | ||
8 | 4 | |||
9 | 5 | - PYTHON: "C:\\Python27" | ||
10 | 6 | PYTHON_VERSION: "2.7.x" | ||
11 | 7 | PYTHON_ARCH: "32" | ||
12 | 8 | |||
13 | 9 | - PYTHON: "C:\\Python27-x64" | ||
14 | 10 | PYTHON_VERSION: "2.7.x" | ||
15 | 11 | PYTHON_ARCH: "64" | ||
16 | 12 | |||
17 | 13 | - PYTHON: "C:\\Python34" | ||
18 | 14 | PYTHON_VERSION: "3.4.x" | ||
19 | 15 | PYTHON_ARCH: "32" | ||
20 | 16 | |||
21 | 17 | - PYTHON: "C:\\Python34-x64" | ||
22 | 18 | PYTHON_VERSION: "3.4.x" | ||
23 | 19 | PYTHON_ARCH: "64" | ||
24 | 20 | DISTUTILS_USE_SDK: "1" | ||
25 | 21 | |||
26 | 22 | - PYTHON: "C:\\Python35" | ||
27 | 23 | PYTHON_VERSION: "3.5.x" | ||
28 | 24 | PYTHON_ARCH: "32" | ||
29 | 25 | |||
30 | 26 | - PYTHON: "C:\\Python35-x64" | ||
31 | 27 | PYTHON_VERSION: "3.5.x" | ||
32 | 28 | PYTHON_ARCH: "64" | ||
33 | 29 | |||
34 | 30 | - PYTHON: "C:\\Python36" | ||
35 | 31 | PYTHON_VERSION: "3.6.x" | ||
36 | 32 | PYTHON_ARCH: "32" | ||
37 | 33 | |||
38 | 34 | - PYTHON: "C:\\Python36-x64" | ||
39 | 35 | PYTHON_VERSION: "3.6.x" | ||
40 | 36 | PYTHON_ARCH: "64" | ||
41 | 37 | |||
42 | 38 | install: | ||
43 | 39 | # If there is a newer build queued for the same PR, cancel this one. | ||
44 | 40 | # The AppVeyor 'rollout builds' option is supposed to serve the same | ||
45 | 41 | # purpose but it is problematic because it tends to cancel builds pushed | ||
46 | 42 | # directly to master instead of just PR builds (or the converse). | ||
47 | 43 | # credits: JuliaLang developers. | ||
48 | 44 | - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` | ||
49 | 45 | https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` | ||
50 | 46 | Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` | ||
51 | 47 | throw "There are newer queued builds for this pull request, failing early." } | ||
52 | 48 | - ECHO "Filesystem root:" | ||
53 | 49 | - ps: "ls \"C:/\"" | ||
54 | 50 | |||
55 | 51 | - ECHO "Installed SDKs:" | ||
56 | 52 | - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\"" | ||
57 | 53 | |||
58 | 54 | # Install Python (from the official .msi of http://python.org) and pip when | ||
59 | 55 | # not already installed. | ||
60 | 56 | - ps: if (-not(Test-Path($env:PYTHON))) { & appveyor\install.ps1 } | ||
61 | 57 | |||
62 | 58 | # Prepend newly installed Python to the PATH of this build (this cannot be | ||
63 | 59 | # done from inside the powershell script as it would require to restart | ||
64 | 60 | # the parent CMD process). | ||
65 | 61 | - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" | ||
66 | 62 | |||
67 | 63 | # Check that we have the expected version and architecture for Python | ||
68 | 64 | - "build.cmd %PYTHON%\\python.exe --version" | ||
69 | 65 | - "build.cmd %PYTHON%\\python.exe -c \"import struct; print(struct.calcsize('P') * 8)\"" | ||
70 | 66 | |||
71 | 67 | # Install setuptools/wheel so that we can e.g. use bdist_wheel | ||
72 | 68 | - "pip install setuptools wheel" | ||
73 | 69 | # Install cython so we can build C extensions | ||
74 | 70 | - "pip install cython" | ||
75 | 71 | |||
76 | 72 | - "build.cmd %PYTHON%\\python.exe setup.py develop" | ||
77 | 73 | |||
78 | 74 | - "pip install launchpadlib" | ||
79 | 75 | |||
80 | 76 | build_script: | ||
81 | 77 | # Build the compiled extension | ||
82 | 78 | - "build.cmd %PYTHON%\\python.exe setup.py build" | ||
83 | 79 | |||
84 | 80 | test_script: | ||
85 | 81 | - "build.cmd %PYTHON%\\python.exe setup.py test" | ||
86 | 82 | - "build.cmd %PYTHON%\\pythonw.exe setup.py test" | ||
87 | 83 | |||
88 | 84 | after_test: | ||
89 | 85 | - "build.cmd %PYTHON%\\python.exe setup.py bdist_wheel" | ||
90 | 86 | # http://stackoverflow.com/questions/43255455/unicode-character-causing-error-with-bdist-wininst-on-python-3-but-not-python-2 | ||
91 | 87 | # - "python setup.py bdist_wininst" | ||
92 | 88 | - "build.cmd %PYTHON%\\python.exe setup.py bdist_msi" | ||
93 | 89 | - ps: "ls dist" | ||
94 | 90 | |||
95 | 91 | artifacts: | ||
96 | 92 | - path: dist\* | ||
97 | 0 | 93 | ||
98 | === modified file 'breezy/_patiencediff_c.c' | |||
99 | --- breezy/_patiencediff_c.c 2019-01-27 18:53:46 +0000 | |||
100 | +++ breezy/_patiencediff_c.c 2019-03-06 06:08:28 +0000 | |||
101 | @@ -1163,14 +1163,47 @@ | |||
102 | 1163 | 1163 | ||
103 | 1164 | 1164 | ||
104 | 1165 | static PyTypeObject PatienceSequenceMatcherType = { | 1165 | static PyTypeObject PatienceSequenceMatcherType = { |
113 | 1166 | PyObject_HEAD_INIT(NULL) | 1166 | PyVarObject_HEAD_INIT(NULL, 0) |
114 | 1167 | .tp_name = "PatienceSequenceMatcher", | 1167 | "PatienceSequenceMatcher", /* tp_name */ |
115 | 1168 | .tp_basicsize = sizeof(PatienceSequenceMatcher), | 1168 | sizeof(PatienceSequenceMatcher), /* tp_basicsize */ |
116 | 1169 | .tp_dealloc = (destructor)PatienceSequenceMatcher_dealloc, | 1169 | sizeof(PyObject *), /* tp_itemsize */ |
117 | 1170 | .tp_flags = Py_TPFLAGS_DEFAULT, | 1170 | (destructor)PatienceSequenceMatcher_dealloc, /* tp_dealloc */ |
118 | 1171 | .tp_doc = PatienceSequenceMatcher_doc, | 1171 | 0, /* tp_print */ |
119 | 1172 | .tp_methods = PatienceSequenceMatcher_methods, | 1172 | 0, /* tp_getattr */ |
120 | 1173 | .tp_new = PatienceSequenceMatcher_new, | 1173 | 0, /* tp_setattr */ |
121 | 1174 | 0, /* tp_compare */ | ||
122 | 1175 | 0, /* tp_repr */ | ||
123 | 1176 | 0, /* tp_as_number */ | ||
124 | 1177 | 0, /* tp_as_sequence */ | ||
125 | 1178 | 0, /* tp_as_mapping */ | ||
126 | 1179 | 0, /* tp_hash */ | ||
127 | 1180 | 0, /* tp_call */ | ||
128 | 1181 | 0, /* tp_str */ | ||
129 | 1182 | 0, /* tp_getattro */ | ||
130 | 1183 | 0, /* tp_setattro */ | ||
131 | 1184 | 0, /* tp_as_buffer */ | ||
132 | 1185 | Py_TPFLAGS_DEFAULT, /* tp_flags */ | ||
133 | 1186 | PatienceSequenceMatcher_doc, /* tp_doc */ | ||
134 | 1187 | 0, /* tp_traverse */ | ||
135 | 1188 | 0, /* tp_clear */ | ||
136 | 1189 | 0, /* tp_richcompare */ | ||
137 | 1190 | 0, /* tp_weaklistoffset */ | ||
138 | 1191 | // without implementing tp_iter, Python will fall back to PySequence* | ||
139 | 1192 | // which seems to work ok, we may need something faster/lighter in the | ||
140 | 1193 | // future. | ||
141 | 1194 | 0, /* tp_iter */ | ||
142 | 1195 | 0, /* tp_iternext */ | ||
143 | 1196 | PatienceSequenceMatcher_methods, /* tp_methods */ | ||
144 | 1197 | 0, /* tp_members */ | ||
145 | 1198 | 0, /* tp_getset */ | ||
146 | 1199 | 0, /* tp_base */ | ||
147 | 1200 | 0, /* tp_dict */ | ||
148 | 1201 | 0, /* tp_descr_get */ | ||
149 | 1202 | 0, /* tp_descr_set */ | ||
150 | 1203 | 0, /* tp_dictoffset */ | ||
151 | 1204 | 0, /* tp_init */ | ||
152 | 1205 | 0, /* tp_alloc */ | ||
153 | 1206 | PatienceSequenceMatcher_new, /* tp_new */ | ||
154 | 1174 | }; | 1207 | }; |
155 | 1175 | 1208 | ||
156 | 1176 | 1209 | ||
157 | 1177 | 1210 | ||
158 | === modified file 'breezy/builtins.py' | |||
159 | --- breezy/builtins.py 2019-02-09 03:23:20 +0000 | |||
160 | +++ breezy/builtins.py 2019-03-06 06:08:28 +0000 | |||
161 | @@ -348,7 +348,7 @@ | |||
162 | 348 | Not versioned and not matching an ignore pattern. | 348 | Not versioned and not matching an ignore pattern. |
163 | 349 | 349 | ||
164 | 350 | Additionally for directories, symlinks and files with a changed | 350 | Additionally for directories, symlinks and files with a changed |
166 | 351 | executable bit, Bazaar indicates their type using a trailing | 351 | executable bit, Breezy indicates their type using a trailing |
167 | 352 | character: '/', '@' or '*' respectively. These decorations can be | 352 | character: '/', '@' or '*' respectively. These decorations can be |
168 | 353 | disabled using the '--no-classify' option. | 353 | disabled using the '--no-classify' option. |
169 | 354 | 354 | ||
170 | @@ -454,11 +454,11 @@ | |||
171 | 454 | 454 | ||
172 | 455 | b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1] | 455 | b = controldir.ControlDir.open_containing_tree_or_branch(directory)[1] |
173 | 456 | 456 | ||
175 | 457 | revisions = b.repository.revisions | 457 | revisions = getattr(b.repository, "revisions", None) |
176 | 458 | if revisions is None: | 458 | if revisions is None: |
177 | 459 | raise errors.BzrCommandError( | 459 | raise errors.BzrCommandError( |
178 | 460 | gettext('Repository %r does not support ' | 460 | gettext('Repository %r does not support ' |
180 | 461 | 'access to raw revision texts')) | 461 | 'access to raw revision texts') % b.repository) |
181 | 462 | 462 | ||
182 | 463 | with b.repository.lock_read(): | 463 | with b.repository.lock_read(): |
183 | 464 | # TODO: jam 20060112 should cat-revision always output utf-8? | 464 | # TODO: jam 20060112 should cat-revision always output utf-8? |
184 | @@ -1344,6 +1344,7 @@ | |||
185 | 1344 | use_existing_dir=False, directory=None, stacked_on=None, | 1344 | use_existing_dir=False, directory=None, stacked_on=None, |
186 | 1345 | stacked=False, strict=None, no_tree=False, | 1345 | stacked=False, strict=None, no_tree=False, |
187 | 1346 | overwrite_tags=False, lossy=False): | 1346 | overwrite_tags=False, lossy=False): |
188 | 1347 | from .location import location_to_url | ||
189 | 1347 | from .push import _show_push_branch | 1348 | from .push import _show_push_branch |
190 | 1348 | 1349 | ||
191 | 1349 | if overwrite: | 1350 | if overwrite: |
192 | @@ -1371,6 +1372,7 @@ | |||
193 | 1371 | more_warning='Uncommitted changes will not be pushed.') | 1372 | more_warning='Uncommitted changes will not be pushed.') |
194 | 1372 | # Get the stacked_on branch, if any | 1373 | # Get the stacked_on branch, if any |
195 | 1373 | if stacked_on is not None: | 1374 | if stacked_on is not None: |
196 | 1375 | stacked_on = location_to_url(stacked_on, 'read') | ||
197 | 1374 | stacked_on = urlutils.normalize_url(stacked_on) | 1376 | stacked_on = urlutils.normalize_url(stacked_on) |
198 | 1375 | elif stacked: | 1377 | elif stacked: |
199 | 1376 | parent_url = br_from.get_parent() | 1378 | parent_url = br_from.get_parent() |
200 | @@ -1728,7 +1730,7 @@ | |||
201 | 1728 | If the tree's branch is bound to a master branch, brz will also update | 1730 | If the tree's branch is bound to a master branch, brz will also update |
202 | 1729 | the branch from the master. | 1731 | the branch from the master. |
203 | 1730 | 1732 | ||
205 | 1731 | You cannot update just a single file or directory, because each Bazaar | 1733 | You cannot update just a single file or directory, because each Breezy |
206 | 1732 | working tree has just a single basis revision. If you want to restore a | 1734 | working tree has just a single basis revision. If you want to restore a |
207 | 1733 | file that has been removed locally, use 'brz revert' instead of 'brz | 1735 | file that has been removed locally, use 'brz revert' instead of 'brz |
208 | 1734 | update'. If you want to restore a file to its state in a previous | 1736 | update'. If you want to restore a file to its state in a previous |
209 | @@ -1871,11 +1873,11 @@ | |||
210 | 1871 | class cmd_remove(Command): | 1873 | class cmd_remove(Command): |
211 | 1872 | __doc__ = """Remove files or directories. | 1874 | __doc__ = """Remove files or directories. |
212 | 1873 | 1875 | ||
214 | 1874 | This makes Bazaar stop tracking changes to the specified files. Bazaar will | 1876 | This makes Breezy stop tracking changes to the specified files. Breezy will |
215 | 1875 | delete them if they can easily be recovered using revert otherwise they | 1877 | delete them if they can easily be recovered using revert otherwise they |
216 | 1876 | will be backed up (adding an extension of the form .~#~). If no options or | 1878 | will be backed up (adding an extension of the form .~#~). If no options or |
219 | 1877 | parameters are given Bazaar will scan for files that are being tracked by | 1879 | parameters are given Breezy will scan for files that are being tracked by |
220 | 1878 | Bazaar but missing in your tree and stop tracking them for you. | 1880 | Breezy but missing in your tree and stop tracking them for you. |
221 | 1879 | """ | 1881 | """ |
222 | 1880 | takes_args = ['file*'] | 1882 | takes_args = ['file*'] |
223 | 1881 | takes_options = ['verbose', | 1883 | takes_options = ['verbose', |
224 | @@ -3091,9 +3093,10 @@ | |||
225 | 3091 | using this command or directly by using an editor, be sure to commit | 3093 | using this command or directly by using an editor, be sure to commit |
226 | 3092 | it. | 3094 | it. |
227 | 3093 | 3095 | ||
231 | 3094 | Bazaar also supports a global ignore file ~/.bazaar/ignore. On Windows | 3096 | Breezy also supports a global ignore file ~/.config/breezy/ignore. On |
232 | 3095 | the global ignore file can be found in the application data directory as | 3097 | Windows the global ignore file can be found in the application data |
233 | 3096 | C:\\Documents and Settings\\<user>\\Application Data\\Bazaar\\2.0\\ignore. | 3098 | directory as |
234 | 3099 | C:\\Documents and Settings\\<user>\\Application Data\\Breezy\\3.0\\ignore. | ||
235 | 3097 | Global ignores are not touched by this command. The global ignore file | 3100 | Global ignores are not touched by this command. The global ignore file |
236 | 3098 | can be edited directly using an editor. | 3101 | can be edited directly using an editor. |
237 | 3099 | 3102 | ||
238 | @@ -3732,7 +3735,7 @@ | |||
239 | 3732 | unreferenced ancestors | 3735 | unreferenced ancestors |
240 | 3733 | Texts that are ancestors of other texts, but | 3736 | Texts that are ancestors of other texts, but |
241 | 3734 | are not properly referenced by the revision ancestry. This is a | 3737 | are not properly referenced by the revision ancestry. This is a |
243 | 3735 | subtle problem that Bazaar can work around. | 3738 | subtle problem that Breezy can work around. |
244 | 3736 | 3739 | ||
245 | 3737 | unique file texts | 3740 | unique file texts |
246 | 3738 | This is the total number of unique file contents | 3741 | This is the total number of unique file contents |
247 | @@ -3744,7 +3747,7 @@ | |||
248 | 3744 | entries are modified, but the file contents are not. It does not | 3747 | entries are modified, but the file contents are not. It does not |
249 | 3745 | indicate a problem. | 3748 | indicate a problem. |
250 | 3746 | 3749 | ||
252 | 3747 | If no restrictions are specified, all Bazaar data that is found at the given | 3750 | If no restrictions are specified, all data that is found at the given |
253 | 3748 | location will be checked. | 3751 | location will be checked. |
254 | 3749 | 3752 | ||
255 | 3750 | :Examples: | 3753 | :Examples: |
256 | @@ -3786,10 +3789,10 @@ | |||
257 | 3786 | __doc__ = """Upgrade a repository, branch or working tree to a newer format. | 3789 | __doc__ = """Upgrade a repository, branch or working tree to a newer format. |
258 | 3787 | 3790 | ||
259 | 3788 | When the default format has changed after a major new release of | 3791 | When the default format has changed after a major new release of |
261 | 3789 | Bazaar, you may be informed during certain operations that you | 3792 | Bazaar/Breezy, you may be informed during certain operations that you |
262 | 3790 | should upgrade. Upgrading to a newer format may improve performance | 3793 | should upgrade. Upgrading to a newer format may improve performance |
263 | 3791 | or make new features available. It may however limit interoperability | 3794 | or make new features available. It may however limit interoperability |
265 | 3792 | with older repositories or with older versions of Bazaar. | 3795 | with older repositories or with older versions of Bazaar or Breezy. |
266 | 3793 | 3796 | ||
267 | 3794 | If you wish to upgrade to a particular format rather than the | 3797 | If you wish to upgrade to a particular format rather than the |
268 | 3795 | current default, that can be specified using the --format option. | 3798 | current default, that can be specified using the --format option. |
269 | @@ -3811,7 +3814,7 @@ | |||
270 | 3811 | If the conversion of a branch fails, remaining branches are still | 3814 | If the conversion of a branch fails, remaining branches are still |
271 | 3812 | tried. | 3815 | tried. |
272 | 3813 | 3816 | ||
274 | 3814 | For more information on upgrades, see the Bazaar Upgrade Guide, | 3817 | For more information on upgrades, see the Breezy Upgrade Guide, |
275 | 3815 | https://www.breezy-vcs.org/doc/en/upgrade-guide/. | 3818 | https://www.breezy-vcs.org/doc/en/upgrade-guide/. |
276 | 3816 | """ | 3819 | """ |
277 | 3817 | 3820 | ||
278 | @@ -4312,7 +4315,7 @@ | |||
279 | 4312 | through OTHER, excluding BASE but including OTHER, will be merged. If this | 4315 | through OTHER, excluding BASE but including OTHER, will be merged. If this |
280 | 4313 | causes some revisions to be skipped, i.e. if the destination branch does | 4316 | causes some revisions to be skipped, i.e. if the destination branch does |
281 | 4314 | not already contain revision BASE, such a merge is commonly referred to as | 4317 | not already contain revision BASE, such a merge is commonly referred to as |
283 | 4315 | a "cherrypick". Unlike a normal merge, Bazaar does not currently track | 4318 | a "cherrypick". Unlike a normal merge, Breezy does not currently track |
284 | 4316 | cherrypicks. The changes look like a normal commit, and the history of the | 4319 | cherrypicks. The changes look like a normal commit, and the history of the |
285 | 4317 | changes from the other branch is not stored in the commit. | 4320 | changes from the other branch is not stored in the commit. |
286 | 4318 | 4321 | ||
287 | @@ -5133,8 +5136,8 @@ | |||
288 | 5133 | 5136 | ||
289 | 5134 | --verbose shows the path where each plugin is located. | 5137 | --verbose shows the path where each plugin is located. |
290 | 5135 | 5138 | ||
293 | 5136 | A plugin is an external component for Bazaar that extends the | 5139 | A plugin is an external component for Breezy that extends the |
294 | 5137 | revision control system, by adding or replacing code in Bazaar. | 5140 | revision control system, by adding or replacing code in Breezy. |
295 | 5138 | Plugins can do a variety of things, including overriding commands, | 5141 | Plugins can do a variety of things, including overriding commands, |
296 | 5139 | adding new commands, providing additional network transports and | 5142 | adding new commands, providing additional network transports and |
297 | 5140 | customizing log output. | 5143 | customizing log output. |
298 | @@ -5420,10 +5423,10 @@ | |||
299 | 5420 | else: | 5423 | else: |
300 | 5421 | self.add_cleanup(b.lock_write().unlock) | 5424 | self.add_cleanup(b.lock_write().unlock) |
301 | 5422 | return self._run(b, tree, dry_run, verbose, revision, force, | 5425 | return self._run(b, tree, dry_run, verbose, revision, force, |
303 | 5423 | local, keep_tags) | 5426 | local, keep_tags, location) |
304 | 5424 | 5427 | ||
305 | 5425 | def _run(self, b, tree, dry_run, verbose, revision, force, local, | 5428 | def _run(self, b, tree, dry_run, verbose, revision, force, local, |
307 | 5426 | keep_tags): | 5429 | keep_tags, location): |
308 | 5427 | from .log import log_formatter, show_log | 5430 | from .log import log_formatter, show_log |
309 | 5428 | from .uncommit import uncommit | 5431 | from .uncommit import uncommit |
310 | 5429 | 5432 | ||
311 | @@ -5477,10 +5480,16 @@ | |||
312 | 5477 | last_rev_id, rev_id) | 5480 | last_rev_id, rev_id) |
313 | 5478 | uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose, | 5481 | uncommit(b, tree=tree, dry_run=dry_run, verbose=verbose, |
314 | 5479 | revno=revno, local=local, keep_tags=keep_tags) | 5482 | revno=revno, local=local, keep_tags=keep_tags) |
319 | 5480 | self.outf.write( | 5483 | if location != '.': |
320 | 5481 | gettext('You can restore the old tip by running:\n' | 5484 | self.outf.write( |
321 | 5482 | ' brz pull . -r revid:%s\n') | 5485 | gettext('You can restore the old tip by running:\n' |
322 | 5483 | % last_rev_id.decode('utf-8')) | 5486 | ' brz pull -d %s %s -r revid:%s\n') |
323 | 5487 | % (location, location, last_rev_id.decode('utf-8'))) | ||
324 | 5488 | else: | ||
325 | 5489 | self.outf.write( | ||
326 | 5490 | gettext('You can restore the old tip by running:\n' | ||
327 | 5491 | ' brz pull . -r revid:%s\n') | ||
328 | 5492 | % last_rev_id.decode('utf-8')) | ||
329 | 5484 | 5493 | ||
330 | 5485 | 5494 | ||
331 | 5486 | class cmd_break_lock(Command): | 5495 | class cmd_break_lock(Command): |
332 | @@ -5498,7 +5507,7 @@ | |||
333 | 5498 | :Examples: | 5507 | :Examples: |
334 | 5499 | brz break-lock | 5508 | brz break-lock |
335 | 5500 | brz break-lock brz+ssh://example.com/brz/foo | 5509 | brz break-lock brz+ssh://example.com/brz/foo |
337 | 5501 | brz break-lock --conf ~/.bazaar | 5510 | brz break-lock --conf ~/.config/breezy |
338 | 5502 | """ | 5511 | """ |
339 | 5503 | 5512 | ||
340 | 5504 | takes_args = ['location?'] | 5513 | takes_args = ['location?'] |
341 | @@ -5789,7 +5798,7 @@ | |||
342 | 5789 | branch containing submit_branch in its ancestory without needing access to | 5798 | branch containing submit_branch in its ancestory without needing access to |
343 | 5790 | the source branch. | 5799 | the source branch. |
344 | 5791 | 5800 | ||
346 | 5792 | If --no-bundle is specified, then Bazaar doesn't send the contents of the | 5801 | If --no-bundle is specified, then Breezy doesn't send the contents of the |
347 | 5793 | revisions, but only a structured request to merge from the | 5802 | revisions, but only a structured request to merge from the |
348 | 5794 | public_location. In that case the public_branch is needed and it must be | 5803 | public_location. In that case the public_branch is needed and it must be |
349 | 5795 | up-to-date and accessible to the recipient. The public_branch is always | 5804 | up-to-date and accessible to the recipient. The public_branch is always |
350 | 5796 | 5805 | ||
351 | === modified file 'breezy/git/cache.py' | |||
352 | --- breezy/git/cache.py 2018-11-12 01:41:38 +0000 | |||
353 | +++ breezy/git/cache.py 2019-03-06 06:08:28 +0000 | |||
354 | @@ -613,11 +613,9 @@ | |||
355 | 613 | 613 | ||
356 | 614 | def open(self, transport): | 614 | def open(self, transport): |
357 | 615 | try: | 615 | try: |
359 | 616 | basepath = transport.local_abspath(".").encode(osutils._fs_enc) | 616 | basepath = transport.local_abspath(".") |
360 | 617 | except bzr_errors.NotLocalUrl: | 617 | except bzr_errors.NotLocalUrl: |
361 | 618 | basepath = get_cache_dir() | 618 | basepath = get_cache_dir() |
362 | 619 | if not isinstance(basepath, str): | ||
363 | 620 | raise TypeError(basepath) | ||
364 | 621 | try: | 619 | try: |
365 | 622 | return TdbBzrGitCache(os.path.join(basepath, "idmap.tdb")) | 620 | return TdbBzrGitCache(os.path.join(basepath, "idmap.tdb")) |
366 | 623 | except ImportError: | 621 | except ImportError: |
367 | 624 | 622 | ||
368 | === modified file 'breezy/git/git-remote-bzr' | |||
369 | --- breezy/git/git-remote-bzr 2018-03-26 22:28:24 +0000 | |||
370 | +++ breezy/git/git-remote-bzr 2019-03-06 06:08:28 +0000 | |||
371 | @@ -32,10 +32,12 @@ | |||
372 | 32 | import breezy | 32 | import breezy |
373 | 33 | breezy.initialize() | 33 | breezy.initialize() |
374 | 34 | 34 | ||
375 | 35 | from breezy.sixish import PY3 | ||
376 | 36 | |||
377 | 35 | from breezy.plugin import load_plugins | 37 | from breezy.plugin import load_plugins |
378 | 36 | load_plugins() | 38 | load_plugins() |
379 | 37 | 39 | ||
381 | 38 | from breezy.plugins.git.git_remote_helper import ( | 40 | from breezy.git.git_remote_helper import ( |
382 | 39 | RemoteHelper, | 41 | RemoteHelper, |
383 | 40 | open_local_dir, | 42 | open_local_dir, |
384 | 41 | open_remote_dir, | 43 | open_remote_dir, |
385 | @@ -46,4 +48,7 @@ | |||
386 | 46 | (shortname, url) = args | 48 | (shortname, url) = args |
387 | 47 | 49 | ||
388 | 48 | helper = RemoteHelper(open_local_dir(), shortname, open_remote_dir(url)) | 50 | helper = RemoteHelper(open_local_dir(), shortname, open_remote_dir(url)) |
390 | 49 | helper.process(sys.stdin, sys.stdout) | 51 | if PY3: |
391 | 52 | helper.process(sys.stdin.buffer, sys.stdout.buffer) | ||
392 | 53 | else: | ||
393 | 54 | helper.process(sys.stdin, sys.stdout) | ||
394 | 50 | 55 | ||
395 | === modified file 'breezy/git/git_remote_helper.py' | |||
396 | --- breezy/git/git_remote_helper.py 2018-11-11 14:23:06 +0000 | |||
397 | +++ breezy/git/git_remote_helper.py 2019-03-06 06:08:28 +0000 | |||
398 | @@ -186,7 +186,7 @@ | |||
399 | 186 | self.batchcmd = None | 186 | self.batchcmd = None |
400 | 187 | else: | 187 | else: |
401 | 188 | try: | 188 | try: |
403 | 189 | self.commands[argv[0]](self, outf, argv) | 189 | self.commands[argv[0].decode()](self, outf, argv) |
404 | 190 | except KeyError: | 190 | except KeyError: |
405 | 191 | raise Exception("Unknown remote command %r" % argv) | 191 | raise Exception("Unknown remote command %r" % argv) |
406 | 192 | outf.flush() | 192 | outf.flush() |
407 | 193 | 193 | ||
408 | === modified file 'breezy/git/memorytree.py' | |||
409 | --- breezy/git/memorytree.py 2018-11-18 00:25:19 +0000 | |||
410 | +++ breezy/git/memorytree.py 2019-03-06 06:08:28 +0000 | |||
411 | @@ -258,3 +258,7 @@ | |||
412 | 258 | def kind(self, p): | 258 | def kind(self, p): |
413 | 259 | stat_value = self._file_transport.stat(p) | 259 | stat_value = self._file_transport.stat(p) |
414 | 260 | return osutils.file_kind_from_stat_mode(stat_value.st_mode) | 260 | return osutils.file_kind_from_stat_mode(stat_value.st_mode) |
415 | 261 | |||
416 | 262 | def get_symlink_target(self, path): | ||
417 | 263 | with self.lock_read(): | ||
418 | 264 | return self._file_transport.readlink(path) | ||
419 | 261 | 265 | ||
420 | === modified file 'breezy/git/object_store.py' | |||
421 | --- breezy/git/object_store.py 2019-01-01 21:23:40 +0000 | |||
422 | +++ breezy/git/object_store.py 2019-03-06 06:08:28 +0000 | |||
423 | @@ -359,7 +359,7 @@ | |||
424 | 359 | continue | 359 | continue |
425 | 360 | 360 | ||
426 | 361 | if tree.kind(path) != 'directory': | 361 | if tree.kind(path) != 'directory': |
428 | 362 | raise AssertionError | 362 | continue |
429 | 363 | 363 | ||
430 | 364 | obj = Tree() | 364 | obj = Tree() |
431 | 365 | for value in tree.iter_child_entries(path): | 365 | for value in tree.iter_child_entries(path): |
432 | @@ -589,7 +589,7 @@ | |||
433 | 589 | for (file_id, revision, expected_sha), chunks in stream: | 589 | for (file_id, revision, expected_sha), chunks in stream: |
434 | 590 | blob = Blob() | 590 | blob = Blob() |
435 | 591 | blob.chunked = chunks | 591 | blob.chunked = chunks |
437 | 592 | if blob.id != expected_sha and blob.data == "": | 592 | if blob.id != expected_sha and blob.data == b"": |
438 | 593 | # Perhaps it's a symlink ? | 593 | # Perhaps it's a symlink ? |
439 | 594 | tree = self.tree_cache.revision_tree(revision) | 594 | tree = self.tree_cache.revision_tree(revision) |
440 | 595 | path = tree.id2path(file_id) | 595 | path = tree.id2path(file_id) |
441 | 596 | 596 | ||
442 | === modified file 'breezy/git/tests/test_blackbox.py' | |||
443 | --- breezy/git/tests/test_blackbox.py 2019-02-14 04:20:37 +0000 | |||
444 | +++ breezy/git/tests/test_blackbox.py 2019-03-06 06:08:28 +0000 | |||
445 | @@ -78,6 +78,15 @@ | |||
446 | 78 | self.assertEqual(output, '') | 78 | self.assertEqual(output, '') |
447 | 79 | self.assertFileEqual("foo\n", ".gitignore") | 79 | self.assertFileEqual("foo\n", ".gitignore") |
448 | 80 | 80 | ||
449 | 81 | def test_cat_revision(self): | ||
450 | 82 | self.simple_commit() | ||
451 | 83 | output, error = self.run_bzr(['cat-revision', '-r-1'], retcode=3) | ||
452 | 84 | self.assertContainsRe( | ||
453 | 85 | error, | ||
454 | 86 | 'brz: ERROR: Repository .* does not support access to raw ' | ||
455 | 87 | 'revision texts') | ||
456 | 88 | self.assertEqual(output, '') | ||
457 | 89 | |||
458 | 81 | def test_branch(self): | 90 | def test_branch(self): |
459 | 82 | os.mkdir("gitbranch") | 91 | os.mkdir("gitbranch") |
460 | 83 | GitRepo.init(os.path.join(self.test_dir, "gitbranch")) | 92 | GitRepo.init(os.path.join(self.test_dir, "gitbranch")) |
461 | 84 | 93 | ||
462 | === modified file 'breezy/git/tests/test_branch.py' | |||
463 | --- breezy/git/tests/test_branch.py 2019-01-19 17:13:53 +0000 | |||
464 | +++ breezy/git/tests/test_branch.py 2019-03-06 06:08:28 +0000 | |||
465 | @@ -112,6 +112,7 @@ | |||
466 | 112 | reva = self.simple_commit_a() | 112 | reva = self.simple_commit_a() |
467 | 113 | self.build_tree(['b']) | 113 | self.build_tree(['b']) |
468 | 114 | r = GitRepo(".") | 114 | r = GitRepo(".") |
469 | 115 | self.addCleanup(r.close) | ||
470 | 115 | r.stage("b") | 116 | r.stage("b") |
471 | 116 | revb = r.do_commit(b"b", committer=b"Somebody <foo@example.com>") | 117 | revb = r.do_commit(b"b", committer=b"Somebody <foo@example.com>") |
472 | 117 | 118 | ||
473 | @@ -129,6 +130,7 @@ | |||
474 | 129 | o.tag_timezone = 0 | 130 | o.tag_timezone = 0 |
475 | 130 | o.tag_time = 42 | 131 | o.tag_time = 42 |
476 | 131 | r = GitRepo(".") | 132 | r = GitRepo(".") |
477 | 133 | self.addCleanup(r.close) | ||
478 | 132 | r.object_store.add_object(o) | 134 | r.object_store.add_object(o) |
479 | 133 | r[b'refs/tags/foo'] = o.id | 135 | r[b'refs/tags/foo'] = o.id |
480 | 134 | thebranch = Branch.open('.') | 136 | thebranch = Branch.open('.') |
481 | @@ -138,6 +140,7 @@ | |||
482 | 138 | def test_tag(self): | 140 | def test_tag(self): |
483 | 139 | reva = self.simple_commit_a() | 141 | reva = self.simple_commit_a() |
484 | 140 | r = GitRepo(".") | 142 | r = GitRepo(".") |
485 | 143 | self.addCleanup(r.close) | ||
486 | 141 | r.refs[b"refs/tags/foo"] = reva | 144 | r.refs[b"refs/tags/foo"] = reva |
487 | 142 | thebranch = Branch.open('.') | 145 | thebranch = Branch.open('.') |
488 | 143 | self.assertEqual({"foo": default_mapping.revision_id_foreign_to_bzr(reva)}, | 146 | self.assertEqual({"foo": default_mapping.revision_id_foreign_to_bzr(reva)}, |
489 | @@ -221,6 +224,7 @@ | |||
490 | 221 | def test_sprouted_tags(self): | 224 | def test_sprouted_tags(self): |
491 | 222 | path, gitsha = self.make_onerev_branch() | 225 | path, gitsha = self.make_onerev_branch() |
492 | 223 | r = GitRepo(path) | 226 | r = GitRepo(path) |
493 | 227 | self.addCleanup(r.close) | ||
494 | 224 | r.refs[b"refs/tags/lala"] = r.head() | 228 | r.refs[b"refs/tags/lala"] = r.head() |
495 | 225 | oldrepo = Repository.open(path) | 229 | oldrepo = Repository.open(path) |
496 | 226 | revid = oldrepo.get_mapping().revision_id_foreign_to_bzr(gitsha) | 230 | revid = oldrepo.get_mapping().revision_id_foreign_to_bzr(gitsha) |
497 | @@ -231,6 +235,7 @@ | |||
498 | 231 | def test_sprouted_ghost_tags(self): | 235 | def test_sprouted_ghost_tags(self): |
499 | 232 | path, gitsha = self.make_onerev_branch() | 236 | path, gitsha = self.make_onerev_branch() |
500 | 233 | r = GitRepo(path) | 237 | r = GitRepo(path) |
501 | 238 | self.addCleanup(r.close) | ||
502 | 234 | r.refs[b"refs/tags/lala"] = b"aa" * 20 | 239 | r.refs[b"refs/tags/lala"] = b"aa" * 20 |
503 | 235 | oldrepo = Repository.open(path) | 240 | oldrepo = Repository.open(path) |
504 | 236 | revid = oldrepo.get_mapping().revision_id_foreign_to_bzr(gitsha) | 241 | revid = oldrepo.get_mapping().revision_id_foreign_to_bzr(gitsha) |
505 | @@ -238,7 +243,7 @@ | |||
506 | 238 | self.clone_git_branch, path, "f") | 243 | self.clone_git_branch, path, "f") |
507 | 239 | self.assertEqual({}, newbranch.tags.get_tag_dict()) | 244 | self.assertEqual({}, newbranch.tags.get_tag_dict()) |
508 | 240 | # Dulwich raises a UserWarning for tags with invalid target | 245 | # Dulwich raises a UserWarning for tags with invalid target |
510 | 241 | self.assertEqual(1, len(warnings)) | 246 | self.assertIn(('ref refs/tags/lala points at non-present sha ' + ("aa" * 20), ), [w.args for w in warnings]) |
511 | 242 | 247 | ||
512 | 243 | def test_interbranch_pull(self): | 248 | def test_interbranch_pull(self): |
513 | 244 | path, (gitsha1, gitsha2) = self.make_tworev_branch() | 249 | path, (gitsha1, gitsha2) = self.make_tworev_branch() |
514 | @@ -272,6 +277,7 @@ | |||
515 | 272 | def test_interbranch_pull_with_tags(self): | 277 | def test_interbranch_pull_with_tags(self): |
516 | 273 | path, (gitsha1, gitsha2) = self.make_tworev_branch() | 278 | path, (gitsha1, gitsha2) = self.make_tworev_branch() |
517 | 274 | gitrepo = GitRepo(path) | 279 | gitrepo = GitRepo(path) |
518 | 280 | self.addCleanup(gitrepo.close) | ||
519 | 275 | gitrepo.refs[b"refs/tags/sometag"] = gitsha2 | 281 | gitrepo.refs[b"refs/tags/sometag"] = gitsha2 |
520 | 276 | oldrepo = Repository.open(path) | 282 | oldrepo = Repository.open(path) |
521 | 277 | revid1 = oldrepo.get_mapping().revision_id_foreign_to_bzr(gitsha1) | 283 | revid1 = oldrepo.get_mapping().revision_id_foreign_to_bzr(gitsha1) |
522 | 278 | 284 | ||
523 | === modified file 'breezy/git/tests/test_git_remote_helper.py' | |||
524 | --- breezy/git/tests/test_git_remote_helper.py 2018-11-21 03:39:28 +0000 | |||
525 | +++ breezy/git/tests/test_git_remote_helper.py 2019-03-06 06:08:28 +0000 | |||
526 | @@ -23,12 +23,15 @@ | |||
527 | 23 | 23 | ||
528 | 24 | from io import BytesIO | 24 | from io import BytesIO |
529 | 25 | import os | 25 | import os |
530 | 26 | import subprocess | ||
531 | 27 | import sys | ||
532 | 26 | 28 | ||
533 | 27 | from dulwich.repo import Repo | 29 | from dulwich.repo import Repo |
534 | 28 | 30 | ||
535 | 29 | from ...tests import ( | 31 | from ...tests import ( |
536 | 30 | TestCaseWithTransport, | 32 | TestCaseWithTransport, |
537 | 31 | ) | 33 | ) |
538 | 34 | from ...tests.features import PathFeature | ||
539 | 32 | 35 | ||
540 | 33 | from ..object_store import get_object_store | 36 | from ..object_store import get_object_store |
541 | 34 | from ..git_remote_helper import ( | 37 | from ..git_remote_helper import ( |
542 | @@ -46,6 +49,11 @@ | |||
543 | 46 | return object_store._lookup_revision_sha1(bzr_revid) | 49 | return object_store._lookup_revision_sha1(bzr_revid) |
544 | 47 | 50 | ||
545 | 48 | 51 | ||
546 | 52 | git_remote_bzr_path = os.path.abspath( | ||
547 | 53 | os.path.join(os.path.dirname(__file__), '..', 'git-remote-bzr')) | ||
548 | 54 | git_remote_bzr_feature = PathFeature(git_remote_bzr_path) | ||
549 | 55 | |||
550 | 56 | |||
551 | 49 | class OpenLocalDirTests(TestCaseWithTransport): | 57 | class OpenLocalDirTests(TestCaseWithTransport): |
552 | 50 | 58 | ||
553 | 51 | def test_from_env_dir(self): | 59 | def test_from_env_dir(self): |
554 | @@ -86,8 +94,29 @@ | |||
555 | 86 | self.assertEqual(out, b"\n") | 94 | self.assertEqual(out, b"\n") |
556 | 87 | r = Repo('local') | 95 | r = Repo('local') |
557 | 88 | self.assertTrue(git_sha1 in r.object_store) | 96 | self.assertTrue(git_sha1 in r.object_store) |
560 | 89 | self.assertEqual({ | 97 | self.assertEqual({}, r.get_refs()) |
561 | 90 | }, r.get_refs()) | 98 | |
562 | 99 | |||
563 | 100 | class ExecuteRemoteHelperTests(TestCaseWithTransport): | ||
564 | 101 | |||
565 | 102 | def test_run(self): | ||
566 | 103 | self.requireFeature(git_remote_bzr_feature) | ||
567 | 104 | local_dir = self.make_branch_and_tree('local', format='git').controldir | ||
568 | 105 | local_path = local_dir.control_transport.local_abspath('.') | ||
569 | 106 | remote_tree = self.make_branch_and_tree('remote') | ||
570 | 107 | remote_dir = remote_tree.controldir | ||
571 | 108 | shortname = 'bzr' | ||
572 | 109 | env = dict(os.environ) | ||
573 | 110 | env['GIT_DIR'] = local_path | ||
574 | 111 | env['PYTHONPATH'] = ':'.join(sys.path) | ||
575 | 112 | p = subprocess.Popen( | ||
576 | 113 | [sys.executable, git_remote_bzr_path, local_path, remote_dir.user_url], | ||
577 | 114 | stdin=subprocess.PIPE, stdout=subprocess.PIPE, | ||
578 | 115 | stderr=subprocess.PIPE, env=env) | ||
579 | 116 | (out, err) = p.communicate(b'capabilities\n') | ||
580 | 117 | lines = out.splitlines() | ||
581 | 118 | self.assertIn(b'push', lines, "no 'push' in %r, error: %r" % (lines, err)) | ||
582 | 119 | self.assertEqual(b'', err) | ||
583 | 91 | 120 | ||
584 | 92 | 121 | ||
585 | 93 | class RemoteHelperTests(TestCaseWithTransport): | 122 | class RemoteHelperTests(TestCaseWithTransport): |
586 | 94 | 123 | ||
587 | === modified file 'breezy/git/tests/test_object_store.py' | |||
588 | --- breezy/git/tests/test_object_store.py 2018-11-11 04:08:32 +0000 | |||
589 | +++ breezy/git/tests/test_object_store.py 2019-03-06 06:08:28 +0000 | |||
590 | @@ -18,6 +18,9 @@ | |||
591 | 18 | 18 | ||
592 | 19 | from __future__ import absolute_import | 19 | from __future__ import absolute_import |
593 | 20 | 20 | ||
594 | 21 | import os | ||
595 | 22 | import shutil | ||
596 | 23 | |||
597 | 21 | from dulwich.objects import ( | 24 | from dulwich.objects import ( |
598 | 22 | Blob, | 25 | Blob, |
599 | 23 | Tree, | 26 | Tree, |
600 | @@ -41,6 +44,7 @@ | |||
601 | 41 | TestCase, | 44 | TestCase, |
602 | 42 | TestCaseWithTransport, | 45 | TestCaseWithTransport, |
603 | 43 | ) | 46 | ) |
604 | 47 | from ...tests.features import SymlinkFeature | ||
605 | 44 | 48 | ||
606 | 45 | from ..cache import ( | 49 | from ..cache import ( |
607 | 46 | DictGitShaMap, | 50 | DictGitShaMap, |
608 | @@ -144,11 +148,11 @@ | |||
609 | 144 | def setUp(self): | 148 | def setUp(self): |
610 | 145 | super(BazaarObjectStoreTests, self).setUp() | 149 | super(BazaarObjectStoreTests, self).setUp() |
611 | 146 | self.branch = self.make_branch(".") | 150 | self.branch = self.make_branch(".") |
612 | 147 | self.branch.lock_write() | ||
613 | 148 | self.addCleanup(self.branch.unlock) | ||
614 | 149 | self.store = BazaarObjectStore(self.branch.repository) | 151 | self.store = BazaarObjectStore(self.branch.repository) |
615 | 150 | 152 | ||
616 | 151 | def test_get_blob(self): | 153 | def test_get_blob(self): |
617 | 154 | self.branch.lock_write() | ||
618 | 155 | self.addCleanup(self.branch.unlock) | ||
619 | 152 | b = Blob() | 156 | b = Blob() |
620 | 153 | b.data = b'a\nb\nc\nd\ne\n' | 157 | b.data = b'a\nb\nc\nd\ne\n' |
621 | 154 | self.store.lock_read() | 158 | self.store.lock_read() |
622 | @@ -167,7 +171,31 @@ | |||
623 | 167 | self.store.lock_read() | 171 | self.store.lock_read() |
624 | 168 | self.assertEqual(b, self.store[b.id]) | 172 | self.assertEqual(b, self.store[b.id]) |
625 | 169 | 173 | ||
626 | 174 | def test_directory_converted_to_symlink(self): | ||
627 | 175 | self.requireFeature(SymlinkFeature) | ||
628 | 176 | b = Blob() | ||
629 | 177 | b.data = b'trgt' | ||
630 | 178 | self.store.lock_read() | ||
631 | 179 | self.addCleanup(self.store.unlock) | ||
632 | 180 | self.assertRaises(KeyError, self.store.__getitem__, b.id) | ||
633 | 181 | tree = self.branch.controldir.create_workingtree() | ||
634 | 182 | self.build_tree_contents([ | ||
635 | 183 | ('foo/', ), | ||
636 | 184 | ('foo/bar', b'a\nb\nc\nd\ne\n')]) | ||
637 | 185 | tree.add(['foo', 'foo/bar']) | ||
638 | 186 | revid1 = tree.commit('commit 1') | ||
639 | 187 | shutil.rmtree('foo') | ||
640 | 188 | os.symlink('trgt', 'foo') | ||
641 | 189 | revid2 = tree.commit('commit 2') | ||
642 | 190 | # read locks cache | ||
643 | 191 | self.assertRaises(KeyError, self.store.__getitem__, b.id) | ||
644 | 192 | self.store.unlock() | ||
645 | 193 | self.store.lock_read() | ||
646 | 194 | self.assertEqual(b, self.store[b.id]) | ||
647 | 195 | |||
648 | 170 | def test_get_raw(self): | 196 | def test_get_raw(self): |
649 | 197 | self.branch.lock_write() | ||
650 | 198 | self.addCleanup(self.branch.unlock) | ||
651 | 171 | b = Blob() | 199 | b = Blob() |
652 | 172 | b.data = b'a\nb\nc\nd\ne\n' | 200 | b.data = b'a\nb\nc\nd\ne\n' |
653 | 173 | self.store.lock_read() | 201 | self.store.lock_read() |
654 | @@ -187,6 +215,8 @@ | |||
655 | 187 | self.assertEqual(b.as_raw_string(), self.store.get_raw(b.id)[1]) | 215 | self.assertEqual(b.as_raw_string(), self.store.get_raw(b.id)[1]) |
656 | 188 | 216 | ||
657 | 189 | def test_contains(self): | 217 | def test_contains(self): |
658 | 218 | self.branch.lock_write() | ||
659 | 219 | self.addCleanup(self.branch.unlock) | ||
660 | 190 | b = Blob() | 220 | b = Blob() |
661 | 191 | b.data = b'a\nb\nc\nd\ne\n' | 221 | b.data = b'a\nb\nc\nd\ne\n' |
662 | 192 | self.store.lock_read() | 222 | self.store.lock_read() |
663 | 193 | 223 | ||
664 | === modified file 'breezy/globbing.py' | |||
665 | --- breezy/globbing.py 2018-11-18 19:48:57 +0000 | |||
666 | +++ breezy/globbing.py 2019-03-06 06:08:28 +0000 | |||
667 | @@ -248,7 +248,9 @@ | |||
668 | 248 | # the combined pattern we sent to regex. Instead we indicate to | 248 | # the combined pattern we sent to regex. Instead we indicate to |
669 | 249 | # the user that an ignore file needs fixing. | 249 | # the user that an ignore file needs fixing. |
670 | 250 | mutter('Invalid pattern found in regex: %s.', e.msg) | 250 | mutter('Invalid pattern found in regex: %s.', e.msg) |
672 | 251 | e.msg = "File ~/.bazaar/ignore or .bzrignore contains error(s)." | 251 | e.msg = ( |
673 | 252 | "File ~/.config/breezy/ignore or " | ||
674 | 253 | ".bzrignore contains error(s).") | ||
675 | 252 | bad_patterns = '' | 254 | bad_patterns = '' |
676 | 253 | for _, patterns in self._regex_patterns: | 255 | for _, patterns in self._regex_patterns: |
677 | 254 | for p in patterns: | 256 | for p in patterns: |
678 | 255 | 257 | ||
679 | === modified file 'breezy/ignores.py' | |||
680 | --- breezy/ignores.py 2018-11-12 01:41:38 +0000 | |||
681 | +++ breezy/ignores.py 2019-03-06 06:08:28 +0000 | |||
682 | @@ -33,7 +33,7 @@ | |||
683 | 33 | ) | 33 | ) |
684 | 34 | """) | 34 | """) |
685 | 35 | 35 | ||
687 | 36 | # ~/.bazaar/ignore will be filled out using | 36 | # ~/.config/breezy/ignore will be filled out using |
688 | 37 | # this ignore list, if it does not exist | 37 | # this ignore list, if it does not exist |
689 | 38 | # please keep these sorted (in C locale order) to aid merging | 38 | # please keep these sorted (in C locale order) to aid merging |
690 | 39 | USER_DEFAULTS = [ | 39 | USER_DEFAULTS = [ |
691 | 40 | 40 | ||
692 | === modified file 'breezy/memorytree.py' | |||
693 | --- breezy/memorytree.py 2018-11-18 00:25:19 +0000 | |||
694 | +++ breezy/memorytree.py 2019-03-06 06:08:28 +0000 | |||
695 | @@ -22,6 +22,7 @@ | |||
696 | 22 | from __future__ import absolute_import | 22 | from __future__ import absolute_import |
697 | 23 | 23 | ||
698 | 24 | import os | 24 | import os |
699 | 25 | import stat | ||
700 | 25 | 26 | ||
701 | 26 | from . import ( | 27 | from . import ( |
702 | 27 | errors, | 28 | errors, |
703 | @@ -62,7 +63,15 @@ | |||
704 | 62 | with self.lock_tree_write(): | 63 | with self.lock_tree_write(): |
705 | 63 | for f, file_id, kind in zip(files, ids, kinds): | 64 | for f, file_id, kind in zip(files, ids, kinds): |
706 | 64 | if kind is None: | 65 | if kind is None: |
708 | 65 | kind = 'file' | 66 | st_mode = self._file_transport.stat(f).st_mode |
709 | 67 | if stat.S_ISREG(st_mode): | ||
710 | 68 | kind = 'file' | ||
711 | 69 | elif stat.S_ISLNK(st_mode): | ||
712 | 70 | kind = 'symlink' | ||
713 | 71 | elif stat.S_ISDIR(st_mode): | ||
714 | 72 | kind = 'directory' | ||
715 | 73 | else: | ||
716 | 74 | raise AssertionError('Unknown file kind') | ||
717 | 66 | if file_id is None: | 75 | if file_id is None: |
718 | 67 | self._inventory.add_path(f, kind=kind) | 76 | self._inventory.add_path(f, kind=kind) |
719 | 68 | else: | 77 | else: |
720 | @@ -127,7 +136,7 @@ | |||
721 | 127 | # memory tree does not support nested trees yet. | 136 | # memory tree does not support nested trees yet. |
722 | 128 | return kind, None, None, None | 137 | return kind, None, None, None |
723 | 129 | elif kind == 'symlink': | 138 | elif kind == 'symlink': |
725 | 130 | raise NotImplementedError('symlink support') | 139 | return kind, None, None, self._inventory[id].symlink_target |
726 | 131 | else: | 140 | else: |
727 | 132 | raise NotImplementedError('unknown kind') | 141 | raise NotImplementedError('unknown kind') |
728 | 133 | 142 | ||
729 | @@ -148,8 +157,7 @@ | |||
730 | 148 | return self._inventory.get_entry_by_path(path).executable | 157 | return self._inventory.get_entry_by_path(path).executable |
731 | 149 | 158 | ||
732 | 150 | def kind(self, path): | 159 | def kind(self, path): |
735 | 151 | file_id = self.path2id(path) | 160 | return self._inventory.get_entry_by_path(path).kind |
734 | 152 | return self._inventory[file_id].kind | ||
736 | 153 | 161 | ||
737 | 154 | def mkdir(self, path, file_id=None): | 162 | def mkdir(self, path, file_id=None): |
738 | 155 | """See MutableTree.mkdir().""" | 163 | """See MutableTree.mkdir().""" |
739 | @@ -227,6 +235,8 @@ | |||
740 | 227 | continue | 235 | continue |
741 | 228 | if entry.kind == 'directory': | 236 | if entry.kind == 'directory': |
742 | 229 | self._file_transport.mkdir(path) | 237 | self._file_transport.mkdir(path) |
743 | 238 | elif entry.kind == 'symlink': | ||
744 | 239 | self._file_transport.symlink(entry.symlink_target, path) | ||
745 | 230 | elif entry.kind == 'file': | 240 | elif entry.kind == 'file': |
746 | 231 | self._file_transport.put_file( | 241 | self._file_transport.put_file( |
747 | 232 | path, self._basis_tree.get_file(path)) | 242 | path, self._basis_tree.get_file(path)) |
748 | @@ -302,6 +312,10 @@ | |||
749 | 302 | else: | 312 | else: |
750 | 303 | raise | 313 | raise |
751 | 304 | 314 | ||
752 | 315 | def get_symlink_target(self, path): | ||
753 | 316 | with self.lock_read(): | ||
754 | 317 | return self._file_transport.readlink(path) | ||
755 | 318 | |||
756 | 305 | def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False): | 319 | def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False): |
757 | 306 | """See MutableTree.set_parent_trees().""" | 320 | """See MutableTree.set_parent_trees().""" |
758 | 307 | if len(parents_list) == 0: | 321 | if len(parents_list) == 0: |
759 | 308 | 322 | ||
760 | === modified file 'breezy/plugins/propose/launchpad.py' | |||
761 | --- breezy/plugins/propose/launchpad.py 2019-02-10 18:37:58 +0000 | |||
762 | +++ breezy/plugins/propose/launchpad.py 2019-03-06 06:08:28 +0000 | |||
763 | @@ -140,6 +140,7 @@ | |||
764 | 140 | 140 | ||
765 | 141 | def set_description(self, description): | 141 | def set_description(self, description): |
766 | 142 | self._mp.description = description | 142 | self._mp.description = description |
767 | 143 | self._mp.lp_save() | ||
768 | 143 | 144 | ||
769 | 144 | def close(self): | 145 | def close(self): |
770 | 145 | self._mp.setStatus(status='Rejected') | 146 | self._mp.setStatus(status='Rejected') |
771 | 146 | 147 | ||
772 | === modified file 'breezy/python-compat.h' | |||
773 | --- breezy/python-compat.h 2018-08-21 00:53:34 +0000 | |||
774 | +++ breezy/python-compat.h 2019-03-06 06:08:28 +0000 | |||
775 | @@ -25,6 +25,10 @@ | |||
776 | 25 | #ifndef _BZR_PYTHON_COMPAT_H | 25 | #ifndef _BZR_PYTHON_COMPAT_H |
777 | 26 | #define _BZR_PYTHON_COMPAT_H | 26 | #define _BZR_PYTHON_COMPAT_H |
778 | 27 | 27 | ||
779 | 28 | #ifdef _MSC_VER | ||
780 | 29 | #define inline __inline | ||
781 | 30 | #endif | ||
782 | 31 | |||
783 | 28 | #if PY_MAJOR_VERSION >= 3 | 32 | #if PY_MAJOR_VERSION >= 3 |
784 | 29 | 33 | ||
785 | 30 | #define PyInt_FromSsize_t PyLong_FromSsize_t | 34 | #define PyInt_FromSsize_t PyLong_FromSsize_t |
786 | 31 | 35 | ||
787 | === modified file 'breezy/tests/blackbox/test_bisect.py' | |||
788 | --- breezy/tests/blackbox/test_bisect.py 2018-11-11 04:08:32 +0000 | |||
789 | +++ breezy/tests/blackbox/test_bisect.py 2019-03-06 06:08:28 +0000 | |||
790 | @@ -28,6 +28,7 @@ | |||
791 | 28 | from .. import ( | 28 | from .. import ( |
792 | 29 | KnownFailure, | 29 | KnownFailure, |
793 | 30 | TestCaseWithTransport, | 30 | TestCaseWithTransport, |
794 | 31 | TestSkipped, | ||
795 | 31 | ) | 32 | ) |
796 | 32 | from ...bzr.bzrdir import BzrDir | 33 | from ...bzr.bzrdir import BzrDir |
797 | 33 | 34 | ||
798 | 34 | 35 | ||
799 | === modified file 'breezy/tests/blackbox/test_push.py' | |||
800 | --- breezy/tests/blackbox/test_push.py 2018-11-16 12:08:41 +0000 | |||
801 | +++ breezy/tests/blackbox/test_push.py 2019-03-06 06:08:28 +0000 | |||
802 | @@ -22,6 +22,7 @@ | |||
803 | 22 | from breezy import ( | 22 | from breezy import ( |
804 | 23 | branch, | 23 | branch, |
805 | 24 | controldir, | 24 | controldir, |
806 | 25 | directory_service, | ||
807 | 25 | errors, | 26 | errors, |
808 | 26 | osutils, | 27 | osutils, |
809 | 27 | tests, | 28 | tests, |
810 | @@ -498,6 +499,25 @@ | |||
811 | 498 | self.assertPublished(branch_tree.last_revision(), | 499 | self.assertPublished(branch_tree.last_revision(), |
812 | 499 | trunk_tree.branch.base) | 500 | trunk_tree.branch.base) |
813 | 500 | 501 | ||
814 | 502 | def test_push_new_branch_stacked_on(self): | ||
815 | 503 | """Pushing a new branch with --stacked-on can use directory URLs.""" | ||
816 | 504 | trunk_tree, branch_tree = self.create_trunk_and_feature_branch() | ||
817 | 505 | class FooDirectory(object): | ||
818 | 506 | def look_up(self, name, url, purpose=None): | ||
819 | 507 | if url == 'foo:': | ||
820 | 508 | return trunk_tree.branch.base | ||
821 | 509 | return url | ||
822 | 510 | directory_service.directories.register('foo:', FooDirectory, 'Foo directory') | ||
823 | 511 | self.addCleanup(directory_service.directories.remove, 'foo:') | ||
824 | 512 | # we publish branch_tree with a reference to the mainline. | ||
825 | 513 | out, err = self.run_bzr(['push', '--stacked-on', 'foo:', | ||
826 | 514 | self.get_url('published')], working_dir='branch') | ||
827 | 515 | self.assertEqual('', out) | ||
828 | 516 | self.assertEqual('Created new stacked branch referring to %s.\n' % | ||
829 | 517 | trunk_tree.branch.base, err) | ||
830 | 518 | self.assertPublished(branch_tree.last_revision(), | ||
831 | 519 | trunk_tree.branch.base) | ||
832 | 520 | |||
833 | 501 | def test_push_new_branch_stacked_uses_parent_when_no_public_url(self): | 521 | def test_push_new_branch_stacked_uses_parent_when_no_public_url(self): |
834 | 502 | """When the parent has no public url the parent is used as-is.""" | 522 | """When the parent has no public url the parent is used as-is.""" |
835 | 503 | trunk_tree, branch_tree = self.create_trunk_and_feature_branch() | 523 | trunk_tree, branch_tree = self.create_trunk_and_feature_branch() |
836 | 504 | 524 | ||
837 | === modified file 'breezy/tests/blackbox/test_remove.py' | |||
838 | --- breezy/tests/blackbox/test_remove.py 2018-11-17 18:49:41 +0000 | |||
839 | +++ breezy/tests/blackbox/test_remove.py 2019-03-06 06:08:28 +0000 | |||
840 | @@ -23,6 +23,7 @@ | |||
841 | 23 | features, | 23 | features, |
842 | 24 | TestCaseWithTransport, | 24 | TestCaseWithTransport, |
843 | 25 | TestSkipped, | 25 | TestSkipped, |
844 | 26 | TestNotApplicable, | ||
845 | 26 | ) | 27 | ) |
846 | 27 | from breezy.workingtree import WorkingTree | 28 | from breezy.workingtree import WorkingTree |
847 | 28 | from breezy import osutils | 29 | from breezy import osutils |
848 | @@ -278,7 +279,7 @@ | |||
849 | 278 | def test_remove_backslash(self): | 279 | def test_remove_backslash(self): |
850 | 279 | # pad.lv/176263 | 280 | # pad.lv/176263 |
851 | 280 | if os.path.sep == '\\': | 281 | if os.path.sep == '\\': |
853 | 281 | raise tests.TestNotApplicable( | 282 | raise TestNotApplicable( |
854 | 282 | 'unable to add filenames with backslashes where ' | 283 | 'unable to add filenames with backslashes where ' |
855 | 283 | ' it is the path separator') | 284 | ' it is the path separator') |
856 | 284 | tree = self.make_branch_and_tree('.') | 285 | tree = self.make_branch_and_tree('.') |
857 | 285 | 286 | ||
858 | === modified file 'breezy/tests/blackbox/test_uncommit.py' | |||
859 | --- breezy/tests/blackbox/test_uncommit.py 2018-11-18 19:48:57 +0000 | |||
860 | +++ breezy/tests/blackbox/test_uncommit.py 2019-03-06 06:08:28 +0000 | |||
861 | @@ -246,6 +246,20 @@ | |||
862 | 246 | brz pull . -r revid:a2 | 246 | brz pull . -r revid:a2 |
863 | 247 | """) | 247 | """) |
864 | 248 | 248 | ||
865 | 249 | def test_uncommit_shows_pull_with_location(self): | ||
866 | 250 | wt = self.create_simple_tree() | ||
867 | 251 | |||
868 | 252 | script = ScriptRunner() | ||
869 | 253 | script.run_script(self, """ | ||
870 | 254 | $ brz uncommit --force tree | ||
871 | 255 | 2 ... | ||
872 | 256 | second commit | ||
873 | 257 | ... | ||
874 | 258 | The above revision(s) will be removed. | ||
875 | 259 | You can restore the old tip by running: | ||
876 | 260 | brz pull -d tree tree -r revid:a2 | ||
877 | 261 | """) | ||
878 | 262 | |||
879 | 249 | def test_uncommit_octopus_merge(self): | 263 | def test_uncommit_octopus_merge(self): |
880 | 250 | # Check that uncommit keeps the pending merges in the same order | 264 | # Check that uncommit keeps the pending merges in the same order |
881 | 251 | # though it will also filter out ones in the ancestry | 265 | # though it will also filter out ones in the ancestry |
882 | 252 | 266 | ||
883 | === modified file 'breezy/tests/features.py' | |||
884 | --- breezy/tests/features.py 2019-01-19 01:44:20 +0000 | |||
885 | +++ breezy/tests/features.py 2019-03-06 06:08:28 +0000 | |||
886 | @@ -568,3 +568,17 @@ | |||
887 | 568 | 568 | ||
888 | 569 | 569 | ||
889 | 570 | BackslashFilenameFeature = _BackslashFilenameFeature() | 570 | BackslashFilenameFeature = _BackslashFilenameFeature() |
890 | 571 | |||
891 | 572 | |||
892 | 573 | class PathFeature(Feature): | ||
893 | 574 | """Feature testing whether a particular path exists.""" | ||
894 | 575 | |||
895 | 576 | def __init__(self, path): | ||
896 | 577 | super(PathFeature, self).__init__() | ||
897 | 578 | self.path = path | ||
898 | 579 | |||
899 | 580 | def _probe(self): | ||
900 | 581 | return os.path.exists(self.path) | ||
901 | 582 | |||
902 | 583 | def feature_name(self): | ||
903 | 584 | return "%s exists" % self.path | ||
904 | 571 | 585 | ||
905 | === modified file 'breezy/tests/test_memorytree.py' | |||
906 | --- breezy/tests/test_memorytree.py 2018-11-11 04:08:32 +0000 | |||
907 | +++ breezy/tests/test_memorytree.py 2019-03-06 06:08:28 +0000 | |||
908 | @@ -46,21 +46,17 @@ | |||
909 | 46 | rev_id = tree.commit('first post') | 46 | rev_id = tree.commit('first post') |
910 | 47 | tree.unlock() | 47 | tree.unlock() |
911 | 48 | tree = MemoryTree.create_on_branch(branch) | 48 | tree = MemoryTree.create_on_branch(branch) |
917 | 49 | tree.lock_read() | 49 | with tree.lock_read(): |
918 | 50 | self.assertEqual([rev_id], tree.get_parent_ids()) | 50 | self.assertEqual([rev_id], tree.get_parent_ids()) |
919 | 51 | with tree.get_file('foo') as f: | 51 | with tree.get_file('foo') as f: |
920 | 52 | self.assertEqual(b'contents of foo\n', f.read()) | 52 | self.assertEqual(b'contents of foo\n', f.read()) |
916 | 53 | tree.unlock() | ||
921 | 54 | 53 | ||
922 | 55 | def test_get_root_id(self): | 54 | def test_get_root_id(self): |
923 | 56 | branch = self.make_branch('branch') | 55 | branch = self.make_branch('branch') |
924 | 57 | tree = MemoryTree.create_on_branch(branch) | 56 | tree = MemoryTree.create_on_branch(branch) |
927 | 58 | tree.lock_write() | 57 | with tree.lock_write(): |
926 | 59 | try: | ||
928 | 60 | tree.add(['']) | 58 | tree.add(['']) |
929 | 61 | self.assertIsNot(None, tree.get_root_id()) | 59 | self.assertIsNot(None, tree.get_root_id()) |
930 | 62 | finally: | ||
931 | 63 | tree.unlock() | ||
932 | 64 | 60 | ||
933 | 65 | def test_lock_tree_write(self): | 61 | def test_lock_tree_write(self): |
934 | 66 | """Check we can lock_tree_write and unlock MemoryTrees.""" | 62 | """Check we can lock_tree_write and unlock MemoryTrees.""" |
935 | @@ -73,9 +69,8 @@ | |||
936 | 73 | """Check that we error when trying to upgrade a read lock to write.""" | 69 | """Check that we error when trying to upgrade a read lock to write.""" |
937 | 74 | branch = self.make_branch('branch') | 70 | branch = self.make_branch('branch') |
938 | 75 | tree = MemoryTree.create_on_branch(branch) | 71 | tree = MemoryTree.create_on_branch(branch) |
942 | 76 | tree.lock_read() | 72 | with tree.lock_read(): |
943 | 77 | self.assertRaises(errors.ReadOnlyError, tree.lock_tree_write) | 73 | self.assertRaises(errors.ReadOnlyError, tree.lock_tree_write) |
941 | 78 | tree.unlock() | ||
944 | 79 | 74 | ||
945 | 80 | def test_lock_write(self): | 75 | def test_lock_write(self): |
946 | 81 | """Check we can lock_write and unlock MemoryTrees.""" | 76 | """Check we can lock_write and unlock MemoryTrees.""" |
947 | @@ -88,58 +83,63 @@ | |||
948 | 88 | """Check that we error when trying to upgrade a read lock to write.""" | 83 | """Check that we error when trying to upgrade a read lock to write.""" |
949 | 89 | branch = self.make_branch('branch') | 84 | branch = self.make_branch('branch') |
950 | 90 | tree = MemoryTree.create_on_branch(branch) | 85 | tree = MemoryTree.create_on_branch(branch) |
954 | 91 | tree.lock_read() | 86 | with tree.lock_read(): |
955 | 92 | self.assertRaises(errors.ReadOnlyError, tree.lock_write) | 87 | self.assertRaises(errors.ReadOnlyError, tree.lock_write) |
953 | 93 | tree.unlock() | ||
956 | 94 | 88 | ||
957 | 95 | def test_add_with_kind(self): | 89 | def test_add_with_kind(self): |
958 | 96 | branch = self.make_branch('branch') | 90 | branch = self.make_branch('branch') |
959 | 97 | tree = MemoryTree.create_on_branch(branch) | 91 | tree = MemoryTree.create_on_branch(branch) |
968 | 98 | tree.lock_write() | 92 | with tree.lock_write(): |
969 | 99 | tree.add(['', 'afile', 'adir'], None, | 93 | tree.add(['', 'afile', 'adir'], None, |
970 | 100 | ['directory', 'file', 'directory']) | 94 | ['directory', 'file', 'directory']) |
971 | 101 | self.assertEqual('afile', tree.id2path(tree.path2id('afile'))) | 95 | self.assertEqual('afile', tree.id2path(tree.path2id('afile'))) |
972 | 102 | self.assertEqual('adir', tree.id2path(tree.path2id('adir'))) | 96 | self.assertEqual('adir', tree.id2path(tree.path2id('adir'))) |
973 | 103 | self.assertFalse(tree.has_filename('afile')) | 97 | self.assertFalse(tree.has_filename('afile')) |
974 | 104 | self.assertFalse(tree.has_filename('adir')) | 98 | self.assertFalse(tree.has_filename('adir')) |
967 | 105 | tree.unlock() | ||
975 | 106 | 99 | ||
976 | 107 | def test_put_new_file(self): | 100 | def test_put_new_file(self): |
977 | 108 | branch = self.make_branch('branch') | 101 | branch = self.make_branch('branch') |
978 | 109 | tree = MemoryTree.create_on_branch(branch) | 102 | tree = MemoryTree.create_on_branch(branch) |
985 | 110 | tree.lock_write() | 103 | with tree.lock_write(): |
986 | 111 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], | 104 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], |
987 | 112 | kinds=['directory', 'file']) | 105 | kinds=['directory', 'file']) |
988 | 113 | tree.put_file_bytes_non_atomic('foo', b'barshoom') | 106 | tree.put_file_bytes_non_atomic('foo', b'barshoom') |
989 | 114 | self.assertEqual(b'barshoom', tree.get_file('foo').read()) | 107 | with tree.get_file('foo') as f: |
990 | 115 | tree.unlock() | 108 | self.assertEqual(b'barshoom', f.read()) |
991 | 116 | 109 | ||
992 | 117 | def test_put_existing_file(self): | 110 | def test_put_existing_file(self): |
993 | 118 | branch = self.make_branch('branch') | 111 | branch = self.make_branch('branch') |
994 | 119 | tree = MemoryTree.create_on_branch(branch) | 112 | tree = MemoryTree.create_on_branch(branch) |
1002 | 120 | tree.lock_write() | 113 | with tree.lock_write(): |
1003 | 121 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], | 114 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], |
1004 | 122 | kinds=['directory', 'file']) | 115 | kinds=['directory', 'file']) |
1005 | 123 | tree.put_file_bytes_non_atomic('foo', b'first-content') | 116 | tree.put_file_bytes_non_atomic('foo', b'first-content') |
1006 | 124 | tree.put_file_bytes_non_atomic('foo', b'barshoom') | 117 | tree.put_file_bytes_non_atomic('foo', b'barshoom') |
1007 | 125 | self.assertEqual(b'barshoom', tree.get_file('foo').read()) | 118 | self.assertEqual(b'barshoom', tree.get_file('foo').read()) |
1001 | 126 | tree.unlock() | ||
1008 | 127 | 119 | ||
1009 | 128 | def test_add_in_subdir(self): | 120 | def test_add_in_subdir(self): |
1010 | 129 | branch = self.make_branch('branch') | 121 | branch = self.make_branch('branch') |
1011 | 130 | tree = MemoryTree.create_on_branch(branch) | 122 | tree = MemoryTree.create_on_branch(branch) |
1024 | 131 | tree.lock_write() | 123 | with tree.lock_write(): |
1025 | 132 | self.addCleanup(tree.unlock) | 124 | tree.add([''], [b'root-id'], ['directory']) |
1026 | 133 | tree.add([''], [b'root-id'], ['directory']) | 125 | # Unfortunately, the only way to 'mkdir' is to call 'tree.mkdir', but |
1027 | 134 | # Unfortunately, the only way to 'mkdir' is to call 'tree.mkdir', but | 126 | # that *always* adds the directory as well. So if you want to create a |
1028 | 135 | # that *always* adds the directory as well. So if you want to create a | 127 | # file in a subdirectory, you have to split out the 'mkdir()' calls |
1029 | 136 | # file in a subdirectory, you have to split out the 'mkdir()' calls | 128 | # from the add and put_file_bytes_non_atomic calls. :( |
1030 | 137 | # from the add and put_file_bytes_non_atomic calls. :( | 129 | tree.mkdir('adir', b'dir-id') |
1031 | 138 | tree.mkdir('adir', b'dir-id') | 130 | tree.add(['adir/afile'], [b'file-id'], ['file']) |
1032 | 139 | tree.add(['adir/afile'], [b'file-id'], ['file']) | 131 | self.assertEqual('adir/afile', tree.id2path(b'file-id')) |
1033 | 140 | self.assertEqual('adir/afile', tree.id2path(b'file-id')) | 132 | self.assertEqual('adir', tree.id2path(b'dir-id')) |
1034 | 141 | self.assertEqual('adir', tree.id2path(b'dir-id')) | 133 | tree.put_file_bytes_non_atomic('adir/afile', b'barshoom') |
1035 | 142 | tree.put_file_bytes_non_atomic('adir/afile', b'barshoom') | 134 | |
1036 | 135 | def test_add_symlink(self): | ||
1037 | 136 | branch = self.make_branch('branch') | ||
1038 | 137 | tree = MemoryTree.create_on_branch(branch) | ||
1039 | 138 | with tree.lock_write(): | ||
1040 | 139 | tree._file_transport.symlink('bar', 'foo') | ||
1041 | 140 | tree.add(['', 'foo']) | ||
1042 | 141 | self.assertEqual('symlink', tree.kind('foo')) | ||
1043 | 142 | self.assertEqual('bar', tree.get_symlink_target('foo')) | ||
1044 | 143 | 143 | ||
1045 | 144 | def test_commit_trivial(self): | 144 | def test_commit_trivial(self): |
1046 | 145 | """Smoke test for commit on a MemoryTree. | 145 | """Smoke test for commit on a MemoryTree. |
1047 | @@ -149,40 +149,35 @@ | |||
1048 | 149 | """ | 149 | """ |
1049 | 150 | branch = self.make_branch('branch') | 150 | branch = self.make_branch('branch') |
1050 | 151 | tree = MemoryTree.create_on_branch(branch) | 151 | tree = MemoryTree.create_on_branch(branch) |
1059 | 152 | tree.lock_write() | 152 | with tree.lock_write(): |
1060 | 153 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], | 153 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], |
1061 | 154 | kinds=['directory', 'file']) | 154 | kinds=['directory', 'file']) |
1062 | 155 | tree.put_file_bytes_non_atomic('foo', b'barshoom') | 155 | tree.put_file_bytes_non_atomic('foo', b'barshoom') |
1063 | 156 | revision_id = tree.commit('message baby') | 156 | revision_id = tree.commit('message baby') |
1064 | 157 | # the parents list for the tree should have changed. | 157 | # the parents list for the tree should have changed. |
1065 | 158 | self.assertEqual([revision_id], tree.get_parent_ids()) | 158 | self.assertEqual([revision_id], tree.get_parent_ids()) |
1058 | 159 | tree.unlock() | ||
1066 | 160 | # and we should have a revision that is accessible outside the tree lock | 159 | # and we should have a revision that is accessible outside the tree lock |
1067 | 161 | revtree = tree.branch.repository.revision_tree(revision_id) | 160 | revtree = tree.branch.repository.revision_tree(revision_id) |
1071 | 162 | revtree.lock_read() | 161 | with revtree.lock_read(), revtree.get_file('foo') as f: |
1069 | 163 | self.addCleanup(revtree.unlock) | ||
1070 | 164 | with revtree.get_file('foo') as f: | ||
1072 | 165 | self.assertEqual(b'barshoom', f.read()) | 162 | self.assertEqual(b'barshoom', f.read()) |
1073 | 166 | 163 | ||
1074 | 167 | def test_unversion(self): | 164 | def test_unversion(self): |
1075 | 168 | """Some test for unversion of a memory tree.""" | 165 | """Some test for unversion of a memory tree.""" |
1076 | 169 | branch = self.make_branch('branch') | 166 | branch = self.make_branch('branch') |
1077 | 170 | tree = MemoryTree.create_on_branch(branch) | 167 | tree = MemoryTree.create_on_branch(branch) |
1085 | 171 | tree.lock_write() | 168 | with tree.lock_write(): |
1086 | 172 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], | 169 | tree.add(['', 'foo'], ids=[b'root-id', b'foo-id'], |
1087 | 173 | kinds=['directory', 'file']) | 170 | kinds=['directory', 'file']) |
1088 | 174 | tree.unversion(['foo']) | 171 | tree.unversion(['foo']) |
1089 | 175 | self.assertFalse(tree.is_versioned('foo')) | 172 | self.assertFalse(tree.is_versioned('foo')) |
1090 | 176 | self.assertFalse(tree.has_id(b'foo-id')) | 173 | self.assertFalse(tree.has_id(b'foo-id')) |
1084 | 177 | tree.unlock() | ||
1091 | 178 | 174 | ||
1092 | 179 | def test_last_revision(self): | 175 | def test_last_revision(self): |
1093 | 180 | """There should be a last revision method we can call.""" | 176 | """There should be a last revision method we can call.""" |
1094 | 181 | tree = self.make_branch_and_memory_tree('branch') | 177 | tree = self.make_branch_and_memory_tree('branch') |
1099 | 182 | tree.lock_write() | 178 | with tree.lock_write(): |
1100 | 183 | tree.add('') | 179 | tree.add('') |
1101 | 184 | rev_id = tree.commit('first post') | 180 | rev_id = tree.commit('first post') |
1098 | 185 | tree.unlock() | ||
1102 | 186 | self.assertEqual(rev_id, tree.last_revision()) | 181 | self.assertEqual(rev_id, tree.last_revision()) |
1103 | 187 | 182 | ||
1104 | 188 | def test_rename_file(self): | 183 | def test_rename_file(self): |
1105 | 189 | 184 | ||
1106 | === modified file 'breezy/tests/test_script.py' | |||
1107 | --- breezy/tests/test_script.py 2018-11-20 21:24:08 +0000 | |||
1108 | +++ breezy/tests/test_script.py 2019-03-06 06:08:28 +0000 | |||
1109 | @@ -322,12 +322,12 @@ | |||
1110 | 322 | def test_cat_input_to_file(self): | 322 | def test_cat_input_to_file(self): |
1111 | 323 | retcode, out, err = self.run_command(['cat', '>file'], | 323 | retcode, out, err = self.run_command(['cat', '>file'], |
1112 | 324 | 'content\n', None, None) | 324 | 'content\n', None, None) |
1114 | 325 | self.assertFileEqual(b'content\n', 'file') | 325 | self.assertFileEqual('content\n', 'file') |
1115 | 326 | self.assertEqual(None, out) | 326 | self.assertEqual(None, out) |
1116 | 327 | self.assertEqual(None, err) | 327 | self.assertEqual(None, err) |
1117 | 328 | retcode, out, err = self.run_command(['cat', '>>file'], | 328 | retcode, out, err = self.run_command(['cat', '>>file'], |
1118 | 329 | 'more\n', None, None) | 329 | 'more\n', None, None) |
1120 | 330 | self.assertFileEqual(b'content\nmore\n', 'file') | 330 | self.assertFileEqual('content\nmore\n', 'file') |
1121 | 331 | self.assertEqual(None, out) | 331 | self.assertEqual(None, out) |
1122 | 332 | self.assertEqual(None, err) | 332 | self.assertEqual(None, err) |
1123 | 333 | 333 | ||
1124 | 334 | 334 | ||
1125 | === modified file 'breezy/tests/test_urlutils.py' | |||
1126 | --- breezy/tests/test_urlutils.py 2018-11-23 03:06:01 +0000 | |||
1127 | +++ breezy/tests/test_urlutils.py 2019-03-06 06:08:28 +0000 | |||
1128 | @@ -599,6 +599,9 @@ | |||
1129 | 599 | self.assertEqual(("foo/base,key1=val1/other/elements", | 599 | self.assertEqual(("foo/base,key1=val1/other/elements", |
1130 | 600 | {"key2": "val2"}), split_segment_parameters( | 600 | {"key2": "val2"}), split_segment_parameters( |
1131 | 601 | "foo/base,key1=val1/other/elements,key2=val2")) | 601 | "foo/base,key1=val1/other/elements,key2=val2")) |
1132 | 602 | self.assertRaises( | ||
1133 | 603 | urlutils.InvalidURL, split_segment_parameters, | ||
1134 | 604 | "foo/base,key1") | ||
1135 | 602 | # TODO: Check full URLs as well as relative references | 605 | # TODO: Check full URLs as well as relative references |
1136 | 603 | 606 | ||
1137 | 604 | def test_win32_strip_local_trailing_slash(self): | 607 | def test_win32_strip_local_trailing_slash(self): |
1138 | 605 | 608 | ||
1139 | === modified file 'breezy/transport/memory.py' | |||
1140 | --- breezy/transport/memory.py 2018-11-17 16:53:10 +0000 | |||
1141 | +++ breezy/transport/memory.py 2019-03-06 06:08:28 +0000 | |||
1142 | @@ -26,9 +26,10 @@ | |||
1143 | 26 | from io import ( | 26 | from io import ( |
1144 | 27 | BytesIO, | 27 | BytesIO, |
1145 | 28 | ) | 28 | ) |
1146 | 29 | import itertools | ||
1147 | 29 | import os | 30 | import os |
1148 | 30 | import errno | 31 | import errno |
1150 | 31 | from stat import S_IFREG, S_IFDIR, S_IFLNK | 32 | from stat import S_IFREG, S_IFDIR, S_IFLNK, S_ISDIR |
1151 | 32 | 33 | ||
1152 | 33 | from .. import ( | 34 | from .. import ( |
1153 | 34 | transport, | 35 | transport, |
1154 | @@ -50,20 +51,16 @@ | |||
1155 | 50 | 51 | ||
1156 | 51 | class MemoryStat(object): | 52 | class MemoryStat(object): |
1157 | 52 | 53 | ||
1159 | 53 | def __init__(self, size, kind, perms): | 54 | def __init__(self, size, kind, perms=None): |
1160 | 54 | self.st_size = size | 55 | self.st_size = size |
1162 | 55 | if kind == 'file': | 56 | if not S_ISDIR(kind): |
1163 | 56 | if perms is None: | 57 | if perms is None: |
1164 | 57 | perms = 0o644 | 58 | perms = 0o644 |
1167 | 58 | self.st_mode = S_IFREG | perms | 59 | self.st_mode = kind | perms |
1168 | 59 | elif kind == 'directory': | 60 | else: |
1169 | 60 | if perms is None: | 61 | if perms is None: |
1170 | 61 | perms = 0o755 | 62 | perms = 0o755 |
1176 | 62 | self.st_mode = S_IFDIR | perms | 63 | self.st_mode = kind | perms |
1172 | 63 | elif kind == 'symlink': | ||
1173 | 64 | self.st_mode = S_IFLNK | 0o644 | ||
1174 | 65 | else: | ||
1175 | 66 | raise AssertionError('unknown kind %r' % kind) | ||
1177 | 67 | 64 | ||
1178 | 68 | 65 | ||
1179 | 69 | class MemoryTransport(transport.Transport): | 66 | class MemoryTransport(transport.Transport): |
1180 | @@ -111,7 +108,7 @@ | |||
1181 | 111 | 108 | ||
1182 | 112 | def append_file(self, relpath, f, mode=None): | 109 | def append_file(self, relpath, f, mode=None): |
1183 | 113 | """See Transport.append_file().""" | 110 | """See Transport.append_file().""" |
1185 | 114 | _abspath = self._abspath(relpath) | 111 | _abspath = self._resolve_symlinks(relpath) |
1186 | 115 | self._check_parent(_abspath) | 112 | self._check_parent(_abspath) |
1187 | 116 | orig_content, orig_mode = self._files.get(_abspath, (b"", None)) | 113 | orig_content, orig_mode = self._files.get(_abspath, (b"", None)) |
1188 | 117 | if mode is None: | 114 | if mode is None: |
1189 | @@ -128,16 +125,20 @@ | |||
1190 | 128 | def has(self, relpath): | 125 | def has(self, relpath): |
1191 | 129 | """See Transport.has().""" | 126 | """See Transport.has().""" |
1192 | 130 | _abspath = self._abspath(relpath) | 127 | _abspath = self._abspath(relpath) |
1196 | 131 | return ((_abspath in self._files) | 128 | for container in (self._files, self._dirs, self._symlinks): |
1197 | 132 | or (_abspath in self._dirs) | 129 | if _abspath in container.keys(): |
1198 | 133 | or (_abspath in self._symlinks)) | 130 | return True |
1199 | 131 | return False | ||
1200 | 134 | 132 | ||
1201 | 135 | def delete(self, relpath): | 133 | def delete(self, relpath): |
1202 | 136 | """See Transport.delete().""" | 134 | """See Transport.delete().""" |
1203 | 137 | _abspath = self._abspath(relpath) | 135 | _abspath = self._abspath(relpath) |
1205 | 138 | if _abspath not in self._files: | 136 | if _abspath in self._files: |
1206 | 137 | del self._files[_abspath] | ||
1207 | 138 | elif _abspath in self._symlinks: | ||
1208 | 139 | del self._symlinks[_abspath] | ||
1209 | 140 | else: | ||
1210 | 139 | raise NoSuchFile(relpath) | 141 | raise NoSuchFile(relpath) |
1211 | 140 | del self._files[_abspath] | ||
1212 | 141 | 142 | ||
1213 | 142 | def external_url(self): | 143 | def external_url(self): |
1214 | 143 | """See breezy.transport.Transport.external_url.""" | 144 | """See breezy.transport.Transport.external_url.""" |
1215 | @@ -147,7 +148,7 @@ | |||
1216 | 147 | 148 | ||
1217 | 148 | def get(self, relpath): | 149 | def get(self, relpath): |
1218 | 149 | """See Transport.get().""" | 150 | """See Transport.get().""" |
1220 | 150 | _abspath = self._abspath(relpath) | 151 | _abspath = self._resolve_symlinks(relpath) |
1221 | 151 | if _abspath not in self._files: | 152 | if _abspath not in self._files: |
1222 | 152 | if _abspath in self._dirs: | 153 | if _abspath in self._dirs: |
1223 | 153 | return LateReadError(relpath) | 154 | return LateReadError(relpath) |
1224 | @@ -157,15 +158,20 @@ | |||
1225 | 157 | 158 | ||
1226 | 158 | def put_file(self, relpath, f, mode=None): | 159 | def put_file(self, relpath, f, mode=None): |
1227 | 159 | """See Transport.put_file().""" | 160 | """See Transport.put_file().""" |
1229 | 160 | _abspath = self._abspath(relpath) | 161 | _abspath = self._resolve_symlinks(relpath) |
1230 | 161 | self._check_parent(_abspath) | 162 | self._check_parent(_abspath) |
1231 | 162 | raw_bytes = f.read() | 163 | raw_bytes = f.read() |
1232 | 163 | self._files[_abspath] = (raw_bytes, mode) | 164 | self._files[_abspath] = (raw_bytes, mode) |
1233 | 164 | return len(raw_bytes) | 165 | return len(raw_bytes) |
1234 | 165 | 166 | ||
1235 | 167 | def symlink(self, source, target): | ||
1236 | 168 | _abspath = self._resolve_symlinks(target) | ||
1237 | 169 | self._check_parent(_abspath) | ||
1238 | 170 | self._symlinks[_abspath] = self._abspath(source) | ||
1239 | 171 | |||
1240 | 166 | def mkdir(self, relpath, mode=None): | 172 | def mkdir(self, relpath, mode=None): |
1241 | 167 | """See Transport.mkdir().""" | 173 | """See Transport.mkdir().""" |
1243 | 168 | _abspath = self._abspath(relpath) | 174 | _abspath = self._resolve_symlinks(relpath) |
1244 | 169 | self._check_parent(_abspath) | 175 | self._check_parent(_abspath) |
1245 | 170 | if _abspath in self._dirs: | 176 | if _abspath in self._dirs: |
1246 | 171 | raise FileExists(relpath) | 177 | raise FileExists(relpath) |
1247 | @@ -183,13 +189,13 @@ | |||
1248 | 183 | return True | 189 | return True |
1249 | 184 | 190 | ||
1250 | 185 | def iter_files_recursive(self): | 191 | def iter_files_recursive(self): |
1252 | 186 | for file in self._files: | 192 | for file in itertools.chain(self._files, self._symlinks): |
1253 | 187 | if file.startswith(self._cwd): | 193 | if file.startswith(self._cwd): |
1254 | 188 | yield urlutils.escape(file[len(self._cwd):]) | 194 | yield urlutils.escape(file[len(self._cwd):]) |
1255 | 189 | 195 | ||
1256 | 190 | def list_dir(self, relpath): | 196 | def list_dir(self, relpath): |
1257 | 191 | """See Transport.list_dir().""" | 197 | """See Transport.list_dir().""" |
1259 | 192 | _abspath = self._abspath(relpath) | 198 | _abspath = self._resolve_symlinks(relpath) |
1260 | 193 | if _abspath != '/' and _abspath not in self._dirs: | 199 | if _abspath != '/' and _abspath not in self._dirs: |
1261 | 194 | raise NoSuchFile(relpath) | 200 | raise NoSuchFile(relpath) |
1262 | 195 | result = [] | 201 | result = [] |
1263 | @@ -197,7 +203,7 @@ | |||
1264 | 197 | if not _abspath.endswith('/'): | 203 | if not _abspath.endswith('/'): |
1265 | 198 | _abspath += '/' | 204 | _abspath += '/' |
1266 | 199 | 205 | ||
1268 | 200 | for path_group in self._files, self._dirs: | 206 | for path_group in self._files, self._dirs, self._symlinks: |
1269 | 201 | for path in path_group: | 207 | for path in path_group: |
1270 | 202 | if path.startswith(_abspath): | 208 | if path.startswith(_abspath): |
1271 | 203 | trailing = path[len(_abspath):] | 209 | trailing = path[len(_abspath):] |
1272 | @@ -207,8 +213,8 @@ | |||
1273 | 207 | 213 | ||
1274 | 208 | def rename(self, rel_from, rel_to): | 214 | def rename(self, rel_from, rel_to): |
1275 | 209 | """Rename a file or directory; fail if the destination exists""" | 215 | """Rename a file or directory; fail if the destination exists""" |
1278 | 210 | abs_from = self._abspath(rel_from) | 216 | abs_from = self._resolve_symlinks(rel_from) |
1279 | 211 | abs_to = self._abspath(rel_to) | 217 | abs_to = self._resolve_symlinks(rel_to) |
1280 | 212 | 218 | ||
1281 | 213 | def replace(x): | 219 | def replace(x): |
1282 | 214 | if x == abs_from: | 220 | if x == abs_from: |
1283 | @@ -233,21 +239,25 @@ | |||
1284 | 233 | # fail differently depending on dict order. So work on copy, fail on | 239 | # fail differently depending on dict order. So work on copy, fail on |
1285 | 234 | # error on only replace dicts if all goes well. | 240 | # error on only replace dicts if all goes well. |
1286 | 235 | renamed_files = self._files.copy() | 241 | renamed_files = self._files.copy() |
1287 | 242 | renamed_symlinks = self._symlinks.copy() | ||
1288 | 236 | renamed_dirs = self._dirs.copy() | 243 | renamed_dirs = self._dirs.copy() |
1289 | 237 | do_renames(renamed_files) | 244 | do_renames(renamed_files) |
1290 | 245 | do_renames(renamed_symlinks) | ||
1291 | 238 | do_renames(renamed_dirs) | 246 | do_renames(renamed_dirs) |
1292 | 239 | # We may have been cloned so modify in place | 247 | # We may have been cloned so modify in place |
1293 | 240 | self._files.clear() | 248 | self._files.clear() |
1294 | 241 | self._files.update(renamed_files) | 249 | self._files.update(renamed_files) |
1295 | 250 | self._symlinks.clear() | ||
1296 | 251 | self._symlinks.update(renamed_symlinks) | ||
1297 | 242 | self._dirs.clear() | 252 | self._dirs.clear() |
1298 | 243 | self._dirs.update(renamed_dirs) | 253 | self._dirs.update(renamed_dirs) |
1299 | 244 | 254 | ||
1300 | 245 | def rmdir(self, relpath): | 255 | def rmdir(self, relpath): |
1301 | 246 | """See Transport.rmdir.""" | 256 | """See Transport.rmdir.""" |
1303 | 247 | _abspath = self._abspath(relpath) | 257 | _abspath = self._resolve_symlinks(relpath) |
1304 | 248 | if _abspath in self._files: | 258 | if _abspath in self._files: |
1305 | 249 | self._translate_error(IOError(errno.ENOTDIR, relpath), relpath) | 259 | self._translate_error(IOError(errno.ENOTDIR, relpath), relpath) |
1307 | 250 | for path in self._files: | 260 | for path in itertools.chain(self._files, self._symlinks): |
1308 | 251 | if path.startswith(_abspath + '/'): | 261 | if path.startswith(_abspath + '/'): |
1309 | 252 | self._translate_error(IOError(errno.ENOTEMPTY, relpath), | 262 | self._translate_error(IOError(errno.ENOTEMPTY, relpath), |
1310 | 253 | relpath) | 263 | relpath) |
1311 | @@ -262,13 +272,13 @@ | |||
1312 | 262 | def stat(self, relpath): | 272 | def stat(self, relpath): |
1313 | 263 | """See Transport.stat().""" | 273 | """See Transport.stat().""" |
1314 | 264 | _abspath = self._abspath(relpath) | 274 | _abspath = self._abspath(relpath) |
1317 | 265 | if _abspath in self._files: | 275 | if _abspath in self._files.keys(): |
1318 | 266 | return MemoryStat(len(self._files[_abspath][0]), 'file', | 276 | return MemoryStat(len(self._files[_abspath][0]), S_IFREG, |
1319 | 267 | self._files[_abspath][1]) | 277 | self._files[_abspath][1]) |
1324 | 268 | elif _abspath in self._dirs: | 278 | elif _abspath in self._dirs.keys(): |
1325 | 269 | return MemoryStat(0, 'directory', self._dirs[_abspath]) | 279 | return MemoryStat(0, S_IFDIR, self._dirs[_abspath]) |
1326 | 270 | elif _abspath in self._symlinks: | 280 | elif _abspath in self._symlinks.keys(): |
1327 | 271 | return MemoryStat(0, 'symlink', 0) | 281 | return MemoryStat(0, S_IFLNK) |
1328 | 272 | else: | 282 | else: |
1329 | 273 | raise NoSuchFile(_abspath) | 283 | raise NoSuchFile(_abspath) |
1330 | 274 | 284 | ||
1331 | @@ -280,6 +290,12 @@ | |||
1332 | 280 | """See Transport.lock_write().""" | 290 | """See Transport.lock_write().""" |
1333 | 281 | return _MemoryLock(self._abspath(relpath), self) | 291 | return _MemoryLock(self._abspath(relpath), self) |
1334 | 282 | 292 | ||
1335 | 293 | def _resolve_symlinks(self, relpath): | ||
1336 | 294 | path = self._abspath(relpath) | ||
1337 | 295 | while path in self._symlinks.keys(): | ||
1338 | 296 | path = self._symlinks[path] | ||
1339 | 297 | return path | ||
1340 | 298 | |||
1341 | 283 | def _abspath(self, relpath): | 299 | def _abspath(self, relpath): |
1342 | 284 | """Generate an internal absolute path.""" | 300 | """Generate an internal absolute path.""" |
1343 | 285 | relpath = urlutils.unescape(relpath) | 301 | relpath = urlutils.unescape(relpath) |
1344 | @@ -336,6 +352,7 @@ | |||
1345 | 336 | def start_server(self): | 352 | def start_server(self): |
1346 | 337 | self._dirs = {'/': None} | 353 | self._dirs = {'/': None} |
1347 | 338 | self._files = {} | 354 | self._files = {} |
1348 | 355 | self._symlinks = {} | ||
1349 | 339 | self._locks = {} | 356 | self._locks = {} |
1350 | 340 | self._scheme = "memory+%s:///" % id(self) | 357 | self._scheme = "memory+%s:///" % id(self) |
1351 | 341 | 358 | ||
1352 | @@ -344,6 +361,7 @@ | |||
1353 | 344 | result = memory.MemoryTransport(url) | 361 | result = memory.MemoryTransport(url) |
1354 | 345 | result._dirs = self._dirs | 362 | result._dirs = self._dirs |
1355 | 346 | result._files = self._files | 363 | result._files = self._files |
1356 | 364 | result._symlinks = self._symlinks | ||
1357 | 347 | result._locks = self._locks | 365 | result._locks = self._locks |
1358 | 348 | return result | 366 | return result |
1359 | 349 | self._memory_factory = memory_factory | 367 | self._memory_factory = memory_factory |
1360 | 350 | 368 | ||
1361 | === modified file 'breezy/urlutils.py' | |||
1362 | --- breezy/urlutils.py 2018-11-16 23:19:12 +0000 | |||
1363 | +++ breezy/urlutils.py 2019-03-06 06:08:28 +0000 | |||
1364 | @@ -561,7 +561,10 @@ | |||
1365 | 561 | (base_url, subsegments) = split_segment_parameters_raw(url) | 561 | (base_url, subsegments) = split_segment_parameters_raw(url) |
1366 | 562 | parameters = {} | 562 | parameters = {} |
1367 | 563 | for subsegment in subsegments: | 563 | for subsegment in subsegments: |
1369 | 564 | (key, value) = subsegment.split("=", 1) | 564 | try: |
1370 | 565 | (key, value) = subsegment.split("=", 1) | ||
1371 | 566 | except ValueError: | ||
1372 | 567 | raise InvalidURL(url, "missing = in subsegment") | ||
1373 | 565 | if not isinstance(key, str): | 568 | if not isinstance(key, str): |
1374 | 566 | raise TypeError(key) | 569 | raise TypeError(key) |
1375 | 567 | if not isinstance(value, str): | 570 | if not isinstance(value, str): |
1376 | 568 | 571 | ||
1377 | === added file 'build.cmd' | |||
1378 | --- build.cmd 1970-01-01 00:00:00 +0000 | |||
1379 | +++ build.cmd 2019-03-06 06:08:28 +0000 | |||
1380 | @@ -0,0 +1,21 @@ | |||
1381 | 1 | @echo off | ||
1382 | 2 | :: To build extensions for 64 bit Python 3, we need to configure environment | ||
1383 | 3 | :: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: | ||
1384 | 4 | :: MS Windows SDK for Windows 7 and .NET Framework 4 | ||
1385 | 5 | :: | ||
1386 | 6 | :: More details at: | ||
1387 | 7 | :: https://github.com/cython/cython/wiki/CythonExtensionsOnWindows | ||
1388 | 8 | |||
1389 | 9 | IF "%DISTUTILS_USE_SDK%"=="1" ( | ||
1390 | 10 | ECHO Configuring environment to build with MSVC on a 64bit architecture | ||
1391 | 11 | ECHO Using Windows SDK 7.1 | ||
1392 | 12 | "C:\Program Files\Microsoft SDKs\Windows\v7.1\Setup\WindowsSdkVer.exe" -q -version:v7.1 | ||
1393 | 13 | CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 /release | ||
1394 | 14 | SET MSSdk=1 | ||
1395 | 15 | REM Need the following to allow tox to see the SDK compiler | ||
1396 | 16 | SET TOX_TESTENV_PASSENV=DISTUTILS_USE_SDK MSSdk INCLUDE LIB | ||
1397 | 17 | ) ELSE ( | ||
1398 | 18 | ECHO Using default MSVC build environment | ||
1399 | 19 | ) | ||
1400 | 20 | |||
1401 | 21 | CALL %* | ||
1402 | 0 | 22 | ||
1403 | === modified file 'byov.conf' | |||
1404 | --- byov.conf 2018-12-19 01:30:58 +0000 | |||
1405 | +++ byov.conf 2019-03-06 06:08:28 +0000 | |||
1406 | @@ -13,6 +13,8 @@ | |||
1407 | 13 | sphinx_epytext.install3 = (pip3 install sphinx_epytext) | 13 | sphinx_epytext.install3 = (pip3 install sphinx_epytext) |
1408 | 14 | flake8.install = (pip install flake8) | 14 | flake8.install = (pip install flake8) |
1409 | 15 | flake8.install3 = (pip3 install flake8) | 15 | flake8.install3 = (pip3 install flake8) |
1410 | 16 | cython.install = (pip install cython) | ||
1411 | 17 | cython.install3 = (pip3 install cython) | ||
1412 | 16 | 18 | ||
1413 | 17 | [brz] | 19 | [brz] |
1414 | 18 | # FIXME: we're stuck on xenial | 20 | # FIXME: we're stuck on xenial |
1415 | @@ -25,12 +27,12 @@ | |||
1416 | 25 | 27 | ||
1417 | 26 | # FIXME: Arguably this should be vm.build_deps=brz but it requires either an | 28 | # FIXME: Arguably this should be vm.build_deps=brz but it requires either an |
1418 | 27 | # available package or at least a debian/ dir ? -- vila 2018-02-23 | 29 | # available package or at least a debian/ dir ? -- vila 2018-02-23 |
1420 | 28 | brz.build_deps = gcc, debhelper, python, python-all-dev, python3-all-dev, python-configobj, python3-configobj, python-docutils, python3-docutils, python-paramiko, python3-paramiko, python-subunit, python3-subunit, python-testtools, python3-testtools, subunit, cython, cython3, python-pip, python3-pip, python-setuptools, python3-setuptools, python-flake8, python3-flake8, python-sphinx, python3-sphinx, python-launchpadlib, python3-launchpadlib | 30 | brz.build_deps = gcc, debhelper, python, python-all-dev, python3-all-dev, python-configobj, python3-configobj, python-docutils, python3-docutils, python-paramiko, python3-paramiko, python-subunit, python3-subunit, python-testtools, python3-testtools, subunit, python-pip, python3-pip, python-setuptools, python3-setuptools, python-flake8, python3-flake8, python-sphinx, python3-sphinx, python-launchpadlib, python3-launchpadlib |
1421 | 29 | subunit.build_deps = python-testscenarios, python3-testscenarios, python-testtools, python3-testtools | 31 | subunit.build_deps = python-testscenarios, python3-testscenarios, python-testtools, python3-testtools |
1422 | 30 | vm.packages = {brz.build_deps}, {subunit.build_deps}, bzr, git, python-junitxml | 32 | vm.packages = {brz.build_deps}, {subunit.build_deps}, bzr, git, python-junitxml |
1423 | 31 | [brz-xenial] | 33 | [brz-xenial] |
1424 | 32 | vm.release = xenial | 34 | vm.release = xenial |
1426 | 33 | byoci.setup.command = ({dulwich.clone} && {dulwich.install} && {dulwich.install3} && {fastimport.clone} && {fastimport.install} && {fastimport.install3} && {subunit.clone} && {flake8.install} && {flake8.install3} && {sphinx_epytext.install} && {sphinx_epytext.install3}) | 35 | byoci.setup.command = ({dulwich.clone} && {dulwich.install} && {dulwich.install3} && {fastimport.clone} && {fastimport.install} && {fastimport.install3} && {subunit.clone} && {flake8.install} && {flake8.install3} && {sphinx_epytext.install} && {sphinx_epytext.install3} && {cython.install} && {cython.install3}) |
1427 | 34 | # FIXME: bzr log -l2 should be by default -- vila 2018-03-09 | 36 | # FIXME: bzr log -l2 should be by default -- vila 2018-03-09 |
1428 | 35 | byoci.tests.command = bash -o pipefail -c "bzr log -l2 && PYTHONPATH=../subunit/python:$PYTHONPATH PATH=../subunit/filters:$PATH make check-ci | subunit2junitxml -o ../results.xml -f | subunit2pyunit" | 37 | byoci.tests.command = bash -o pipefail -c "bzr log -l2 && PYTHONPATH=../subunit/python:$PYTHONPATH PATH=../subunit/filters:$PATH make check-ci | subunit2junitxml -o ../results.xml -f | subunit2pyunit" |
1429 | 36 | [brz-bionic] | 38 | [brz-bionic] |
1430 | 37 | 39 | ||
1431 | === modified file 'doc/developers/apport.txt' | |||
1432 | --- doc/developers/apport.txt 2009-12-02 20:34:07 +0000 | |||
1433 | +++ doc/developers/apport.txt 2019-03-06 06:08:28 +0000 | |||
1434 | @@ -41,7 +41,7 @@ | |||
1435 | 41 | 41 | ||
1436 | 42 | #. An exception reaches the top-level handler. | 42 | #. An exception reaches the top-level handler. |
1437 | 43 | 43 | ||
1439 | 44 | #. We log it in apport-format to a file in ~/.bazaar/crash. | 44 | #. We log it in apport-format to a file in ~/.config/breezy/crash. |
1440 | 45 | 45 | ||
1441 | 46 | #. We tell the user where that file is, and invite them to file a bug | 46 | #. We tell the user where that file is, and invite them to file a bug |
1442 | 47 | report. | 47 | report. |
1443 | 48 | 48 | ||
1444 | === modified file 'doc/developers/configuration.txt' | |||
1445 | --- doc/developers/configuration.txt 2017-07-30 16:59:50 +0000 | |||
1446 | +++ doc/developers/configuration.txt 2019-03-06 06:08:28 +0000 | |||
1447 | @@ -154,20 +154,6 @@ | |||
1448 | 154 | though). The ``bzr-bookmarks`` plugin defines a ``BOOKMARKS`` section there | 154 | though). The ``bzr-bookmarks`` plugin defines a ``BOOKMARKS`` section there |
1449 | 155 | for example. | 155 | for example. |
1450 | 156 | 156 | ||
1451 | 157 | pkgimport.conf | ||
1452 | 158 | ============== | ||
1453 | 159 | |||
1454 | 160 | The Ubuntu package importer defines a store and two stacks involving | ||
1455 | 161 | ``pkgimport.conf``. A no-name section contains the options common to all | ||
1456 | 162 | packages and sections named after their corresponding package can also be | ||
1457 | 163 | defined. | ||
1458 | 164 | |||
1459 | 165 | The ``ImporterStack`` uses ``locations.conf`` and the no-name section in | ||
1460 | 166 | ``pkgimport.conf`` for the importer options. | ||
1461 | 167 | |||
1462 | 168 | The ``PackageStack`` uses only ``pkgimport.conf`` and uses the section name | ||
1463 | 169 | after the package followed by the no-name section. | ||
1464 | 170 | |||
1465 | 171 | location.conf | 157 | location.conf |
1466 | 172 | ============= | 158 | ============= |
1467 | 173 | 159 | ||
1468 | 174 | 160 | ||
1469 | === modified file 'doc/developers/contribution-quickstart.txt' | |||
1470 | --- doc/developers/contribution-quickstart.txt 2019-01-01 21:38:07 +0000 | |||
1471 | +++ doc/developers/contribution-quickstart.txt 2019-03-06 06:08:28 +0000 | |||
1472 | @@ -46,7 +46,7 @@ | |||
1473 | 46 | closely-related cluster of bugs per branch, to make reviews and merges | 46 | closely-related cluster of bugs per branch, to make reviews and merges |
1474 | 47 | flow more smoothly. | 47 | flow more smoothly. |
1475 | 48 | 48 | ||
1477 | 49 | You probably want this configuration in ``~/.bazaar/locations.conf``:: | 49 | You probably want this configuration in ``~/.config/breezy/locations.conf``:: |
1478 | 50 | 50 | ||
1479 | 51 | [/home/USER/brz] | 51 | [/home/USER/brz] |
1480 | 52 | push_location = lp:~LAUNCHPAD_USER/brz/{branchname} | 52 | push_location = lp:~LAUNCHPAD_USER/brz/{branchname} |
1481 | 53 | 53 | ||
1482 | === modified file 'doc/developers/plugin-development.txt' | |||
1483 | --- doc/developers/plugin-development.txt 2018-11-22 02:23:26 +0000 | |||
1484 | +++ doc/developers/plugin-development.txt 2019-03-06 06:08:28 +0000 | |||
1485 | @@ -31,7 +31,7 @@ | |||
1486 | 31 | To ensure your plugin under development is available to Breezy, set | 31 | To ensure your plugin under development is available to Breezy, set |
1487 | 32 | the ``BRZ_PLUGIN_PATH`` environment variable to its parent directory. | 32 | the ``BRZ_PLUGIN_PATH`` environment variable to its parent directory. |
1488 | 33 | Alternatively, you may wish to develop your plugin within a directory | 33 | Alternatively, you may wish to develop your plugin within a directory |
1490 | 34 | under your personal plugins area (``~/.bazaar/plugins`` on GNU/Linux) | 34 | under your personal plugins area (``~/.config/breezy/plugins`` on GNU/Linux) |
1491 | 35 | or put a symbolic link in that area pointing to your plugin under | 35 | or put a symbolic link in that area pointing to your plugin under |
1492 | 36 | test. Finally you can use ``BRZ_PLUGINS_AT`` to point to a specific | 36 | test. Finally you can use ``BRZ_PLUGINS_AT`` to point to a specific |
1493 | 37 | directory for a specific plugin (separated by your platform's value of | 37 | directory for a specific plugin (separated by your platform's value of |
1494 | 38 | 38 | ||
1495 | === modified file 'doc/en/admin-guide/hooks-plugins.txt' | |||
1496 | --- doc/en/admin-guide/hooks-plugins.txt 2018-11-18 13:20:01 +0000 | |||
1497 | +++ doc/en/admin-guide/hooks-plugins.txt 2019-03-06 06:08:28 +0000 | |||
1498 | @@ -25,10 +25,10 @@ | |||
1499 | 25 | http://doc.bazaar.canonical.com/plugins/en/. For purposes of installation, | 25 | http://doc.bazaar.canonical.com/plugins/en/. For purposes of installation, |
1500 | 26 | plugins are simply python packages. They can be installed alongside Bazaar in | 26 | plugins are simply python packages. They can be installed alongside Bazaar in |
1501 | 27 | the ``bzrlib.plugins`` package using each plugin's ``setup.py``. They can | 27 | the ``bzrlib.plugins`` package using each plugin's ``setup.py``. They can |
1506 | 28 | also be installed in the plugin path which is the user's ``~/.bazaar/plugins`` | 28 | also be installed in the plugin path which is the user's |
1507 | 29 | directory or can be specified with the ``BZR_PLUGIN_PATH`` environment | 29 | ``~/.config/breezy/plugins`` directory or can be specified with the |
1508 | 30 | variable. See ``bzr help configuration`` for more on specifying the location | 30 | ``BZR_PLUGIN_PATH`` environment variable. See ``bzr help configuration`` for |
1509 | 31 | of plugins. | 31 | more on specifying the location of plugins. |
1510 | 32 | 32 | ||
1511 | 33 | 33 | ||
1512 | 34 | Email Notification | 34 | Email Notification |
1513 | 35 | 35 | ||
1514 | === modified file 'doc/en/admin-guide/migration.txt' | |||
1515 | --- doc/en/admin-guide/migration.txt 2018-11-18 13:20:01 +0000 | |||
1516 | +++ doc/en/admin-guide/migration.txt 2019-03-06 06:08:28 +0000 | |||
1517 | @@ -56,7 +56,7 @@ | |||
1518 | 56 | This command has flexible ways to specify what paths within the Subversion | 56 | This command has flexible ways to specify what paths within the Subversion |
1519 | 57 | repository contain branches and which contain tags. For example, the | 57 | repository contain branches and which contain tags. For example, the |
1520 | 58 | recommended layout for Subversion projects (called ``trunk`` by the svn | 58 | recommended layout for Subversion projects (called ``trunk`` by the svn |
1522 | 59 | plugin) could be specified in ``~/.bazaar/subversion.conf`` as | 59 | plugin) could be specified in ``~/.config/breezy/subversion.conf`` as |
1523 | 60 | 60 | ||
1524 | 61 | :: | 61 | :: |
1525 | 62 | 62 | ||
1526 | 63 | 63 | ||
1527 | === modified file 'doc/en/release-notes/brz-3.0.txt' | |||
1528 | --- doc/en/release-notes/brz-3.0.txt 2019-03-02 22:31:28 +0000 | |||
1529 | +++ doc/en/release-notes/brz-3.0.txt 2019-03-06 06:08:28 +0000 | |||
1530 | @@ -85,6 +85,9 @@ | |||
1531 | 85 | longer performed, since there are no longer | 85 | longer performed, since there are no longer |
1532 | 86 | any automated imports. (Jelmer Vernooij) | 86 | any automated imports. (Jelmer Vernooij) |
1533 | 87 | 87 | ||
1534 | 88 | * ``setuptools`` is now required to build and install Breezy. | ||
1535 | 89 | (Jelmer Vernooij) | ||
1536 | 90 | |||
1537 | 88 | New Features | 91 | New Features |
1538 | 89 | ************ | 92 | ************ |
1539 | 90 | 93 | ||
1540 | @@ -234,6 +237,13 @@ | |||
1541 | 234 | * Don't report .git files as unknown files. | 237 | * Don't report .git files as unknown files. |
1542 | 235 | (Jelmer Vernooij, Debian Bug #921240) | 238 | (Jelmer Vernooij, Debian Bug #921240) |
1543 | 236 | 239 | ||
1544 | 240 | * Raise better error when path subsegments lack =. | ||
1545 | 241 | (Jelmer Vernooij, #891483) | ||
1546 | 242 | |||
1547 | 243 | * Display correct pull location argument in | ||
1548 | 244 | output of ``brz uncommit``. | ||
1549 | 245 | (Jelmer Vernooij, #386577) | ||
1550 | 246 | |||
1551 | 237 | Documentation | 247 | Documentation |
1552 | 238 | ************* | 248 | ************* |
1553 | 239 | 249 | ||
1554 | 240 | 250 | ||
1555 | === modified file 'doc/en/user-guide/controlling_registration.txt' | |||
1556 | --- doc/en/user-guide/controlling_registration.txt 2017-05-21 13:41:54 +0000 | |||
1557 | +++ doc/en/user-guide/controlling_registration.txt 2019-03-06 06:08:28 +0000 | |||
1558 | @@ -95,12 +95,12 @@ | |||
1559 | 95 | There are some ignored files which are not project specific, but more user | 95 | There are some ignored files which are not project specific, but more user |
1560 | 96 | specific. Things like editor temporary files, or personal temporary files. | 96 | specific. Things like editor temporary files, or personal temporary files. |
1561 | 97 | Rather than add these ignores to every project, brz supports a global | 97 | Rather than add these ignores to every project, brz supports a global |
1563 | 98 | ignore file in ``~/.bazaar/ignore`` [#]_. It has the same syntax as the | 98 | ignore file in ``~/.config/breezy/ignore`` [#]_. It has the same syntax as the |
1564 | 99 | per-project ignore file. | 99 | per-project ignore file. |
1565 | 100 | 100 | ||
1566 | 101 | .. [#] On Windows, the users configuration files can be found in the | 101 | .. [#] On Windows, the users configuration files can be found in the |
1568 | 102 | application data directory. So instead of ``~/.bazaar/branch.conf`` | 102 | application data directory. So instead of ``~/.config/breezy/branch.conf`` |
1569 | 103 | the configuration file can be found as: | 103 | the configuration file can be found as: |
1571 | 104 | ``C:\Documents and Settings\<username>\Application Data\Breezy\2.0\branch.conf``. | 104 | ``C:\Documents and Settings\<username>\Application Data\Breezy\3.0\branch.conf``. |
1572 | 105 | The same is true for ``locations.conf``, ``ignore``, and the | 105 | The same is true for ``locations.conf``, ``ignore``, and the |
1573 | 106 | ``plugins`` directory. | 106 | ``plugins`` directory. |
1574 | 107 | 107 | ||
1575 | === added file 'doc/en/user-guide/git_limitations.txt' | |||
1576 | --- doc/en/user-guide/git_limitations.txt 1970-01-01 00:00:00 +0000 | |||
1577 | +++ doc/en/user-guide/git_limitations.txt 2019-03-06 06:08:28 +0000 | |||
1578 | @@ -0,0 +1,18 @@ | |||
1579 | 1 | Git Limitations | ||
1580 | 2 | =============== | ||
1581 | 3 | |||
1582 | 4 | Breezy's support for Git repositories currently has the following limitations: | ||
1583 | 5 | |||
1584 | 6 | * No support for creating annotated tags. pad.lv/1758185 | ||
1585 | 7 | * No support for gitattributes and the features that depend on it (lfs, eol, etc). pad.lv/1802797 | ||
1586 | 8 | * Limited support for submodules. pad.lv/402814 | ||
1587 | 9 | * No rename/copy inference. pad.lv/1760740 | ||
1588 | 10 | * No support for creating shallow branches (pad.lv/1760151) | ||
1589 | 11 | * No good way to refer to git remotes from the command-line (pad.lv/1702283) | ||
1590 | 12 | * No mailmap support (pad.lv/544031) | ||
1591 | 13 | |||
1592 | 14 | Functionality similar to git that's missing: | ||
1593 | 15 | |||
1594 | 16 | * No rebase command. pad.lv/1708046 | ||
1595 | 17 | * No --amend option for commit. pad.lv/507529 | ||
1596 | 18 | * No clone/fetch commands. pad.lv/831939 | ||
1597 | 0 | 19 | ||
1598 | === modified file 'doc/en/user-guide/index-plain.txt' | |||
1599 | --- doc/en/user-guide/index-plain.txt 2018-11-24 15:56:05 +0000 | |||
1600 | +++ doc/en/user-guide/index-plain.txt 2019-03-06 06:08:28 +0000 | |||
1601 | @@ -114,6 +114,7 @@ | |||
1602 | 114 | .. include:: setting_up_email.txt | 114 | .. include:: setting_up_email.txt |
1603 | 115 | .. include:: http_smart_server.txt | 115 | .. include:: http_smart_server.txt |
1604 | 116 | .. include:: writing_a_plugin.txt | 116 | .. include:: writing_a_plugin.txt |
1605 | 117 | .. include:: git_limitations.txt | ||
1606 | 117 | .. include:: licence.txt | 118 | .. include:: licence.txt |
1607 | 118 | 119 | ||
1608 | 119 | .. |--| unicode:: U+2014 | 120 | .. |--| unicode:: U+2014 |
1609 | 120 | 121 | ||
1610 | === modified file 'doc/en/user-guide/installing_breezy.txt' | |||
1611 | --- doc/en/user-guide/installing_breezy.txt 2018-11-18 13:43:04 +0000 | |||
1612 | +++ doc/en/user-guide/installing_breezy.txt 2019-03-06 06:08:28 +0000 | |||
1613 | @@ -90,7 +90,7 @@ | |||
1614 | 90 | 3. Put the created directory on your PATH. | 90 | 3. Put the created directory on your PATH. |
1615 | 91 | 91 | ||
1616 | 92 | Advanced users may also wish to build the optional C extensions for greater | 92 | Advanced users may also wish to build the optional C extensions for greater |
1618 | 93 | speed. This can be done using ``make`` and requires ``pyrex`` and a C compiler. | 93 | speed. This can be done using ``make`` and requires ``cython`` and a C compiler. |
1619 | 94 | Please contact us on email or IRC if you need assistance with this. | 94 | Please contact us on email or IRC if you need assistance with this. |
1620 | 95 | 95 | ||
1621 | 96 | 96 | ||
1622 | 97 | 97 | ||
1623 | === modified file 'doc/en/user-guide/plugins.txt' | |||
1624 | --- doc/en/user-guide/plugins.txt 2017-05-21 13:41:54 +0000 | |||
1625 | +++ doc/en/user-guide/plugins.txt 2019-03-06 06:08:28 +0000 | |||
1626 | @@ -35,7 +35,7 @@ | |||
1627 | 35 | 35 | ||
1628 | 36 | Installing a plugin is very easy! If not already created, create a | 36 | Installing a plugin is very easy! If not already created, create a |
1629 | 37 | ``plugins`` directory under your Breezy configuration directory, | 37 | ``plugins`` directory under your Breezy configuration directory, |
1631 | 38 | ``~/.bazaar/`` on Unix and | 38 | ``~/.config/breezy/`` on Unix and |
1632 | 39 | ``C:\Documents and Settings\<username>\Application Data\Breezy\2.0\`` | 39 | ``C:\Documents and Settings\<username>\Application Data\Breezy\2.0\`` |
1633 | 40 | on Windows. Within this directory (referred to as $BZR_HOME below), | 40 | on Windows. Within this directory (referred to as $BZR_HOME below), |
1634 | 41 | each plugin is placed in its own subdirectory. | 41 | each plugin is placed in its own subdirectory. |
1635 | @@ -45,7 +45,7 @@ | |||
1636 | 45 | one can perform the following:: | 45 | one can perform the following:: |
1637 | 46 | 46 | ||
1638 | 47 | brz branch http://panoramicfeedback.com/opensource/brz/brztools | 47 | brz branch http://panoramicfeedback.com/opensource/brz/brztools |
1640 | 48 | ~/.bazaar/plugins/brztools | 48 | ~/.config/breezy/plugins/brztools |
1641 | 49 | 49 | ||
1642 | 50 | When installing plugins, the directories that you install them in must | 50 | When installing plugins, the directories that you install them in must |
1643 | 51 | be valid python identifiers. This means that they can only contain | 51 | be valid python identifiers. This means that they can only contain |
1644 | 52 | 52 | ||
1645 | === modified file 'setup.py' | |||
1646 | --- setup.py 2019-02-06 05:44:37 +0000 | |||
1647 | +++ setup.py 2019-03-06 06:08:28 +0000 | |||
1648 | @@ -16,6 +16,14 @@ | |||
1649 | 16 | sys.stderr.write("[ERROR] Not a supported Python version. Need 2.7+\n") | 16 | sys.stderr.write("[ERROR] Not a supported Python version. Need 2.7+\n") |
1650 | 17 | sys.exit(1) | 17 | sys.exit(1) |
1651 | 18 | 18 | ||
1652 | 19 | |||
1653 | 20 | try: | ||
1654 | 21 | import setuptools | ||
1655 | 22 | except ImportError: | ||
1656 | 23 | sys.stderr.write("[ERROR] Please install setuptools\n") | ||
1657 | 24 | sys.exit(1) | ||
1658 | 25 | |||
1659 | 26 | |||
1660 | 19 | # NOTE: The directory containing setup.py, whether run by 'python setup.py' or | 27 | # NOTE: The directory containing setup.py, whether run by 'python setup.py' or |
1661 | 20 | # './setup.py' or the equivalent with another path, should always be at the | 28 | # './setup.py' or the equivalent with another path, should always be at the |
1662 | 21 | # start of the path, so this should find the right one... | 29 | # start of the path, so this should find the right one... |
1663 | @@ -118,8 +126,7 @@ | |||
1664 | 118 | BREEZY['packages'] = get_breezy_packages() | 126 | BREEZY['packages'] = get_breezy_packages() |
1665 | 119 | 127 | ||
1666 | 120 | 128 | ||
1669 | 121 | from distutils import log | 129 | from setuptools import setup |
1668 | 122 | from distutils.core import setup | ||
1670 | 123 | from distutils.version import LooseVersion | 130 | from distutils.version import LooseVersion |
1671 | 124 | from distutils.command.install_scripts import install_scripts | 131 | from distutils.command.install_scripts import install_scripts |
1672 | 125 | from distutils.command.install_data import install_data | 132 | from distutils.command.install_data import install_data |
1673 | @@ -211,8 +218,17 @@ | |||
1674 | 211 | print("") | 218 | print("") |
1675 | 212 | from distutils.command.build_ext import build_ext | 219 | from distutils.command.build_ext import build_ext |
1676 | 213 | else: | 220 | else: |
1678 | 214 | have_cython = True | 221 | minimum_cython_version = '0.29' |
1679 | 215 | cython_version_info = LooseVersion(cython_version) | 222 | cython_version_info = LooseVersion(cython_version) |
1680 | 223 | if cython_version_info < LooseVersion(minimum_cython_version): | ||
1681 | 224 | print("Version of Cython is too old. " | ||
1682 | 225 | "Current is %s, need at least %s." | ||
1683 | 226 | % (cython_version, minimum_cython_version)) | ||
1684 | 227 | print("If the .c files are available, they will be built," | ||
1685 | 228 | " but modifying the .pyx files will not rebuild them.") | ||
1686 | 229 | have_cython = False | ||
1687 | 230 | else: | ||
1688 | 231 | have_cython = True | ||
1689 | 216 | 232 | ||
1690 | 217 | 233 | ||
1691 | 218 | class build_ext_if_possible(build_ext): | 234 | class build_ext_if_possible(build_ext): |