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