comparison mercurial/localrepo.py @ 39549:089fc0db0954

hg: allow extra arguments to be passed to repo creation (API) Currently, repository creation is influenced by consulting the ui instance and turning config options into requirements. This means that in order to influence repository creation, you need to define and set a config option and that the option must translate to a requirement stored in the .hg/requires file. This commit introduces a new mechanism to influence repository creation. hg.repository() and hg.peer() have been taught to receive a new optional argument defining extra options to apply to repository creation. This value is passed along to the various instance() functions and can be used to influence repository creation. This will allow us to pass rich data directly to repository creation without having to go through the config layer. It also allows us to be more explicit about the features requested during repository creation and provides a natural point to detect unhandled options influencing repository creation. The new code detects when unknown creation options are present and aborts in that case. .. api:: options can now be passed to influence repository creation The various instance() functions to spawn new peers or repository instances now receive a ``createopts`` argument that can be a dict defining additional options to influence repository creation. localrepo.newreporequirements() also receives this argument. Differential Revision: https://phab.mercurial-scm.org/D4535
author Gregory Szorc <gregory.szorc@gmail.com>
date Tue, 11 Sep 2018 17:11:32 -0700
parents 7ce9dea3a14a
children 261f1e8dc300
comparison
equal deleted inserted replaced
39548:7ce9dea3a14a 39549:089fc0db0954
2378 def undoname(fn): 2378 def undoname(fn):
2379 base, name = os.path.split(fn) 2379 base, name = os.path.split(fn)
2380 assert name.startswith('journal') 2380 assert name.startswith('journal')
2381 return os.path.join(base, name.replace('journal', 'undo', 1)) 2381 return os.path.join(base, name.replace('journal', 'undo', 1))
2382 2382
2383 def instance(ui, path, create, intents=None): 2383 def instance(ui, path, create, intents=None, createopts=None):
2384 if create: 2384 if create:
2385 vfs = vfsmod.vfs(path, expandpath=True, realpath=True) 2385 vfs = vfsmod.vfs(path, expandpath=True, realpath=True)
2386 2386
2387 if vfs.exists('.hg'): 2387 if vfs.exists('.hg'):
2388 raise error.RepoError(_('repository %s already exists') % path) 2388 raise error.RepoError(_('repository %s already exists') % path)
2389 2389
2390 createrepository(ui, vfs) 2390 createrepository(ui, vfs, createopts=createopts)
2391 2391
2392 return localrepository(ui, util.urllocalpath(path), intents=intents) 2392 return localrepository(ui, util.urllocalpath(path), intents=intents)
2393 2393
2394 def islocal(path): 2394 def islocal(path):
2395 return True 2395 return True
2396 2396
2397 def newreporequirements(ui): 2397 def newreporequirements(ui, createopts=None):
2398 """Determine the set of requirements for a new local repository. 2398 """Determine the set of requirements for a new local repository.
2399 2399
2400 Extensions can wrap this function to specify custom requirements for 2400 Extensions can wrap this function to specify custom requirements for
2401 new repositories. 2401 new repositories.
2402 """ 2402 """
2403 createopts = createopts or {}
2404
2403 requirements = {'revlogv1'} 2405 requirements = {'revlogv1'}
2404 if ui.configbool('format', 'usestore'): 2406 if ui.configbool('format', 'usestore'):
2405 requirements.add('store') 2407 requirements.add('store')
2406 if ui.configbool('format', 'usefncache'): 2408 if ui.configbool('format', 'usefncache'):
2407 requirements.add('fncache') 2409 requirements.add('fncache')
2438 if ui.configbool('format', 'internal-phase'): 2440 if ui.configbool('format', 'internal-phase'):
2439 requirements.add('internal-phase') 2441 requirements.add('internal-phase')
2440 2442
2441 return requirements 2443 return requirements
2442 2444
2443 def createrepository(ui, wdirvfs): 2445 def filterknowncreateopts(ui, createopts):
2446 """Filters a dict of repo creation options against options that are known.
2447
2448 Receives a dict of repo creation options and returns a dict of those
2449 options that we don't know how to handle.
2450
2451 This function is called as part of repository creation. If the
2452 returned dict contains any items, repository creation will not
2453 be allowed, as it means there was a request to create a repository
2454 with options not recognized by loaded code.
2455
2456 Extensions can wrap this function to filter out creation options
2457 they know how to handle.
2458 """
2459 return dict(createopts)
2460
2461 def createrepository(ui, wdirvfs, createopts=None):
2444 """Create a new repository in a vfs. 2462 """Create a new repository in a vfs.
2445 2463
2446 ``wdirvfs`` is a vfs instance pointing at the working directory. 2464 ``wdirvfs`` is a vfs instance pointing at the working directory.
2447 ``requirements`` is a set of requirements for the new repository. 2465 ``requirements`` is a set of requirements for the new repository.
2448 """ 2466 """
2449 requirements = newreporequirements(ui) 2467 createopts = createopts or {}
2468
2469 unknownopts = filterknowncreateopts(ui, createopts)
2470
2471 if not isinstance(unknownopts, dict):
2472 raise error.ProgrammingError('filterknowncreateopts() did not return '
2473 'a dict')
2474
2475 if unknownopts:
2476 raise error.Abort(_('unable to create repository because of unknown '
2477 'creation option: %s') %
2478 ', '.sorted(unknownopts),
2479 hint=_('is a required extension not loaded?'))
2480
2481 requirements = newreporequirements(ui, createopts=createopts)
2450 2482
2451 if not wdirvfs.exists(): 2483 if not wdirvfs.exists():
2452 wdirvfs.makedirs() 2484 wdirvfs.makedirs()
2453 2485
2454 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg')) 2486 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))