ZyX_I avatar ZyX_I committed 417a71e

@%aurum/drivers/mercurial: Moved python/aurum.py to python/aurum/aumercurial.py
(aumercurial name was chosen to avoid conflict with
mercurial own package)
Fixed phases support in non-python version of driver
Fixed repository object updating in non-python version of driver
Added support for pyeval() to rf-ignore()

Comments (0)

Files changed (4)

autoload/aurum/drivers/mercurial.vim

 let s:usepythondriver=0
 if has('python')
     let s:py='python'
+    let s:pp='aurum.aumercurial'
+    let s:pya=s:py.' '.s:pp.'.'
     try
         " execute s:py "try:\n".
                     " \"    if type(aurum).__name__=='module':\n".
                     " \"        reload(aurum)\n".
                     " \"except NameError:\n".
                     " \"    pass"
-        execute s:py 'import aurum'
+        execute s:py 'import '.s:pp
         let s:usepythondriver=1
     catch
         " s:usepythondriver stays equal to 0, errors are ignored
         " FIXME Does not work in python3. Not very problematic as mercurial does 
         "       not do this either, but it will be necessary to review these 
         "       lines after python3 support in mercurial will be finished.
-        execute s:py 'reload(aurum)'
+        execute s:py 'reload('.s:pp.')'
         if s:_r.utils.using_ansi_esc_echo
             if exists('*pyeval')
-                execute s:py 'aurum.register_ansi_esc_echo_func('.
-                            \       'vim.bindeval("s:_r.utils.printm"))'
+                execute s:pya.'register_ansi_esc_echo_func('.
+                            \               'vim.bindeval("s:_r.utils.printm"))'
             endif
         endif
     endif
     if index(s:_f.getoption('hg_useshell'), a:attr)!=-1
         return s:F.runshellcmd(a:repo, a:attr, a:args, a:kwargs)
     endif
