168 if kwmaps: # override default templates |
168 if kwmaps: # override default templates |
169 self.templates = dict((k, templater.parsestring(v, False)) |
169 self.templates = dict((k, templater.parsestring(v, False)) |
170 for k, v in kwmaps) |
170 for k, v in kwmaps) |
171 else: |
171 else: |
172 self.templates = _defaultkwmaps(self.ui) |
172 self.templates = _defaultkwmaps(self.ui) |
173 escaped = '|'.join(map(re.escape, self.templates.keys())) |
|
174 self.re_kw = re.compile(r'\$(%s)\$' % escaped) |
|
175 self.re_kwexp = re.compile(r'\$(%s): [^$\n\r]*? \$' % escaped) |
|
176 |
|
177 templatefilters.filters.update({'utcdate': utcdate, |
173 templatefilters.filters.update({'utcdate': utcdate, |
178 'svnisodate': svnisodate, |
174 'svnisodate': svnisodate, |
179 'svnutcdate': svnutcdate}) |
175 'svnutcdate': svnutcdate}) |
|
176 |
|
177 @util.propertycache |
|
178 def escape(self): |
|
179 '''Returns bar-separated and escaped keywords.''' |
|
180 return '|'.join(map(re.escape, self.templates.keys())) |
|
181 |
|
182 @util.propertycache |
|
183 def rekw(self): |
|
184 '''Returns regex for unexpanded keywords.''' |
|
185 return re.compile(r'\$(%s)\$' % self.escape) |
|
186 |
|
187 @util.propertycache |
|
188 def rekwexp(self): |
|
189 '''Returns regex for expanded keywords.''' |
|
190 return re.compile(r'\$(%s): [^$\n\r]*? \$' % self.escape) |
180 |
191 |
181 def substitute(self, data, path, ctx, subfunc): |
192 def substitute(self, data, path, ctx, subfunc): |
182 '''Replaces keywords in data with expanded template.''' |
193 '''Replaces keywords in data with expanded template.''' |
183 def kwsub(mobj): |
194 def kwsub(mobj): |
184 kw = mobj.group(1) |
195 kw = mobj.group(1) |
197 |
208 |
198 def expand(self, path, node, data): |
209 def expand(self, path, node, data): |
199 '''Returns data with keywords expanded.''' |
210 '''Returns data with keywords expanded.''' |
200 if not self.restrict and self.match(path) and not util.binary(data): |
211 if not self.restrict and self.match(path) and not util.binary(data): |
201 ctx = self.linkctx(path, node) |
212 ctx = self.linkctx(path, node) |
202 return self.substitute(data, path, ctx, self.re_kw.sub) |
213 return self.substitute(data, path, ctx, self.rekw.sub) |
203 return data |
214 return data |
204 |
215 |
205 def iskwfile(self, cand, ctx): |
216 def iskwfile(self, cand, ctx): |
206 '''Returns subset of candidates which are configured for keyword |
217 '''Returns subset of candidates which are configured for keyword |
207 expansion are not symbolic links.''' |
218 expansion are not symbolic links.''' |
215 return |
226 return |
216 kwcmd = self.restrict and lookup # kwexpand/kwshrink |
227 kwcmd = self.restrict and lookup # kwexpand/kwshrink |
217 if self.restrict or expand and lookup: |
228 if self.restrict or expand and lookup: |
218 mf = ctx.manifest() |
229 mf = ctx.manifest() |
219 lctx = ctx |
230 lctx = ctx |
220 subn = (self.restrict or rekw) and self.re_kw.subn or self.re_kwexp.subn |
231 re_kw = (self.restrict or rekw) and self.rekw or self.rekwexp |
221 msg = (expand and _('overwriting %s expanding keywords\n') |
232 msg = (expand and _('overwriting %s expanding keywords\n') |
222 or _('overwriting %s shrinking keywords\n')) |
233 or _('overwriting %s shrinking keywords\n')) |
223 for f in candidates: |
234 for f in candidates: |
224 if self.restrict: |
235 if self.restrict: |
225 data = self.repo.file(f).read(mf[f]) |
236 data = self.repo.file(f).read(mf[f]) |
228 if util.binary(data): |
239 if util.binary(data): |
229 continue |
240 continue |
230 if expand: |
241 if expand: |
231 if lookup: |
242 if lookup: |
232 lctx = self.linkctx(f, mf[f]) |
243 lctx = self.linkctx(f, mf[f]) |
233 data, found = self.substitute(data, f, lctx, subn) |
244 data, found = self.substitute(data, f, lctx, re_kw.subn) |
234 elif self.restrict: |
245 elif self.restrict: |
235 found = self.re_kw.search(data) |
246 found = re_kw.search(data) |
236 else: |
247 else: |
237 data, found = _shrinktext(data, subn) |
248 data, found = _shrinktext(data, re_kw.subn) |
238 if found: |
249 if found: |
239 self.ui.note(msg % f) |
250 self.ui.note(msg % f) |
240 self.repo.wwrite(f, data, ctx.flags(f)) |
251 self.repo.wwrite(f, data, ctx.flags(f)) |
241 if kwcmd: |
252 if kwcmd: |
242 self.repo.dirstate.normal(f) |
253 self.repo.dirstate.normal(f) |
244 self.repo.dirstate.normallookup(f) |
255 self.repo.dirstate.normallookup(f) |
245 |
256 |
246 def shrink(self, fname, text): |
257 def shrink(self, fname, text): |
247 '''Returns text with all keyword substitutions removed.''' |
258 '''Returns text with all keyword substitutions removed.''' |
248 if self.match(fname) and not util.binary(text): |
259 if self.match(fname) and not util.binary(text): |
249 return _shrinktext(text, self.re_kwexp.sub) |
260 return _shrinktext(text, self.rekwexp.sub) |
250 return text |
261 return text |
251 |
262 |
252 def shrinklines(self, fname, lines): |
263 def shrinklines(self, fname, lines): |
253 '''Returns lines with keyword substitutions removed.''' |
264 '''Returns lines with keyword substitutions removed.''' |
254 if self.match(fname): |
265 if self.match(fname): |
255 text = ''.join(lines) |
266 text = ''.join(lines) |
256 if not util.binary(text): |
267 if not util.binary(text): |
257 return _shrinktext(text, self.re_kwexp.sub).splitlines(True) |
268 return _shrinktext(text, self.rekwexp.sub).splitlines(True) |
258 return lines |
269 return lines |
259 |
270 |
260 def wread(self, fname, data): |
271 def wread(self, fname, data): |
261 '''If in restricted mode returns data read from wdir with |
272 '''If in restricted mode returns data read from wdir with |
262 keyword substitutions removed.''' |
273 keyword substitutions removed.''' |