rbbt-util 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,200 @@
1
+ require 'rbbt/util/cmd'
2
+ require 'rbbt/util/misc'
3
+ require 'rbbt/util/tmpfile'
4
+
5
+ require 'zlib'
6
+ require 'digest/md5'
7
+
8
+ module Open
9
+ class OpenURLError < StandardError; end
10
+ class OpenGzipError < StandardError; end
11
+
12
+ REMOTE_CACHEDIR = "/tmp/open_cache"
13
+ FileUtils.mkdir REMOTE_CACHEDIR unless File.exist? REMOTE_CACHEDIR
14
+
15
+ def self.cachedir=(cachedir)
16
+ REMOTE_CACHEDIR.replace cachedir
17
+ FileUtils.mkdir REMOTE_CACHEDIR unless File.exist? REMOTE_CACHEDIR
18
+ end
19
+
20
+ def self.cachedir
21
+ REMOTE_CACHEDIR
22
+ end
23
+
24
+ # Remote WGET
25
+ LAST_TIME = {}
26
+ def self.wait(lag, key = nil)
27
+ time = Time.now
28
+
29
+ if LAST_TIME[key] != nil && (time < LAST_TIME[key] + lag)
30
+ sleep (LAST_TIME[key] + lag) - time
31
+ end
32
+
33
+ LAST_TIME[key] = Time.now
34
+ end
35
+
36
+ def self.wget(url, options = {})
37
+ options = Misc.add_defaults options, "--user-agent=" => 'firefox', :pipe => true
38
+
39
+ wait(options[:nice], options[:nice_key]) if options[:nice]
40
+ options.delete(:nice)
41
+ options.delete(:nice_key)
42
+
43
+ pipe = options.delete(:pipe)
44
+ quiet = options.delete(:quiet)
45
+ options["--quiet"] = quiet if options["--quiet"].nil?
46
+
47
+ stderr = case
48
+ when options['stderr']
49
+ options['stderr']
50
+ when options['--quiet']
51
+ false
52
+ else
53
+ nil
54
+ end
55
+ begin
56
+ CMD.cmd("wget '#{ url }'", options.merge(
57
+ '-O' => '-',
58
+ :pipe => pipe,
59
+ :stderr => stderr
60
+ ))
61
+ rescue
62
+ STDERR.puts $!.backtrace.inspect
63
+ raise OpenURLError, "Error reading remote url: #{ url }.\n#{$!.message}"
64
+ end
65
+ end
66
+
67
+ # Cache
68
+
69
+ def self.in_cache(url, options = {})
70
+ digest = Digest::MD5.hexdigest(url)
71
+
72
+ filename = File.join(REMOTE_CACHEDIR, digest)
73
+ if File.exists? filename
74
+ return filename
75
+ else
76
+ nil
77
+ end
78
+ end
79
+
80
+ def self.add_cache(url, data, options = {})
81
+ digest = Digest::MD5.hexdigest(url)
82
+ Misc.sensiblewrite(File.join(REMOTE_CACHEDIR, digest), data)
83
+ end
84
+
85
+ # Grep
86
+
87
+ def self.grep(stream, grep)
88
+ case
89
+ when Array === grep
90
+ TmpFile.with_file(grep * "\n", false) do |f|
91
+ CMD.cmd("grep", "-F" => true, "-f" => f, :in => stream, :pipe => true, :post => proc{FileUtils.rm f})
92
+ end
93
+ else
94
+ CMD.cmd("grep '#{grep}' -", :in => stream, :pipe => true)
95
+ end
96
+ end
97
+
98
+ def self.file_open(file, grep)
99
+ if grep
100
+ grep(File.open(file), grep)
101
+ else
102
+ File.open(file)
103
+ end
104
+ end
105
+
106
+ # Decompression
107
+
108
+ def self.gunzip(stream)
109
+ if String === stream
110
+ Zlib::Inflate.inflate(stream)
111
+ else
112
+ CMD.cmd("gunzip", :pipe => true, :in => stream)
113
+ end
114
+ end
115
+
116
+ def self.unzip(stream)
117
+ TmpFile.with_file(stream.read) do |filename|
118
+ StringIO.new(CMD.cmd("unzip '{opt}' #{filename}", "-p" => true, :pipe => true).read)
119
+ end
120
+ end
121
+
122
+ # Questions
123
+
124
+ def self.remote?(file)
125
+ !! (file =~ /^(?:https?|ftp):\/\//)
126
+ end
127
+
128
+ def self.gzip?(file)
129
+ !! (file =~ /\.gz$/)
130
+ end
131
+
132
+ def self.zip?(file)
133
+ !! (file =~ /\.zip/)
134
+ end
135
+
136
+ # Open Read Write
137
+
138
+ def self.open(url, options = {})
139
+ options = Misc.add_defaults options, :noz => false
140
+
141
+ wget_options = options[:wget_options] || {}
142
+ wget_options[:nice] = options.delete(:nice)
143
+ wget_options[:nice_key] = options.delete(:nice_key)
144
+
145
+ io = case
146
+ when (not remote?(url))
147
+ file_open(url, options[:grep])
148
+ when options[:nocache]
149
+ wget(url, wget_options)
150
+ when in_cache(url)
151
+ file_open(in_cache(url), options[:grep])
152
+ else
153
+ io = wget(url, wget_options)
154
+ add_cache(url, io)
155
+ io.close
156
+ file_open(in_cache(url), options[:grep])
157
+ end
158
+ io = unzip(io) if zip? url and not options[:noz]
159
+ io = gunzip(io) if gzip? url and not options[:noz]
160
+
161
+ io
162
+ end
163
+
164
+ def self.read(file, options = {}, &block)
165
+ f = open(file, options)
166
+
167
+ if block_given?
168
+ while l = Misc.fixutf8(f.gets)
169
+ l = fixutf8(l) if l.respond_to?(:valid_encoding?) && ! l.valid_encoding?
170
+ yield l
171
+ end
172
+ else
173
+ Misc.fixutf8(f.read)
174
+ end
175
+ end
176
+
177
+ def self.write(file, content)
178
+ if String === content
179
+ File.open(file, 'w') do |f| f.write content end
180
+ else
181
+ File.open(file, 'w') do |f|
182
+ while l = content.gets
183
+ f.write l
184
+ end
185
+ end
186
+ content.close
187
+ end
188
+ end
189
+ end
190
+
191
+ if __FILE__ == $0
192
+ require 'benchmark'
193
+ require 'progress-monitor'
194
+
195
+ file = '/home/mvazquezg/rbbt/data/dbs/entrez/gene_info'
196
+ puts Benchmark.measure {
197
+ #Open.open(file).read.split(/\n/).each do |l| l end
198
+ Open.read(file) do |l| l end
199
+ }
200
+ end
@@ -0,0 +1,78 @@
1
+ require 'yaml'
2
+
3
+ module PKGConfig
4
+ class NoConfig < Exception; end
5
+ class NoVariables < Exception; end
6
+
7
+ class RootdirNotFoundError < StandardError; end
8
+
9
+ def self.rootdir_for_file(file = __FILE__)
10
+ dir = File.expand_path(File.dirname file)
11
+
12
+ while not File.exists?(File.join(dir, 'lib')) and dir != '/'
13
+ dir = File.dirname(dir)
14
+ end
15
+
16
+ if File.exists? File.join(dir, 'lib')
17
+ dir
18
+ else
19
+ raise RootdirNotFoundError
20
+ end
21
+ end
22
+
23
+ def self.get_caller_rootdir
24
+ caller.each do |line|
25
+ next if line =~ /\/pkg_config\.rb/
26
+ begin
27
+ return PKGConfig.rootdir_for_file(line)
28
+ rescue RootdirNotFoundError
29
+ end
30
+ end
31
+ raise RootdirNotFoundError
32
+ end
33
+
34
+
35
+ def self.extended(base)
36
+ base.module_eval{ @@rootdir = PKGConfig.get_caller_rootdir}
37
+ end
38
+
39
+ def rootdir
40
+ @@rootdir
41
+ end
42
+
43
+ def load_config(file, pkg_variables)
44
+ config = YAML.load_file(file)
45
+
46
+ pkg_variables.each do |variable|
47
+ self.send("#{variable}=", config[variable])
48
+ end
49
+ end
50
+
51
+ def load_cfg(pkg_variables, default = nil)
52
+ pkg_cfg_files = [ ENV['RBBT_CONFIG'] || "",
53
+ File.join(ENV["HOME"], '.' + self.to_s),
54
+ File.join('/etc/', '.' + self.to_s)]
55
+
56
+ pkg_variables.each do |variable|
57
+ self.class_eval %{
58
+ def self.#{variable}
59
+ @#{variable}
60
+ end
61
+ def self.#{variable}=(value)
62
+ @#{variable} = value
63
+ end
64
+ }
65
+ end
66
+
67
+ file = pkg_cfg_files.select{|file| File.exists? file}.first
68
+ if file.nil?
69
+ if default
70
+ file = pkg_cfg_files[1]
71
+ Open.write(file, default)
72
+ else
73
+ raise NoConfig, "No config file found. [#{pkg_cfg_files * ", "}]" if file.nil?
74
+ end
75
+ end
76
+ load_config file, pkg_variables
77
+ end
78
+ end
@@ -0,0 +1,110 @@
1
+ require 'rbbt/util/open'
2
+ require 'rbbt/util/tsv'
3
+ require 'rbbt/util/log'
4
+ require 'rake'
5
+
6
+ module PKGData
7
+ FILES = {} unless defined? FILES
8
+ class SharedirNotFoundError < StandardError; end
9
+
10
+ def self.sharedir_for_file(file = __FILE__)
11
+ dir = File.expand_path(File.dirname file)
12
+
13
+ while not File.exists?(File.join(dir, 'lib')) and dir != '/'
14
+ dir = File.dirname(dir)
15
+ end
16
+
17
+ if File.exists? File.join(dir, 'lib')
18
+ File.join(dir, 'share')
19
+ else
20
+ raise SharedirNotFoundError
21
+ end
22
+ end
23
+
24
+ def self.get_caller_sharedir
25
+ caller.each do |line|
26
+ next if line =~ /\/data_module\.rb/ or line =~ /\/pkg_data\.rb/
27
+ begin
28
+ return PKGData.sharedir_for_file(line)
29
+ rescue SharedirNotFoundError
30
+ end
31
+ end
32
+ raise SharedirNotFoundError
33
+ end
34
+
35
+ def run_rake(path, dir, task = nil)
36
+ rakefile = File.join(dir, 'Rakefile')
37
+ return nil unless File.exists? rakefile
38
+ if task.nil?
39
+ task ||= :default
40
+ else
41
+ task.sub!(/\/$/,'') if String === task
42
+ path = File.dirname(path)
43
+ end
44
+
45
+ load rakefile
46
+ old_dir = FileUtils.pwd
47
+ begin
48
+ FileUtils.mkdir_p path
49
+ FileUtils.chdir path
50
+ Rake::Task[task].invoke
51
+ Rake::Task[task].reenable
52
+ ensure
53
+ FileUtils.chdir old_dir
54
+ end
55
+ true
56
+ end
57
+
58
+ def get_datafile(file, path, get, sharedir)
59
+ Log.log "Getting data file '#{ file }' into '#{ path }'. Get: #{get.to_s}"
60
+
61
+ FileUtils.mkdir_p File.dirname(path) unless File.exists?(File.dirname(path))
62
+
63
+ case
64
+ when get.nil?
65
+ load File.join(sharedir, 'install', file)
66
+
67
+ when Proc === get
68
+ Open.write(path, get.call(file, path))
69
+
70
+ when TSV === get
71
+ Open.write(path, get.to_s)
72
+
73
+ when String === get
74
+ install_dir =File.expand_path(File.join(sharedir, 'install'))
75
+ rake_dir = File.join(install_dir, File.dirname(get), file)
76
+ rake_task = nil
77
+
78
+ until rake_dir == install_dir
79
+ return if run_rake(path, rake_dir, rake_task)
80
+ rake_task = File.join(File.basename(rake_dir), rake_task || "")
81
+ rake_dir = File.dirname(rake_dir)
82
+ end
83
+
84
+ if (File.exists?(File.join(sharedir, get)) and not File.directory?(File.join(sharedir, get)))
85
+ Open.write(path, Open.open(File.join(sharedir, get)))
86
+ else
87
+ Open.write(path, Open.open(get, :wget_options => {:pipe => true}, :nocache => true))
88
+ end
89
+ end
90
+ end
91
+
92
+ def add_datafiles(files = {})
93
+ files.each do |file, info|
94
+ subpath, get, sharedir = info
95
+
96
+ path = File.join(datadir, subpath.to_s, file.to_s)
97
+
98
+ if not File.exists?(path)
99
+ sharedir ||= PKGData.get_caller_sharedir
100
+ get_datafile(file.to_s, path, get, sharedir)
101
+ end
102
+
103
+ FILES[file.to_s] = path
104
+ end
105
+ end
106
+
107
+ def find_datafile(file)
108
+ FILES[file.to_s]
109
+ end
110
+ end
@@ -0,0 +1,130 @@
1
+ require 'rbbt/util/open'
2
+ require 'rbbt/util/tsv'
3
+ require 'rbbt/util/log'
4
+ require 'rbbt/util/cmd'
5
+ require 'rake'
6
+
7
+ module PKGSoftware
8
+ SOFTWARE = {} unless defined? SOFTWARE
9
+
10
+ class SharedirNotFoundError < StandardError; end
11
+
12
+ def self.sharedir_for_file(file = __FILE__)
13
+ dir = File.expand_path(File.dirname file)
14
+
15
+ while not File.exists?(File.join(dir, 'lib')) and dir != '/'
16
+ dir = File.dirname(dir)
17
+ end
18
+
19
+ if File.exists? File.join(dir, 'lib')
20
+ File.join(dir, 'share')
21
+ else
22
+ raise SharedirNotFoundError
23
+ end
24
+ end
25
+
26
+ def self.get_caller_sharedir
27
+ caller.each do |line|
28
+ next if line =~ /\/data_module\.rb/ or line =~ /\/pkg_software\.rb/
29
+ begin
30
+ return PKGData.sharedir_for_file(line)
31
+ rescue SharedirNotFoundError
32
+ end
33
+ end
34
+ raise SharedirNotFoundError
35
+ end
36
+
37
+ def software_dir
38
+ File.join(datadir, 'software')
39
+ end
40
+
41
+ def opt_dir
42
+ File.join(software_dir, 'opt')
43
+ end
44
+
45
+ def bin_dir
46
+ File.join(opt_dir, 'bin')
47
+ end
48
+
49
+
50
+ def get_pkg(pkg, path, get, sharedir)
51
+ Log.log "Getting software '#{ pkg }' into '#{ path }'. Get: #{get.to_s}"
52
+
53
+ FileUtils.mkdir_p File.dirname(path) unless File.exists?(File.dirname(path))
54
+
55
+ if get.nil? or get.empty?
56
+ CMD.cmd("#{File.join(sharedir, 'install', 'software', pkg)} #{File.join(Rbbt.rootdir, 'share/install/software/lib', 'install_helpers')} #{software_dir}", :stderr => Log::HIGH)
57
+ else
58
+ CMD.cmd("#{File.join(sharedir, 'install', 'software', get)} #{File.join(Rbbt.rootdir, 'share/install/software/lib', 'install_helpers')} #{software_dir}")
59
+ end
60
+ end
61
+
62
+ def add_software(pkgs = {})
63
+ pkgs.each do |pkg, info|
64
+ subpath, get, sharedir = info
65
+
66
+ setup_env(software_dir)
67
+
68
+ path = File.join(opt_dir, subpath.to_s, pkg.to_s)
69
+
70
+ if not File.exists?(path)
71
+ sharedir ||= PKGSoftware.get_caller_sharedir
72
+ get_pkg(pkg.to_s, path, get, sharedir)
73
+ end
74
+
75
+ SOFTWARE[pkg.to_s] = path
76
+ end
77
+ end
78
+
79
+ def find_software(pkg)
80
+ SOFTWARE[pkg.to_s]
81
+ end
82
+
83
+
84
+ def setup_env(software_dir)
85
+ Misc.env_add 'PATH', bin_dir
86
+
87
+ FileUtils.mkdir_p opt_dir unless File.exists? opt_dir
88
+ %w(.ld-paths .pkgconfig-paths .aclocal-paths .java-classpaths).each do |file|
89
+ filename = File.join(opt_dir, file)
90
+ FileUtils.touch filename unless File.exists? filename
91
+ end
92
+
93
+ if not File.exists? File.join(opt_dir,'.post_install')
94
+ Open.write(File.join(opt_dir,'.post_install'),"#!/bin/bash\n")
95
+ end
96
+
97
+ Open.read(File.join opt_dir, '.ld-paths').split(/\n/).each do |line|
98
+ Misc.env_add('LD_LIBRARY_PATH',line.chomp)
99
+ Misc.env_add('LD_RUN_PATH',line.chomp)
100
+ end
101
+
102
+ Open.read(File.join opt_dir, '.pkgconfig-paths').split(/\n/).each do |line|
103
+ Misc.env_add('PKG_CONFIG_PATH',line.chomp)
104
+ end
105
+
106
+ Open.read(File.join opt_dir, '.ld-paths').split(/\n/).each do |line|
107
+ Misc.env_add('LD_LIBRARY_PATH',line.chomp)
108
+ end
109
+
110
+ Open.read(File.join opt_dir, '.ld-paths').split(/\n/).each do |line|
111
+ Misc.env_add('LD_LIBRARY_PATH',line.chomp)
112
+ end
113
+
114
+ Open.read(File.join opt_dir, '.aclocal-paths').split(/\n/).each do |line|
115
+ Misc.env_add('ACLOCAL_FLAGS', "-I#{File.join(opt_dir, line.chomp)}", ' ')
116
+ end
117
+
118
+ Open.read(File.join opt_dir, '.java-classpaths').split(/\n/).each do |line|
119
+ Misc.env_add('CLASSPATH', "#{File.join(opt_dir,'java', 'lib', line.chomp)}")
120
+ end
121
+
122
+ Dir.glob(File.join opt_dir, 'jars', '*').each do |file|
123
+ Misc.env_add('CLASSPATH', "#{File.expand_path(file)}")
124
+ end
125
+
126
+ File.chmod 0774, File.join(opt_dir, '.post_install')
127
+
128
+ CMD.cmd(File.join(opt_dir, '.post_install'))
129
+ end
130
+ end
@@ -0,0 +1,92 @@
1
+ # This class helps designing DSL in ruby based on method_missing. Class
2
+ # is initialize with a block of code or a file with the code, and it is
3
+ # given a method to be invoked instead of method missing. This class
4
+ # deals simply with making the method_missing alias and removing it and
5
+ # executing the block of file with code.
6
+ module SimpleDSL
7
+
8
+ class ConfigFileMissingError < StandardError; end
9
+ class NoRuby2Ruby < StandardError; end
10
+
11
+ private
12
+
13
+ def hook_method(method = nil)
14
+ method ||= :DSL_action
15
+ @@restore_name = ("restore_DSL_" + method.to_s).to_sym
16
+ @@method_name = method.to_sym
17
+
18
+ class << self
19
+ @restore_stack ||= []
20
+ @restore_stack << @@restore_name
21
+ alias_method(@@restore_name, :method_missing)
22
+ alias_method(:method_missing, @@method_name)
23
+ end
24
+ end
25
+
26
+ def unhook_method
27
+ class << self
28
+ alias_method(:method_missing, @restore_stack.pop)
29
+ end
30
+ end
31
+
32
+ public
33
+
34
+ def parse(method = nil, actions = nil, &block)
35
+
36
+ actions ||= block
37
+
38
+ hook_method(method)
39
+
40
+ # Execute
41
+ if actions.is_a? Proc
42
+ begin
43
+ require 'parse_tree_extensions'
44
+ require 'parse_tree'
45
+ require 'ruby2ruby'
46
+ @config[@@method_name] = actions.to_ruby.collect[1..-2].join
47
+ rescue Exception
48
+ @config[@@method_name] = NoRuby2Ruby.new "The gem ruby2ruby is not installed. It will not work on ruby 1.9."
49
+ end
50
+
51
+ instance_eval &actions
52
+ elsif File.exists?(actions)
53
+
54
+ @config[@@method_name] = File.open(actions).read
55
+
56
+ eval File.open(actions).read
57
+ end
58
+
59
+ unhook_method
60
+
61
+ end
62
+
63
+
64
+ # Processes a DSL. +method+ is the name of the method executed instead
65
+ # of method_missing. The code to be evaluated as a DSL is either
66
+ # specified in +&block+ or in the file pointed by +file+.
67
+ def load_config(method = nil, file = nil, &block)
68
+ @config = {}
69
+ if file
70
+ raise ConfigFileMissingError.new "File '#{ file }' is missing. Have you installed the config files? (use rbbt_config)." unless File.exists? file
71
+ parse(method, file)
72
+ end
73
+
74
+ if block
75
+ parse(method, block)
76
+ end
77
+ end
78
+
79
+ def config(action = nil)
80
+ if action
81
+ config = @config[action.to_sym]
82
+ else
83
+ config = @config[:DSL_action]
84
+ end
85
+
86
+ raise config if NoRuby2Ruby === config
87
+
88
+ config
89
+ end
90
+ end
91
+
92
+
@@ -0,0 +1,56 @@
1
+ module SOPT
2
+ def self.name(info)
3
+ (info[:long] || info[:short]).sub(/^-*/,'')
4
+ end
5
+
6
+ def self.parse(opts)
7
+ info = {}
8
+ opts.split(/:/).each do |opt|
9
+ short, long = opt.sub(/\*$/,'').split('--').values_at(0,1)
10
+ i= {
11
+ :arg => !opt.match(/\*$/).nil?,
12
+ }
13
+ i[:short] = short unless short.nil? || short.empty?
14
+ i[:long] = '--' + long unless long.nil? || long.empty?
15
+ info[name(i)] = i
16
+ end
17
+
18
+ info
19
+ end
20
+
21
+ def self.get(opts)
22
+ info = parse(opts)
23
+
24
+ switches = {}
25
+ info.each do |name, i|
26
+ switches[i[:short]] = name if i[:short]
27
+ switches[i[:long]] = name if i[:long]
28
+ end
29
+
30
+ options = Hash.new(false)
31
+ rest = []
32
+
33
+ index = 0
34
+ while index < ARGV.length do
35
+ arg = ARGV[index]
36
+ if switches.include? arg
37
+ name = switches[arg]
38
+ i = info[name]
39
+ if i[:arg]
40
+ options[name.to_sym] = ARGV[index + 1]
41
+ index += 1
42
+ else
43
+ options[name.to_sym] = true
44
+ end
45
+ else
46
+ rest << arg
47
+ end
48
+ index += 1
49
+ end
50
+
51
+ ARGV.delete_if do true end
52
+ rest.each do |e| ARGV << e end
53
+
54
+ options
55
+ end
56
+ end