74 |
74 |
75 def utcdate(date): |
75 def utcdate(date): |
76 '''Returns hgdate in cvs-like UTC format.''' |
76 '''Returns hgdate in cvs-like UTC format.''' |
77 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
77 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
78 |
78 |
79 def getkwconfig(ui, repo): |
79 def getmodulename(): |
80 inc = [pat for pat, opt in ui.configitems('keyword') if opt != 'ignore'] |
80 '''Makes sure pretxncommit-hook can import keyword module |
81 if not inc: |
81 regardless of where its located.''' |
82 ui.warn(_('keyword: no filename globs for substitution\n')) |
82 for k, v in sys.modules.iteritems(): |
83 return None, None |
83 if v is None: |
84 exc = [pat for pat, opt in ui.configitems('keyword') if opt == 'ignore'] |
84 continue |
85 return inc, exc |
85 if not hasattr(v, '__file__'): |
|
86 continue |
|
87 if v.__file__.startswith(__file__): |
|
88 return k |
|
89 else: |
|
90 sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) |
|
91 return os.path.splitext(os.path.basename(__file__))[0] |
86 |
92 |
87 |
93 |
88 class kwtemplater(object): |
94 class kwtemplater(object): |
89 ''' |
95 ''' |
90 Sets up keyword templates, corresponding keyword regex, and |
96 Sets up keyword templates, corresponding keyword regex, and |
117 '''Sets up repo, and filelog especially, as kwrepo and kwfilelog |
123 '''Sets up repo, and filelog especially, as kwrepo and kwfilelog |
118 for keyword substitution. This is done for local repos only.''' |
124 for keyword substitution. This is done for local repos only.''' |
119 if not repo.local(): |
125 if not repo.local(): |
120 return |
126 return |
121 |
127 |
122 inc, exc = getkwconfig(ui, repo) |
128 # get glob patterns to detect filenames |
|
129 # for inclusion in or exclusion from keyword substitution |
|
130 inc = [pat for pat, opt in ui.configitems('keyword') if opt != 'ignore'] |
123 if not inc: |
131 if not inc: |
124 # no files configured for keyword substitution: |
132 ui.warn(_('keyword: no filename globs for substitution\n')) |
125 # no need to burden repo with extra ballast |
133 return |
126 return |
134 exc = [pat for pat, opt in ui.configitems('keyword') if opt == 'ignore'] |
|
135 |
127 |
136 |
128 class kwrepo(repo.__class__): |
137 class kwrepo(repo.__class__): |
129 def file(self, f): |
138 def file(self, f): |
130 if f[0] == '/': |
139 if f[0] == '/': |
131 f = f[1:] |
140 f = f[1:] |
172 '''Removes keyword substitutions for comparison.''' |
181 '''Removes keyword substitutions for comparison.''' |
173 if self.iskwcandidate(text): |
182 if self.iskwcandidate(text): |
174 text = self._repo.kwt.re_kw.sub(r'$\1$', text) |
183 text = self._repo.kwt.re_kw.sub(r'$\1$', text) |
175 return super(kwfilelog, self).cmp(node, text) |
184 return super(kwfilelog, self).cmp(node, text) |
176 |
185 |
|
186 |
177 filelog.filelog = kwfilelog |
187 filelog.filelog = kwfilelog |
178 repo.__class__ = kwrepo |
188 repo.__class__ = kwrepo |
179 |
189 |
180 # create filematching function once for repo |
190 # create filematching function once for repo |
181 setattr(repo, 'kwfmatcher', |
191 repo.kwfmatcher = util.matcher(repo.root, inc=inc, exc=['.hg*']+exc)[1] |
182 util.matcher(repo.root, inc=inc, exc=['.hg*']+exc)[1]) |
|
183 # initialize kwtemplater once for repo |
192 # initialize kwtemplater once for repo |
184 setattr(repo, 'kwt', kwtemplater(ui, repo)) |
193 repo.kwt = kwtemplater(ui, repo) |
185 |
194 # configure pretxncommit hook |
186 # make pretxncommit hook import kwmodule regardless of where it's located |
195 ui.setconfig('hooks', 'pretxncommit.keyword', |
187 for k, v in sys.modules.iteritems(): |
196 'python:%s.pretxnkw' % getmodulename()) |
188 if v is None: |
|
189 continue |
|
190 if not hasattr(v, '__file__'): |
|
191 continue |
|
192 if v.__file__.startswith(__file__): |
|
193 mod = k |
|
194 break |
|
195 else: |
|
196 sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) |
|
197 mod = os.path.splitext(os.path.basename(__file__))[0] |
|
198 ui.setconfig('hooks', 'pretxncommit.keyword', 'python:%s.pretxnkw' % mod) |
|
199 |
|
200 del inc, exc, mod |
|
201 |
197 |
202 |
198 |
203 def pretxnkw(ui, repo, hooktype, **args): |
199 def pretxnkw(ui, repo, hooktype, **args): |
204 '''pretxncommit hook that collects candidates for keyword expansion |
200 '''pretxncommit hook that collects candidates for keyword expansion |
205 on commit and expands keywords in working dir.''' |
201 on commit and expands keywords in working dir.''' |
217 node = bin(args['node']) |
213 node = bin(args['node']) |
218 for f in candidates: |
214 for f in candidates: |
219 data = repo.wfile(f).read() |
215 data = repo.wfile(f).read() |
220 if not util.binary(data): |
216 if not util.binary(data): |
221 data, kwct = repo.kwt.re_kw.subn(lambda m: |
217 data, kwct = repo.kwt.re_kw.subn(lambda m: |
222 repo.kwt.expand(m, f, node), data) |
218 repo.kwt.expand(m, f, node), data) |
223 if kwct: |
219 if kwct: |
224 ui.debug(_('overwriting %s expanding keywords\n' % f)) |
220 ui.debug(_('overwriting %s expanding keywords\n' % f)) |
225 repo.wfile(f, 'w').write(data) |
221 repo.wfile(f, 'w').write(data) |