Re-organised configuration files

This commit is contained in:
Emmanuel BENOîT 2015-02-23 22:11:15 +01:00
parent 2d7eff306a
commit 34f84c9155
13 changed files with 54 additions and 40 deletions

50
cfg-pre/00-vardata.vim Normal file
View file

@ -0,0 +1,50 @@
" Variable data directory handling
" Create a directory if it doesn't already exist
function! CreateDirectoryIfNecessary( name )
if isdirectory( a:name )
if !filewritable( a:name )
echoerr "Directory" a:name "is not writable"
return 0
endif
return 1
endif
if !empty( glob( a:name ) )
echoerr a:name "exists but is not a directory"
return 0
endif
if exists( "*mkdir" )
return mkdir( a:name , "p" , 0700 )
endif
let rv = system( "mkdir -p -m 0700 " . shellescape( a:name )
\ . " >/dev/null 2>&1; echo $?" )
if l:rv
echoerr "Cannot create" a:name
endif
return !rv
endfunction
" Get it from either g:vim_vardata, $VIM_DATA or create it based on $HOME
if exists( 'g:vim_vardata' )
let s:vim_vardata_base = g:vim_vardata
elseif $VIM_DATA != ""
let s:vim_vardata_base = $VIM_DATA
else
let s:vim_vardata_base = $HOME . '/.vimdata'
endif
" Remove trailing slash
if s:vim_vardata_base =~ "/$"
let s:vim_vardata_base = s:vim_vardata_base[ 0 : -1 ]
endif
" Attempt creating it
if CreateDirectoryIfNecessary( s:vim_vardata_base )
let g:vim_vardata = glob( s:vim_vardata_base )
else
let g:vim_vardata = ''
endif

128
cfg-pre/10-signatures.vim Normal file
View file

@ -0,0 +1,128 @@
" Manage keys used for signing local configuration files
"
" * Can be disabled completely by setting VIM_NOCRYPTO in the environment
" * Will disable itself silently if openssl is unavailable
" * Keys will be looked up in g:vim_vardata/keys by default, unless
" g:vim_keys is set
" Register no-operation functions for signing and checking signatures
function! SignFile(filename,sigfile)
if !empty( glob( a:sigfile ) )
call delete( a:sigfile )
endif
return 0
endfunction
function! CheckSignature(filename,sigfile)
echoerr "Signature checking is disabled."
return 0
endfunction
" Get configured directory / use default. Make sure global configuration
" is cleared.
if exists( "g:vim_keys" )
if $VIM_NOCRYPTO == ""
let s:keys_dir = g:vim_keys
endif
unlet g:vim_keys
elseif $VIM_NOCRYPTO == "" && g:vim_vardata != ""
let s:keys_dir = g:vim_vardata . "/keys"
endif
if !exists( "s:keys_dir" ) || !executable( "openssl" ) || !has( "cryptv" )
finish
endif
" Try creating the directory
if ! CreateDirectoryIfNecessary( s:keys_dir )
echoerr "Could not create" s:keys_dir
\ "; signed configuration support disabled"
finish
endif
" Create the key if necessary
if !filereadable( s:keys_dir . "/vim.key" )
let s:key_bits = exists( "g:vim_key_bits" ) ? g:vim_key_bits : 4096
echo "Generating configuration signing key (" . s:key_bits
\ . " bits)..."
let s:genrsa = system( "openssl genrsa -out "
\ . shellescape( s:keys_dir . "/vim.key" )
\ . " " . s:key_bits . " >/dev/null 2>&1; echo $?" )
if s:genrsa
echoerr "Key generation failed!"
finish
endif
endif
" Set global configuration variable and define actual signature functions
let g:vim_keys = s:keys_dir
function! SignFile(filename,sigfile)
if !empty( glob( a:sigfile ) )
if delete( a:sigfile )
echoerr "Could not delete old signature file"
\ a:sigfile
return 0
endif
endif
" Load the file
if !filereadable( a:filename )
echoerr "File" a:filename "is not readable"
return 0
endif
try
let file_contents = readfile( a:filename , "b" )
catch /.*/
echoerr "Could not load" a:filename
return 0
endtry
" Compute checksum
let checksum = sha256( join( l:file_contents , "\n" ) )
" Sign and store checksum
let command = "echo " . l:checksum
\ . " | openssl rsautl -sign -inkey "
\ . shellescape( g:vim_keys . "/vim.key" )
\ . " -out " . shellescape( a:sigfile )
\ . " >/dev/null 2>&1; echo $?"
let rv = system( l:command )
if l:rv
echoerr "Signature failed for" a:filename
echoerr "Command was:" l:command
endif
return !l:rv
endfunction
function! CheckSignature(filename,sigfile)
let signed_sum = system( "openssl rsautl -verify -inkey "
\ . shellescape( g:vim_keys . "/vim.key" )
\ . " -in " . shellescape( a:sigfile )
\ . " 2>/dev/null" )
if signed_sum == ""
echoerr "Signature verification failed for" a:filename
return 0
endif
" Load the file
try
let file_contents = readfile( a:filename , "b" )
catch /.*/
echoerr "Could not load" a:filename
return 0
endtry
" Verify checksum
let computed = sha256( join( l:file_contents , "\n" ) )
if len( l:signed_sum ) > len( l:computed )
let l:signed_sum = l:signed_sum[ 0 : len( l:computed ) - 1 ]
endif
if l:computed != l:signed_sum
echoerr "Checksum mismatch for" a:filename
return 0
endif
return 1
endfunction

