5 trap('INT') { exit
130 }
6 trap('PIPE') { exit
0 }
8 # this is to be compatible with config files used by the Perl tools
9 def parse_config_file
!(path
, overwrite
= false)
11 File
.open(path
).each_line
do |line
|
13 if /^(domain|class)\s*=\s*(\S+)/.match(line
)
15 elsif m
= /^(?:trackers|hosts)\s*=\s*(.*)/.match(line
)
16 dest
[:hosts] = $1.split(/\s*,\s*/)
18 STDERR.puts
"Ignored configuration line: #{line}" unless /^#/.match(line
)
24 # parse the default config file if one exists
25 def_file
= File
.expand_path("~/.mogilefs-client.conf")
26 def_cfg
= File
.exist
?(def_file
) ? parse_config_file
!(def_file
) : {}
28 # parse the command-line first, these options take precedence over all else
34 x
.banner
= "Usage: #{$0} [options] <command> [<arguments>]"
37 x
.on('-c', '--config=/path/to/config',
38 'config file to load') { |file
| config_file
= file
}
40 x
.on('-t', '--trackers=host1[,host2]', '--hosts=host1[,host2]', Array
,
41 'hostnames/IP addresses of trackers') do |trackers
|
42 cli_cfg
[:hosts] = trackers
45 x
.on('-C', '--class=s', 'class') { |klass
| cli_cfg
[:class] = klass
}
46 x
.on('-d', '--domain=s', 'domain') { |domain
| cli_cfg
[:domain] = domain
}
47 x
.on('-l', "long listing format (`ls' command)") { ls_l
= true }
48 x
.on('-h', '--human-readable',
49 "print sizes in human-readable format (`ls' command)") { ls_h
= true }
52 x
.on('--help', 'Show this help message.') { puts x
; exit
}
56 # parse the config file specified at the command-line
57 file_cfg
= config_file
? parse_config_file
!(config_file
, true) : {}
59 # read environment variables, too. This Ruby API favors the term
60 # "hosts", however upstream MogileFS teminology favors "trackers" instead.
61 # Favor the term more consistent with what the MogileFS inventors used.
63 if ENV["MOG_TRACKERS"]
64 env_cfg
[:hosts] = ENV["MOG_TRACKERS"].split(/\s*,\s*/)
66 if ENV["MOG_HOSTS"] && env_cfg
[:hosts].empty
?
67 env_cfg
[:hosts] = ENV["MOG_HOSTS"].split(/\s*,\s*/)
69 env_cfg
[:domain] = ENV["MOG_DOMAIN"] if ENV["MOG_DOMAIN"]
70 env_cfg
[:class] = ENV["MOG_CLASS"] if ENV["MOG_CLASS"]
72 # merge the configs, favoring them in order specified:
73 cfg
= {}.merge(def_cfg
).merge(env_cfg
).merge(file_cfg
).merge(cli_cfg
)
77 err
<< "trackers must be specified" if cfg
[:hosts].nil? || cfg
[:hosts].empty
?
78 err
<< "domain must be specified" unless cfg
[:domain]
80 STDERR.puts
"Errors:\n #{err.join("\n ")}"
81 STDERR.puts
ARGV.options
85 unless cmd
= ARGV.shift
86 STDERR.puts
ARGV.options
90 include MogileFS
::Util
91 mg
= MogileFS
::MogileFS.new(cfg
)
96 filename
= ARGV.shift
or raise ArgumentError
, '<filename> <key>'
97 key
= ARGV.shift
or raise ArgumentError
, '<filename> <key>'
98 ARGV.shift
and raise ArgumentError
, '<filename> <key>'
99 cfg
[:class] or raise ArgumentError
, 'E: --class must be specified'
100 mg
.store_file(key
, cfg
[:class], filename
)
102 ARGV.empty
? and raise ArgumentError
, '<key1> [<key2> ...]'
103 ARGV.each
{ |key
| mg
.get_file_data(key
) { |fp
| sysrwloop(fp
, STDOUT) } }
105 prefixes
= ARGV.empty
? ? [ nil ] : ARGV
106 prefixes
.each
do |prefix
|
107 mg
.each_key(prefix
) do |key
|
109 path_nr
= "% 2d" % mg
.get_paths(key
).size
111 if ls_h
&& size
> 1024
113 %w(K M G
).each
do |s
|
116 break if size
<= 1024
118 size
= sprintf("%.1f%s", size
, suff
)
122 size
= (' ' * (12 - size
.length
)) << size
# right justify
123 puts
[ path_nr
, size
, key
].pack("A4 A16 A32")
130 ARGV.empty
? and raise ArgumentError
, '<key1> [<key2>]'
131 ARGV.each
{ |key
| mg
.delete(key
) }
133 from
= ARGV.shift
or raise ArgumentError
, '<from> <to>'
134 to
= ARGV.shift
or raise ArgumentError
, '<from> <to>'
135 ARGV.shift
and raise ArgumentError
, '<from> <to>'
137 when 'stat' # this outputs a RFC822-like format
138 ARGV.empty
? and raise ArgumentError
, '<key1> [<key2>]'
139 ARGV.each_with_index
do |key
, i
|
140 if size
= mg
.size(key
)
143 mg
.get_paths(key
).each_with_index
do |path
,i
|
144 puts
"URL-#{i}: #{path}"
148 STDERR.puts
"No such key: #{key}"
153 key
= ARGV.shift
or raise ArgumentError
, '<key>'
154 ARGV.shift
and raise ArgumentError
, '<key>'
155 cfg
[:class] or raise ArgumentError
, 'E: --class must be specified'
157 tmp
= Tempfile
.new('mog-tee') # TODO: explore Transfer-Encoding:chunked :)
158 at_exit
{ tmp
.unlink
}
160 sysrwloop(STDIN, tmp
)
161 mg
.store_file(key
, cfg
[:class], tmp
.path
)
166 raise ArgumentError
, "Unknown command: #{cmd}"
168 rescue ArgumentError
=> err
169 STDERR.puts
"Usage: #{$0} #{cmd} #{err.message}"