##// END OF EJS Templates
remotenames: introduce a class to lazily resolve remotnames...
Pulkit Goyal -
r36078:be72f642 default
parent child Browse files
Show More
@@ -10,6 +10,11 b''
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12
12
13 import UserDict
14
15 from mercurial.node import (
16 bin,
17 )
13 from mercurial import (
18 from mercurial import (
14 logexchange,
19 logexchange,
15 )
20 )
@@ -20,34 +25,102 b' from mercurial import ('
20 # leave the attribute unspecified.
25 # leave the attribute unspecified.
21 testedwith = 'ships-with-hg-core'
26 testedwith = 'ships-with-hg-core'
22
27
28 class lazyremotenamedict(UserDict.DictMixin):
29 """
30 Read-only dict-like Class to lazily resolve remotename entries
31
32 We are doing that because remotenames startup was slow.
33 We lazily read the remotenames file once to figure out the potential entries
34 and store them in self.potentialentries. Then when asked to resolve an
35 entry, if it is not in self.potentialentries, then it isn't there, if it
36 is in self.potentialentries we resolve it and store the result in
37 self.cache. We cannot be lazy is when asked all the entries (keys).
38 """
39 def __init__(self, kind, repo):
40 self.cache = {}
41 self.potentialentries = {}
42 self._kind = kind # bookmarks or branches
43 self._repo = repo
44 self.loaded = False
45
46 def _load(self):
47 """ Read the remotenames file, store entries matching selected kind """
48 self.loaded = True
49 repo = self._repo
50 for node, rpath, rname in logexchange.readremotenamefile(repo,
51 self._kind):
52 name = rpath + '/' + rname
53 self.potentialentries[name] = (node, rpath, name)
54
55 def _resolvedata(self, potentialentry):
56 """ Check that the node for potentialentry exists and return it """
57 if not potentialentry in self.potentialentries:
58 return None
59 node, remote, name = self.potentialentries[potentialentry]
60 repo = self._repo
61 binnode = bin(node)
62 # if the node doesn't exist, skip it
63 try:
64 repo.changelog.rev(binnode)
65 except LookupError:
66 return None
67 # Skip closed branches
68 if (self._kind == 'branches' and repo[binnode].closesbranch()):
69 return None
70 return [binnode]
71
72 def __getitem__(self, key):
73 if not self.loaded:
74 self._load()
75 val = self._fetchandcache(key)
76 if val is not None:
77 return val
78 else:
79 raise KeyError()
80
81 def _fetchandcache(self, key):
82 if key in self.cache:
83 return self.cache[key]
84 val = self._resolvedata(key)
85 if val is not None:
86 self.cache[key] = val
87 return val
88 else:
89 return None
90
91 def keys(self):
92 """ Get a list of bookmark or branch names """
93 if not self.loaded:
94 self._load()
95 return self.potentialentries.keys()
96
97 def iteritems(self):
98 """ Iterate over (name, node) tuples """
99
100 if not self.loaded:
101 self._load()
102
103 for k, vtup in self.potentialentries.iteritems():
104 yield (k, [bin(vtup[0])])
105
23 class remotenames(dict):
106 class remotenames(dict):
24 """
107 """
25 This class encapsulates all the remotenames state. It also contains
108 This class encapsulates all the remotenames state. It also contains
26 methods to access that state in convenient ways.
109 methods to access that state in convenient ways. Remotenames are lazy
110 loaded. Whenever client code needs to ensure the freshest copy of
111 remotenames, use the `clearnames` method to force an eventual load.
27 """
112 """
28
113
29 def __init__(self, repo, *args):
114 def __init__(self, repo, *args):
30 dict.__init__(self, *args)
115 dict.__init__(self, *args)
31 self._repo = repo
116 self._repo = repo
32 self['bookmarks'] = {}
117 self.clearnames()
33 self['branches'] = {}
34 self.loadnames()
35 self._loadednames = True
36
37 def loadnames(self):
38 """ loads the remotenames information from the remotenames file """
39 for rtype in ('bookmarks', 'branches'):
40 for node, rpath, name in logexchange.readremotenamefile(self._repo,
41 rtype):
42 rname = rpath + '/' + name
43 self[rtype][rname] = [node]
44
118
45 def clearnames(self):
119 def clearnames(self):
46 """ Clear all remote names state """
120 """ Clear all remote names state """
47 self['bookmarks'] = {}
121 self['bookmarks'] = lazyremotenamedict("bookmarks", self._repo)
48 self['branches'] = {}
122 self['branches'] = lazyremotenamedict("branches", self._repo)
49 self._invalidatecache()
123 self._invalidatecache()
50 self._loadednames = False
51
124
52 def _invalidatecache(self):
125 def _invalidatecache(self):
53 self._nodetobmarks = None
126 self._nodetobmarks = None
General Comments 0
You need to be logged in to leave comments. Login now