comparison hglib/context.py @ 94:4da6bb8abfcc

context: initial implementation of changectx tries to mimic Mercurial's changectx
author Idan Kamara <idankk86@gmail.com>
date Thu, 22 Dec 2011 19:12:47 +0200
parents
children 2b36619ec0a0
comparison
equal deleted inserted replaced
93:a4fcece7dd8e 94:4da6bb8abfcc
1 import client, util, templates
2
3 _nullcset = ['-1', '000000000000000000000000000000000000000', '', '', '', '']
4
5 class changectx(object):
6 """A changecontext object makes access to data related to a particular
7 changeset convenient."""
8 def __init__(self, repo, changeid=''):
9 """changeid is a revision number, node, or tag"""
10 if changeid == '':
11 changeid = '.'
12 self._repo = repo
13 if isinstance(changeid, client.revision):
14 cset = changeid
15 elif changeid == -1:
16 cset = _nullcset
17 else:
18 if isinstance(changeid, (long, int)):
19 changeid = 'rev(%d)' % changeid
20
21 cset = self._repo.log(changeid)
22 if not len(cset):
23 raise ValueError('changeid %r not found in repo' % changeid)
24 if len(cset) > 1:
25 raise ValueError('changeid must yield a single changeset')
26 cset = cset[0]
27
28 self._rev, self._node, self._tags = cset[:3]
29 self._branch, self._author, self._description = cset[3:]
30
31 self._rev = int(self._rev)
32
33 self._tags = self._tags.split()
34 try:
35 self._tags.remove('tip')
36 except ValueError:
37 pass
38
39 self._ignored = None
40 self._clean = None
41
42 def __str__(self):
43 return self._node[:12]
44
45 def __int__(self):
46 return self._rev
47
48 def __repr__(self):
49 return "<changectx %s>" % str(self)
50
51 def __hash__(self):
52 try:
53 return hash(self._rev)
54 except AttributeError:
55 return id(self)
56
57 def __eq__(self, other):
58 try:
59 return self._rev == other._rev
60 except AttributeError:
61 return False
62
63 def __ne__(self, other):
64 return not (self == other)
65
66 def __nonzero__(self):
67 return self._rev != -1
68
69 def __contains__(self, key):
70 return key in self._manifest
71
72 def __iter__(self):
73 for f in sorted(self._manifest):
74 yield f
75
76 @util.propertycache
77 def _status(self):
78 return self._parsestatus(self._repo.status(change=self))[:4]
79
80 def _parsestatus(self, stat):
81 d = dict((c, []) for c in 'MAR!?IC ')
82 for k, path in stat:
83 d[k].append(path)
84 return d['M'], d['A'], d['R'], d['!'], d['?'], d['I'], d['C']
85
86 def status(self, ignored=False, clean=False):
87 """Explicit status query
88 Unless this method is used to query the working copy status, the
89 _status property will implicitly read the status using its default
90 arguments."""
91 stat = self._parsestatus(self._repo.status(change=self, ignored=ignored,
92 clean=clean))
93 self._unknown = self._ignored = self._clean = None
94 if ignored:
95 self._ignored = stat[5]
96 if clean:
97 self._clean = stat[6]
98 self._status = stat[:4]
99 return stat
100
101 def rev(self):
102 return self._rev
103
104 def node(self):
105 return self._node
106
107 def tags(self):
108 return self._tags
109
110 def branch(self):
111 return self._branch
112
113 def author(self):
114 return self._author
115
116 def user(self):
117 return self._author
118
119 def date(self):
120 return self._date
121
122 def description(self):
123 return self._description
124
125 def files(self):
126 return sorted(self._status[0] + self._status[1] + self._status[2])
127
128 def modified(self):
129 return self._status[0]
130
131 def added(self):
132 return self._status[1]
133
134 def removed(self):
135 return self._status[2]
136
137 def ignored(self):
138 if self._ignored is None:
139 self.status(ignored=True)
140 return self._ignored
141
142 def clean(self):
143 if self._clean is None:
144 self.status(clean=True)
145 return self._clean
146
147 @util.propertycache
148 def _manifest(self):
149 d = {}
150 for node, p, e, s, path in self._repo.manifest(rev=self):
151 d[path] = node
152 return d
153
154 def manifest(self):
155 return self._manifest
156
157 def hex(self):
158 return hex(self._node)
159
160 @util.propertycache
161 def _parents(self):
162 """return contexts for each parent changeset"""
163 par = self._repo.parents(rev=self)
164 if not par:
165 return [changectx(self._repo, -1)]
166 return [changectx(self._repo, int(cset.rev)) for cset in par]
167
168 def parents(self):
169 return self._parents
170
171 def p1(self):
172 return self._parents[0]
173
174 def p2(self):
175 if len(self._parents) == 2:
176 return self._parents[1]
177 return changectx(self._repo, -1)
178
179 @util.propertycache
180 def _bookmarks(self):
181 books = [bm for bm in self._repo.bookmarks()[0] if bm[1] == self._rev]
182
183 bms = []
184 for name, r, n in books:
185 bms.append(name)
186 return bms
187
188 def bookmarks(self):
189 return self._bookmarks
190
191 def children(self):
192 """return contexts for each child changeset"""
193 for c in self._repo.log('children(%s)' % self._node):
194 yield changectx(self._repo, c)
195
196 def ancestors(self):
197 for a in self._repo.log('ancestors(%s)' % self._node):
198 yield changectx(self._repo, a)
199
200 def descendants(self):
201 for d in self._repo.log('descendants(%s)' % self._node):
202 yield changectx(self._repo, d)
203
204 def ancestor(self, c2):
205 """
206 return the ancestor context of self and c2
207 """
208 return changectx(self._repo, 'ancestor(%s, %s)' % (self, n2))