Commits

ZyX_I  committed db25aec

@aurum/repo: Added default rf-copy() implementation (untested)
Moved rf-diffre() from @aurum/drivers/mercurial to @aurum/repo

  • Participants
  • Parent commits c12b80d

Comments (0)

Files changed (3)

File doc/aurum.txt

     headers (normally lines starting with ^diff) and obtaining file names from 
     them. Is used by a number of command for obtaining current file name while 
     in diff buffer and also by |aurum-rf-getstats| function.
+    This function must return regex that captures filename into the first 
+    capturing group.
   getstats :: diff, diffopts -> stats                      *aurum-rf-getstats*
     Returns a dictionary describing summary of changes described in {diff} (it 
     is what |aurum-rf-diff| returns). Dictionary will contain the following 
                          calls |aurum-rf-setcsprop|.
   |aurum-rf-reltorepo|     Uses |aurum-repo.path| to get requested path.
   |aurum-rf-difftobuffer|  Wrapper around |aurum-rf-diff|.
+  |aurum-rf-getstats|      Parses git-like unified diff, depends on 
+                         |aurum-rf-diffre|. For this function to work, first 
+                         eight characters of the expression returned by 
+                         |aurum-rf-diffre| must be equal to "\m^diff ".
+  |aurum-rf-copy|          Copies file to destination (using command-line “cp” 
+                         (cp -- source target), “copy” (copy source target) or 
+                         |readfile()| + |writefile()| (in last case 
+                         permissions are not copied)), then uses 
+                         |aurum-rf-add| to make destination tracked.
   |aurum-rf-move|          Uses |aurum-rf-copy| and |aurum-rf-remove| to 
                          emulate renaming command.
   |aurum-rf-remove|        Uses |aurum-rf-forget| to untrack file and then 

File plugin/aurum/drivers/mercurial.vim

     endtry
 endfunction
 endif
-"▶1 hg.diffre :: _, diffopts → regex
+"▶1 diffre :: _, diffopts → regex
 function s:hg.diffre(repo, diffopts)
     " XXX first characters must be identical for hg.getstats(), but it must not 
     " match lines not containing filename for getdifffile()
         return '\m^diff \v.*\-r\ \w+\s(.*)$'
     endif
 endfunction
-"▶1 hg.getstats :: _, diff, diffopts → stats
-" stats :: { ( "insertions" | "deletions" ): UInt,
-"            "files": { ( "insertions" | "deletions" ): UInt } }
-function s:hg.getstats(repo, diff, diffopts)
-    let diffre=a:repo.functions.diffre(a:repo, a:diffopts)
-    let i=0
-    let llines=len(a:diff)
-    let stats={'files': {}, 'insertions': 0, 'deletions': 0}
-    let file=0
-    while i<llines
-        let line=a:diff[i]
-        if line[:3] is# 'diff'
-            let file=get(matchlist(line, diffre[8:], 5), 1, 0)
-            if file isnot 0
-                let stats.files[file]={'insertions': 0, 'deletions': 0,}
-                let i+=1
-                let oldi=i
-                let pmlines=2
-                while pmlines && i<llines
-                    let lstart=a:diff[i][:2]
-                    if lstart is# '+++' || lstart is# '---'
-                        let pmlines-=1
-                    endif
-                    let i+=1
-                    if i-oldi>=4
-                        let i=oldi
-                        break
-                    endif
-                endwhile
-                continue
-            endif
-        elseif file is 0
-        elseif line[0] is# '+'
-            let stats.insertions+=1
-            let stats.files[file].insertions+=1
-        elseif line[0] is# '-'
-            let stats.deletions+=1
-            let stats.files[file].deletions+=1
-        endif
-        let i+=1
-    endwhile
-    return stats
-endfunction
 "▶1 hg.getrepoprop :: repo, prop → a
 if s:usepythondriver "▶2
 function s:hg.getrepoprop(repo, prop)

