Commits

ZyX_I committed e5972d0

@aurum/drivers/git: Added g:aurum_git_maxitercsnum option
Added iterfuncs.revrange and iterfuncs.changesets
Fixes #35

  • Participants
  • Parent commits f360c3b

Comments (0)

Files changed (3)

File README.markdown

   - Viewing working directory status ([:AuStatus](http://vimpluginloader.sourceforge.net/doc/aurum.txt.html#line392-0)).
 
   - Commiting changes ([:AuCommit](http://vimpluginloader.sourceforge.net/doc/aurum.txt.html#line102-0)), commit messages are remembered in case of 
-    rollback ([g:aurum_remembermsg](http://vimpluginloader.sourceforge.net/doc/aurum.txt.html#line998-0)).
+    rollback ([g:aurum_remembermsg](http://vimpluginloader.sourceforge.net/doc/aurum.txt.html#line1005-0)).
 
   - Obtaining various URL’s out of remote repository URL (like URL of the HTML 
     version of the current file with URL fragment pointing to the current line 
 
   - Frontends for various other VCS commands.
 
-Most commands can be reached with a set of mappings (see [aurum-mappings](http://vimpluginloader.sourceforge.net/doc/aurum.txt.html#line794-0)), 
+Most commands can be reached with a set of mappings (see [aurum-mappings](http://vimpluginloader.sourceforge.net/doc/aurum.txt.html#line801-0)), 
 all mappings are customizable.
 
 

File doc/aurum.txt

     not a lowercase letter) of Mercurial commands that are to be called 
     without using Mercurial Python API.
 
-    Functions supporting this option: |rf-commit|, |rf-update|, |rf-move| 
-    (uses "rename" mercurial command), |rf-copy|, |rf-forget|, |rf-remove|, 
-    |rf-add|, |rf-branch|, |rf-label| (uses "tag" or "bookmark" Mercurial 
-    commands). Every function except |rf-move| and |rf-label| uses Mercurial 
+    Functions supporting this option: |aurum-rf-commit|, |aurum-rf-update|, 
+    |aurum-rf-move| (uses "rename" mercurial command), |aurum-rf-copy|, 
+    |aurum-rf-forget|, |aurum-rf-remove|, |aurum-rf-add|, |aurum-rf-branch|, 
+    |aurum-rf-label| (uses "tag" or "bookmark" Mercurial commands). Every 
+    function except |aurum-rf-move| and |aurum-rf-label| uses Mercurial 
     command identical to its name.
 
+git_maxitercsnum                                    *g:aurum_git_maxitercsnum*
+    Unsigned (non-negative) integer, must be less then a number of arguments 
+    that can be accepted by a shell command. Determines information about how 
+    many revisions will be obtained by |aurum-rf-getchangesets| and 
+    |aurum-rf-revrange| functions and also how many revisions will be 
+    processed by |aurum-repo.iterfuncs| (currently only revrange and 
+    changesets are supported). Zero means that all revisions will be pulled at 
+    once, don’t use this if you are working with large repositories.
+    Note: Setting it to non-zero produces extra shell call used to obtain list 
+          of revisions to show. Setting it to zero increases memory 
+          consumption, the time in which first log entry can be shown and may 
+          increase the time needed to create full log.
+    Default: 1000.
+
 ==============================================================================
 5. Globs                                                         *aurum-globs*
 

File plugin/aurum/drivers/git.vim

 if !exists('s:_pluginloaded')
     execute frawor#Setup('0.1', {   '@aurum/repo': '4.0',
                 \                          '@/os': '0.1',
+                \                     '@/options': '0.0',
                 \   '@aurum/drivers/common/utils': '0.0',
                 \'@aurum/drivers/common/hypsites': '0.0',}, 0)
     finish
             \    'ppf': 'Failed to run “git %s” for the repository %s: %s',
         \}
 let s:git={}
+let s:_options={
+            \'git_maxitercsnum': {'default': 1000, 'checker': 'range 0 inf'},
+        \}
 "▶1 s:hypsites
 let s:hypsites=s:_r.hypsites.git
 "▶1 refile :: gitfname → path
 " 1-indented commit message
 let s:logformat='%h-%H-%P-%at%n%an%n%ae%n%d%n%w(0,1,1)%B'
 let s:logkwargs={'format': s:logformat, 'encoding': 'utf-8', 'date-order': 1}
-function s:F.parsecs(csdata, lstart)
-    let line=a:lstart
+function s:F.parsecs(csdata)
     let cs={'branch': 'default'}
-    let [rev, hex, parents, time]=split(a:csdata[line], '-', 1) | let line+=1
+    let [rev, hex, parents, time]=split(remove(a:csdata, 0), '-', 1)
     let cs.hex=hex
     let cs.parents=split(parents)
     let cs.time=+time
     let cs.rev=rev
-    let aname=a:csdata[line]                                    | let line+=1
-    let aemail=a:csdata[line]                                   | let line+=1
+    let aname=remove(a:csdata, 0)
+    let aemail=remove(a:csdata, 0)
     let cs.user=aname.' <'.aemail.'>'
-    let cs.tags=split(a:csdata[line][2:-2], ', ')               | let line+=1
+    let cs.tags=split(remove(a:csdata, 0)[2:-2], ', ')
     let cs.bookmarks=[]
     "▶2 get description
     let description=[]
-    let lcsdata=len(a:csdata)
-    while line<lcsdata && a:csdata[line][0] is# ' '
-        let description+=[a:csdata[line][1:]]
-        let line+=1
+    while !empty(a:csdata) && a:csdata[0][0] is# ' '
+        let description+=[remove(a:csdata, 0)[1:]]
     endwhile
     let cs.description=join(description, "\n")
-    if empty(get(a:csdata, line, 0))
-        let line+=1
+    if get(a:csdata, 0, 0) is# ''
+        call remove(a:csdata, 0)
     endif
     "▲2
-    return [cs, line]
+    return cs
 endfunction
 "▶1 git.getcs :: repo, rev → cs
 function s:git.getcs(repo, rev)
     let cs=s:F.parsecs(s:F.git(a:repo, 'log', ['-n1', a:rev], s:logkwargs,
-                \              0, 'csf', a:rev),
-                \      0)[0]
+                \              0, 'csf', a:rev))
     " XXX This construct is used to preserve information like “allfiles” etc
     let a:repo.changesets[cs.hex]=extend(get(a:repo.changesets, cs.hex, {}), cs)
     return a:repo.changesets[cs.hex]
 function s:git.getwork(repo)
     return a:repo.functions.getcs(a:repo, 'HEAD')
 endfunction
-"▶1 git.getchangesets :: repo → []
-function s:git.getchangesets(repo, ...)
+"▶1 prepgitargs
+function s:F.prepgitargs(repo, ...)
     "▶2 Prepare s:F.git arguments
     let args=[]
     let kwargs=copy(s:logkwargs)
+    let revargs=[]
+    let revkwargs={}
     if a:0
-        let args+=[a:1.'^..'.a:2]
+        let revargs+=[a:1.'^..'.a:2]
     else
-        let kwargs.all=1
-        let kwargs['full-history']=1
+        let revkwargs.all=1
+        let revkwargs['full-history']=1
     endif
     let gitargs=[a:repo, 'log', args, kwargs, 0]
     if a:0
     else
         let gitargs+=['logf']
     endif
+    "▶2 Prepare hexslist in case git_maxitercsnum is greater then zero
+    if a:repo.maxitercsnum
+        let gitrlargs=copy(gitargs)
+        let gitrlargs[2]=copy(gitrlargs[2])+revargs
+        let gitrlargs[3]=extend(extend(copy(gitrlargs[3]),
+                    \           s:rlkwargs),
+                    \           revkwargs)
+        let hexlist=call(s:F.git, gitrlargs, {})[:-2]
+        let kwargs['no-walk']=1
+    else
+        call extend(kwargs, revkwargs)
+        call extend(  args, revargs  )
+        let hexlist=1
+    endif
     "▲2
-    let log=call(s:F.git, gitargs, {})[:-2]
-    "▶2 If log has shown nothing, try reversing range
-    if a:0 && empty(log)
-        let args[0]=a:2.'..'.a:1
-        let gitargs[-1]=a:1
-        let gitargs[-2]=a:2
+    return [hexlist, gitargs]
+endfunction
+"▶1 git.getchangesets :: repo[, rangestart[, rangeend]] → [cs]
+let s:rlkwargs={'format': '%H'}
+function s:git.getchangesets(repo, ...)
+    let [hexlist, gitargs]=call(s:F.prepgitargs, [a:repo]+a:000, {})
+    let args=gitargs[2]
+    let cslist=[]
+    while !empty(hexlist)
+        if hexlist is 1
+            let hexlist=0
+        else
+            let curhexs=remove(hexlist, 0,
+                        \      min([a:repo.maxitercsnum, len(hexlist)])-1)
+            let gitargs[2]=args+curhexs
+        endif
         let log=call(s:F.git, gitargs, {})[:-2]
-        if empty(log)
-            call s:_f.throw('invrng', a:1, a:2, a:repo.path)
-        endif
-    endif
-    "▶2 Parse changeset information
-    let i=0
-    let llog=len(log)
-    let cslist=[]
-    while i<llog
-        let [cs, i]=s:F.parsecs(log, i)
-        let a:repo.changesets[cs.hex]=extend(get(a:repo.changesets, cs.hex, {}),
-                    \                        cs)
-        call insert(cslist, a:repo.changesets[cs.hex])
+        "▶2 Parse changeset information
+        while !empty(log)
+            let cs=s:F.parsecs(log)
+            let a:repo.changesets[cs.hex]=extend(get(a:repo.changesets, cs.hex,
+                        \                            {}),
+                        \                        cs)
+            call insert(cslist, a:repo.changesets[cs.hex])
+        endwhile
+        "▲2
     endwhile
-    "▲2
     return cslist
 endfunction
 "▶1 git.revrange :: repo, rev1, rev2 → [cs]
 let s:git.revrange=s:git.getchangesets
 "▶1 git.updatechangesets :: repo → _
-let s:git.updatechangesets=s:git.getchangesets
+function s:git.updatechangesets(...)
+endfunction
 "▶1 git.getrevhex :: repo, rev → hex
 let s:prevrevhex={}
 function s:git.getrevhex(repo, rev)
                 \'labeltypes': ['tag', 'branch'],
                 \'hasrevisions': 0, 'requires_sort': 0,
                 \'githpath': s:_r.os.path.join(a:path, '.git', 'refs', 'heads'),
-                \'hypsites': deepcopy(s:hypsites),}
+                \'hypsites': deepcopy(s:hypsites),
+                \'maxitercsnum': s:_f.getoption('git_maxitercsnum'),
+                \'iterfuncs': deepcopy(s:iterfuncs),
+                \}
     if has_key(s:prevrevhex, a:path)
         unlet s:prevrevhex[a:path]
     endif
 function s:git.checkdir(dir)
     return s:_r.os.path.isdir(s:_r.os.path.join(a:dir, '.git'))
 endfunction
+"▶1 iterfuncs
+let s:iterfuncs={}
+"▶2 nextcs
+function s:F.nextcs()
+    if empty(self.log)
+        if empty(self.hexlist)
+            return 0
+        endif
+        let curhexs=remove(self.hexlist, 0, min([self.maxitercsnum,
+                    \                            len(self.hexlist)])-1)
+        let gitargs=copy(self.gitargs)
+        let gitargs[2]=gitargs[2]+curhexs
+        let self.log=call(s:F.git, gitargs, {})[:-2]
+    endif
+    let cs=s:F.parsecs(self.log)
+    let self.repo.changesets[cs.hex]=extend(get(self.repo.changesets, cs.hex,
+                \                               {}),
+                \                          cs)
+    return self.repo.changesets[cs.hex]
+endfunction
+"▶2 iterfuncs.revrange, iterfuncs.changesets
+function s:iterfuncs.revrange(repo, opts)
+    let pgaargs=[a:repo]
+    if has_key(a:opts, 'revrange')
+        let pgaargs+=a:opts.revrange
+    endif
+    let [hexlist, gitargs]=call(s:F.prepgitargs, pgaargs, {})
+    if hexlist is 1
+        let hexlist=0
+        let log=call(s:F.git, gitargs, {})[:-2]
+    else
+        let log=[]
+    endif
+    return {'repo': a:repo, 'maxitercsnum': a:repo.maxitercsnum,
+                \'hexlist': hexlist,
+                \'gitargs': gitargs, 'log': log,
+                \'next': s:F.nextcs}
+endfunction
+let s:iterfuncs.changesets=s:iterfuncs.revrange
 "▶1 Register driver
 call s:_f.regdriver('Git', s:git)
 "▶1