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