##// END OF EJS Templates
remotenames: inline _parseargs() into _revsetutil()...
Yuya Nishihara -
r40101:25533575 default
parent child Browse files
Show More
@@ -1,408 +1,397 b''
1 # remotenames.py - extension to display remotenames
1 # remotenames.py - extension to display remotenames
2 #
2 #
3 # Copyright 2017 Augie Fackler <raf@durin42.com>
3 # Copyright 2017 Augie Fackler <raf@durin42.com>
4 # Copyright 2017 Sean Farley <sean@farley.io>
4 # Copyright 2017 Sean Farley <sean@farley.io>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 """ showing remotebookmarks and remotebranches in UI (EXPERIMENTAL)
9 """ showing remotebookmarks and remotebranches in UI (EXPERIMENTAL)
10
10
11 By default both remotebookmarks and remotebranches are turned on. Config knob to
11 By default both remotebookmarks and remotebranches are turned on. Config knob to
12 control the individually are as follows.
12 control the individually are as follows.
13
13
14 Config options to tweak the default behaviour:
14 Config options to tweak the default behaviour:
15
15
16 remotenames.bookmarks
16 remotenames.bookmarks
17 Boolean value to enable or disable showing of remotebookmarks (default: True)
17 Boolean value to enable or disable showing of remotebookmarks (default: True)
18
18
19 remotenames.branches
19 remotenames.branches
20 Boolean value to enable or disable showing of remotebranches (default: True)
20 Boolean value to enable or disable showing of remotebranches (default: True)
21
21
22 remotenames.hoistedpeer
22 remotenames.hoistedpeer
23 Name of the peer whose remotebookmarks should be hoisted into the top-level
23 Name of the peer whose remotebookmarks should be hoisted into the top-level
24 namespace (default: 'default')
24 namespace (default: 'default')
25 """
25 """
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 (
32 bin,
32 bin,
33 )
33 )
34 from mercurial import (
34 from mercurial import (
35 bookmarks,
35 bookmarks,
36 extensions,
36 extensions,
37 logexchange,
37 logexchange,
38 namespaces,
38 namespaces,
39 pycompat,
39 pycompat,
40 registrar,
40 registrar,
41 revsetlang,
41 revsetlang,
42 smartset,
42 smartset,
43 templateutil,
43 templateutil,
44 )
44 )
45
45
46 from mercurial.utils import (
46 from mercurial.utils import (
47 stringutil,
47 stringutil,
48 )
48 )
49
49
50 if pycompat.ispy3:
50 if pycompat.ispy3:
51 import collections.abc
51 import collections.abc
52 mutablemapping = collections.abc.MutableMapping
52 mutablemapping = collections.abc.MutableMapping
53 else:
53 else:
54 import collections
54 import collections
55 mutablemapping = collections.MutableMapping
55 mutablemapping = collections.MutableMapping
56
56
57 # 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
58 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
58 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
59 # 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
60 # leave the attribute unspecified.
60 # leave the attribute unspecified.
61 testedwith = 'ships-with-hg-core'
61 testedwith = 'ships-with-hg-core'
62
62
63 configtable = {}
63 configtable = {}
64 configitem = registrar.configitem(configtable)
64 configitem = registrar.configitem(configtable)
65 templatekeyword = registrar.templatekeyword()
65 templatekeyword = registrar.templatekeyword()
66 revsetpredicate = registrar.revsetpredicate()
66 revsetpredicate = registrar.revsetpredicate()
67
67
68 configitem('remotenames', 'bookmarks',
68 configitem('remotenames', 'bookmarks',
69 default=True,
69 default=True,
70 )
70 )
71 configitem('remotenames', 'branches',
71 configitem('remotenames', 'branches',
72 default=True,
72 default=True,
73 )
73 )
74 configitem('remotenames', 'hoistedpeer',
74 configitem('remotenames', 'hoistedpeer',
75 default='default',
75 default='default',
76 )
76 )
77
77
78 class lazyremotenamedict(mutablemapping):
78 class lazyremotenamedict(mutablemapping):
79 """
79 """
80 Read-only dict-like Class to lazily resolve remotename entries
80 Read-only dict-like Class to lazily resolve remotename entries
81
81
82 We are doing that because remotenames startup was slow.
82 We are doing that because remotenames startup was slow.
83 We lazily read the remotenames file once to figure out the potential entries
83 We lazily read the remotenames file once to figure out the potential entries
84 and store them in self.potentialentries. Then when asked to resolve an
84 and store them in self.potentialentries. Then when asked to resolve an
85 entry, if it is not in self.potentialentries, then it isn't there, if it
85 entry, if it is not in self.potentialentries, then it isn't there, if it
86 is in self.potentialentries we resolve it and store the result in
86 is in self.potentialentries we resolve it and store the result in
87 self.cache. We cannot be lazy is when asked all the entries (keys).
87 self.cache. We cannot be lazy is when asked all the entries (keys).
88 """
88 """
89 def __init__(self, kind, repo):
89 def __init__(self, kind, repo):
90 self.cache = {}
90 self.cache = {}
91 self.potentialentries = {}
91 self.potentialentries = {}
92 self._kind = kind # bookmarks or branches
92 self._kind = kind # bookmarks or branches
93 self._repo = repo
93 self._repo = repo
94 self.loaded = False
94 self.loaded = False
95
95
96 def _load(self):
96 def _load(self):
97 """ Read the remotenames file, store entries matching selected kind """
97 """ Read the remotenames file, store entries matching selected kind """
98 self.loaded = True
98 self.loaded = True
99 repo = self._repo
99 repo = self._repo
100 for node, rpath, rname in logexchange.readremotenamefile(repo,
100 for node, rpath, rname in logexchange.readremotenamefile(repo,
101 self._kind):
101 self._kind):
102 name = rpath + '/' + rname
102 name = rpath + '/' + rname
103 self.potentialentries[name] = (node, rpath, name)
103 self.potentialentries[name] = (node, rpath, name)
104
104
105 def _resolvedata(self, potentialentry):
105 def _resolvedata(self, potentialentry):
106 """ Check that the node for potentialentry exists and return it """
106 """ Check that the node for potentialentry exists and return it """
107 if not potentialentry in self.potentialentries:
107 if not potentialentry in self.potentialentries:
108 return None
108 return None
109 node, remote, name = self.potentialentries[potentialentry]
109 node, remote, name = self.potentialentries[potentialentry]
110 repo = self._repo
110 repo = self._repo
111 binnode = bin(node)
111 binnode = bin(node)
112 # if the node doesn't exist, skip it
112 # if the node doesn't exist, skip it
113 try:
113 try:
114 repo.changelog.rev(binnode)
114 repo.changelog.rev(binnode)
115 except LookupError:
115 except LookupError:
116 return None
116 return None
117 # Skip closed branches
117 # Skip closed branches
118 if (self._kind == 'branches' and repo[binnode].closesbranch()):
118 if (self._kind == 'branches' and repo[binnode].closesbranch()):
119 return None
119 return None
120 return [binnode]
120 return [binnode]
121
121
122 def __getitem__(self, key):
122 def __getitem__(self, key):
123 if not self.loaded:
123 if not self.loaded:
124 self._load()
124 self._load()
125 val = self._fetchandcache(key)
125 val = self._fetchandcache(key)
126 if val is not None:
126 if val is not None:
127 return val
127 return val
128 else:
128 else:
129 raise KeyError()
129 raise KeyError()
130
130
131 def __iter__(self):
131 def __iter__(self):
132 return iter(self.potentialentries)
132 return iter(self.potentialentries)
133
133
134 def __len__(self):
134 def __len__(self):
135 return len(self.potentialentries)
135 return len(self.potentialentries)
136
136
137 def __setitem__(self):
137 def __setitem__(self):
138 raise NotImplementedError
138 raise NotImplementedError
139
139
140 def __delitem__(self):
140 def __delitem__(self):
141 raise NotImplementedError
141 raise NotImplementedError
142
142
143 def _fetchandcache(self, key):
143 def _fetchandcache(self, key):
144 if key in self.cache:
144 if key in self.cache:
145 return self.cache[key]
145 return self.cache[key]
146 val = self._resolvedata(key)
146 val = self._resolvedata(key)
147 if val is not None:
147 if val is not None:
148 self.cache[key] = val
148 self.cache[key] = val
149 return val
149 return val
150 else:
150 else:
151 return None
151 return None
152
152
153 def keys(self):
153 def keys(self):
154 """ Get a list of bookmark or branch names """
154 """ Get a list of bookmark or branch names """
155 if not self.loaded:
155 if not self.loaded:
156 self._load()
156 self._load()
157 return self.potentialentries.keys()
157 return self.potentialentries.keys()
158
158
159 def iteritems(self):
159 def iteritems(self):
160 """ Iterate over (name, node) tuples """
160 """ Iterate over (name, node) tuples """
161
161
162 if not self.loaded:
162 if not self.loaded:
163 self._load()
163 self._load()
164
164
165 for k, vtup in self.potentialentries.iteritems():
165 for k, vtup in self.potentialentries.iteritems():
166 yield (k, [bin(vtup[0])])
166 yield (k, [bin(vtup[0])])
167
167
168 class remotenames(object):
168 class remotenames(object):
169 """
169 """
170 This class encapsulates all the remotenames state. It also contains
170 This class encapsulates all the remotenames state. It also contains
171 methods to access that state in convenient ways. Remotenames are lazy
171 methods to access that state in convenient ways. Remotenames are lazy
172 loaded. Whenever client code needs to ensure the freshest copy of
172 loaded. Whenever client code needs to ensure the freshest copy of
173 remotenames, use the `clearnames` method to force an eventual load.
173 remotenames, use the `clearnames` method to force an eventual load.
174 """
174 """
175
175
176 def __init__(self, repo, *args):
176 def __init__(self, repo, *args):
177 self._repo = repo
177 self._repo = repo
178 self.clearnames()
178 self.clearnames()
179
179
180 def clearnames(self):
180 def clearnames(self):
181 """ Clear all remote names state """
181 """ Clear all remote names state """
182 self.bookmarks = lazyremotenamedict("bookmarks", self._repo)
182 self.bookmarks = lazyremotenamedict("bookmarks", self._repo)
183 self.branches = lazyremotenamedict("branches", self._repo)
183 self.branches = lazyremotenamedict("branches", self._repo)
184 self._invalidatecache()
184 self._invalidatecache()
185
185
186 def _invalidatecache(self):
186 def _invalidatecache(self):
187 self._nodetobmarks = None
187 self._nodetobmarks = None
188 self._nodetobranch = None
188 self._nodetobranch = None
189 self._hoisttonodes = None
189 self._hoisttonodes = None
190 self._nodetohoists = None
190 self._nodetohoists = None
191
191
192 def bmarktonodes(self):
192 def bmarktonodes(self):
193 return self.bookmarks
193 return self.bookmarks
194
194
195 def nodetobmarks(self):
195 def nodetobmarks(self):
196 if not self._nodetobmarks:
196 if not self._nodetobmarks:
197 bmarktonodes = self.bmarktonodes()
197 bmarktonodes = self.bmarktonodes()
198 self._nodetobmarks = {}
198 self._nodetobmarks = {}
199 for name, node in bmarktonodes.iteritems():
199 for name, node in bmarktonodes.iteritems():
200 self._nodetobmarks.setdefault(node[0], []).append(name)
200 self._nodetobmarks.setdefault(node[0], []).append(name)
201 return self._nodetobmarks
201 return self._nodetobmarks
202
202
203 def branchtonodes(self):
203 def branchtonodes(self):
204 return self.branches
204 return self.branches
205
205
206 def nodetobranch(self):
206 def nodetobranch(self):
207 if not self._nodetobranch:
207 if not self._nodetobranch:
208 branchtonodes = self.branchtonodes()
208 branchtonodes = self.branchtonodes()
209 self._nodetobranch = {}
209 self._nodetobranch = {}
210 for name, nodes in branchtonodes.iteritems():
210 for name, nodes in branchtonodes.iteritems():
211 for node in nodes:
211 for node in nodes:
212 self._nodetobranch.setdefault(node, []).append(name)
212 self._nodetobranch.setdefault(node, []).append(name)
213 return self._nodetobranch
213 return self._nodetobranch
214
214
215 def hoisttonodes(self, hoist):
215 def hoisttonodes(self, hoist):
216 if not self._hoisttonodes:
216 if not self._hoisttonodes:
217 marktonodes = self.bmarktonodes()
217 marktonodes = self.bmarktonodes()
218 self._hoisttonodes = {}
218 self._hoisttonodes = {}
219 hoist += '/'
219 hoist += '/'
220 for name, node in marktonodes.iteritems():
220 for name, node in marktonodes.iteritems():
221 if name.startswith(hoist):
221 if name.startswith(hoist):
222 name = name[len(hoist):]
222 name = name[len(hoist):]
223 self._hoisttonodes[name] = node
223 self._hoisttonodes[name] = node
224 return self._hoisttonodes
224 return self._hoisttonodes
225
225
226 def nodetohoists(self, hoist):
226 def nodetohoists(self, hoist):
227 if not self._nodetohoists:
227 if not self._nodetohoists:
228 marktonodes = self.bmarktonodes()
228 marktonodes = self.bmarktonodes()
229 self._nodetohoists = {}
229 self._nodetohoists = {}
230 hoist += '/'
230 hoist += '/'
231 for name, node in marktonodes.iteritems():
231 for name, node in marktonodes.iteritems():
232 if name.startswith(hoist):
232 if name.startswith(hoist):
233 name = name[len(hoist):]
233 name = name[len(hoist):]
234 self._nodetohoists.setdefault(node[0], []).append(name)
234 self._nodetohoists.setdefault(node[0], []).append(name)
235 return self._nodetohoists
235 return self._nodetohoists
236
236
237 def wrapprintbookmarks(orig, ui, repo, fm, bmarks):
237 def wrapprintbookmarks(orig, ui, repo, fm, bmarks):
238 if 'remotebookmarks' not in repo.names:
238 if 'remotebookmarks' not in repo.names:
239 return
239 return
240 ns = repo.names['remotebookmarks']
240 ns = repo.names['remotebookmarks']
241
241
242 for name in ns.listnames(repo):
242 for name in ns.listnames(repo):
243 nodes = ns.nodes(repo, name)
243 nodes = ns.nodes(repo, name)
244 if not nodes:
244 if not nodes:
245 continue
245 continue
246 node = nodes[0]
246 node = nodes[0]
247
247
248 bmarks[name] = (node, ' ', '')
248 bmarks[name] = (node, ' ', '')
249
249
250 return orig(ui, repo, fm, bmarks)
250 return orig(ui, repo, fm, bmarks)
251
251
252 def extsetup(ui):
252 def extsetup(ui):
253 extensions.wrapfunction(bookmarks, '_printbookmarks', wrapprintbookmarks)
253 extensions.wrapfunction(bookmarks, '_printbookmarks', wrapprintbookmarks)
254
254
255 def reposetup(ui, repo):
255 def reposetup(ui, repo):
256
256
257 # set the config option to store remotenames
257 # set the config option to store remotenames
258 repo.ui.setconfig('experimental', 'remotenames', True, 'remotenames-ext')
258 repo.ui.setconfig('experimental', 'remotenames', True, 'remotenames-ext')
259
259
260 if not repo.local():
260 if not repo.local():
261 return
261 return
262
262
263 repo._remotenames = remotenames(repo)
263 repo._remotenames = remotenames(repo)
264 ns = namespaces.namespace
264 ns = namespaces.namespace
265
265
266 if ui.configbool('remotenames', 'bookmarks'):
266 if ui.configbool('remotenames', 'bookmarks'):
267 remotebookmarkns = ns(
267 remotebookmarkns = ns(
268 'remotebookmarks',
268 'remotebookmarks',
269 templatename='remotebookmarks',
269 templatename='remotebookmarks',
270 colorname='remotebookmark',
270 colorname='remotebookmark',
271 logfmt='remote bookmark: %s\n',
271 logfmt='remote bookmark: %s\n',
272 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(),
272 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(),
273 namemap=lambda repo, name:
273 namemap=lambda repo, name:
274 repo._remotenames.bmarktonodes().get(name, []),
274 repo._remotenames.bmarktonodes().get(name, []),
275 nodemap=lambda repo, node:
275 nodemap=lambda repo, node:
276 repo._remotenames.nodetobmarks().get(node, []))
276 repo._remotenames.nodetobmarks().get(node, []))
277 repo.names.addnamespace(remotebookmarkns)
277 repo.names.addnamespace(remotebookmarkns)
278
278
279 # hoisting only works if there are remote bookmarks
279 # hoisting only works if there are remote bookmarks
280 hoist = ui.config('remotenames', 'hoistedpeer')
280 hoist = ui.config('remotenames', 'hoistedpeer')
281 if hoist:
281 if hoist:
282 hoistednamens = ns(
282 hoistednamens = ns(
283 'hoistednames',
283 'hoistednames',
284 templatename='hoistednames',
284 templatename='hoistednames',
285 colorname='hoistedname',
285 colorname='hoistedname',
286 logfmt='hoisted name: %s\n',
286 logfmt='hoisted name: %s\n',
287 listnames = lambda repo:
287 listnames = lambda repo:
288 repo._remotenames.hoisttonodes(hoist).keys(),
288 repo._remotenames.hoisttonodes(hoist).keys(),
289 namemap = lambda repo, name:
289 namemap = lambda repo, name:
290 repo._remotenames.hoisttonodes(hoist).get(name, []),
290 repo._remotenames.hoisttonodes(hoist).get(name, []),
291 nodemap = lambda repo, node:
291 nodemap = lambda repo, node:
292 repo._remotenames.nodetohoists(hoist).get(node, []))
292 repo._remotenames.nodetohoists(hoist).get(node, []))
293 repo.names.addnamespace(hoistednamens)
293 repo.names.addnamespace(hoistednamens)
294
294
295 if ui.configbool('remotenames', 'branches'):
295 if ui.configbool('remotenames', 'branches'):
296 remotebranchns = ns(
296 remotebranchns = ns(
297 'remotebranches',
297 'remotebranches',
298 templatename='remotebranches',
298 templatename='remotebranches',
299 colorname='remotebranch',
299 colorname='remotebranch',
300 logfmt='remote branch: %s\n',
300 logfmt='remote branch: %s\n',
301 listnames = lambda repo: repo._remotenames.branchtonodes().keys(),
301 listnames = lambda repo: repo._remotenames.branchtonodes().keys(),
302 namemap = lambda repo, name:
302 namemap = lambda repo, name:
303 repo._remotenames.branchtonodes().get(name, []),
303 repo._remotenames.branchtonodes().get(name, []),
304 nodemap = lambda repo, node:
304 nodemap = lambda repo, node:
305 repo._remotenames.nodetobranch().get(node, []))
305 repo._remotenames.nodetobranch().get(node, []))
306 repo.names.addnamespace(remotebranchns)
306 repo.names.addnamespace(remotebranchns)
307
307
308 @templatekeyword('remotenames', requires={'repo', 'ctx'})
308 @templatekeyword('remotenames', requires={'repo', 'ctx'})
309 def remotenameskw(context, mapping):
309 def remotenameskw(context, mapping):
310 """List of strings. Remote names associated with the changeset."""
310 """List of strings. Remote names associated with the changeset."""
311 repo = context.resource(mapping, 'repo')
311 repo = context.resource(mapping, 'repo')
312 ctx = context.resource(mapping, 'ctx')
312 ctx = context.resource(mapping, 'ctx')
313
313
314 remotenames = []
314 remotenames = []
315 if 'remotebookmarks' in repo.names:
315 if 'remotebookmarks' in repo.names:
316 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node())
316 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node())
317
317
318 if 'remotebranches' in repo.names:
318 if 'remotebranches' in repo.names:
319 remotenames += repo.names['remotebranches'].names(repo, ctx.node())
319 remotenames += repo.names['remotebranches'].names(repo, ctx.node())
320
320
321 return templateutil.compatlist(context, mapping, 'remotename', remotenames,
321 return templateutil.compatlist(context, mapping, 'remotename', remotenames,
322 plural='remotenames')
322 plural='remotenames')
323
323
324 @templatekeyword('remotebookmarks', requires={'repo', 'ctx'})
324 @templatekeyword('remotebookmarks', requires={'repo', 'ctx'})
325 def remotebookmarkskw(context, mapping):
325 def remotebookmarkskw(context, mapping):
326 """List of strings. Remote bookmarks associated with the changeset."""
326 """List of strings. Remote bookmarks associated with the changeset."""
327 repo = context.resource(mapping, 'repo')
327 repo = context.resource(mapping, 'repo')
328 ctx = context.resource(mapping, 'ctx')
328 ctx = context.resource(mapping, 'ctx')
329
329
330 remotebmarks = []
330 remotebmarks = []
331 if 'remotebookmarks' in repo.names:
331 if 'remotebookmarks' in repo.names:
332 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node())
332 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node())
333
333
334 return templateutil.compatlist(context, mapping, 'remotebookmark',
334 return templateutil.compatlist(context, mapping, 'remotebookmark',
335 remotebmarks, plural='remotebookmarks')
335 remotebmarks, plural='remotebookmarks')
336
336
337 @templatekeyword('remotebranches', requires={'repo', 'ctx'})
337 @templatekeyword('remotebranches', requires={'repo', 'ctx'})
338 def remotebrancheskw(context, mapping):
338 def remotebrancheskw(context, mapping):
339 """List of strings. Remote branches associated with the changeset."""
339 """List of strings. Remote branches associated with the changeset."""
340 repo = context.resource(mapping, 'repo')
340 repo = context.resource(mapping, 'repo')
341 ctx = context.resource(mapping, 'ctx')
341 ctx = context.resource(mapping, 'ctx')
342
342
343 remotebranches = []
343 remotebranches = []
344 if 'remotebranches' in repo.names:
344 if 'remotebranches' in repo.names:
345 remotebranches = repo.names['remotebranches'].names(repo, ctx.node())
345 remotebranches = repo.names['remotebranches'].names(repo, ctx.node())
346
346
347 return templateutil.compatlist(context, mapping, 'remotebranch',
347 return templateutil.compatlist(context, mapping, 'remotebranch',
348 remotebranches, plural='remotebranches')
348 remotebranches, plural='remotebranches')
349
349
350 def _revsetutil(repo, subset, x, rtypes, matcher):
350 def _revsetutil(repo, subset, x, rtypes):
351 """utility function to return a set of revs based on the rtypes"""
351 """utility function to return a set of revs based on the rtypes"""
352 args = revsetlang.getargs(x, 0, 1, _('only one argument accepted'))
353 if args:
354 kind, pattern, matcher = stringutil.stringmatcher(
355 revsetlang.getstring(args[0], _('argument must be a string')))
356 else:
357 matcher = lambda a: True
352
358
353 revs = set()
359 revs = set()
354 cl = repo.changelog
360 cl = repo.changelog
355 for rtype in rtypes:
361 for rtype in rtypes:
356 if rtype in repo.names:
362 if rtype in repo.names:
357 ns = repo.names[rtype]
363 ns = repo.names[rtype]
358 for name in ns.listnames(repo):
364 for name in ns.listnames(repo):
359 if not matcher(name):
365 if not matcher(name):
360 continue
366 continue
361 revs.update(ns.nodes(repo, name))
367 revs.update(ns.nodes(repo, name))
362
368
363 results = (cl.rev(n) for n in revs if cl.hasnode(n))
369 results = (cl.rev(n) for n in revs if cl.hasnode(n))
364 return subset & smartset.baseset(sorted(results))
370 return subset & smartset.baseset(sorted(results))
365
371
366 def _parseargs(x):
367 """parses the argument passed in revsets
368
369 Returns a matcher for the passed pattern.
370 """
371 args = revsetlang.getargs(x, 0, 1, _('only one argument accepted'))
372 for arg in args:
373 kind, pattern, matcher = stringutil.stringmatcher(
374 revsetlang.getstring(arg, _('argument must be a string')))
375 return matcher
376 return lambda a: True
377
378 @revsetpredicate('remotenames([name])')
372 @revsetpredicate('remotenames([name])')
379 def remotenamesrevset(repo, subset, x):
373 def remotenamesrevset(repo, subset, x):
380 """All changesets which have a remotename on them. If `name` is
374 """All changesets which have a remotename on them. If `name` is
381 specified, only remotenames of matching remote paths are considered.
375 specified, only remotenames of matching remote paths are considered.
382
376
383 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
377 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
384 """
378 """
385 return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches'),
379 return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches'))
386 _parseargs(x))
387
380
388 @revsetpredicate('remotebranches([name])')
381 @revsetpredicate('remotebranches([name])')
389 def remotebranchesrevset(repo, subset, x):
382 def remotebranchesrevset(repo, subset, x):
390 """All changesets which are branch heads on remotes. If `name` is
383 """All changesets which are branch heads on remotes. If `name` is
391 specified, only remotenames of matching remote paths are considered.
384 specified, only remotenames of matching remote paths are considered.
392
385
393 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
386 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
394 """
387 """
395
388 return _revsetutil(repo, subset, x, ('remotebranches',))
396 args = _parseargs(x)
397 return _revsetutil(repo, subset, x, ('remotebranches',), args)
398
389
399 @revsetpredicate('remotebookmarks([name])')
390 @revsetpredicate('remotebookmarks([name])')
400 def remotebmarksrevset(repo, subset, x):
391 def remotebmarksrevset(repo, subset, x):
401 """All changesets which have bookmarks on remotes. If `name` is
392 """All changesets which have bookmarks on remotes. If `name` is
402 specified, only remotenames of matching remote paths are considered.
393 specified, only remotenames of matching remote paths are considered.
403
394
404 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
395 Pattern matching is supported for `name`. See :hg:`help revisions.patterns`.
405 """
396 """
406
397 return _revsetutil(repo, subset, x, ('remotebookmarks',))
407 args = _parseargs(x)
408 return _revsetutil(repo, subset, x, ('remotebookmarks',), args)
General Comments 0
You need to be logged in to leave comments. Login now