1234567module machine89import os1011pub const remote_file = 'remote'12pub const credentials_file = 'credentials'1314pub const kind_folder = 'folder'15pub const kind_s3 = 's3'1617pub struct RemoteSettings {18pub:19 kind string20 path string 21 endpoint string 22 bucket string23 region string24 kepr string25}2627pub struct Credentials {28pub:29 access_key string30 secret_key string31}3233pub fn save_remote(settings RemoteSettings) ! {34 os.mkdir_all(config_dir(), os.MkdirParams{})!35 mut text := '# written by koh remote — the remote for every repo on this machine\n'36 text += 'kind=${settings.kind}\n'37 if settings.kind == kind_folder {38 text += 'path=${settings.path}\n'39 } else {40 text += 'endpoint=${settings.endpoint}\n'41 text += 'bucket=${settings.bucket}\n'42 text += 'region=${settings.region}\n'43 if settings.kepr != '' {44 text += 'kepr=${settings.kepr}\n'45 }46 }47 os.write_file(config_path(remote_file), text)!48}4950pub fn load_remote() !RemoteSettings {51 text := os.read_file(config_path(remote_file)) or {52 return error('this machine has no remote yet — run "koh remote"')53 }54 values := parse_config(text)55 settings := RemoteSettings{56 kind: values['kind'] or { '' }57 path: values['path'] or { '' }58 endpoint: values['endpoint'] or { '' }59 bucket: values['bucket'] or { '' }60 region: values['region'] or { '' }61 kepr: values['kepr'] or { '' }62 }63 if settings.kind !in [kind_folder, kind_s3] {64 return error('the remote setting in ${config_path(remote_file)} is not readable — run "koh remote" again')65 }66 return settings67}6869pub fn has_remote() bool {70 return os.is_file(config_path(remote_file))71}7273pub fn forget_remote() ! {74 if os.exists(config_path(remote_file)) {75 os.rm(config_path(remote_file))!76 }77}787980pub fn save_credentials(credentials Credentials) ! {81 os.mkdir_all(config_dir(), mode: 0o700)!82 83 os.chmod(config_dir(), 0o700)!84 mut text := '# written by koh remote — keep this file private\n'85 text += 'access_key=${credentials.access_key}\n'86 text += 'secret_key=${credentials.secret_key}\n'87 path := config_path(credentials_file)88 89 90 91 temporary := '${path}.tmp-${os.getpid()}'92 93 94 if os.exists(temporary) || os.is_link(temporary) {95 os.rm(temporary)!96 }97 mut file := os.open_file(temporary, 'w', 0o600) or {98 os.rm(temporary) or {}99 return err100 }101 os.chmod(temporary, 0o600) or {102 file.close()103 os.rm(temporary) or {}104 return err105 }106 file.write_string(text) or {107 file.close()108 os.rm(temporary) or {}109 return err110 }111 file.close()112 113 if (os.read_file(temporary) or { '' }) != text {114 os.rm(temporary) or {}115 return error('could not write ${path}')116 }117 118 if os.is_dir(path) {119 os.rm(temporary) or {}120 return error('${path} is a directory')121 }122 os.rename(temporary, path) or {123 os.rm(temporary) or {}124 return err125 }126}127128pub fn load_credentials() !Credentials {129 path := config_path(credentials_file)130 text := os.read_file(path) or {131 return error('this machine has no S3 keys yet — run "koh remote"')132 }133 134 135 if os.stat(path)!.mode & 0o077 != 0 {136 return error('${path} can be read by others — run "chmod 600 ${path}"')137 }138 values := parse_config(text)139 credentials := Credentials{140 access_key: values['access_key'] or { '' }141 secret_key: values['secret_key'] or { '' }142 }143 if credentials.access_key == '' || credentials.secret_key == '' {144 return error('the S3 keys in ${config_path(credentials_file)} are incomplete — run "koh remote" again')145 }146 return credentials147}148149fn parse_config(text string) map[string]string {150 mut values := map[string]string{}151 for line in text.split_into_lines() {152 trimmed := line.trim_space()153 if trimmed == '' || trimmed.starts_with('#') {154 continue155 }156 at := trimmed.index('=') or { continue }157 values[trimmed[..at].trim_space()] = trimmed[at + 1..].trim_space()158 }159 return values160}