##// END OF EJS Templates
remotenames: add functionality to hoist remotebookmarks...
Pulkit Goyal -
r37107:9938992c default
parent child Browse files
Show More
@@ -1,305 +1,352 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
9 """ showing remotebookmarks and remotebranches in UI
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
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
20 Boolean value to enable or disable showing of remotebranches (default: True)
21
22 remotenames.hoistedpeer
23 Name of the peer whose remotebookmarks should be hoisted into the top-level
24 namespace (default: 'default')
21 """
25 """
22
26
23 from __future__ import absolute_import
27 from __future__ import absolute_import
24
28
25 from mercurial.i18n import _
29 from mercurial.i18n import _
26
30
27 from mercurial.node import (
31 from mercurial.node import (
28 bin,
32 bin,
29 )
33 )
30 from mercurial import (
34 from mercurial import (
31 logexchange,
35 logexchange,
32 namespaces,
36 namespaces,
33 pycompat,
37 pycompat,
34 registrar,
38 registrar,
35 revsetlang,
39 revsetlang,
36 smartset,
40 smartset,
37 templateutil,
41 templateutil,
38 )
42 )
39
43
40 if pycompat.ispy3:
44 if pycompat.ispy3:
41 import collections.abc
45 import collections.abc
42 mutablemapping = collections.abc.MutableMapping
46 mutablemapping = collections.abc.MutableMapping
43 else:
47 else:
44 import collections
48 import collections
45 mutablemapping = collections.MutableMapping
49 mutablemapping = collections.MutableMapping
46
50
47 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
51 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
48 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
52 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
49 # be specifying the version(s) of Mercurial they are tested with, or
53 # be specifying the version(s) of Mercurial they are tested with, or
50 # leave the attribute unspecified.
54 # leave the attribute unspecified.
51 testedwith = 'ships-with-hg-core'
55 testedwith = 'ships-with-hg-core'
52
56
53 configtable = {}
57 configtable = {}
54 configitem = registrar.configitem(configtable)
58 configitem = registrar.configitem(configtable)
55 templatekeyword = registrar.templatekeyword()
59 templatekeyword = registrar.templatekeyword()
56 revsetpredicate = registrar.revsetpredicate()
60 revsetpredicate = registrar.revsetpredicate()
57
61
58 configitem('remotenames', 'bookmarks',
62 configitem('remotenames', 'bookmarks',
59 default=True,
63 default=True,
60 )
64 )
61 configitem('remotenames', 'branches',
65 configitem('remotenames', 'branches',
62 default=True,
66 default=True,
63 )
67 )
68 configitem('remotenames', 'hoistedpeer',
69 default='default',
70 )
64
71
65 class lazyremotenamedict(mutablemapping):
72 class lazyremotenamedict(mutablemapping):
66 """
73 """
67 Read-only dict-like Class to lazily resolve remotename entries
74 Read-only dict-like Class to lazily resolve remotename entries
68
75
69 We are doing that because remotenames startup was slow.
76 We are doing that because remotenames startup was slow.
70 We lazily read the remotenames file once to figure out the potential entries
77 We lazily read the remotenames file once to figure out the potential entries
71 and store them in self.potentialentries. Then when asked to resolve an
78 and store them in self.potentialentries. Then when asked to resolve an
72 entry, if it is not in self.potentialentries, then it isn't there, if it
79 entry, if it is not in self.potentialentries, then it isn't there, if it
73 is in self.potentialentries we resolve it and store the result in
80 is in self.potentialentries we resolve it and store the result in
74 self.cache. We cannot be lazy is when asked all the entries (keys).
81 self.cache. We cannot be lazy is when asked all the entries (keys).
75 """
82 """
76 def __init__(self, kind, repo):
83 def __init__(self, kind, repo):
77 self.cache = {}
84 self.cache = {}
78 self.potentialentries = {}
85 self.potentialentries = {}
79 self._kind = kind # bookmarks or branches
86 self._kind = kind # bookmarks or branches
80 self._repo = repo
87 self._repo = repo
81 self.loaded = False
88 self.loaded = False
82
89
83 def _load(self):
90 def _load(self):
84 """ Read the remotenames file, store entries matching selected kind """
91 """ Read the remotenames file, store entries matching selected kind """
85 self.loaded = True
92 self.loaded = True
86 repo = self._repo
93 repo = self._repo
87 for node, rpath, rname in logexchange.readremotenamefile(repo,
94 for node, rpath, rname in logexchange.readremotenamefile(repo,
88 self._kind):
95 self._kind):
89 name = rpath + '/' + rname
96 name = rpath + '/' + rname
90 self.potentialentries[name] = (node, rpath, name)
97 self.potentialentries[name] = (node, rpath, name)
91
98
92 def _resolvedata(self, potentialentry):
99 def _resolvedata(self, potentialentry):
93 """ Check that the node for potentialentry exists and return it """
100 """ Check that the node for potentialentry exists and return it """
94 if not potentialentry in self.potentialentries:
101 if not potentialentry in self.potentialentries:
95 return None
102 return None
96 node, remote, name = self.potentialentries[potentialentry]
103 node, remote, name = self.potentialentries[potentialentry]
97 repo = self._repo
104 repo = self._repo
98 binnode = bin(node)
105 binnode = bin(node)
99 # if the node doesn't exist, skip it
106 # if the node doesn't exist, skip it
100 try:
107 try:
101 repo.changelog.rev(binnode)
108 repo.changelog.rev(binnode)
102 except LookupError:
109 except LookupError:
103 return None
110 return None
104 # Skip closed branches
111 # Skip closed branches
105 if (self._kind == 'branches' and repo[binnode].closesbranch()):
112 if (self._kind == 'branches' and repo[binnode].closesbranch()):
106 return None
113 return None
107 return [binnode]
114 return [binnode]
108
115
109 def __getitem__(self, key):
116 def __getitem__(self, key):
110 if not self.loaded:
117 if not self.loaded:
111 self._load()
118 self._load()
112 val = self._fetchandcache(key)
119 val = self._fetchandcache(key)
113 if val is not None:
120 if val is not None:
114 return val
121 return val
115 else:
122 else:
116 raise KeyError()
123 raise KeyError()
117
124
118 def __iter__(self):
125 def __iter__(self):
119 return iter(self.potentialentries)
126 return iter(self.potentialentries)
120
127
121 def __len__(self):
128 def __len__(self):
122 return len(self.potentialentries)
129 return len(self.potentialentries)
123
130
124 def __setitem__(self):
131 def __setitem__(self):
125 raise NotImplementedError
132 raise NotImplementedError
126
133
127 def __delitem__(self):
134 def __delitem__(self):
128 raise NotImplementedError
135 raise NotImplementedError
129
136
130 def _fetchandcache(self, key):
137 def _fetchandcache(self, key):
131 if key in self.cache:
138 if key in self.cache:
132 return self.cache[key]
139 return self.cache[key]
133 val = self._resolvedata(key)
140 val = self._resolvedata(key)
134 if val is not None:
141 if val is not None:
135 self.cache[key] = val
142 self.cache[key] = val
136 return val
143 return val
137 else:
144 else:
138 return None
145 return None
139
146
140 def keys(self):
147 def keys(self):
141 """ Get a list of bookmark or branch names """
148 """ Get a list of bookmark or branch names """
142 if not self.loaded:
149 if not self.loaded:
143 self._load()
150 self._load()
144 return self.potentialentries.keys()
151 return self.potentialentries.keys()
145
152
146 def iteritems(self):
153 def iteritems(self):
147 """ Iterate over (name, node) tuples """
154 """ Iterate over (name, node) tuples """
148
155
149 if not self.loaded:
156 if not self.loaded:
150 self._load()
157 self._load()
151
158
152 for k, vtup in self.potentialentries.iteritems():
159 for k, vtup in self.potentialentries.iteritems():
153 yield (k, [bin(vtup[0])])
160 yield (k, [bin(vtup[0])])
154
161
155 class remotenames(object):
162 class remotenames(object):
156 """
163 """
157 This class encapsulates all the remotenames state. It also contains
164 This class encapsulates all the remotenames state. It also contains
158 methods to access that state in convenient ways. Remotenames are lazy
165 methods to access that state in convenient ways. Remotenames are lazy
159 loaded. Whenever client code needs to ensure the freshest copy of
166 loaded. Whenever client code needs to ensure the freshest copy of
160 remotenames, use the `clearnames` method to force an eventual load.
167 remotenames, use the `clearnames` method to force an eventual load.
161 """
168 """
162
169
163 def __init__(self, repo, *args):
170 def __init__(self, repo, *args):
164 self._repo = repo
171 self._repo = repo
165 self.clearnames()
172 self.clearnames()
166
173
167 def clearnames(self):
174 def clearnames(self):
168 """ Clear all remote names state """
175 """ Clear all remote names state """
169 self.bookmarks = lazyremotenamedict("bookmarks", self._repo)
176 self.bookmarks = lazyremotenamedict("bookmarks", self._repo)
170 self.branches = lazyremotenamedict("branches", self._repo)
177 self.branches = lazyremotenamedict("branches", self._repo)
171 self._invalidatecache()
178 self._invalidatecache()
172
179
173 def _invalidatecache(self):
180 def _invalidatecache(self):
174 self._nodetobmarks = None
181 self._nodetobmarks = None
175 self._nodetobranch = None
182 self._nodetobranch = None
183 self._hoisttonodes = None
184 self._nodetohoists = None
176
185
177 def bmarktonodes(self):
186 def bmarktonodes(self):
178 return self.bookmarks
187 return self.bookmarks
179
188
180 def nodetobmarks(self):
189 def nodetobmarks(self):
181 if not self._nodetobmarks:
190 if not self._nodetobmarks:
182 bmarktonodes = self.bmarktonodes()
191 bmarktonodes = self.bmarktonodes()
183 self._nodetobmarks = {}
192 self._nodetobmarks = {}
184 for name, node in bmarktonodes.iteritems():
193 for name, node in bmarktonodes.iteritems():
185 self._nodetobmarks.setdefault(node[0], []).append(name)
194 self._nodetobmarks.setdefault(node[0], []).append(name)
186 return self._nodetobmarks
195 return self._nodetobmarks
187
196
188 def branchtonodes(self):
197 def branchtonodes(self):
189 return self.branches
198 return self.branches
190
199
191 def nodetobranch(self):
200 def nodetobranch(self):
192 if not self._nodetobranch:
201 if not self._nodetobranch:
193 branchtonodes = self.branchtonodes()
202 branchtonodes = self.branchtonodes()
194 self._nodetobranch = {}
203 self._nodetobranch = {}
195 for name, nodes in branchtonodes.iteritems():
204 for name, nodes in branchtonodes.iteritems():
196 for node in nodes:
205 for node in nodes:
197 self._nodetobranch.setdefault(node, []).append(name)
206 self._nodetobranch.setdefault(node, []).append(name)
198 return self._nodetobranch
207 return self._nodetobranch
199
208
209 def hoisttonodes(self, hoist):
210 if not self._hoisttonodes:
211 marktonodes = self.bmarktonodes()
212 self._hoisttonodes = {}
213 hoist += '/'
214 for name, node in marktonodes.iteritems():
215 if name.startswith(hoist):
216 name = name[len(hoist):]
217 self._hoisttonodes[name] = node
218 return self._hoisttonodes
219
220 def nodetohoists(self, hoist):
221 if not self._nodetohoists:
222 marktonodes = self.bmarktonodes()
223 self._nodetohoists = {}
224 hoist += '/'
225 for name, node in marktonodes.iteritems():
226 if name.startswith(hoist):
227 name = name[len(hoist):]
228 self._nodetohoists.setdefault(node[0], []).append(name)
229 return self._nodetohoists
230
200 def reposetup(ui, repo):
231 def reposetup(ui, repo):
201 if not repo.local():
232 if not repo.local():
202 return
233 return
203
234
204 repo._remotenames = remotenames(repo)
235 repo._remotenames = remotenames(repo)
205 ns = namespaces.namespace
236 ns = namespaces.namespace
206
237
207 if ui.configbool('remotenames', 'bookmarks'):
238 if ui.configbool('remotenames', 'bookmarks'):
208 remotebookmarkns = ns(
239 remotebookmarkns = ns(
209 'remotebookmarks',
240 'remotebookmarks',
210 templatename='remotebookmarks',
241 templatename='remotebookmarks',
211 colorname='remotebookmark',
242 colorname='remotebookmark',
212 logfmt='remote bookmark: %s\n',
243 logfmt='remote bookmark: %s\n',
213 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(),
244 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(),
214 namemap=lambda repo, name:
245 namemap=lambda repo, name:
215 repo._remotenames.bmarktonodes().get(name, []),
246 repo._remotenames.bmarktonodes().get(name, []),
216 nodemap=lambda repo, node:
247 nodemap=lambda repo, node:
217 repo._remotenames.nodetobmarks().get(node, []))
248 repo._remotenames.nodetobmarks().get(node, []))
218 repo.names.addnamespace(remotebookmarkns)
249 repo.names.addnamespace(remotebookmarkns)
219
250
251 # hoisting only works if there are remote bookmarks
252 hoist = ui.config('remotenames', 'hoistedpeer')
253 if hoist:
254 hoistednamens = ns(
255 'hoistednames',
256 templatename='hoistednames',
257 colorname='hoistedname',
258 logfmt='hoisted name: %s\n',
259 listnames = lambda repo:
260 repo._remotenames.hoisttonodes(hoist).keys(),
261 namemap = lambda repo, name:
262 repo._remotenames.hoisttonodes(hoist).get(name, []),
263 nodemap = lambda repo, node:
264 repo._remotenames.nodetohoists(hoist).get(node, []))
265 repo.names.addnamespace(hoistednamens)
266
220 if ui.configbool('remotenames', 'branches'):
267 if ui.configbool('remotenames', 'branches'):
221 remotebranchns = ns(
268 remotebranchns = ns(
222 'remotebranches',
269 'remotebranches',
223 templatename='remotebranches',
270 templatename='remotebranches',
224 colorname='remotebranch',
271 colorname='remotebranch',
225 logfmt='remote branch: %s\n',
272 logfmt='remote branch: %s\n',
226 listnames = lambda repo: repo._remotenames.branchtonodes().keys(),
273 listnames = lambda repo: repo._remotenames.branchtonodes().keys(),
227 namemap = lambda repo, name:
274 namemap = lambda repo, name:
228 repo._remotenames.branchtonodes().get(name, []),
275 repo._remotenames.branchtonodes().get(name, []),
229 nodemap = lambda repo, node:
276 nodemap = lambda repo, node:
230 repo._remotenames.nodetobranch().get(node, []))
277 repo._remotenames.nodetobranch().get(node, []))
231 repo.names.addnamespace(remotebranchns)
278 repo.names.addnamespace(remotebranchns)
232
279
233 @templatekeyword('remotenames', requires={'repo', 'ctx'})
280 @templatekeyword('remotenames', requires={'repo', 'ctx'})
234 def remotenameskw(context, mapping):
281 def remotenameskw(context, mapping):
235 """List of strings. Remote names associated with the changeset."""
282 """List of strings. Remote names associated with the changeset."""
236 repo = context.resource(mapping, 'repo')
283 repo = context.resource(mapping, 'repo')
237 ctx = context.resource(mapping, 'ctx')
284 ctx = context.resource(mapping, 'ctx')
238
285
239 remotenames = []
286 remotenames = []
240 if 'remotebookmarks' in repo.names:
287 if 'remotebookmarks' in repo.names:
241 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node())
288 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node())
242
289
243 if 'remotebranches' in repo.names:
290 if 'remotebranches' in repo.names:
244 remotenames += repo.names['remotebranches'].names(repo, ctx.node())
291 remotenames += repo.names['remotebranches'].names(repo, ctx.node())
245
292
246 return templateutil.compatlist(context, mapping, 'remotename', remotenames,
293 return templateutil.compatlist(context, mapping, 'remotename', remotenames,
247 plural='remotenames')
294 plural='remotenames')
248
295
249 @templatekeyword('remotebookmarks', requires={'repo', 'ctx'})
296 @templatekeyword('remotebookmarks', requires={'repo', 'ctx'})
250 def remotebookmarkskw(context, mapping):
297 def remotebookmarkskw(context, mapping):
251 """List of strings. Remote bookmarks associated with the changeset."""
298 """List of strings. Remote bookmarks associated with the changeset."""
252 repo = context.resource(mapping, 'repo')
299 repo = context.resource(mapping, 'repo')
253 ctx = context.resource(mapping, 'ctx')
300 ctx = context.resource(mapping, 'ctx')
254
301
255 remotebmarks = []
302 remotebmarks = []
256 if 'remotebookmarks' in repo.names:
303 if 'remotebookmarks' in repo.names:
257 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node())
304 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node())
258
305
259 return templateutil.compatlist(context, mapping, 'remotebookmark',
306 return templateutil.compatlist(context, mapping, 'remotebookmark',
260 remotebmarks, plural='remotebookmarks')
307 remotebmarks, plural='remotebookmarks')
261
308
262 @templatekeyword('remotebranches', requires={'repo', 'ctx'})
309 @templatekeyword('remotebranches', requires={'repo', 'ctx'})
263 def remotebrancheskw(context, mapping):
310 def remotebrancheskw(context, mapping):
264 """List of strings. Remote branches associated with the changeset."""
311 """List of strings. Remote branches associated with the changeset."""
265 repo = context.resource(mapping, 'repo')
312 repo = context.resource(mapping, 'repo')
266 ctx = context.resource(mapping, 'ctx')
313 ctx = context.resource(mapping, 'ctx')
267
314
268 remotebranches = []
315 remotebranches = []
269 if 'remotebranches' in repo.names:
316 if 'remotebranches' in repo.names:
270 remotebranches = repo.names['remotebranches'].names(repo, ctx.node())
317 remotebranches = repo.names['remotebranches'].names(repo, ctx.node())
271
318
272 return templateutil.compatlist(context, mapping, 'remotebranch',
319 return templateutil.compatlist(context, mapping, 'remotebranch',
273 remotebranches, plural='remotebranches')
320 remotebranches, plural='remotebranches')
274
321
275 def _revsetutil(repo, subset, x, rtypes):
322 def _revsetutil(repo, subset, x, rtypes):
276 """utility function to return a set of revs based on the rtypes"""
323 """utility function to return a set of revs based on the rtypes"""
277
324
278 revs = set()
325 revs = set()
279 cl = repo.changelog
326 cl = repo.changelog
280 for rtype in rtypes:
327 for rtype in rtypes:
281 if rtype in repo.names:
328 if rtype in repo.names:
282 ns = repo.names[rtype]
329 ns = repo.names[rtype]
283 for name in ns.listnames(repo):
330 for name in ns.listnames(repo):
284 revs.update(ns.nodes(repo, name))
331 revs.update(ns.nodes(repo, name))
285
332
286 results = (cl.rev(n) for n in revs if cl.hasnode(n))
333 results = (cl.rev(n) for n in revs if cl.hasnode(n))
287 return subset & smartset.baseset(sorted(results))
334 return subset & smartset.baseset(sorted(results))
288
335
289 @revsetpredicate('remotenames()')
336 @revsetpredicate('remotenames()')
290 def remotenamesrevset(repo, subset, x):
337 def remotenamesrevset(repo, subset, x):
291 """All changesets which have a remotename on them."""
338 """All changesets which have a remotename on them."""
292 revsetlang.getargs(x, 0, 0, _("remotenames takes no arguments"))
339 revsetlang.getargs(x, 0, 0, _("remotenames takes no arguments"))
293 return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches'))
340 return _revsetutil(repo, subset, x, ('remotebookmarks', 'remotebranches'))
294
341
295 @revsetpredicate('remotebranches()')
342 @revsetpredicate('remotebranches()')
296 def remotebranchesrevset(repo, subset, x):
343 def remotebranchesrevset(repo, subset, x):
297 """All changesets which are branch heads on remotes."""
344 """All changesets which are branch heads on remotes."""
298 revsetlang.getargs(x, 0, 0, _("remotebranches takes no arguments"))
345 revsetlang.getargs(x, 0, 0, _("remotebranches takes no arguments"))
299 return _revsetutil(repo, subset, x, ('remotebranches',))
346 return _revsetutil(repo, subset, x, ('remotebranches',))
300
347
301 @revsetpredicate('remotebookmarks()')
348 @revsetpredicate('remotebookmarks()')
302 def remotebmarksrevset(repo, subset, x):
349 def remotebmarksrevset(repo, subset, x):
303 """All changesets which have bookmarks on remotes."""
350 """All changesets which have bookmarks on remotes."""
304 revsetlang.getargs(x, 0, 0, _("remotebookmarks takes no arguments"))
351 revsetlang.getargs(x, 0, 0, _("remotebookmarks takes no arguments"))
305 return _revsetutil(repo, subset, x, ('remotebookmarks',))
352 return _revsetutil(repo, subset, x, ('remotebookmarks',))
@@ -1,261 +1,329 b''
1 Testing the functionality to pull remotenames
1 Testing the functionality to pull remotenames
2 =============================================
2 =============================================
3
3
4 $ cat >> $HGRCPATH << EOF
4 $ cat >> $HGRCPATH << EOF
5 > [alias]
5 > [alias]
6 > glog = log -G -T '{rev}:{node|short} {desc}'
6 > glog = log -G -T '{rev}:{node|short} {desc}'
7 > [experimental]
7 > [experimental]
8 > remotenames = True
8 > remotenames = True
9 > [extensions]
9 > [extensions]
10 > remotenames =
10 > remotenames =
11 > show =
11 > show =
12 > EOF
12 > EOF
13
13
14 Making a server repo
14 Making a server repo
15 --------------------
15 --------------------
16
16
17 $ hg init server
17 $ hg init server
18 $ cd server
18 $ cd server
19 $ for ch in a b c d e f g h; do
19 $ for ch in a b c d e f g h; do
20 > echo "foo" >> $ch
20 > echo "foo" >> $ch
21 > hg ci -Aqm "Added "$ch
21 > hg ci -Aqm "Added "$ch
22 > done
22 > done
23 $ hg glog
23 $ hg glog
24 @ 7:ec2426147f0e Added h
24 @ 7:ec2426147f0e Added h
25 |
25 |
26 o 6:87d6d6676308 Added g
26 o 6:87d6d6676308 Added g
27 |
27 |
28 o 5:825660c69f0c Added f
28 o 5:825660c69f0c Added f
29 |
29 |
30 o 4:aa98ab95a928 Added e
30 o 4:aa98ab95a928 Added e
31 |
31 |
32 o 3:62615734edd5 Added d
32 o 3:62615734edd5 Added d
33 |
33 |
34 o 2:28ad74487de9 Added c
34 o 2:28ad74487de9 Added c
35 |
35 |
36 o 1:29becc82797a Added b
36 o 1:29becc82797a Added b
37 |
37 |
38 o 0:18d04c59bb5d Added a
38 o 0:18d04c59bb5d Added a
39
39
40 $ hg bookmark -r 3 foo
40 $ hg bookmark -r 3 foo
41 $ hg bookmark -r 6 bar
41 $ hg bookmark -r 6 bar
42 $ hg up 4
42 $ hg up 4
43 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
43 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
44 $ hg branch wat
44 $ hg branch wat
45 marked working directory as branch wat
45 marked working directory as branch wat
46 (branches are permanent and global, did you want a bookmark?)
46 (branches are permanent and global, did you want a bookmark?)
47 $ echo foo >> bar
47 $ echo foo >> bar
48 $ hg ci -Aqm "added bar"
48 $ hg ci -Aqm "added bar"
49
49
50 Making a client repo
50 Making a client repo
51 --------------------
51 --------------------
52
52
53 $ cd ..
53 $ cd ..
54
54
55 $ hg clone server client
55 $ hg clone server client
56 updating to branch default
56 updating to branch default
57 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
58
58
59 $ cd client
59 $ cd client
60 $ cat .hg/logexchange/bookmarks
60 $ cat .hg/logexchange/bookmarks
61 0
61 0
62
62
63 87d6d66763085b629e6d7ed56778c79827273022\x00default\x00bar (esc)
63 87d6d66763085b629e6d7ed56778c79827273022\x00default\x00bar (esc)
64 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00default\x00foo (esc)
64 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00default\x00foo (esc)
65
65
66 $ cat .hg/logexchange/branches
66 $ cat .hg/logexchange/branches
67 0
67 0
68
68
69 ec2426147f0e39dbc9cef599b066be6035ce691d\x00default\x00default (esc)
69 ec2426147f0e39dbc9cef599b066be6035ce691d\x00default\x00default (esc)
70 3e1487808078543b0af6d10dadf5d46943578db0\x00default\x00wat (esc)
70 3e1487808078543b0af6d10dadf5d46943578db0\x00default\x00wat (esc)
71
71
72 $ hg show work
72 $ hg show work
73 o 3e14 (wat) (default/wat) added bar
73 o 3e14 (wat) (default/wat) added bar
74 |
74 |
75 ~
75 ~
76 @ ec24 (default/default) Added h
76 @ ec24 (default/default) Added h
77 |
77 |
78 ~
78 ~
79
79
80 $ hg update "default/wat"
80 $ hg update "default/wat"
81 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
81 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
82 $ hg identify
82 $ hg identify
83 3e1487808078 (wat) tip
83 3e1487808078 (wat) tip
84
84
85 Making a new server
85 Making a new server
86 -------------------
86 -------------------
87
87
88 $ cd ..
88 $ cd ..
89 $ hg init server2
89 $ hg init server2
90 $ cd server2
90 $ cd server2
91 $ hg pull ../server/
91 $ hg pull ../server/
92 pulling from ../server/
92 pulling from ../server/
93 requesting all changes
93 requesting all changes
94 adding changesets
94 adding changesets
95 adding manifests
95 adding manifests
96 adding file changes
96 adding file changes
97 added 9 changesets with 9 changes to 9 files (+1 heads)
97 added 9 changesets with 9 changes to 9 files (+1 heads)
98 adding remote bookmark bar
98 adding remote bookmark bar
99 adding remote bookmark foo
99 adding remote bookmark foo
100 new changesets 18d04c59bb5d:3e1487808078
100 new changesets 18d04c59bb5d:3e1487808078
101 (run 'hg heads' to see heads)
101 (run 'hg heads' to see heads)
102
102
103 Pulling form the new server
103 Pulling form the new server
104 ---------------------------
104 ---------------------------
105 $ cd ../client/
105 $ cd ../client/
106 $ hg pull ../server2/
106 $ hg pull ../server2/
107 pulling from ../server2/
107 pulling from ../server2/
108 searching for changes
108 searching for changes
109 no changes found
109 no changes found
110 $ cat .hg/logexchange/bookmarks
110 $ cat .hg/logexchange/bookmarks
111 0
111 0
112
112
113 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00default\x00foo (esc)
113 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00default\x00foo (esc)
114 87d6d66763085b629e6d7ed56778c79827273022\x00default\x00bar (esc)
114 87d6d66763085b629e6d7ed56778c79827273022\x00default\x00bar (esc)
115 87d6d66763085b629e6d7ed56778c79827273022\x00$TESTTMP/server2\x00bar (esc)
115 87d6d66763085b629e6d7ed56778c79827273022\x00$TESTTMP/server2\x00bar (esc)
116 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00$TESTTMP/server2\x00foo (esc)
116 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00$TESTTMP/server2\x00foo (esc)
117
117
118 $ cat .hg/logexchange/branches
118 $ cat .hg/logexchange/branches
119 0
119 0
120
120
121 3e1487808078543b0af6d10dadf5d46943578db0\x00default\x00wat (esc)
121 3e1487808078543b0af6d10dadf5d46943578db0\x00default\x00wat (esc)
122 ec2426147f0e39dbc9cef599b066be6035ce691d\x00default\x00default (esc)
122 ec2426147f0e39dbc9cef599b066be6035ce691d\x00default\x00default (esc)
123 ec2426147f0e39dbc9cef599b066be6035ce691d\x00$TESTTMP/server2\x00default (esc)
123 ec2426147f0e39dbc9cef599b066be6035ce691d\x00$TESTTMP/server2\x00default (esc)
124 3e1487808078543b0af6d10dadf5d46943578db0\x00$TESTTMP/server2\x00wat (esc)
124 3e1487808078543b0af6d10dadf5d46943578db0\x00$TESTTMP/server2\x00wat (esc)
125
125
126 $ hg log -G
126 $ hg log -G
127 @ changeset: 8:3e1487808078
127 @ changeset: 8:3e1487808078
128 | branch: wat
128 | branch: wat
129 | tag: tip
129 | tag: tip
130 | remote branch: $TESTTMP/server2/wat
130 | remote branch: $TESTTMP/server2/wat
131 | remote branch: default/wat
131 | remote branch: default/wat
132 | parent: 4:aa98ab95a928
132 | parent: 4:aa98ab95a928
133 | user: test
133 | user: test
134 | date: Thu Jan 01 00:00:00 1970 +0000
134 | date: Thu Jan 01 00:00:00 1970 +0000
135 | summary: added bar
135 | summary: added bar
136 |
136 |
137 | o changeset: 7:ec2426147f0e
137 | o changeset: 7:ec2426147f0e
138 | | remote branch: $TESTTMP/server2/default
138 | | remote branch: $TESTTMP/server2/default
139 | | remote branch: default/default
139 | | remote branch: default/default
140 | | user: test
140 | | user: test
141 | | date: Thu Jan 01 00:00:00 1970 +0000
141 | | date: Thu Jan 01 00:00:00 1970 +0000
142 | | summary: Added h
142 | | summary: Added h
143 | |
143 | |
144 | o changeset: 6:87d6d6676308
144 | o changeset: 6:87d6d6676308
145 | | bookmark: bar
145 | | bookmark: bar
146 | | remote bookmark: $TESTTMP/server2/bar
146 | | remote bookmark: $TESTTMP/server2/bar
147 | | remote bookmark: default/bar
147 | | remote bookmark: default/bar
148 | | hoisted name: bar
148 | | user: test
149 | | user: test
149 | | date: Thu Jan 01 00:00:00 1970 +0000
150 | | date: Thu Jan 01 00:00:00 1970 +0000
150 | | summary: Added g
151 | | summary: Added g
151 | |
152 | |
152 | o changeset: 5:825660c69f0c
153 | o changeset: 5:825660c69f0c
153 |/ user: test
154 |/ user: test
154 | date: Thu Jan 01 00:00:00 1970 +0000
155 | date: Thu Jan 01 00:00:00 1970 +0000
155 | summary: Added f
156 | summary: Added f
156 |
157 |
157 o changeset: 4:aa98ab95a928
158 o changeset: 4:aa98ab95a928
158 | user: test
159 | user: test
159 | date: Thu Jan 01 00:00:00 1970 +0000
160 | date: Thu Jan 01 00:00:00 1970 +0000
160 | summary: Added e
161 | summary: Added e
161 |
162 |
162 o changeset: 3:62615734edd5
163 o changeset: 3:62615734edd5
163 | bookmark: foo
164 | bookmark: foo
164 | remote bookmark: $TESTTMP/server2/foo
165 | remote bookmark: $TESTTMP/server2/foo
165 | remote bookmark: default/foo
166 | remote bookmark: default/foo
167 | hoisted name: foo
166 | user: test
168 | user: test
167 | date: Thu Jan 01 00:00:00 1970 +0000
169 | date: Thu Jan 01 00:00:00 1970 +0000
168 | summary: Added d
170 | summary: Added d
169 |
171 |
170 o changeset: 2:28ad74487de9
172 o changeset: 2:28ad74487de9
171 | user: test
173 | user: test
172 | date: Thu Jan 01 00:00:00 1970 +0000
174 | date: Thu Jan 01 00:00:00 1970 +0000
173 | summary: Added c
175 | summary: Added c
174 |
176 |
175 o changeset: 1:29becc82797a
177 o changeset: 1:29becc82797a
176 | user: test
178 | user: test
177 | date: Thu Jan 01 00:00:00 1970 +0000
179 | date: Thu Jan 01 00:00:00 1970 +0000
178 | summary: Added b
180 | summary: Added b
179 |
181 |
180 o changeset: 0:18d04c59bb5d
182 o changeset: 0:18d04c59bb5d
181 user: test
183 user: test
182 date: Thu Jan 01 00:00:00 1970 +0000
184 date: Thu Jan 01 00:00:00 1970 +0000
183 summary: Added a
185 summary: Added a
184
186
185 Testing the templates provided by remotenames extension
187 Testing the templates provided by remotenames extension
186
188
187 `remotenames` keyword
189 `remotenames` keyword
188
190
189 $ hg log -G -T "{rev}:{node|short} {remotenames}\n"
191 $ hg log -G -T "{rev}:{node|short} {remotenames}\n"
190 @ 8:3e1487808078 $TESTTMP/server2/wat default/wat
192 @ 8:3e1487808078 $TESTTMP/server2/wat default/wat
191 |
193 |
192 | o 7:ec2426147f0e $TESTTMP/server2/default default/default
194 | o 7:ec2426147f0e $TESTTMP/server2/default default/default
193 | |
195 | |
194 | o 6:87d6d6676308 $TESTTMP/server2/bar default/bar
196 | o 6:87d6d6676308 $TESTTMP/server2/bar default/bar
195 | |
197 | |
196 | o 5:825660c69f0c
198 | o 5:825660c69f0c
197 |/
199 |/
198 o 4:aa98ab95a928
200 o 4:aa98ab95a928
199 |
201 |
200 o 3:62615734edd5 $TESTTMP/server2/foo default/foo
202 o 3:62615734edd5 $TESTTMP/server2/foo default/foo
201 |
203 |
202 o 2:28ad74487de9
204 o 2:28ad74487de9
203 |
205 |
204 o 1:29becc82797a
206 o 1:29becc82797a
205 |
207 |
206 o 0:18d04c59bb5d
208 o 0:18d04c59bb5d
207
209
208 `remotebookmarks` and `remotebranches` keywords
210 `remotebookmarks` and `remotebranches` keywords
209
211
210 $ hg log -G -T "{rev}:{node|short} [{remotebookmarks}] ({remotebranches})"
212 $ hg log -G -T "{rev}:{node|short} [{remotebookmarks}] ({remotebranches})"
211 @ 8:3e1487808078 [] ($TESTTMP/server2/wat default/wat)
213 @ 8:3e1487808078 [] ($TESTTMP/server2/wat default/wat)
212 |
214 |
213 | o 7:ec2426147f0e [] ($TESTTMP/server2/default default/default)
215 | o 7:ec2426147f0e [] ($TESTTMP/server2/default default/default)
214 | |
216 | |
215 | o 6:87d6d6676308 [$TESTTMP/server2/bar default/bar] ()
217 | o 6:87d6d6676308 [$TESTTMP/server2/bar default/bar] ()
216 | |
218 | |
217 | o 5:825660c69f0c [] ()
219 | o 5:825660c69f0c [] ()
218 |/
220 |/
219 o 4:aa98ab95a928 [] ()
221 o 4:aa98ab95a928 [] ()
220 |
222 |
221 o 3:62615734edd5 [$TESTTMP/server2/foo default/foo] ()
223 o 3:62615734edd5 [$TESTTMP/server2/foo default/foo] ()
222 |
224 |
223 o 2:28ad74487de9 [] ()
225 o 2:28ad74487de9 [] ()
224 |
226 |
225 o 1:29becc82797a [] ()
227 o 1:29becc82797a [] ()
226 |
228 |
227 o 0:18d04c59bb5d [] ()
229 o 0:18d04c59bb5d [] ()
228
230
231 The `hoistednames` template keyword
232
233 $ hg log -GT "{rev}:{node|short} ({hoistednames})"
234 @ 8:3e1487808078 ()
235 |
236 | o 7:ec2426147f0e ()
237 | |
238 | o 6:87d6d6676308 (bar)
239 | |
240 | o 5:825660c69f0c ()
241 |/
242 o 4:aa98ab95a928 ()
243 |
244 o 3:62615734edd5 (foo)
245 |
246 o 2:28ad74487de9 ()
247 |
248 o 1:29becc82797a ()
249 |
250 o 0:18d04c59bb5d ()
251
252
229 Testing the revsets provided by remotenames extension
253 Testing the revsets provided by remotenames extension
230
254
231 `remotenames` revset
255 `remotenames` revset
232
256
233 $ hg log -r "remotenames()" -GT "{rev}:{node|short} {remotenames}\n"
257 $ hg log -r "remotenames()" -GT "{rev}:{node|short} {remotenames}\n"
234 @ 8:3e1487808078 $TESTTMP/server2/wat default/wat
258 @ 8:3e1487808078 $TESTTMP/server2/wat default/wat
235 :
259 :
236 : o 7:ec2426147f0e $TESTTMP/server2/default default/default
260 : o 7:ec2426147f0e $TESTTMP/server2/default default/default
237 : |
261 : |
238 : o 6:87d6d6676308 $TESTTMP/server2/bar default/bar
262 : o 6:87d6d6676308 $TESTTMP/server2/bar default/bar
239 :/
263 :/
240 o 3:62615734edd5 $TESTTMP/server2/foo default/foo
264 o 3:62615734edd5 $TESTTMP/server2/foo default/foo
241 |
265 |
242 ~
266 ~
243
267
244 `remotebranches` revset
268 `remotebranches` revset
245
269
246 $ hg log -r "remotebranches()" -GT "{rev}:{node|short} {remotenames}\n"
270 $ hg log -r "remotebranches()" -GT "{rev}:{node|short} {remotenames}\n"
247 @ 8:3e1487808078 $TESTTMP/server2/wat default/wat
271 @ 8:3e1487808078 $TESTTMP/server2/wat default/wat
248 |
272 |
249 ~
273 ~
250 o 7:ec2426147f0e $TESTTMP/server2/default default/default
274 o 7:ec2426147f0e $TESTTMP/server2/default default/default
251 |
275 |
252 ~
276 ~
253
277
254 `remotebookmarks` revset
278 `remotebookmarks` revset
255
279
256 $ hg log -r "remotebookmarks()" -GT "{rev}:{node|short} {remotenames}\n"
280 $ hg log -r "remotebookmarks()" -GT "{rev}:{node|short} {remotenames}\n"
257 o 6:87d6d6676308 $TESTTMP/server2/bar default/bar
281 o 6:87d6d6676308 $TESTTMP/server2/bar default/bar
258 :
282 :
259 o 3:62615734edd5 $TESTTMP/server2/foo default/foo
283 o 3:62615734edd5 $TESTTMP/server2/foo default/foo
260 |
284 |
261 ~
285 ~
286
287 Updating to revision using hoisted name
288
289 Deleting local bookmark to make sure we update to hoisted name only
290
291 $ hg bookmark -d bar
292
293 $ hg up bar
294 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
295
296 $ hg log -r .
297 changeset: 6:87d6d6676308
298 remote bookmark: $TESTTMP/server2/bar
299 remote bookmark: default/bar
300 hoisted name: bar
301 user: test
302 date: Thu Jan 01 00:00:00 1970 +0000
303 summary: Added g
304
305 When both local bookmark and hoisted name exists but on different revs
306
307 $ hg up 8
308 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
309
310 $ hg bookmark foo
311 moving bookmark 'foo' forward from 62615734edd5
312
313 Local bookmark should take precedence over hoisted name
314
315 $ hg up foo
316 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
317
318 $ hg log -r .
319 changeset: 8:3e1487808078
320 branch: wat
321 bookmark: foo
322 tag: tip
323 remote branch: $TESTTMP/server2/wat
324 remote branch: default/wat
325 parent: 4:aa98ab95a928
326 user: test
327 date: Thu Jan 01 00:00:00 1970 +0000
328 summary: added bar
329
General Comments 0
You need to be logged in to leave comments. Login now