-    execute s:py 'aurum.call_cmd(vim.eval("a:repo.path"), '.
-                \               'vim.eval("a:attr"), '.
-                \               ((a:0)?(string(a:1)):('None')).', '.
-                \               '*vim.eval("a:args"), '.
-                \               '**vim.eval("a:kwargs"))'
+    execute s:pya.'call_cmd(vim.eval("a:repo.path"), '.
+                \           'vim.eval("a:attr"), '.
+                \           ((a:0)?(string(a:1)):('None')).', '.
+                \           '*vim.eval("a:args"), '.
+                \           '**vim.eval("a:kwargs"))'
 endfunction
 "▲2
 else "▶1
     return map(copy(lines), 'matchlist(v:val, '.
                 \                         '''\v^(.{-})\ +(\d+)\:\x{12}'')[1:2]')
 endfunction
+"▶2 runcmd :: repo, attr, args, kwargs[, bkwargs] → + ?
+function s:F.runcmd(repo, attr, args, kwargs, ...)
+    return s:F.runshellcmd(a:repo, a:attr, a:args, a:kwargs)
+endfunction
 "▲2
-let s:F.runcmd=s:F.runshellcmd
 endif
 "▶1 getcs :: repo, rev → cs
 if s:usepythondriver "▶2
     function s:F.getcs(repo, rev)
         let cs={}
         try
-            execute s:py 'aurum.get_cs(vim.eval("a:repo.path"), '.
-                        \             'vim.eval("a:rev"))'
+            execute s:pya.'get_cs(vim.eval("a:repo.path"), '.
+                        \        'vim.eval("a:rev"))'
         endtry
         return cs
     endfunction
         try
             " XXX get_updates also modifies a:repo
             " execute s:py 'import cProfile as profile'
-            " execute s:py 'profile.run("aurum.get_updates(vim.eval(''a:repo.path''), '.a:start.')", "python.profile")'
-            execute s:py 'aurum.get_updates(vim.eval("a:repo.path"), '.
-                        \                   a:start.')'
+            " execute s:py 'profile.run("'.s:pp.'.get_updates(vim.eval(''a:repo.path''), '.a:start.')", "python.profile")'
+            execute s:pya.'get_updates(vim.eval("a:repo.path"), '.a:start.')'
         endtry
         return d
     endfunction
         endif
         let d={}
         try
-            execute s:py 'aurum.get_tags(vim.eval("a:repo.path"))'
+            execute s:pya.'get_tags(vim.eval("a:repo.path"))'
         endtry
         call s:F.updatewithtagsdict(a:repo.changesets, d)
         if a:repo.hasphases
             try
-                execute s:py 'aurum.get_phases(vim.eval("a:repo.path"))'
+                execute s:pya.'get_phases(vim.eval("a:repo.path"))'
             endtry
             " XXX empty() is here in order to prevent “using dictionary as 
             "     a Number” error
     function s:F.getupdates(repo, start)
         let r={}
         let tip_hex=a:repo.functions.getrevhex(a:repo, 'tip')
+        let cschange=1
         if a:start
             try
                 let oldtip=a:repo.functions.getcs(a:repo, a:start)
-                if tip_hex is# oldtip.hex
-                    return r
+                if tip_hex is# oldtp.hex
+                    let cschange=0
                 endif
                 let startrev=oldtip.rev
             catch
             let startrev=0
         endif
         let r.startrev=startrev
-        let r.css=s:F.getcslist(a:repo, startrev, -1)
+        if cschange
+            let r.css=s:F.getcslist(a:repo, startrev, -1)
+        else
+            let r.css=[]
+        endif
         for key in ['tags', 'bookmarks']
             let list=s:F.getkeylist(a:repo, key)
+            if cschange
+                call filter(list, 'v:val[1]<'.startrev)
+            endif
             let r[key]={}
-            for [name, rev] in filter(copy(list), 'v:val[1]<'.a:start)
+            for [name, rev] in list
                 let r[key][name]=a:repo.mutable.cslist[rev].hex
             endfor
         endfor
-        if a:repo.hasphases
+        if a:repo.hasphases && startrev
             let r.phases=map(s:F.hg(a:repo, 'phase', [],
-                        \           {'rev': '0:'.(a:start-1)}, 0),
+                        \           {'rev': '0:'.(startrev-1)}, 0),
                         \           'v:val[stridx(v:val, " ")+1:]')
         endif
-        let a:repo.csnum=a:start+len(r.css)
+        let a:repo.csnum=startrev+len(r.css)
         return r
     endfunction
     function s:F.updatetags(repo)
 function s:hg.getrevhex(repo, rev)
     try
         execute s:py 'vim.command(''return "''+'.
-                    \      'aurum.g_cs(aurum.g_repo(vim.eval("a:repo.path")), '.
-                    \               'vim.eval("a:rev")).hex()+''"'')'
+                    \      s:pp.'.g_cs('.
+                    \           s:pp.'.g_repo(vim.eval("a:repo.path")), '.
+                    \          'vim.eval("a:rev")).hex()+''"'')'
     catch /\v^Frawor:/
         throw v:exception
     catch
 if s:usepythondriver "▶2
 function s:hg.setcsprop(repo, cs, prop)
     try
-        execute s:py 'aurum.get_cs_prop(vim.eval("a:repo.path"), '.
-                    \                  'vim.eval("a:cs.hex"), '.
-                    \                  'vim.eval("a:prop"))'
+        execute s:pya.'get_cs_prop(vim.eval("a:repo.path"), '.
+                    \             'vim.eval("a:cs.hex"), '.
+                    \             'vim.eval("a:prop"))'
     endtry
 endfunction
 else "▶2
     let revargs=join(map(copy(a:000), 'v:val is 0? "None": string(v:val)'), ',')
     let d={}
     try
-        execute s:py 'aurum.get_status(vim.eval("a:repo.path"), '.revargs.')'
+        execute s:pya.'get_status(vim.eval("a:repo.path"), '.revargs.')'
     endtry
     return d
 endfunction
 function s:hg.dirty(repo, file)
     try
         let r=0
-        execute s:py 'aurum.dirty(vim.eval("a:repo.path"), '.
-                    \            'vim.eval("a:file"))'
+        execute s:pya.'dirty(vim.eval("a:repo.path"), vim.eval("a:file"))'
         return r
     endtry
 endfunction
         call s:_f.throw('uknphase', a:phase, s:phaseliststr)
     endif
     for phase in s:phaselist
-        " XXX something inside mercurial expects
+        " XXX something inside mercurial expects all these keys to be present
         let kwargs[phase]=(a:phase is# phase)
     endfor
     let kwargs.rev=[a:rev]
 if s:usepythondriver "▶2
 function s:hg.update(repo, rev, force)
     try
-        execute s:py 'aurum.update(vim.eval("a:repo.path"), '.
-                    \             'vim.eval("a:rev"), '.
-                    \             'int(vim.eval("a:force")))'
+        execute s:pya.'update(vim.eval("a:repo.path"), '.
+                    \        'vim.eval("a:rev"), '.
+                    \        'int(vim.eval("a:force")))'
     endtry
 endfunction
 else "▶2
     endtry
 endif
 if s:usepython "▶2
+if exists('*pyeval')
+function s:hg.ignore(repo, file)
+    let reline='^'.pyeval('re.escape(vim.bindeval("a:file"))').'$'
+    return s:F.addtosection(a:repo, hgignore, 'regexp', reline)
+endfunction
+else
 function s:hg.ignore(repo, file)
     let d={}
     execute s:py 'vim.eval("extend(d, {''pattern'': "+'.
     let reline='^'.d.pattern.'$'
     return s:F.addtosection(a:repo, hgignore, 'regexp', reline)
 endfunction
+endif
 else "▶2
 function s:hg.ignore(repo, file)
     let hgignore=s:_r.os.path.join(a:repo.path, '.hgignore')
 if s:usepythondriver "▶2
 function s:hg.grep(repo, pattern, files, revisions, ignore_case, wdfiles)
     let r=[]
-    execute s:py 'aurum.grep(vim.eval("a:repo.path"), '.
-                \           'vim.eval("a:pattern"), '.
-                \           'vim.eval("a:files"), '.
-                \           'vim.eval("a:revisions"), '.
-                \           'bool(int(vim.eval("a:ignore_case"))), '.
-                \           'bool(int(vim.eval("a:wdfiles"))))'
+    execute s:pya.'grep(vim.eval("a:repo.path"), '.
+                \      'vim.eval("a:pattern"), '.
+                \      'vim.eval("a:files"), '.
+                \      'vim.eval("a:revisions"), '.
+                \      'bool(int(vim.eval("a:ignore_case"))), '.
+                \      'bool(int(vim.eval("a:wdfiles"))))'
     return r
 endfunction
 else "▶2
 function s:hg.readfile(repo, rev, file)
     let r=[]
     try
-        execute s:py 'aurum.get_file(vim.eval("a:repo.path"), '.
-                    \               'vim.eval("a:rev"), '.
-                    \               'vim.eval("a:file"))'
+        execute s:pya.'get_file(vim.eval("a:repo.path"), '.
+                    \          'vim.eval("a:rev"), '.
+                    \          'vim.eval("a:file"))'
     endtry
     return r
 endfunction
 function s:hg.annotate(repo, rev, file)
     let r=[]
     try
-        execute s:py 'aurum.annotate(vim.eval("a:repo.path"), '.
-                    \               'vim.eval("a:rev"), '.
-                    \               'vim.eval("a:file"))'
+        execute s:pya.'annotate(vim.eval("a:repo.path"), '.
+                    \          'vim.eval("a:rev"), '.
+                    \          'vim.eval("a:file"))'
     endtry
     return r
 endfunction
     let r=[]
     let diffopts=s:_r.utils.diffopts(a:opts, a:repo.diffopts, s:difftrans)
     try
-        execute s:py 'aurum.diff(vim.eval("a:repo.path"), '.
-                    \           'vim.eval("a:rev1"), '.
-                    \           'vim.eval("a:rev2"), '.
-                    \           'vim.eval("a:files"), '.
-                    \           'vim.eval("diffopts"))'
+        execute s:pya.'diff(vim.eval("a:repo.path"), '.
+                    \      'vim.eval("a:rev1"), '.
+                    \      'vim.eval("a:rev2"), '.
+                    \      'vim.eval("a:files"), '.
+                    \      'vim.eval("diffopts"))'
     endtry
     return r
 endfunction
     endif
     try
         let diffopts=s:_r.utils.diffopts(a:opts, a:repo.diffopts, s:difftrans)
-        execute s:py 'aurum.diffToBuffer(vim.eval("a:repo.path"), '.
-                    \                   'vim.eval("a:rev1"), '.
-                    \                   'vim.eval("a:rev2"), '.
-                    \                   'vim.eval("a:files"), '.
-                    \                   'vim.eval("diffopts"))'
+        execute s:pya.'diffToBuffer(vim.eval("a:repo.path"), '.
+                    \              'vim.eval("a:rev1"), '.
+                    \              'vim.eval("a:rev2"), '.
+                    \              'vim.eval("a:files"), '.
+                    \              'vim.eval("diffopts"))'
     finally
         if oldbuf!=a:buf
             execute 'buffer' oldbuf
 function s:hg.getrepoprop(repo, prop)
     let d={}
     try
-        execute s:py 'aurum.get_repo_prop(vim.eval("a:repo.path"), '.
-                    \                    'vim.eval("a:prop"))'
+        execute s:pya.'get_repo_prop(vim.eval("a:repo.path"), '.
+                    \               'vim.eval("a:prop"))'
     endtry
     return d[a:prop]
 endfunction
     let repo={}
     try
         " execute s:py 'import cProfile as profile'
-        " execute s:py 'profile.run("aurum.new_repo(vim.eval(''a:path''))", "python.profile")'
-        execute s:py 'aurum.new_repo(vim.eval("a:path"))'
+        " execute s:py 'profile.run("'.s:pp.'.new_repo(vim.eval(''a:path''))", "python.profile")'
+        execute s:pya.'new_repo(vim.eval("a:path"))'
     catch /\V\^Frawor:\[^:]\+:norepo:/
         return 0
     endtry
 "▶1 hg.gitrev :: repo, rev → githex
 if s:usepythondriver
 function s:hg.githex(repo, rev)
-    execute s:py 'aurum.git_hash(vim.eval("a:repo.path"), '.
-                \               'vim.eval("a:rev"))'
+    execute s:pya.'git_hash(vim.eval("a:repo.path"), vim.eval("a:rev"))'
 endfunction
 endif
 "▶1 Register driver

python/aurum.py

-from mercurial import hg, ui, commands, match
-from mercurial.repo import error
-import vim
-import os
-import json
-import re
-import sys
-
-def outermethod(func):
-    """
-        Decorator used to make functions omit showing python traceback in case vim_throw was used.
-        Also transforms first argument (which is a path) to an repository object
-    """
-    def f(path, *args, **kwargs):
-        try:
-            repo=g_repo(path)
-            try:
-                func(repo, *args, **kwargs)
-            finally:
-                repo.ui.flush()
-        except AurumError:
-            pass
-        except vim.error:
-            pass
-    return f
-
-def nonutf_dumps(obj):
-    todump=[('dump', obj)]
-    r=''
-    while todump:
-        t, obj = todump.pop(0)
-        if t == 'inject':
-            r+=obj
-        else:
-            tobj=type(obj)
-            if tobj is int:
-                r+=str(obj)
-            elif tobj is float:
-                r += "%1.1e" % obj
-            elif tobj is list or tobj is tuple:
-                r+='['
-                todump.insert(0, ('inject', ']'))
-                for value in reversed(obj):
-                    todump[:0]=[('dump', value), ('inject', ',')]
-            elif tobj is dict:
-                r+='{'
-                todump.insert(0, ('inject', '}'))
-                for key, value in obj.items():
-                    todump[:0]=[('dump', key),
-                                ('inject', ':'),
-                                ('dump', value),
-                                ('inject', ',')]
-            else:
-                r+='"'+str(obj).replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')+'"'
-    return r
-
-def pyecho(o, error=False):
-    try:
-        return (sys.stderr if error else sys.stdout).write(str(o))
-    except UnicodeDecodeError:
-        if error:
-            vim.command('echohl ErrorMsg')
-        for line in str(o).split("\n"):
-            if not line:
-                line=' '
-            vim.command('echomsg '+utf_dumps(line))
-        if error:
-            vim.command('echohl None')
-
-if hasattr(vim, 'bindeval'):
-    ansi_esc_echo_func=None
-    def register_ansi_esc_echo_func(func):
-        global ansi_esc_echo_func
-        ansi_esc_echo_func=func
-        global echom
-        echom=ansi_esc_echo
-
-    def ansi_esc_echo(o, colinfo):
-        if colinfo is None:
-            return ansi_esc_echo_func(str(o), self={})
-        else:
-            return ansi_esc_echo_func(str(o), colinfo, self={})
-
-echoe=lambda o, colinfo: pyecho(o, True )
-echom=lambda o, colinfo: pyecho(o, False)
-
-def utf_dumps(obj):
-    return json.dumps(obj, encoding='utf8')
-
-class AurumError(Exception):
-    pass
-
-class VIMEncode(json.JSONEncoder):
-    def encode(self, obj, *args, **kwargs):
-        if isinstance(obj, (dict, list, int)):
-            return super(VIMEncode, self).encode(obj, *args, **kwargs)
-        return '"'+str(obj).replace('\\', '\\\\').replace('"', '\\"')+'"'
-
-class PrintUI(ui.ui):
-    # ui.ui for some reason does not support outputting unicode
-    def write(self, *args, **kwargs):
-        if self._buffers:
-            self._buffers[-1].extend([str(a) for a in args])
-        else:
-            colinfo=None
-            for a in args:
-                colinfo=echom(a, colinfo)
-
-    def write_err(self, *args, **kwargs):
-        colinfo=None
-        for a in args:
-            colinfo=echoe(a, colinfo)
-
-class CaptureUI(PrintUI):
-    def __init__(self):
-        self._captured=[]
-        super(CaptureUI, self).__init__()
-
-    def write(self, *args, **kwargs):
-        target=self._buffers[-1] if self._buffers else self._captured
-        target.extend([str(a) for a in args])
-
-    def _getCaptured(self, verbatim=False):
-        if verbatim:
-            return "".join(self._captured)
-        r=[s.replace("\0", "\n") for s in ("".join(self._captured)).split("\n")]
-        self._captured=[]
-        return r
-
-class CaptureToBuf(PrintUI):
-    def __init__(self, buf):
-        self._vimbuffer=buf
-        super(CaptureToBuf, self).__init__()
-
-    def write(self, *args, **kwargs):
-        target=self._buffers[-1] if self._buffers else self._vimbuffer
-        for a in args:
-            lines=str(a).split("\n")
-            target[-1]+=lines.pop(0)
-            for line in lines:
-                target.append(line)
-
-def vim_throw(*args):
-    vim.command('call s:_f.throw('+nonutf_dumps(args)[1:-1]+')')
-    raise AurumError()
-
-def g_repo(path):
-    try:
-        return hg.repository(PrintUI(), path)
-    except error.RepoError:
-        vim_throw('norepo', path)
-
-def g_cs(repo, rev):
-    try:
-        if not hasattr(repo, '__getitem__'):
-            vim.command('call s:_f.throw("csuns", '+nonutf_dumps(repo.path)+')')
-            raise AurumError()
-        return repo[rev]
-    except error.RepoLookupError:
-        vim_throw('norev', rev, repo.path)
-
-def g_fctx(cs, filepath):
-    try:
-        return cs.filectx(filepath)
-    except error.LookupError:
-        vim_throw('nofile', filepath, cs.hex(), cs._repo.path)
-
-def set_rev_dict(cs, cs_vim):
-    cs_vim['hex']=cs.hex()
-    cs_vim['time']=int(cs.date()[0])
-    cs_vim['description']=cs.description()
-    cs_vim['user']=cs.user()
-    cs_vim['parents']=[parent.hex() for parent in cs.parents()]
-    try:
-        branch=cs.branch()
-        cs_vim['branch']=branch
-        cs_vim['tags']=cs.tags()
-        cs_vim['bookmarks']=cs.bookmarks()
-    except AttributeError:
-        pass
-    return cs_vim
-
-def get_revlist(repo, startrev=0):
-    cscount=len(repo)
-    r=[set_rev_dict(g_cs(repo, i), {'rev': i,}) for i in range(startrev, cscount+1)]
-    return r
-
-if hasattr(vim, 'bindeval'):
-    def vim_extend(val, var='d', utf=True, list=False):
-        d_vim = vim.bindeval(var)
-        if list:
-            d_vim.extend(val)
-        else:
-            for key in val:
-                d_vim[key] = val[key]
-else:
-    def vim_extend(val, var='d', utf=True, list=False):
-        vim.eval('extend('+var+', '+((utf_dumps if utf else nonutf_dumps)(val))+')')
-
-@outermethod
-def get_updates(repo, oldtip=None):
-    tipcs=repo['tip']
-    if oldtip is not None:
-        try:
-            cs=repo[oldtip]
-            if tipcs.hex()==cs.hex():
-                return
-            startrev=cs.rev()
-        except error.RepoLookupError:
-            startrev=0
-    else:
-        startrev=0
-    r=get_revlist(repo, startrev)
-    tags_vim={}
-    for (tag, b) in repo.tags().items():
-        tags_vim[tag]=repo[b].hex()
-    bookmarks_vim={}
-    if hasattr(repo, 'listkeys'):
-        bookmarks_vim=repo.listkeys('bookmarks')
-    vim_extend(var='a:repo', val={'csnum': (len(repo)+1)})
-    vim_extend(val={'css': r,
-               'startrev': startrev,
-                   'tags': tags_vim,
-              'bookmarks': bookmarks_vim,})
-    if hasattr(tipcs, 'phase'):
-        vim_extend(val={'phases': [repo[rev].phasestr() for rev in range(startrev)]})
-
-def get_cs_tag_dict(l):
-    r={}
-    for hex, tag in l:
-        if hex in r:
-            r[hex].append(tag)
-        else:
-            r[hex]=[tag]
-    for key in r:
-        r[key].sort()
-    return r
-
-@outermethod
-def get_tags(repo):
-    tags=get_cs_tag_dict([(repo[val].hex(), key) for key, val
-                          in repo.tags().items()])
-    bookmarks={}
-    if hasattr(repo, 'listkeys'):
-        bookmarks=get_cs_tag_dict([(val, key) for key, val
-                                   in repo.listkeys('bookmarks').items()])
-    vim_extend(val={'tags': tags, 'bookmarks': bookmarks})
-
-@outermethod
-def get_phases(repo):
-    vim_extend(val={'phasemap': dict((lambda cs: (cs.hex(), cs.phasestr()))(repo[rev]) for rev in repo)})
-
-@outermethod
-def get_cs(repo, rev):
-    cs=g_cs(repo, rev)
-    vim_extend(var='cs', val=set_rev_dict(cs, {'rev': cs.rev()}))
-
-@outermethod
-def new_repo(repo):
-    # TODO remove bookmark label type if it is not available
-    vim_repo={'has_octopus_merges': 0,
-                   'requires_sort': 0,
-                      'changesets': {},
-                         'mutable': {'cslist': []},
-                           'local': 1 if repo.local() else 0,
-                      'labeltypes': ['tag', 'bookmark'],
-                       'hasphases': int(hasattr(repo[None], 'phase')),
-             }
-    if hasattr(repo, '__len__'):
-        vim_repo['csnum']=len(repo)+1
-    vim_extend(var='repo', val=vim_repo)
-
-@outermethod
-def get_file(repo, rev, filepath):
-    fctx=g_fctx(g_cs(repo, rev), filepath)
-    lines=[line.replace("\0", "\n") for line in fctx.data().split("\n")]
-    vim_extend(var='r', val=lines, utf=False, list=True)
-
-@outermethod
-def annotate(repo, rev, filepath):
-    ann=g_fctx(g_cs(repo, rev), filepath).annotate(follow=True, linenumber=True)
-    ann_vim=[(line[0][0].path(), str(line[0][0].rev()), line[0][1])
-                                                            for line in ann]
-    vim_extend(var='r', val=ann_vim, utf=False, list=True)
-
-def run_in_dir(dir, func, *args, **kwargs):
-    workdir=os.path.abspath('.')
-    try:
-        os.chdir(dir)
-    except AttributeError:
-        pass
-    except OSError:
-        pass
-    try:
-        func(*args, **kwargs)
-    finally:
-        os.chdir(workdir)
-
-def dodiff(ui, repo, rev1, rev2, files, opts):
-    if not hasattr(repo, '__getitem__'):
-        vim_throw('diffuns', repo.path)
-    args=[ui, repo]+files
-    kwargs=opts
-    if rev2:
-        kwargs["rev"]=[rev2]
-        if rev1:
-            kwargs["rev"].append(rev1)
-    else:
-        if rev1:
-            kwargs["change"]=rev1
-    run_in_dir(repo.root, commands.diff, *args, **kwargs)
-
-@outermethod
-def diff(*args, **kwargs):
-    ui=CaptureUI()
-    dodiff(ui, *args, **kwargs)
-    vim_extend(var='r', val=ui._getCaptured(), utf=False, list=True)
-
-@outermethod
-def diffToBuffer(*args, **kwargs):
-    ui=CaptureToBuf(vim.current.buffer)
-    dodiff(ui, *args, **kwargs)
-    if len(vim.current.buffer)>1 and vim.current.buffer[-1] == '':
-        vim.current.buffer[-1:]=[]
-    else:
-        vim.command('setlocal binary noendofline')
-
-def get_renames(cs):
-    def get_renames_value(rename):
-        return rename[0] if rename else 0
-    renames_vim={}
-    copies_vim={}
-    for f in cs:
-        fctx=g_fctx(cs, f)
-        rename=get_renames_value(fctx.renamed())
-        if rename:
-            if rename in cs:
-                copies_vim[f]=rename
-                renames_vim[f]=0
-            else:
-                copies_vim[f]=0
-                renames_vim[f]=rename
-        else:
-            copies_vim[f]=0
-            renames_vim[f]=0
-    vim_extend(var='a:cs', val={'renames': renames_vim, 'copies': copies_vim},
-               utf=False)
-
-@outermethod
-def get_cs_prop(repo, rev, prop):
-    cs=g_cs(repo, rev)
-    if prop=='files' or prop=='removes' or prop=='changes':
-        am=[]
-        r=[]
-        c=cs.files()
-        for f in c:
-            if f in cs:
-                am.append(f)
-            else:
-                r.append(f)
-        vim_extend(var='a:cs', val={'files': am, 'removes': r, 'changes': c},
-                   utf=False)
-        return
-    elif prop=='renames' or prop=='copies':
-        get_renames(cs)
-        return
-    elif prop=='allfiles':
-        r=[f for f in cs]
-    elif prop=='children':
-        r=[ccs.hex() for ccs in cs.children()]
-    elif prop=='phase':
-        if hasattr(cs, 'phasestr'):
-            r=cs.phasestr()
-        else:
-            r='unknown'
-    else:
-        r=cs.__getattribute__(prop)()
-    # XXX There is much code relying on the fact that after getcsprop
-    #     property with given name is added to changeset dictionary
-    vim_extend(var='a:cs', val={prop : r}, utf=False)
-
-@outermethod
-def get_status(repo, rev1=None, rev2=None, files=None, clean=None):
-    if rev1 is None and rev2 is None:
-        rev1='.'
-    if hasattr(repo, 'status'):
-        if not files:
-            m=None
-        else:
-            m=match.match(None, None, files, exact=True)
-        status=repo.status(rev1, rev2, ignored=True, clean=clean,
-                           unknown=True, match=m)
-        vim_extend(val={'modified': status[0],
-                           'added': status[1],
-                         'removed': status[2],
-                         'deleted': status[3],
-                         'unknown': status[4],
-                         'ignored': status[5],
-                           'clean': status[6],},
-                   utf=False)
-    else:
-        vim_throw('statuns', repo.path)
-
-@outermethod
-def update(repo, rev='tip', force=False):
-    if not hasattr(repo, '__getitem__'):
-        vim_throw('upduns', repo.path)
-    rev=g_cs(repo, rev).hex()
-    args=[repo.ui, repo, rev]
-    kwargs={'clean': bool(force)}
-    run_in_dir(repo.root, commands.update, *args, **kwargs)
-
-@outermethod
-def dirty(repo, filepath):
-    if not hasattr(repo, '__getitem__'):
-        vim_throw('statuns', repo.path)
-    dirty=repo[None].dirty()
-    if dirty and filepath in dirty:
-        vim.command('let r=1')
-
-repo_props={
-            'tagslist': lambda repo: repo.tags().keys(),
-        'brancheslist': lambda repo: repo.branchmap().keys(),
-       'bookmarkslist': lambda repo: repo.listkeys('bookmarks').keys()
-                                        if hasattr(repo, 'listkeys') else [],
-                 'url': lambda repo: repo.ui.config('paths', 'default-push') or
-                                     repo.ui.config('paths', 'default'),
-              'branch': lambda repo: repo.dirstate.branch(),
-        }
-@outermethod
-def get_repo_prop(repo, prop):
-    if prop in repo_props:
-        r=repo_props[prop](repo)
-        if r is None:
-            vim_throw('failcfg', prop, repo.path)
-        else:
-            vim_extend(val={prop : r})
-    else:
-        vim_throw('nocfg', repo.path, prop)
-
-@outermethod
-def call_cmd(repo, attr, bkwargs, *args, **kwargs):
-    if bkwargs:
-        for kw in bkwargs:
-            if kw in kwargs:
-                kwargs[kw]=bool(int(kwargs[kw]))
-    if 'force' in kwargs:
-        kwargs['force']=bool(int(kwargs['force']))
-    else:
-        kwargs['force']=False
-    if 'bundle' not in kwargs:
-        kwargs['bundle']=None
-    for key in [key for key in kwargs if key.find('-')!=-1]:
-        newkey=key.replace('-', '_')
-        kwargs[newkey]=kwargs.pop(key)
-    cargs=[repo.ui, repo]
-    cargs.extend(args)
-    run_in_dir(repo.root, commands.__getattribute__(attr),
-               *cargs, **kwargs)
-
-@outermethod
-def grep(repo, pattern, files, revisions=None, ignore_case=False, wdfiles=True):
-    ui=CaptureUI()
-    args=[ui, repo, pattern]
-    args.extend(files)
-    revisions=[":".join(rev) if type(rev) is list else rev
-                             for rev in revisions]
-    if not revisions:
-        revisions=None
-    kwargs={'rev': revisions, 'ignore_case': bool(ignore_case),
-            'line_number': True, 'print0': True}
-    cs=g_cs(repo, '.')
-    kwargs['follow']=not [f for f in files if f not in cs]
-    run_in_dir(repo.root, commands.grep, *args, **kwargs)
-    items=(ui._getCaptured(verbatim=True)).split("\0")
-    # XXX grep uses "\0" as a terminator, thus last line ends with "\0"
-    items.pop()
-    r_vim=[]
-    status_cache={}
-    def check_not_modified_since(rev, file):
-        key=rev+':'+file
-        if key in status_cache:
-            return status_cache[key]
-        r=file in repo.status(node1=rev, clean=True,
-                              match=match.match(None, None, [file],
-                                                exact=True))[6]
-        status_cache[key]=r
-        return r
-    while items:
-        file=items.pop(0)
-        rev=items.pop(0)
-        lnum=int(items.pop(0))
-        text=items.pop(0)
-        if wdfiles and check_not_modified_since(rev, file):
-            file=os.path.join(repo.root, file)
-        else:
-            file=(rev, file)
-        r_vim.append({'filename': file, 'lnum': int(lnum), 'text': text})
-    vim_extend(var='r', val=r_vim, utf=False, list=True)
-
-@outermethod
-def git_hash(repo, rev):
-    hggitpath=None
-    hggitname=None
-    for hggitname in ['hggit', 'git']:
-        hggitpath=repo.ui.config('extensions', hggitname)
-        if hggitpath is not None:
-            break
-    if hggitpath is None:
-        vim_throw('nohggitc')
-    import sys
-    sys.path.insert(0, hggitpath)
-    try:
-        try:
-            if hggitname=='hggit':
-                from hggit.git_handler import GitHandler
-            elif hggitname=='git':
-                from git.git_handler   import GitHandler
-        except ImportError:
-            vim_throw('nohggit')
-        git=GitHandler(repo, repo.ui)
-        cs=g_cs(repo, rev)
-        r=git.map_git_get(cs.hex())
-        if r is None:
-            vim_throw('nogitrev', cs.hex(), repo.path)
-        vim.command('return '+json.dumps(r))
-    finally:
-        sys.path.pop(0)
Add a comment to this file

python/aurum/__init__.py

Empty file added.

python/aurum/aumercurial.py

+from mercurial import hg, ui, commands, match
+from mercurial.repo import error
+import vim
+import os
+import json
+import re
+import sys
+
+def outermethod(func):
+    """
+        Decorator used to make functions omit showing python traceback in case vim_throw was used.
+        Also transforms first argument (which is a path) to an repository object
+    """
+    def f(path, *args, **kwargs):
+        try:
+            repo=g_repo(path)
+            try:
+                func(repo, *args, **kwargs)
+            finally:
+                repo.ui.flush()
+        except AurumError:
+            pass
+        except vim.error:
+            pass
+    return f
+
+def nonutf_dumps(obj):
+    todump=[('dump', obj)]
+    r=''
+    while todump:
+        t, obj = todump.pop(0)
+        if t == 'inject':
+            r+=obj
+        else:
+            tobj=type(obj)
+            if tobj is int:
+                r+=str(obj)
+            elif tobj is float:
+                r += "%1.1e" % obj
+            elif tobj is list or tobj is tuple:
+                r+='['
+                todump.insert(0, ('inject', ']'))
+                for value in reversed(obj):
+                    todump[:0]=[('dump', value), ('inject', ',')]
+            elif tobj is dict:
+                r+='{'
+                todump.insert(0, ('inject', '}'))
+                for key, value in obj.items():
+                    todump[:0]=[('dump', key),
+                                ('inject', ':'),
+                                ('dump', value),
+                                ('inject', ',')]
+            else:
+                r+='"'+str(obj).replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')+'"'
+    return r
+
+def pyecho(o, error=False):
+    try:
+        return (sys.stderr if error else sys.stdout).write(str(o))
+    except UnicodeDecodeError:
+        if error:
+            vim.command('echohl ErrorMsg')
+        for line in str(o).split("\n"):
+            if not line:
+                line=' '
+            vim.command('echomsg '+utf_dumps(line))
+        if error:
+            vim.command('echohl None')
+
+if hasattr(vim, 'bindeval'):
+    ansi_esc_echo_func=None
+    def register_ansi_esc_echo_func(func):
+        global ansi_esc_echo_func
+        ansi_esc_echo_func=func
+        global echom
+        echom=ansi_esc_echo
+
+    def ansi_esc_echo(o, colinfo):
+        if colinfo is None:
+            return ansi_esc_echo_func(str(o), self={})
+        else:
+            return ansi_esc_echo_func(str(o), colinfo, self={})
+
+echoe=lambda o, colinfo: pyecho(o, True )
+echom=lambda o, colinfo: pyecho(o, False)
+
+def utf_dumps(obj):
+    return json.dumps(obj, encoding='utf8')
+
+class AurumError(Exception):
+    pass
+
+class VIMEncode(json.JSONEncoder):
+    def encode(self, obj, *args, **kwargs):
+        if isinstance(obj, (dict, list, int)):
+            return super(VIMEncode, self).encode(obj, *args, **kwargs)
+        return '"'+str(obj).replace('\\', '\\\\').replace('"', '\\"')+'"'
+
+class PrintUI(ui.ui):
+    # ui.ui for some reason does not support outputting unicode
+    def write(self, *args, **kwargs):
+        if self._buffers:
+            self._buffers[-1].extend([str(a) for a in args])
+        else:
+            colinfo=None
+            for a in args:
+                colinfo=echom(a, colinfo)
+
+    def write_err(self, *args, **kwargs):
+        colinfo=None
+        for a in args:
+            colinfo=echoe(a, colinfo)
+
+class CaptureUI(PrintUI):
+    def __init__(self):
+        self._captured=[]
+        super(CaptureUI, self).__init__()
+
+    def write(self, *args, **kwargs):
+        target=self._buffers[-1] if self._buffers else self._captured
+        target.extend([str(a) for a in args])
+
+    def _getCaptured(self, verbatim=False):
+        if verbatim:
+            return "".join(self._captured)
+        r=[s.replace("\0", "\n") for s in ("".join(self._captured)).split("\n")]
+        self._captured=[]
+        return r
+
+class CaptureToBuf(PrintUI):
+    def __init__(self, buf):
+        self._vimbuffer=buf
+        super(CaptureToBuf, self).__init__()
+
+    def write(self, *args, **kwargs):
+        target=self._buffers[-1] if self._buffers else self._vimbuffer
+        for a in args:
+            lines=str(a).split("\n")
+            target[-1]+=lines.pop(0)
+            for line in lines:
+                target.append(line)
+
+def vim_throw(*args):
+    vim.command('call s:_f.throw('+nonutf_dumps(args)[1:-1]+')')
+    raise AurumError()
+
+def g_repo(path):
+    try:
+        return hg.repository(PrintUI(), path)
+    except error.RepoError:
+        vim_throw('norepo', path)
+
+def g_cs(repo, rev):
+    try:
+        if not hasattr(repo, '__getitem__'):
+            vim.command('call s:_f.throw("csuns", '+nonutf_dumps(repo.path)+')')
+            raise AurumError()
+        return repo[rev]
+    except error.RepoLookupError:
+        vim_throw('norev', rev, repo.path)
+
+def g_fctx(cs, filepath):
+    try:
+        return cs.filectx(filepath)
+    except error.LookupError:
+        vim_throw('nofile', filepath, cs.hex(), cs._repo.path)
+
+def set_rev_dict(cs, cs_vim):
+    cs_vim['hex']=cs.hex()
+    cs_vim['time']=int(cs.date()[0])
+    cs_vim['description']=cs.description()
+    cs_vim['user']=cs.user()
+    cs_vim['parents']=[parent.hex() for parent in cs.parents()]
+    try:
+        branch=cs.branch()
+        cs_vim['branch']=branch
+        cs_vim['tags']=cs.tags()
+        cs_vim['bookmarks']=cs.bookmarks()
+    except AttributeError:
+        pass
+    return cs_vim
+
+def get_revlist(repo, startrev=0):
+    cscount=len(repo)
+    r=[set_rev_dict(g_cs(repo, i), {'rev': i,}) for i in range(startrev, cscount+1)]
+    return r
+
+if hasattr(vim, 'bindeval'):
+    def vim_extend(val, var='d', utf=True, list=False):
+        d_vim = vim.bindeval(var)
+        if list:
+            d_vim.extend(val)
+        else:
+            for key in val:
+                d_vim[key] = val[key]
+else:
+    def vim_extend(val, var='d', utf=True, list=False):
+        vim.eval('extend('+var+', '+((utf_dumps if utf else nonutf_dumps)(val))+')')
+
+@outermethod
+def get_updates(repo, oldtip=None):
+    tipcs=repo['tip']
+    if oldtip is not None:
+        try:
+            cs=repo[oldtip]
+            if tipcs.hex()==cs.hex():
+                return
+            startrev=cs.rev()
+        except error.RepoLookupError:
+            startrev=0
+    else:
+        startrev=0
+    r=get_revlist(repo, startrev)
+    tags_vim={}
+    for (tag, b) in repo.tags().items():
+        tags_vim[tag]=repo[b].hex()
+    bookmarks_vim={}
+    if hasattr(repo, 'listkeys'):
+        bookmarks_vim=repo.listkeys('bookmarks')
+    vim_extend(var='a:repo', val={'csnum': (len(repo)+1)})
+    vim_extend(val={'css': r,
+               'startrev': startrev,
+                   'tags': tags_vim,
+              'bookmarks': bookmarks_vim,})
+    if hasattr(tipcs, 'phase'):
+        vim_extend(val={'phases': [repo[rev].phasestr() for rev in range(startrev)]})
+
+def get_cs_tag_dict(l):
+    r={}
+    for hex, tag in l:
+        if hex in r:
+            r[hex].append(tag)
+        else:
+            r[hex]=[tag]
+    for key in r:
+        r[key].sort()
+    return r
+
+@outermethod
+def get_tags(repo):
+    tags=get_cs_tag_dict([(repo[val].hex(), key) for key, val
+                          in repo.tags().items()])
+    bookmarks={}
+    if hasattr(repo, 'listkeys'):
+        bookmarks=get_cs_tag_dict([(val, key) for key, val
+                                   in repo.listkeys('bookmarks').items()])
+    vim_extend(val={'tags': tags, 'bookmarks': bookmarks})
+
+@outermethod
+def get_phases(repo):
+    vim_extend(val={'phasemap': dict((lambda cs: (cs.hex(), cs.phasestr()))(repo[rev]) for rev in repo)})
+
+@outermethod
+def get_cs(repo, rev):
+    cs=g_cs(repo, rev)
+    vim_extend(var='cs', val=set_rev_dict(cs, {'rev': cs.rev()}))
+
+@outermethod
+def new_repo(repo):
+    # TODO remove bookmark label type if it is not available
+    vim_repo={'has_octopus_merges': 0,
+                   'requires_sort': 0,
+                      'changesets': {},
+                         'mutable': {'cslist': []},
+                           'local': 1 if repo.local() else 0,
+                      'labeltypes': ['tag', 'bookmark'],
+                       'hasphases': int(hasattr(repo[None], 'phase')),
+             }
+    if hasattr(repo, '__len__'):
+        vim_repo['csnum']=len(repo)+1
+    vim_extend(var='repo', val=vim_repo)
+
+@outermethod
+def get_file(repo, rev, filepath):
+    fctx=g_fctx(g_cs(repo, rev), filepath)
+    lines=[line.replace("\0", "\n") for line in fctx.data().split("\n")]
+    vim_extend(var='r', val=lines, utf=False, list=True)
+
+@outermethod
+def annotate(repo, rev, filepath):
+    ann=g_fctx(g_cs(repo, rev), filepath).annotate(follow=True, linenumber=True)
+    ann_vim=[(line[0][0].path(), str(line[0][0].rev()), line[0][1])
+                                                            for line in ann]
+    vim_extend(var='r', val=ann_vim, utf=False, list=True)
+
+def run_in_dir(dir, func, *args, **kwargs):
+    workdir=os.path.abspath('.')
+    try:
+        os.chdir(dir)
+    except AttributeError:
+        pass
+    except OSError:
+        pass
+    try:
+        func(*args, **kwargs)
+    finally:
+        os.chdir(workdir)
+
+def dodiff(ui, repo, rev1, rev2, files, opts):
+    if not hasattr(repo, '__getitem__'):
+        vim_throw('diffuns', repo.path)
+    args=[ui, repo]+files
+    kwargs=opts
+    if rev2:
+        kwargs["rev"]=[rev2]
+        if rev1:
+            kwargs["rev"].append(rev1)
+    else:
+        if rev1:
+            kwargs["change"]=rev1
+    run_in_dir(repo.root, commands.diff, *args, **kwargs)
+
+@outermethod
+def diff(*args, **kwargs):
+    ui=CaptureUI()
+    dodiff(ui, *args, **kwargs)
+    vim_extend(var='r', val=ui._getCaptured(), utf=False, list=True)
+
+@outermethod
+def diffToBuffer(*args, **kwargs):
+    ui=CaptureToBuf(vim.current.buffer)
+    dodiff(ui, *args, **kwargs)
+    if len(vim.current.buffer)>1 and vim.current.buffer[-1] == '':
+        vim.current.buffer[-1:]=[]
+    else:
+        vim.command('setlocal binary noendofline')
+
+def get_renames(cs):
+    def get_renames_value(rename):
+        return rename[0] if rename else 0
+    renames_vim={}
+    copies_vim={}
+    for f in cs:
+        fctx=g_fctx(cs, f)
+        rename=get_renames_value(fctx.renamed())
+        if rename:
+            if rename in cs:
+                copies_vim[f]=rename
+                renames_vim[f]=0
+            else:
+                copies_vim[f]=0
+                renames_vim[f]=rename
+        else:
+            copies_vim[f]=0
+            renames_vim[f]=0
+    vim_extend(var='a:cs', val={'renames': renames_vim, 'copies': copies_vim},
+               utf=False)
+
+@outermethod
+def get_cs_prop(repo, rev, prop):
+    cs=g_cs(repo, rev)
+    if prop=='files' or prop=='removes' or prop=='changes':
+        am=[]
+        r=[]
+        c=cs.files()
+        for f in c:
+            if f in cs:
+                am.append(f)
+            else:
+                r.append(f)
+        vim_extend(var='a:cs', val={'files': am, 'removes': r, 'changes': c},
+                   utf=False)
+        return
+    elif prop=='renames' or prop=='copies':
+        get_renames(cs)
+        return
+    elif prop=='allfiles':
+        r=[f for f in cs]
+    elif prop=='children':
+        r=[ccs.hex() for ccs in cs.children()]
+    elif prop=='phase':
+        if hasattr(cs, 'phasestr'):
+            r=cs.phasestr()
+        else:
+            r='unknown'
+    else:
+        r=cs.__getattribute__(prop)()
+    # XXX There is much code relying on the fact that after getcsprop
+    #     property with given name is added to changeset dictionary
+    vim_extend(var='a:cs', val={prop : r}, utf=False)
+
+@outermethod
+def get_status(repo, rev1=None, rev2=None, files=None, clean=None):
+    if rev1 is None and rev2 is None:
+        rev1='.'
+    if hasattr(repo, 'status'):
+        if not files:
+            m=None
+        else:
+            m=match.match(None, None, files, exact=True)
+        status=repo.status(rev1, rev2, ignored=True, clean=clean,
+                           unknown=True, match=m)
+        vim_extend(val={'modified': status[0],
+                           'added': status[1],
+                         'removed': status[2],
+                         'deleted': status[3],
+                         'unknown': status[4],
+                         'ignored': status[5],
+                           'clean': status[6],},
+                   utf=False)
+    else:
+        vim_throw('statuns', repo.path)
+
+@outermethod
+def update(repo, rev='tip', force=False):
+    if not hasattr(repo, '__getitem__'):
+        vim_throw('upduns', repo.path)
+    rev=g_cs(repo, rev).hex()
+    args=[repo.ui, repo, rev]
+    kwargs={'clean': bool(force)}
+    run_in_dir(repo.root, commands.update, *args, **kwargs)
+
+@outermethod
+def dirty(repo, filepath):
+    if not hasattr(repo, '__getitem__'):
+        vim_throw('statuns', repo.path)
+    dirty=repo[None].dirty()
+    if dirty and filepath in dirty:
+        vim.command('let r=1')
+
+repo_props={
+            'tagslist': lambda repo: repo.tags().keys(),
+        'brancheslist': lambda repo: repo.branchmap().keys(),
+       'bookmarkslist': lambda repo: repo.listkeys('bookmarks').keys()
+                                        if hasattr(repo, 'listkeys') else [],
+                 'url': lambda repo: repo.ui.config('paths', 'default-push') or
+                                     repo.ui.config('paths', 'default'),
+              'branch': lambda repo: repo.dirstate.branch(),
+        }
+@outermethod
+def get_repo_prop(repo, prop):
+    if prop in repo_props:
+        r=repo_props[prop](repo)
+        if r is None:
+            vim_throw('failcfg', prop, repo.path)
+        else:
+            vim_extend(val={prop : r})
+    else:
+        vim_throw('nocfg', repo.path, prop)
+
+@outermethod
+def call_cmd(repo, attr, bkwargs, *args, **kwargs):
+    if bkwargs:
+        for kw in bkwargs:
+            if kw in kwargs:
+                kwargs[kw]=bool(int(kwargs[kw]))
+    if 'force' in kwargs:
+        kwargs['force']=bool(int(kwargs['force']))
+    else:
+        kwargs['force']=False
+    if 'bundle' not in kwargs:
+        kwargs['bundle']=None
+    for key in [key for key in kwargs if key.find('-')!=-1]:
+        newkey=key.replace('-', '_')
+        kwargs[newkey]=kwargs.pop(key)
+    cargs=[repo.ui, repo]
+    cargs.extend(args)
+    run_in_dir(repo.root, commands.__getattribute__(attr),
+               *cargs, **kwargs)
+
+@outermethod
+def grep(repo, pattern, files, revisions=None, ignore_case=False, wdfiles=True):
+    ui=CaptureUI()
+    args=[ui, repo, pattern]
+    args.extend(files)
+    revisions=[":".join(rev) if type(rev) is list else rev
+                             for rev in revisions]
+    if not revisions:
+        revisions=None
+    kwargs={'rev': revisions, 'ignore_case': bool(ignore_case),
+            'line_number': True, 'print0': True}
+    cs=g_cs(repo, '.')
+    kwargs['follow']=not [f for f in files if f not in cs]
+    run_in_dir(repo.root, commands.grep, *args, **kwargs)
+    items=(ui._getCaptured(verbatim=True)).split("\0")
+    # XXX grep uses "\0" as a terminator, thus last line ends with "\0"
+    items.pop()
+    r_vim=[]
+    status_cache={}
+    def check_not_modified_since(rev, file):
+        key=rev+':'+file
+        if key in status_cache:
+            return status_cache[key]
+        r=file in repo.status(node1=rev, clean=True,
+                              match=match.match(None, None, [file],
+                                                exact=True))[6]
+        status_cache[key]=r
+        return r
+    while items:
+        file=items.pop(0)
+        rev=items.pop(0)
+        lnum=int(items.pop(0))
+        text=items.pop(0)
+        if wdfiles and check_not_modified_since(rev, file):
+            file=os.path.join(repo.root, file)
+        else:
+            file=(rev, file)
+        r_vim.append({'filename': file, 'lnum': int(lnum), 'text': text})
+    vim_extend(var='r', val=r_vim, utf=False, list=True)
+
+@outermethod
+def git_hash(repo, rev):
+    hggitpath=None
+    hggitname=None
+    for hggitname in ['hggit', 'git']:
+        hggitpath=repo.ui.config('extensions', hggitname)
+        if hggitpath is not None:
+            break
+    if hggitpath is None:
+        vim_throw('nohggitc')
+    import sys
+    sys.path.insert(0, hggitpath)
+    try:
+        try:
+            if hggitname=='hggit':
+                from hggit.git_handler import GitHandler
+            elif hggitname=='git':
+                from git.git_handler   import GitHandler
+        except ImportError:
+            vim_throw('nohggit')
+        git=GitHandler(repo, repo.ui)
+        cs=g_cs(repo, rev)
+        r=git.map_git_get(cs.hex())
+        if r is None:
+            vim_throw('nogitrev', cs.hex(), repo.path)
+        vim.command('return '+json.dumps(r))
+    finally:
+        sys.path.pop(0)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.