Thursday, October 7, 2010

Re: Vim mutilating file permissions through Samba?

I said I'd post my results on this issue just in case it ever hits
anyone else - below is the code I've settled on which is working well
for my particular needs. (And note - my ssh mechanism is not always
reliable so I try to only use it when I believe I need to.)

John

let s:linuxServer = 'devel'
let s:linuxServerMappings = { 'j': '/home/john' }

function! GetFilePermissions(...) " {{{3
" Function to get a file's permissions.
" With no arg, assumes current buffer, and returns a cached result
unless v:cmdbang is set
if a:0 == 0
" Use the current buffer. First, check if the cached version is
appropriate
if exists('b:SavedFilePermissions')
\ && b:SavedFilePermissions =~ '^\d\{3,4\}$'
\ && v:cmdbang != 1
return b:SavedFilePermissions
else
let file = expand('%:p')
endif
else
let file = expand(a:1)
endif

let cmd = ''
if exists('s:linuxServerMappings') && file =~
'\c^['.join(keys(s:linuxServerMappings),'').']:'
" File on linux fileserver - try remotely on linuxServer
let f = file
for drive in keys(s:linuxServerMappings)
exec 'let f = substitute(f, ''\c^\('.drive.'\):'',
'''.s:linuxServerMappings[drive].''', ''g'')'
endfor
let f = substitute(f, '\\', '\/', 'g')
let cmd .= 'ssh -x '.s:linuxServer.' '
else
" Local file - try locally, converting any Win paths to Cygwin
first
let f = ConvertPathWinToCyg(file)
endif
let cmd .= 'stat -c"%a" "'.f.'"'
let perms = Chomp(system(cmd))
if v:shell_error != 0 || perms !~ '^\d\{3,4\}$'
echom file.": unable to get permissions with command '".cmd."'"
let perms = 'unobtainable'
endif
if a:0 == 0
let b:SavedFilePermissions = perms
endif
return perms
endfunction

function! SetFilePermissions(...) " {{{3
" Function to set a file's permissions
" With no args, assumes current buffer, uses cached permissions.
" With one arg, it must be the permissions to set on the current
buffer
" With two args, it must be the permissions to set and the file to
set them on
if a:0 == 0
let file = expand('%:p')
if !exists('b:SavedFilePermissions')
echom "SetFilePermissions() unable to set permissions on
".file." since b:SavedFilePermissions not set"
return
else
let perms = b:SavedFilePermissions
endif
elseif a:0 == 1
let file = expand('%:p')
let perms = a:1
elseif a:0 == 2
let perms = a:1
let file = a:2
endif

if perms !~ '^\d\{3,4\}$'
echom "SetFilePermissions(...) : perms=".perms.",file=".file."
doing nothing due to invalid permissions"
return
endif

let cmd = ''
if exists('s:linuxServerMappings') && file =~
'\c^['.join(keys(s:linuxServerMappings),'').']:'
" File on linux fileserver - try remotely on linuxServer
let f = file
for drive in keys(s:linuxServerMappings)
exec 'let f = substitute(f, ''\c^\('.drive.'\):'',
'''.s:linuxServerMappings[drive].''', ''g'')'
endfor
let f = substitute(f, '\\', '\/', 'g')
let cmd .= 'ssh -x -vvv '.s:linuxServer.' '
else
" Local file - try locally, converting any Win paths to Cygwin
first
let f = ConvertPathWinToCyg(file)
endif
let cmd .= 'chmod '.perms.' "'.f.'"'
let output = system(cmd)
if v:shell_error != 0
echom "SetFilePermissions(...) : perms=".perms.",file=".file."
unable to set permissions with command '".cmd."', debug saved in @z"
let @z = output
return
endif
endfunction

function! SetFilePermissionsIfRequired() " {{{3
" Function to call SetFilePermissions, but only if it's necessary
for my particular circumstances
" My specific issues are
" 1. 'ux' permissions on linux server files not being preserved
" 2. 'ux' permissions being given to local files (on windows)
inappropriately
if !exists('b:SavedFilePermissions')
return
endif

let user_permission_digit = strpart(b:SavedFilePermissions,
strlen(b:SavedFilePermissions)-3, 1)
if (exists('s:linuxServerMappings') && ((expand('%:p') =~
'\c^['.join(keys(s:linuxServerMappings),'').']:' &&
user_permission_digit % 2 == 1)
\ || expand('%:p') !~
'\c^['.join(keys(s:linuxServerMappings),'').']:'))
\ || (!exists('s:linuxServerMappings') && user_permission_digit %
2 == 0)
call SetFilePermissions()
endif
endfunction

function! ConvertPathWinToCyg(path) "{{{3
let path = a:path
if path =~ '^.:' || path =~ '\\'
let path = Chomp(system('cygpath "'.a:path.'"'))
if v:shell_error != 0
echoe "ConvertPathWinToCyg(".a:path."): cygpath command failed -
cygwin not installed or not in path?"
let path = "ConvertPathWinToCygFailedToConvertPath"
endif
endif
return path
endfunction

function! Chomp(line) " {{{3 Perl's chomp function
return substitute(a:line, '\v(\r)?(\n)?$', '', '')
endfunction

autocmd BufWritePre * call GetFilePermissions()
autocmd BufWritePost * call SetFilePermissionsIfRequired()

--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

No comments: