# HG changeset patch # User Christian Ebert # Date 1196537473 -3600 # Node ID 32061d23db1457bc7e7216db38eec028fefd3310 # Parent 78b80b2511dec96abae744d559ce0ec1864e47f1 Refactor to initialize kwtemplater only once during reposetup - when overwriting kwtemplater was initialized (and the same keyword regex compiled) before and with every file read. - therefore remove overwrite from kwtemplater, and make it private method. _ matcher becomes attribute of kwtemplater. - by making kwtemplater a global, avoid adding attribute to ui. diff -r 78b80b2511de -r 32061d23db14 hgkw/keyword.py --- a/hgkw/keyword.py Sat Dec 01 13:15:13 2007 +0100 +++ b/hgkw/keyword.py Sat Dec 01 20:31:13 2007 +0100 @@ -92,6 +92,8 @@ '''Returns hgdate in cvs-like UTC format.''' return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) +_kwtemplater = None + class kwtemplater(object): ''' Sets up keyword templates, corresponding keyword regex, and @@ -107,12 +109,12 @@ 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}', } - def __init__(self, ui, repo, expand, path='', node=None): + def __init__(self, ui, repo, inc, exc): self.ui = ui self.repo = repo - self.ct = expand or None - self.path = path - self.node = node + self.match = util.matcher(repo.root, inc=inc, exc=exc)[1] + self.node = None + self.path = '' kwmaps = self.ui.configitems('keywordmaps') if kwmaps: # override default templates @@ -122,10 +124,10 @@ escaped = map(re.escape, self.templates.keys()) kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped) self.re_kw = re.compile(kwpat) - if self.ct: - templater.common_filters['utcdate'] = utcdate - self.ct = cmdutil.changeset_templater(self.ui, self.repo, - False, '', False) + + templater.common_filters['utcdate'] = utcdate + self.ct = cmdutil.changeset_templater(self.ui, self.repo, + False, '', False) def substitute(self, node, data, subfunc): '''Obtains node if missing, and calls given substitution function.''' @@ -150,14 +152,14 @@ return data return self.substitute(node, data, self.re_kw.sub) - def process(self, node, data): + def process(self, node, data, expand): '''Returns a tuple: data, count. Count is number of keywords/keyword substitutions, indicates to caller whether to act on file containing data. Keywords in data are expanded, if templater was initialized.''' if util.binary(data): return data, None - if self.ct: + if expand: return self.substitute(node, data, self.re_kw.subn) return data, self.re_kw.search(data) @@ -167,21 +169,6 @@ return text return self.re_kw.sub(r'$\1$', text) - def overwrite(self, candidates, man, commit): - '''Overwrites files in working directory if keywords are detected. - Keywords are expanded if keyword templater is initialized, - otherwise their substitution is removed.''' - expand = self.ct is not None - action = ('shrinking', 'expanding')[expand] - notify = (self.ui.note, self.ui.debug)[commit] - for f in candidates: - fp = self.repo.file(f, kwexp=expand, kwmatch=True) - data, kwfound = fp.kwctread(man[f]) - if kwfound: - notify(_('overwriting %s %s keywords\n') % (f, action)) - self.repo.wwrite(f, data, man.flags(f)) - self.repo.dirstate.normal(f) - class kwfilelog(filelog.filelog): ''' Subclass of filelog to hook into its read, add, cmp methods. @@ -191,11 +178,11 @@ super(kwfilelog, self).__init__(opener, path) self.kwtemplater = kwtemplater - def kwctread(self, node): + def kwctread(self, node, expand): '''Reads expanding and counting keywords (only called from kwtemplater.overwrite).''' data = super(kwfilelog, self).read(node) - return self.kwtemplater.process(node, data) + return self.kwtemplater.process(node, data, expand) def read(self, node): '''Expands keywords when reading filelog.''' @@ -215,28 +202,42 @@ return t2 != text return revlog.revlog.cmp(self, node, text) -def _status(ui, repo, *pats, **opts): +def _status(ui, repo, kwtemplater, *pats, **opts): '''Bails out if [keyword] configuration is not active. Returns status of working directory.''' - if hasattr(ui, 'kwfmatcher'): + if kwtemplater: files, match, anypats = cmdutil.matchpats(repo, pats, opts) return repo.status(files=files, match=match, list_clean=True) if ui.configitems('keyword'): raise util.Abort(_('[keyword] patterns cannot match')) raise util.Abort(_('no [keyword] patterns configured')) -def _iskwfile(ui, man, f): - return not man.linkf(f) and ui.kwfmatcher(f) - -def _overwrite(ui, repo, files, node, man, expand, commit): - '''Passes given files to kwtemplater for overwriting.''' - files.sort() - kwt = kwtemplater(ui, repo, expand, node=node) - kwt.overwrite(files, man, commit) +def _overwrite(ui, repo, kwtemplater, node=None, expand=True, files=None): + '''Overwrites selected files expanding/shrinking keywords.''' + ctx = repo.changectx(node) + mf = ctx.manifest() + if files is None: + notify = ui.debug # commit + files = [f for f in ctx.files() if mf.has_key(f)] + else: + notify = ui.note # kwexpand/kwshrink + candidates = [f for f in files if not mf.linkf(f) and kwtemplater.match(f)] + if candidates: + candidates.sort() + action = expand and 'expanding' or 'shrinking' + kwtemplater.node = node or ctx.node() + for f in candidates: + fp = repo.file(f, kwmatch=True) + data, kwfound = fp.kwctread(mf[f], expand) + if kwfound: + notify(_('overwriting %s %s keywords\n') % (f, action)) + repo.wwrite(f, data, mf.flags(f)) + repo.dirstate.normal(f) def _kwfwrite(ui, repo, expand, *pats, **opts): '''Selects files and passes them to _overwrite.''' - status = _status(ui, repo, *pats, **opts) + global _kwtemplater + status = _status(ui, repo, _kwtemplater, *pats, **opts) modified, added, removed, deleted, unknown, ignored, clean = status if modified or added or removed or deleted: raise util.Abort(_('outstanding uncommitted changes in given files')) @@ -244,12 +245,7 @@ try: wlock = repo.wlock() lock = repo.lock() - ctx = repo.changectx() - man = ctx.manifest() - candidates = [f for f in clean if _iskwfile(ui, man, f)] - if candidates: - # 7th argument sets commit to False - _overwrite(ui, repo, candidates, ctx.node(), man, expand, False) + _overwrite(ui, repo, _kwtemplater, expand=expand, files=clean) finally: del wlock, lock @@ -352,14 +348,15 @@ keyword expansion. That is, files matched by [keyword] config patterns but not symlinks. ''' - status = _status(ui, repo, *pats, **opts) + global _kwtemplater + status = _status(ui, repo, _kwtemplater, *pats, **opts) modified, added, removed, deleted, unknown, ignored, clean = status if opts['untracked']: files = modified + added + unknown + clean else: files = modified + added + clean files.sort() - kwfiles = [f for f in files if ui.kwfmatcher(f) and not repo._link(f)] + kwfiles = [f for f in files if _kwtemplater.match(f) and not repo._link(f)] cwd = pats and repo.getcwd() or '' allf = opts['all'] ignore = opts['ignore'] @@ -421,15 +418,16 @@ if not inc: return - ui.kwfmatcher = util.matcher(repo.root, inc=inc, exc=exc)[1] + global _kwtemplater + _kwtemplater = kwtemplater(ui, repo, inc, exc) class kwrepo(repo.__class__): - def file(self, f, kwexp=True, kwmatch=False): + def file(self, f, kwmatch=False): if f[0] == '/': f = f[1:] - if kwmatch or ui.kwfmatcher(f): - kwt = kwtemplater(ui, self, kwexp, path=f) - return kwfilelog(self.sopener, f, kwt) + if kwmatch or _kwtemplater.match(f): + _kwtemplater.path = f + return kwfilelog(self.sopener, f, _kwtemplater) return filelog.filelog(self.sopener, f) def commit(self, files=None, text='', user=None, date=None, @@ -468,13 +466,7 @@ for name, cmd in commithooks: ui.setconfig('hooks', name, cmd) if node is not None: - cl = self.changelog.read(node) - mn = self.manifest.read(cl[0]) - candidates = [f for f in cl[3] if mn.has_key(f) - and _iskwfile(ui, mn, f)] - if candidates: - # 6th, 7th arguments set expansion, commit to True - _overwrite(ui, self, candidates, node, mn, True, True) + _overwrite(ui, self, _kwtemplater, node=node) repo.hook('commit', node=node, parent1=_p1, parent2=_p2) return node finally: