Commits

ZyX_I committed f69e05a

@aurum/log, @aurum/repo: Moved csiterfuncs from @aurum/log to @aurum/repo, added repo.iterfuncs key

Comments (0)

Files changed (3)

     List of label types supported by |aurum-rf-label|. First type will be 
     default used by |:AuName|.
 requires_sort :: Bool                               *aurum-repo.requires_sort*
-    Determines whether it is necessary to run sort_in_topological_order function 
-    on commit lists returned by |aurum-rf-revrange| and |aurum-rf-getchangesets| 
-    when it is about to be displayed in |aurum://log| buffer. If it is false, 
-    then this list will only be reversed (|reverse()|).
-    See |aurum-rf-getchangesets| for the description of what “topological order” 
-    is.
+    Determines whether it is necessary to run sort_in_topological_order 
+    function on commit lists returned by |aurum-rf-revrange| and 
+    |aurum-rf-getchangesets| when it is about to be displayed in |aurum://log| 
+    buffer. If it is false, then this list will only be reversed 
+    (|reverse()|).
+    See |aurum-rf-getchangesets| for the description of what “topological 
+    order” is.
     This key is optional, default value: true.
 has_octopus_merges :: Bool                     *aurum-repo.has_octopus_merges*
     Determines whether repository has merges containing more then two parents. 
     If it is true, then it also assumes that changesets sorted by revision 
     numbers are sorted in topological order (see |aurum-rf-getchangesets|).
     This key is optional, default value: true.
+                                                        *aurum-repo.iterfuncs*
+iterfuncs :: {String : {"start": startfunc, "next": nextfunc}}
+        startfunc :: repo, opts -> d
+         nextfunc :: d -> cs
+    Dictionary containing keys "ancestors", "revrange" and "changesets" (all 
+    are optional). Each key’s value should in turn contain dictionary 
+    containing two keys: "start" and "next", both corresponding values have to 
+    be function references:
+    1. "start" function must accept |aurum-repo| dictionary and |:AuLog| 
+       options dictionary and return something that will be saved (for 
+       example, |Dictionary| containing a counter).
+       Note due to |E704| error returned value must not be a function 
+            reference.
+       Note 2: try to omit processsing options dictionary more then it is 
+               required to do the job (see below). It will be done in any case 
+               by log generator function.
+    2. "next" function must accept value returned by "start" function and 
+       return |aurum-cs| object. Returned objects must be sorted in 
+       topological order like described under |aurum-rf-getchangesets|.
+
+    Value of "changesets" key will be used to view full repository history.
+    Value of "revrange" key will be used to view history between specified 
+    revisions (they will be contained in opts.revrange).
+    Value of "ancestors" key will be used to view specific changesets 
+    ancestors (it will be contained in opts.revision).
+
+    This key is optional, see |aurum-new-driver|. If some of keys inside 
+    iterfuncs dictionary are missing they will also be added.
 functions :: {String : FRef}                            *aurum-repo.functions*
     Dictionary that contains all driver-specific functions. All functions 
     except |aurum-rf-repo|, |aurum-rf-checkdir| and |aurum-rf-checkremote| 
   |aurum-rf-remove|        Uses |aurum-rf-forget| to untrack file and then 
                          |delete()|s it.
   |aurum-rf-checkremote|   Returns 0.
+  |aurum-repo.iterfuncs|   "changeset": Uses |aurum-rf-getchangesets|
+                         "revrange": Uses |aurum-rf-revrange|
+                         "ancestors": Iterates recursively over 
+                                      |aurum-cs.parents|, parents of the 
+                                      parents and so on.
 Other functions, mentioned in |aurum-repo.functions|, but not mentioned here, 
 throw an "nimp" exception.
 
     1.3: Added default implementation of |aurum-rf-revrange|.
     2.0: Purged support of numeric ranges out of |aurum-rf-revrange|, returned 
          value of |aurum-rf-getchangesets| is not stated as ignored.
+    2.1: Added |aurum-repo.iterfuncs| support.
 @aurum:
     0.1: Added :AuBranch and :AuName
 @aurum/edit:

plugin/aurum/log.vim

             \'argmis': 'Missing argument #%u for keyword %s',
             \  'ebuf': 'Switched to another buffer: exiting',
         \}
-" iterfunc :: {fname: { "start": startfunc, "next": nextfunc }}
+" iterfuncs :: {fname: { "start": startfunc, "next": nextfunc }}
 " startfunc (always) :: repo, opts, * → d
 let s:iterfuncs={}
 "▶1 graph
     endif
     return r
 endfunction
