Commits

ZyX_I committed 76edf59

@aurum/drivers/subversion: Moved code generating status from diff to a separate function
Added support for rf-setcsprop(changes/files/removes) (completely untested)

  • Participants
  • Parent commits ef26b22
  • Branches svnsupport

Comments (0)

Files changed (1)

File plugin/aurum/drivers/subversion.vim

                     \                         'revision': a:cs.hex}, 0,
                     \ 'listf', a:cs.hex)
     elseif a:prop is# 'children'
+        " TODO
     elseif  a:prop is# 'changes' || a:prop is# 'files' || a:prop is# 'removes'
+        let diff=a:repo.functions.diff(a:repo, a:cs.hex, 0, [], {})
+        if empty(a:cs.parents)
+            let ofs=[]
+        else
+            let ofs=a:repo.functions.getcsprop(a:repo, a:cs.parents[0],
+                        \                     'allfiles')
+        endif
+        let fs=a:repo.functions.getcsprop(a:repo, a:cs, 'allfiles')
+        let status=s:F.statfromdiff(a:repo, diff, ofs, fs, [])[0]
+        let a:cs.files=status.modified+status.added
+        let a:cs.removes=status.removed
+        let a:cs.changes=a:cs.files+a:cs.removes
+        return a:cs[a:prop]
     endif
     let a:cs[a:prop]=r
     return r
     endfor
     return r
 endfunction
