gamefic 0.0.5 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/gamefic +7 -0
- data/lib/gamefic/character.rb +2 -0
- data/lib/gamefic/core_ext/string.rb +2 -2
- data/lib/gamefic/director.rb +36 -3
- data/lib/gamefic/engine.rb +9 -5
- data/lib/gamefic/entity.rb +1 -1
- data/lib/gamefic/import/basics.rb +2 -0
- data/lib/gamefic/import/basics/actions.rb +1 -0
- data/lib/gamefic/import/basics/actions/container.rb +111 -0
- data/lib/gamefic/import/basics/actions/inventory.rb +49 -0
- data/lib/gamefic/import/basics/actions/look.rb +67 -0
- data/lib/gamefic/import/basics/actions/meta.rb +6 -0
- data/lib/gamefic/import/basics/actions/traversal.rb +35 -0
- data/lib/gamefic/import/basics/entities.rb +1 -0
- data/lib/gamefic/import/basics/entities/container.rb +24 -0
- data/lib/gamefic/import/basics/entities/fixture.rb +5 -0
- data/lib/gamefic/import/basics/entities/item.rb +7 -0
- data/lib/gamefic/import/basics/entities/itemized.rb +3 -0
- data/lib/gamefic/import/basics/entities/portable.rb +3 -0
- data/lib/gamefic/import/basics/entities/portal.rb +43 -0
- data/lib/gamefic/import/basics/entities/room.rb +24 -0
- data/lib/gamefic/import/basics/entities/scenery.rb +3 -0
- data/lib/gamefic/import/basics/room_modes.rb +48 -0
- data/lib/gamefic/plot.rb +89 -16
- data/lib/gamefic/shell.rb +317 -0
- data/lib/gamefic/syntax.rb +1 -1
- data/lib/gamefic/user.rb +3 -3
- metadata +23 -18
- data/lib/gamefic/action_ext.rb +0 -7
- data/lib/gamefic/action_ext/container.rb +0 -114
- data/lib/gamefic/action_ext/inventory.rb +0 -53
- data/lib/gamefic/action_ext/look.rb +0 -52
- data/lib/gamefic/action_ext/meta.rb +0 -10
- data/lib/gamefic/action_ext/traversal.rb +0 -39
- data/lib/gamefic/entity_ext.rb +0 -7
- data/lib/gamefic/entity_ext/container.rb +0 -28
- data/lib/gamefic/entity_ext/fixture.rb +0 -9
- data/lib/gamefic/entity_ext/item.rb +0 -11
- data/lib/gamefic/entity_ext/itemized.rb +0 -7
- data/lib/gamefic/entity_ext/portable.rb +0 -33
- data/lib/gamefic/entity_ext/portal.rb +0 -47
- data/lib/gamefic/entity_ext/room.rb +0 -28
- data/lib/gamefic/entity_ext/scenery.rb +0 -7
@@ -0,0 +1,43 @@
|
|
1
|
+
class Portal < Entity
|
2
|
+
attr_accessor :destination
|
3
|
+
#def initialize
|
4
|
+
# super
|
5
|
+
# @destination = nil
|
6
|
+
#end
|
7
|
+
def find_reverse
|
8
|
+
rev = Portal.reverse(self.name)
|
9
|
+
if rev != nil
|
10
|
+
destination.children.that_are(Portal).each { |c|
|
11
|
+
if c.name == rev
|
12
|
+
return c
|
13
|
+
end
|
14
|
+
}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
def self.reverse(direction)
|
18
|
+
case direction.downcase
|
19
|
+
when "north"
|
20
|
+
"south"
|
21
|
+
when "south"
|
22
|
+
"north"
|
23
|
+
when "west"
|
24
|
+
"east"
|
25
|
+
when "east"
|
26
|
+
"west"
|
27
|
+
when "northwest"
|
28
|
+
"southeast"
|
29
|
+
when "southeast"
|
30
|
+
"northwest"
|
31
|
+
when "northeast"
|
32
|
+
"southwest"
|
33
|
+
when "southwest"
|
34
|
+
"northeast"
|
35
|
+
when "up"
|
36
|
+
"down"
|
37
|
+
when "down"
|
38
|
+
"up"
|
39
|
+
else
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import 'basics/entities/portal'
|
2
|
+
|
3
|
+
class Room < Entity
|
4
|
+
def connect(destination, direction, type = Portal, two_way = true)
|
5
|
+
portal = type.new self.plot, :name => direction, :parent => self, :destination => destination
|
6
|
+
if two_way == true
|
7
|
+
reverse = Portal.reverse(direction)
|
8
|
+
if reverse == nil
|
9
|
+
raise "\"#{direction.cap_first}\" does not have an opposite direction"
|
10
|
+
end
|
11
|
+
portal2 = type.new(self.plot, {
|
12
|
+
:name => reverse,
|
13
|
+
:parent => destination,
|
14
|
+
:destination => self
|
15
|
+
})
|
16
|
+
end
|
17
|
+
portal
|
18
|
+
end
|
19
|
+
def tell(message, refresh = false)
|
20
|
+
children.each { |c|
|
21
|
+
c.tell message, refresh
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module RoomModes
|
2
|
+
attr_writer :description_mode
|
3
|
+
def description_seen
|
4
|
+
@description_seen ||= Array.new
|
5
|
+
end
|
6
|
+
def description_seen=(value)
|
7
|
+
if value.kind_of?(Array)
|
8
|
+
@description_seen = value
|
9
|
+
else
|
10
|
+
raise "Character#visited must be an Array"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
def description_mode
|
14
|
+
@description_mode ||= "brief"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Character
|
19
|
+
include RoomModes
|
20
|
+
end
|
21
|
+
|
22
|
+
respond :go, Query.new(:siblings, Portal) do |actor, portal|
|
23
|
+
actor.tell "You go #{portal.name}."
|
24
|
+
actor.parent = portal.destination
|
25
|
+
if actor.description_mode == "superbrief" or (actor.description_mode == "brief" and actor.description_seen.include?(actor.parent))
|
26
|
+
actor.perform "itemize room"
|
27
|
+
else
|
28
|
+
actor.perform "itemize room full"
|
29
|
+
end
|
30
|
+
if actor.description_seen.include?(actor.parent) == false
|
31
|
+
actor.description_seen.push actor.parent
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
respond :brief do |actor|
|
36
|
+
actor.description_mode = "brief"
|
37
|
+
actor.tell "You are now in BRIEF mode. Detailed descriptions of rooms will only be displayed the first time you visit them. Other options are SUPERBRIEF and VERBOSE."
|
38
|
+
end
|
39
|
+
|
40
|
+
respond :verbose do |actor|
|
41
|
+
actor.description_mode = "verbose"
|
42
|
+
actor.tell "You are now in VERBOSE mode. Detailed descriptions will be displayed every time you enter a room. Other options are BRIEF and SUPERBRIEF."
|
43
|
+
end
|
44
|
+
|
45
|
+
respond :superbrief do |actor|
|
46
|
+
actor.description_mode = "superbrief"
|
47
|
+
actor.tell "You are now in VERBOSE mode. Detailed room descriptions will never be displayed unless you LOOK AROUND. Other options are BRIEF and VERBOSE."
|
48
|
+
end
|
data/lib/gamefic/plot.rb
CHANGED
@@ -1,7 +1,25 @@
|
|
1
1
|
module Gamefic
|
2
2
|
|
3
|
+
def self.bind(plot)
|
4
|
+
mod = Module.new do
|
5
|
+
def self.bind(plot)
|
6
|
+
@@plot = plot
|
7
|
+
end
|
8
|
+
def self.get_binding
|
9
|
+
binding
|
10
|
+
end
|
11
|
+
def self.method_missing(name, *args, &block)
|
12
|
+
if @@plot.respond_to?(name)
|
13
|
+
@@plot.send name, *args, &block
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
mod.bind plot
|
18
|
+
mod.get_binding
|
19
|
+
end
|
20
|
+
|
3
21
|
class Plot
|
4
|
-
attr_reader :scenes, :commands, :conclusions, :
|
22
|
+
attr_reader :scenes, :commands, :conclusions, :imported_scripts
|
5
23
|
attr_accessor :story
|
6
24
|
def commandwords
|
7
25
|
words = Array.new
|
@@ -16,7 +34,8 @@ module Gamefic
|
|
16
34
|
@syntaxes = Array.new
|
17
35
|
@conclusions = Hash.new
|
18
36
|
@update_procs = Array.new
|
19
|
-
|
37
|
+
@available_scripts = Hash.new
|
38
|
+
@imported_scripts = Array.new
|
20
39
|
@entities = Array.new
|
21
40
|
post_initialize
|
22
41
|
end
|
@@ -82,30 +101,76 @@ module Gamefic
|
|
82
101
|
@update_procs.each { |p|
|
83
102
|
p.call
|
84
103
|
}
|
85
|
-
#@entities.flatten.each { |e|
|
86
104
|
@entities.each { |e|
|
87
|
-
#recursive_update e
|
88
105
|
e.update
|
89
106
|
}
|
90
107
|
end
|
108
|
+
|
91
109
|
def tell entities, message, refresh = false
|
92
110
|
entities.each { |entity|
|
93
111
|
entity.tell message, refresh
|
94
112
|
}
|
95
113
|
end
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
114
|
+
|
115
|
+
def load script, with_libs = true
|
116
|
+
code = File.read(script)
|
117
|
+
code.untaint
|
118
|
+
@source_directory = File.dirname(script)
|
119
|
+
if with_libs == true
|
120
|
+
$LOAD_PATH.reverse.each { |path|
|
121
|
+
get_scripts path + '/gamefic/import'
|
122
|
+
}
|
123
|
+
end
|
124
|
+
get_scripts @source_directory + '/import'
|
125
|
+
proc {
|
126
|
+
$SAFE = 3
|
127
|
+
eval code, ::Gamefic.bind(self), script, 1
|
128
|
+
}.call
|
129
|
+
end
|
106
130
|
|
107
|
-
|
131
|
+
def import script
|
132
|
+
if script[-2, 2] == '/*'
|
133
|
+
directory = script[0..-3]
|
134
|
+
resolved = directory
|
135
|
+
@available_scripts.each { |f, c|
|
136
|
+
if f.start_with?(resolved)
|
137
|
+
self.import f
|
138
|
+
end
|
139
|
+
}
|
140
|
+
else
|
141
|
+
resolved = script
|
142
|
+
if !@available_scripts.has_key?(resolved)
|
143
|
+
if @available_scripts.has_key?(resolved + '.rb')
|
144
|
+
resolved = resolved + '.rb'
|
145
|
+
end
|
146
|
+
end
|
147
|
+
if @available_scripts.has_key?(resolved)
|
148
|
+
if @available_scripts[resolved] != nil
|
149
|
+
script_object = @available_scripts[resolved]
|
150
|
+
@available_scripts[resolved] = nil
|
151
|
+
proc {
|
152
|
+
$SAFE = 3
|
153
|
+
@imported_scripts.push script_object
|
154
|
+
eval script_object.code, Gamefic.bind(self), script_object.filename, 1
|
155
|
+
}.call
|
156
|
+
end
|
157
|
+
else
|
158
|
+
raise "Unavailable import: #{resolved}"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
108
162
|
|
163
|
+
private
|
164
|
+
def get_scripts(directory)
|
165
|
+
Dir[directory + '/*'].each { |f|
|
166
|
+
if File.directory?(f)
|
167
|
+
get_scripts f
|
168
|
+
else
|
169
|
+
relative = f[(f.index('/import/')+8)..-1]
|
170
|
+
@available_scripts[relative] = Script.new(f)
|
171
|
+
end
|
172
|
+
}
|
173
|
+
end
|
109
174
|
def rem_entity(entity)
|
110
175
|
@entities.delete(entity)
|
111
176
|
end
|
@@ -170,6 +235,14 @@ module Gamefic
|
|
170
235
|
def add_entity(entity)
|
171
236
|
@entities.push entity
|
172
237
|
end
|
173
|
-
|
238
|
+
class Script
|
239
|
+
attr_reader :filename, :code
|
240
|
+
def initialize filename
|
241
|
+
@filename = filename
|
242
|
+
@code = File.read(filename)
|
243
|
+
@code.untaint
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
174
247
|
|
175
248
|
end
|
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'rubygems/package'
|
2
|
+
require 'zlib'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'getoptlong'
|
5
|
+
|
6
|
+
# Crazy hack to set file mtimes in tar file
|
7
|
+
class Gem::Package::TarHeader
|
8
|
+
@@mtime = Time.now
|
9
|
+
def self.set_mtime(time)
|
10
|
+
@@mtime = time
|
11
|
+
end
|
12
|
+
alias :initialize_orig :initialize
|
13
|
+
def initialize(vals)
|
14
|
+
initialize_orig(vals)
|
15
|
+
@mtime = @@mtime
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Gamefic
|
20
|
+
|
21
|
+
class Shell
|
22
|
+
attr_accessor :argv
|
23
|
+
def initialize
|
24
|
+
|
25
|
+
end
|
26
|
+
def execute
|
27
|
+
if ARGV.length == 0
|
28
|
+
ARGV.push 'help'
|
29
|
+
end
|
30
|
+
cmd = ARGV.shift
|
31
|
+
case cmd
|
32
|
+
when 'play'
|
33
|
+
play ARGV.shift
|
34
|
+
when 'test'
|
35
|
+
test ARGV.shift
|
36
|
+
when 'init'
|
37
|
+
init ARGV.shift
|
38
|
+
when 'build'
|
39
|
+
build ARGV.shift
|
40
|
+
when 'fetch'
|
41
|
+
fetch ARGV.shift
|
42
|
+
when 'help'
|
43
|
+
help ARGV.shift
|
44
|
+
else
|
45
|
+
play cmd
|
46
|
+
end
|
47
|
+
end
|
48
|
+
private
|
49
|
+
def play file
|
50
|
+
if !File.exist?(file)
|
51
|
+
puts "'#{file}' does not exist."
|
52
|
+
exit 1
|
53
|
+
end
|
54
|
+
if File.directory?(file)
|
55
|
+
puts "'#{file}' is not a Gamefic file."
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
Dir.mktmpdir 'gamefic_' do |dir|
|
59
|
+
puts "Loading..."
|
60
|
+
story = Story.new
|
61
|
+
begin
|
62
|
+
decompress file, dir
|
63
|
+
rescue Exception => e
|
64
|
+
puts "'#{file}' does not appear to be a valid Gamefic file."
|
65
|
+
puts "#{e}"
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
story.load dir + '/main.rb'
|
69
|
+
engine = Engine.new story
|
70
|
+
puts "\n"
|
71
|
+
engine.run
|
72
|
+
end
|
73
|
+
end
|
74
|
+
def test path
|
75
|
+
puts "Loading..."
|
76
|
+
story = Story.new
|
77
|
+
#begin
|
78
|
+
if File.directory?(path)
|
79
|
+
if !File.file?(path + '/main.rb')
|
80
|
+
raise "#{path}/main.rb does not exist"
|
81
|
+
end
|
82
|
+
story.load path + '/main.rb', true
|
83
|
+
else
|
84
|
+
story.load path
|
85
|
+
end
|
86
|
+
#rescue Exception => e
|
87
|
+
# puts "An error occurred in #{path}:"
|
88
|
+
# puts "#{e.inspect}"
|
89
|
+
# exit 1
|
90
|
+
#end
|
91
|
+
engine = Engine.new story
|
92
|
+
engine.run
|
93
|
+
end
|
94
|
+
def init directory
|
95
|
+
if directory.to_s == ''
|
96
|
+
puts "No directory specified."
|
97
|
+
exit 1
|
98
|
+
elsif File.exist?(directory)
|
99
|
+
if !File.directory?(directory)
|
100
|
+
files = Dir[directory + '/*']
|
101
|
+
if files.length > 0
|
102
|
+
puts "'#{directory}' is not an empty directory."
|
103
|
+
exit 1
|
104
|
+
end
|
105
|
+
else
|
106
|
+
puts "'#{directory}' is not an empty directory."
|
107
|
+
exit 1
|
108
|
+
end
|
109
|
+
else
|
110
|
+
Dir.mkdir(directory)
|
111
|
+
end
|
112
|
+
Dir.mkdir(directory + '/import')
|
113
|
+
main_rb = File.new(directory + '/main.rb', 'w')
|
114
|
+
main_rb.write <<EOS
|
115
|
+
import 'basics'
|
116
|
+
|
117
|
+
room = make Room, :name => 'room'
|
118
|
+
|
119
|
+
introduction do |player|
|
120
|
+
player.parent = room
|
121
|
+
player.perform "look"
|
122
|
+
end
|
123
|
+
EOS
|
124
|
+
main_rb.close
|
125
|
+
fetch directory
|
126
|
+
puts "Game directory '#{directory}' initialized."
|
127
|
+
end
|
128
|
+
def fetch directory
|
129
|
+
if directory.to_s == ''
|
130
|
+
puts "No source directory was specified."
|
131
|
+
exit 1
|
132
|
+
end
|
133
|
+
if !File.directory?(directory)
|
134
|
+
puts "#{directory} is not a directory."
|
135
|
+
exit 1
|
136
|
+
end
|
137
|
+
puts "Loading game data..."
|
138
|
+
story = Story.new
|
139
|
+
begin
|
140
|
+
story.load directory + '/main.rb', true
|
141
|
+
rescue Exception => e
|
142
|
+
puts "'#{directory}' has errors or is not a valid source directory."
|
143
|
+
puts "#{e}"
|
144
|
+
exit 1
|
145
|
+
end
|
146
|
+
puts "Checking for external script references..."
|
147
|
+
fetched = 0
|
148
|
+
story.imported_scripts.each { |script|
|
149
|
+
if !script.filename.start_with?(directory)
|
150
|
+
base = script.filename[(script.filename.rindex('import/') + 7)..-1]
|
151
|
+
puts "Fetching #{base}"
|
152
|
+
FileUtils.mkdir_p directory + '/import/' + File.dirname(base)
|
153
|
+
FileUtils.copy script.filename, directory + '/import/' + base
|
154
|
+
fetched += 1
|
155
|
+
end
|
156
|
+
}
|
157
|
+
if fetched == 0
|
158
|
+
puts "Nothing to fetch."
|
159
|
+
else
|
160
|
+
puts "Done."
|
161
|
+
end
|
162
|
+
end
|
163
|
+
def build directory
|
164
|
+
if directory.to_s == ''
|
165
|
+
puts "No source directory was specified."
|
166
|
+
exit 1
|
167
|
+
end
|
168
|
+
if !File.directory?(directory)
|
169
|
+
puts "#{directory} is not a directory."
|
170
|
+
exit 1
|
171
|
+
end
|
172
|
+
filename = File.basename(directory) + '.gfic'
|
173
|
+
opts = GetoptLong.new(
|
174
|
+
[ '-o', '--output', GetoptLong::REQUIRED_ARGUMENT ]
|
175
|
+
)
|
176
|
+
opts.quiet = true
|
177
|
+
begin
|
178
|
+
opts.each { |opt, arg|
|
179
|
+
case opt
|
180
|
+
when '-o'
|
181
|
+
filename = arg
|
182
|
+
end
|
183
|
+
}
|
184
|
+
rescue Exception => e
|
185
|
+
puts "#{e}"
|
186
|
+
exit 1
|
187
|
+
end
|
188
|
+
if File.exist?(filename)
|
189
|
+
puts "The file #{filename} already exists."
|
190
|
+
exit 1
|
191
|
+
end
|
192
|
+
story = Story.new
|
193
|
+
puts "Loading game data..."
|
194
|
+
begin
|
195
|
+
story.load directory + '/main.rb', true
|
196
|
+
rescue Exception => e
|
197
|
+
puts "'#{directory}' has errors or is not a valid source directory."
|
198
|
+
puts "#{e}"
|
199
|
+
exit 1
|
200
|
+
end
|
201
|
+
puts "Building file..."
|
202
|
+
stream = StringIO.new("")
|
203
|
+
Gem::Package::TarWriter.new(stream) do |tar|
|
204
|
+
Gem::Package::TarHeader.set_mtime Time.now
|
205
|
+
tar.add_file('main.rb', 0600) do |io|
|
206
|
+
File.open(directory + '/main.rb', "rb") { |f| io.write f.read }
|
207
|
+
end
|
208
|
+
if story.imported_scripts.length > 0
|
209
|
+
Gem::Package::TarHeader.set_mtime Time.now
|
210
|
+
tar.mkdir('import', 0700)
|
211
|
+
story.imported_scripts.each { |script|
|
212
|
+
base = script.filename[script.filename.rindex('import/') + 7..-1]
|
213
|
+
Gem::Package::TarHeader.set_mtime Time.now
|
214
|
+
tar.add_file('import/' + base, 0700) do |io|
|
215
|
+
io.write script.code
|
216
|
+
end
|
217
|
+
}
|
218
|
+
end
|
219
|
+
end
|
220
|
+
gz = StringIO.new("")
|
221
|
+
z = Zlib::GzipWriter.new(gz)
|
222
|
+
z.mtime = Time.now
|
223
|
+
z.write stream.string
|
224
|
+
z.close
|
225
|
+
file = File.new(filename, "w")
|
226
|
+
file.write gz.string
|
227
|
+
file.close
|
228
|
+
puts "Gamefic file '#{filename}' complete."
|
229
|
+
end
|
230
|
+
def help command
|
231
|
+
shell_script = File.basename($0)
|
232
|
+
case command
|
233
|
+
when "play"
|
234
|
+
puts <<EOS
|
235
|
+
#{shell_script} play [file]
|
236
|
+
Play a Gamefic file on the command line.
|
237
|
+
EOS
|
238
|
+
when "test"
|
239
|
+
puts <<EOS
|
240
|
+
#{shell_script} test [path]
|
241
|
+
Test a Gamefic source directory or script.
|
242
|
+
EOS
|
243
|
+
when "init"
|
244
|
+
puts <<EOS
|
245
|
+
#{shell_script} init [directory]
|
246
|
+
Initialize a Gamefic source directory. The resulting directory will contain
|
247
|
+
source files ready to build into a Gamefic file.
|
248
|
+
EOS
|
249
|
+
when "fetch"
|
250
|
+
puts <<EOS
|
251
|
+
#{shell_script} fetch [directory]
|
252
|
+
Copy shared scripts to the source directory.
|
253
|
+
If the specified game directory imnports external scripts, such as the ones
|
254
|
+
that are distributed with the Gamefic gem, this command will copy them into
|
255
|
+
the game's import directory. Fetching can be useful if you want to customize
|
256
|
+
common features.
|
257
|
+
EOS
|
258
|
+
when "build"
|
259
|
+
puts <<EOS
|
260
|
+
#{shell_script} build [directory] [-o | --output filename]
|
261
|
+
Build a distributable Gamefic file from the source directory. The default
|
262
|
+
filename is [directory].gfic. You can change the filename with the -o option.
|
263
|
+
EOS
|
264
|
+
when nil, "help"
|
265
|
+
puts <<EOS
|
266
|
+
#{shell_script} play [file] - play a Gamefic file
|
267
|
+
#{shell_script} init [dir] - initialize a Gamefic source directory
|
268
|
+
#{shell_script} test [path] - test a Gamefic source directory or script
|
269
|
+
#{shell_script} fetch [directory] - copy shared scripts into directory
|
270
|
+
#{shell_script} build [directory] - build a Gamefic file
|
271
|
+
#{shell_script} help - display this message
|
272
|
+
#{shell_script} help [command] - display info about command
|
273
|
+
EOS
|
274
|
+
else
|
275
|
+
puts "Unrecognized command '#{command}'"
|
276
|
+
exit 1
|
277
|
+
end
|
278
|
+
end
|
279
|
+
def decompress(tarfile, destination)
|
280
|
+
tar_longlink = '././@LongLink'
|
281
|
+
Gem::Package::TarReader.new( Zlib::GzipReader.open tarfile ) do |tar|
|
282
|
+
dest = nil
|
283
|
+
tar.each do |entry|
|
284
|
+
if entry.full_name == tar_longlink
|
285
|
+
dest = File.join destination, entry.read.strip
|
286
|
+
next
|
287
|
+
end
|
288
|
+
dest ||= File.join destination, entry.full_name
|
289
|
+
if entry.directory?
|
290
|
+
FileUtils.rm_rf dest unless File.directory? dest
|
291
|
+
FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false
|
292
|
+
elsif entry.file?
|
293
|
+
cur_stack = dest.split('/')
|
294
|
+
cur_stack.pop
|
295
|
+
cur_dir = ''
|
296
|
+
while cur_stack.length > 0
|
297
|
+
cur_dir += '/' + cur_stack.shift
|
298
|
+
if !File.exist?(destination + cur_dir)
|
299
|
+
FileUtils.mkdir_p dest, :mode => 0700, :verbose => false
|
300
|
+
end
|
301
|
+
end
|
302
|
+
FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false
|
303
|
+
FileUtils.rm_rf dest unless File.file? dest
|
304
|
+
File.open dest, "wb" do |f|
|
305
|
+
f.print entry.read
|
306
|
+
end
|
307
|
+
FileUtils.chmod entry.header.mode, dest, :verbose => false
|
308
|
+
elsif entry.header.typeflag == '2' #Symlink!
|
309
|
+
File.symlink entry.header.linkname, dest
|
310
|
+
end
|
311
|
+
dest = nil
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|