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