-"▶1 status :: repo, files → Either (status, files) revstatus
+"▶1 status :: repo, files → (status, revstatus)
 let s:initstatdct={
             \'modified': [],
             \   'added': [],
 function s:F.status(repo, files)
     let r=deepcopy(s:initstatdct)
     let slines=s:F.svn(a:repo, 'status', ['--']+a:files, {}, 0, 'statf')
-    let files={}
+    let revstatus={}
     for line in slines
         let status=line[:6]
         let file=line[8:]
             if has_key(colschars, status[col])
                 let state=colschars[status[col]]
                 let r[state]+=[file]
-                let files[file]=state
+                let revstatus[file]=state
                 break
             endif
             let col+=1
         endfor
     endfor
-    return [r, files]
+    return [r, revstatus]
+endfunction
+"▶1 statfromdiff :: repo, diff, ofs, fs, files → (status, revstatus)
+" ofs :: [file]
+"  fs :: Either status [file]
+function s:F.statfromdiff(repo, diff, ofs, fs, files)
+    "▶2 Initialize variables
+    let diff=copy(a:diff)
+    let r=deepcopy(s:initstatdct)
+    let diffre=a:repo.functions.diffre(a:repo, {})
+    let revstatus={}
+    let file=0
+    let hasfiles=!empty(a:files)
+    let usesstatus=(type(a:fs)==type({}))
+    "▶2 Main cycle: get statuses
+    while !empty(diff)
+        let filematch=matchlist(remove(diff, 0), diffre)[1:1]
+        if empty(filematch)
+            if file is 0
+                continue
+            endif
+            "▶3 Find === separator line
+            while !empty(diff) && diff[0]!~#'[^=]'
+                call remove(diff, 0)
+            endwhile
+            if empty(diff)
+                break
+            endif
+            call remove(diff, 0)
+            if empty(diff)
+                call s:_f.throw('iediff')
+            endif
+            "▶3 Get file status
+            let binary=0
+            if diff[0][:2] isnot# '---'
+                " Binary file
+                let state='modified'
+                let binary=1
+            elseif diff[0][-12:] is# '(revision 0)'
+                let state='added'
+            else
+                let state='modified'
+            endif
+            "▶3 If file was modified check: we can’t trust this information
+            if state is# 'modified'
+                if usesstatus
+                    if index(a:ofs, file)==-1
+                        let state='added'
+                    elseif has_key(a:fs, file)
+                        let state=a:fs[file]
+                    endif
+                else
+                    " File additions are normally caught by ---.*(revision 0)?
+                    " if index(a:ofs, file)==-1
+                        " let state='added'
+                    if index(a:fs, file)==-1
+                        let state='removed'
+                    endif
+                endif
+            endif
+            "▶3 Reset values
+            let r[state]+=[file]
+            let revstatus[file]=state
+            let file=0
+            "▶3 Skip unneeded lines
+            if !binary
+                call remove(diff, 0, 1)
+                while !empty(diff) && stridx('@-+ ', diff[0][0])!=-1
+                    call remove(diff, 0)
+                endwhile
+            endif
+            "▲3
+        elseif hasfiles && index(a:files, filematch[0])==-1
+            continue
+        else
+            let file=filematch[0]
+        endif
+    endwhile
+    "▲2
+    return [r, revstatus]
 endfunction
 "▶1 svn.status :: repo[, rev1[, rev2[, files]]]
 function s:svn.status(repo, ...)
     "▶2 Simple case: we can use “svn status”
     if !a:0 || (a:1 is 0 && !(a:0>1 && a:2 isnot 0))
-        let [r, files]=s:F.status(a:repo, get(a:000, 2, []))
+        let [r, revstatus]=s:F.status(a:repo, get(a:000, 2, []))
         let allfiles=a:repo.functions.getcsprop(a:repo, 'HEAD', 'allfiles')
         if a:0>2 && !empty(a:3)
             let allfiles=filter(copy(allfiles), 'index(a:3, v:val)!=-1')
         endif
-        let r.clean=filter(copy(allfiles), '!has_key(files, v:val)')
     "▶2 Complicated case: we must use diff
     else
         "▶3 Get diff
             let dargs+=[[]]
         endif
         let dargs+=[{}]
-        let diff=copy(call(a:repo.functions.diff, dargs, {}))
-        "▶3 Initialize other variables
-        let r=deepcopy(s:initstatdct)
-        let diffre=a:repo.functions.diffre(a:repo, {})
-        let files={}
-        let file=0
+        let diff=call(a:repo.functions.diff, dargs, {})
+        "▶3 Getting status
         let usescur=(len(rspec)==1)
         let rsallfiless=map(copy(rspec),
                     \       'a:repo.functions.getcsprop(a:repo, v:val, '.
                     \                                  '"allfiles")')
-        if usescur
-            let revstatus=s:F.status(a:repo, get(a:000, 2, []))[1]
-            call filter(revstatus, 'v:val is# "deleted" || v:val is# "removed"')
-        endif
         if a:0>2 && !empty(a:3)
             call map(rsallfiless, 'filter(v:val, "index(a:3, v:val)!=-1")')
         endif
-        "▶3 Main cycle: get statuses
-        while !empty(diff)
-            let filematch=matchlist(remove(diff, 0), diffre)[1:1]
-            if empty(filematch)
-                if file is 0
-                    continue
-                endif
-                "▶4 Find === separator line
-                while !empty(diff) && diff[0]!~#'[^=]'
-                    call remove(diff, 0)
-                endwhile
-                if empty(diff)
-                    break
-                endif
-                call remove(diff, 0)
-                if empty(diff)
-                    call s:_f.throw('iediff')
-                endif
-                "▶4 Get file status
-                let binary=0
-                if diff[0][:2] isnot# '---'
-                    " Binary file
-                    let state='modified'
-                    let binary=1
-                elseif diff[0][-12:] is# '(revision 0)'
-                    let state='added'
-                else
-                    let state='modified'
-                endif
-                "▶4 If file was modified check: we can’t trust this information
-                if state is# 'modified'
-                    if usescur
-                        if index(rsallfiless[0], file)==-1
-                            let state='added'
-                        elseif has_key(revstatus, file)
-                            let state=revstatus[file]
-                        endif
-                    else
-                        if index(rsallfiless[0], file)==-1
-                            let state='added'
-                        elseif index(rsallfiless[1], file)==-1
-                            let state='removed'
-                        endif
-                    endif
-                endif
-                "▶4 Reset values
-                let r[state]+=[file]
-                let files[file]=1
-                let file=0
-                "▶4 Skip unneeded lines
-                if !binary
-                    call remove(diff, 0, 1)
-                    while !empty(diff) && stridx('@-+ ', diff[0][0])!=-1
-                        call remove(diff, 0)
-                    endwhile
-                endif
-                "▲4
-            else
-                let file=filematch[0]
-            endif
-        endwhile
+        if usescur
+            let fs=s:F.status(a:repo, get(a:000, 2, []))[1]
+            call filter(fs, 'v:val is# "deleted" || v:val is# "removed"')
+            let ofs=rsallfiless[0]
+        else
+            let [ofs, fs]=rsallfiless
+        endif
+        "▲3
+        let [r, revstatus]=s:F.statfromdiff(a:repo, diff, ofs, fs,
+                    \                       get(a:000, 2, []))
+        "▶3 Reversing range
         if reverse
             let [r.deleted, r.unknown]=[r.unknown, r.deleted]
             let [r.added,   r.removed]=[r.removed, r.added  ]
         endif
-        let allfiles=a:repo.functions.getcsprop(a:repo, get(rspec, 0, 'HEAD'),
-                    \                           'allfiles')
-        let r.clean=filter(copy(allfiles), '!has_key(files, v:val)')
+        "▲3
+        let allfiles=rsallfiless[0]
     endif
+    let r.clean=filter(copy(allfiles), '!has_key(revstatus, v:val)')
     return r
 endfunction
 "▶1 svn.annotate :: repo, rev, file → [(file, hex, linenumber)]