##// END OF EJS Templates
Add equality operators to changectx and filectx
Matt Mackall -
r3165:e7818574 default
parent child Browse files
Show More
@@ -1,203 +1,209
1 # context.py - changeset and file context objects for mercurial
1 # context.py - changeset and file context objects for mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import *
8 from node import *
9 from demandload import demandload
9 from demandload import demandload
10 demandload(globals(), "ancestor util")
10 demandload(globals(), "ancestor util")
11
11
12 class changectx(object):
12 class changectx(object):
13 """A changecontext object makes access to data related to a particular
13 """A changecontext object makes access to data related to a particular
14 changeset convenient."""
14 changeset convenient."""
15 def __init__(self, repo, changeid=None):
15 def __init__(self, repo, changeid=None):
16 """changeid is a revision number, node, or tag"""
16 """changeid is a revision number, node, or tag"""
17 self._repo = repo
17 self._repo = repo
18
18
19 if not changeid and changeid != 0:
19 if not changeid and changeid != 0:
20 p1, p2 = self._repo.dirstate.parents()
20 p1, p2 = self._repo.dirstate.parents()
21 self._rev = self._repo.changelog.rev(p1)
21 self._rev = self._repo.changelog.rev(p1)
22 if self._rev == -1:
22 if self._rev == -1:
23 changeid = 'tip'
23 changeid = 'tip'
24 else:
24 else:
25 self._node = p1
25 self._node = p1
26 return
26 return
27
27
28 self._node = self._repo.lookup(changeid)
28 self._node = self._repo.lookup(changeid)
29 self._rev = self._repo.changelog.rev(self._node)
29 self._rev = self._repo.changelog.rev(self._node)
30
30
31 def __repr__(self):
31 def __repr__(self):
32 return "<changectx %s>" % short(self.node())
32 return "<changectx %s>" % short(self.node())
33
33
34 def __eq__(self, other):
35 return self._rev == other._rev
36
34 def changeset(self):
37 def changeset(self):
35 try:
38 try:
36 return self._changeset
39 return self._changeset
37 except AttributeError:
40 except AttributeError:
38 self._changeset = self._repo.changelog.read(self.node())
41 self._changeset = self._repo.changelog.read(self.node())
39 return self._changeset
42 return self._changeset
40
43
41 def manifest(self):
44 def manifest(self):
42 try:
45 try:
43 return self._manifest
46 return self._manifest
44 except AttributeError:
47 except AttributeError:
45 self._manifest = self._repo.manifest.read(self.changeset()[0])
48 self._manifest = self._repo.manifest.read(self.changeset()[0])
46 return self._manifest
49 return self._manifest
47
50
48 def rev(self): return self._rev
51 def rev(self): return self._rev
49 def node(self): return self._node
52 def node(self): return self._node
50 def user(self): return self.changeset()[1]
53 def user(self): return self.changeset()[1]
51 def date(self): return self.changeset()[2]
54 def date(self): return self.changeset()[2]
52 def files(self): return self.changeset()[3]
55 def files(self): return self.changeset()[3]
53 def description(self): return self.changeset()[4]
56 def description(self): return self.changeset()[4]
54
57
55 def parents(self):
58 def parents(self):
56 """return contexts for each parent changeset"""
59 """return contexts for each parent changeset"""
57 p = self._repo.changelog.parents(self._node)
60 p = self._repo.changelog.parents(self._node)
58 return [ changectx(self._repo, x) for x in p ]
61 return [ changectx(self._repo, x) for x in p ]
59
62
60 def children(self):
63 def children(self):
61 """return contexts for each child changeset"""
64 """return contexts for each child changeset"""
62 c = self._repo.changelog.children(self._node)
65 c = self._repo.changelog.children(self._node)
63 return [ changectx(self._repo, x) for x in c ]
66 return [ changectx(self._repo, x) for x in c ]
64
67
65 def filenode(self, path):
68 def filenode(self, path):
66 node, flag = self._repo.manifest.find(self.changeset()[0], path)
69 node, flag = self._repo.manifest.find(self.changeset()[0], path)
67 return node
70 return node
68
71
69 def filectx(self, path, fileid=None):
72 def filectx(self, path, fileid=None):
70 """get a file context from this changeset"""
73 """get a file context from this changeset"""
71 if fileid is None:
74 if fileid is None:
72 fileid = self.filenode(path)
75 fileid = self.filenode(path)
73 return filectx(self._repo, path, fileid=fileid)
76 return filectx(self._repo, path, fileid=fileid)
74
77
75 def filectxs(self):
78 def filectxs(self):
76 """generate a file context for each file in this changeset's
79 """generate a file context for each file in this changeset's
77 manifest"""
80 manifest"""
78 mf = self.manifest()
81 mf = self.manifest()
79 m = mf.keys()
82 m = mf.keys()
80 m.sort()
83 m.sort()
81 for f in m:
84 for f in m:
82 yield self.filectx(f, fileid=mf[f])
85 yield self.filectx(f, fileid=mf[f])
83
86
84 def ancestor(self, c2):
87 def ancestor(self, c2):
85 """
88 """
86 return the ancestor context of self and c2
89 return the ancestor context of self and c2
87 """
90 """
88 n = self._repo.changelog.ancestor(self._node, c2._node)
91 n = self._repo.changelog.ancestor(self._node, c2._node)
89 return changectx(self._repo, n)
92 return changectx(self._repo, n)
90
93
91 class filectx(object):
94 class filectx(object):
92 """A filecontext object makes access to data related to a particular
95 """A filecontext object makes access to data related to a particular
93 filerevision convenient."""
96 filerevision convenient."""
94 def __init__(self, repo, path, changeid=None, fileid=None, filelog=None):
97 def __init__(self, repo, path, changeid=None, fileid=None, filelog=None):
95 """changeid can be a changeset revision, node, or tag.
98 """changeid can be a changeset revision, node, or tag.
96 fileid can be a file revision or node."""
99 fileid can be a file revision or node."""
97 self._repo = repo
100 self._repo = repo
98 self._path = path
101 self._path = path
99
102
100 assert changeid is not None or fileid is not None
103 assert changeid is not None or fileid is not None
101
104
102 if filelog:
105 if filelog:
103 self._filelog = filelog
106 self._filelog = filelog
104 else:
107 else:
105 self._filelog = self._repo.file(self._path)
108 self._filelog = self._repo.file(self._path)
106
109
107 if fileid is None:
110 if fileid is None:
108 self._changeid = changeid
111 self._changeid = changeid
109 else:
112 else:
110 self._filenode = self._filelog.lookup(fileid)
113 self._filenode = self._filelog.lookup(fileid)
111 self._changeid = self._filelog.linkrev(self._filenode)
114 self._changeid = self._filelog.linkrev(self._filenode)
112
115
113 def __getattr__(self, name):
116 def __getattr__(self, name):
114 if name == '_changectx':
117 if name == '_changectx':
115 self._changectx = changectx(self._repo, self._changeid)
118 self._changectx = changectx(self._repo, self._changeid)
116 return self._changectx
119 return self._changectx
117 elif name == '_filenode':
120 elif name == '_filenode':
118 self._filenode = self._changectx.filenode(self._path)
121 self._filenode = self._changectx.filenode(self._path)
119 return self._filenode
122 return self._filenode
120 elif name == '_filerev':
123 elif name == '_filerev':
121 self._filerev = self._filelog.rev(self._filenode)
124 self._filerev = self._filelog.rev(self._filenode)
122 return self._filerev
125 return self._filerev
123 else:
126 else:
124 raise AttributeError, name
127 raise AttributeError, name
125
128
126 def __repr__(self):
129 def __repr__(self):
127 return "<filectx %s@%s>" % (self.path(), short(self.node()))
130 return "<filectx %s@%s>" % (self.path(), short(self.node()))
128
131
132 def __eq__(self, other):
133 return self._path == other._path and self._changeid == other._changeid
134
129 def filerev(self): return self._filerev
135 def filerev(self): return self._filerev
130 def filenode(self): return self._filenode
136 def filenode(self): return self._filenode
131 def filelog(self): return self._filelog
137 def filelog(self): return self._filelog
132
138
133 def rev(self):
139 def rev(self):
134 if hasattr(self, "_changectx"):
140 if hasattr(self, "_changectx"):
135 return self._changectx.rev()
141 return self._changectx.rev()
136 return self._filelog.linkrev(self._filenode)
142 return self._filelog.linkrev(self._filenode)
137
143
138 def node(self): return self._changectx.node()
144 def node(self): return self._changectx.node()
139 def user(self): return self._changectx.user()
145 def user(self): return self._changectx.user()
140 def date(self): return self._changectx.date()
146 def date(self): return self._changectx.date()
141 def files(self): return self._changectx.files()
147 def files(self): return self._changectx.files()
142 def description(self): return self._changectx.description()
148 def description(self): return self._changectx.description()
143 def manifest(self): return self._changectx.manifest()
149 def manifest(self): return self._changectx.manifest()
144 def changectx(self): return self._changectx
150 def changectx(self): return self._changectx
145
151
146 def data(self): return self._filelog.read(self._filenode)
152 def data(self): return self._filelog.read(self._filenode)
147 def renamed(self): return self._filelog.renamed(self._filenode)
153 def renamed(self): return self._filelog.renamed(self._filenode)
148 def path(self): return self._path
154 def path(self): return self._path
149
155
150 def parents(self):
156 def parents(self):
151 p = self._path
157 p = self._path
152 fl = self._filelog
158 fl = self._filelog
153 pl = [ (p, n, fl) for n in self._filelog.parents(self._filenode) ]
159 pl = [ (p, n, fl) for n in self._filelog.parents(self._filenode) ]
154
160
155 r = self.renamed()
161 r = self.renamed()
156 if r:
162 if r:
157 pl[0] = (r[0], r[1], None)
163 pl[0] = (r[0], r[1], None)
158
164
159 return [ filectx(self._repo, p, fileid=n, filelog=l)
165 return [ filectx(self._repo, p, fileid=n, filelog=l)
160 for p,n,l in pl if n != nullid ]
166 for p,n,l in pl if n != nullid ]
161
167
162 def children(self):
168 def children(self):
163 # hard for renames
169 # hard for renames
164 c = self._filelog.children(self._filenode)
170 c = self._filelog.children(self._filenode)
165 return [ filectx(self._repo, self._path, fileid=x,
171 return [ filectx(self._repo, self._path, fileid=x,
166 filelog=self._filelog) for x in c ]
172 filelog=self._filelog) for x in c ]
167
173
168 def annotate(self):
174 def annotate(self):
169 getctx = util.cachefunc(lambda x: filectx(self._repo, self._path,
175 getctx = util.cachefunc(lambda x: filectx(self._repo, self._path,
170 changeid=x,
176 changeid=x,
171 filelog=self._filelog))
177 filelog=self._filelog))
172 hist = self._filelog.annotate(self._filenode)
178 hist = self._filelog.annotate(self._filenode)
173
179
174 return [(getctx(rev), line) for rev, line in hist]
180 return [(getctx(rev), line) for rev, line in hist]
175
181
176 def ancestor(self, fc2):
182 def ancestor(self, fc2):
177 """
183 """
178 find the common ancestor file context, if any, of self, and fc2
184 find the common ancestor file context, if any, of self, and fc2
179 """
185 """
180
186
181 acache = {}
187 acache = {}
182 flcache = {self._path:self._filelog, fc2._path:fc2._filelog}
188 flcache = {self._path:self._filelog, fc2._path:fc2._filelog}
183 def parents(vertex):
189 def parents(vertex):
184 if vertex in acache:
190 if vertex in acache:
185 return acache[vertex]
191 return acache[vertex]
186 f, n = vertex
192 f, n = vertex
187 if f not in flcache:
193 if f not in flcache:
188 flcache[f] = self._repo.file(f)
194 flcache[f] = self._repo.file(f)
189 fl = flcache[f]
195 fl = flcache[f]
190 pl = [ (f,p) for p in fl.parents(n) if p != nullid ]
196 pl = [ (f,p) for p in fl.parents(n) if p != nullid ]
191 re = fl.renamed(n)
197 re = fl.renamed(n)
192 if re:
198 if re:
193 pl.append(re)
199 pl.append(re)
194 acache[vertex]=pl
200 acache[vertex]=pl
195 return pl
201 return pl
196
202
197 a, b = (self._path, self._filenode), (fc2._path, fc2._filenode)
203 a, b = (self._path, self._filenode), (fc2._path, fc2._filenode)
198 v = ancestor.ancestor(a, b, parents)
204 v = ancestor.ancestor(a, b, parents)
199 if v:
205 if v:
200 f,n = v
206 f,n = v
201 return filectx(self._repo, f, fileid=n, filelog=flcache[f])
207 return filectx(self._repo, f, fileid=n, filelog=flcache[f])
202
208
203 return None
209 return None
General Comments 0
You need to be logged in to leave comments. Login now