View file

@ -0,0 +1,2 @@
filetype plugin indent on
syntax on

194
cfg-pre/50-local-config.vim Normal file
View file

@ -0,0 +1,194 @@
" Attempt to find a local configuration or configuration directory
" Clear various things that could be here from a previous execution
unlet! g:vim_local
unlet! g:vim_local_path
command! -bang -nargs=* SaveAndSign echoerr "Command not supported"
command! -bang -nargs=* SignConfig echoerr "Command not supported"
" Clear configuration signing autocommands
augroup LocalConfigurationSigning
autocmd!
augroup END
" Always define this function; it tries to access data from either g:vim_local
" if that is defined, or from a global variable otherwise
function! GetConfigValue(name,...)
if exists( "g:vim_local['" . a:name . "']" )
return g:vim_local[ a:name ]
endif
if exists( "g:" . a:name )
execute "return g:" . a:name
endif
return a:1
endfunction
" Get a vardata path, either from the local configuration or from
" g:vim_vardata.
function! GetVardataPath(name)
if exists( "g:vim_local['vardata']" )
return g:vim_local['vardata'] . "/" . a:name
endif
return g:vim_vardata . "/" . a:name
endfunction
" Find a configuration file, based on a path relative to the configuration
" directory and a name.
"
" 1/ If there is a local configuration, this will look for the file in the
" local configuration. If it exists, its full path will be returned.
" 2/ If there is a local configuration, this will look for a file named
" 'suppress.<name>' at the same location; if the file is found, the
" function will return an empty string.
" 3/ If the file exists in the global configuration, its full path will be
" returned.
" 4/ An empty string will be returned.
function! GetConfigFilePath(base,name)
if exists( "g:vim_local_path" )
let bd = g:vim_local_path . "/" . a:base
if filereadable( l:bd . "/" . a:name )
return l:bd . "/" . a:name
endif
if filereadable( l:bd . "/suppress." . a:name )
return ""
endif
endif
let f = g:vim_home . "/" . a:base . "/" . a:name
if filereadable( l:f )
return l:f
endif
return ''
endfunction
" List files in a configuration directory, letting the local configuration
" override the main configuration. The files are returned as a dictionary;
" keys are the files' basenames, while values are the full paths.
function! GetConfigFiles(base,pattern)
let fd = {}
" Get main configuration files
for mcf in glob( g:vim_home . "/" . a:base . "/" . a:pattern , 1 , 1 )
let l:fd[ fnamemodify( l:mcf , ":t" ) ] = l:mcf
endfor
" Exit if there's no local configuration
if !exists( "g:vim_local_path" )
return l:fd
endif
" Handle suppressions
for lsf in glob( g:vim_local_path . "/" . a:base . "/suppress." . a:pattern , 1 , 1 )
unlet! l:fd[ fnamemodify( l:lsf , ":t" )[ 9 : -1 ] ]
endfor
" Handle local files
for lcf in glob( g:vim_local_path . "/" . a:base . "/" . a:pattern , 1 , 1 )
let l:fd[ fnamemodify( l:lcf , ":t" ) ] = l:lcf
endfor
return l:fd
endfunction
" We need signature handling abilities to continue
if !exists( "g:vim_keys" )
finish
endif
" When a .vim.local/vimrc file is saved, print a warning about the lack of
" signature.
function! <SID>WarnAboutSignature()
let bp = expand( "%:p:h" )
if fnamemodify( bp , ":t" ) == ".vim.local"
if exists( "g:vim_local_path" )
let bp = l:bp . "/"
if g:vim_local_path =~ "/$" && l:bp !~ "/$"
let l:bp = l:bp . "/"
elseif g:vim_local_path !~ "/$" && l:bp =~ "/$"
let l:bp = l:bp[ 0 : -2 ]
endif
endif
" If we're being called from SaveAndSign, sign it instead of
" whining.
if exists( "s:save_and_sign" )
call SignFile( expand( "%:p" ) , l:bp . "/signature" )
return
endif
echohl WarningMsg
if exists( "g:vim_local_path" ) && g:vim_local_path == l:bp
echo "Warning: not signed, use :SignConfig"
else
echo "Warning: not signed, use :SaveAndSign."
endif
echohl None
endif
endfunction
augroup LocalConfigurationSigning
autocmd BufWritePost vimrc :call <SID>WarnAboutSignature()
augroup END
" Sign the local configuration file; only works when one has already been
" loaded.
function! <SID>SignConfig()
if exists( "g:vim_local_path" ) && filereadable( g:vim_local_path . "/vimrc" )
call SignFile( g:vim_local_path . "/vimrc" ,
\ g:vim_local_path . "/signature" )
elseif exists( "g:vim_local_path" )
echohl ErrorMsg
echo "ERROR: no local vimrc file"
echohl None
else
echohl ErrorMsg
echo "ERROR: no local configuration; use :SaveAndSign for new configurations"
echohl None
endif
endfunction
command! SignConfig :call <SID>SignConfig()
" Save and sign a local configuration file. Can be used with both active local
" configurations and new or external configurations.
function! <SID>SaveAndSign(force,...)
if a:0 > 1
echohl ErrorMsg
echo "E172: Only one file name allowed"
echohl None
return
endif
let s:save_and_sign = 1
if a:0 == 1 && a:force
execute "w!" a:1
elseif a:0
execute "w" a:1
elseif a:force
w!
else
w
endif
unlet! s:save_and_sign
endfunction
command! -bang -complete=file -nargs=? SaveAndSign
\ call <SID>SaveAndSign( "<bang>" == "!" , <f-args> )
" Check if the local directory and local vimrc exist
if !( isdirectory( ".vim.local" ) && filereadable( ".vim.local/vimrc" ) )
finish
endif
echo " "
echo "Found local configuration in .vim.local ; validating..."
" Verify the vimrc's signature
try
call CheckSignature( ".vim.local/vimrc" , ".vim.local/signature" )
catch /.*/
echo " "
echo " -> SIGNATURE VERIFICATION FAILED"
echo " "
finish
endtry
echo " -> Using local configuration."
echo " "
let g:vim_local_path = fnamemodify( ".vim.local" , ":p" )
let &g:runtimepath = &g:runtimepath . "," . g:vim_local_path
" Source it
source .vim.local/vimrc

