///|
fn parse_mode(text : String) -> Int raise {
let digits = if text.has_prefix("0o") || text.has_prefix("0O") {
text[2:].to_owned()
} else {
text
}
if digits == "" {
fail("empty mode")
}
let mut value = 0
for digit in digits {
if !(digit is ('0'..='7')) {
fail("invalid mode")
}
value = value * 8 + digit.to_int() - '0'.to_int()
if value > 0o7777 {
fail("mode out of range")
}
}
value
}
///|
async fn main {
let args = @env.args()[1:]
let parsed = @cli.parse(args, [
@cli.flag("parents", short='p'),
@cli.option("mode", short='m'),
@cli.flag("verbose", short='v'),
@cli.flag("help"),
]) catch {
@cli.CliError(option~, message~, ..) => {
@stdio.stderr.write("mkdir: \{message}: '\{option}'\n")
@sys.exit(2)
return
}
}
if parsed.contains("help") {
@stdio.stdout.write("Usage: mkdir [-p] [-m MODE] [-v] DIRECTORY...\n")
return
}
let permission = match parsed.last_value("mode") {
Some(value) =>
parse_mode(value) catch {
_ => {
@stdio.stderr.write("mkdir: invalid mode: '\{value}'\n")
@sys.exit(1)
return
}
}
None => 0o755
}
let directories = parsed.operands
let parents = parsed.contains("parents")
let verbose = parsed.contains("verbose")
if directories.is_empty() {
@stdio.stderr.write("mkdir: missing operand\n")
@sys.exit(1)
return
}
let mut failed = false
for directory in directories {
let created = try {
match @fsops.kind_if_exists(directory) {
Some(Directory) if parents => false
Some(_) => fail("path already exists")
None => {
@fs.mkdir(directory, permission~, recursive=parents)
true
}
}
} catch {
err => {
@stdio.stderr.write("mkdir: cannot create '\{directory}': \{err}\n")
failed = true
false
}
}
if created && verbose {
@stdio.stdout.write("mkdir: created directory '\{directory}'\n")
}
}
if failed {
@sys.exit(1)
}
}