##// END OF EJS Templates
remotenames: drop redundant templatekw names from help text...
Yuya Nishihara -
r36458:bb852a52 default
parent child Browse files
Show More
@@ -1,307 +1,301 b''
1 1 # remotenames.py - extension to display remotenames
2 2 #
3 3 # Copyright 2017 Augie Fackler <raf@durin42.com>
4 4 # Copyright 2017 Sean Farley <sean@farley.io>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 """ showing remotebookmarks and remotebranches in UI
10 10
11 11 By default both remotebookmarks and remotebranches are turned on. Config knob to
12 12 control the individually are as follows.
13 13
14 14 Config options to tweak the default behaviour:
15 15
16 16 remotenames.bookmarks
17 17 Boolean value to enable or disable showing of remotebookmarks
18 18
19 19 remotenames.branches
20 20 Boolean value to enable or disable showing of remotebranches
21 21 """
22 22
23 23 from __future__ import absolute_import
24 24
25 25 import collections
26 26
27 27 from mercurial.i18n import _
28 28
29 29 from mercurial.node import (
30 30 bin,
31 31 )
32 32 from mercurial import (
33 33 logexchange,
34 34 namespaces,
35 35 pycompat,
36 36 registrar,
37 37 revsetlang,
38 38 smartset,
39 39 templatekw,
40 40 )
41 41
42 42 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
43 43 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
44 44 # be specifying the version(s) of Mercurial they are tested with, or
45 45 # leave the attribute unspecified.
46 46 testedwith = 'ships-with-hg-core'
47 47
48 48 configtable = {}
49 49 configitem = registrar.configitem(configtable)
50 50 templatekeyword = registrar.templatekeyword()
51 51 revsetpredicate = registrar.revsetpredicate()
52 52
53 53 configitem('remotenames', 'bookmarks',
54 54 default=True,
55 55 )
56 56 configitem('remotenames', 'branches',
57 57 default=True,
58 58 )
59 59
60 60 class lazyremotenamedict(collections.MutableMapping):
61 61 """
62 62 Read-only dict-like Class to lazily resolve remotename entries
63 63
64 64 We are doing that because remotenames startup was slow.
65 65 We lazily read the remotenames file once to figure out the potential entries
66 66 and store them in self.potentialentries. Then when asked to resolve an
67 67 entry, if it is not in self.potentialentries, then it isn't there, if it
68 68 is in self.potentialentries we resolve it and store the result in
69 69 self.cache. We cannot be lazy is when asked all the entries (keys).
70 70 """
71 71 def __init__(self, kind, repo):
72 72 self.cache = {}
73 73 self.potentialentries = {}
74 74 self._kind = kind # bookmarks or branches
75 75 self._repo = repo
76 76 self.loaded = False
77 77
78 78 def _load(self):
79 79 """ Read the remotenames file, store entries matching selected kind """
80 80 self.loaded = True
81 81 repo = self._repo
82 82 for node, rpath, rname in logexchange.readremotenamefile(repo,
83 83 self._kind):
84 84 name = rpath + '/' + rname
85 85 self.potentialentries[name] = (node, rpath, name)
86 86
87 87 def _resolvedata(self, potentialentry):
88 88 """ Check that the node for potentialentry exists and return it """
89 89 if not potentialentry in self.potentialentries:
90 90 return None
91 91 node, remote, name = self.potentialentries[potentialentry]
92 92 repo = self._repo
93 93 binnode = bin(node)
94 94 # if the node doesn't exist, skip it
95 95 try:
96 96 repo.changelog.rev(binnode)
97 97 except LookupError:
98 98 return None
99 99 # Skip closed branches
100 100 if (self._kind == 'branches' and repo[binnode].closesbranch()):
101 101 return None
102 102 return [binnode]
103 103
104 104 def __getitem__(self, key):
105 105 if not self.loaded:
106 106 self._load()
107 107 val = self._fetchandcache(key)
108 108 if val is not None:
109 109 return val
110 110 else:
111 111 raise KeyError()
112 112
113 113 def __iter__(self):
114 114 return iter(self.potentialentries)
115 115
116 116 def __len__(self):
117 117 return len(self.potentialentries)
118 118
119 119 def __setitem__(self):
120 120 raise NotImplementedError
121 121
122 122 def __delitem__(self):
123 123 raise NotImplementedError
124 124
125 125 def _fetchandcache(self, key):
126 126 if key in self.cache:
127 127 return self.cache[key]
128 128 val = self._resolvedata(key)
129 129 if val is not None:
130 130 self.cache[key] = val
131 131 return val
132 132 else:
133 133 return None
134 134
135 135 def keys(self):
136 136 """ Get a list of bookmark or branch names """
137 137 if not self.loaded:
138 138 self._load()
139 139 return self.potentialentries.keys()
140 140
141 141 def iteritems(self):
142 142 """ Iterate over (name, node) tuples """
143 143
144 144 if not self.loaded:
145 145 self._load()
146 146
147 147 for k, vtup in self.potentialentries.iteritems():
148 148 yield (k, [bin(vtup[0])])
149 149
150 150 class remotenames(dict):
151 151 """
152 152 This class encapsulates all the remotenames state. It also contains
153 153 methods to access that state in convenient ways. Remotenames are lazy
154 154 loaded. Whenever client code needs to ensure the freshest copy of
155 155 remotenames, use the `clearnames` method to force an eventual load.
156 156 """
157 157
158 158 def __init__(self, repo, *args):
159 159 dict.__init__(self, *args)
160 160 self._repo = repo
161 161 self.clearnames()
162 162
163 163 def clearnames(self):
164 164 """ Clear all remote names state """
165 165 self['bookmarks'] = lazyremotenamedict("bookmarks", self._repo)
166 166 self['branches'] = lazyremotenamedict("branches", self._repo)
167 167 self._invalidatecache()
168 168
169 169 def _invalidatecache(self):
170 170 self._nodetobmarks = None
171 171 self._nodetobranch = None
172 172
173 173 def bmarktonodes(self):
174 174 return self['bookmarks']
175 175
176 176 def nodetobmarks(self):
177 177 if not self._nodetobmarks:
178 178 bmarktonodes = self.bmarktonodes()
179 179 self._nodetobmarks = {}
180 180 for name, node in bmarktonodes.iteritems():
181 181 self._nodetobmarks.setdefault(node[0], []).append(name)
182 182 return self._nodetobmarks
183 183
184 184 def branchtonodes(self):
185 185 return self['branches']
186 186
187 187 def nodetobranch(self):
188 188 if not self._nodetobranch:
189 189 branchtonodes = self.branchtonodes()
190 190 self._nodetobranch = {}
191 191 for name, nodes in branchtonodes.iteritems():
192 192 for node in nodes:
193 193 self._nodetobranch.setdefault(node, []).append(name)
194 194 return self._nodetobranch
195 195
196 196 def reposetup(ui, repo):
197 197 if not repo.local():
198 198 return
199 199
200 200 repo._remotenames = remotenames(repo)
201 201 ns = namespaces.namespace
202 202
203 203 if ui.configbool('remotenames', 'bookmarks'):
204 204 remotebookmarkns = ns(
205 205 'remotebookmarks',
206 206 templatename='remotebookmarks',
207 207 colorname='remotebookmark',
208 208 logfmt='remote bookmark: %s\n',
209 209 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(),
210 210 namemap=lambda repo, name:
211 211 repo._remotenames.bmarktonodes().get(name, []),
212 212 nodemap=lambda repo, node:
213 213 repo._remotenames.nodetobmarks().get(node, []))
214 214 repo.names.addnamespace(remotebookmarkns)
215 215
216 216 if ui.configbool('remotenames', 'branches'):
217 217 remotebranchns = ns(
218 218 'remotebranches',
219 219 templatename='remotebranches',
220 220 colorname='remotebranch',
221 221 logfmt='remote branch: %s\n',
222 222 listnames = lambda repo: repo._remotenames.branchtonodes().keys(),
223 223 namemap = lambda repo, name:
224 224 repo._remotenames.branchtonodes().get(name, []),
225 225 nodemap = lambda repo, node:
226 226 repo._remotenames.nodetobranch().get(node, []))
227 227 repo.names.addnamespace(remotebranchns)
228 228
229 229 @templatekeyword('remotenames')
230 230 def remotenameskw(**args):
231 """:remotenames: List of strings. List of remote names associated with the
232 changeset.
233 """
231 """List of strings. Remote names associated with the changeset."""
234 232 args = pycompat.byteskwargs(args)
235 233 repo, ctx = args['repo'], args['ctx']
236 234
237 235 remotenames = []
238 236 if 'remotebookmarks' in repo.names:
239 237 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node())
240 238
241 239 if 'remotebranches' in repo.names:
242 240 remotenames += repo.names['remotebranches'].names(repo, ctx.node())
243 241
244 242 return templatekw.showlist('remotename', remotenames, args,
245 243 plural='remotenames')
246 244
247 245 @templatekeyword('remotebookmarks')
248 246 def remotebookmarkskw(**args):
249 """:remotebookmarks: List of strings. List of remote bookmarks associated
250 with the changeset.
251 """
247 """List of strings. Remote bookmarks associated with the changeset."""
252 248 args = pycompat.byteskwargs(args)
253 249 repo, ctx = args['repo'], args['ctx']
254 250
255 251 remotebmarks = []
256 252 if 'remotebookmarks' in repo.names:
257 253 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node())
258 254
259 255 return templatekw.showlist('remotebookmark', remotebmarks, args,
260 256 plural='remotebookmarks')
261 257
262 258 @templatekeyword('remotebranches')
263 259 def remotebrancheskw(**args):
264 """:remotebranches: List of strings. List of remote branches associated
265 with the changeset.
266 """
260 """List of strings. Remote branches associated with the changeset."""
267 261 args = pycompat.byteskwargs(args)
268 262 repo, ctx = args['repo'], args['ctx']
269 263
270 264 remotebranches = []
271 265 if 'remotebranches' in repo.names:
272 266 remotebranches = repo.names['remotebranches'].names(repo, ctx.node())
273 267
274 268 return templatekw.showlist('remotebranch', remotebranches, args,
275 269 plural='remotebranches')
276 270
277 271 def _revsetutil(repo, subset, x, rtypes):
278 272 """utility function to return a set of revs based on the rtypes"""
279 273
280 274 revs = set()
281 275 cl = repo.changelog
282 276 for rtype in rtypes:
283 277 if rtype in repo.names:
284 278 ns = repo.names[rtype]
285 279 for name in ns.listnames(repo):
286 280 revs.update(ns.nodes(repo, name))
287 281
288 282 results = (cl.rev(n) for n in revs if cl.hasnode(n))
289 283 return subset & smartset.baseset(sorted(results))
290 284
291 285 @revsetpredicate('remotenames()')
292 286 def remotenamesrevset(repo, subset, x):
293 287 """All changesets which have a remotename on them."""
294 288 revsetlang.getargs(x, 0, 0, _("remotenames takes no arguments"))
295 289 return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches'))
296 290
297 291 @revsetpredicate('remotebranches()')
298 292 def remotebranchesrevset(repo, subset, x):
299 293 """All changesets which are branch heads on remotes."""
300 294 revsetlang.getargs(x, 0, 0, _("remotebranches takes no arguments"))
301 295 return _revsetutil(repo, subset, x, ('remotebranches',))
302 296
303 297 @revsetpredicate('remotebookmarks()')
304 298 def remotebmarksrevset(repo, subset, x):
305 299 """All changesets which have bookmarks on remotes."""
306 300 revsetlang.getargs(x, 0, 0, _("remotebookmarks takes no arguments"))
307 301 return _revsetutil(repo, subset, x, ('remotebookmarks',))
General Comments 0
You need to be logged in to leave comments. Login now