hgkw/keyword.py
branch0.9.2compat
changeset 444 987648c1ff69
parent 435 7bc92583f344
child 453 0804ead55da7
--- a/hgkw/keyword.py	Mon Mar 31 10:50:10 2008 +0200
+++ b/hgkw/keyword.py	Wed Apr 09 13:40:16 2008 +0200
@@ -106,23 +106,17 @@
     '''Returns hgdate in cvs-like UTC format.'''
     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
 
+def textsafe(s):
+    '''Safe version of util.binary with reversed logic.
+    Note: argument may not be None, which is allowed for util.binary.'''
+    return '\0' not in s
 
 # make keyword tools accessible
 kwtools = {'templater': None, 'hgcmd': None}
 
-# monkeypatches and backwards compatibility hacks
-
-try:
-    # cmdutil.parse moves to dispatch._parse in 18a9fbb5cd78
-    from mercurial import dispatch
-    _dispatch_parse = dispatch._parse
-except ImportError:
-    try:
-        # commands.parse moves to cmdutil.parse in 0c61124ad877
-        _dispatch_parse = cmdutil.parse
-    except AttributeError:
-        _dispatch_parse = commands.parse
-
+# monkeypatch argument parsing
+# due to backwards compatibility this can't be done in uisetup
+# uisetup introduced with extensions module in 930ed513c864
 def _kwdispatch_parse(ui, args):
     '''Monkeypatch dispatch._parse to obtain running hg command.'''
     cmd, func, args, options, cmdoptions = _dispatch_parse(ui, args)
@@ -130,74 +124,20 @@
     return cmd, func, args, options, cmdoptions
 
 try:
-    setattr(dispatch, '_parse', _kwdispatch_parse)
-except (NameError, ImportError):
-    # 0.9.4 needs ImportError
-    if hasattr(cmdutil, 'parse'):
+    # cmdutil.parse moves to dispatch._parse in 18a9fbb5cd78
+    from mercurial import dispatch
+    _dispatch_parse = dispatch._parse
+    dispatch._parse = _kwdispatch_parse
+except ImportError:
+    try:
+        # commands.parse moves to cmdutil.parse in 0c61124ad877
+        _dispatch_parse = cmdutil.parse
         cmdutil.parse = _kwdispatch_parse
-    else:
+    except AttributeError:
+        _dispatch_parse = commands.parse
         commands.parse = _kwdispatch_parse
 
 try:
-    # avoid spurious rejects if patchfile is available
-    _patchfile_init = patch.patchfile.__init__
-
-    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.'''
-        try:
-            _patchfile_init(self, ui, fname, missing=missing)
-        except TypeError:
-            # "missing" arg added in e90e72c6b4c7
-            _patchfile_init(self, ui, fname)
-        self.lines = kwtools['templater'].shrinklines(self.fname, self.lines)
-except AttributeError:
-    pass
-
-_patch_diff = patch.diff
-def _kw_diff(repo, node1=None, node2=None, files=None, match=util.always,
-             fp=None, changes=None, opts=None):
-    # only expand if 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)
-
-try:
-    from mercurial.hgweb import webcommands
-    _webcommands_changeset = webcommands.changeset
-    _webcommands_filediff = webcommands.filediff
-
-    def _kwweb_changeset(web, req, tmpl):
-        '''Wraps webcommands.changeset turning off keyword expansion.'''
-        kwtools['templater'].matcher = util.never
-        return _webcommands_changeset(web, req, tmpl)
-
-    def _kwweb_filediff(web, req, tmpl):
-        '''Wraps webcommands.filediff turning off keyword expansion.'''
-        kwtools['templater'].matcher = util.never
-        return _webcommands_filediff(web, req, tmpl)
-
-    webcommands.changeset = webcommands.rev = _kwweb_changeset
-    webcommands.filediff = webcommands.diff = _kwweb_filediff
-
-except ImportError:
-    from mercurial.hgweb.hgweb_mod import hgweb
-
-    def _kwweb_do_changeset(self, req):
-        kwtools['templater'].matcher = util.never
-        req.write(self.changeset(self.changectx(req)))
-
-    def _kwweb_do_filediff(self, req):
-        kwtools['templater'].matcher = util.never
-        req.write(self.filediff(self.filectx(req)))
-
-    hgweb.do_changeset = hgweb.do_rev = _kwweb_do_changeset
-    hgweb.do_filediff = hgweb.do_diff = _kwweb_do_filediff
-
-try:
     # templatefilters module introduced in 9f1e6ab76069
     from mercurial import templatefilters
     template_filters = templatefilters.filters
@@ -313,7 +253,7 @@
 
         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())
@@ -351,7 +291,7 @@
 
     def expand(self, path, node, data):
         '''Returns data with keywords expanded.'''
-        if not self.restrict and self.matcher(path) and not util.binary(data):
+        if not self.restrict and self.matcher(path) and textsafe(data):
             changenode = self.getnode(path, node)
             return self.substitute(data, path, changenode, self.re_kw.sub)
         return data
@@ -362,7 +302,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()
@@ -380,7 +320,7 @@
             for f in candidates:
                 fp = self.repo.file(f)
                 data = fp.read(mf[f])
-                if util.binary(data):
+                if not textsafe(data):
                     continue
                 if expand:
                     changenode = node or self.getnode(f, mf[f])
@@ -401,7 +341,7 @@
 
     def shrink(self, fname, text):
         '''Returns text with all keyword substitutions removed.'''
-        if self.matcher(fname) and not util.binary(text):
+        if self.matcher(fname) and textsafe(text):
             return self.shrinktext(text)
         return text
 
@@ -409,7 +349,7 @@
         '''Returns lines with keyword substitutions removed.'''
         if self.matcher(fname):
             text = ''.join(lines)
-            if not util.binary(text):
+            if textsafe(text):
                 return self.shrinktext(text).splitlines(True)
         return lines
 
@@ -423,9 +363,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):
@@ -436,7 +376,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.'''
@@ -467,7 +407,7 @@
     try:
         wlock = repo.wlock()
         lock = repo.lock()
