Merge lp:brz/3.3 into lp:brz

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: 7796
Merged at revision: 7692
Proposed branch: lp:brz/3.3
Merge into: lp:brz
Diff against target: 504 lines (+67/-154)
12 files modified
breezy/git/branch.py (+1/-2)
breezy/git/interrepo.py (+10/-6)
breezy/git/refs.py (+6/-40)
breezy/plugin.py (+4/-26)
breezy/plugins/bash_completion/tests/test_bashcomp.py (+6/-3)
breezy/plugins/launchpad/lp_directory.py (+11/-4)
breezy/tests/__init__.py (+8/-3)
breezy/tests/features.py (+0/-1)
breezy/tests/test_plugins.py (+1/-60)
breezy/tests/test_selftest.py (+14/-3)
breezy/tests/test_transport.py (+3/-3)
pyproject.toml (+3/-3)
To merge this branch: bzr merge lp:brz/3.3
Reviewer Review Type Date Requested Status
Jelmer Vernooij Approve
Review via email: mp+440187@code.launchpad.net

Commit message

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) :
review: Approve
Revision history for this message
The Breezy Bot (the-breezy-bot) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/git/branch.py'
2--- breezy/git/branch.py 2023-03-09 13:47:07 +0000
3+++ breezy/git/branch.py 2023-03-31 22:11:54 +0000
4@@ -40,8 +40,7 @@
5 from .mapping import decode_git_path, encode_git_path
6 from .push import remote_divergence
7 from .refs import (branch_name_to_ref, is_tag, ref_to_branch_name,
8- ref_to_tag_name, remote_refs_dict_to_tag_refs,
9- tag_name_to_ref)
10+ ref_to_tag_name, tag_name_to_ref)
11 from .unpeel_map import UnpeelMap
12 from .urls import bzr_url_to_git_url, git_url_to_bzr_url
13
14
15=== modified file 'breezy/git/interrepo.py'
16--- breezy/git/interrepo.py 2023-03-09 13:47:07 +0000
17+++ breezy/git/interrepo.py 2023-03-31 22:11:54 +0000
18@@ -24,7 +24,11 @@
19 from dulwich.object_store import ObjectStoreGraphWalker
20 from dulwich.pack import PACK_SPOOL_FILE_MAX_SIZE
21 from dulwich.protocol import CAPABILITY_THIN_PACK, ZERO_SHA
22-from dulwich.refs import ANNOTATED_TAG_SUFFIX, SYMREF
23+from dulwich.refs import SYMREF
24+try:
25+ from dulwich.refs import PEELED_TAG_SUFFIX
26+except ImportError: # dulwich < 0.21.3
27+ from dulwich.refs import ANNOTATED_TAG_SUFFIX as PEELED_TAG_SUFFIX
28 from dulwich.walk import Walker
29
30 from .. import config, trace, ui
31@@ -378,12 +382,12 @@
32 def determine_wants(refs):
33 unpeel_lookup = {}
34 for k, v in refs.items():
35- if k.endswith(ANNOTATED_TAG_SUFFIX):
36- unpeel_lookup[v] = refs[k[:-len(ANNOTATED_TAG_SUFFIX)]]
37+ if k.endswith(PEELED_TAG_SUFFIX):
38+ unpeel_lookup[v] = refs[k[:-len(PEELED_TAG_SUFFIX)]]
39 potential = {unpeel_lookup.get(w, w) for w in wants}
40 if include_tags:
41 for k, sha in refs.items():
42- if k.endswith(ANNOTATED_TAG_SUFFIX):
43+ if k.endswith(PEELED_TAG_SUFFIX):
44 continue
45 try:
46 tag_name = ref_to_tag_name(k)
47@@ -686,7 +690,7 @@
48 if value == ZERO_SHA:
49 continue
50
51- if name.endswith(ANNOTATED_TAG_SUFFIX):
52+ if name.endswith(PEELED_TAG_SUFFIX):
53 continue
54
55 if name in branches or (include_tags and is_tag(name)):
56@@ -697,7 +701,7 @@
57 def determine_wants_all(self, refs):
58 potential = {
59 v for k, v in refs.items()
60- if not v == ZERO_SHA and not k.endswith(ANNOTATED_TAG_SUFFIX)}
61+ if not v == ZERO_SHA and not k.endswith(PEELED_TAG_SUFFIX)}
62 return list(potential - self._target_has_shas(potential))
63
64
65
66=== modified file 'breezy/git/refs.py'
67--- breezy/git/refs.py 2023-01-31 01:05:40 +0000
68+++ breezy/git/refs.py 2023-03-31 22:11:54 +0000
69@@ -17,8 +17,11 @@
70 """Conversion between refs and Bazaar revision pointers."""
71
72 from dulwich.objects import Tag, object_class
73-from dulwich.refs import (ANNOTATED_TAG_SUFFIX, LOCAL_BRANCH_PREFIX,
74- LOCAL_TAG_PREFIX)
75+from dulwich.refs import (LOCAL_BRANCH_PREFIX, LOCAL_TAG_PREFIX)
76+try:
77+ from dulwich.refs import PEELED_TAG_SUFFIX
78+except ImportError:
79+ from dulwich.refs import ANNOTATED_TAG_SUFFIX as PEELED_TAG_SUFFIX
80 from dulwich.repo import RefsContainer
81
82 from .. import controldir, errors, osutils
83@@ -29,27 +32,8 @@
84 return x.startswith(LOCAL_TAG_PREFIX)
85
86
87-def is_head(x):
88- return x.startswith(LOCAL_BRANCH_PREFIX)
89-
90-
91 def is_peeled(x):
92- return x.endswith(ANNOTATED_TAG_SUFFIX)
93-
94-
95-def gather_peeled(refs):
96- ret = {}
97- for k, v in refs.items():
98- if is_peeled(k):
99- continue
100- try:
101- peeled = refs[k + ANNOTATED_TAG_SUFFIX]
102- unpeeled = v
103- except KeyError:
104- peeled = v
105- unpeeled = None
106- ret[k] = (peeled, unpeeled)
107- return ret
108+ return x.endswith(PEELED_TAG_SUFFIX)
109
110
111 def branch_name_to_ref(name):
112@@ -192,21 +176,3 @@
113 if fn is not None:
114 return fn()
115 return BazaarRefsContainer(controldir, object_store)
116-
117-
118-def remote_refs_dict_to_tag_refs(refs_dict):
119- base = {}
120- peeled = {}
121- for k, v in refs_dict.items():
122- if is_peeled(k):
123- peeled[k[:-3]] = v
124- else:
125- base[k] = v
126- peeled[k] = v
127- all_keys = set().union(base.keys(), peeled.keys())
128- for n in all_keys:
129- try:
130- tag_name = ref_to_tag_name(n)
131- except ValueError:
132- continue
133- yield (n, tag_name, peeled.get(n), base.get(n))
134
135=== modified file 'breezy/plugin.py'
136--- breezy/plugin.py 2023-01-31 01:05:40 +0000
137+++ breezy/plugin.py 2023-03-31 22:11:54 +0000
138@@ -87,9 +87,7 @@
139 from breezy.plugins import __path__ as path
140
141 state.plugin_warnings = {}
142- _load_plugins_from_path(state, path)
143- if (None, 'entrypoints') in _env_plugin_path():
144- _load_plugins_from_entrypoints(state)
145+ _load_plugins(state, path)
146 state.plugins = plugins()
147 if warn_load_problems:
148 for plugin, errors in state.plugin_warnings.items():
149@@ -97,25 +95,6 @@
150 trace.warning('%s', error)
151
152
153-def _load_plugins_from_entrypoints(state):
154- try:
155- from importlib.metadata import entry_points
156- except ModuleNotFoundError:
157- # No importlib.metadata, no entrypoints.
158- pass
159- else:
160- try:
161- eps = entry_points(group='breezy.plugin')
162- except TypeError: # python < 3.10 didn't support group argument
163- eps = [ep[0] for ep in entry_points().values()
164- if ep[0].group == 'breezy.plugin']
165- for ep in eps:
166- fullname = _MODULE_PREFIX + ep.name
167- if fullname in sys.modules:
168- continue
169- sys.modules[fullname] = ep.load()
170-
171-
172 def plugin_name(module_name):
173 """Gives unprefixed name from module_name or None."""
174 if module_name.startswith(_MODULE_PREFIX):
175@@ -216,7 +195,7 @@
176 """Gives list of paths and contexts for plugins from environ key.
177
178 Each entry is either a specific path to load plugins from and the value
179- 'path', or None and one of the values 'user', 'core', 'entrypoints', 'site'.
180+ 'path', or None and one of the three values 'user', 'core', 'site'.
181 """
182 path_details = []
183 env = os.environ.get(key)
184@@ -224,7 +203,6 @@
185 "user": not env,
186 "core": True,
187 "site": True,
188- 'entrypoints': False,
189 }
190 if env:
191 # Add paths specified by user in order
192@@ -238,7 +216,7 @@
193 path_details.append((p, 'path'))
194
195 # Add any remaining default paths
196- for name in ('user', 'core', 'entrypoints', 'site'):
197+ for name in ('user', 'core', 'site'):
198 if defaults[name]:
199 path_details.append((None, name))
200
201@@ -272,7 +250,7 @@
202 sys.meta_path.insert(2, finder)
203
204
205-def _load_plugins_from_path(state, paths):
206+def _load_plugins(state, paths):
207 """Do the importing all plugins from paths."""
208 imported_names = set()
209 for name, path in _iter_possible_plugins(paths):
210
211=== modified file 'breezy/plugins/bash_completion/tests/test_bashcomp.py'
212--- breezy/plugins/bash_completion/tests/test_bashcomp.py 2023-01-31 01:05:40 +0000
213+++ breezy/plugins/bash_completion/tests/test_bashcomp.py 2023-03-31 22:11:54 +0000
214@@ -59,9 +59,12 @@
215 input += b"IFS=$'\\n'\n"
216 input += b'echo "${COMPREPLY[*]}"\n'
217 (out, err) = proc.communicate(input)
218- if b'' != err:
219+ errlines = [
220+ line for line in err.splitlines()
221+ if not line.startswith(b'brz: warning: ')]
222+ if [] != errlines:
223 raise AssertionError('Unexpected error message:\n%s' % err)
224- self.assertEqual(b'', err, 'No messages to standard error')
225+ self.assertEqual(b'', b''.join(errlines), 'No messages to standard error')
226 #import sys
227 #print >>sys.stdout, '---\n%s\n---\n%s\n---\n' % (input, out)
228 lines = out.split(b'\n')
229@@ -167,7 +170,7 @@
230
231 def get_script(self):
232 s = super().get_script()
233- s = s.replace("$(brz ", "$('%s' " % self.get_brz_path())
234+ s = s.replace("$(brz ", "$(%s " % ' '.join(self.get_brz_command()))
235 s = s.replace("2>/dev/null", "")
236 return s
237
238
239=== modified file 'breezy/plugins/launchpad/lp_directory.py'
240--- breezy/plugins/launchpad/lp_directory.py 2023-01-31 01:05:40 +0000
241+++ breezy/plugins/launchpad/lp_directory.py 2023-03-31 22:11:54 +0000
242@@ -20,7 +20,7 @@
243
244 from ... import debug, errors, trace, transport
245 from ...i18n import gettext
246-from ...urlutils import InvalidURL
247+from ...urlutils import InvalidURL, split, join
248 from .account import get_lp_login
249 from .uris import DEFAULT_INSTANCE, LAUNCHPAD_DOMAINS, LPNET_SERVICE_ROOT
250
251@@ -63,10 +63,17 @@
252 def _resolve_via_api(path, url, api_base_url=LPNET_SERVICE_ROOT):
253 from .lp_api import connect_launchpad
254 lp = connect_launchpad(api_base_url, version='devel')
255- lp_branch = lp.branches.getByPath(path=path)
256+ subpaths = []
257+ while path:
258+ lp_branch = lp.branches.getByPath(path=path)
259+ if lp_branch:
260+ break
261+ path, subpath = split(path)
262+ subpaths.insert(0, subpath)
263 if not lp_branch:
264- raise InvalidURL("Unknown Launchpad path: %s" % path)
265- return {'urls': [lp_branch.composePublicURL(scheme='bzr+ssh'), lp_branch.composePublicURL(scheme='http')]}
266+ raise errors.InvalidURL("Unknown Launchpad path: %s" % url)
267+ return {'urls': [join(lp_branch.composePublicURL(scheme='bzr+ssh'), *subpaths),
268+ join(lp_branch.composePublicURL(scheme='http'), *subpaths)]}
269
270
271 class LaunchpadDirectory:
272
273=== modified file 'breezy/tests/__init__.py'
274--- breezy/tests/__init__.py 2023-01-31 01:05:40 +0000
275+++ breezy/tests/__init__.py 2023-03-31 22:11:54 +0000
276@@ -2207,8 +2207,6 @@
277 for env_var, value in old_env.items():
278 osutils.set_or_unset_env(env_var, value)
279
280- bzr_path = self.get_brz_path()
281-
282 cwd = None
283 if working_dir is not None:
284 cwd = osutils.getcwd()
285@@ -2222,7 +2220,7 @@
286 # Include the subprocess's log file in the test details, in case
287 # the test fails due to an error in the subprocess.
288 self._add_subprocess_log(trace._get_brz_log_filename())
289- command = [bzr_path]
290+ command = self.get_brz_command()
291 if not allow_plugins:
292 command.append('--no-plugins')
293 command.extend(process_args)
294@@ -2284,6 +2282,13 @@
295 brz_path = sys.argv[0]
296 return brz_path
297
298+ def get_brz_command(self):
299+ bzr_path = self.get_brz_path()
300+ if bzr_path.endswith('__main__.py'):
301+ return [sys.executable, '-m', 'breezy']
302+ else:
303+ return [bzr_path]
304+
305 def finish_brz_subprocess(self, process, retcode=0, send_signal=None,
306 universal_newlines=False, process_args=None):
307 """Finish the execution of process.
308
309=== modified file 'breezy/tests/features.py'
310--- breezy/tests/features.py 2023-01-31 01:05:40 +0000
311+++ breezy/tests/features.py 2023-03-31 22:11:54 +0000
312@@ -400,7 +400,6 @@
313 flake8 = ModuleAvailableFeature('flake8.api.legacy')
314
315 lsprof_feature = ModuleAvailableFeature('breezy.lsprof')
316-importlib_metadata_feature = ModuleAvailableFeature('importlib.metadata')
317
318 pyinotify = ModuleAvailableFeature('pyinotify')
319
320
321=== modified file 'breezy/tests/test_plugins.py'
322--- breezy/tests/test_plugins.py 2023-01-31 01:05:40 +0000
323+++ breezy/tests/test_plugins.py 2023-03-31 22:11:54 +0000
324@@ -28,7 +28,6 @@
325 import breezy
326
327 from .. import osutils, plugin, tests
328-from ..tests.features import importlib_metadata_feature
329
330 # TODO: Write a test for plugin decoration of commands.
331
332@@ -610,7 +609,6 @@
333 user = "USER"
334 core = "CORE"
335 site = "SITE"
336- entrypoints = "ENTRYPOINTS"
337
338 def check_path(self, expected_dirs, setting_dirs):
339 if setting_dirs is None:
340@@ -636,10 +634,6 @@
341 self.check_path([self.user, self.site, self.core],
342 ['+user', '+site', '+core'])
343
344- def test_enable_entrypoints(self):
345- self.check_path([self.user, self.core, self.site, self.entrypoints],
346- ['+user', '+core', '+site', '+entrypoints'])
347-
348 def test_disable_user(self):
349 self.check_path([self.core, self.site], ['-user'])
350
351@@ -681,9 +675,7 @@
352 ['mycore', '-core'])
353
354 def test_my_plugin_only(self):
355- self.check_path(
356- ['myplugin'],
357- ['myplugin', '-user', '-core', '-site', '-entrypoints'])
358+ self.check_path(['myplugin'], ['myplugin', '-user', '-core', '-site'])
359
360 def test_my_plugin_first(self):
361 self.check_path(['myplugin', self.core, self.site, self.user],
362@@ -917,54 +909,3 @@
363 Hi there
364
365 """, ''.join(plugin.describe_plugins(state=self)))
366-
367-
368-class DummyPlugin:
369- """Plugin."""
370-
371-
372-class TestLoadEnvPlugin(BaseTestPlugins):
373-
374- _test_needs_features = [importlib_metadata_feature]
375-
376- def setup_plugin(self, source=""):
377- # This test tests a new plugin appears in breezy.plugin.plugins().
378- # check the plugin is not loaded already
379- self.assertPluginUnknown('plugin')
380- # write a plugin that _cannot_ fail to load.
381- from importlib.metadata import Distribution, EntryPoint, entry_points
382- class DummyDistribution:
383-
384- def __init__(self, name, entry_points):
385- self._normalized_name = self.name = name
386- self.entry_points = entry_points
387- ep = EntryPoint(name='plugin', group='breezy.plugin',
388- value=__name__ + ':DummyPlugin')
389- d = DummyDistribution('lala', [ep])
390- old_discover = Distribution.discover
391- def override_discover(**kwargs):
392- yield from old_discover(**kwargs)
393- yield d
394- self.overrideAttr(Distribution, 'discover', override_discover)
395- try:
396- eps = entry_points(group='breezy.plugin')
397- except TypeError: # python < 3.10
398- eps = [ep[0] for ep in entry_points().values()
399- if ep[0].group == 'breezy.plugin']
400- self.assertEqual(['plugin'], [ep.name for ep in eps])
401- self.load_with_paths(['.'])
402-
403- def test_plugin_loaded(self):
404- self.assertPluginUnknown('plugin')
405- self.overrideEnv('BRZ_PLUGIN_PATH', '+entrypoints')
406- self.setup_plugin()
407- p = self.plugins['plugin']
408- self.assertIsInstance(p, breezy.plugin.PlugIn)
409- self.assertIs(p.module, sys.modules[self.module_prefix + 'plugin'])
410-
411- def test_plugin_loaded_disabled(self):
412- self.assertPluginUnknown('plugin')
413- self.overrideEnv('BRZ_PLUGIN_PATH', '+entrypoints')
414- self.overrideEnv('BRZ_DISABLE_PLUGINS', 'plugin')
415- self.setup_plugin()
416- self.assertNotIn('plugin', self.plugins)
417
418=== modified file 'breezy/tests/test_selftest.py'
419--- breezy/tests/test_selftest.py 2023-01-31 01:05:40 +0000
420+++ breezy/tests/test_selftest.py 2023-03-31 22:11:54 +0000
421@@ -2618,14 +2618,25 @@
422 def test_run_brz_subprocess_no_plugins(self):
423 self.assertRaises(_DontSpawnProcess, self.start_brz_subprocess, [])
424 command = self._popen_args[0]
425- self.assertEqual(self.get_brz_path(), command[0])
426- self.assertEqual(['--no-plugins'], command[1:])
427+ if self.get_brz_path().endswith('__main__.py'):
428+ self.assertEqual(sys.executable, command[0])
429+ self.assertEqual('-m', command[1])
430+ self.assertEqual('breezy', command[2])
431+ rest = command[3:]
432+ else:
433+ self.assertEqual(self.get_brz_path(), command[0])
434+ rest = command[1:]
435+ self.assertEqual(['--no-plugins'], rest)
436
437 def test_allow_plugins(self):
438 self.assertRaises(_DontSpawnProcess, self.start_brz_subprocess, [],
439 allow_plugins=True)
440 command = self._popen_args[0]
441- self.assertEqual([], command[2:])
442+ if self.get_brz_path().endswith('__main__.py'):
443+ rest = command[3:]
444+ else:
445+ rest = command[1:]
446+ self.assertEqual([], rest)
447
448 def test_set_env(self):
449 self.assertFalse('EXISTANT_ENV_VAR' in os.environ)
450
451=== modified file 'breezy/tests/test_transport.py'
452--- breezy/tests/test_transport.py 2023-01-31 01:05:40 +0000
453+++ breezy/tests/test_transport.py 2023-03-31 22:11:54 +0000
454@@ -1048,8 +1048,8 @@
455 self.start_server(ssh_server)
456 port = ssh_server.port
457
458- bzr_remote_path = self.get_brz_path()
459- self.overrideEnv('BZR_REMOTE_PATH', bzr_remote_path)
460+ bzr_remote_command = self.get_brz_command()
461+ self.overrideEnv('BZR_REMOTE_PATH', ' '.join(bzr_remote_command))
462 self.overrideEnv('PYTHONPATH', ':'.join(sys.path))
463
464 # Access the branch via a bzr+ssh URL. The BZR_REMOTE_PATH environment
465@@ -1066,7 +1066,7 @@
466
467 self.assertEqual(
468 [b'%s serve --inet --directory=/ --allow-writes' %
469- bzr_remote_path.encode()],
470+ ' '.join(bzr_remote_command).encode()],
471 self.command_executed)
472 # Make sure to disconnect, so that the remote process can stop, and we
473 # can cleanup. Then pause the test until everything is shutdown
474
475=== modified file 'pyproject.toml'
476--- pyproject.toml 2023-03-09 13:21:34 +0000
477+++ pyproject.toml 2023-03-31 22:11:54 +0000
478@@ -31,7 +31,7 @@
479 "fastbencode",
480 "patiencediff",
481 "merge3",
482- "dulwich>=0.21.2",
483+ "dulwich>=0.21.3",
484 "urllib3>=1.24.1",
485 "pyyaml",
486 ]
487@@ -43,7 +43,7 @@
488
489 [project.optional-dependencies]
490 fastimport = ["fastimport"]
491-git = ["dulwich>=0.21.2"]
492+git = ["dulwich>=0.21.3"]
493 launchpad = ["launchpadlib>=1.6.3"]
494 workspace = ["pyinotify"]
495 doc = [
496@@ -67,7 +67,7 @@
497 "testtools",
498 "testscenarios",
499 "python-subunit",
500- "dulwich>=0.21.2",
501+ "dulwich>=0.21.3",
502 ]
503
504 [tool.setuptools]

Subscribers

People subscribed via source and target branches