Merge lp:~vila/brz/trunk into lp:brz

Proposed by Vincent Ladeuil
Status: Merged
Approved by: Vincent Ladeuil
Approved revision: no longer in the source branch.
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~vila/brz/trunk
Merge into: lp:brz
Diff against target: 637 lines (+270/-56)
20 files modified
breezy/__init__.py (+1/-1)
breezy/_static_tuple_c.c (+73/-0)
breezy/bzr/_dirstate_helpers_pyx.pyx (+13/-2)
breezy/git/annotate.py (+2/-1)
breezy/git/filegraph.py (+2/-2)
breezy/git/remote.py (+5/-7)
breezy/git/tests/test_blackbox.py (+22/-0)
breezy/git/tests/test_remote.py (+10/-0)
breezy/ignores.py (+2/-2)
breezy/plugins/launchpad/lp_api.py (+0/-17)
breezy/plugins/launchpad/lp_directory.py (+1/-1)
breezy/plugins/launchpad/lp_registration.py (+1/-1)
breezy/plugins/launchpad/test_lp_directory.py (+1/-1)
breezy/plugins/launchpad/test_lp_service.py (+2/-2)
breezy/plugins/launchpad/uris.py (+36/-0)
breezy/tests/blackbox/test_testament.py (+10/-11)
breezy/tests/test_ignores.py (+18/-0)
breezy/tests/test_server.py (+5/-1)
doc/en/release-notes/brz-3.0.txt (+65/-6)
doc/en/release-notes/release-template.txt (+1/-1)
To merge this branch: bzr merge lp:~vila/brz/trunk
Reviewer Review Type Date Requested Status
Vincent Ladeuil Approve
Review via email: mp+375724@code.launchpad.net

Commit message

Merge lp:brz/3.0 after 3.0.2 release.

Description of the change

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

RM self-approval.

