comparison mercurial/localrepo.py @ 45483:d252f51ab032

share: introduce config option to store requires in .hg/store This introduces a config option which enabled stores the requirements on a repository in store instead. When enabled, `.hg/requires` will contain the `share-safe` requirement which marks that the requirements are present in the store. This is done so that repository requirements can be shared with shares made using `hg share` command. After this patch, `hg share` checks whether the source repository has share-safe requirement, if yes, it does not copy the requirements. Test for the new functionality is added and a test case in exitsing share tests is also added. Differential Revision: https://phab.mercurial-scm.org/D8633
author Pulkit Goyal <7895pulkit@gmail.com>
date Tue, 14 Apr 2020 21:07:09 +0530
parents 4a0ccbecbaa6
children b71858b42963
comparison
equal deleted inserted replaced
45482:9a99ab8217bd 45483:d252f51ab032
543 ) 543 )
544 544
545 raise error.RepoError(_(b'repository %s not found') % path) 545 raise error.RepoError(_(b'repository %s not found') % path)
546 546
547 requirements = _readrequires(hgvfs, True) 547 requirements = _readrequires(hgvfs, True)
548 shared = (
549 requirementsmod.SHARED_REQUIREMENT in requirements
550 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
551 )
552 if shared:
553 sharedvfs = _getsharedvfs(hgvfs, requirements)
554
555 # if .hg/requires contains the sharesafe requirement, it means
556 # there exists a `.hg/store/requires` too and we should read it
557 # NOTE: presence of SHARESAFE_REQUIREMENT imply that store requirement
558 # is present. We never write SHARESAFE_REQUIREMENT for a repo if store
559 # is not present, refer checkrequirementscompat() for that
560 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
561 if shared:
562 # This is a shared repo
563 storevfs = vfsmod.vfs(sharedvfs.join(b'store'))
564 else:
565 storevfs = vfsmod.vfs(hgvfs.join(b'store'))
566
567 requirements |= _readrequires(storevfs, False)
548 568
549 # The .hg/hgrc file may load extensions or contain config options 569 # The .hg/hgrc file may load extensions or contain config options
550 # that influence repository construction. Attempt to load it and 570 # that influence repository construction. Attempt to load it and
551 # process any new extensions that it may have pulled in. 571 # process any new extensions that it may have pulled in.
552 if loadhgrc(ui, wdirvfs, hgvfs, requirements): 572 if loadhgrc(ui, wdirvfs, hgvfs, requirements):
585 605
586 # The "store" part of the repository holds versioned data. How it is 606 # The "store" part of the repository holds versioned data. How it is
587 # accessed is determined by various requirements. If `shared` or 607 # accessed is determined by various requirements. If `shared` or
588 # `relshared` requirements are present, this indicates current repository 608 # `relshared` requirements are present, this indicates current repository
589 # is a share and store exists in path mentioned in `.hg/sharedpath` 609 # is a share and store exists in path mentioned in `.hg/sharedpath`
590 shared = (
591 requirementsmod.SHARED_REQUIREMENT in requirements
592 or requirementsmod.RELATIVE_SHARED_REQUIREMENT in requirements
593 )
594 if shared: 610 if shared:
595 sharedvfs = _getsharedvfs(hgvfs, requirements)
596 storebasepath = sharedvfs.base 611 storebasepath = sharedvfs.base
597 cachepath = sharedvfs.join(b'cache') 612 cachepath = sharedvfs.join(b'cache')
598 features.add(repository.REPO_FEATURE_SHARED_STORAGE) 613 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
599 else: 614 else:
600 storebasepath = hgvfs.base 615 storebasepath = hgvfs.base
1046 requirementsmod.REVLOGV2_REQUIREMENT, 1061 requirementsmod.REVLOGV2_REQUIREMENT,
1047 requirementsmod.SIDEDATA_REQUIREMENT, 1062 requirementsmod.SIDEDATA_REQUIREMENT,
1048 requirementsmod.SPARSEREVLOG_REQUIREMENT, 1063 requirementsmod.SPARSEREVLOG_REQUIREMENT,
1049 requirementsmod.NODEMAP_REQUIREMENT, 1064 requirementsmod.NODEMAP_REQUIREMENT,
1050 bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT, 1065 bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
1066 requirementsmod.SHARESAFE_REQUIREMENT,
1051 } 1067 }
1052 _basesupported = supportedformats | { 1068 _basesupported = supportedformats | {
1053 b'store', 1069 b'store',
1054 b'fncache', 1070 b'fncache',
1055 requirementsmod.SHARED_REQUIREMENT, 1071 requirementsmod.SHARED_REQUIREMENT,
3327 requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT) 3343 requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3328 3344
3329 if ui.configbool(b'format', b'use-persistent-nodemap'): 3345 if ui.configbool(b'format', b'use-persistent-nodemap'):
3330 requirements.add(requirementsmod.NODEMAP_REQUIREMENT) 3346 requirements.add(requirementsmod.NODEMAP_REQUIREMENT)
3331 3347
3348 # if share-safe is enabled, let's create the new repository with the new
3349 # requirement
3350 if ui.configbool(b'format', b'exp-share-safe'):
3351 requirements.add(requirementsmod.SHARESAFE_REQUIREMENT)
3352
3332 return requirements 3353 return requirements
3333 3354
3334 3355
3335 def checkrequirementscompat(ui, requirements): 3356 def checkrequirementscompat(ui, requirements):
3336 """ Checks compatibility of repository requirements enabled and disabled. 3357 """ Checks compatibility of repository requirements enabled and disabled.
3359 _( 3380 _(
3360 b"cannot create shared repository as source was created" 3381 b"cannot create shared repository as source was created"
3361 b" with 'format.usestore' config disabled" 3382 b" with 'format.usestore' config disabled"
3362 ) 3383 )
3363 ) 3384 )
3385
3386 if requirementsmod.SHARESAFE_REQUIREMENT in requirements:
3387 ui.warn(
3388 _(
3389 b"ignoring enabled 'format.exp-share-safe' config because "
3390 b"it is incompatible with disabled 'format.usestore'"
3391 b" config\n"
3392 )
3393 )
3394 dropped.add(requirementsmod.SHARESAFE_REQUIREMENT)
3364 3395
3365 return dropped 3396 return dropped
3366 3397
3367 3398
3368 def filterknowncreateopts(ui, createopts): 3399 def filterknowncreateopts(ui, createopts):
3484 b'00changelog.i', 3515 b'00changelog.i',
3485 b'\0\0\0\2 dummy changelog to prevent using the old repo ' 3516 b'\0\0\0\2 dummy changelog to prevent using the old repo '
3486 b'layout', 3517 b'layout',
3487 ) 3518 )
3488 3519
3489 scmutil.writerequires(hgvfs, requirements) 3520 # Filter the requirements into working copy and store ones
3521 wcreq, storereq = scmutil.filterrequirements(requirements)
3522 # write working copy ones
3523 scmutil.writerequires(hgvfs, wcreq)
3524 # If there are store requirements and the current repository
3525 # is not a shared one, write stored requirements
3526 # For new shared repository, we don't need to write the store
3527 # requirements as they are already present in store requires
3528 if storereq and b'sharedrepo' not in createopts:
3529 scmutil.writerequires(hgvfs, wcreq)
3530 storevfs = vfsmod.vfs(hgvfs.join(b'store'), cacheaudited=True)
3531 scmutil.writerequires(storevfs, storereq)
3490 3532
3491 # Write out file telling readers where to find the shared store. 3533 # Write out file telling readers where to find the shared store.
3492 if b'sharedrepo' in createopts: 3534 if b'sharedrepo' in createopts:
3493 hgvfs.write(b'sharedpath', sharedpath) 3535 hgvfs.write(b'sharedpath', sharedpath)
3494 3536