##// END OF EJS Templates
phase: expose a `_phase(idx)` revset...
phase: expose a `_phase(idx)` revset Internally phase related revset are calling the `_phase` function. We expose it as an internal revset. This is useful to refer to phase in revset doing debatable things around the phase name.

File last commit:

r38908:576eef1a default
r39310:31c0ee6e default
Show More
narrowspec.py
198 lines | 6.8 KiB | text/x-python | PythonLexer
Gregory Szorc
narrowspec: move module into core...
r36178 # narrowspec.py - methods for working with a narrow view of a repository
#
# Copyright 2017 Google, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import errno
from .i18n import _
from . import (
error,
match as matchmod,
Martin von Zweigbergk
narrow: call narrowspec.{save,restore,clear}backup directly...
r38905 repository,
Pulkit Goyal
narrowspec: use sparse.parseconfig() to parse narrowspec file (BC)...
r38875 sparse,
Gregory Szorc
narrowspec: move module into core...
r36178 util,
)
FILENAME = 'narrowspec'
def parseserverpatterns(text):
"""Parses the narrowspec format that's returned by the server."""
includepats = set()
excludepats = set()
# We get one entry per line, in the format "<key> <value>".
# It's OK for value to contain other spaces.
for kp in (l.split(' ', 1) for l in text.splitlines()):
if len(kp) != 2:
raise error.Abort(_('Invalid narrowspec pattern line: "%s"') % kp)
key = kp[0]
pat = kp[1]
if key == 'include':
includepats.add(pat)
elif key == 'exclude':
excludepats.add(pat)
else:
raise error.Abort(_('Invalid key "%s" in server response') % key)
return includepats, excludepats
def normalizesplitpattern(kind, pat):
"""Returns the normalized version of a pattern and kind.
Returns a tuple with the normalized kind and normalized pattern.
"""
pat = pat.rstrip('/')
_validatepattern(pat)
return kind, pat
def _numlines(s):
"""Returns the number of lines in s, including ending empty lines."""
# We use splitlines because it is Unicode-friendly and thus Python 3
# compatible. However, it does not count empty lines at the end, so trick
# it by adding a character at the end.
return len((s + 'x').splitlines())
def _validatepattern(pat):
"""Validates the pattern and aborts if it is invalid.
Patterns are stored in the narrowspec as newline-separated
POSIX-style bytestring paths. There's no escaping.
"""
# We use newlines as separators in the narrowspec file, so don't allow them
# in patterns.
if _numlines(pat) > 1:
raise error.Abort(_('newlines are not allowed in narrowspec paths'))
components = pat.split('/')
if '.' in components or '..' in components:
raise error.Abort(_('"." and ".." are not allowed in narrowspec paths'))
def normalizepattern(pattern, defaultkind='path'):
"""Returns the normalized version of a text-format pattern.
If the pattern has no kind, the default will be added.
"""
kind, pat = matchmod._patsplit(pattern, defaultkind)
return '%s:%s' % normalizesplitpattern(kind, pat)
def parsepatterns(pats):
"""Parses a list of patterns into a typed pattern set."""
return set(normalizepattern(p) for p in pats)
def format(includes, excludes):
Pulkit Goyal
narrowspec: use sparse.parseconfig() to parse narrowspec file (BC)...
r38875 output = '[include]\n'
Gregory Szorc
narrowspec: move module into core...
r36178 for i in sorted(includes - excludes):
output += i + '\n'
Pulkit Goyal
narrowspec: use sparse.parseconfig() to parse narrowspec file (BC)...
r38875 output += '[exclude]\n'
Gregory Szorc
narrowspec: move module into core...
r36178 for e in sorted(excludes):
output += e + '\n'
return output
def match(root, include=None, exclude=None):
if not include:
# Passing empty include and empty exclude to matchmod.match()
# gives a matcher that matches everything, so explicitly use
# the nevermatcher.
return matchmod.never(root, '')
return matchmod.match(root, '', [], include=include or [],
exclude=exclude or [])
def needsexpansion(includes):
return [i for i in includes if i.startswith('include:')]
def load(repo):
try:
Martin von Zweigbergk
narrow: move .hg/narrowspec to .hg/store/narrowspec (BC)...
r38908 spec = repo.svfs.read(FILENAME)
Gregory Szorc
narrowspec: move module into core...
r36178 except IOError as e:
# Treat "narrowspec does not exist" the same as "narrowspec file exists
# and is empty".
if e.errno == errno.ENOENT:
return set(), set()
raise
Pulkit Goyal
narrowspec: use sparse.parseconfig() to parse narrowspec file (BC)...
r38875 # maybe we should care about the profiles returned too
includepats, excludepats, profiles = sparse.parseconfig(repo.ui, spec,
'narrow')
if profiles:
raise error.Abort(_("including other spec files using '%include' is not"
" suported in narrowspec"))
return includepats, excludepats
Gregory Szorc
narrowspec: move module into core...
r36178
def save(repo, includepats, excludepats):
spec = format(includepats, excludepats)
Martin von Zweigbergk
narrow: move .hg/narrowspec to .hg/store/narrowspec (BC)...
r38908 repo.svfs.write(FILENAME, spec)
Gregory Szorc
narrowspec: move module into core...
r36178
Martin von Zweigbergk
narrow: call narrowspec.{save,restore,clear}backup directly...
r38905 def savebackup(repo, backupname):
if repository.NARROW_REQUIREMENT not in repo.requirements:
return
vfs = repo.vfs
Martin von Zweigbergk
narrow: extract part of narrowspec backup to core...
r38872 vfs.tryunlink(backupname)
Martin von Zweigbergk
narrow: move .hg/narrowspec to .hg/store/narrowspec (BC)...
r38908 util.copyfile(repo.svfs.join(FILENAME), vfs.join(backupname), hardlink=True)
Martin von Zweigbergk
narrow: extract part of narrowspec backup to core...
r38872
Martin von Zweigbergk
narrow: call narrowspec.{save,restore,clear}backup directly...
r38905 def restorebackup(repo, backupname):
if repository.NARROW_REQUIREMENT not in repo.requirements:
return
Martin von Zweigbergk
narrow: move .hg/narrowspec to .hg/store/narrowspec (BC)...
r38908 util.rename(repo.vfs.join(backupname), repo.svfs.join(FILENAME))
Martin von Zweigbergk
narrow: extract part of narrowspec backup to core...
r38872
Martin von Zweigbergk
narrow: call narrowspec.{save,restore,clear}backup directly...
r38905 def clearbackup(repo, backupname):
if repository.NARROW_REQUIREMENT not in repo.requirements:
return
repo.vfs.unlink(backupname)
Martin von Zweigbergk
narrow: extract part of narrowspec backup to core...
r38872
Gregory Szorc
narrowspec: move module into core...
r36178 def restrictpatterns(req_includes, req_excludes, repo_includes, repo_excludes):
r""" Restricts the patterns according to repo settings,
results in a logical AND operation
:param req_includes: requested includes
:param req_excludes: requested excludes
:param repo_includes: repo includes
:param repo_excludes: repo excludes
:return: include patterns, exclude patterns, and invalid include patterns.
>>> restrictpatterns({'f1','f2'}, {}, ['f1'], [])
(set(['f1']), {}, [])
>>> restrictpatterns({'f1'}, {}, ['f1','f2'], [])
(set(['f1']), {}, [])
>>> restrictpatterns({'f1/fc1', 'f3/fc3'}, {}, ['f1','f2'], [])
(set(['f1/fc1']), {}, [])
>>> restrictpatterns({'f1_fc1'}, {}, ['f1','f2'], [])
([], set(['path:.']), [])
>>> restrictpatterns({'f1/../f2/fc2'}, {}, ['f1','f2'], [])
(set(['f2/fc2']), {}, [])
>>> restrictpatterns({'f1/../f3/fc3'}, {}, ['f1','f2'], [])
([], set(['path:.']), [])
>>> restrictpatterns({'f1/$non_exitent_var'}, {}, ['f1','f2'], [])
(set(['f1/$non_exitent_var']), {}, [])
"""
res_excludes = set(req_excludes)
res_excludes.update(repo_excludes)
invalid_includes = []
if not req_includes:
res_includes = set(repo_includes)
elif 'path:.' not in repo_includes:
res_includes = []
for req_include in req_includes:
req_include = util.expandpath(util.normpath(req_include))
if req_include in repo_includes:
res_includes.append(req_include)
continue
valid = False
for repo_include in repo_includes:
if req_include.startswith(repo_include + '/'):
valid = True
res_includes.append(req_include)
break
if not valid:
invalid_includes.append(req_include)
if len(res_includes) == 0:
res_excludes = {'path:.'}
else:
res_includes = set(res_includes)
else:
res_includes = set(req_includes)
return res_includes, res_excludes, invalid_includes