review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/__init__.py'
2--- breezy/__init__.py 2019-06-18 11:21:15 +0000
3+++ breezy/__init__.py 2019-11-19 20:09:35 +0000
4@@ -53,7 +53,7 @@
5 # Python version 2.0 is (2, 0, 0, 'final', 0)." Additionally we use a
6 # releaselevel of 'dev' for unreleased under-development code.
7
8-version_info = (3, 1, 0, 'dev', 1)
9+version_info = (3, 1, 0, 'dev', 0)
10
11
12 def _format_version_tuple(version_info):
13
14=== modified file 'breezy/_static_tuple_c.c'
15--- breezy/_static_tuple_c.c 2017-06-27 00:56:24 +0000
16+++ breezy/_static_tuple_c.c 2019-11-19 20:09:35 +0000
17@@ -320,6 +320,78 @@
18 return result;
19 }
20
21+/* adapted from tuplehash(), is the specific hash value considered
22+ * 'stable'?
23+ */
24+
25+#if PY_MAJOR_VERSION > 3 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 8)
26+/* Hash for tuples. This is a slightly simplified version of the xxHash
27+ non-cryptographic hash:
28+ - we do not use any parallellism, there is only 1 accumulator.
29+ - we drop the final mixing since this is just a permutation of the
30+ output space: it does not help against collisions.
31+ - at the end, we mangle the length with a single constant.
32+ For the xxHash specification, see
33+ https://github.com/Cyan4973/xxHash/blob/master/doc/xxhash_spec.md
34+
35+ Below are the official constants from the xxHash specification. Optimizing
36+ compilers should emit a single "rotate" instruction for the
37+ _PyHASH_XXROTATE() expansion. If that doesn't happen for some important
38+ platform, the macro could be changed to expand to a platform-specific rotate
39+ spelling instead.
40+*/
41+#if SIZEOF_PY_UHASH_T > 4
42+#define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
43+#define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
44+#define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
45+#define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33)) /* Rotate left 31 bits */
46+#else
47+#define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
48+#define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
49+#define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
50+#define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19)) /* Rotate left 13 bits */
51+#endif
52+
53+/* Tests have shown that it's not worth to cache the hash value, see
54+ https://bugs.python.org/issue9685 */
55+static Py_hash_t
56+StaticTuple_hash(StaticTuple *self)
57+{
58+ Py_ssize_t i, len = self->size;
59+ PyObject **item = self->items;
60+
61+#if STATIC_TUPLE_HAS_HASH
62+ if (self->hash != -1) {
63+ return self->hash;
64+ }
65+#endif
66+
67+ Py_uhash_t acc = _PyHASH_XXPRIME_5;
68+ for (i = 0; i < len; i++) {
69+ Py_uhash_t lane = PyObject_Hash(item[i]);
70+ if (lane == (Py_uhash_t)-1) {
71+ return -1;
72+ }
73+ acc += lane * _PyHASH_XXPRIME_2;
74+ acc = _PyHASH_XXROTATE(acc);
75+ acc *= _PyHASH_XXPRIME_1;
76+ }
77+
78+ /* Add input length, mangled to keep the historical value of hash(()). */
79+ acc += len ^ (_PyHASH_XXPRIME_5 ^ 3527539UL);
80+
81+ if (acc == (Py_uhash_t)-1) {
82+ acc = 1546275796;
83+ }
84+
85+#if STATIC_TUPLE_HAS_HASH
86+ self->hash = acc;
87+#endif
88+ return acc;
89+}
90+
91+
92+#else
93 static long
94 StaticTuple_hash(StaticTuple *self)
95 {
96@@ -357,6 +429,7 @@
97 #endif
98 return x;
99 }
100+#endif
101
102 static PyObject *
103 StaticTuple_richcompare_to_tuple(StaticTuple *v, PyObject *wt, int op)
104
105=== modified file 'breezy/bzr/_dirstate_helpers_pyx.pyx'
106--- breezy/bzr/_dirstate_helpers_pyx.pyx 2019-09-22 02:25:23 +0000
107+++ breezy/bzr/_dirstate_helpers_pyx.pyx 2019-11-19 20:09:35 +0000
108@@ -109,6 +109,9 @@
109 int PyBytes_Size(object p)
110 int PyBytes_GET_SIZE_void "PyBytes_GET_SIZE" (void *p)
111 int PyBytes_CheckExact(object p)
112+ int PyFloat_Check(object p)
113+ double PyFloat_AsDouble(object p)
114+ int PyLong_Check(object p)
115 void Py_INCREF(object o)
116 void Py_DECREF(object o)
117
118@@ -794,6 +797,14 @@
119 _encode = binascii.b2a_base64
120
121
122+cdef unsigned long _time_to_unsigned(object t): # cannot_raise
123+ cdef double dt
124+ if PyFloat_Check(t):
125+ dt = PyFloat_AsDouble(t)
126+ return <unsigned long>dt
127+ return PyInt_AsUnsignedLongMask(t)
128+
129+
130 cdef _pack_stat(stat_value):
131 """return a string representing the stat value's key fields.
132
133@@ -805,8 +816,8 @@
134 aliased = <int *>result
135 aliased[0] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_size))
136 # mtime and ctime will often be floats but get converted to PyInt within
137- aliased[1] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_mtime))
138- aliased[2] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_ctime))
139+ aliased[1] = htonl(_time_to_unsigned(stat_value.st_mtime))
140+ aliased[2] = htonl(_time_to_unsigned(stat_value.st_ctime))
141 aliased[3] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_dev))
142 aliased[4] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_ino))
143 aliased[5] = htonl(PyInt_AsUnsignedLongMask(stat_value.st_mode))
144
145=== modified file 'breezy/git/annotate.py'
146--- breezy/git/annotate.py 2018-11-11 14:23:06 +0000
147+++ breezy/git/annotate.py 2019-11-19 20:09:35 +0000
148@@ -100,11 +100,12 @@
149 self.change_scanner.repository.lookup_bzr_revision_id(
150 text_revision))
151 text_parents = []
152+ path = path.encode('utf-8')
153 for commit_parent in self.store[commit_id].parents:
154 try:
155 (path, text_parent) = (
156 self.change_scanner.find_last_change_revision(
157- path.encode('utf-8'), commit_parent))
158+ path, commit_parent))
159 except KeyError:
160 continue
161 if text_parent not in text_parents:
162
163=== modified file 'breezy/git/filegraph.py'
164--- breezy/git/filegraph.py 2018-11-11 14:23:06 +0000
165+++ breezy/git/filegraph.py 2019-11-19 20:09:35 +0000
166@@ -84,7 +84,7 @@
167 self.change_scanner.repository.lookup_bzr_revision_id(
168 text_revision))
169 try:
170- path = mapping.parse_file_id(file_id)
171+ path = mapping.parse_file_id(file_id).encode('utf-8')
172 except ValueError:
173 raise KeyError(file_id)
174 text_parents = []
175@@ -92,7 +92,7 @@
176 try:
177 (path, text_parent) = (
178 self.change_scanner.find_last_change_revision(
179- path.encode('utf-8'), commit_parent))
180+ path, commit_parent))
181 except KeyError:
182 continue
183 if text_parent not in text_parents:
184
185=== modified file 'breezy/git/remote.py'
186--- breezy/git/remote.py 2019-08-11 16:27:38 +0000
187+++ breezy/git/remote.py 2019-11-19 20:09:35 +0000
188@@ -123,10 +123,10 @@
189
190 try:
191 import urllib.parse as urlparse
192- from urllib.parse import splituser, splitnport
193+ from urllib.parse import splituser
194 except ImportError:
195 import urlparse
196- from urllib import splituser, splitnport
197+ from urllib import splituser
198
199 # urlparse only supports a limited number of schemes by default
200 register_urlparse_netloc_protocol('git')
201@@ -165,13 +165,11 @@
202 :param url: Git URL
203 :return: Tuple with host, port, username, path.
204 """
205- (scheme, netloc, loc, _, _) = urlparse.urlsplit(url)
206- path = urlparse.unquote(loc)
207+ parsed_url = urlparse.urlparse(url)
208+ path = urlparse.unquote(parsed_url.path)
209 if path.startswith("/~"):
210 path = path[1:]
211- (username, hostport) = splituser(netloc)
212- (host, port) = splitnport(hostport, None)
213- return (host, port, username, path)
214+ return ((parsed_url.hostname or '', parsed_url.port, parsed_url.username, path))
215
216
217 class RemoteGitError(BzrError):
218
219=== modified file 'breezy/git/tests/test_blackbox.py'
220--- breezy/git/tests/test_blackbox.py 2019-06-22 18:46:21 +0000
221+++ breezy/git/tests/test_blackbox.py 2019-11-19 20:09:35 +0000
222@@ -216,6 +216,28 @@
223 self.assertNotContainsRe(error, 'Committed revision 2.')
224 self.assertContainsRe(error, 'Committed revid .*.')
225
226+ def test_log_file(self):
227+ # Smoke test for "bzr log" in a git repository.
228+ repo = GitRepo.init(self.test_dir)
229+ builder = tests.GitBranchBuilder()
230+ builder.set_file('a', b'text for a\n', False)
231+ r1 = builder.commit(b'Joe Foo <joe@foo.com>', u'First')
232+ builder.set_file('a', b'text 3a for a\n', False)
233+ r2a = builder.commit(b'Joe Foo <joe@foo.com>', u'Second a', base=r1)
234+ builder.set_file('a', b'text 3b for a\n', False)
235+ r2b = builder.commit(b'Joe Foo <joe@foo.com>', u'Second b', base=r1)
236+ builder.set_file('a', b'text 4 for a\n', False)
237+ builder.commit(b'Joe Foo <joe@foo.com>', u'Third', merge=[r2a], base=r2b)
238+ builder.finish()
239+
240+ # Check that bzr log does not fail and includes the revision.
241+ output, error = self.run_bzr(['log', '-n2', 'a'])
242+ self.assertEqual(error, '')
243+ self.assertIn('Second a', output)
244+ self.assertIn('Second b', output)
245+ self.assertIn('First', output)
246+ self.assertIn('Third', output)
247+
248 def test_tags(self):
249 git_repo, commit_sha1 = self.simple_commit()
250 git_repo.refs[b"refs/tags/foo"] = commit_sha1
251
252=== modified file 'breezy/git/tests/test_remote.py'
253--- breezy/git/tests/test_remote.py 2019-08-06 07:11:09 +0000
254+++ breezy/git/tests/test_remote.py 2019-11-19 20:09:35 +0000
255@@ -65,6 +65,11 @@
256 self.assertEqual(("foo", None, "la", "/bar"),
257 split_git_url("git://la@foo/bar"))
258
259+ def test_username_password(self):
260+ self.assertEqual(
261+ ("foo", None, "la", "/bar"),
262+ split_git_url("git://la:passwd@foo/bar"))
263+
264 def test_nopath(self):
265 self.assertEqual(("foo", None, None, "/"),
266 split_git_url("git://foo/"))
267@@ -77,6 +82,11 @@
268 self.assertEqual(("foo", None, None, "~bar"),
269 split_git_url("git://foo/~bar"))
270
271+ def test_file(self):
272+ self.assertEqual(
273+ ("", None, None, "/bar"),
274+ split_git_url("file:///bar"))
275+
276
277 class ParseGitErrorTests(TestCase):
278
279
280=== modified file 'breezy/ignores.py'
281--- breezy/ignores.py 2019-06-16 01:03:51 +0000
282+++ breezy/ignores.py 2019-11-19 20:09:35 +0000
283@@ -101,8 +101,8 @@
284 # since get_* should be a safe operation
285 try:
286 _set_user_ignores(USER_DEFAULTS)
287- except (IOError, OSError) as e:
288- if e.errno not in (errno.EPERM,):
289+ except EnvironmentError as e:
290+ if e.errno not in (errno.EPERM, errno.ENOENT):
291 raise
292 return patterns
293
294
295=== modified file 'breezy/plugins/launchpad/lp_api.py'
296--- breezy/plugins/launchpad/lp_api.py 2019-07-15 23:23:48 +0000
297+++ breezy/plugins/launchpad/lp_api.py 2019-11-19 20:09:35 +0000
298@@ -69,23 +69,6 @@
299 MINIMUM_LAUNCHPADLIB_VERSION = (1, 6, 3)
300
301
302-# We use production as the default because edge has been deprecated circa
303-# 2010-11 (see bug https://bugs.launchpad.net/bzr/+bug/583667)
304-DEFAULT_INSTANCE = 'production'
305-
306-LAUNCHPAD_DOMAINS = {
307- 'production': 'launchpad.net',
308- 'staging': 'staging.launchpad.net',
309- 'qastaging': 'qastaging.launchpad.net',
310- 'demo': 'demo.launchpad.net',
311- 'dev': 'launchpad.test',
312- }
313-
314-LAUNCHPAD_BAZAAR_DOMAINS = [
315- 'bazaar.%s' % domain
316- for domain in LAUNCHPAD_DOMAINS.values()]
317-
318-
319 def get_cache_directory():
320 """Return the directory to cache launchpadlib objects in."""
321 return osutils.pathjoin(bedding.cache_dir(), 'launchpad')
322
323=== modified file 'breezy/plugins/launchpad/lp_directory.py'
324--- breezy/plugins/launchpad/lp_directory.py 2019-05-29 09:48:08 +0000
325+++ breezy/plugins/launchpad/lp_directory.py 2019-11-19 20:09:35 +0000
326@@ -35,7 +35,7 @@
327 )
328 from ...i18n import gettext
329
330-from .lp_api import (
331+from .uris import (
332 DEFAULT_INSTANCE,
333 LAUNCHPAD_DOMAINS,
334 )
335
336=== modified file 'breezy/plugins/launchpad/lp_registration.py'
337--- breezy/plugins/launchpad/lp_registration.py 2019-05-20 02:22:19 +0000
338+++ breezy/plugins/launchpad/lp_registration.py 2019-11-19 20:09:35 +0000
339@@ -48,7 +48,7 @@
340 )
341 from ...transport import http, get_transport
342
343-from .lp_api import (
344+from .uris import (
345 DEFAULT_INSTANCE,
346 LAUNCHPAD_DOMAINS,
347 LAUNCHPAD_BAZAAR_DOMAINS,
348
349=== modified file 'breezy/plugins/launchpad/test_lp_directory.py'
350--- breezy/plugins/launchpad/test_lp_directory.py 2019-05-29 09:48:08 +0000
351+++ breezy/plugins/launchpad/test_lp_directory.py 2019-11-19 20:09:35 +0000
352@@ -213,7 +213,7 @@
353 'lp:///apt')
354 self.assertResolve('bzr+ssh://bazaar.launchpad.net/+branch/apt',
355 'lp://production/apt')
356- self.assertResolve('bzr+ssh://bazaar.launchpad.test/+branch/apt',
357+ self.assertResolve('bzr+ssh://bazaar.launchpad.dev/+branch/apt',
358 'lp://dev/apt')
359 self.assertResolve('bzr+ssh://bazaar.staging.launchpad.net/+branch/apt',
360 'lp://staging/apt')
361
362=== modified file 'breezy/plugins/launchpad/test_lp_service.py'
363--- breezy/plugins/launchpad/test_lp_service.py 2019-05-29 09:48:08 +0000
364+++ breezy/plugins/launchpad/test_lp_service.py 2019-11-19 20:09:35 +0000
365@@ -62,7 +62,7 @@
366
367 def test_dev_service(self):
368 service = LaunchpadService(lp_instance='dev')
369- self.assertEqual('https://xmlrpc.launchpad.test/bazaar/',
370+ self.assertEqual('https://xmlrpc.launchpad.dev/bazaar/',
371 service.service_url)
372
373 def test_demo_service(self):
374@@ -178,7 +178,7 @@
375 web_url = service.get_web_url_from_branch_url(
376 'bzr+ssh://bazaar.launchpad.net/~foo/bar/baz')
377 self.assertEqual(
378- 'https://code.launchpad.test/~foo/bar/baz', web_url)
379+ 'https://code.launchpad.dev/~foo/bar/baz', web_url)
380
381 def test_demo_url(self):
382 service = LaunchpadService(lp_instance='demo')
383
384=== added file 'breezy/plugins/launchpad/uris.py'
385--- breezy/plugins/launchpad/uris.py 1970-01-01 00:00:00 +0000
386+++ breezy/plugins/launchpad/uris.py 2019-11-19 20:09:35 +0000
387@@ -0,0 +1,36 @@
388+# Copyright (C) 2009-2012 Canonical Ltd
389+#
390+# This program is free software; you can redistribute it and/or modify
391+# it under the terms of the GNU General Public License as published by
392+# the Free Software Foundation; either version 2 of the License, or
393+# (at your option) any later version.
394+#
395+# This program is distributed in the hope that it will be useful,
396+# but WITHOUT ANY WARRANTY; without even the implied warranty of
397+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
398+# GNU General Public License for more details.
399+#
400+# You should have received a copy of the GNU General Public License
401+# along with this program; if not, write to the Free Software
402+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
403+
404+"""Launchpad URIs."""
405+
406+from __future__ import absolute_import
407+
408+
409+# We use production as the default because edge has been deprecated circa
410+# 2010-11 (see bug https://bugs.launchpad.net/bzr/+bug/583667)
411+DEFAULT_INSTANCE = 'production'
412+
413+LAUNCHPAD_DOMAINS = {
414+ 'production': 'launchpad.net',
415+ 'staging': 'staging.launchpad.net',
416+ 'qastaging': 'qastaging.launchpad.net',
417+ 'demo': 'demo.launchpad.net',
418+ 'dev': 'launchpad.dev',
419+ }
420+
421+LAUNCHPAD_BAZAAR_DOMAINS = [
422+ 'bazaar.%s' % domain
423+ for domain in LAUNCHPAD_DOMAINS.values()]
424
425=== modified file 'breezy/tests/blackbox/test_testament.py'
426--- breezy/tests/blackbox/test_testament.py 2018-11-11 04:08:32 +0000
427+++ breezy/tests/blackbox/test_testament.py 2019-11-19 20:09:35 +0000
428@@ -35,28 +35,27 @@
429 """Testament containing a file and a directory."""
430 out, err = self.run_bzr('testament --long')
431 self.assertEqualDiff(err, '')
432- self.assertEqualDiff(out, REV_2_TESTAMENT.decode('utf-8'))
433+ self.assertEqualDiff(out, REV_2_TESTAMENT.decode('ascii'))
434
435 def test_testament_command_2(self):
436 """Command getting short testament of previous version."""
437 out, err = self.run_bzr('testament -r1')
438 self.assertEqualDiff(err, '')
439- self.assertEqualDiff(out, REV_1_SHORT.decode('utf-8'))
440+ self.assertEqualDiff(out, REV_1_SHORT.decode('ascii'))
441
442 def test_testament_command_3(self):
443 """Command getting short testament of previous version."""
444 out, err = self.run_bzr('testament -r1 --strict')
445 self.assertEqualDiff(err, '')
446- self.assertEqualDiff(out, REV_1_SHORT_STRICT.decode('utf-8'))
447+ self.assertEqualDiff(out, REV_1_SHORT_STRICT.decode('ascii'))
448
449 def test_testament_non_ascii(self):
450 self.wt.commit(u"Non \xe5ssci message")
451- long_out, err = self.run_bzr('testament --long')
452- self.assertEqualDiff(err, '')
453- short_out, err = self.run_bzr('testament')
454- self.assertEqualDiff(err, '')
455- sha1_re = re.compile('sha1: (?P<sha1>[a-f0-9]+)$', re.M)
456+ long_out, err = self.run_bzr_raw('testament --long', encoding='utf-8')
457+ self.assertEqualDiff(err, b'')
458+ long_out, err = self.run_bzr_raw('testament --long', encoding='ascii')
459+ short_out, err = self.run_bzr_raw('testament', encoding='ascii')
460+ self.assertEqualDiff(err, b'')
461+ sha1_re = re.compile(b'sha1: (?P<sha1>[a-f0-9]+)$', re.M)
462 sha1 = sha1_re.search(short_out).group('sha1')
463- self.assertEqual(
464- sha1.encode('ascii'),
465- osutils.sha_string(long_out.encode('utf-8') if PY3 else long_out))
466+ self.assertEqual(sha1, osutils.sha_string(long_out))
467
468=== modified file 'breezy/tests/test_ignores.py'
469--- breezy/tests/test_ignores.py 2019-06-16 01:03:51 +0000
470+++ breezy/tests/test_ignores.py 2019-11-19 20:09:35 +0000
471@@ -16,6 +16,8 @@
472
473 """Tests for handling of ignore files"""
474
475+import os
476+
477 from .. import (
478 bedding,
479 ignores,
480@@ -86,6 +88,22 @@
481 entries = ignores.parse_ignore_file(f)
482 self.assertEqual(set(ignores.USER_DEFAULTS), entries)
483
484+ def test_create_with_intermediate_missing(self):
485+ # $HOME should be set to '.'
486+ ignore_path = bedding.user_ignore_config_path()
487+ self.assertPathDoesNotExist(ignore_path)
488+ os.mkdir('empty-home')
489+
490+ config_path = os.path.join(self.test_dir, 'empty-home', '.config')
491+ self.overrideEnv('BRZ_HOME', config_path)
492+ self.assertPathDoesNotExist(config_path)
493+
494+ user_ignores = ignores.get_user_ignores()
495+ self.assertEqual(set(ignores.USER_DEFAULTS), user_ignores)
496+
497+ ignore_path = bedding.user_ignore_config_path()
498+ self.assertPathDoesNotExist(ignore_path)
499+
500 def test_use_existing(self):
501 patterns = [u'*.o', u'*.py[co]', u'\xe5*']
502 ignores._set_user_ignores(patterns)
503
504=== modified file 'breezy/tests/test_server.py'
505--- breezy/tests/test_server.py 2018-11-12 01:41:38 +0000
506+++ breezy/tests/test_server.py 2019-11-19 20:09:35 +0000
507@@ -249,6 +249,10 @@
508
509 class TestThread(cethread.CatchingExceptionThread):
510
511+ if not getattr(cethread.CatchingExceptionThread, 'is_alive', None):
512+ def is_alive(self):
513+ return self.isAlive()
514+
515 def join(self, timeout=5):
516 """Overrides to use a default timeout.
517
518@@ -256,7 +260,7 @@
519 serving a client connection is hung.
520 """
521 super(TestThread, self).join(timeout)
522- if timeout and self.isAlive():
523+ if timeout and self.is_alive():
524 # The timeout expired without joining the thread, the thread is
525 # therefore stucked and that's a failure as far as the test is
526 # concerned. We used to hang here.
527
528=== modified file 'doc/en/release-notes/brz-3.0.txt'
529--- doc/en/release-notes/brz-3.0.txt 2019-10-14 00:07:00 +0000
530+++ doc/en/release-notes/brz-3.0.txt 2019-11-19 20:09:35 +0000
531@@ -5,10 +5,10 @@
532 .. toctree::
533 :maxdepth: 1
534
535-brz 3.0.2
536+brz 3.0.3
537 #########
538
539-:3.0.2: NOT RELEASED YET
540+:3.0.3: NOT RELEASED YET
541
542 External Compatibility Breaks
543 *****************************
544@@ -32,10 +32,6 @@
545 .. Fixes for situations where brz would previously crash or give incorrect
546 or undesirable results.
547
548- * Disable loading from entrypoints by default, since it can
549- significantly slow down startup on some platforms.
550- (Jelmer Vernooij, #1832868)
551-
552 Documentation
553 *************
554
555@@ -61,6 +57,69 @@
556 spurious test failures and changes to the way things should be tested.
557
558
559+brz 3.0.2
560+#########
561+
562+:3.0.2: 2019-11-19
563+
564+External Compatibility Breaks
565+*****************************
566+
567+None.
568+
569+New Features
570+************
571+
572+None.
573+
574+Improvements
575+************
576+
577+None.
578+
579+Bug Fixes
580+*********
581+
582+ * Disable loading from entrypoints by default, since it can
583+ significantly slow down startup on some platforms.
584+ (Jelmer Vernooij, #1832868)
585+
586+ * Don't fail when unable to write per-user ignore list due to
587+ one of the intermediate directories not existing
588+ (Jelmer Vernooij, #1851904)
589+
590+ * Fix file graph operations on Git repositories.
591+ (Jelmer Vernooij, #1847913)
592+
593+ * Allow running tests without launchpadlib installed.
594+ (Jelmer Vernooij, #1849988)
595+
596+ * Fix compatibility with Python 3.8.
597+ (Jelmer Vernooij, Victor Stinner, #1844684)
598+
599+Documentation
600+*************
601+
602+None
603+
604+API Changes
605+***********
606+
607+None.
608+
609+Internals
610+*********
611+
612+None.
613+
614+Testing
615+*******
616+
617+ * Fix bb.test_testament.TestTestament.test_testament_non_ascii
618+ when the host encoding is non-utf8.
619+ (Jelmer Vernooij, #1849986)
620+
621+
622 bzr 3.0.1
623 #########
624
625
626=== modified file 'doc/en/release-notes/release-template.txt'
627--- doc/en/release-notes/release-template.txt 2017-05-21 18:10:28 +0000
628+++ doc/en/release-notes/release-template.txt 2019-11-19 20:09:35 +0000
629@@ -2,7 +2,7 @@
630 #########
631
632 :Codename: Nirvana
633-:2.x.y: NOT RELEASED YET
634+:3.y.z: NOT RELEASED YET
635
636 External Compatibility Breaks
637 *****************************

Subscribers

People subscribed via source and target branches