Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/context.py @ 3239:6d98149d70fe
contexts: add working dir and working file contexts
add workingctx
add workingfilectx
extend filectx.annotate for rev=None
extend filectx.ancestor
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 02 Oct 2006 22:03:14 -0500 |
parents | d865390c1781 |
children | 8d4855fd9d7b |
comparison
equal
deleted
inserted
replaced
3238:d865390c1781 | 3239:6d98149d70fe |
---|---|
224 getctx = util.cachefunc(getctx) | 224 getctx = util.cachefunc(getctx) |
225 | 225 |
226 def parents(f): | 226 def parents(f): |
227 # we want to reuse filectx objects as much as possible | 227 # we want to reuse filectx objects as much as possible |
228 p = f._path | 228 p = f._path |
229 pl = [ (p, f._filelog.rev(n)) for n in f._filelog.parents(f._filenode) ] | 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) ] | |
230 | 233 |
231 if follow: | 234 if follow: |
232 r = f.renamed() | 235 r = f.renamed() |
233 if r: | 236 if r: |
234 pl[0] = (r[0], getlog(r[0]).rev(r[1])) | 237 pl[0] = (r[0], getlog(r[0]).rev(r[1])) |
235 | 238 |
236 return [ getctx(p, n) for p, n in pl if n != -1 ] | 239 return [ getctx(p, n) for p, n in pl if n != -1 ] |
237 | 240 |
238 # find all ancestors | 241 # find all ancestors |
239 needed = {self: 1} | 242 needed = {self: 1} |
240 visit = [self] | 243 visit = [self] |
241 files = [self._path] | 244 files = [self._path] |
242 while visit: | 245 while visit: |
277 """ | 280 """ |
278 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 |
279 """ | 282 """ |
280 | 283 |
281 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 | |
282 flcache = {self._path:self._filelog, fc2._path:fc2._filelog} | 292 flcache = {self._path:self._filelog, fc2._path:fc2._filelog} |
283 def parents(vertex): | 293 def parents(vertex): |
284 if vertex in acache: | 294 if vertex in acache: |
285 return acache[vertex] | 295 return acache[vertex] |
286 f, n = vertex | 296 f, n = vertex |
299 if v: | 309 if v: |
300 f,n = v | 310 f,n = v |
301 return filectx(self._repo, f, fileid=n, filelog=flcache[f]) | 311 return filectx(self._repo, f, fileid=n, filelog=flcache[f]) |
302 | 312 |
303 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().coy() | |
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 |