Mercurial > python-hglib
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)) |