Mercurial > public > mercurial-scm > hg
comparison mercurial/context.py @ 3241:a184cd0c2db9
Merge with upstream
author | Brendan Cully <brendan@kublai.com> |
---|---|
date | Tue, 03 Oct 2006 12:14:33 -0700 |
parents | f7a8228fde17 8d4855fd9d7b |
children | 1539f788e913 |
comparison
equal
deleted
inserted
replaced
3240:e0069e7fe419 | 3241:a184cd0c2db9 |
---|---|
31 | 31 |
32 def __str__(self): | 32 def __str__(self): |
33 return short(self.node()) | 33 return short(self.node()) |
34 | 34 |
35 def __repr__(self): | 35 def __repr__(self): |
36 return "<changectx %s>" % short(self.node()) | 36 return "<changectx %s>" % str(self) |
37 | 37 |
38 def __eq__(self, other): | 38 def __eq__(self, other): |
39 return self._rev == other._rev | 39 return self._rev == other._rev |
40 | 40 |
41 def __nonzero__(self): | 41 def __nonzero__(self): |
42 return self._rev != -1 | 42 return self._rev != -1 |
43 | 43 |
44 def changeset(self): | 44 def __getattr__(self, name): |
45 try: | 45 if name == '_changeset': |
46 return self._changeset | |
47 except AttributeError: | |
48 self._changeset = self._repo.changelog.read(self.node()) | 46 self._changeset = self._repo.changelog.read(self.node()) |
49 return self._changeset | 47 return self._changeset |
50 | 48 elif name == '_manifest': |
51 def manifest(self): | 49 self._manifest = self._repo.manifest.read(self._changeset[0]) |
52 try: | |
53 return self._manifest | 50 return self._manifest |
54 except AttributeError: | 51 else: |
55 self._manifest = self._repo.manifest.read(self.changeset()[0]) | 52 raise AttributeError, name |
56 return self._manifest | 53 |
54 def changeset(self): return self._changeset | |
55 def manifest(self): return self._manifest | |
57 | 56 |
58 def rev(self): return self._rev | 57 def rev(self): return self._rev |
59 def node(self): return self._node | 58 def node(self): return self._node |
60 def user(self): return self.changeset()[1] | 59 def user(self): return self._changeset[1] |
61 def date(self): return self.changeset()[2] | 60 def date(self): return self._changeset[2] |
62 def files(self): return self.changeset()[3] | 61 def files(self): return self._changeset[3] |
63 def description(self): return self.changeset()[4] | 62 def description(self): return self._changeset[4] |
64 | 63 |
65 def parents(self): | 64 def parents(self): |
66 """return contexts for each parent changeset""" | 65 """return contexts for each parent changeset""" |
67 p = self._repo.changelog.parents(self._node) | 66 p = self._repo.changelog.parents(self._node) |
68 return [ changectx(self._repo, x) for x in p ] | 67 return [ changectx(self._repo, x) for x in p ] |
71 """return contexts for each child changeset""" | 70 """return contexts for each child changeset""" |
72 c = self._repo.changelog.children(self._node) | 71 c = self._repo.changelog.children(self._node) |
73 return [ changectx(self._repo, x) for x in c ] | 72 return [ changectx(self._repo, x) for x in c ] |
74 | 73 |
75 def filenode(self, path): | 74 def filenode(self, path): |
76 node, flag = self._repo.manifest.find(self.changeset()[0], path) | 75 if hasattr(self, "_manifest"): |
76 return self._manifest[path] | |
77 node, flag = self._repo.manifest.find(self._changeset[0], path) | |
77 return node | 78 return node |
78 | 79 |
79 def filectx(self, path, fileid=None): | 80 def filectx(self, path, fileid=None): |
80 """get a file context from this changeset""" | 81 """get a file context from this changeset""" |
81 if fileid is None: | 82 if fileid is None: |
82 fileid = self.filenode(path) | 83 fileid = self.filenode(path) |
83 if not fileid: | 84 return filectx(self._repo, path, fileid=fileid, changectx=self) |
84 raise repo.LookupError(_("'%s' does not exist in changeset %s") % | |
85 (path, hex(self.node()))) | |
86 return filectx(self._repo, path, fileid=fileid) | |
87 | 85 |
88 def filectxs(self): | 86 def filectxs(self): |
89 """generate a file context for each file in this changeset's | 87 """generate a file context for each file in this changeset's |
90 manifest""" | 88 manifest""" |
91 mf = self.manifest() | 89 mf = self.manifest() |
102 return changectx(self._repo, n) | 100 return changectx(self._repo, n) |
103 | 101 |
104 class filectx(object): | 102 class filectx(object): |
105 """A filecontext object makes access to data related to a particular | 103 """A filecontext object makes access to data related to a particular |
106 filerevision convenient.""" | 104 filerevision convenient.""" |
107 def __init__(self, repo_, path, changeid=None, fileid=None, filelog=None): | 105 def __init__(self, repo, path, changeid=None, fileid=None, |
106 filelog=None, changectx=None): | |
108 """changeid can be a changeset revision, node, or tag. | 107 """changeid can be a changeset revision, node, or tag. |
109 fileid can be a file revision or node.""" | 108 fileid can be a file revision or node.""" |
110 self._repo = repo_ | 109 self._repo = repo |
111 self._path = path | 110 self._path = path |
112 | 111 |
113 assert changeid is not None or fileid is not None | 112 assert changeid is not None or fileid is not None |
114 | 113 |
115 if filelog: | 114 if filelog: |
116 self._filelog = filelog | 115 self._filelog = filelog |
117 else: | 116 if changectx: |
118 self._filelog = self._repo.file(self._path) | 117 self._changectx = changectx |
118 self._changeid = changectx.node() | |
119 | 119 |
120 if fileid is None: | 120 if fileid is None: |
121 self._changeid = changeid | 121 self._changeid = changeid |
122 else: | 122 else: |
123 try: | 123 self._fileid = fileid |
124 self._filenode = self._filelog.lookup(fileid) | |
125 except revlog.RevlogError, inst: | |
126 raise repo.LookupError(str(inst)) | |
127 self._changeid = self._filelog.linkrev(self._filenode) | |
128 | 124 |
129 def __getattr__(self, name): | 125 def __getattr__(self, name): |
130 if name == '_changectx': | 126 if name == '_changectx': |
131 self._changectx = changectx(self._repo, self._changeid) | 127 self._changectx = changectx(self._repo, self._changeid) |
132 return self._changectx | 128 return self._changectx |
129 elif name == '_filelog': | |
130 self._filelog = self._repo.file(self._path) | |
131 return self._filelog | |
132 elif name == '_changeid': | |
133 self._changeid = self._filelog.linkrev(self._filenode) | |
134 return self._changeid | |
133 elif name == '_filenode': | 135 elif name == '_filenode': |
134 self._filenode = self._changectx.filenode(self._path) | 136 try: |
137 if hasattr(self, "_fileid"): | |
138 self._filenode = self._filelog.lookup(self._fileid) | |
139 else: | |
140 self._filenode = self._changectx.filenode(self._path) | |
141 except revlog.RevlogError, inst: | |
142 raise repo.LookupError(str(inst)) | |
135 return self._filenode | 143 return self._filenode |
136 elif name == '_filerev': | 144 elif name == '_filerev': |
137 self._filerev = self._filelog.rev(self._filenode) | 145 self._filerev = self._filelog.rev(self._filenode) |
138 return self._filerev | 146 return self._filerev |
139 else: | 147 else: |
144 | 152 |
145 def __str__(self): | 153 def __str__(self): |
146 return "%s@%s" % (self.path(), short(self.node())) | 154 return "%s@%s" % (self.path(), short(self.node())) |
147 | 155 |
148 def __repr__(self): | 156 def __repr__(self): |
149 return "<filectx %s@%s>" % (self.path(), short(self.node())) | 157 return "<filectx %s>" % str(self) |
150 | 158 |
151 def __eq__(self, other): | 159 def __eq__(self, other): |
152 return self._path == other._path and self._changeid == other._changeid | 160 return self._path == other._path and self._changeid == other._changeid |
153 | 161 |
154 def filectx(self, fileid): | 162 def filectx(self, fileid): |
216 getctx = util.cachefunc(getctx) | 224 getctx = util.cachefunc(getctx) |
217 | 225 |
218 def parents(f): | 226 def parents(f): |
219 # we want to reuse filectx objects as much as possible | 227 # we want to reuse filectx objects as much as possible |
220 p = f._path | 228 p = f._path |
221 pl = [ (p, r) for r in f._filelog.parentrevs(f._filerev) ] | 229 if f._filerev is None: # working dir |
230 pl = [ (n.path(), n.filerev()) for n in f.parents() ] | |
231 else: | |
232 pl = [ (p, n) for n in f._filelog.parentrevs(f._filerev) ] | |
222 | 233 |
223 if follow: | 234 if follow: |
224 r = f.renamed() | 235 r = f.renamed() |
225 if r: | 236 if r: |
226 pl[0] = (r[0], getlog(r[0]).rev(r[1])) | 237 pl[0] = (r[0], getlog(r[0]).rev(r[1])) |
269 """ | 280 """ |
270 find the common ancestor file context, if any, of self, and fc2 | 281 find the common ancestor file context, if any, of self, and fc2 |
271 """ | 282 """ |
272 | 283 |
273 acache = {} | 284 acache = {} |
285 | |
286 # prime the ancestor cache for the working directory | |
287 for c in (self, fc2): | |
288 if c._filerev == None: | |
289 pl = [ (n.path(), n.filenode()) for n in c.parents() ] | |
290 acache[(c._path, None)] = pl | |
291 | |
274 flcache = {self._path:self._filelog, fc2._path:fc2._filelog} | 292 flcache = {self._path:self._filelog, fc2._path:fc2._filelog} |
275 def parents(vertex): | 293 def parents(vertex): |
276 if vertex in acache: | 294 if vertex in acache: |
277 return acache[vertex] | 295 return acache[vertex] |
278 f, n = vertex | 296 f, n = vertex |
291 if v: | 309 if v: |
292 f,n = v | 310 f,n = v |
293 return filectx(self._repo, f, fileid=n, filelog=flcache[f]) | 311 return filectx(self._repo, f, fileid=n, filelog=flcache[f]) |
294 | 312 |
295 return None | 313 return None |
314 | |
315 class workingctx(changectx): | |
316 """A workingctx object makes access to data related to | |
317 the current working directory convenient.""" | |
318 def __init__(self, repo): | |
319 self._repo = repo | |
320 self._rev = None | |
321 self._node = None | |
322 | |
323 def __str__(self): | |
324 return "." | |
325 | |
326 def __nonzero__(self): | |
327 return True | |
328 | |
329 def __getattr__(self, name): | |
330 if name == '_parents': | |
331 self._parents = self._repo.parents() | |
332 return self._parents | |
333 if name == '_status': | |
334 self._status = self._repo.status() | |
335 return self._status | |
336 if name == '_manifest': | |
337 self._buildmanifest() | |
338 return self._manifest | |
339 else: | |
340 raise AttributeError, name | |
341 | |
342 def _buildmanifest(self): | |
343 """generate a manifest corresponding to the working directory""" | |
344 | |
345 man = self._parents[0].manifest().copy() | |
346 copied = self._repo.dirstate.copies() | |
347 modified, added, removed, deleted, unknown = self._status[:5] | |
348 for i,l in (("a", added), ("m", modified), ("u", unknown)): | |
349 for f in l: | |
350 man[f] = man.get(copied.get(f, f), nullid) + i | |
351 man.set(f, util.is_exec(self._repo.wjoin(f), man.execf(f))) | |
352 | |
353 for f in deleted + removed: | |
354 del man[f] | |
355 | |
356 self._manifest = man | |
357 | |
358 def manifest(self): return self._manifest | |
359 | |
360 def user(self): return self._repo.ui.username() | |
361 def date(self): return util.makedate() | |
362 def description(self): return "" | |
363 def files(self): | |
364 f = self.modified() + self.added() + self.removed() | |
365 f.sort() | |
366 return f | |
367 | |
368 def modified(self): return self._status[0] | |
369 def added(self): return self._status[1] | |
370 def removed(self): return self._status[2] | |
371 def deleted(self): return self._status[3] | |
372 def unknown(self): return self._status[4] | |
373 def clean(self): return self._status[5] | |
374 | |
375 def parents(self): | |
376 """return contexts for each parent changeset""" | |
377 return self._parents | |
378 | |
379 def children(self): | |
380 return [] | |
381 | |
382 def filectx(self, path): | |
383 """get a file context from the working directory""" | |
384 return workingfilectx(self._repo, path, workingctx=self) | |
385 | |
386 def ancestor(self, c2): | |
387 """return the ancestor context of self and c2""" | |
388 return self._parents[0].ancestor(c2) # punt on two parents for now | |
389 | |
390 class workingfilectx(filectx): | |
391 """A workingfilectx object makes access to data related to a particular | |
392 file in the working directory convenient.""" | |
393 def __init__(self, repo, path, filelog=None, workingctx=None): | |
394 """changeid can be a changeset revision, node, or tag. | |
395 fileid can be a file revision or node.""" | |
396 self._repo = repo | |
397 self._path = path | |
398 self._changeid = None | |
399 self._filerev = self._filenode = None | |
400 | |
401 if filelog: | |
402 self._filelog = filelog | |
403 if workingctx: | |
404 self._changectx = workingctx | |
405 | |
406 def __getattr__(self, name): | |
407 if name == '_changectx': | |
408 self._changectx = workingctx(repo) | |
409 return self._changectx | |
410 elif name == '_repopath': | |
411 self._repopath = self._repo.dirstate.copied(p) or self._path | |
412 elif name == '_filelog': | |
413 self._filelog = self._repo.file(self._repopath) | |
414 return self._filelog | |
415 else: | |
416 raise AttributeError, name | |
417 | |
418 def __nonzero__(self): | |
419 return True | |
420 | |
421 def __str__(self): | |
422 return "%s@." % self.path() | |
423 | |
424 def filectx(self, fileid): | |
425 '''opens an arbitrary revision of the file without | |
426 opening a new filelog''' | |
427 return filectx(self._repo, self._repopath, fileid=fileid, | |
428 filelog=self._filelog) | |
429 | |
430 def rev(self): | |
431 if hasattr(self, "_changectx"): | |
432 return self._changectx.rev() | |
433 return self._filelog.linkrev(self._filenode) | |
434 | |
435 def data(self): return self._repo.wread(self._path) | |
436 def renamed(self): | |
437 rp = self._repopath | |
438 if rp == self._path: | |
439 return None | |
440 return rp, self._workingctx._parents._manifest.get(rp, nullid) | |
441 | |
442 def parents(self): | |
443 '''return parent filectxs, following copies if necessary''' | |
444 p = self._path | |
445 rp = self._repopath | |
446 pcl = self._workingctx._parents | |
447 fl = self._filelog | |
448 pl = [ (rp, pcl[0]._manifest.get(rp, nullid), fl) ] | |
449 if len(pcl) > 1: | |
450 if rp != p: | |
451 fl = None | |
452 pl.append((p, pcl[1]._manifest.get(p, nullid), fl)) | |
453 | |
454 return [ filectx(self._repo, p, fileid=n, filelog=l) | |
455 for p,n,l in pl if n != nullid ] | |
456 | |
457 def children(self): | |
458 return [] | |
459 |