-        kwt.overwrite(expand=expand, files=clean)
+        kwt.overwrite(None, expand, clean)
     finally:
         del wlock, lock
 
@@ -497,7 +437,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'
@@ -636,7 +576,7 @@
         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)
@@ -646,27 +586,25 @@
                     force_editor, p1, p2, extra, empty_ok):
             '''Private commit wrapper for backwards compatibility.'''
             try:
-                return super(kwrepo, self).commit(files=files, text=text,
-                                                  user=user, date=date,
-                                                  match=match, force=force,
+                return super(kwrepo, self).commit(files, text, user, date,
+                                                  match, force,
                                                   lock=lock, wlock=wlock,
                                                   force_editor=force_editor,
                                                   p1=p1, p2=p2, extra=extra)
             except TypeError:
                 try:
-                    return 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)
+                    return super(kwrepo,
+                                 self).commit(files, text, user, date,
+                                              match, force,
+                                              force_editor=force_editor,
+                                              p1=p1, p2=p2, extra=extra,
+                                              empty_ok=empty_ok)
                 except TypeError:
-                    return 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)
+                    return super(kwrepo,
+                                 self).commit(files, text, user, date,
+                                              match, force,
+                                              force_editor=force_editor,
+                                              p1=p1, p2=p2, extra=extra)
 
         def commit(self, files=None, text='', user=None, date=None,
                    match=util.always, force=False, lock=None, wlock=None,
@@ -702,24 +640,82 @@
                     else:
                         _p2 = hex(_p2)
 
-                node = self._commit(files, text, user, date, match, force,
-                                    _lock, _wlock, force_editor, p1, p2, extra,
-                                    empty_ok)
+                n = self._commit(files, text, user, date, match, force, _lock,
+                                 _wlock, 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
 
     repo.__class__ = kwrepo
-    patch.diff = _kw_diff
-    if hasattr(patch, 'patchfile'):
-        patch.patchfile.__init__ = _kwpatchfile_init
+
+    # monkeypatches
+    try:
+        # avoid spurious rejects if patchfile is available
+        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.'''
+            try:
+                patchfile_init(self, ui, fname, missing)
+            except TypeError:
+                # "missing" arg added in e90e72c6b4c7
+                patchfile_init(self, ui, fname)
+            self.lines = kwt.shrinklines(self.fname, self.lines)
+
+        patchfile_init = patch.patchfile.__init__
+        patch.patchfile.__init__ = kwpatchfile_init
+    except AttributeError:
+        pass
+
+    def kw_diff(repo, node1=None, node2=None, files=None, match=util.always,
+                 fp=None, changes=None, opts=None):
+        # only expand if 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)
+
+    patch_diff = patch.diff
+    patch.diff = kw_diff
+
+    try:
+        from mercurial.hgweb import webcommands
+        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)
+
+        webcommands_changeset = webcommands.changeset
+        webcommands_filediff = webcommands.filediff
+        webcommands.changeset = webcommands.rev = kwweb_changeset
+        webcommands.filediff = webcommands.diff = kwweb_filediff
+
+    except ImportError:
+        from mercurial.hgweb.hgweb_mod import hgweb
+        def kwweb_do_changeset(self, req):
+            kwt.matcher = util.never
+            hgweb_do_changeset(self, req)
+
+        def kwweb_do_filediff(self, req):
+            kwt.matcher = util.never
+            hgweb_do_filediff(self, req)
+
+        hgweb_do_changeset = hgweb.do_changeset
+        hgweb_do_filediff = hgweb.do_filediff
+        hgweb.do_changeset = hgweb.do_rev = kwweb_do_changeset
+        hgweb.do_filediff = hgweb.do_diff = kwweb_do_filediff
 
 
 cmdtable = {