##// END OF EJS Templates
remotenames: introduce new template keywords for remotenames...
Pulkit Goyal -
r36080:5a53af7d default
parent child Browse files
Show More
@@ -1,207 +1,258
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 UserDict
26 26
27 27 from mercurial.node import (
28 28 bin,
29 29 )
30 30 from mercurial import (
31 31 logexchange,
32 32 namespaces,
33 pycompat,
33 34 registrar,
35 templatekw,
34 36 )
35 37
36 38 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
37 39 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
38 40 # be specifying the version(s) of Mercurial they are tested with, or
39 41 # leave the attribute unspecified.
40 42 testedwith = 'ships-with-hg-core'
41 43
42 44 configtable = {}
43 45 configitem = registrar.configitem(configtable)
46 templatekeyword = registrar.templatekeyword()
44 47
45 48 configitem('remotenames', 'bookmarks',
46 49 default=True,
47 50 )
48 51 configitem('remotenames', 'branches',
49 52 default=True,
50 53 )
51 54
52 55 class lazyremotenamedict(UserDict.DictMixin):
53 56 """
54 57 Read-only dict-like Class to lazily resolve remotename entries
55 58
56 59 We are doing that because remotenames startup was slow.
57 60 We lazily read the remotenames file once to figure out the potential entries
58 61 and store them in self.potentialentries. Then when asked to resolve an
59 62 entry, if it is not in self.potentialentries, then it isn't there, if it
60 63 is in self.potentialentries we resolve it and store the result in
61 64 self.cache. We cannot be lazy is when asked all the entries (keys).
62 65 """
63 66 def __init__(self, kind, repo):
64 67 self.cache = {}
65 68 self.potentialentries = {}
66 69 self._kind = kind # bookmarks or branches
67 70 self._repo = repo
68 71 self.loaded = False
69 72
70 73 def _load(self):
71 74 """ Read the remotenames file, store entries matching selected kind """
72 75 self.loaded = True
73 76 repo = self._repo
74 77 for node, rpath, rname in logexchange.readremotenamefile(repo,
75 78 self._kind):
76 79 name = rpath + '/' + rname
77 80 self.potentialentries[name] = (node, rpath, name)
78 81
79 82 def _resolvedata(self, potentialentry):
80 83 """ Check that the node for potentialentry exists and return it """
81 84 if not potentialentry in self.potentialentries:
82 85 return None
83 86 node, remote, name = self.potentialentries[potentialentry]
84 87 repo = self._repo
85 88 binnode = bin(node)
86 89 # if the node doesn't exist, skip it
87 90 try:
88 91 repo.changelog.rev(binnode)
89 92 except LookupError:
90 93 return None
91 94 # Skip closed branches
92 95 if (self._kind == 'branches' and repo[binnode].closesbranch()):
93 96 return None
94 97 return [binnode]
95 98
96 99 def __getitem__(self, key):
97 100 if not self.loaded:
98 101 self._load()
99 102 val = self._fetchandcache(key)
100 103 if val is not None:
101 104 return val
102 105 else:
103 106 raise KeyError()
104 107
105 108 def _fetchandcache(self, key):
106 109 if key in self.cache:
107 110 return self.cache[key]
108 111 val = self._resolvedata(key)
109 112 if val is not None:
110 113 self.cache[key] = val
111 114 return val
112 115 else:
113 116 return None
114 117
115 118 def keys(self):
116 119 """ Get a list of bookmark or branch names """
117 120 if not self.loaded:
118 121 self._load()
119 122 return self.potentialentries.keys()
120 123
121 124 def iteritems(self):
122 125 """ Iterate over (name, node) tuples """
123 126
124 127 if not self.loaded:
125 128 self._load()
126 129
127 130 for k, vtup in self.potentialentries.iteritems():
128 131 yield (k, [bin(vtup[0])])
129 132
130 133 class remotenames(dict):
131 134 """
132 135 This class encapsulates all the remotenames state. It also contains
133 136 methods to access that state in convenient ways. Remotenames are lazy
134 137 loaded. Whenever client code needs to ensure the freshest copy of
135 138 remotenames, use the `clearnames` method to force an eventual load.
136 139 """
137 140
138 141 def __init__(self, repo, *args):
139 142 dict.__init__(self, *args)
140 143 self._repo = repo
141 144 self.clearnames()
142 145
143 146 def clearnames(self):
144 147 """ Clear all remote names state """
145 148 self['bookmarks'] = lazyremotenamedict("bookmarks", self._repo)
146 149 self['branches'] = lazyremotenamedict("branches", self._repo)
147 150 self._invalidatecache()
148 151
149 152 def _invalidatecache(self):
150 153 self._nodetobmarks = None
151 154 self._nodetobranch = None
152 155
153 156 def bmarktonodes(self):
154 157 return self['bookmarks']
155 158
156 159 def nodetobmarks(self):
157 160 if not self._nodetobmarks:
158 161 bmarktonodes = self.bmarktonodes()
159 162 self._nodetobmarks = {}
160 163 for name, node in bmarktonodes.iteritems():
161 164 self._nodetobmarks.setdefault(node[0], []).append(name)
162 165 return self._nodetobmarks
163 166
164 167 def branchtonodes(self):
165 168 return self['branches']
166 169
167 170 def nodetobranch(self):
168 171 if not self._nodetobranch:
169 172 branchtonodes = self.branchtonodes()
170 173 self._nodetobranch = {}
171 174 for name, nodes in branchtonodes.iteritems():
172 175 for node in nodes:
173 176 self._nodetobranch.setdefault(node, []).append(name)
174 177 return self._nodetobranch
175 178
176 179 def reposetup(ui, repo):
177 180 if not repo.local():
178 181 return
179 182
180 183 repo._remotenames = remotenames(repo)
181 184 ns = namespaces.namespace
182 185
183 186 if ui.configbool('remotenames', 'bookmarks'):
184 187 remotebookmarkns = ns(
185 188 'remotebookmarks',
186 189 templatename='remotebookmarks',
187 190 logname='remote bookmark',
188 191 colorname='remotebookmark',
189 192 listnames=lambda repo: repo._remotenames.bmarktonodes().keys(),
190 193 namemap=lambda repo, name:
191 194 repo._remotenames.bmarktonodes().get(name, []),
192 195 nodemap=lambda repo, node:
193 196 repo._remotenames.nodetobmarks().get(node, []))
194 197 repo.names.addnamespace(remotebookmarkns)
195 198
196 199 if ui.configbool('remotenames', 'branches'):
197 200 remotebranchns = ns(
198 201 'remotebranches',
199 202 templatename='remotebranches',
200 203 logname='remote branch',
201 204 colorname='remotebranch',
202 205 listnames = lambda repo: repo._remotenames.branchtonodes().keys(),
203 206 namemap = lambda repo, name:
204 207 repo._remotenames.branchtonodes().get(name, []),
205 208 nodemap = lambda repo, node:
206 209 repo._remotenames.nodetobranch().get(node, []))
207 210 repo.names.addnamespace(remotebranchns)
211
212 @templatekeyword('remotenames')
213 def remotenameskw(**args):
214 """:remotenames: List of strings. List of remote names associated with the
215 changeset.
216 """
217 args = pycompat.byteskwargs(args)
218 repo, ctx = args['repo'], args['ctx']
219
220 remotenames = []
221 if 'remotebookmarks' in repo.names:
222 remotenames = repo.names['remotebookmarks'].names(repo, ctx.node())
223
224 if 'remotebranches' in repo.names:
225 remotenames += repo.names['remotebranches'].names(repo, ctx.node())
226
227 return templatekw.showlist('remotename', remotenames, args,
228 plural='remotenames')
229
230 @templatekeyword('remotebookmarks')
231 def remotebookmarkskw(**args):
232 """:remotebookmarks: List of strings. List of remote bookmarks associated
233 with the changeset.
234 """
235 args = pycompat.byteskwargs(args)
236 repo, ctx = args['repo'], args['ctx']
237
238 remotebmarks = []
239 if 'remotebookmarks' in repo.names:
240 remotebmarks = repo.names['remotebookmarks'].names(repo, ctx.node())
241
242 return templatekw.showlist('remotebookmark', remotebmarks, args,
243 plural='remotebookmarks')
244
245 @templatekeyword('remotebranches')
246 def remotebrancheskw(**args):
247 """:remotebranches: List of strings. List of remote branches associated
248 with the changeset.
249 """
250 args = pycompat.byteskwargs(args)
251 repo, ctx = args['repo'], args['ctx']
252
253 remotebranches = []
254 if 'remotebranches' in repo.names:
255 remotebranches = repo.names['remotebranches'].names(repo, ctx.node())
256
257 return templatekw.showlist('remotebranch', remotebranches, args,
258 plural='remotebranches')
@@ -1,184 +1,228
1 1 Testing the functionality to pull remotenames
2 2 =============================================
3 3
4 4 $ cat >> $HGRCPATH << EOF
5 5 > [alias]
6 6 > glog = log -G -T '{rev}:{node|short} {desc}'
7 7 > [experimental]
8 8 > remotenames = True
9 9 > [extensions]
10 10 > remotenames =
11 11 > show =
12 12 > EOF
13 13
14 14 Making a server repo
15 15 --------------------
16 16
17 17 $ hg init server
18 18 $ cd server
19 19 $ for ch in a b c d e f g h; do
20 20 > echo "foo" >> $ch
21 21 > hg ci -Aqm "Added "$ch
22 22 > done
23 23 $ hg glog
24 24 @ 7:ec2426147f0e Added h
25 25 |
26 26 o 6:87d6d6676308 Added g
27 27 |
28 28 o 5:825660c69f0c Added f
29 29 |
30 30 o 4:aa98ab95a928 Added e
31 31 |
32 32 o 3:62615734edd5 Added d
33 33 |
34 34 o 2:28ad74487de9 Added c
35 35 |
36 36 o 1:29becc82797a Added b
37 37 |
38 38 o 0:18d04c59bb5d Added a
39 39
40 40 $ hg bookmark -r 3 foo
41 41 $ hg bookmark -r 6 bar
42 42 $ hg up 4
43 43 0 files updated, 0 files merged, 3 files removed, 0 files unresolved
44 44 $ hg branch wat
45 45 marked working directory as branch wat
46 46 (branches are permanent and global, did you want a bookmark?)
47 47 $ echo foo >> bar
48 48 $ hg ci -Aqm "added bar"
49 49
50 50 Making a client repo
51 51 --------------------
52 52
53 53 $ cd ..
54 54
55 55 $ hg clone server client
56 56 updating to branch default
57 57 8 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 58
59 59 $ cd client
60 60 $ cat .hg/logexchange/bookmarks
61 61 0
62 62
63 63 87d6d66763085b629e6d7ed56778c79827273022\x00default\x00bar (esc)
64 64 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00default\x00foo (esc)
65 65
66 66 $ cat .hg/logexchange/branches
67 67 0
68 68
69 69 ec2426147f0e39dbc9cef599b066be6035ce691d\x00default\x00default (esc)
70 70 3e1487808078543b0af6d10dadf5d46943578db0\x00default\x00wat (esc)
71 71
72 72 $ hg show work
73 73 o 3e14 (wat) (default/wat) added bar
74 74 |
75 75 ~
76 76 @ ec24 (default/default) Added h
77 77 |
78 78 ~
79 79
80 80 $ hg update "default/wat"
81 81 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
82 82 $ hg identify
83 83 3e1487808078 (wat) tip
84 84
85 85 Making a new server
86 86 -------------------
87 87
88 88 $ cd ..
89 89 $ hg init server2
90 90 $ cd server2
91 91 $ hg pull ../server/
92 92 pulling from ../server/
93 93 requesting all changes
94 94 adding changesets
95 95 adding manifests
96 96 adding file changes
97 97 added 9 changesets with 9 changes to 9 files (+1 heads)
98 98 adding remote bookmark bar
99 99 adding remote bookmark foo
100 100 new changesets 18d04c59bb5d:3e1487808078
101 101 (run 'hg heads' to see heads)
102 102
103 103 Pulling form the new server
104 104 ---------------------------
105 105 $ cd ../client/
106 106 $ hg pull ../server2/
107 107 pulling from ../server2/
108 108 searching for changes
109 109 no changes found
110 110 $ cat .hg/logexchange/bookmarks
111 111 0
112 112
113 113 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00default\x00foo (esc)
114 114 87d6d66763085b629e6d7ed56778c79827273022\x00default\x00bar (esc)
115 115 87d6d66763085b629e6d7ed56778c79827273022\x00$TESTTMP/server2\x00bar (esc)
116 116 62615734edd52f06b6fb9c2beb429e4fe30d57b8\x00$TESTTMP/server2\x00foo (esc)
117 117
118 118 $ cat .hg/logexchange/branches
119 119 0
120 120
121 121 3e1487808078543b0af6d10dadf5d46943578db0\x00default\x00wat (esc)
122 122 ec2426147f0e39dbc9cef599b066be6035ce691d\x00default\x00default (esc)
123 123 ec2426147f0e39dbc9cef599b066be6035ce691d\x00$TESTTMP/server2\x00default (esc)
124 124 3e1487808078543b0af6d10dadf5d46943578db0\x00$TESTTMP/server2\x00wat (esc)
125 125
126 126 $ hg log -G
127 127 @ changeset: 8:3e1487808078
128 128 | branch: wat
129 129 | tag: tip
130 130 | remote branch:$TESTTMP/server2/wat
131 131 | remote branch:default/wat
132 132 | parent: 4:aa98ab95a928
133 133 | user: test
134 134 | date: Thu Jan 01 00:00:00 1970 +0000
135 135 | summary: added bar
136 136 |
137 137 | o changeset: 7:ec2426147f0e
138 138 | | remote branch:$TESTTMP/server2/default
139 139 | | remote branch:default/default
140 140 | | user: test
141 141 | | date: Thu Jan 01 00:00:00 1970 +0000
142 142 | | summary: Added h
143 143 | |
144 144 | o changeset: 6:87d6d6676308
145 145 | | bookmark: bar
146 146 | | remote bookmark:$TESTTMP/server2/bar
147 147 | | remote bookmark:default/bar
148 148 | | user: test
149 149 | | date: Thu Jan 01 00:00:00 1970 +0000
150 150 | | summary: Added g
151 151 | |
152 152 | o changeset: 5:825660c69f0c
153 153 |/ user: test
154 154 | date: Thu Jan 01 00:00:00 1970 +0000
155 155 | summary: Added f
156 156 |
157 157 o changeset: 4:aa98ab95a928
158 158 | user: test
159 159 | date: Thu Jan 01 00:00:00 1970 +0000
160 160 | summary: Added e
161 161 |
162 162 o changeset: 3:62615734edd5
163 163 | bookmark: foo
164 164 | remote bookmark:$TESTTMP/server2/foo
165 165 | remote bookmark:default/foo
166 166 | user: test
167 167 | date: Thu Jan 01 00:00:00 1970 +0000
168 168 | summary: Added d
169 169 |
170 170 o changeset: 2:28ad74487de9
171 171 | user: test
172 172 | date: Thu Jan 01 00:00:00 1970 +0000
173 173 | summary: Added c
174 174 |
175 175 o changeset: 1:29becc82797a
176 176 | user: test
177 177 | date: Thu Jan 01 00:00:00 1970 +0000
178 178 | summary: Added b
179 179 |
180 180 o changeset: 0:18d04c59bb5d
181 181 user: test
182 182 date: Thu Jan 01 00:00:00 1970 +0000
183 183 summary: Added a
184 184
185 Testing the templates provided by remotenames extension
186
187 `remotenames` keyword
188
189 $ hg log -G -T "{rev}:{node|short} {remotenames}\n"
190 @ 8:3e1487808078 $TESTTMP/server2/wat default/wat
191 |
192 | o 7:ec2426147f0e $TESTTMP/server2/default default/default
193 | |
194 | o 6:87d6d6676308 $TESTTMP/server2/bar default/bar
195 | |
196 | o 5:825660c69f0c
197 |/
198 o 4:aa98ab95a928
199 |
200 o 3:62615734edd5 $TESTTMP/server2/foo default/foo
201 |
202 o 2:28ad74487de9
203 |
204 o 1:29becc82797a
205 |
206 o 0:18d04c59bb5d
207
208 `remotebookmarks` and `remotebranches` keywords
209
210 $ hg log -G -T "{rev}:{node|short} [{remotebookmarks}] ({remotebranches})"
211 @ 8:3e1487808078 [] ($TESTTMP/server2/wat default/wat)
212 |
213 | o 7:ec2426147f0e [] ($TESTTMP/server2/default default/default)
214 | |
215 | o 6:87d6d6676308 [$TESTTMP/server2/bar default/bar] ()
216 | |
217 | o 5:825660c69f0c [] ()
218 |/
219 o 4:aa98ab95a928 [] ()
220 |
221 o 3:62615734edd5 [$TESTTMP/server2/foo default/foo] ()
222 |
223 o 2:28ad74487de9 [] ()
224 |
225 o 1:29becc82797a [] ()
226 |
227 o 0:18d04c59bb5d [] ()
228
General Comments 0
You need to be logged in to leave comments. Login now