Details
Details
- Reviewers
indygreg - Group Reviewers
hg-reviewers - Commits
- rHGbc01f48c18cc: narrowbundle2: make constants ALLCAPS to be a bit more readable
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
indygreg |
hg-reviewers |
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | hgext/narrow/narrowbundle2.py (62 lines) | |||
M | hgext/narrow/narrowcommands.py (2 lines) |
Status | Author | Revision | |
---|---|---|---|
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 | ||
Closed | durin42 |
wireproto, | wireproto, | ||||
) | ) | ||||
from . import ( | from . import ( | ||||
narrowrepo, | narrowrepo, | ||||
narrowspec, | narrowspec, | ||||
) | ) | ||||
narrowcap = 'narrow' | NARROWCAP = 'narrow' | ||||
narrowacl_section = 'narrowhgacl' | NARROWACL_SECTION = 'narrowhgacl' | ||||
changespecpart = narrowcap + ':changespec' | CHANGESPECPART = NARROWCAP + ':changespec' | ||||
specpart = narrowcap + ':spec' | SPECPART = NARROWCAP + ':spec' | ||||
specpart_include = 'include' | SPECPART_INCLUDE = 'include' | ||||
specpart_exclude = 'exclude' | SPECPART_EXCLUDE = 'exclude' | ||||
killnodesignal = 'KILL' | KILLNODESIGNAL = 'KILL' | ||||
donesignal = 'DONE' | DONESIGNAL = 'DONE' | ||||
elidedcsheader = '>20s20s20sl' # cset id, p1, p2, len(text) | ELIDEDCSHEADER = '>20s20s20sl' # cset id, p1, p2, len(text) | ||||
elidedmfheader = '>20s20s20s20sl' # manifest id, p1, p2, link id, len(text) | ELIDEDMFHEADER = '>20s20s20s20sl' # manifest id, p1, p2, link id, len(text) | ||||
csheadersize = struct.calcsize(elidedcsheader) | CSHEADERSIZE = struct.calcsize(ELIDEDCSHEADER) | ||||
mfheadersize = struct.calcsize(elidedmfheader) | MFHEADERSIZE = struct.calcsize(ELIDEDMFHEADER) | ||||
# When advertising capabilities, always include narrow clone support. | # When advertising capabilities, always include narrow clone support. | ||||
def getrepocaps_narrow(orig, repo, **kwargs): | def getrepocaps_narrow(orig, repo, **kwargs): | ||||
caps = orig(repo, **kwargs) | caps = orig(repo, **kwargs) | ||||
caps[narrowcap] = ['v0'] | caps[NARROWCAP] = ['v0'] | ||||
return caps | return caps | ||||
def _computeellipsis(repo, common, heads, known, match, depth=None): | def _computeellipsis(repo, common, heads, known, match, depth=None): | ||||
"""Compute the shape of a narrowed DAG. | """Compute the shape of a narrowed DAG. | ||||
Args: | Args: | ||||
repo: The repository we're transferring. | repo: The repository we're transferring. | ||||
common: The roots of the DAG range we're transferring. | common: The roots of the DAG range we're transferring. | ||||
wrappedgetbundler): | wrappedgetbundler): | ||||
cg = changegroup.makestream(repo, outgoing, version, source) | cg = changegroup.makestream(repo, outgoing, version, source) | ||||
part = bundler.newpart('changegroup', data=cg) | part = bundler.newpart('changegroup', data=cg) | ||||
part.addparam('version', version) | part.addparam('version', version) | ||||
if 'treemanifest' in repo.requirements: | if 'treemanifest' in repo.requirements: | ||||
part.addparam('treemanifest', '1') | part.addparam('treemanifest', '1') | ||||
if include or exclude: | if include or exclude: | ||||
narrowspecpart = bundler.newpart(specpart) | narrowspecpart = bundler.newpart(SPECPART) | ||||
if include: | if include: | ||||
narrowspecpart.addparam( | narrowspecpart.addparam( | ||||
specpart_include, '\n'.join(include), mandatory=True) | SPECPART_INCLUDE, '\n'.join(include), mandatory=True) | ||||
if exclude: | if exclude: | ||||
narrowspecpart.addparam( | narrowspecpart.addparam( | ||||
specpart_exclude, '\n'.join(exclude), mandatory=True) | SPECPART_EXCLUDE, '\n'.join(exclude), mandatory=True) | ||||
return | return | ||||
depth = kwargs.get('depth', None) | depth = kwargs.get('depth', None) | ||||
if depth is not None: | if depth is not None: | ||||
depth = int(depth) | depth = int(depth) | ||||
if depth < 1: | if depth < 1: | ||||
raise error.Abort(_('depth must be positive, got %d') % depth) | raise error.Abort(_('depth must be positive, got %d') % depth) | ||||
known = set(repo.revs("%ln & ::%ln", known, common)) | known = set(repo.revs("%ln & ::%ln", known, common)) | ||||
# TODO: we could send only roots() of this set, and the | # TODO: we could send only roots() of this set, and the | ||||
# list of nodes in common, and the client could work out | # list of nodes in common, and the client could work out | ||||
# what to strip, instead of us explicitly sending every | # what to strip, instead of us explicitly sending every | ||||
# single node. | # single node. | ||||
deadrevs = known | deadrevs = known | ||||
def genkills(): | def genkills(): | ||||
for r in deadrevs: | for r in deadrevs: | ||||
yield killnodesignal | yield KILLNODESIGNAL | ||||
yield repo.changelog.node(r) | yield repo.changelog.node(r) | ||||
yield donesignal | yield DONESIGNAL | ||||
bundler.newpart(changespecpart, data=genkills()) | bundler.newpart(CHANGESPECPART, data=genkills()) | ||||
newvisit, newfull, newellipsis = _computeellipsis( | newvisit, newfull, newellipsis = _computeellipsis( | ||||
repo, set(), common, known, newmatch) | repo, set(), common, known, newmatch) | ||||
if newvisit: | if newvisit: | ||||
cg = _packellipsischangegroup( | cg = _packellipsischangegroup( | ||||
repo, common, newmatch, newfull, newellipsis, | repo, common, newmatch, newfull, newellipsis, | ||||
newvisit, depth, source, version) | newvisit, depth, source, version) | ||||
part = bundler.newpart('changegroup', data=cg) | part = bundler.newpart('changegroup', data=cg) | ||||
part.addparam('version', version) | part.addparam('version', version) | ||||
part = bundler.newpart('changegroup', data=cg) | part = bundler.newpart('changegroup', data=cg) | ||||
part.addparam('version', version) | part.addparam('version', version) | ||||
if 'treemanifest' in repo.requirements: | if 'treemanifest' in repo.requirements: | ||||
part.addparam('treemanifest', '1') | part.addparam('treemanifest', '1') | ||||
def applyacl_narrow(repo, kwargs): | def applyacl_narrow(repo, kwargs): | ||||
username = repo.ui.shortuser(repo.ui.username()) | username = repo.ui.shortuser(repo.ui.username()) | ||||
user_includes = repo.ui.configlist( | user_includes = repo.ui.configlist( | ||||
narrowacl_section, username + '.includes', | NARROWACL_SECTION, username + '.includes', | ||||
repo.ui.configlist(narrowacl_section, 'default.includes')) | repo.ui.configlist(NARROWACL_SECTION, 'default.includes')) | ||||
user_excludes = repo.ui.configlist( | user_excludes = repo.ui.configlist( | ||||
narrowacl_section, username + '.excludes', | NARROWACL_SECTION, username + '.excludes', | ||||
repo.ui.configlist(narrowacl_section, 'default.excludes')) | repo.ui.configlist(NARROWACL_SECTION, 'default.excludes')) | ||||
if not user_includes: | if not user_includes: | ||||
raise error.Abort(_("{} configuration for user {} is empty") | raise error.Abort(_("{} configuration for user {} is empty") | ||||
.format(narrowacl_section, username)) | .format(NARROWACL_SECTION, username)) | ||||
user_includes = [ | user_includes = [ | ||||
'path:.' if p == '*' else 'path:' + p for p in user_includes] | 'path:.' if p == '*' else 'path:' + p for p in user_includes] | ||||
user_excludes = [ | user_excludes = [ | ||||
'path:.' if p == '*' else 'path:' + p for p in user_excludes] | 'path:.' if p == '*' else 'path:' + p for p in user_excludes] | ||||
req_includes = set(kwargs.get('includepats', [])) | req_includes = set(kwargs.get('includepats', [])) | ||||
req_excludes = set(kwargs.get('excludepats', [])) | req_excludes = set(kwargs.get('excludepats', [])) | ||||
new_args = {} | new_args = {} | ||||
new_args.update(kwargs) | new_args.update(kwargs) | ||||
new_args['includepats'] = req_includes | new_args['includepats'] = req_includes | ||||
if req_excludes: | if req_excludes: | ||||
new_args['excludepats'] = req_excludes | new_args['excludepats'] = req_excludes | ||||
return new_args | return new_args | ||||
@bundle2.parthandler(specpart, (specpart_include, specpart_exclude)) | @bundle2.parthandler(SPECPART, (SPECPART_INCLUDE, SPECPART_EXCLUDE)) | ||||
def _handlechangespec_2(op, inpart): | def _handlechangespec_2(op, inpart): | ||||
includepats = set(inpart.params.get(specpart_include, '').splitlines()) | includepats = set(inpart.params.get(SPECPART_INCLUDE, '').splitlines()) | ||||
excludepats = set(inpart.params.get(specpart_exclude, '').splitlines()) | excludepats = set(inpart.params.get(SPECPART_EXCLUDE, '').splitlines()) | ||||
narrowspec.save(op.repo, includepats, excludepats) | narrowspec.save(op.repo, includepats, excludepats) | ||||
if not narrowrepo.requirement in op.repo.requirements: | if not narrowrepo.requirement in op.repo.requirements: | ||||
op.repo.requirements.add(narrowrepo.requirement) | op.repo.requirements.add(narrowrepo.requirement) | ||||
op.repo._writerequirements() | op.repo._writerequirements() | ||||
op.repo.invalidate(clearfilecache=True) | op.repo.invalidate(clearfilecache=True) | ||||
@bundle2.parthandler(changespecpart) | @bundle2.parthandler(CHANGESPECPART) | ||||
def _handlechangespec(op, inpart): | def _handlechangespec(op, inpart): | ||||
repo = op.repo | repo = op.repo | ||||
cl = repo.changelog | cl = repo.changelog | ||||
# changesets which need to be stripped entirely. either they're no longer | # changesets which need to be stripped entirely. either they're no longer | ||||
# needed in the new narrow spec, or the server is sending a replacement | # needed in the new narrow spec, or the server is sending a replacement | ||||
# in the changegroup part. | # in the changegroup part. | ||||
clkills = set() | clkills = set() | ||||
# A changespec part contains all the updates to ellipsis nodes | # A changespec part contains all the updates to ellipsis nodes | ||||
# that will happen as a result of widening or narrowing a | # that will happen as a result of widening or narrowing a | ||||
# repo. All the changes that this block encounters are ellipsis | # repo. All the changes that this block encounters are ellipsis | ||||
# nodes or flags to kill an existing ellipsis. | # nodes or flags to kill an existing ellipsis. | ||||
chunksignal = changegroup.readexactly(inpart, 4) | chunksignal = changegroup.readexactly(inpart, 4) | ||||
while chunksignal != donesignal: | while chunksignal != DONESIGNAL: | ||||
if chunksignal == killnodesignal: | if chunksignal == KILLNODESIGNAL: | ||||
# a node used to be an ellipsis but isn't anymore | # a node used to be an ellipsis but isn't anymore | ||||
ck = changegroup.readexactly(inpart, 20) | ck = changegroup.readexactly(inpart, 20) | ||||
if cl.hasnode(ck): | if cl.hasnode(ck): | ||||
clkills.add(ck) | clkills.add(ck) | ||||
else: | else: | ||||
raise error.Abort( | raise error.Abort( | ||||
_('unexpected changespec node chunk type: %s') % chunksignal) | _('unexpected changespec node chunk type: %s') % chunksignal) | ||||
chunksignal = changegroup.readexactly(inpart, 4) | chunksignal = changegroup.readexactly(inpart, 4) | ||||
wireproto.gboptsmap['includepats'] = 'csv' | wireproto.gboptsmap['includepats'] = 'csv' | ||||
wireproto.gboptsmap['excludepats'] = 'csv' | wireproto.gboptsmap['excludepats'] = 'csv' | ||||
wireproto.gboptsmap['known'] = 'csv' | wireproto.gboptsmap['known'] = 'csv' | ||||
# Extend changegroup serving to handle requests from narrow clients. | # Extend changegroup serving to handle requests from narrow clients. | ||||
origcgfn = exchange.getbundle2partsmapping['changegroup'] | origcgfn = exchange.getbundle2partsmapping['changegroup'] | ||||
def wrappedcgfn(*args, **kwargs): | def wrappedcgfn(*args, **kwargs): | ||||
repo = args[1] | repo = args[1] | ||||
if repo.ui.has_section(narrowacl_section): | if repo.ui.has_section(NARROWACL_SECTION): | ||||
getbundlechangegrouppart_narrow( | getbundlechangegrouppart_narrow( | ||||
*args, **applyacl_narrow(repo, kwargs)) | *args, **applyacl_narrow(repo, kwargs)) | ||||
elif kwargs.get('narrow', False): | elif kwargs.get('narrow', False): | ||||
getbundlechangegrouppart_narrow(*args, **kwargs) | getbundlechangegrouppart_narrow(*args, **kwargs) | ||||
else: | else: | ||||
origcgfn(*args, **kwargs) | origcgfn(*args, **kwargs) | ||||
exchange.getbundle2partsmapping['changegroup'] = wrappedcgfn | exchange.getbundle2partsmapping['changegroup'] = wrappedcgfn | ||||
# Extend changegroup receiver so client can fixup after widen requests. | # Extend changegroup receiver so client can fixup after widen requests. | ||||
origcghandler = bundle2.parthandlermapping['changegroup'] | origcghandler = bundle2.parthandlermapping['changegroup'] | ||||
def wrappedcghandler(op, inpart): | def wrappedcghandler(op, inpart): | ||||
origcghandler(op, inpart) | origcghandler(op, inpart) | ||||
if util.safehasattr(op, '_widen_bundle'): | if util.safehasattr(op, '_widen_bundle'): | ||||
handlechangegroup_widen(op, inpart) | handlechangegroup_widen(op, inpart) | ||||
wrappedcghandler.params = origcghandler.params | wrappedcghandler.params = origcghandler.params | ||||
bundle2.parthandlermapping['changegroup'] = wrappedcghandler | bundle2.parthandlermapping['changegroup'] = wrappedcghandler |
opts['exclude'] = excludes | opts['exclude'] = excludes | ||||
return orig(ui, repo, *args, **opts) | return orig(ui, repo, *args, **opts) | ||||
def pullbundle2extraprepare(orig, pullop, kwargs): | def pullbundle2extraprepare(orig, pullop, kwargs): | ||||
repo = pullop.repo | repo = pullop.repo | ||||
if narrowrepo.requirement not in repo.requirements: | if narrowrepo.requirement not in repo.requirements: | ||||
return orig(pullop, kwargs) | return orig(pullop, kwargs) | ||||
if narrowbundle2.narrowcap not in pullop.remotebundle2caps: | if narrowbundle2.NARROWCAP not in pullop.remotebundle2caps: | ||||
raise error.Abort(_("server doesn't support narrow clones")) | raise error.Abort(_("server doesn't support narrow clones")) | ||||
orig(pullop, kwargs) | orig(pullop, kwargs) | ||||
kwargs['narrow'] = True | kwargs['narrow'] = True | ||||
include, exclude = repo.narrowpats | include, exclude = repo.narrowpats | ||||
kwargs['oldincludepats'] = include | kwargs['oldincludepats'] = include | ||||
kwargs['oldexcludepats'] = exclude | kwargs['oldexcludepats'] = exclude | ||||
kwargs['includepats'] = include | kwargs['includepats'] = include | ||||
kwargs['excludepats'] = exclude | kwargs['excludepats'] = exclude |