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