##// END OF EJS Templates
narrowspec: remove the unused _parsestoredpatterns() function...
Pulkit Goyal -
r38876:794afa91 default
parent child Browse files
Show More
@@ -1,216 +1,193 b''
1 1 # narrowspec.py - methods for working with a narrow view of a repository
2 2 #
3 3 # Copyright 2017 Google, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11
12 12 from .i18n import _
13 13 from . import (
14 14 error,
15 15 match as matchmod,
16 16 sparse,
17 17 util,
18 18 )
19 19
20 20 FILENAME = 'narrowspec'
21 21
22 def _parsestoredpatterns(text):
23 """Parses the narrowspec format that's stored on disk."""
24 patlist = None
25 includepats = []
26 excludepats = []
27 for l in text.splitlines():
28 if l == '[includes]':
29 if patlist is None:
30 patlist = includepats
31 else:
32 raise error.Abort(_('narrowspec includes section must appear '
33 'at most once, before excludes'))
34 elif l == '[excludes]':
35 if patlist is not excludepats:
36 patlist = excludepats
37 else:
38 raise error.Abort(_('narrowspec excludes section must appear '
39 'at most once'))
40 else:
41 patlist.append(l)
42
43 return set(includepats), set(excludepats)
44
45 22 def parseserverpatterns(text):
46 23 """Parses the narrowspec format that's returned by the server."""
47 24 includepats = set()
48 25 excludepats = set()
49 26
50 27 # We get one entry per line, in the format "<key> <value>".
51 28 # It's OK for value to contain other spaces.
52 29 for kp in (l.split(' ', 1) for l in text.splitlines()):
53 30 if len(kp) != 2:
54 31 raise error.Abort(_('Invalid narrowspec pattern line: "%s"') % kp)
55 32 key = kp[0]
56 33 pat = kp[1]
57 34 if key == 'include':
58 35 includepats.add(pat)
59 36 elif key == 'exclude':
60 37 excludepats.add(pat)
61 38 else:
62 39 raise error.Abort(_('Invalid key "%s" in server response') % key)
63 40
64 41 return includepats, excludepats
65 42
66 43 def normalizesplitpattern(kind, pat):
67 44 """Returns the normalized version of a pattern and kind.
68 45
69 46 Returns a tuple with the normalized kind and normalized pattern.
70 47 """
71 48 pat = pat.rstrip('/')
72 49 _validatepattern(pat)
73 50 return kind, pat
74 51
75 52 def _numlines(s):
76 53 """Returns the number of lines in s, including ending empty lines."""
77 54 # We use splitlines because it is Unicode-friendly and thus Python 3
78 55 # compatible. However, it does not count empty lines at the end, so trick
79 56 # it by adding a character at the end.
80 57 return len((s + 'x').splitlines())
81 58
82 59 def _validatepattern(pat):
83 60 """Validates the pattern and aborts if it is invalid.
84 61
85 62 Patterns are stored in the narrowspec as newline-separated
86 63 POSIX-style bytestring paths. There's no escaping.
87 64 """
88 65
89 66 # We use newlines as separators in the narrowspec file, so don't allow them
90 67 # in patterns.
91 68 if _numlines(pat) > 1:
92 69 raise error.Abort(_('newlines are not allowed in narrowspec paths'))
93 70
94 71 components = pat.split('/')
95 72 if '.' in components or '..' in components:
96 73 raise error.Abort(_('"." and ".." are not allowed in narrowspec paths'))
97 74
98 75 def normalizepattern(pattern, defaultkind='path'):
99 76 """Returns the normalized version of a text-format pattern.
100 77
101 78 If the pattern has no kind, the default will be added.
102 79 """
103 80 kind, pat = matchmod._patsplit(pattern, defaultkind)
104 81 return '%s:%s' % normalizesplitpattern(kind, pat)
105 82
106 83 def parsepatterns(pats):
107 84 """Parses a list of patterns into a typed pattern set."""
108 85 return set(normalizepattern(p) for p in pats)
109 86
110 87 def format(includes, excludes):
111 88 output = '[include]\n'
112 89 for i in sorted(includes - excludes):
113 90 output += i + '\n'
114 91 output += '[exclude]\n'
115 92 for e in sorted(excludes):
116 93 output += e + '\n'
117 94 return output
118 95
119 96 def match(root, include=None, exclude=None):
120 97 if not include:
121 98 # Passing empty include and empty exclude to matchmod.match()
122 99 # gives a matcher that matches everything, so explicitly use
123 100 # the nevermatcher.
124 101 return matchmod.never(root, '')
125 102 return matchmod.match(root, '', [], include=include or [],
126 103 exclude=exclude or [])
127 104
128 105 def needsexpansion(includes):
129 106 return [i for i in includes if i.startswith('include:')]
130 107
131 108 def load(repo):
132 109 try:
133 110 spec = repo.vfs.read(FILENAME)
134 111 except IOError as e:
135 112 # Treat "narrowspec does not exist" the same as "narrowspec file exists
136 113 # and is empty".
137 114 if e.errno == errno.ENOENT:
138 115 # Without this the next call to load will use the cached
139 116 # non-existence of the file, which can cause some odd issues.
140 117 repo.invalidate(clearfilecache=True)
141 118 return set(), set()
142 119 raise
143 120 # maybe we should care about the profiles returned too
144 121 includepats, excludepats, profiles = sparse.parseconfig(repo.ui, spec,
145 122 'narrow')
146 123 if profiles:
147 124 raise error.Abort(_("including other spec files using '%include' is not"
148 125 " suported in narrowspec"))
149 126 return includepats, excludepats
150 127
151 128 def save(repo, includepats, excludepats):
152 129 spec = format(includepats, excludepats)
153 130 repo.vfs.write(FILENAME, spec)
154 131
155 132 def savebackup(vfs, backupname):
156 133 vfs.tryunlink(backupname)
157 134 util.copyfile(vfs.join(FILENAME), vfs.join(backupname), hardlink=True)
158 135
159 136 def restorebackup(vfs, backupname):
160 137 vfs.rename(backupname, FILENAME, checkambig=True)
161 138
162 139 def clearbackup(vfs, backupname):
163 140 vfs.unlink(backupname)
164 141
165 142 def restrictpatterns(req_includes, req_excludes, repo_includes, repo_excludes):
166 143 r""" Restricts the patterns according to repo settings,
167 144 results in a logical AND operation
168 145
169 146 :param req_includes: requested includes
170 147 :param req_excludes: requested excludes
171 148 :param repo_includes: repo includes
172 149 :param repo_excludes: repo excludes
173 150 :return: include patterns, exclude patterns, and invalid include patterns.
174 151
175 152 >>> restrictpatterns({'f1','f2'}, {}, ['f1'], [])
176 153 (set(['f1']), {}, [])
177 154 >>> restrictpatterns({'f1'}, {}, ['f1','f2'], [])
178 155 (set(['f1']), {}, [])
179 156 >>> restrictpatterns({'f1/fc1', 'f3/fc3'}, {}, ['f1','f2'], [])
180 157 (set(['f1/fc1']), {}, [])
181 158 >>> restrictpatterns({'f1_fc1'}, {}, ['f1','f2'], [])
182 159 ([], set(['path:.']), [])
183 160 >>> restrictpatterns({'f1/../f2/fc2'}, {}, ['f1','f2'], [])
184 161 (set(['f2/fc2']), {}, [])
185 162 >>> restrictpatterns({'f1/../f3/fc3'}, {}, ['f1','f2'], [])
186 163 ([], set(['path:.']), [])
187 164 >>> restrictpatterns({'f1/$non_exitent_var'}, {}, ['f1','f2'], [])
188 165 (set(['f1/$non_exitent_var']), {}, [])
189 166 """
190 167 res_excludes = set(req_excludes)
191 168 res_excludes.update(repo_excludes)
192 169 invalid_includes = []
193 170 if not req_includes:
194 171 res_includes = set(repo_includes)
195 172 elif 'path:.' not in repo_includes:
196 173 res_includes = []
197 174 for req_include in req_includes:
198 175 req_include = util.expandpath(util.normpath(req_include))
199 176 if req_include in repo_includes:
200 177 res_includes.append(req_include)
201 178 continue
202 179 valid = False
203 180 for repo_include in repo_includes:
204 181 if req_include.startswith(repo_include + '/'):
205 182 valid = True
206 183 res_includes.append(req_include)
207 184 break
208 185 if not valid:
209 186 invalid_includes.append(req_include)
210 187 if len(res_includes) == 0:
211 188 res_excludes = {'path:.'}
212 189 else:
213 190 res_includes = set(res_includes)
214 191 else:
215 192 res_includes = set(req_includes)
216 193 return res_includes, res_excludes, invalid_includes
General Comments 0
You need to be logged in to leave comments. Login now