comparison mercurial/hg.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 cb675e95a2c2
children 4ece3cdfd907
comparison
equal deleted inserted replaced
39605:23f2299e9e53 39606:c5e6c1ba1c79
305 305
306 def unshare(ui, repo): 306 def unshare(ui, repo):
307 """convert a shared repository to a normal one 307 """convert a shared repository to a normal one
308 308
309 Copy the store data to the repo and remove the sharedpath data. 309 Copy the store data to the repo and remove the sharedpath data.
310
311 Returns a new repository object representing the unshared repository.
312
313 The passed repository object is not usable after this function is
314 called.
310 """ 315 """
311 316
312 destlock = lock = None 317 destlock = lock = None
313 lock = repo.lock() 318 lock = repo.lock()
314 try: 319 try:
327 repo._writerequirements() 332 repo._writerequirements()
328 finally: 333 finally:
329 destlock and destlock.release() 334 destlock and destlock.release()
330 lock and lock.release() 335 lock and lock.release()
331 336
332 # update store, spath, svfs and sjoin of repo 337 # Removing share changes some fundamental properties of the repo instance.
333 repo.unfiltered().__init__(repo.baseui, repo.root) 338 # So we instantiate a new repo object and operate on it rather than
339 # try to keep the existing repo usable.
340 newrepo = repository(repo.baseui, repo.root, create=False)
334 341
335 # TODO: figure out how to access subrepos that exist, but were previously 342 # TODO: figure out how to access subrepos that exist, but were previously
336 # removed from .hgsub 343 # removed from .hgsub
337 c = repo['.'] 344 c = newrepo['.']
338 subs = c.substate 345 subs = c.substate
339 for s in sorted(subs): 346 for s in sorted(subs):
340 c.sub(s).unshare() 347 c.sub(s).unshare()
348
349 localrepo.poisonrepository(repo)
350
351 return newrepo
341 352
342 def postshare(sourcerepo, destrepo, bookmarks=True, defaultpath=None): 353 def postshare(sourcerepo, destrepo, bookmarks=True, defaultpath=None):
343 """Called after a new shared repo is created. 354 """Called after a new shared repo is created.
344 355
345 The new repo only has a requirements file and pointer to the source. 356 The new repo only has a requirements file and pointer to the source.