71 hgrc files. |
71 hgrc files. |
72 ''' |
72 ''' |
73 |
73 |
74 from mercurial.i18n import gettext as _ |
74 from mercurial.i18n import gettext as _ |
75 # above line for backwards compatibility of standalone version |
75 # above line for backwards compatibility of standalone version |
76 from mercurial import commands, cmdutil, templater, util |
76 from mercurial import cmdutil, templater, util |
77 from mercurial import context, filelog, revlog |
77 from mercurial import context, filelog, revlog |
78 from mercurial.node import bin |
78 import os.path, re, time |
79 import os.path, re, sys, time |
|
80 |
79 |
81 deftemplates = { |
80 deftemplates = { |
82 'Revision': '{node|short}', |
81 'Revision': '{node|short}', |
83 'Author': '{author|user}', |
82 'Author': '{author|user}', |
84 'Date': '{date|utcdate}', |
83 'Date': '{date|utcdate}', |
89 } |
88 } |
90 |
89 |
91 def utcdate(date): |
90 def utcdate(date): |
92 '''Returns hgdate in cvs-like UTC format.''' |
91 '''Returns hgdate in cvs-like UTC format.''' |
93 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
92 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
94 |
|
95 def getmodulename(): |
|
96 '''Makes sure pretxncommit-hook can import keyword module |
|
97 regardless of where its located.''' |
|
98 for k, v in sys.modules.iteritems(): |
|
99 if v is None or not hasattr(v, '__file__'): |
|
100 continue |
|
101 if v.__file__.startswith(__file__): |
|
102 return k |
|
103 else: |
|
104 sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) |
|
105 return os.path.splitext(os.path.basename(__file__))[0] |
|
106 |
93 |
107 class kwtemplater(object): |
94 class kwtemplater(object): |
108 ''' |
95 ''' |
109 Sets up keyword templates, corresponding keyword regex, and |
96 Sets up keyword templates, corresponding keyword regex, and |
110 provides keyword expansion function. |
97 provides keyword expansion function. |
150 class kwrepo(repo.__class__): |
137 class kwrepo(repo.__class__): |
151 def file(self, f): |
138 def file(self, f): |
152 if f[0] == '/': |
139 if f[0] == '/': |
153 f = f[1:] |
140 f = f[1:] |
154 return filelog.filelog(self.sopener, f, self, self.revlogversion) |
141 return filelog.filelog(self.sopener, f, self, self.revlogversion) |
|
142 |
|
143 def commit(self, files=None, text="", user=None, date=None, |
|
144 match=util.always, force=False, lock=None, wlock=None, |
|
145 force_editor=False, p1=None, p2=None, extra={}): |
|
146 '''Wraps commit, expanding keywords of committed and |
|
147 configured files in working directory.''' |
|
148 |
|
149 node = super(kwrepo, self).commit(files=files, |
|
150 text=text, user=user, date=date, |
|
151 match=match, force=force, lock=lock, wlock=wlock, |
|
152 force_editor=force_editor, p1=p1, p2=p2, extra=extra) |
|
153 if node is None: |
|
154 return node |
|
155 |
|
156 candidates = self.changelog.read(node)[3] |
|
157 candidates = [f for f in candidates |
|
158 if self.kwfmatcher(f) and os.path.isfile(self.wjoin(f))] |
|
159 if not candidates: |
|
160 return node |
|
161 |
|
162 kwt = kwtemplater(self.ui, self) |
|
163 overwrite = [] |
|
164 for f in candidates: |
|
165 data = self.wfile(f).read() |
|
166 if not util.binary(data): |
|
167 data, kwct = kwt.re_kw.subn(lambda m: |
|
168 kwt.expand(m, f, node), data) |
|
169 if kwct: |
|
170 ui.debug(_('overwriting %s expanding keywords\n' % f)) |
|
171 self.wfile(f, 'w').write(data) |
|
172 overwrite.append(f) |
|
173 self.dirstate.update(overwrite, 'n') |
|
174 return node |
155 |
175 |
156 class kwfilelog(filelog.filelog): |
176 class kwfilelog(filelog.filelog): |
157 ''' |
177 ''' |
158 Superclass over filelog to customize it's read, add, cmp methods. |
178 Superclass over filelog to customize it's read, add, cmp methods. |
159 Keywords are "stored" unexpanded, and expanded on reading. |
179 Keywords are "stored" unexpanded, and expanded on reading. |
196 text = self.kwt.re_kw.sub(r'$\1$', text) |
216 text = self.kwt.re_kw.sub(r'$\1$', text) |
197 return super(kwfilelog, self).cmp(node, text) |
217 return super(kwfilelog, self).cmp(node, text) |
198 |
218 |
199 filelog.filelog = kwfilelog |
219 filelog.filelog = kwfilelog |
200 repo.__class__ = kwrepo |
220 repo.__class__ = kwrepo |
201 # configure pretxncommit hook |
|
202 repo.ui.setconfig('hooks', 'pretxncommit.keyword', |
|
203 'python:%s.pretxnkw' % getmodulename()) |
|
204 |
|
205 |
|
206 def pretxnkw(ui, repo, hooktype, **args): |
|
207 '''pretxncommit hook that collects candidates for keyword expansion |
|
208 on commit and expands keywords in working dir.''' |
|
209 |
|
210 cmd, sysargs, globalopts, cmdopts = commands.parse(ui, sys.argv[1:])[1:] |
|
211 if repr(cmd).split()[1] in ('tag', 'import_'): |
|
212 return |
|
213 |
|
214 files, match, anypats = cmdutil.matchpats(repo, sysargs, cmdopts) |
|
215 modified, added = repo.status(files=files, match=match)[:2] |
|
216 candidates = [f for f in modified + added if repo.kwfmatcher(f)] |
|
217 if not candidates: |
|
218 return |
|
219 |
|
220 kwt = kwtemplater(ui, repo) |
|
221 node = bin(args['node']) |
|
222 for f in candidates: |
|
223 data = repo.wfile(f).read() |
|
224 if not util.binary(data): |
|
225 data, kwct = kwt.re_kw.subn(lambda m: kwt.expand(m, f, node), data) |
|
226 if kwct: |
|
227 ui.debug(_('overwriting %s expanding keywords\n' % f)) |
|
228 repo.wfile(f, 'w').write(data) |
|