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) |
189 ct.show(ctx, root=self.repo.root, file=path) |
200 ct.show(ctx, root=self.repo.root, file=path) |
190 ekw = templatefilters.firstline(self.ui.popbuffer()) |
201 ekw = templatefilters.firstline(self.ui.popbuffer()) |
191 return '$%s: %s $' % (kw, ekw) |
202 return '$%s: %s $' % (kw, ekw) |
192 return subfunc(kwsub, data) |
203 return subfunc(kwsub, data) |
193 |
204 |
|
205 def linkctx(self, path, fileid): |
|
206 '''Similar to filelog.linkrev, but returns a changectx.''' |
|
207 return self.repo.filectx(path, fileid=fileid).changectx() |
|
208 |
194 def expand(self, path, node, data): |
209 def expand(self, path, node, data): |
195 '''Returns data with keywords expanded.''' |
210 '''Returns data with keywords expanded.''' |
196 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): |
197 ctx = self.repo.filectx(path, fileid=node).changectx() |
212 ctx = self.linkctx(path, node) |
198 return self.substitute(data, path, ctx, self.re_kw.sub) |
213 return self.substitute(data, path, ctx, self.rekw.sub) |
199 return data |
214 return data |
200 |
215 |
201 def iskwfile(self, cand, ctx): |
216 def iskwfile(self, cand, ctx): |
202 '''Returns subset of candidates which are configured for keyword |
217 '''Returns subset of candidates which are configured for keyword |
203 expansion are not symbolic links.''' |
218 expansion are not symbolic links.''' |
210 if not candidates: |
225 if not candidates: |
211 return |
226 return |
212 kwcmd = self.restrict and lookup # kwexpand/kwshrink |
227 kwcmd = self.restrict and lookup # kwexpand/kwshrink |
213 if self.restrict or expand and lookup: |
228 if self.restrict or expand and lookup: |
214 mf = ctx.manifest() |
229 mf = ctx.manifest() |
215 fctx = ctx |
230 lctx = ctx |
216 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 |
217 msg = (expand and _('overwriting %s expanding keywords\n') |
232 msg = (expand and _('overwriting %s expanding keywords\n') |
218 or _('overwriting %s shrinking keywords\n')) |
233 or _('overwriting %s shrinking keywords\n')) |
219 for f in candidates: |
234 for f in candidates: |
220 if self.restrict: |
235 if self.restrict: |
221 data = self.repo.file(f).read(mf[f]) |
236 data = self.repo.file(f).read(mf[f]) |
223 data = self.repo.wread(f) |
238 data = self.repo.wread(f) |
224 if util.binary(data): |
239 if util.binary(data): |
225 continue |
240 continue |
226 if expand: |
241 if expand: |
227 if lookup: |
242 if lookup: |
228 fctx = self.repo.filectx(f, fileid=mf[f]).changectx() |
243 lctx = self.linkctx(f, mf[f]) |
229 data, found = self.substitute(data, f, fctx, subn) |
244 data, found = self.substitute(data, f, lctx, re_kw.subn) |
230 elif self.restrict: |
245 elif self.restrict: |
231 found = self.re_kw.search(data) |
246 found = re_kw.search(data) |
232 else: |
247 else: |
233 data, found = _shrinktext(data, subn) |
248 data, found = _shrinktext(data, re_kw.subn) |
234 if found: |
249 if found: |
235 self.ui.note(msg % f) |
250 self.ui.note(msg % f) |
236 self.repo.wwrite(f, data, ctx.flags(f)) |
251 self.repo.wwrite(f, data, ctx.flags(f)) |
237 if kwcmd: |
252 if kwcmd: |
238 self.repo.dirstate.normal(f) |
253 self.repo.dirstate.normal(f) |
240 self.repo.dirstate.normallookup(f) |
255 self.repo.dirstate.normallookup(f) |
241 |
256 |
242 def shrink(self, fname, text): |
257 def shrink(self, fname, text): |
243 '''Returns text with all keyword substitutions removed.''' |
258 '''Returns text with all keyword substitutions removed.''' |
244 if self.match(fname) and not util.binary(text): |
259 if self.match(fname) and not util.binary(text): |
245 return _shrinktext(text, self.re_kwexp.sub) |
260 return _shrinktext(text, self.rekwexp.sub) |
246 return text |
261 return text |
247 |
262 |
248 def shrinklines(self, fname, lines): |
263 def shrinklines(self, fname, lines): |
249 '''Returns lines with keyword substitutions removed.''' |
264 '''Returns lines with keyword substitutions removed.''' |
250 if self.match(fname): |
265 if self.match(fname): |
251 text = ''.join(lines) |
266 text = ''.join(lines) |
252 if not util.binary(text): |
267 if not util.binary(text): |
253 return _shrinktext(text, self.re_kwexp.sub).splitlines(True) |
268 return _shrinktext(text, self.rekwexp.sub).splitlines(True) |
254 return lines |
269 return lines |
255 |
270 |
256 def wread(self, fname, data): |
271 def wread(self, fname, data): |
257 '''If in restricted mode returns data read from wdir with |
272 '''If in restricted mode returns data read from wdir with |
258 keyword substitutions removed.''' |
273 keyword substitutions removed.''' |