///|
/// Everything before the last `/` or `\`, or "" when there is none.
fn dirname(path : String) -> String {
let mut cut = -1
for i in 0.. Bool {
path.has_prefix("/") ||
path.has_prefix("\\") ||
(path.length() >= 2 && path[1] == ':' && path[0] is ('a'..<='z' | 'A'..<='Z'))
}
///|
/// Resolve `path` relative to `base` (a directory, "" for the current one).
fn join_path(base : String, path : String) -> String {
if base == "" || is_absolute(path) {
path
} else if base.has_suffix("/") {
base + path
} else {
base + "/" + path
}
}
///|
fn describe_io(error : @fs.IOError, what : String) -> String {
match error {
IOError(message) => "\{what}: \{message}"
}
}
///|
fn read_bytes(path : String) -> Bytes raise CliError {
@fs.read_file_to_bytes(path) catch {
err => raise Failed(describe_io(err, "cannot read \"\{path}\""))
}
}
///|
fn write_bytes(path : String, data : Bytes) -> Unit raise CliError {
@fs.write_bytes_to_file(path, data) catch {
err => raise Failed(describe_io(err, "cannot write \"\{path}\""))
}
}
///|
/// Create `path` when it does not exist yet.
fn ensure_dir(path : String) -> Unit raise CliError {
if path == "" || path == "." || path == "/" || @fs.path_exists(path) {
return
}
let parent = dirname(path)
if parent != path {
ensure_dir(parent)
}
@fs.create_dir(path) catch {
err => raise Failed(describe_io(err, "cannot create directory \"\{path}\""))
}
}
///|
/// `SOURCE_DATE_EPOCH` as a timestamp, if set. See
/// https://reproducible-builds.org/specs/source-date-epoch/
fn source_date_epoch() -> Int64? raise CliError {
match @env.get_env_var("SOURCE_DATE_EPOCH") {
None | Some("") => None
Some(text) => {
let mut value = 0L
if text.length() > 15 {
raise Failed(
"SOURCE_DATE_EPOCH must be a non-negative integer, got \"\{text}\"",
)
}
for c in text {
guard c is ('0'..<='9') else {
raise Failed(
"SOURCE_DATE_EPOCH must be a non-negative integer, got \"\{text}\"",
)
}
value = value * 10L + (c.to_int() - '0'.to_int()).to_int64()
}
Some(value)
}
}
}