revolt 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/README +150 -0
  2. data/Rakefile +197 -0
  3. data/bin/rv_find_levels.rb +186 -0
  4. data/bin/rv_install_level_urls.rb +191 -0
  5. data/bin/rv_install_levels.rb +76 -0
  6. data/examples/find_rv_track.rb +17 -0
  7. data/examples/install_rv_track.rb +28 -0
  8. data/lib/revolt/args.rb +46 -0
  9. data/lib/revolt/config.rb +5 -0
  10. data/lib/revolt/exceptions.rb +34 -0
  11. data/lib/revolt/fetcher/file_system.rb +31 -0
  12. data/lib/revolt/fetcher/www.rb +117 -0
  13. data/lib/revolt/fetcher.rb +30 -0
  14. data/lib/revolt/info.rb +40 -0
  15. data/lib/revolt/level.rb +298 -0
  16. data/lib/revolt/levels.rb +362 -0
  17. data/lib/revolt/logger.rb +24 -0
  18. data/lib/revolt/package/archive/analyzer/normalized.rb +50 -0
  19. data/lib/revolt/package/archive/analyzer/troubled.rb +97 -0
  20. data/lib/revolt/package/archive/analyzer.rb +34 -0
  21. data/lib/revolt/package/archive/zip/browser.rb +44 -0
  22. data/lib/revolt/package/archive.rb +35 -0
  23. data/lib/revolt/package/exe.rb +10 -0
  24. data/lib/revolt/package/installer/archive.rb +105 -0
  25. data/lib/revolt/package/installer/exe.rb +10 -0
  26. data/lib/revolt/package.rb +64 -0
  27. data/lib/revolt/util/fs_browser.rb +30 -0
  28. data/lib/revolt/util.rb +20 -0
  29. data/lib/revolt.rb +12 -0
  30. data/test/common.rb +78 -0
  31. data/test/fixtures/files/nodirs_track.zip +0 -0
  32. data/test/fixtures/files/readme.txt +1 -0
  33. data/test/fixtures/files/rickyd_track.zip +0 -0
  34. data/test/fixtures/files/standard_multi.zip +0 -0
  35. data/test/fixtures/files/standard_rev_track.zip +0 -0
  36. data/test/fixtures/files/standard_track.zip +0 -0
  37. data/test/fixtures/files/zips_inside.zip +0 -0
  38. data/test/fixtures/rv/gfx/levid.bmp +1 -0
  39. data/test/fixtures/rv/gfx/levid.bmq +1 -0
  40. data/test/fixtures/rv/gfx/levidrev.bmp +1 -0
  41. data/test/fixtures/rv/gfx/levidrev.bmq +1 -0
  42. data/test/fixtures/rv/gfx/tEsT Level.bmp +1 -0
  43. data/test/fixtures/rv/levels/levid/levid.inf +1 -0
  44. data/test/fixtures/rv/levels/levid/levid.w +1 -0
  45. data/test/fixtures/rv/levels/levid/levida.bmp +1 -0
  46. data/test/fixtures/rv/levels/levid/readme.txt +1 -0
  47. data/test/fixtures/rv/levels/levidrev/levidrev.inf +1 -0
  48. data/test/fixtures/rv/levels/levidrev/levidrev.w +1 -0
  49. data/test/fixtures/rv/levels/levidrev/levidreva.bmp +1 -0
  50. data/test/fixtures/rv/levels/levidrev/readme.txt +1 -0
  51. data/test/fixtures/rv/levels/levidrev/reversed/levidrev.cam +1 -0
  52. data/test/fixtures/rv/levels/levidrev/reversed/levidrev.fan +1 -0
  53. data/test/fixtures/rv/levels/levidrev/reversed/levidrev.fin +1 -0
  54. data/test/fixtures/rv/levels/test lEveL/TEst level.inf +4 -0
  55. data/test/fixtures/rv/levels/test lEveL/TeST level.w +1 -0
  56. data/test/fixtures/rv/levels/test lEveL/readme.txt +1 -0
  57. data/test/fixtures/rv/levels/test lEveL/reversed/TEst level.inf +1 -0
  58. data/test/fixtures/rv/levels/test lEveL/reversed/TeST level.w +1 -0
  59. data/test/fixtures/rv/levels/test lEveL/reversed/readme.txt +1 -0
  60. data/test/fixtures/rv/levels/test lEveL/reversed/test LEVELa.bmp +1 -0
  61. data/test/fixtures/rv/levels/test lEveL/test LEVELa.bmp +1 -0
  62. data/test/tc_archive_analyzer.rb +185 -0
  63. data/test/tc_args.rb +55 -0
  64. data/test/tc_args_external.rb +55 -0
  65. data/test/tc_file_system_fetcher.rb +26 -0
  66. data/test/tc_info.rb +23 -0
  67. data/test/tc_level.rb +182 -0
  68. data/test/tc_level_installer.rb +88 -0
  69. data/test/tc_level_installer_external.rb +124 -0
  70. data/test/tc_levels.rb +68 -0
  71. data/test/tc_package_track_installer.rb +174 -0
  72. data/test/ts_base.rb +14 -0
  73. data/test/ts_external.rb +7 -0
  74. metadata +133 -0
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ require 'optparse'
4
+ require 'pp'
5
+ require 'revolt'
6
+ require 'set'
7
+
8
+
9
+ def main
10
+ @cmd = CmdArguments.new(ARGV)
11
+
12
+ @summary = {
13
+ :installed => [],
14
+ :skipped => [],
15
+ :exists => [],
16
+ :error_url => [],
17
+ }
18
+
19
+ # Setup some callbacks so that progress is reported
20
+ ReVolt::global_args = REPORTING_ARGS
21
+
22
+ ReVolt::Logger::enable if @cmd[:debug]
23
+ @levels = ReVolt::Levels.at(@cmd[:base])
24
+ tmplevels = ReVolt::Levels.new(ReVolt::Util::tmpdir + 'rv_install_level')
25
+ # Delete any tmplevel directory if it existed
26
+ tmplevels.base_path.rmtree
27
+ tmplevels.create_dir_structure
28
+
29
+ puts "Enter track URLs to install. Press Ctrl+D to install."
30
+ input_open(@cmd[:input]) do |input|
31
+ input.each_line do |tracksrc|
32
+ tmplevels.install_urls tracksrc
33
+ end
34
+ end
35
+
36
+ puts "Installing tracks"
37
+ tmplevels.each do |level|
38
+ # Install only levels that do not exist already
39
+ if !@cmd[:force] && @levels.member?(level)
40
+ puts "Skipping installing of " + level.to_s + " because it exists"
41
+ @summary[:exists] << level
42
+ else
43
+ puts "Installing level " + level.to_s
44
+ level.move_to @levels
45
+ @summary[:installed] << level
46
+ end
47
+ end
48
+
49
+ # Output summary of installed tracks.
50
+ puts
51
+ puts "Summary"
52
+ puts "-------"
53
+ unless @summary[:installed].empty?
54
+ puts "Installed Tracks:"
55
+ @summary[:installed].each {|l| puts " #{l}"}
56
+ end
57
+ unless @summary[:skipped].empty?
58
+ puts "Likely exists (use option -f to force installing):"
59
+ @summary[:skipped].each {|(l,u)| puts " #{l} [name from URL #{u}]}"}
60
+ end
61
+ unless @summary[:exists].empty?
62
+ puts "Already exists (use option -f to force installing):"
63
+ @summary[:exists].each {|l| puts " #{l}"}
64
+ end
65
+ unless @summary[:error_url].empty?
66
+ puts "Errors installing URLs:"
67
+ @summary[:error_url].each {|(e,u)| puts " #{u}: #{e}"}
68
+ end
69
+
70
+ ReVolt::Logger::debug "Removing uninstalled tracks"
71
+
72
+ # Remove any remaining files from the temporary directory
73
+ tmplevels.each do |level|
74
+ ReVolt::Logger::debug "Removing uninstalled level " +
75
+ level.to_s + " from temporary levels"
76
+ level.delete
77
+ end
78
+ end
79
+
80
+ # Opens input file safely so that it gets closed too,
81
+ # and uses STDIN without the closing command otherwise
82
+ def input_open(input)
83
+ input = File.open(input) if input
84
+ input ||= STDIN
85
+ yield input
86
+ ensure
87
+ input.close unless input == STDIN
88
+ end
89
+
90
+
91
+ # Expects @levels instance variable
92
+ def track_installed?(url)
93
+ return false if @cmd[:force]
94
+ trackname = $1 if url =~ /dload\.php\?trackname=([^\&]+)/
95
+ return false if !trackname
96
+
97
+ urltrackname = URI::decode(trackname) # ).gsub!(/\+/, ' ')
98
+ trackname = normalize_track_name(urltrackname)
99
+ ReVolt::Logger::debug "Normalized track name to #{trackname}"
100
+ @levels.each_custom do |level|
101
+ levelname = normalize_track_name(level.name)
102
+ if trackname == levelname
103
+ ReVolt::Logger::debug "Match #{trackname} -> #{levelname}"
104
+ puts "URL probably already installed as #{level}, skipping (use -f option to force install)"
105
+ @summary[:skipped] << [level,urltrackname]
106
+ return true
107
+ end
108
+ end
109
+
110
+ false
111
+ end
112
+
113
+ def normalize_track_name(s)
114
+ t = s.chomp
115
+ t.downcase!
116
+ # Remove 'by someone' from the end
117
+ t.gsub!(/ +by +.*$/, '')
118
+ # Remove all special characters
119
+ t.gsub!(/[^a-z0-9]+/, '')
120
+ t
121
+ end
122
+
123
+ # Callbacks for different stages of track installing
124
+ REPORTING_ARGS = {
125
+ ReVolt::ARG_INSTALL_URL => lambda {|url|
126
+ # Often people copy-paste a link to RVZT comment section,
127
+ # so in that case automatically make a download link of it
128
+ url = url.to_s.sub(/comments.php/, 'dload.php')
129
+ puts "Installing URL #{url}"
130
+ # Only install tracks that most likely haven't already been
131
+ # installed. The track_installed? takes the URL and tries
132
+ # using a heuristic to determine if similar track is installed
133
+ track_installed?(url) ? nil : url
134
+ },
135
+ ReVolt::ARG_INSTALL_URL_EX => lambda {|e,url|
136
+ # Called if exception raised when installing url
137
+ @summary[:error_url] << [e,url]
138
+ puts "Error installing: #{e}"
139
+ },
140
+ ReVolt::ARG_FETCHER_PROGRESS => lambda {|obj,url,nread,total|
141
+ $now = Time.new().sec()
142
+ if !$last or $now - $last > 1 then
143
+ puts '%.2f%% (%d/%d bytes) downloaded' %
144
+ [(total > 0 ? nread*100/total : 0), nread, total]
145
+ $last = $now
146
+ end
147
+ },
148
+ ReVolt::ARG_FETCHER_STOP => lambda {|obj,url,total|
149
+ $last = nil
150
+ ReVolt::call_arg(ReVolt::ARG_FETCHER_PROGRESS, {}, obj, url, total, total)
151
+ }
152
+ }
153
+
154
+ class CmdArguments < Hash
155
+ def initialize(cmd)
156
+ super()
157
+ inf_matches = []
158
+ self[:base] = ReVolt::Info::path
159
+
160
+ opts = OptionParser.new do |opts|
161
+ opts.banner = "Usage: #$0 [options]\n"
162
+ opts.separator "By default the URLs are read from standard console input"
163
+
164
+ opts.separator ""
165
+ opts.separator "Options:"
166
+
167
+ opts.on('-i', '--input [FILE]',
168
+ 'Reads the URLs from given file') do |value|
169
+ self[:input] = value
170
+ end
171
+ opts.on('-b', '--base [DIR]',
172
+ 'RV base path. Defaults to RV installation') do |value|
173
+ self[:base] = value
174
+ end
175
+ opts.on('-f', '--force',
176
+ 'Forces installing of tracks') do
177
+ self[:force] = true
178
+ end
179
+
180
+ opts.on_tail('-h', '--help',
181
+ 'Display this help and exit') do
182
+ puts opts
183
+ exit(1)
184
+ end
185
+ end
186
+
187
+ opts.parse!(cmd)
188
+ end
189
+ end
190
+
191
+ main
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ require 'optparse'
4
+ require 'pp'
5
+ require 'revolt'
6
+ require 'set'
7
+
8
+
9
+ def main
10
+ cmd = CmdArguments.new(ARGV)
11
+
12
+ ReVolt::Logger::enable if cmd[:debug]
13
+ levels = ReVolt::Levels.at(cmd[:base])
14
+
15
+ levelids = []
16
+ ARGV.each do |levelpackage|
17
+ puts "Installing #{levelpackage}"
18
+ levelids += levels.install(levelpackage) || []
19
+ end
20
+ puts "Installed levels: " if levelids.size > 0
21
+ levelids.each do |levelid|
22
+ level = levels[levelid]
23
+ puts " #{level}" if level
24
+ end
25
+ end
26
+
27
+ # Opens input file safely so that it gets closed too,
28
+ # and uses STDIN without the closing command otherwise
29
+ def input_open(input)
30
+ input = File.open(input) if input
31
+ input ||= STDIN
32
+ yield input
33
+ ensure
34
+ input.close unless input == STDIN
35
+ end
36
+
37
+ class CmdArguments < Hash
38
+ def initialize(cmd)
39
+ super()
40
+ inf_matches = []
41
+ self[:base] = ReVolt::Info::path
42
+
43
+ opts = OptionParser.new do |opts|
44
+ opts.banner = "Usage: #$0 [options] package1 [package2 ...]\n"
45
+ opts.separator "By default the URLs are read from standard console input"
46
+
47
+ opts.separator ""
48
+ opts.separator "Options:"
49
+
50
+ opts.on('-d', '--debug',
51
+ 'Writes debugging information') do
52
+ self[:debug] = true
53
+ end
54
+ opts.on('-b', '--base [DIR]',
55
+ 'RV base path. Defaults to RV installation') do |value|
56
+ self[:base] = value
57
+ end
58
+
59
+ opts.on_tail('-h', '--help',
60
+ 'Display this help and exit') do
61
+ puts opts
62
+ exit(1)
63
+ end
64
+ end
65
+
66
+ opts.parse!(cmd)
67
+
68
+ if ARGV.size <= 0
69
+ puts opts
70
+ exit(1)
71
+ end
72
+ end
73
+ end
74
+
75
+
76
+ main
@@ -0,0 +1,17 @@
1
+ require 'revolt'
2
+
3
+ # Very simple example of how to find a track
4
+ # with some name (case insensitive).
5
+
6
+ search_for = ARGV[0]
7
+ unless search_for
8
+ STDERR.puts "Usage: #{$0} track_name_search_pattern"
9
+ exit(1)
10
+ end
11
+
12
+ levels = ReVolt::Levels.installed
13
+ levels.each_level do |level|
14
+ if level.name.match(/#{search_for}/i)
15
+ puts "Level matched: " + level.to_s
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ require 'revolt'
2
+
3
+ levels = ReVolt::Levels.installed
4
+ tmplevels = ReVolt::Levels.at('./tmp')
5
+ tmplevels.create_dir_structure
6
+
7
+ # Install to temporary levels dir first
8
+ STDIN.each_line do |tracksrc|
9
+ puts "Installing: " + tracksrc + " to temporary levels directory"
10
+ tmplevels.install tracksrc
11
+ end
12
+
13
+ tmplevels.each do |level|
14
+ # Install only levels that do not exist already
15
+ if levels.member? level
16
+ puts "Skipping installing of " + level.to_s + " because it exists"
17
+ else
18
+ puts "Installing level " + levels.to_s
19
+ level.move_to levels
20
+ end
21
+ end
22
+
23
+ # Remove any remaining files from the temporary directory
24
+ tmplevels.each do |level|
25
+ puts "Removing uninstalled level " + level.to_s + " from temporary levels"
26
+ level.delete
27
+ end
28
+
@@ -0,0 +1,46 @@
1
+ module ReVolt
2
+ @@global_args = {}
3
+
4
+ ARG_INSTALL_URL = :install_url
5
+ ARG_INSTALL_URL_EX = :install_url_ex
6
+ ARG_FETCHER_PROGRESS = :fetcher_progress
7
+ ARG_FETCHER_START = :fetcher_start
8
+ ARG_FETCHER_STOP = :fetcher_stop
9
+
10
+ module_function
11
+
12
+ def global_args
13
+ @@global_args
14
+ end
15
+ def global_args=(o)
16
+ @@global_args = (o.is_a?(Hash) ? o : {})
17
+ end
18
+
19
+ def arg(id, args = {})
20
+ return args[id] if args.member?(id)
21
+ return @@global_args[id] if @@global_args.member?(id)
22
+ nil
23
+ end
24
+ def call_arg(id, args, *params)
25
+ a = arg(id, args)
26
+ a.call(*params) if a
27
+ end
28
+ def call_changer_arg(id, args, *params)
29
+ a = arg(id, args)
30
+ a ? a.call(*params) : params
31
+ end
32
+
33
+ # Calls the defined callback if the block raises Runtime error
34
+ # and otherwise rethrows it
35
+ def arg_ex_watch(id, args, *rest)
36
+ begin
37
+ yield
38
+ rescue RuntimeError => e
39
+ if arg(id, args)
40
+ call_arg(id, args, e, *rest)
41
+ else
42
+ raise e
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ module ReVolt
2
+ module Config
3
+ # For now nothing
4
+ end
5
+ end
@@ -0,0 +1,34 @@
1
+ require 'pathname'
2
+
3
+ module ReVolt
4
+
5
+ # All exceptions derived from RVException
6
+ class RVException < RuntimeError; end
7
+
8
+ # Thrown if a file is not found. The file can
9
+ # be accessed via an attribute if necessary
10
+ class FileNotFoundError < RVException
11
+ attr_reader :file
12
+ def initialize(filename)
13
+ @file = filename.to_s
14
+ end
15
+ end
16
+
17
+ # Thrown if level's .inf file was not found
18
+ # when needed.
19
+ class InfFileNotFoundError < FileNotFoundError
20
+ attr_reader :levels, :level
21
+ def initialize(levels, level, inf_file)
22
+ super inf_file
23
+ @levels, @level = levels, level
24
+ end
25
+ end
26
+
27
+ # Thrown if an unknown package was tried to be
28
+ # operated on.
29
+ class PackageUnknownError < RVException; end
30
+ # Thrown if no Fetcher could be created for
31
+ # the given source.
32
+ class FetcherNoneError < RVException; end
33
+ class InvalidLevelIdError < RVException; end
34
+ end # module ReVolt
@@ -0,0 +1,31 @@
1
+ require 'pathname'
2
+
3
+ require 'revolt/exceptions'
4
+ require 'revolt/logger'
5
+
6
+ module ReVolt
7
+ module Fetcher
8
+
9
+ class FileSystem
10
+ include ReVolt::Logger
11
+
12
+ attr_reader :target, :source
13
+
14
+ def initialize(id, args = {})
15
+ debug("Source id: #{id} size #{id.size}")
16
+ @source = Pathname.new(id.to_s)
17
+ end
18
+
19
+ # Possible exceptions:
20
+ # FileNotFoundError
21
+ def run(args = {})
22
+ debug Dir['*'].join(" ")
23
+
24
+ raise ReVolt::FileNotFoundError.new(@source),
25
+ "File #{source} not found" unless File.exist?(@source.to_s) # @source.exist?
26
+
27
+ @target = @source
28
+ end
29
+ end # FileSystem
30
+ end # Fetcher
31
+ end # ReVolt
@@ -0,0 +1,117 @@
1
+ require 'pathname'
2
+ require 'uri'
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'set'
6
+
7
+ require 'revolt/exceptions'
8
+ require 'revolt/util'
9
+ require 'revolt/logger'
10
+ require 'revolt/args'
11
+
12
+ module ReVolt
13
+ module Fetcher
14
+
15
+ class WWW
16
+ include ReVolt::Logger
17
+
18
+ class TooManyRedirectionsError < ReVolt::RVException; end
19
+
20
+ attr_reader :target, :source, :final_uri
21
+ def initialize(id, args = {})
22
+ @@file_name_count = 0
23
+ @max_redirects = 3
24
+
25
+ @source = (id.is_a?(URI) ? id : URI.parse(id.to_s))
26
+ end
27
+
28
+ # Possible exceptions:
29
+ # TooManyRedirections
30
+ def run(args = {})
31
+ fetch(@source) do |resp,final_uri|
32
+ # debug "Headers: "
33
+ # resp.each {|key,val| debug "#{key}: #{val}"}
34
+ @target = ReVolt::Util::tmpdir
35
+ @target += generate_basename_from final_uri
36
+
37
+ debug "Saving to target #{@target}"
38
+
39
+ total = resp.content_length
40
+ total ||= 0
41
+ nread = 0
42
+ debug "Total size: " + total.to_s
43
+
44
+ ReVolt::call_arg(ReVolt::ARG_FETCHER_START, args,
45
+ self, @source, total)
46
+
47
+ open(@target, 'wb') do |file|
48
+ resp.read_body do |segment|
49
+ debug("%s: read %d/%d bytes read" %
50
+ [@source.to_s, nread, total])
51
+ ReVolt::call_arg(ReVolt::ARG_FETCHER_PROGRESS, args,
52
+ self, @source, nread, total)
53
+ file.syswrite segment
54
+ nread += segment.size
55
+ end
56
+ end
57
+
58
+ ReVolt::call_arg(ReVolt::ARG_FETCHER_STOP, args,
59
+ self, @source, nread)
60
+
61
+ debug "Saved to target #{@target}"
62
+ end
63
+ end
64
+
65
+ def fetch(uri, args = {}, &block)
66
+ http = Net::HTTP.new(uri.host, uri.port)
67
+ http.use_ssl = true if uri.scheme == 'https'
68
+
69
+ debug "Fetching #{uri}"
70
+
71
+ req = Net::HTTP::Get.new(uri.request_uri)
72
+ urls_seen = args[:urls_seen] || Set.new
73
+ http.request(req) do |resp|
74
+ if resp.is_a? Net::HTTPRedirection
75
+ debug "Is a redirection. Location: " + resp['Location']
76
+ new_loc = resp['Location']
77
+ if urls_seen.size < @max_redirects && new_loc
78
+ urls_seen << uri
79
+ new_uri = URI.parse new_loc
80
+ new_uri = uri.merge new_uri if new_uri.relative?
81
+
82
+ if urls_seen.member? new_uri
83
+ raise TooManyRedirectionsError,
84
+ "Too many redirections (max #{@max_redirects}): #{urls_seen}"
85
+ end
86
+
87
+ fetch(new_uri, args, &block)
88
+ end
89
+ else
90
+ debug "Final uri: " + uri.to_s
91
+ yield resp,uri
92
+ end
93
+ end
94
+ end
95
+
96
+ def generate_basename_from(uri)
97
+ uri = URI.parse uri unless uri.is_a? URI
98
+ name = Pathname.new uri.path.downcase
99
+ name = name.basename
100
+
101
+ # If the gotten name looks safe, use it as the
102
+ # basename. Otherwise use generated sequence.
103
+ if name.to_s =~ /^[^\.][\w\.]+/
104
+ else
105
+ name = "rvfetcher" + @@file_name_count.to_s
106
+ @@file_name_count += 1
107
+ end
108
+
109
+ name
110
+ end
111
+
112
+ def to_i
113
+ 'WWW Fetcher'
114
+ end
115
+ end # WWW
116
+ end # Fetcher
117
+ end # ReVolt
@@ -0,0 +1,30 @@
1
+ require 'revolt/fetcher/www'
2
+ require 'revolt/fetcher/file_system'
3
+ require 'revolt/exceptions'
4
+
5
+ module ReVolt
6
+ # Internally used module that shouldn't usually be needed
7
+ # to call directly
8
+ module Fetcher
9
+ include ReVolt
10
+
11
+ module_function
12
+
13
+ # Factory method for creating a specific fetcher.
14
+ # At the moment recognizes http(s) and basically
15
+ # others are treated as files on local filesystem
16
+ def for(id, args = {})
17
+ clas = nil
18
+ case id.to_s
19
+ when /^http[s]?/
20
+ clas = WWW
21
+ when /^ftp:\/\//
22
+ raise FetcherNoneError, "No fetcher for FTP sites implemented: #{id}"
23
+ else
24
+ clas = FileSystem
25
+ end
26
+
27
+ return clas.new(id, args)
28
+ end
29
+ end # Fetcher
30
+ end # ReVolt
@@ -0,0 +1,40 @@
1
+ require 'win32/registry'
2
+
3
+ module ReVolt
4
+
5
+ # Contains functions that can be used to find
6
+ # information about the Re-Volt installation
7
+ module Info
8
+ RV_REG_KEY = 'SOFTWARE\Acclaim\Re-Volt\1.0'
9
+ RV_REG_KEY_PATH = 'SOFTWARE\Microsoft\DirectPlay\Applications\Re-Volt'
10
+
11
+ module_function
12
+
13
+ def reg_path_to_hash(key) # :nodoc:
14
+ h = {}
15
+ Win32::Registry::HKEY_LOCAL_MACHINE.open(key) do |root|
16
+ # puts "Root keyname: #{root.keyname}, hkey: #{root.class}"
17
+ root.each do |key, type, data|
18
+ h[key.to_s.downcase.to_sym] = data
19
+ # puts 'key: %s, type: %s, data: %s' % [key, type, data]
20
+ end
21
+ end
22
+ h
23
+ end
24
+
25
+ # Returns full path of the Re-Volt base directory
26
+ def path
27
+ h = reg_path_to_hash(RV_REG_KEY_PATH)
28
+ p = Pathname.new(h[:path])
29
+ p
30
+ end
31
+
32
+ # Returns full path of the Re-Volt executable
33
+ def exe_path
34
+ h = reg_path_to_hash(RV_REG_KEY_PATH)
35
+ p = Pathname.new(h[:path])
36
+ p += h[:file]
37
+ p
38
+ end
39
+ end # Info
40
+ end # ReVolt