╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭───────────────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯
210 const value = value_maybe orelse return error.SshListenNeedsValue; 211 options.ssh_listen = if (std.mem.eql(u8, value, "none")) null else value; 212 } 213 // urls are joined with "/" + a path 214 if (cmd_args.get("--web-url")) |value_maybe| options.web_url = std.mem.trimEnd(u8, value_maybe orelse return error.WebUrlNeedsValue, "/"); 215 if (cmd_args.get("--ssh-url")) |value_maybe| options.ssh_url = std.mem.trimEnd(u8, value_maybe orelse return error.SshUrlNeedsValue, "/"); 216 if (cmd_args.get("--max-repo-size")) |value_maybe| options.max_repo_size = try parseSize(value_maybe orelse return error.MaxRepoSizeNeedsValue); 217 if (cmd_args.get("--data-dir")) |value_maybe| options.data_dir = value_maybe orelse return error.DataDirNeedsValue; 218 return options; 219 } 220 221 // a byte count with an optional K, M or G suffix 222 fn parseSize(value: []const u8) !u64 { 223 if (value.len == 0) return error.InvalidSize; 224 const shift: u6 = switch (value[value.len - 1]) { 225 'K', 'k' => 10, 226 'M', 'm' => 20, 227 'G', 'g' => 30, 228 else => 0, 229 }; 230 const digits = if (shift == 0) value else value[0 .. value.len - 1]; 231 const count = std.fmt.parseInt(u64, digits, 10) catch return error.InvalidSize; 232 return std.math.shlExact(u64, count, shift) catch error.InvalidSize; 233 } 234 235 /// parses the given args into a command if valid, and determines how it should be run 236 /// (via the TUI or CLI). 237 pub const CommandDispatch = union(enum) { 238 invalid: union(enum) { 239 command: []const u8, 240 argument: struct { 241 command: ?CommandKind, 242 value: []const u8, 243 }, 244 }, 245 help: ?CommandKind, 246 local, 247 cli: Command, 248 249 pub fn init(cmd_args: *CommandArgs) !CommandDispatch { 250 const dispatch = try initIgnoreUnused(cmd_args); 251 if (cmd_args.unused_args.count() > 0) { 252 return .{ 253 .invalid = .{ 254 .argument = .{ 255 .command = switch (dispatch) { 256 .invalid => return dispatch, // if there was already an error, return it instead 257 .help => |cmd_kind_maybe| cmd_kind_maybe, 258 .local => null, 259 .cli => |command| command, 260 }, 261 .value = cmd_args.unused_args.keys()[0], 262 }, 263 }, 264 }; 265 } 266 return dispatch; 267 } 268 269 pub fn initIgnoreUnused(cmd_args: *CommandArgs) !CommandDispatch { 270 const show_help = cmd_args.contains("--help"); 271 272 if (cmd_args.command_kind) |command_kind| { 273 if (show_help) { 274 return .{ .help = command_kind }; 275 } else if (try Command.initMaybe(cmd_args)) |cmd| { 276 return .{ .cli = cmd }; 277 } else { 278 return .{ .help = command_kind }; 279 } 280 } else if (cmd_args.command_name) |command_name| { 281 return .{ .invalid = .{ .command = command_name } }; 282 } else if (show_help) { 283 return .{ .help = null }; 284 } else { 285 return .local; 286 } 287 } 288 }; 289