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