383 |
382 |
384 class changectx(basectx): |
383 class changectx(basectx): |
385 """A changecontext object makes access to data related to a particular |
384 """A changecontext object makes access to data related to a particular |
386 changeset convenient. It represents a read-only context already present in |
385 changeset convenient. It represents a read-only context already present in |
387 the repo.""" |
386 the repo.""" |
388 def __init__(self, repo, changeid='.'): |
387 def __init__(self, repo, rev, node): |
389 """changeid is a revision number, node, or tag""" |
388 """changeid is a revision number, node, or tag""" |
390 super(changectx, self).__init__(repo) |
389 super(changectx, self).__init__(repo) |
391 |
390 self._rev = rev |
392 try: |
391 self._node = node |
393 if isinstance(changeid, int): |
|
394 self._node = repo.changelog.node(changeid) |
|
395 self._rev = changeid |
|
396 return |
|
397 elif changeid == 'null': |
|
398 self._node = nullid |
|
399 self._rev = nullrev |
|
400 return |
|
401 elif changeid == 'tip': |
|
402 self._node = repo.changelog.tip() |
|
403 self._rev = repo.changelog.rev(self._node) |
|
404 return |
|
405 elif (changeid == '.' |
|
406 or repo.local() and changeid == repo.dirstate.p1()): |
|
407 # this is a hack to delay/avoid loading obsmarkers |
|
408 # when we know that '.' won't be hidden |
|
409 self._node = repo.dirstate.p1() |
|
410 self._rev = repo.unfiltered().changelog.rev(self._node) |
|
411 return |
|
412 elif len(changeid) == 20: |
|
413 try: |
|
414 self._node = changeid |
|
415 self._rev = repo.changelog.rev(changeid) |
|
416 return |
|
417 except error.FilteredLookupError: |
|
418 changeid = hex(changeid) # for the error message |
|
419 raise |
|
420 except LookupError: |
|
421 # check if it might have come from damaged dirstate |
|
422 # |
|
423 # XXX we could avoid the unfiltered if we had a recognizable |
|
424 # exception for filtered changeset access |
|
425 if (repo.local() |
|
426 and changeid in repo.unfiltered().dirstate.parents()): |
|
427 msg = _("working directory has unknown parent '%s'!") |
|
428 raise error.Abort(msg % short(changeid)) |
|
429 changeid = hex(changeid) # for the error message |
|
430 |
|
431 elif len(changeid) == 40: |
|
432 try: |
|
433 self._node = bin(changeid) |
|
434 self._rev = repo.changelog.rev(self._node) |
|
435 return |
|
436 except error.FilteredLookupError: |
|
437 raise |
|
438 except LookupError: |
|
439 pass |
|
440 else: |
|
441 raise error.ProgrammingError( |
|
442 "unsupported changeid '%s' of type %s" % |
|
443 (changeid, type(changeid))) |
|
444 |
|
445 except (error.FilteredIndexError, error.FilteredLookupError): |
|
446 raise error.FilteredRepoLookupError(_("filtered revision '%s'") |
|
447 % pycompat.bytestr(changeid)) |
|
448 except IndexError: |
|
449 pass |
|
450 raise error.RepoLookupError( |
|
451 _("unknown revision '%s'") % changeid) |
|
452 |
392 |
453 def __hash__(self): |
393 def __hash__(self): |
454 try: |
394 try: |
455 return hash(self._rev) |
395 return hash(self._rev) |
456 except AttributeError: |
396 except AttributeError: |