///|
/// Map compact UUID handles to lowercase filenames on case-insensitive filesystems.
/// Historical job IDs retain their original filenames.
pub fn job_storage_name(id : String) -> String {
guard id.length() == 22 else { return id }
let encoded = id.replace_all(old="-", new="+").replace_all(old="_", new="/")
let bytes = @base64.decode(encoded + "==") catch { _ => return id }
guard bytes.length() == 16 else { return id }
"uuid-" + @hex.encode(bytes)
}
///|
/// Recover a compact job handle from its reversible on-disk name.
pub fn job_id_from_storage(name : String) -> String {
guard name.length() == 37 && name.has_prefix("uuid-") else { return name }
let bytes = @hex.decode(name[5:]) catch { _ => return name }
@base64.encode(bytes, padding=false)
.replace_all(old="+", new="-")
.replace_all(old="/", new="_")
}
///|
test "compact job filenames distinguish case and preserve legacy IDs" {
let upper = "AZTjwQBAeryN7wEjRWeJqw"
let lower = "AZTjwQBaeryN7wEjRWeJqw"
assert_true(job_storage_name(upper) != job_storage_name(lower))
for id in [upper, lower, "0194e3c1-2345-7abc-8def-0123456789ab", "bg-1"] {
let name = job_storage_name(id)
assert_eq(name, name.to_lower())
assert_eq(job_id_from_storage(name), id)
assert_true(valid_job_component(name))
}
}