Skip to content

Commit

Permalink
ENH: Avoid tag updating when ctags output has identical fingerprint.
Browse files Browse the repository at this point in the history
We can avoid the lengthy and blocking update of the tags database when the ctags output returns the same information as before; i.e. nothing tag-relevant has been changed since the last update.
Since 7.3.816, Vim has a sha256() function that allows us to quickly calculate a fingerprint over the ctags output. When that is not available, only handle the special case of a (covered) file that has no tags at all (as calculating a hash in Vimscript is costly and would probably defeat the intended speedup).
  • Loading branch information
inkarkat committed Mar 28, 2013
1 parent 44b0487 commit d789e8e
Showing 1 changed file with 35 additions and 2 deletions.
37 changes: 35 additions & 2 deletions autoload/xolox/easytags.vim
Expand Up @@ -99,8 +99,11 @@ function! xolox#easytags#update(silent, filter_tags, filenames) " {{{2
let tagsfile = xolox#easytags#get_tagsfile()
let firstrun = !filereadable(tagsfile)
let cmdline = s:prep_cmdline(cfile, tagsfile, firstrun, a:filenames, context)
let output = s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline)
let [output, has_updates] = s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline)
if !firstrun
if !has_updates
return 1
endif
if have_args && !empty(g:easytags_by_filetype)
" TODO Get the headers from somewhere?!
call s:save_by_filetype(a:filter_tags, [], output, context)
Expand Down Expand Up @@ -201,12 +204,41 @@ function! s:prep_cmdline(cfile, tagsfile, firstrun, arguments, context) " {{{3
return have_args ? join(cmdline) : ''
endfunction

if exists('*sha256')
function! s:get_fingerprint(cfile, output)
return sha256(a:output)
endfunction
else
function! s:get_fingerprint(cfile, output)
" Don't want to re-implement a costly hashing function in Vimscript. Just
" handle files that never had any tags.
if empty(a:output)
return get(s:fingerprints, a:cfile, 1)
else
return ''
endif
endfunction
endif

let s:fingerprints = {}
function! s:has_updates(cfile, output)
let fingerprint = s:get_fingerprint(a:cfile, a:output)
if ! empty(fingerprint) && get(s:fingerprints, a:cfile, '') ==# fingerprint
return 0
endif

let s:fingerprints[a:cfile] = fingerprint
return 1
endfunction

function! s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) " {{{3
let lines = []
let has_updates = 1
if a:cmdline != ''
call xolox#misc#msg#debug("easytags.vim %s: Executing %s.", g:xolox#easytags#version, a:cmdline)
try
let lines = xolox#shell#execute(a:cmdline, 1)
let has_updates = a:firstrun || s:has_updates(a:cfile, join(lines, "\n"))
catch /^Vim\%((\a\+)\)\=:E117/
" Ignore missing shell.vim plug-in.
let output = system(a:cmdline)
Expand All @@ -215,6 +247,7 @@ function! s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) " {{{3
throw printf(msg, fnamemodify(a:tagsfile, ':~'), strtrans(output))
endif
let lines = split(output, "\n")
let has_updates = a:firstrun || s:has_updates(a:cfile, output)
endtry
if a:firstrun
if a:cfile != ''
Expand All @@ -225,7 +258,7 @@ function! s:run_ctags(starttime, cfile, tagsfile, firstrun, cmdline) " {{{3
return []
endif
endif
return xolox#easytags#parse_entries(lines)
return [xolox#easytags#parse_entries(lines), has_updates]
endfunction

function! s:filter_merge_tags(filter_tags, tagsfile, output, context) " {{{3
Expand Down

0 comments on commit d789e8e

Please sign in to comment.