comparison mercurial/context.py @ 39958:3d35304bd09b

context: move logic from changectx.__init__ to localrepo.__getitem__ (API) My motivation for this change was to make repo[node] not load the dirstate (more about that in the next patch), but I think it makes more sense this way too. For example, raising RepoLookupError seems to belong better in the repo lookup function (i.e. localrepo.__getitem__). This makes the changectx constructor very simple -- it just assigns the given repo, revnum, and nodeid to properties. Differential Revision: https://phab.mercurial-scm.org/D4827
author Martin von Zweigbergk <martinvonz@google.com>
date Wed, 26 Sep 2018 22:53:14 -0700
parents e1e3d1b498d3
children 43d3b09b3e5a
comparison
equal deleted inserted replaced
39957:e1e3d1b498d3 39958:3d35304bd09b
13 import stat 13 import stat
14 14
15 from .i18n import _ 15 from .i18n import _
16 from .node import ( 16 from .node import (
17 addednodeid, 17 addednodeid,
18 bin,
19 hex, 18 hex,
20 modifiednodeid, 19 modifiednodeid,
21 nullid, 20 nullid,
22 nullrev, 21 nullrev,
23 short, 22 short,
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: