99 restricted = 'record qfold qimport qnew qpush qrefresh qrecord' |
99 restricted = 'record qfold qimport qnew qpush qrefresh qrecord' |
100 |
100 |
101 def utcdate(date): |
101 def utcdate(date): |
102 '''Returns hgdate in cvs-like UTC format.''' |
102 '''Returns hgdate in cvs-like UTC format.''' |
103 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
103 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
|
104 |
|
105 def textsafe(s): |
|
106 '''Safe version of util.binary with reversed logic. |
|
107 Note: argument may not be None, which is allowed for util.binary.''' |
|
108 return '\0' not in s |
104 |
109 |
105 # make keyword tools accessible |
110 # make keyword tools accessible |
106 kwtools = {'templater': None, 'hgcmd': '', 'inc': [], 'exc': ['.hg*']} |
111 kwtools = {'templater': None, 'hgcmd': '', 'inc': [], 'exc': ['.hg*']} |
107 |
112 |
108 |
113 |
158 return '$%s: %s $' % (kw, ekw) |
163 return '$%s: %s $' % (kw, ekw) |
159 return subfunc(kwsub, data) |
164 return subfunc(kwsub, data) |
160 |
165 |
161 def expand(self, path, node, data): |
166 def expand(self, path, node, data): |
162 '''Returns data with keywords expanded.''' |
167 '''Returns data with keywords expanded.''' |
163 if not self.restrict and self.matcher(path) and not util.binary(data): |
168 if not self.restrict and self.matcher(path) and textsafe(data): |
164 changenode = self.getnode(path, node) |
169 changenode = self.getnode(path, node) |
165 return self.substitute(data, path, changenode, self.re_kw.sub) |
170 return self.substitute(data, path, changenode, self.re_kw.sub) |
166 return data |
171 return data |
167 |
172 |
168 def iskwfile(self, path, islink): |
173 def iskwfile(self, path, islink): |
186 candidates.sort() |
191 candidates.sort() |
187 action = expand and 'expanding' or 'shrinking' |
192 action = expand and 'expanding' or 'shrinking' |
188 for f in candidates: |
193 for f in candidates: |
189 fp = self.repo.file(f) |
194 fp = self.repo.file(f) |
190 data = fp.read(mf[f]) |
195 data = fp.read(mf[f]) |
191 if util.binary(data): |
196 if not textsafe(data): |
192 continue |
197 continue |
193 if expand: |
198 if expand: |
194 changenode = node or self.getnode(f, mf[f]) |
199 changenode = node or self.getnode(f, mf[f]) |
195 data, found = self.substitute(data, f, changenode, |
200 data, found = self.substitute(data, f, changenode, |
196 self.re_kw.subn) |
201 self.re_kw.subn) |
206 '''Unconditionally removes all keyword substitutions from text.''' |
211 '''Unconditionally removes all keyword substitutions from text.''' |
207 return self.re_kw.sub(r'$\1$', text) |
212 return self.re_kw.sub(r'$\1$', text) |
208 |
213 |
209 def shrink(self, fname, text): |
214 def shrink(self, fname, text): |
210 '''Returns text with all keyword substitutions removed.''' |
215 '''Returns text with all keyword substitutions removed.''' |
211 if self.matcher(fname) and not util.binary(text): |
216 if self.matcher(fname) and textsafe(text): |
212 return self.shrinktext(text) |
217 return self.shrinktext(text) |
213 return text |
218 return text |
214 |
219 |
215 def shrinklines(self, fname, lines): |
220 def shrinklines(self, fname, lines): |
216 '''Returns lines with keyword substitutions removed.''' |
221 '''Returns lines with keyword substitutions removed.''' |
217 if self.matcher(fname): |
222 if self.matcher(fname): |
218 text = ''.join(lines) |
223 text = ''.join(lines) |
219 if not util.binary(text): |
224 if textsafe(text): |
220 return self.shrinktext(text).splitlines(True) |
225 return self.shrinktext(text).splitlines(True) |
221 return lines |
226 return lines |
222 |
227 |
223 def wread(self, fname, data): |
228 def wread(self, fname, data): |
224 '''If in restricted mode returns data read from wdir with |
229 '''If in restricted mode returns data read from wdir with |