99
cfg-pre/75-neobundle.vim Normal file
View file

@ -0,0 +1,99 @@
" Load and initialise NeoBundle and plugins
echo "location"
if !exists( "g:bundles_dir" )
if exists( "g:vim_local['local_bundles']" )
if !exists( "g:vim_local['vardata']" )
echo "Local bundles requested, but local data directory is not set."
endif
let g:bundles_dir = GetVardataPath( "bundles" )
else
let g:bundles_dir = g:vim_vardata . "/bundles/"
endif
endif
if g:bundles_dir !~ "/$"
let g:bundles_dir = g:bundles_dir . "/"
endif
if !CreateDirectoryIfNecessary( g:bundles_dir )
unlet g:bundles_dir
function! DoNeoBundleCheck()
" Empty placeholder function
endfunction
finish
endif
if has( 'vim_starting' )
if &compatible
set nocompatible
endif
if isdirectory( g:bundles_dir . "neobundle.vim" )
let s:neobundle_path = g:bundles_dir . "neobundle.vim"
else
let s:neobundle_path = g:vim_home . "/neobundle-initial"
endif
let &g:runtimepath = &g:runtimepath . "," . s:neobundle_path
endif
call neobundle#begin( g:bundles_dir )
" Load NeoBundle itself, as well as VimProc
NeoBundleFetch 'Shougo/neobundle.vim'
" Load all plugins from bundles-init/*.load.vim
let s:binit_dir = g:vim_home . "/bundles-init"
let s:bundle_load_files = GetConfigFiles( "bundles-init" , "*.load.vim" )
for s:plfn in values( s:bundle_load_files )
execute "source" s:plfn
" Create configuration loading hooks
let s:pname = fnamemodify( s:plfn , ":t:r:r" )
let s:bundle = neobundle#get( s:pname )
if empty( s:bundle )
continue
endif
function! s:bundle.hooks.on_post_source( bundle )
let cfgfile = GetConfigFilePath( "bundles-init" ,
\ a:bundle.name . ".cfg.vim" )
if l:cfgfile != ""
execute "source" l:cfgfile
endif
endfunction
endfor
call neobundle#end()
" Function that runs NeoBundleCheck after enabling all filetype bits; it
" restores them on exit
function! DoNeoBundleCheck()
" Save current filetype settings
let s:has_ft = exists( "g:did_load_filetypes" )
let s:has_fti = exists( "g:did_indent_on" )
let s:has_ftp = exists( "g:did_load_ftplugin" )
" Enable filetype with both indent and plugins
if !( s:has_ft && s:has_fti && s:has_ftp )
filetype plugin indent on
endif
" Let NeoBundle check for installations
NeoBundleCheck
" Call hooks on reload
if !has( "vim_starting" )
call neobundle#call_hook( "on_post_source" )
endif
" Restore filetype settings
if ! s:has_fti
filetype indent off
endif
if ! s:has_ftp
filetype plugin off
endif
if ! s:has_ft
filetype off
endif
endfunction

View file

@ -0,0 +1,7 @@
" Loads the main configuration from cfg/, using a merge from the main and
" local configurations.
let s:cfg_files = GetConfigFiles( "cfg" , "??-?*.vim" )
for s:cfg_file in sort( keys( s:cfg_files ) )
execute 'source ' . s:cfg_files[ s:cfg_file ]
endfor