File plugin/aurum/repo.vim

             \               '" ?".v:val." range 0 inf" : '.
             \               '"!?".v:val'))
 let s:_messages={
-            \  'nrm': 'Failed to remove file %s from repository %s',
-            \'iname': 'Error while registering driver for plugin %s: '.
-            \         'invalid name: it must be a non-empty sting, '.
-            \         'containing only latin letters, digits and underscores',
-            \ 'nimp': 'Function %s was not implemented in driver %s',
+            \    'nrm': 'Failed to remove file %s from repository %s',
+            \  'iname': 'Error while registering driver for plugin %s: '.
+            \           'invalid name: it must be a non-empty sting, '.
+            \           'containing only latin letters, digits and underscores',
+            \   'nimp': 'Function %s was not implemented in driver %s',
+            \  'tgtex': 'Target already exists: %s',
+            \ 'cpfail': 'Failed to copy %s to %s: %s',
+            \ 'wrfail': 'Failed to write copy of %s to %s',
         \}
 call extend(s:_messages, map({
-            \ 'dreg': 'driver was already registered by plugin %s',
-            \'fndct': 'second argument is not a dictionary',
-            \ 'fmis': 'some required functions are missing',
-            \ 'nfun': 'some of dictionary values are not '.
-            \         'callable function references',
+            \   'dreg': 'driver was already registered by plugin %s',
+            \  'fndct': 'second argument is not a dictionary',
+            \   'fmis': 'some required functions are missing',
+            \   'nfun': 'some of dictionary values are not '.
+            \           'callable function references',
         \}, '"Error while registering driver %s for plugin %s: ".v:val'))
 let s:deffuncs={}
 "▶1 setlines :: [String], read::Bool → + buffer
         execute 'buffer' oldbuf
     endif
 endfunction
+"▶1 getstats :: _, diff, diffopts → stats
+" stats :: { ( "insertions" | "deletions" ): UInt,
+"            "files": { ( "insertions" | "deletions" ): UInt } }
+function s:deffuncs.getstats(repo, diff, diffopts)
+    let diffre=a:repo.functions.diffre(a:repo, a:diffopts)
+    let i=0
+    let llines=len(a:diff)
+    let stats={'files': {}, 'insertions': 0, 'deletions': 0}
+    let file=0
+    while i<llines
+        let line=a:diff[i]
+        if line[:3] is# 'diff'
+            let file=get(matchlist(line, diffre[8:], 5), 1, 0)
+            if file isnot 0
+                let stats.files[file]={'insertions': 0, 'deletions': 0,}
+                let i+=1
+                let oldi=i
+                let pmlines=2
+                while pmlines && i<llines
+                    let lstart=a:diff[i][:2]
+                    if lstart is# '+++' || lstart is# '---'
+                        let pmlines-=1
+                    endif
+                    let i+=1
+                    if i-oldi>=4
+                        let i=oldi
+                        break
+                    endif
+                endwhile
+                continue
+            endif
+        elseif file is 0
+        elseif line[0] is# '+'
+            let stats.insertions+=1
+            let stats.files[file].insertions+=1
+        elseif line[0] is# '-'
+            let stats.deletions+=1
+            let stats.files[file].deletions+=1
+        endif
+        let i+=1
+    endwhile
+    return stats
+endfunction
+"▶1 copy
+function s:deffuncs.copy(repo, force, source, target)
+    let src=s:_r.os.path.normpath(s:_r.os.path.join(a:repo.path, a:source))
+    let tgt=s:_r.os.path.normpath(s:_r.os.path.join(a:repo.path, a:target))
+    if filereadable(tgt)
+        if a:force
+            call delete(tgt)
+        else
+            call s:_f.throw('tgtex', tgt)
+        endif
+    endif
+    let cmd=0
+    if executable('cp')
+        let cmd='cp --'
+    elseif executable('copy')
+        let cmd='copy'
+    endif
+    if cmd is 0
+        try
+            if writefile(readfile(src, 'b'), tgt, 'b')!=0
+                call s:_f.throw('wrfail', src, tgt)
+            endif
+        endtry
+    else
+        let hasnls=(stridx(src.tgt, "\n")==-1)
+        let cmd.=' '.shellescape(src, hasnls).' '.shellescape(tgt, hasnls)
+        if hasnls
+            let shout=system(cmd)
+        else
+            noautocmd tabnew
+            noautocmd setlocal buftype=nofile
+            noautocmd execute 'silent! %!'.cmd
+            let shout=join(getline(1, '$'), "\n")
+            noautocmd tabclose
+        endif
+        if v:shell_error
+            call s:_f.throw('cpfail', src, tgt, shout)
+        endif
+    endif
+    call a:repo.functions.add(a:repo, tgt)
+endfunction
 "▶1 move
 function s:deffuncs.move(repo, force, source, target)
     call a:repo.functions.copy(a:repo, a:force, a:source, a:target)
 "▶1 regdriver feature
 let s:requiredfuncs=['repo', 'getcs', 'checkdir']
 let s:optfuncs=['readfile', 'annotate', 'diff', 'status', 'commit', 'update',
-            \   'dirty', 'diffre', 'getstats', 'getrepoprop', 'copy', 'forget',
-            \   'branch', 'label']
+            \   'dirty', 'diffre', 'getrepoprop', 'forget', 'branch', 'label']
 "▶2 regdriver :: {f}, name, funcs → + s:drivers
 function s:F.regdriver(plugdict, fdict, name, funcs)
     "▶3 Check arguments