comparison mercurial/localrepo.py @ 39606:c5e6c1ba1c79

hg: don't reuse repo instance after unshare() Unsharing a repository is a pretty invasive procedure and fundamentally changes the behavior of the repository. Currently, hg.unshare() calls into localrepository.__init__ to re-initialize the repository instance. This is a bit hacky. And future commits that refactor how localrepository instances are constructed will make this difficult to support. This commit changes unshare() so it constructs a new repo instance once the unshare I/O has completed. It then poisons the old repo instance so any further use will result in error. Surprisingly, nothing in core appears to access a repo instance after it has been unshared! .. api:: ``hg.unshare()`` now poisons the repo instance so it can't be used. It also returns a new repo instance suitable for interacting with the unshared repository. Differential Revision: https://phab.mercurial-scm.org/D4557
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 12 Sep 2018 19:00:46 -0700
parents 76b58f240821
children 24870f1be088
comparison
equal deleted inserted replaced
39605:23f2299e9e53 39606:c5e6c1ba1c79
2501 hgvfs.append(b'00changelog.i', 2501 hgvfs.append(b'00changelog.i',
2502 b'\0\0\0\2 dummy changelog to prevent using the old repo ' 2502 b'\0\0\0\2 dummy changelog to prevent using the old repo '
2503 b'layout') 2503 b'layout')
2504 2504
2505 scmutil.writerequires(hgvfs, requirements) 2505 scmutil.writerequires(hgvfs, requirements)
2506
2507 def poisonrepository(repo):
2508 """Poison a repository instance so it can no longer be used."""
2509 # Perform any cleanup on the instance.
2510 repo.close()
2511
2512 # Our strategy is to replace the type of the object with one that
2513 # has all attribute lookups result in error.
2514 #
2515 # But we have to allow the close() method because some constructors
2516 # of repos call close() on repo references.
2517 class poisonedrepository(object):
2518 def __getattribute__(self, item):
2519 if item == r'close':
2520 return object.__getattribute__(self, item)
2521
2522 raise error.ProgrammingError('repo instances should not be used '
2523 'after unshare')
2524
2525 def close(self):
2526 pass
2527
2528 # We may have a repoview, which intercepts __setattr__. So be sure
2529 # we operate at the lowest level possible.
2530 object.__setattr__(repo, r'__class__', poisonedrepository)