// cell qopconv - Convert QOP archive formats var fd = use('fd') var qop = use('internal/qop') function print_usage() { log.console("Usage: qopconv [OPTION...] FILE...") log.console(" -u .. unpack archive") log.console(" -l .. list contents of archive") log.console(" -d ....... change read dir when creating archives") log.console(" .. create archive from sources") } function list_archive(archive_path) { var blob = fd.slurp(archive_path) var archive = null if (!blob) { log.console("Could not open archive " + archive_path) return } var _open = function() { archive = qop.open(blob) } disruption { log.console("Could not open archive " + archive_path) return } _open() var files = archive.list() arrfor(files, function(f) { var s = archive.stat(f) // Format: index hash size path // We don't have index/hash easily available in JS binding yet, just size/path log.console(`${f} (${s.size} bytes)`) }) archive.close() } function unpack(archive_path) { var blob = fd.slurp(archive_path) var archive = null if (!blob) { log.console("Could not open archive " + archive_path) return } var _open = function() { archive = qop.open(blob) } disruption { log.console("Could not open archive " + archive_path) return } _open() var files = archive.list() arrfor(files, function(f) { var data = archive.read(f) var dir = null var parts = null var curr = null var fh = null var _mk = null if (data) { // Ensure directory exists dir = fd.dirname(f) if (dir) { // recursive mkdir parts = array(dir, '/') curr = "." arrfor(parts, function(p) { curr += "/" + p _mk = function() { fd.mkdir(curr) } disruption {} _mk() }) } fh = fd.open(f, "w") fd.write(fh, data) fd.close(fh) log.console("Extracted " + f) } }) archive.close() } function pack(sources, archive_path, read_dir) { var writer = qop.write(archive_path) var base_dir = read_dir || "." function add_recursive(path) { var full_path = base_dir + "/" + path var st = null var list = null var data = null if (path == ".") full_path = base_dir if (read_dir == null && path != ".") full_path = path st = fd.stat(full_path) if (!st) { log.console("Could not stat " + full_path) return } if (st.isDirectory) { list = fd.readdir(full_path) arrfor(list, function(item) { if (item == "." || item == "..") return var sub = path == "." ? item : path + "/" + item add_recursive(sub) }) } else { data = fd.slurp(full_path) if (data) { writer.add_file(path, data) log.console("Added " + path) } } } arrfor(sources, function(s) { add_recursive(s) }) writer.finalize() log.console("Created " + archive_path) } var sources = null var archive = null var read_dir = null var i = 0 if (!is_array(args) || length(args) < 1) { print_usage() } else { if (args[0] == "-l") { if (length(args) < 2) print_usage() else list_archive(args[1]) } else if (args[0] == "-u") { if (length(args) < 2) print_usage() else unpack(args[1]) } else { sources = [] archive = null read_dir = null i = 0 if (args[0] == "-d") { read_dir = args[1] i = 2 } for (; i < length(args) - 1; i++) { push(sources, args[i]) } archive = args[length(args) - 1] if (length(sources) == 0) { print_usage() } else { pack(sources, archive, read_dir) } } } $stop()