# HG changeset patch # User Christian Ebert # Date 1207784766 -7200 # Node ID 0c91995647e954b557b1e25ac494b95041d91585 # Parent 4fb8a2e526ffd422f8dd2adbb787c44109be4354 (stable) patches from default in 4b2c266bf059 Revert to util.binary, as checks entire data for \0 now. diff -r 4fb8a2e526ff -r 0c91995647e9 hgkw/keyword.py --- a/hgkw/keyword.py Fri Mar 28 19:40:44 2008 +0100 +++ b/hgkw/keyword.py Thu Apr 10 01:46:06 2008 +0200 @@ -102,58 +102,8 @@ '''Returns hgdate in cvs-like UTC format.''' return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) - # make keyword tools accessible -kwtools = {'templater': None, 'hgcmd': None} - -# store originals of monkeypatches -_patchfile_init = patch.patchfile.__init__ -_patch_diff = patch.diff -_dispatch_parse = dispatch._parse - -def _kwpatchfile_init(self, ui, fname, missing=False): - '''Monkeypatch/wrap patch.patchfile.__init__ to avoid - rejects or conflicts due to expanded keywords in working dir.''' - _patchfile_init(self, ui, fname, missing=missing) - # shrink keywords read from working dir - kwt = kwtools['templater'] - self.lines = kwt.shrinklines(self.fname, self.lines) - -def _kw_diff(repo, node1=None, node2=None, files=None, match=util.always, - fp=None, changes=None, opts=None): - '''Monkeypatch patch.diff to avoid expansion except when - comparing against working dir.''' - if node2 is not None: - kwtools['templater'].matcher = util.never - elif node1 is not None and node1 != repo.changectx().node(): - kwtools['templater'].restrict = True - _patch_diff(repo, node1=node1, node2=node2, files=files, match=match, - fp=fp, changes=changes, opts=opts) - -# monkeypatching hgweb functions changeset and filediff -# actual monkeypatching is done at the bottom of reposetup() - -web_changeset = webcommands.changeset -web_filediff = webcommands.filediff - -def _kwweb_changeset(web, req, tmpl): - '''Wraps webcommands.changeset turning off keyword expansion.''' - kwtools['templater'].matcher = util.never - return web_changeset(web, req, tmpl) - -def _kwweb_filediff(web, req, tmpl): - '''Wraps webcommands.filediff turning off keyword expansion.''' - kwtools['templater'].matcher = util.never - return web_filediff(web, req, tmpl) - -def _kwdispatch_parse(ui, args): - '''Monkeypatch dispatch._parse to obtain running hg command.''' - cmd, func, args, options, cmdoptions = _dispatch_parse(ui, args) - kwtools['hgcmd'] = cmd - return cmd, func, args, options, cmdoptions - -# dispatch._parse is run before reposetup, so wrap it here -dispatch._parse = _kwdispatch_parse +kwtools = {'templater': None, 'hgcmd': '', 'inc': [], 'exc': ['.hg*']} class kwtemplater(object): @@ -171,15 +121,16 @@ 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}', } - def __init__(self, ui, repo, inc, exc): + def __init__(self, ui, repo): self.ui = ui self.repo = repo - self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1] + self.matcher = util.matcher(repo.root, + inc=kwtools['inc'], exc=kwtools['exc'])[1] self.restrict = kwtools['hgcmd'] in restricted.split() kwmaps = self.ui.configitems('keywordmaps') if kwmaps: # override default templates - kwmaps = [(k, templater.parsestring(v, quoted=False)) + kwmaps = [(k, templater.parsestring(v, False)) for (k, v) in kwmaps] self.templates = dict(kwmaps) escaped = map(re.escape, self.templates.keys()) @@ -220,7 +171,7 @@ Caveat: localrepository._link fails on Windows.''' return self.matcher(path) and not islink(path) - def overwrite(self, node=None, expand=True, files=None): + def overwrite(self, node, expand, files): '''Overwrites selected files expanding/shrinking keywords.''' ctx = self.repo.changectx(node) mf = ctx.manifest() @@ -279,9 +230,9 @@ Subclass of filelog to hook into its read, add, cmp methods. Keywords are "stored" unexpanded, and processed on reading. ''' - def __init__(self, opener, path): + def __init__(self, opener, kwt, path): super(kwfilelog, self).__init__(opener, path) - self.kwt = kwtools['templater'] + self.kwt = kwt self.path = path def read(self, node): @@ -292,7 +243,7 @@ def add(self, text, meta, tr, link, p1=None, p2=None): '''Removes keyword substitutions when adding to filelog.''' text = self.kwt.shrink(self.path, text) - return super(kwfilelog, self).add(text, meta, tr, link, p1=p1, p2=p2) + return super(kwfilelog, self).add(text, meta, tr, link, p1, p2) def cmp(self, node, text): '''Removes keyword substitutions for comparison.''' @@ -323,7 +274,7 @@ try: wlock = repo.wlock() lock = repo.lock() - kwt.overwrite(expand=expand, files=clean) + kwt.overwrite(None, expand, clean) finally: del wlock, lock @@ -353,7 +304,7 @@ branchname = 'demobranch' tmpdir = tempfile.mkdtemp('', 'kwdemo.') ui.note(_('creating temporary repo at %s\n') % tmpdir) - repo = localrepo.localrepository(ui, path=tmpdir, create=True) + repo = localrepo.localrepository(ui, tmpdir, True) ui.setconfig('keyword', fn, '') if args or opts.get('rcfile'): kwstatus = 'custom' @@ -375,6 +326,7 @@ ui.readconfig(repo.join('hgrc')) if not opts.get('default'): kwmaps = dict(ui.configitems('keywordmaps')) or kwtemplater.templates + uisetup(ui) reposetup(ui, repo) for k, v in ui.configitems('extensions'): if k.endswith('keyword'): @@ -456,39 +408,50 @@ _kwfwrite(ui, repo, False, *pats, **opts) +def uisetup(ui): + '''Collects [keyword] config in kwtools. + Monkeypatches dispatch._parse if needed.''' + + for pat, opt in ui.configitems('keyword'): + if opt != 'ignore': + kwtools['inc'].append(pat) + else: + kwtools['exc'].append(pat) + + if kwtools['inc']: + def kwdispatch_parse(ui, args): + '''Monkeypatch dispatch._parse to obtain running hg command.''' + cmd, func, args, options, cmdoptions = dispatch_parse(ui, args) + kwtools['hgcmd'] = cmd + return cmd, func, args, options, cmdoptions + + dispatch_parse = dispatch._parse + dispatch._parse = kwdispatch_parse + def reposetup(ui, repo): '''Sets up repo as kwrepo for keyword substitution. Overrides file method to return kwfilelog instead of filelog if file matches user configuration. Wraps commit to overwrite configured files with updated keyword substitutions. - This is done for local repos only, and only if there are - files configured at all for keyword substitution.''' + Monkeypatches patch and webcommands.''' try: - if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split() + if (not repo.local() or not kwtools['inc'] + or kwtools['hgcmd'] in nokwcommands.split() or '.hg' in util.splitpath(repo.root) or repo._url.startswith('bundle:')): return except AttributeError: pass - inc, exc = [], ['.hg*'] - for pat, opt in ui.configitems('keyword'): - if opt != 'ignore': - inc.append(pat) - else: - exc.append(pat) - if not inc: - return - - kwtools['templater'] = kwt = kwtemplater(ui, repo, inc, exc) + kwtools['templater'] = kwt = kwtemplater(ui, repo) class kwrepo(repo.__class__): def file(self, f): if f[0] == '/': f = f[1:] - return kwfilelog(self.sopener, f) + return kwfilelog(self.sopener, kwt, f) def wread(self, filename): data = super(kwrepo, self).wread(filename) @@ -520,28 +483,59 @@ else: _p2 = hex(_p2) - node = super(kwrepo, - self).commit(files=files, text=text, user=user, - date=date, match=match, force=force, - force_editor=force_editor, - p1=p1, p2=p2, extra=extra, - empty_ok=empty_ok) + n = super(kwrepo, self).commit(files, text, user, date, match, + force, force_editor, p1, p2, + extra, empty_ok) # restore commit hooks for name, cmd in commithooks.iteritems(): ui.setconfig('hooks', name, cmd) - if node is not None: - kwt.overwrite(node=node) - repo.hook('commit', node=node, parent1=_p1, parent2=_p2) - return node + if n is not None: + kwt.overwrite(n, True, None) + repo.hook('commit', node=n, parent1=_p1, parent2=_p2) + return n finally: del wlock, lock + # monkeypatches + def kwpatchfile_init(self, ui, fname, missing=False): + '''Monkeypatch/wrap patch.patchfile.__init__ to avoid + rejects or conflicts due to expanded keywords in working dir.''' + patchfile_init(self, ui, fname, missing) + # shrink keywords read from working dir + self.lines = kwt.shrinklines(self.fname, self.lines) + + def kw_diff(repo, node1=None, node2=None, files=None, match=util.always, + fp=None, changes=None, opts=None): + '''Monkeypatch patch.diff to avoid expansion except when + comparing against working dir.''' + if node2 is not None: + kwt.matcher = util.never + elif node1 is not None and node1 != repo.changectx().node(): + kwt.restrict = True + patch_diff(repo, node1, node2, files, match, fp, changes, opts) + + def kwweb_changeset(web, req, tmpl): + '''Wraps webcommands.changeset turning off keyword expansion.''' + kwt.matcher = util.never + return webcommands_changeset(web, req, tmpl) + + def kwweb_filediff(web, req, tmpl): + '''Wraps webcommands.filediff turning off keyword expansion.''' + kwt.matcher = util.never + return webcommands_filediff(web, req, tmpl) + repo.__class__ = kwrepo - patch.patchfile.__init__ = _kwpatchfile_init - patch.diff = _kw_diff - webcommands.changeset = webcommands.rev = _kwweb_changeset - webcommands.filediff = webcommands.diff = _kwweb_filediff + + patchfile_init = patch.patchfile.__init__ + patch_diff = patch.diff + webcommands_changeset = webcommands.changeset + webcommands_filediff = webcommands.filediff + + patch.patchfile.__init__ = kwpatchfile_init + patch.diff = kw_diff + webcommands.changeset = webcommands.rev = kwweb_changeset + webcommands.filediff = webcommands.diff = kwweb_filediff cmdtable = {