be090694e2
* Added progressbar display using ANSI sequences ; * Handle a new naming pattern (.xtm.*) .
148 lines
3.1 KiB
Ruby
Executable file
148 lines
3.1 KiB
Ruby
Executable file
#!/usr/bin/ruby
|
|
|
|
require 'optparse'
|
|
|
|
require 'rubygems'
|
|
require 'bindata'
|
|
|
|
require 'xtmfile/xtmheader'
|
|
|
|
|
|
class XtmJoin
|
|
class XtmJoinArgumentError < ArgumentError ; end
|
|
|
|
attr_reader :opts
|
|
|
|
BUFFER_MAX_SIZE = 4096 * 4096
|
|
|
|
def initialize args
|
|
@args = []
|
|
@input_filename = nil
|
|
parse_command_line args
|
|
end
|
|
|
|
def parse_command_line args
|
|
@args = args.clone
|
|
@opts = OptionParser.new do |opts|
|
|
opts.banner = "Usage: #{File.basename $0} [options]\n"
|
|
|
|
opts.separator ""
|
|
opts.separator "Mandatory options"
|
|
|
|
opts.on("-i", "--input FILE", "Input XTM file") do |r|
|
|
@input_filename = r
|
|
end
|
|
|
|
opts.separator ""
|
|
opts.separator "General options:"
|
|
|
|
opts.on("-h", "--help", "Show this help") do |h|
|
|
@help = h
|
|
end
|
|
opts.on("-v", "--verbose", "Show warnings too") do |v|
|
|
@verbose = v
|
|
end
|
|
opts.separator ""
|
|
end
|
|
end
|
|
|
|
def validate!
|
|
@opts.parse!
|
|
|
|
raise XtmJoinArgumentError, "No input XTM file specified!" if @input_filename.nil?
|
|
|
|
raise RuntimeError, "Current input XTM does not exist!" unless File.exist? @input_filename
|
|
raise RuntimeError, "Current input XTML is not a file!" unless File.file? @input_filename
|
|
@input_filename = File.expand_path @input_filename
|
|
end
|
|
|
|
|
|
def run
|
|
validate!
|
|
|
|
output_file = nil
|
|
# initial file
|
|
|
|
in_xtm = File.open @input_filename, "rb"
|
|
header = XtmHeader::read in_xtm
|
|
|
|
output_file = header.filename_str
|
|
puts "Writing data to %s" % output_file
|
|
|
|
# FIXME: prevent overwriting
|
|
out_xtm = File.open output_file, "wb"
|
|
|
|
cur_xtm = @input_filename
|
|
is_first = true
|
|
cur_size = header.filesize
|
|
print "\x1b[s"
|
|
while cur_size > 0 do
|
|
unless is_first then
|
|
cur_xtm = _nextfile cur_xtm
|
|
puts "Opening %s" % cur_xtm
|
|
in_xtm = File.open cur_xtm, "rb"
|
|
end
|
|
while cur_size > 0 and (not in_xtm.eof?) do
|
|
pcent = ((header.filesize - cur_size) * 100 / header.filesize)
|
|
|
|
STDOUT.print "\x1b[uProgress : %s %" % pcent
|
|
STDOUT.flush
|
|
|
|
read_size = if cur_size > BUFFER_MAX_SIZE then BUFFER_MAX_SIZE
|
|
else cur_size
|
|
end
|
|
buffer = in_xtm.read read_size
|
|
cur_size = cur_size - buffer.length
|
|
out_xtm.write buffer.slice(0, buffer.length)
|
|
end
|
|
is_first = false
|
|
in_xtm.close
|
|
end
|
|
out_xtm.close
|
|
STDOUT.puts ""
|
|
|
|
# remaining files
|
|
end
|
|
|
|
def _nextfile curfile
|
|
result = nil
|
|
cur_idx = 0
|
|
cur_len = 0
|
|
case curfile
|
|
when /\.([0-9]+)\.xtm$/ then
|
|
cur_idx = $1.to_i
|
|
cur_len = $1.length
|
|
next_idx = cur_idx + 1
|
|
result = curfile.gsub(/\.([0-9]+)\.xtm$/, ".%0#{cur_len}d.xtm" % next_idx)
|
|
when /\.xtm\.([0-9]+)$/ then
|
|
cur_idx = $1.to_i
|
|
cur_len = $1.length
|
|
next_idx = cur_idx + 1
|
|
result = curfile.gsub(/\.xtm\.([0-9]+)$/, ".xtm.%0#{cur_len}d" % next_idx)
|
|
else
|
|
raise "Unable to detect a naming patterng for file sequence!"
|
|
end
|
|
return result
|
|
end
|
|
|
|
def self.main args
|
|
xj = nil
|
|
begin
|
|
xj = XtmJoin.new args
|
|
xj.run
|
|
exit 0
|
|
rescue XtmJoinArgumentError => e
|
|
STDERR.puts "%s" % xj.opts
|
|
STDERR.puts "error: %s" % e.message
|
|
|
|
exit 1
|
|
rescue SystemExit => e
|
|
raise e
|
|
rescue Exception => e
|
|
STDERR.puts "error: %s" % e.message
|
|
exit 1
|
|
end
|
|
end
|
|
end
|
|
|
|
XtmJoin.main ARGV
|