Mercurial > hg
comparison hgext/remotenames.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | 3018749a71bb |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
26 | 26 |
27 from __future__ import absolute_import | 27 from __future__ import absolute_import |
28 | 28 |
29 from mercurial.i18n import _ | 29 from mercurial.i18n import _ |
30 | 30 |
31 from mercurial.node import ( | 31 from mercurial.node import bin |
32 bin, | |
33 ) | |
34 from mercurial import ( | 32 from mercurial import ( |
35 bookmarks, | 33 bookmarks, |
36 error, | 34 error, |
37 extensions, | 35 extensions, |
38 logexchange, | 36 logexchange, |
43 smartset, | 41 smartset, |
44 templateutil, | 42 templateutil, |
45 util, | 43 util, |
46 ) | 44 ) |
47 | 45 |
48 from mercurial.utils import ( | 46 from mercurial.utils import stringutil |
49 stringutil, | |
50 ) | |
51 | 47 |
52 if pycompat.ispy3: | 48 if pycompat.ispy3: |
53 import collections.abc | 49 import collections.abc |
50 | |
54 mutablemapping = collections.abc.MutableMapping | 51 mutablemapping = collections.abc.MutableMapping |
55 else: | 52 else: |
56 import collections | 53 import collections |
54 | |
57 mutablemapping = collections.MutableMapping | 55 mutablemapping = collections.MutableMapping |
58 | 56 |
59 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | 57 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for |
60 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | 58 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
61 # be specifying the version(s) of Mercurial they are tested with, or | 59 # be specifying the version(s) of Mercurial they are tested with, or |
65 configtable = {} | 63 configtable = {} |
66 configitem = registrar.configitem(configtable) | 64 configitem = registrar.configitem(configtable) |
67 templatekeyword = registrar.templatekeyword() | 65 templatekeyword = registrar.templatekeyword() |
68 revsetpredicate = registrar.revsetpredicate() | 66 revsetpredicate = registrar.revsetpredicate() |
69 | 67 |
70 configitem('remotenames', 'bookmarks', | 68 configitem( |
71 default=True, | 69 'remotenames', 'bookmarks', default=True, |
72 ) | 70 ) |
73 configitem('remotenames', 'branches', | 71 configitem( |
74 default=True, | 72 'remotenames', 'branches', default=True, |
75 ) | 73 ) |
76 configitem('remotenames', 'hoistedpeer', | 74 configitem( |
77 default='default', | 75 'remotenames', 'hoistedpeer', default='default', |
78 ) | 76 ) |
77 | |
79 | 78 |
80 class lazyremotenamedict(mutablemapping): | 79 class lazyremotenamedict(mutablemapping): |
81 """ | 80 """ |
82 Read-only dict-like Class to lazily resolve remotename entries | 81 Read-only dict-like Class to lazily resolve remotename entries |
83 | 82 |
86 and store them in self.potentialentries. Then when asked to resolve an | 85 and store them in self.potentialentries. Then when asked to resolve an |
87 entry, if it is not in self.potentialentries, then it isn't there, if it | 86 entry, if it is not in self.potentialentries, then it isn't there, if it |
88 is in self.potentialentries we resolve it and store the result in | 87 is in self.potentialentries we resolve it and store the result in |
89 self.cache. We cannot be lazy is when asked all the entries (keys). | 88 self.cache. We cannot be lazy is when asked all the entries (keys). |
90 """ | 89 """ |
90 | |
91 def __init__(self, kind, repo): | 91 def __init__(self, kind, repo): |
92 self.cache = {} | 92 self.cache = {} |
93 self.potentialentries = {} | 93 self.potentialentries = {} |
94 self._kind = kind # bookmarks or branches | 94 self._kind = kind # bookmarks or branches |
95 self._repo = repo | 95 self._repo = repo |
96 self.loaded = False | 96 self.loaded = False |
97 | 97 |
98 def _load(self): | 98 def _load(self): |
99 """ Read the remotenames file, store entries matching selected kind """ | 99 """ Read the remotenames file, store entries matching selected kind """ |
100 self.loaded = True | 100 self.loaded = True |
101 repo = self._repo | 101 repo = self._repo |
102 for node, rpath, rname in logexchange.readremotenamefile(repo, | 102 for node, rpath, rname in logexchange.readremotenamefile( |
103 self._kind): | 103 repo, self._kind |
104 ): | |
104 name = rpath + '/' + rname | 105 name = rpath + '/' + rname |
105 self.potentialentries[name] = (node, rpath, name) | 106 self.potentialentries[name] = (node, rpath, name) |
106 | 107 |
107 def _resolvedata(self, potentialentry): | 108 def _resolvedata(self, potentialentry): |
108 """ Check that the node for potentialentry exists and return it """ | 109 """ Check that the node for potentialentry exists and return it """ |
115 try: | 116 try: |
116 repo.changelog.rev(binnode) | 117 repo.changelog.rev(binnode) |
117 except LookupError: | 118 except LookupError: |
118 return None | 119 return None |
119 # Skip closed branches | 120 # Skip closed branches |
120 if (self._kind == 'branches' and repo[binnode].closesbranch()): | 121 if self._kind == 'branches' and repo[binnode].closesbranch(): |
121 return None | 122 return None |
122 return [binnode] | 123 return [binnode] |
123 | 124 |
124 def __getitem__(self, key): | 125 def __getitem__(self, key): |
125 if not self.loaded: | 126 if not self.loaded: |
167 for k, vtup in self.potentialentries.iteritems(): | 168 for k, vtup in self.potentialentries.iteritems(): |
168 yield (k, [bin(vtup[0])]) | 169 yield (k, [bin(vtup[0])]) |
169 | 170 |
170 items = iteritems | 171 items = iteritems |
171 | 172 |
173 | |
172 class remotenames(object): | 174 class remotenames(object): |
173 """ | 175 """ |
174 This class encapsulates all the remotenames state. It also contains | 176 This class encapsulates all the remotenames state. It also contains |
175 methods to access that state in convenient ways. Remotenames are lazy | 177 methods to access that state in convenient ways. Remotenames are lazy |
176 loaded. Whenever client code needs to ensure the freshest copy of | 178 loaded. Whenever client code needs to ensure the freshest copy of |
221 marktonodes = self.bmarktonodes() | 223 marktonodes = self.bmarktonodes() |
222 self._hoisttonodes = {} | 224 self._hoisttonodes = {} |
223 hoist += '/' | 225 hoist += '/' |
224 for name, node in marktonodes.iteritems(): | 226 for name, node in marktonodes.iteritems(): |
225 if name.startswith(hoist): | 227 if name.startswith(hoist): |
226 name = name[len(hoist):] | 228 name = name[len(hoist) :] |
227 self._hoisttonodes[name] = node | 229 self._hoisttonodes[name] = node |
228 return self._hoisttonodes | 230 return self._hoisttonodes |
229 | 231 |
230 def nodetohoists(self, hoist): | 232 def nodetohoists(self, hoist): |
231 if not self._nodetohoists: | 233 if not self._nodetohoists: |
232 marktonodes = self.bmarktonodes() | 234 marktonodes = self.bmarktonodes() |
233 self._nodetohoists = {} | 235 self._nodetohoists = {} |
234 hoist += '/' | 236 hoist += '/' |
235 for name, node in marktonodes.iteritems(): | 237 for name, node in marktonodes.iteritems(): |
236 if name.startswith(hoist): | 238 if name.startswith(hoist): |
237 name = name[len(hoist):] | 239 name = name[len(hoist) :] |
238 self._nodetohoists.setdefault(node[0], []).append(name) | 240 self._nodetohoists.setdefault(node[0], []).append(name) |
239 return self._nodetohoists | 241 return self._nodetohoists |
242 | |
240 | 243 |
241 def wrapprintbookmarks(orig, ui, repo, fm, bmarks): | 244 def wrapprintbookmarks(orig, ui, repo, fm, bmarks): |
242 if 'remotebookmarks' not in repo.names: | 245 if 'remotebookmarks' not in repo.names: |
243 return | 246 return |
244 ns = repo.names['remotebookmarks'] | 247 ns = repo.names['remotebookmarks'] |
251 | 254 |
252 bmarks[name] = (node, ' ', '') | 255 bmarks[name] = (node, ' ', '') |
253 | 256 |
254 return orig(ui, repo, fm, bmarks) | 257 return orig(ui, repo, fm, bmarks) |
255 | 258 |
259 | |
256 def extsetup(ui): | 260 def extsetup(ui): |
257 extensions.wrapfunction(bookmarks, '_printbookmarks', wrapprintbookmarks) | 261 extensions.wrapfunction(bookmarks, '_printbookmarks', wrapprintbookmarks) |
262 | |
258 | 263 |
259 def reposetup(ui, repo): | 264 def reposetup(ui, repo): |
260 | 265 |
261 # set the config option to store remotenames | 266 # set the config option to store remotenames |
262 repo.ui.setconfig('experimental', 'remotenames', True, 'remotenames-ext') | 267 repo.ui.setconfig('experimental', 'remotenames', True, 'remotenames-ext') |
272 'remotebookmarks', | 277 'remotebookmarks', |
273 templatename='remotebookmarks', | 278 templatename='remotebookmarks', |
274 colorname='remotebookmark', | 279 colorname='remotebookmark', |
275 logfmt='remote bookmark: %s\n', | 280 logfmt='remote bookmark: %s\n', |
276 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(), | 281 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(), |
277 namemap=lambda repo, name: | 282 namemap=lambda repo, name: repo._remotenames.bmarktonodes().get( |
278 repo._remotenames.bmarktonodes().get(name, []), | 283 name, [] |
279 nodemap=lambda repo, node: | 284 ), |
280 repo._remotenames.nodetobmarks().get(node, [])) | 285 nodemap=lambda repo, node: repo._remotenames.nodetobmarks().get( |
286 node, [] | |
287 ), | |
288 ) | |
281 repo.names.addnamespace(remotebookmarkns) | 289 repo.names.addnamespace(remotebookmarkns) |
282 | 290 |
283 # hoisting only works if there are remote bookmarks | 291 # hoisting only works if there are remote bookmarks |
284 hoist = ui.config('remotenames', 'hoistedpeer') | 292 hoist = ui.config('remotenames', 'hoistedpeer') |
285 if hoist: | 293 if hoist: |
286 hoistednamens = ns( | 294 hoistednamens = ns( |
287 'hoistednames', | 295 'hoistednames', |
288 templatename='hoistednames', | 296 templatename='hoistednames', |
289 colorname='hoistedname', | 297 colorname='hoistedname', |
290 logfmt='hoisted name: %s\n', | 298 logfmt='hoisted name: %s\n', |
291 listnames = lambda repo: | 299 listnames=lambda repo: repo._remotenames.hoisttonodes( |
292 repo._remotenames.hoisttonodes(hoist).keys(), | 300 hoist |
293 namemap = lambda repo, name: | 301 ).keys(), |
294 repo._remotenames.hoisttonodes(hoist).get(name, []), | 302 namemap=lambda repo, name: repo._remotenames.hoisttonodes( |
295 nodemap = lambda repo, node: | 303 hoist |
296 repo._remotenames.nodetohoists(hoist).get(node, [])) | 304 ).get(name, []), |
305 nodemap=lambda repo, node: repo._remotenames.nodetohoists( | |
306 hoist | |
307 ).get(node, []), | |
308 ) | |
297 repo.names.addnamespace(hoistednamens) | 309 repo.names.addnamespace(hoistednamens) |
298 | 310 |
299 if ui.configbool('remotenames', 'branches'): | 311 if ui.configbool('remotenames', 'branches'): |
300 remotebranchns = ns( | 312 remotebranchns = ns( |
301 'remotebranches', | 313 'remotebranches', |
302 templatename='remotebranches', | 314 templatename='remotebranches', |
303 colorname='remotebranch', | 315 colorname='remotebranch', |
304 logfmt='remote branch: %s\n', | 316 logfmt='remote branch: %s\n', |
305 listnames = lambda repo: repo._remotenames.branchtonodes().keys(), | 317 listnames=lambda repo: repo._remotenames.branchtonodes().keys(), |
306 namemap = lambda repo, name: | 318 namemap=lambda repo, name: repo._remotenames.branchtonodes().get( |
307 repo._remotenames.branchtonodes().get(name, []), | 319 name, [] |
308 nodemap = lambda repo, node: | 320 ), |
309 repo._remotenames.nodetobranch().get(node, [])) | 321 nodemap=lambda repo, node: repo._remotenames.nodetobranch().get( |
322 node, [] | |
323 ), | |
324 ) | |
310 repo.names.addnamespace(remotebranchns) | 325 repo.names.addnamespace(remotebranchns) |
326 | |
311 | 327 |
312 @templatekeyword('remotenames', requires={'repo', 'ctx'}) | 328 @templatekeyword('remotenames', requires={'repo', 'ctx'}) |
313 def remotenameskw(context, mapping): | 329 def remotenameskw(context, mapping): |
314 """List of strings. Remote names associated with the changeset.""" | 330 """List of strings. Remote names associated with the changeset.""" |
315 repo = context.resource(mapping, 'repo') | 331 repo = context.resource(mapping, 'repo') |
320 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node()) | 336 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node()) |
321 | 337 |
322 if 'remotebranches' in repo.names: | 338 if 'remotebranches' in repo.names: |
323 remotenames += repo.names['remotebranches'].names(repo, ctx.node()) | 339 remotenames += repo.names['remotebranches'].names(repo, ctx.node()) |
324 | 340 |
325 return templateutil.compatlist(context, mapping, 'remotename', remotenames, | 341 return templateutil.compatlist( |
326 plural='remotenames') | 342 context, mapping, 'remotename', remotenames, plural='remotenames' |
343 ) | |
344 | |
327 | 345 |
328 @templatekeyword('remotebookmarks', requires={'repo', 'ctx'}) | 346 @templatekeyword('remotebookmarks', requires={'repo', 'ctx'}) |
329 def remotebookmarkskw(context, mapping): | 347 def remotebookmarkskw(context, mapping): |
330 """List of strings. Remote bookmarks associated with the changeset.""" | 348 """List of strings. Remote bookmarks associated with the changeset.""" |
331 repo = context.resource(mapping, 'repo') | 349 repo = context.resource(mapping, 'repo') |
333 | 351 |
334 remotebmarks = [] | 352 remotebmarks = [] |
335 if 'remotebookmarks' in repo.names: | 353 if 'remotebookmarks' in repo.names: |
336 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node()) | 354 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node()) |
337 | 355 |
338 return templateutil.compatlist(context, mapping, 'remotebookmark', | 356 return templateutil.compatlist( |
339 remotebmarks, plural='remotebookmarks') | 357 context, |
358 mapping, | |
359 'remotebookmark', | |
360 remotebmarks, | |
361 plural='remotebookmarks', | |
362 ) | |
363 | |
340 | 364 |
341 @templatekeyword('remotebranches', requires={'repo', 'ctx'}) | 365 @templatekeyword('remotebranches', requires={'repo', 'ctx'}) |
342 def remotebrancheskw(context, mapping): | 366 def remotebrancheskw(context, mapping): |
343 """List of strings. Remote branches associated with the changeset.""" | 367 """List of strings. Remote branches associated with the changeset.""" |
344 repo = context.resource(mapping, 'repo') | 368 repo = context.resource(mapping, 'repo') |
346 | 370 |
347 remotebranches = [] | 371 remotebranches = [] |
348 if 'remotebranches' in repo.names: | 372 if 'remotebranches' in repo.names: |
349 remotebranches = repo.names['remotebranches'].names(repo, ctx.node()) | 373 remotebranches = repo.names['remotebranches'].names(repo, ctx.node()) |
350 | 374 |
351 return templateutil.compatlist(context, mapping, 'remotebranch', | 375 return templateutil.compatlist( |
352 remotebranches, plural='remotebranches') | 376 context, |
377 mapping, | |
378 'remotebranch', | |
379 remotebranches, | |
380 plural='remotebranches', | |
381 ) | |
382 | |
353 | 383 |
354 def _revsetutil(repo, subset, x, rtypes): | 384 def _revsetutil(repo, subset, x, rtypes): |
355 """utility function to return a set of revs based on the rtypes""" | 385 """utility function to return a set of revs based on the rtypes""" |
356 args = revsetlang.getargs(x, 0, 1, _('only one argument accepted')) | 386 args = revsetlang.getargs(x, 0, 1, _('only one argument accepted')) |
357 if args: | 387 if args: |
358 kind, pattern, matcher = stringutil.stringmatcher( | 388 kind, pattern, matcher = stringutil.stringmatcher( |
359 revsetlang.getstring(args[0], _('argument must be a string'))) | 389 revsetlang.getstring(args[0], _('argument must be a string')) |
390 ) | |
360 else: | 391 else: |
361 kind = pattern = None | 392 kind = pattern = None |
362 matcher = util.always | 393 matcher = util.always |
363 | 394 |
364 nodes = set() | 395 nodes = set() |
369 for name in ns.listnames(repo): | 400 for name in ns.listnames(repo): |
370 if not matcher(name): | 401 if not matcher(name): |
371 continue | 402 continue |
372 nodes.update(ns.nodes(repo, name)) | 403 nodes.update(ns.nodes(repo, name)) |
373 if kind == 'literal' and not nodes: | 404 if kind == 'literal' and not nodes: |
374 raise error.RepoLookupError(_("remote name '%s' does not exist") | 405 raise error.RepoLookupError( |
375 % pattern) | 406 _("remote name '%s' does not exist") % pattern |
407 ) | |
376 | 408 |
377 revs = (cl.rev(n) for n in nodes if cl.hasnode(n)) | 409 revs = (cl.rev(n) for n in nodes if cl.hasnode(n)) |
378 return subset & smartset.baseset(revs) | 410 return subset & smartset.baseset(revs) |
411 | |
379 | 412 |
380 @revsetpredicate('remotenames([name])') | 413 @revsetpredicate('remotenames([name])') |
381 def remotenamesrevset(repo, subset, x): | 414 def remotenamesrevset(repo, subset, x): |
382 """All changesets which have a remotename on them. If `name` is | 415 """All changesets which have a remotename on them. If `name` is |
383 specified, only remotenames of matching remote paths are considered. | 416 specified, only remotenames of matching remote paths are considered. |
384 | 417 |
385 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. | 418 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. |
386 """ | 419 """ |
387 return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches')) | 420 return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches')) |
388 | 421 |
422 | |
389 @revsetpredicate('remotebranches([name])') | 423 @revsetpredicate('remotebranches([name])') |
390 def remotebranchesrevset(repo, subset, x): | 424 def remotebranchesrevset(repo, subset, x): |
391 """All changesets which are branch heads on remotes. If `name` is | 425 """All changesets which are branch heads on remotes. If `name` is |
392 specified, only remotenames of matching remote paths are considered. | 426 specified, only remotenames of matching remote paths are considered. |
393 | 427 |
394 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. | 428 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`. |
395 """ | 429 """ |
396 return _revsetutil(repo, subset, x, ('remotebranches',)) | 430 return _revsetutil(repo, subset, x, ('remotebranches',)) |
397 | 431 |
432 | |
398 @revsetpredicate('remotebookmarks([name])') | 433 @revsetpredicate('remotebookmarks([name])') |
399 def remotebmarksrevset(repo, subset, x): | 434 def remotebmarksrevset(repo, subset, x): |
400 """All changesets which have bookmarks on remotes. If `name` is | 435 """All changesets which have bookmarks on remotes. If `name` is |
401 specified, only remotenames of matching remote paths are considered. | 436 specified, only remotenames of matching remote paths are considered. |
402 | 437 |