-"▶1 sort_in_topological_order :: [cs] → [cs]
-" TODO put sorting requirement on getchangesets and revrange functions.
-function s:F.sort_in_topological_order(repo, css)
-    try
-        call map(copy(a:css), 'extend(v:val, {"indegree": 1})')
-        for parents in map(copy(a:css), 'v:val.parents')
-            for parent in filter(map(filter(copy(parents),
-                        \                   'has_key(a:repo.changesets,v:val)'),
-                        \            'a:repo.changesets[v:val]'),
-                        \        'get(v:val, "indegree", 0)')
-                let parent.indegree+=1
-            endfor
-        endfor
-        let work=[]
-        call map(copy(a:css), 'v:val.indegree==1 && add(work, v:val) is 0')
-        call sort(work, 's:DateCmp')
-        let r=[]
-        while !empty(work)
-            let cs=remove(work, 0)
-            for parent in filter(map(filter(copy(cs.parents),
-                        \                   'has_key(a:repo.changesets,v:val)'),
-                        \            'a:repo.changesets[v:val]'),
-                        \        'get(v:val, "indegree", 0)')
-                let parent.indegree-=1
-                if parent.indegree==1
-                    let j=0
-                    let lwork=len(work)
-                    while j<lwork && work[j].time<parent.time
-                        let j+=1
-                    endwhile
-                    call insert(work, parent, j)
-                endif
-            endfor
-            let cs.indegree=0
-            call add(r, cs)
-        endwhile
-    finally
-        call map(copy(a:css), 'remove(v:val, "indegree")')
-    endtry
-    return r
-endfunction
-"▶1 iterfuncs: cs generators
-" startfunc (here)  :: repo, opts → d
-"▶2 ancestors
-let s:iterfuncs.ancestors={}
-function s:iterfuncs.ancestors.start(repo, opts)
-    let cs=a:repo.functions.getcs(a:repo,
-                \a:repo.functions.getrevhex(a:repo, a:opts.revision))
-    return {'addrevs': [cs], 'revisions': {}, 'repo': a:repo,
-                \'hasrevisions': get(a:repo, 'hasrevisions', 1)}
-endfunction
-function! s:RevCmp(cs1, cs2)
-    let rev1=a:cs1.rev
-    let rev2=a:cs2.rev
-    return ((rev1==rev2)?(0):((rev1<rev2)?(1):(-1)))
-endfunction
-let s:_functions+=['s:RevCmp']
-function s:iterfuncs.ancestors.next(d)
-    if empty(a:d.addrevs)
-        return 0
-    endif
-    let cs=remove(a:d.addrevs, 0)
-    if has_key(a:d.revisions, cs.hex)
-        return s:iterfuncs.ancestors.next(a:d)
-    endif
-    let a:d.revisions[cs.hex]=cs
-    let parents=map(copy(cs.parents),'a:d.repo.functions.getcs(a:d.repo,v:val)')
-    call extend(a:d.addrevs, parents)
-    if a:d.hasrevisions
-        call sort(a:d.addrevs, 's:RevCmp')
-    endif
-    return cs
-endfunction
-"▶2 revrange
-let s:iterfuncs.revrange={}
-function s:iterfuncs.revrange.start(repo, opts)
-    if has_key(a:opts, 'revrange')
-        call map(a:opts.revrange, 'a:repo.functions.getrevhex(a:repo, v:val)')
-        let cslist=copy(call(a:repo.functions.revrange,
-                    \   [a:repo]+a:opts.revrange, {}))
-    else
-        let cslist=copy(a:repo.functions.getchangesets(a:repo))
-    endif
-    if get(a:repo, 'requires_sort', 1)
-        let cslist=s:F.sort_in_topological_order(a:repo, cslist)
-    else
-        call reverse(cslist)
-    endif
-    return {'cslist': cslist}
-endfunction
-function s:iterfuncs.revrange.next(d)
-    if empty(a:d.cslist)
-        return 0
-    endif
-    return remove(a:d.cslist, 0)
-endfunction
-"▶2 changesets
-let s:iterfuncs.changesets=s:iterfuncs.revrange
 "▶1 iterfuncs.check
 " startfunc (here)  :: repo, opts → d
 let s:fcheckpropslist=['renames', 'copies', 'changes', 'files']
     call map(copy(ignorefiles), 'extend(opts.ignorefiles, {v:val : 1})')
     unlet ignorefiles
     "▶2 Get cslist
-    let iterfuncs=s:iterfuncs[((has_key(opts, 'revision'))?
-                \                ('ancestors'):
-                \             ((has_key(opts, 'revrange'))?
-                \                ('revrange')
-                \             :
-                \                ('changesets')))]
+    let csiterfuncsname=((has_key(opts, 'revision'))?
+                \          ('ancestors'):
+                \       ((has_key(opts, 'revrange'))?
+                \          ('revrange')
+                \       :
+                \          ('changesets')))
+    let csiterfuncs=a:repo.iterfuncs[csiterfuncsname]
     "▶2 Get template
     if has_key(opts, 'template')
         let template=eval(opts.template)
         augroup END
     endif
     let bvar.cw=s:_f.getoption('closewindow')
-    let text=s:F.glog.graphlog(a:repo, opts, iterfuncs, bvar, a:read)
+    let text=s:F.glog.graphlog(a:repo, opts, csiterfuncs, bvar, a:read)
     if a:read
         call s:_r.setlines(text, a:read)
     else

plugin/aurum/repo.vim

 "▶1
 scriptencoding utf-8
 if !exists('s:_pluginloaded')
