vfmt: keep file permissions with -w on !windows (#13334)

pull/13337/head
Tarcisio Gruppi 2022-02-01 09:49:06 -03:00 committed by GitHub
parent 7c1b249da0
commit 51513ae19a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 0 deletions

View File

@ -259,7 +259,15 @@ fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path
file_bak := '${file}.bak' file_bak := '${file}.bak'
os.cp(file, file_bak) or {} os.cp(file, file_bak) or {}
} }
mut perms_to_restore := u32(0)
$if !windows {
fm := os.inode(file)
perms_to_restore = fm.bitmask()
}
os.mv_by_cp(formatted_file_path, file) or { panic(err) } os.mv_by_cp(formatted_file_path, file) or { panic(err) }
$if !windows {
os.chmod(file, int(perms_to_restore)) or { panic(err) }
}
eprintln('Reformatted file: $file') eprintln('Reformatted file: $file')
} else { } else {
eprintln('Already formatted file: $file') eprintln('Already formatted file: $file')

View File

@ -20,6 +20,22 @@ pub:
execute bool execute bool
} }
// bitmask returns a 3 bit sequence in the order RWE where
// the bit is set to 1 if the value is true or 0 otherwise.
pub fn (p FilePermission) bitmask() u32 {
mut mask := u32(0)
if p.read {
mask |= 4
}
if p.write {
mask |= 2
}
if p.execute {
mask |= 1
}
return mask
}
struct FileMode { struct FileMode {
pub: pub:
typ FileType typ FileType
@ -28,6 +44,12 @@ pub:
others FilePermission others FilePermission
} }
// bitmask returns a 9 bit sequence in the order owner + group + others.
// This is a valid bitmask to use with `os.chmod`.
pub fn (m FileMode) bitmask() u32 {
return m.owner.bitmask() << 6 | m.group.bitmask() << 3 | m.others.bitmask()
}
// inode returns the mode of the file/inode containing inode type and permission information // inode returns the mode of the file/inode containing inode type and permission information
// it supports windows for regular files but it doesn't matter if you use owner, group or others when checking permissions on windows // it supports windows for regular files but it doesn't matter if you use owner, group or others when checking permissions on windows
pub fn inode(path string) FileMode { pub fn inode(path string) FileMode {

View File

@ -41,3 +41,16 @@ fn test_inode_file_owner_permission() {
assert mode.owner.write assert mode.owner.write
assert !mode.owner.execute assert !mode.owner.execute
} }
fn test_inode_file_permissions_bitmask() {
if user_os() == 'windows' {
println('> skipping ${@FN} on windows')
return
}
filename := './test3.txt'
mut file := open_file(filename, 'w', 0o641) or { return }
file.close()
mode := inode(filename)
rm(filename) or {}
assert mode.bitmask() == 0o641
}