///|
async fn main {
let mut args = @env.args()
let password = if args.length() >= 3 && args[1] == "--password-env" {
let name = args[2]
let secret = @env.get_env_var(name)
guard secret is Some(_) else {
fail("password environment variable is not set: " + name)
}
args = [args[0]] + args[3:].to_owned()
secret
} else {
None
}
if sfx_command(args, password) {
return
}
if volume_command(args, password) {
return
}
if source_command(args, password) {
return
}
if source_compare_command(args, password) {
return
}
if source_volumes_command(args, password) {
return
}
if source_sfx_command(args, password) {
return
}
if args.length() == 4 && args[1] == "audit" && args[2] == "--json" {
let archive = @host.open_file(args[3], password?)
println(archive.audit().to_json().stringify())
return
}
if args.length() == 5 && args[1] == "diff" && args[2] == "--json" {
let left = @host.open_file(args[3], password?)
let right = @host.open_file(args[4], password?)
println(left.compare(right).to_json().stringify())
return
}
if args.length() >= 7 &&
args[1] == "extract-selected" &&
args[2] == "--contents-only" {
let archive = @host.open_file(args[3], password?)
let ids = args[6:].map(id => @string.parse_int(id))
let exported = @host.export_selected(
archive,
ids,
parent=args[4],
name=args[5],
)
println(
"Exported \{exported.entries.length()} selected entries to \{exported.directory}; only selected folders were verified and metadata was not applied",
)
return
}
if args.length() >= 3 &&
(args[1] == "list" || args[1] == "test") &&
args[2] == "--json" {
let strict = args.length() == 5 &&
args[1] == "test" &&
args[3] == "--require-member-crcs"
guard args.length() == 4 || strict else {
fail(
"usage: list --json archive.7z OR test --json [--require-member-crcs] archive.7z",
)
}
let archive = @host.open_file(args[if strict { 4 } else { 3 }], password?)
let document = if args[1] == "list" {
archive.inventory_json()
} else {
archive.verify(require_member_crcs=strict).to_json()
}
println(document.stringify())
return
}
if args.length() == 4 &&
args[1] == "test" &&
args[2] == "--require-member-crcs" {
let archive = @host.open_file(args[3], password?)
let report = archive.verify(require_member_crcs=true) catch {
err => fail(err.to_string())
}
println(Repr(report))
return
}
if args.length() == 6 && args[1] == "read-range" {
let archive = @host.open_file(args[2], password?)
let id = @string.parse_int(args[3])
let offset = @string.parse_int(args[4])
let length = @string.parse_int(args[5])
let bytes = archive.reader().read_range(id, offset~, length~)
@stdio.stdout.write(bytes)
return
}
if args.length() == 4 && args[1] == "read" {
let archive = @host.open_file(args[2], password?)
let id = @string.parse_int(args[3])
let item = archive.reader().read(id)
guard item.entry.kind == File else {
fail("selected entry is a directory; select a file ID")
}
@stdio.stdout.write(item.bytes)
return
}
if args.length() == 6 && args[1] == "extract" && args[2] == "--contents-only" {
let archive = @host.open_file(args[3], password?)
let exported = @host.export_contents(archive, parent=args[4], name=args[5])
println(
"Exported \{exported.entries.length()} entries to \{exported.directory}; timestamps and attributes were not applied",
)
return
}
guard args.length() == 3 && (args[1] == "list" || args[1] == "test") else {
fail(
"usage: moon run app -- [--json] archive.7z OR audit --json archive.7z OR diff --json left.7z right.7z OR test [--json] --require-member-crcs archive.7z OR read archive.7z entry-id OR read-range archive.7z entry-id offset length OR extract --contents-only archive.7z existing-parent new-name OR extract-selected --contents-only archive.7z existing-parent new-name entry-id...",
)
}
let archive = @host.open_file(args[2], password?)
if args[1] == "list" {
for entry in archive.entries() {
let semantics = if entry.anti {
"\tanti-item"
} else if entry.semantics() != Regular {
"\t" + Repr(entry.semantics()).to_string()
} else {
""
}
println(
"\{entry.id}\t\{entry.size}\t\{Repr(entry.kind)}\t\{Repr(entry.name)}\{semantics}",
)
}
} else {
let report = archive.verify() catch { err => fail("\{Repr(err)}") }
println(Repr(report))
}
}