-    execute frawor#Setup('2.0', {'@/resources': '0.0',
+    execute frawor#Setup('2.1', {'@/resources': '0.0',
                 \                       '@/os': '0.0',
                 \                  '@/options': '0.0',
                 \             '@aurum/bufvars': '0.0',}, 0)
             \           'callable function references',
         \}, '"Error while registering driver %s for plugin %s: ".v:val'))
 let s:deffuncs={}
+let s:iterfuncs={}
+"▶1 sort_in_topological_order :: [cs] → [cs]
+" TODO put sorting requirement on getchangesets and revrange functions.
+function s:F.sort_in_topological_order(repo, css)
+    try
+        call map(copy(a:css), 'extend(v:val, {"indegree": 1})')
+        for parents in map(copy(a:css), 'v:val.parents')
+            for parent in filter(map(filter(copy(parents),
+                        \                   'has_key(a:repo.changesets,v:val)'),
+                        \            'a:repo.changesets[v:val]'),
+                        \        'get(v:val, "indegree", 0)')
+                let parent.indegree+=1
+            endfor
+        endfor
+        let work=[]
+        call map(copy(a:css), 'v:val.indegree==1 && add(work, v:val) is 0')
+        call sort(work, 's:DateCmp')
+        let r=[]
+        while !empty(work)
+            let cs=remove(work, 0)
+            for parent in filter(map(filter(copy(cs.parents),
+                        \                   'has_key(a:repo.changesets,v:val)'),
+                        \            'a:repo.changesets[v:val]'),
+                        \        'get(v:val, "indegree", 0)')
+                let parent.indegree-=1
+                if parent.indegree==1
+                    let j=0
+                    let lwork=len(work)
+                    while j<lwork && work[j].time<parent.time
+                        let j+=1
+                    endwhile
+                    call insert(work, parent, j)
+                endif
+            endfor
+            let cs.indegree=0
+            call add(r, cs)
+        endwhile
+    finally
+        call map(copy(a:css), 'remove(v:val, "indegree")')
+    endtry
+    return r
+endfunction
+"▶1 iterfuncs: cs generators
+" startfunc (here)  :: repo, opts → d
+"▶2 ancestors
+let s:iterfuncs.ancestors={}
+function s:iterfuncs.ancestors.start(repo, opts)
+    let cs=a:repo.functions.getcs(a:repo,
+                \a:repo.functions.getrevhex(a:repo, a:opts.revision))
+    return {'addrevs': [cs], 'revisions': {}, 'repo': a:repo,
+                \'hasrevisions': get(a:repo, 'hasrevisions', 1)}
+endfunction
+function! s:RevCmp(cs1, cs2)
+    let rev1=a:cs1.rev
+    let rev2=a:cs2.rev
+    return ((rev1==rev2)?(0):((rev1<rev2)?(1):(-1)))
+endfunction
+let s:_functions+=['s:RevCmp']
+function s:iterfuncs.ancestors.next(d)
+    if empty(a:d.addrevs)
+        return 0
+    endif
+    let cs=remove(a:d.addrevs, 0)
+    if has_key(a:d.revisions, cs.hex)
+        return s:iterfuncs.ancestors.next(a:d)
+    endif
+    let a:d.revisions[cs.hex]=cs
+    let parents=map(copy(cs.parents),'a:d.repo.functions.getcs(a:d.repo,v:val)')
+    call extend(a:d.addrevs, parents)
+    if a:d.hasrevisions
+        call sort(a:d.addrevs, 's:RevCmp')
+    endif
+    return cs
+endfunction
+"▶2 revrange
+let s:iterfuncs.revrange={}
+function s:iterfuncs.revrange.start(repo, opts)
+    if has_key(a:opts, 'revrange')
+        call map(a:opts.revrange, 'a:repo.functions.getrevhex(a:repo, v:val)')
+        let cslist=copy(call(a:repo.functions.revrange,
+                    \   [a:repo]+a:opts.revrange, {}))
+    else
+        let cslist=copy(a:repo.functions.getchangesets(a:repo))
+    endif
+    if get(a:repo, 'requires_sort', 1)
+        let cslist=s:F.sort_in_topological_order(a:repo, cslist)
+    else
+        call reverse(cslist)
+    endif
+    return {'cslist': cslist}
+endfunction
+function s:iterfuncs.revrange.next(d)
+    if empty(a:d.cslist)
+        return 0
+    endif
+    return remove(a:d.cslist, 0)
+endfunction
+"▶2 changesets
+let s:iterfuncs.changesets=s:iterfuncs.revrange
 "▶1 setlines :: [String], read::Bool → + buffer
 function s:F.setlines(lines, read)
     let d={'set': function((a:read)?('append'):('setline'))}
     let repo.path=path
     let repo.functions=copy(driver.functions)
     let repo.diffopts=copy(s:_f.getoption('diffopts'))
+    if !has_key(repo, 'iterfuncs')
+        let repo.iterfuncs=deepcopy(s:iterfuncs)
+    else
+        call extend(repo.iterfuncs, s:iterfuncs, 'keep')
+    endif
     lockvar! repo
     unlockvar! repo.cslist
     unlockvar! repo.changesets