Commits

ZyX_I committed 1d5a549 Merge

Merge

  • Participants
  • Parent commits 40f285f, 52a8630
  • Branches bzr-support

Comments (0)

Files changed (17)

File autoload/aurum/commit.vim

 "▶1 commfunc
 function s:cmd.function(opts, ...)
     let rrfopts=copy(a:opts)
-    if a:0 && index(a:000, 'all')==-1
+    let hasall=index(a:000, 'all')!=-1
+    if a:0 && !hasall
         let rrfopts.files=a:000
     endif
     let [repo, rev, files]=s:_r.cmdutils.getrrf(rrfopts,
     let status=repo.functions.status(repo)
     "▶2 Get file list
     let types=['modified', 'added', 'removed']
-    if a:0 && index(a:000, 'all')!=-1
+    if hasall
+        unlet files
         let files=[]
     elseif a:0
         if has_key(a:opts, 'type')

File autoload/aurum/drivers/common/utils.vim

     endif
     return cmd
 endfunction
-"▶1 utils.run :: sh, hasnulls::0|1|2 → [String] + shell
+"▶1 utils.run :: cmd, hasnulls::0|1|2, path → [String] + shell
 function s:utils.run(cmd, hasnulls, cdpath)
     if a:hasnulls==2 && !empty(&shellredir)
         return call(s:_r.os.readsystem, [a:cmd]+(empty(a:cdpath)?

File autoload/aurum/drivers/mercurial.vim

             \ 'norev' : 'No revision %s in repository %s',
             \ 'nofile': 'File %s is not present in revision %s '.
             \           'from repository %s',
-            \  'csuns': 'Unable to get changeset from repository %s: '.
-            \           'operation not supported',
             \'statuns': 'Unable to get working directory status '.
             \           'of repository %s: operation not supported',
             \ 'comuns': 'Unable to commit to repository %s: '.
                 \           '*vim.eval("a:args"), '.
                 \           '**vim.eval("a:kwargs"))'
 endfunction
+"▶2 trycmd :: repo, attr → Bool
+function s:F.trycmd(repo, cmd)
+    execute s:py 'vim.command("let r="+str(int(hasattr('.s:pp.',"'.a:cmd.'"))))'
+    return r
+endfunction
 "▲2
 else "▶1
 "▶2 addchangesets :: repo, [cs] → _ + repo
     endif
     let line+=1
     "▶3 Simple keys: rev, hex, branch, time, user
-    let cs.rev    = str2nr(a:csdata[line])    | let line+=1
-    let cs.hex    = a:csdata[line]            | let line+=1
-    let cs.phase  = a:csdata[line]            | let line+=1
-    let cs.branch = s:F.unesc(a:csdata[line]) | let line+=1
-    let cs.time   = str2nr(a:csdata[line])    | let line+=1
-    let cs.user   = s:F.unesc(a:csdata[line]) | let line+=1
+    let null=''
+    let cs.rev    = str2nr(a:csdata[line])       | let line+=1
+    let cs.hex    = a:csdata[line]               | let line+=1
+    let cs.phase  = a:csdata[line]               | let line+=1
+    let cs.branch = s:F.unesc(a:csdata[line])[0] | let line+=1
+    let cs.time   = str2nr(a:csdata[line])       | let line+=1
+    let cs.user   = s:F.unesc(a:csdata[line])    | let line+=1
     if empty(cs.phase)
         let cs.phase='unknown'
     endif
+    if empty(cs.branch)
+        let cs.branch='default'
+    endif
     "▶3 List keys: parents, tags, bookmarks, changes, removes
     for [char, key] in s:chars
         let cs[key]=[]
 function s:F.runcmd(repo, attr, args, kwargs, ...)
     return s:F.runshellcmd(a:repo, a:attr, a:args, a:kwargs)
 endfunction
+"▶2 trycmd :: repo, attr → Bool
+function s:F.trycmd(repo, cmd)
+    try
+        call s:F.hg(a:repo, 'help', [a:cmd], {}, 0)
+        return !v:shell_error
+    catch
+        return 0
+    endtry
+endfunction
 "▲2
 endif
+"▶1 trycmdcached :: repo, attr → Bool
+function s:F.trycmdcached(repo, cmd)
+    if !has_key(a:repo.mutable.commands, a:cmd)
+        let a:repo.mutable.commands[a:cmd]=s:F.trycmd(a:repo, a:cmd)
+    endif
+    return a:repo.mutable.commands[a:cmd]
+endfunction
 "▶1 getcs :: repo, rev → cs
 if s:usepythondriver "▶2
     function s:F.getcs(repo, rev)
         else
             let r.css=[]
         endif
-        for key in ['tags', 'bookmarks']
+        for key in a:repo.updkeys
             let list=s:F.getkeylist(a:repo, key)
             if cschange
                 call filter(list, 'v:val[1]<'.startrev)
         let revmap={}
         call map(copy(a:repo.changesets), 'extend(revmap, {v:val.rev : v:val})')
         let d={}
-        for key in ['tags', 'bookmarks']
+        for key in a:repo.updkeys
             try
                 let list=s:F.getkeylist(a:repo, key)
             catch
     if !empty(a:repo.mutable.cslist)
         call s:F.removechangesets(a:repo, d.startrev)
     endif
-    for key in ['tags', 'bookmarks']
+    for key in a:repo.updkeys
         call map(a:repo.mutable.cslist, 'extend(v:val, {key : []})')
         for [name, hex] in filter(items(d[key]),
                     \             'has_key(a:repo.changesets, v:val[1])')
 endfunction
 "▶1 hg.forget :: repo, file → + FS
 function s:hg.forget(repo, ...)
-    return s:F.runcmd(a:repo, 'forget', a:000, {})
+    " XXX “hg rm --after --force” works like forget, but this behavior is not 
+    "     documented in “hg help remove”. Using it in order to support older 
+    "     mercurial versions
+    return s:F.runcmd(a:repo, 'remove', a:000, {'after': 1, 'force': 1})
 endfunction
 "▶1 hg.remove :: repo, file → + FS
 function s:hg.remove(repo, ...)
     if a:ignore_case
         let kwargs['ignore-case']=1
     endif
-    let lines=s:F.hg(a:repo, 'grep', args, kwargs, 1)
+    let kwargs.print0=1
+    let lines=s:F.hg(a:repo, 'grep', args, kwargs, 2)
     if v:shell_error
         " Grep failed because it has found nothing
         if lines ==# ['']
     endif
     let r=[]
     let cnmscache={}
-    for line in lines
-        let match=matchlist(line, '\v^(.{-})\:(0|[1-9]\d*)\:([1-9]\d*)\:(.*)$')
-        if empty(match)
-            call s:_f.throw('grepfail', a:repo.path, line)
-        endif
-        let [file, rev, lnum, text]=match[1:4]
-        if a:wdfiles && s:F.checknotmodifiedsince(a:repo, rev, file, cnmscache)
+    let lines=s:_r.utils.nullnl(lines)
+    call remove(lines, -1)
+    while !empty(lines)
+        let [file, rev, lnum, text]=remove(lines, 0, 3)
+        if a:wdfiles && index(allfiles, file)!=-1 &&
+                    \s:F.checknotmodifiedsince(a:repo, rev, file, cnmscache)
             let filename=s:_r.os.path.normpath(s:_r.os.path.join(a:repo.path,
                         \                      file))
         else
         endif
         let r+=[{'filename': filename, 'lnum': lnum, 'text': text}]
         unlet filename
-    endfor
+    endwhile
     return r
 endfunction
 endif
 else "▶2
 function s:hg.annotate(repo, rev, file)
     let r=[]
+    " XXX Warning: --follow has the same effect as --file, but is not documented 
+    "              in most recent mercurial
     let lines=s:F.hg(a:repo, 'annotate', ['--', a:file],
-                \    {'rev': ''.a:rev, 'file':1, 'number':1, 'line-number':1},
+                \    {'rev': ''.a:rev, 'follow':1, 'number':1, 'line-number':1},
                 \    1, 'ann', a:rev, a:file)
     for line in lines
         " XXX This won't work for files that start with spaces and also with 
             let kwargs[tr(o, '_', '-')]=1
         endif
     endfor
+    if has_key(kwargs, 'reverse') &&
+                \(!has_key(a:repo.mutable, 'noreverse') ||
+                \ empty(filter(s:F.hg(a:repo, 'help', 'diff', [], {}, 0, 0),
+                \              'stridx(v:val, "--reverse")!=-1')))
+        let a:repo.mutable.noreverse=1
+        unlet kwargs.reverse
+    endif
     if !empty(a:files)
         let args+=['--']+a:files
     endif
         return s:F.hg(a:repo, 'branch', [], {}, 0, 'b')[0]
     elseif a:prop is# 'tagslist' || a:prop is# 'brancheslist' ||
                 \                   a:prop is# 'bookmarkslist'
+        if a:prop is# 'bookmarkslist' && !a:repo.hasbookmarks
+            return []
+        endif
         return map(copy(s:F.getkeylist(a:repo, a:prop[:-5])), 'v:val[0]')
     elseif a:prop is# 'url'
         let lines=s:F.hg(a:repo, 'showconfig', ['paths'], {}, 0, 'sc')[:-2]
     return repo
 endfunction
 else "▶2
-function s:F.trycmd(repo, cmd)
-    try
-        return !empty(s:F.hg(a:repo, 'help', [a:cmd], {}, 0))
-    catch
-        return 0
-    endtry
-endfunction
 function s:hg.repo(path)
-    let repo={'path': a:path, 'changesets': {}, 'mutable': {'cslist': []},
+    let repo={'path': a:path, 'changesets': {}, 'mutable': {'cslist': [],
+                \                                         'commands': {}},
                 \'local': (stridx(a:path, '://')==-1),
                 \'labeltypes': ['tag', 'bookmark'],
                 \'has_octopus_merges': 0, 'requires_sort': 0,
                 \              'copies', 'renames', 'files', 'description',
                 \              'phase']}
     let repo.hasphases=s:F.trycmd(repo, 'phase')
+    let repo.updkeys=['tags']
     if !s:F.trycmd(repo, 'bookmark')
         call filter(repo.labeltypes, 'v:val isnot# "bookmark"')
         let repo.hasbookmarks=0
     else
         let repo.hasbookmarks=1
+        let repo.updkeys+=['bookmarks']
     endif
     return repo
 endfunction

File autoload/aurum/drivers/subversion.vim

     let reverse=get(a:opts, 'reverse', 0)
     let kwargs={}
     let args=[]
-    for [k, v] in items(diffopts)
-        if v
-            let args+=['--extensions', '--'.k]
-        endif
+    for [k, v] in filter(items(diffopts), 'v:val[1]')
+        let args+=['--extensions', '--'.k]
     endfor
     "▶2 Get revision arguments
     if empty(a:rev2)

File doc/aurum.txt

        replaced with static string "HEAD".
 |aurum-rf-status|: For non-python driver this function does not support names 
     containing newlines.
-|aurum-rf-grep|: For non-python driver filenames that look like 
-    {smth}:{num>=0}:{num>0} are not supported and will lead to invalid 
-    results.
+|aurum-rf-diff| requires at least mercurial-1.4 to support reverse diff 
+    option.
+|aurum-rf-getcsprop|(…, "children") requires at least mercurial-1.7 or manual 
+    preceding |aurum-rf-getchangesets| call. Thus many Next mappings do not 
+    work.
 *aurum-rf-svnrev* exists and produces svn revision number out of repository 
     object and mercurial revision specification.
 *aurum-rf-githex* exists and produces git sha1 out of repository object and 

File misc/map-cmdline.csinfo

-changeset = ':\n{rev}\n{node}\n{phase}\n{branch|json}\n{date}\n{author|json}\n{parents}{tags}{bookmarks}{files}{file_dels}{file_copies}\t{desc|json}\n'
+changeset = ':\n{rev}\n{node}\n{phase}\n{branches|json}\n{date}\n{author|json}\n{parents}{tags}{bookmarks}{files}{file_dels}{file_copies}\t{desc|json}\n'
 parent    = 'P{node|json}\n'
 tag       = 'T{tag|json}\n'
 bookmark  = 'B{bookmark|json}\n'

File python/aurum/aumercurial.py

 from mercurial import hg, ui, commands, match
-from mercurial.repo import error
+try:
+    from mercurial.repo import error
+except ImportError:
+    from mercurial import error
 import vim
 import os
 import json
 import re
 import sys
 
+if hasattr(error, 'RepoLookupError'):
+    RepoLookupError=error.RepoLookupError
+else:
+    RepoLookupError=error.RepoError
+
 def outermethod(func):
     """
         Decorator used to make functions omit showing python traceback in case vim_throw was used.
 
 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:
+    except RepoLookupError:
         vim_throw('norev', rev, repo.path)
 
 def g_fctx(cs, filepath):
     vim_repo={'has_octopus_merges': 0,
                    'requires_sort': 0,
                       'changesets': {},
-                         'mutable': {'cslist': []},
+                         'mutable': {'cslist': [], 'commands': {}},
                            'local': 1 if repo.local() else 0,
-                      'labeltypes': ['tag', 'bookmark'],
+                      'labeltypes': ['tag',  'bookmark'],
+                         'updkeys': ['tags', 'bookmarks'],
+                    'hasbookmarks': 1,
                        'hasphases': int(hasattr(repo[None], 'phase')),
              }
     if hasattr(repo, '__len__'):
         vim_repo['csnum']=len(repo)+1
+    if not hasattr(commands, 'bookmarks'):
+        vim_repo['labeltypes'].pop()
+        vim_repo['updkeys'].pop()
+        vim_repo['hasbookmarks']=0
     vim_extend(var='repo', val=vim_repo)
 
 @outermethod

File test/addEmessages.vim

+redir => s:messages
+messages
+redir END
+let s:meslines=filter(split(s:messages, "\n")[1:], 'v:val=~#"\\v^E\\d+\\:"')
+if !empty(s:meslines)
+    call WriteFile(['>>> Error Messages:']+
+                \  s:meslines+
+                \  ['<<< Error Messages^'])
+endif

File test/cmd-other.pre

 #!/bin/zsh
+export HGRCPATH=''
 tar xJf hgtestbranchedrepo.tar.xz
 hg -q clone hgtestbranchedrepo cmd-other-A -r A -r B
 hg -q clone cmd-other-A        cmd-other-B

File test/drivers-git.in

 :let g:curtest='gittest'
 :let g:tipname='HEAD'
-:W{{{1 Annotate
-:Run! AuAnnotate file ./gittestrepo/* | wincmd w
-:bwipeout!
-:bwipeout!
 :W{{{1 Branch
 :AuBranch next3 repo ./gittestrepo/
 :WT
 Added second line to newfile.vim
 // It was not required really:write
 :WT! 1delete _
+:bwipeout!
+:W{{{1 File :
+:Run AuFile : *
+:bwipeout!
+:W{{{1 File HEAD
+:Run AuFile HEAD newfile.vim
+:bwipeout!
+:W{{{1 File HEAD^
+:Run AuFile HEAD^ newfile.vim
+:bwipeout!
+:W{{{1 Annotate newfile.vim
+:R AuAnnotate file newfile.vim | wincmd p | call WriteFile(map(getline(1, '$'), 'v:val[stridx(v:val, " "):]'))
+:bwipeout!
+:bwipeout!
+:W{{{1 Diff changes
+:Run AuDiff changes HEAD^^^^
+:bwipeout!
+:W{{{1 Diff rev2
+:Run AuDiff rev2 HEAD^^^^^
+:bwipeout!
+:W{{{1 Diff rev1+rev2
+:Run AuDiff rev1 HEAD^^^^^ rev2 HEAD^^^^
+:bwipeout!
 :W{{{1 Update
 :AuUpdate HEAD^ ./gittestrepo/
 :WT 1delete _
 :W{{{1 Update: force
+:R e newfile.vim
+:AuFile next replace
 :write!
-:AuUpdate! HEAD^^ ./gittestrepo/
+:AuUpdate! HEAD^^
 :WT
 :W{{{1 Update: branch
-:AuUpdate next ./gittestrepo/
+:AuUpdate next
 :WT 1delete _
-:edit!
+:bwipeout!
 :W{{{1 Move
 :AuMove ./gittestrepo/--force ./gittestrepo/-f
 :AuCommit message Moved\ --force\ to\ -f repo ./gittestrepo/ all
 :Run! AuGrep W ignorecase repo ./gittestrepo/ | cwindow
 :cclose
 :W{{{1 Grep: HEAD^^^^
-:let repo=aurum#repository()
+:R let g:repo=aurum#repository()
 :let cs=repo.functions.getcs(repo, 'HEAD^^^^')
-:AuGrep W revision HEAD^^^^ repo ./gittestrepo/ | cwindow
+:AuGrep W revision HEAD^^^^ repo ./gittestrepo | cwindow
 :call WriteFile(map(getline(1, '$'), 'substitute(v:val, "'.cs.hex.'", "HEAD^^^^", "g")'))
 :cclose
 :W{{{1 Junk: ignore, ignoreglob
 :AuOther! pull : gittestbranchedrepo gitteststatusrepo
 :Run! AuLog gitteststatusrepo
 :bwipeout
+:source addEmessages.vim

File test/drivers-git.ok

Binary file modified.

File test/drivers-subversion-subdir.in

 :W{{{1 Commit
 :edit ./svntest-subdirrepo/newfile.vim
 iW In file newfile.vim:write
-:Run! AuCommit message Added\ newfile.vim type unknown ./svntest-subdirrepo/newfile.vim
+:AuCommit message Added\ newfile.vim type unknown ./svntest-subdirrepo/newfile.vim
 :WT
 :W{{{1 Commit 2
 oW File newfile.vim, second line:write
 Added second line to newfile.vim
 // It was not required really:write
 :WT
+:W{{{1 File
+:AuUpdate
+:let cs=aurum#changeset()
+:execute 'Run! AuFile '.(cs.rev-1)
+:bwipeout!
 :W{{{1 Update
 :AuUpdate 6 ./svntest-subdirrepo/
 :WTF
 :W{{{2 Status after junk
 :Run! AuStatus ./svntest-subdirrepo/
 :bwipeout!
+:source addEmessages.vim

File test/drivers-subversion-subdir.ok

 {{{1 Status: between two revisions
 R file-2
 {{{1 Commit
-W In file newfile.vim
 o Changeset 10
 | @ Added newfile.vim
 {{{1 Commit 2
 o Changeset 11
 | @ Added second line to newfile.vim
 | @ // It was not required really
+{{{1 File
+W In file newfile.vim
 {{{1 Update
 Line 1
 First line

File test/drivers-subversion.in

 :W{{{1 Commit
 :edit ./svntestrepo/newfile.vim
 iW In file newfile.vim:write
-:Run! AuCommit message Added\ newfile.vim type unknown ./svntestrepo/newfile.vim
+:AuCommit message Added\ newfile.vim type unknown ./svntestrepo/newfile.vim
 :WT
 :W{{{1 Commit 2
 oW File newfile.vim, second line:write
 Added second line to newfile.vim
 // It was not required really:write
 :WT
+:W{{{1 File
+:AuUpdate
+:let cs=aurum#changeset()
+:execute 'Run! AuFile '.(cs.rev-1)
+:bwipeout!
 :W{{{1 Update
 :AuUpdate 3 ./svntestrepo/
 :WTF
 :W{{{2 Status after junk
 :Run! AuStatus ./svntestrepo/
 :bwipeout!
+:source addEmessages.vim

File test/drivers-subversion.ok

 R subdir2/stu
 R def
 {{{1 Commit
-W In file newfile.vim
 o Changeset 10
 | @ Added newfile.vim
 {{{1 Commit 2
 o Changeset 11
 | @ Added second line to newfile.vim
 | @ // It was not required really
+{{{1 File
+W In file newfile.vim
 {{{1 Update
 First line
 Second line

File test/util-add-cloned-repo.zsh

 #!/bin/zsh
+export HGRCPATH=''
 hg -q clone hgtestrepo ${CURTEST}repo

File test/wine/cmd-vimdiff-full.ok

+{{{1 full
+ 1*1: 
+*2*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:nohglinesrev.lst
+*2 2: %TMPDIR%\test\cmd-vimdiff-fullrepo\nohglinesrev.lst
+{{{1 ,X
+*1*1: 
+{{{1 noonlymodified
+ 1*1: 
+ 2*1: 
+ 2#2: %TMPDIR%\test\cmd-vimdiff-fullrepo\addeddef
+ 3*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:hglines2.lst
+ 3 2: 
+*4*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:nohglinesrev.lst
+*4 2: %TMPDIR%\test\cmd-vimdiff-fullrepo\nohglinesrev.lst
+{{{1 untracked
+ 1*1: 
+ 2*1: 
+ 2#2: %TMPDIR%\test\cmd-vimdiff-fullrepo\addeddef
+ 3*1: 
+ 3#2: %TMPDIR%\test\cmd-vimdiff-fullrepo\hglinesrev.lst
+ 4*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:hglines2.lst
+ 4 2: 
+ 5*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:nohglinesrev.lst
+ 5 2: %TMPDIR%\test\cmd-vimdiff-fullrepo\nohglinesrev.lst
+*6*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:nohglines.lst
+*6 2: 
+{{{1 noonlymodified files *.lst
+ 1*1: 
+ 2*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:nohglinesrev.lst
+ 2 2: %TMPDIR%\test\cmd-vimdiff-fullrepo\nohglinesrev.lst
+*3*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:hglines2.lst
+*3 2: 
+{{{1 files :
+ 1*1: %TMPDIR%\test\cmd-vimdiff-fullrepo\nohglinesrev.lst
+*2*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:nohglinesrev.lst
+*2 2: %TMPDIR%\test\cmd-vimdiff-fullrepo\nohglinesrev.lst
+{{{1 files repo/*.lst
+ 1*1: 
+*2*1: aurum:\\file:%ETMPDIR%%+test%+cmd-vimdiff-fullrepo:504f74154456dbb0e9441326514e42ce66279e62:nohglinesrev.lst
+*2 2: %TMPDIR%\test\cmd-vimdiff-fullrepo\nohglinesrev.lst