wolftrans 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +363 -0
- data/README.md +42 -0
- data/bin/wolftrans +11 -0
- data/lib/wolfrpg.rb +65 -0
- data/lib/wolfrpg/command.rb +218 -0
- data/lib/wolfrpg/common_events.rb +160 -0
- data/lib/wolfrpg/database.rb +315 -0
- data/lib/wolfrpg/game_dat.rb +76 -0
- data/lib/wolfrpg/io.rb +63 -0
- data/lib/wolfrpg/map.rb +250 -0
- data/lib/wolfrpg/route.rb +36 -0
- data/lib/wolftrans.rb +169 -0
- data/lib/wolftrans/context.rb +193 -0
- data/lib/wolftrans/patch_data.rb +341 -0
- data/lib/wolftrans/patch_text.rb +319 -0
- data/wolftrans.gemspec +14 -0
- metadata +60 -0
@@ -0,0 +1,193 @@
|
|
1
|
+
module WolfTrans
|
2
|
+
# Represents the context of a translatable string
|
3
|
+
class Context
|
4
|
+
def eql?(other)
|
5
|
+
self.class == other.class
|
6
|
+
end
|
7
|
+
|
8
|
+
# Parse a string to determine context
|
9
|
+
def self.from_string(string)
|
10
|
+
pair = string.split(':', 2)
|
11
|
+
if pair.size != 2
|
12
|
+
raise "malformed context line"
|
13
|
+
end
|
14
|
+
type, path = pair
|
15
|
+
path = path.split('/')
|
16
|
+
|
17
|
+
case type
|
18
|
+
when 'MPS'
|
19
|
+
return MapEvent.from_string(path)
|
20
|
+
when 'GAMEDAT'
|
21
|
+
return GameDat.from_string(path)
|
22
|
+
when 'DB'
|
23
|
+
return Database.from_string(path)
|
24
|
+
when 'COMMONEVENT'
|
25
|
+
return CommonEvent.from_string(path)
|
26
|
+
end
|
27
|
+
raise "unrecognized context type '#{type}'"
|
28
|
+
end
|
29
|
+
|
30
|
+
class MapEvent < Context
|
31
|
+
attr_reader :map_name
|
32
|
+
attr_reader :event_num
|
33
|
+
attr_reader :page_num
|
34
|
+
attr_reader :line_num
|
35
|
+
attr_reader :command_name
|
36
|
+
|
37
|
+
def initialize(map_name, event_num, page_num, line_num, command_name)
|
38
|
+
@map_name = map_name
|
39
|
+
@event_num = event_num
|
40
|
+
@page_num = page_num
|
41
|
+
@line_num = line_num
|
42
|
+
@command_name = command_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def eql?(other)
|
46
|
+
super &&
|
47
|
+
@map_name == other.map_name &&
|
48
|
+
@event_num == other.event_num &&
|
49
|
+
@page_num == other.page_num
|
50
|
+
end
|
51
|
+
|
52
|
+
def hash
|
53
|
+
[@map_name, @event_num, @page_num].hash
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
"MPS:#{@map_name}/events/#{@event_num}/pages/#{@page_num}/#{@line_num}/#{@command_name}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.from_data(map_name, event, page, cmd_index, command)
|
61
|
+
MapEvent.new(map_name, event.id, page.id + 1, cmd_index + 1, command.class.name.split('::').last)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.from_string(path)
|
65
|
+
map_name, events_str, event_num, pages_str, page_num, line_num, command_name = path
|
66
|
+
if events_str != 'events' || pages_str != 'pages'
|
67
|
+
raise "unexpected path element in MPS context line"
|
68
|
+
end
|
69
|
+
MapEvent.new(map_name, event_num.to_i, page_num.to_i, line_num.to_i, command_name)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class CommonEvent < Context
|
74
|
+
attr_reader :event_num
|
75
|
+
attr_reader :line_num
|
76
|
+
attr_reader :command_name
|
77
|
+
|
78
|
+
def initialize(event_num, line_num, command_name)
|
79
|
+
@event_num = event_num
|
80
|
+
@line_num = line_num
|
81
|
+
@command_name = command_name
|
82
|
+
end
|
83
|
+
|
84
|
+
def eql?(other)
|
85
|
+
super && @event_num == other.event_num
|
86
|
+
end
|
87
|
+
|
88
|
+
def hash
|
89
|
+
@event_num.hash
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_s
|
93
|
+
"COMMONEVENT:#{@event_num}/#{@line_num}/#{@command_name}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.from_data(event, cmd_index, command)
|
97
|
+
CommonEvent.new(event.id, cmd_index + 1, command.class.name.split('::').last)
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.from_string(path)
|
101
|
+
event_num, line_num, command_name = path
|
102
|
+
CommonEvent.new(event_num.to_i, line_num.to_i, command_name)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class GameDat < Context
|
107
|
+
attr_reader :name
|
108
|
+
|
109
|
+
def initialize(name)
|
110
|
+
@name = name
|
111
|
+
end
|
112
|
+
|
113
|
+
def eql?(other)
|
114
|
+
super && @name == other.name
|
115
|
+
end
|
116
|
+
|
117
|
+
def hash
|
118
|
+
@name.hash
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_s
|
122
|
+
"GAMEDAT:#{@name}"
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.from_data(name)
|
126
|
+
GameDat.new(name)
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.from_string(path)
|
130
|
+
if path.size != 1
|
131
|
+
raise "invalid path specified for GAMEDAT context line"
|
132
|
+
end
|
133
|
+
GameDat.new(path.first)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class Database < Context
|
138
|
+
attr_reader :db_name
|
139
|
+
attr_reader :type_index
|
140
|
+
attr_reader :type_name
|
141
|
+
attr_reader :datum_index
|
142
|
+
attr_reader :datum_name
|
143
|
+
attr_reader :field_index
|
144
|
+
attr_reader :field_name
|
145
|
+
|
146
|
+
def initialize(db_name, type_index, type_name, datum_index, datum_name, field_index, field_name)
|
147
|
+
@db_name = db_name
|
148
|
+
@type_index = type_index
|
149
|
+
@type_name = WolfTrans.full_strip(type_name)
|
150
|
+
@datum_index = datum_index
|
151
|
+
@datum_name = WolfTrans.full_strip(datum_name)
|
152
|
+
@field_index = field_index
|
153
|
+
@field_name = WolfTrans.full_strip(field_name)
|
154
|
+
end
|
155
|
+
|
156
|
+
def eql?(other)
|
157
|
+
super &&
|
158
|
+
@db_name == db_name &&
|
159
|
+
@type_index == other.type_index &&
|
160
|
+
@datum_index == other.datum_index &&
|
161
|
+
@field_index == other.field_index
|
162
|
+
end
|
163
|
+
|
164
|
+
def hash
|
165
|
+
[@db_name, @type_index, @datum_index, @field_index].hash
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_s
|
169
|
+
"DB:#{@db_name}/[#{@type_index}]#{@type_name}/[#{@datum_index}]#{@datum_name}/[#{@field_index}]#{@field_name}"
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.from_data(db_name, type_index, type, datum_index, datum, field)
|
173
|
+
Database.new(db_name, type_index, type.name, datum_index, datum.name, field.index, field.name)
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.from_string(path)
|
177
|
+
if path.size != 4
|
178
|
+
raise "invalid path specified for DB context line"
|
179
|
+
end
|
180
|
+
indices = Array.new(3)
|
181
|
+
path.each_with_index do |str, i|
|
182
|
+
next if i == 0
|
183
|
+
str.match(/^\[\d+\]/) do |m|
|
184
|
+
indices[i-1] = m.to_s[1..-2].to_i
|
185
|
+
end
|
186
|
+
str.sub!(/^\[\d+\]/, '')
|
187
|
+
end
|
188
|
+
|
189
|
+
Database.new(path[0], indices[0], path[1], indices[1], path[2], indices[2], path[3])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,341 @@
|
|
1
|
+
require 'wolftrans/context'
|
2
|
+
require 'wolfrpg'
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
require 'find'
|
6
|
+
|
7
|
+
#####################
|
8
|
+
# Loading Game data #
|
9
|
+
module WolfTrans
|
10
|
+
class Patch
|
11
|
+
def load_data(game_dir)
|
12
|
+
@game_dir = WolfTrans.sanitize_path(game_dir)
|
13
|
+
unless Dir.exist? @game_dir
|
14
|
+
raise "could not find game folder '#{@game_dir}'"
|
15
|
+
end
|
16
|
+
@game_data_dir = WolfTrans.join_path_nocase(@game_dir, 'data')
|
17
|
+
if @game_data_dir == nil
|
18
|
+
raise "could not find data folder in '#{@game_dir}'"
|
19
|
+
end
|
20
|
+
|
21
|
+
@maps = {}
|
22
|
+
@databases = {}
|
23
|
+
|
24
|
+
# Find and read all necessary data
|
25
|
+
Dir.entries(@game_data_dir).each do |parent_name|
|
26
|
+
parent_name_downcase = parent_name.downcase
|
27
|
+
next unless ['basicdata', 'mapdata'].include? parent_name_downcase
|
28
|
+
parent_path = "#{@game_data_dir}/#{parent_name}"
|
29
|
+
Dir.entries(parent_path).each do |basename|
|
30
|
+
basename_downcase = basename.downcase
|
31
|
+
extension = File.extname(basename_downcase)
|
32
|
+
basename_noext = File.basename(basename_downcase, '.*')
|
33
|
+
filename = "#{parent_path}/#{basename}"
|
34
|
+
case parent_name_downcase
|
35
|
+
when 'mapdata'
|
36
|
+
load_map(filename) if extension == '.mps'
|
37
|
+
when 'basicdata'
|
38
|
+
if basename_downcase == 'game.dat'
|
39
|
+
load_game_dat(filename)
|
40
|
+
elsif extension == '.project'
|
41
|
+
next if basename_downcase == 'sysdatabasebasic.project'
|
42
|
+
dat_filename = WolfTrans.join_path_nocase(parent_path, "#{basename_noext}.dat")
|
43
|
+
next if dat_filename == nil
|
44
|
+
load_game_database(filename, dat_filename)
|
45
|
+
elsif basename_downcase == 'commonevent.dat'
|
46
|
+
load_common_events(filename)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Apply the patch to the files in the game path and write them to the
|
54
|
+
# output directory
|
55
|
+
def apply(out_dir)
|
56
|
+
out_dir = WolfTrans.sanitize_path(out_dir)
|
57
|
+
out_data_dir = "#{out_dir}/Data"
|
58
|
+
|
59
|
+
# Clear out directory
|
60
|
+
FileUtils.rm_rf(out_dir)
|
61
|
+
|
62
|
+
# Patch all the maps and dump them
|
63
|
+
FileUtils.mkdir_p("#{out_data_dir}/MapData")
|
64
|
+
@maps.each do |map_name, map|
|
65
|
+
map.events.each do |event|
|
66
|
+
event.pages.each do |page|
|
67
|
+
page.commands.each_with_index do |command, cmd_index|
|
68
|
+
context = Context::MapEvent.from_data(map_name, event, page, cmd_index, command)
|
69
|
+
patch_command(command, context)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
map.dump("#{out_data_dir}/MapData/#{map_name}.mps")
|
74
|
+
end
|
75
|
+
|
76
|
+
# Patch the databases
|
77
|
+
FileUtils.mkdir_p("#{out_data_dir}/BasicData")
|
78
|
+
@databases.each do |db_name, db|
|
79
|
+
db.types.each_with_index do |type, type_index|
|
80
|
+
next if type.name.empty?
|
81
|
+
type.data.each_with_index do |datum, datum_index|
|
82
|
+
datum.each_translatable do |str, field|
|
83
|
+
context = Context::Database.from_data(db_name, type_index, type, datum_index, datum, field)
|
84
|
+
yield_translation(str, context) do |newstr|
|
85
|
+
datum[field] = newstr
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
name_noext = "#{out_data_dir}/BasicData/#{db_name}"
|
91
|
+
db.dump("#{name_noext}.project", "#{name_noext}.dat")
|
92
|
+
end
|
93
|
+
|
94
|
+
# Patch the common events
|
95
|
+
@common_events.events.each do |event|
|
96
|
+
event.commands.each_with_index do |command, cmd_index|
|
97
|
+
context = Context::CommonEvent.from_data(event, cmd_index, command)
|
98
|
+
patch_command(command, context)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
@common_events.dump("#{out_data_dir}/BasicData/CommonEvent.dat")
|
102
|
+
|
103
|
+
# Patch Game.dat
|
104
|
+
FileUtils.mkdir_p("#{out_data_dir}/BasicData")
|
105
|
+
patch_game_dat
|
106
|
+
@game_dat.dump("#{out_data_dir}/BasicData/Game.dat")
|
107
|
+
|
108
|
+
# Copy image files
|
109
|
+
[
|
110
|
+
'BattleEffect',
|
111
|
+
'CharaChip',
|
112
|
+
'EnemyGraphic',
|
113
|
+
'Fog_BackGround',
|
114
|
+
'MapChip',
|
115
|
+
'Picture',
|
116
|
+
'SystemFile',
|
117
|
+
].each do |dirname|
|
118
|
+
copy_data_files(out_data_dir, dirname, ['png','jpg','jpeg','bmp'])
|
119
|
+
end
|
120
|
+
|
121
|
+
# Copy sound/music files
|
122
|
+
[
|
123
|
+
'BGM',
|
124
|
+
'SE',
|
125
|
+
'SystemFile',
|
126
|
+
].each do |dirname|
|
127
|
+
copy_data_files(out_data_dir, dirname, ['ogg','mp3','wav','mid','midi'])
|
128
|
+
end
|
129
|
+
|
130
|
+
# Copy BasicData
|
131
|
+
copy_data_files(out_data_dir, 'BasicData', ['dat','project','xxxxx','png'])
|
132
|
+
|
133
|
+
# Copy fonts
|
134
|
+
copy_data_files(out_data_dir, '', ['ttf','ttc'])
|
135
|
+
|
136
|
+
# Copy remainder of files in the base patch/game dirs
|
137
|
+
copy_files(@patch_assets_dir, @patch_data_dir, out_dir)
|
138
|
+
copy_files(@game_dir, @game_data_dir, out_dir)
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
def load_map(filename)
|
143
|
+
map_name = File.basename(filename, '.*')
|
144
|
+
patch_filename = "dump/mps/#{map_name}.txt"
|
145
|
+
|
146
|
+
map = WolfRpg::Map.new(filename)
|
147
|
+
map.events.each do |event|
|
148
|
+
event.pages.each do |page|
|
149
|
+
page.commands.each_with_index do |command, cmd_index|
|
150
|
+
strings_of_command(command) do |string|
|
151
|
+
@strings[string][Context::MapEvent.from_data(map_name, event, page, cmd_index, command)] ||=
|
152
|
+
Translation.new(patch_filename)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
@maps[map_name] = map
|
158
|
+
end
|
159
|
+
|
160
|
+
def load_game_dat(filename)
|
161
|
+
patch_filename = 'dump/GameDat.txt'
|
162
|
+
@game_dat = WolfRpg::GameDat.new(filename)
|
163
|
+
unless @game_dat.title.empty?
|
164
|
+
@strings[@game_dat.title][Context::GameDat.from_data('Title')] = Translation.new(patch_filename)
|
165
|
+
end
|
166
|
+
unless @game_dat.version.empty?
|
167
|
+
@strings[@game_dat.version][Context::GameDat.from_data('Version')] = Translation.new(patch_filename)
|
168
|
+
end
|
169
|
+
unless @game_dat.font.empty?
|
170
|
+
@strings[@game_dat.font][Context::GameDat.from_data('Font')] = Translation.new(patch_filename)
|
171
|
+
end
|
172
|
+
@game_dat.subfonts.each_with_index do |sf, i|
|
173
|
+
unless sf.empty?
|
174
|
+
name = 'SubFont' + (i + 1).to_s
|
175
|
+
@strings[sf][Context::GameDat.from_data(name)] ||=
|
176
|
+
Translation.new(patch_filename)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def load_game_database(project_filename, dat_filename)
|
182
|
+
db = WolfRpg::Database.new(project_filename, dat_filename)
|
183
|
+
db.types.each_with_index do |type, type_index|
|
184
|
+
next if type.name.empty?
|
185
|
+
patch_filename = "dump/db/#{db.name}/#{WolfTrans.escape_path(type.name)}.txt"
|
186
|
+
type.data.each_with_index do |datum, datum_index|
|
187
|
+
datum.each_translatable do |str, field|
|
188
|
+
context = Context::Database.from_data(db.name, type_index, type, datum_index, datum, field)
|
189
|
+
@strings[str][context] ||= Translation.new(patch_filename)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
@databases[db.name] = db
|
194
|
+
end
|
195
|
+
|
196
|
+
def load_common_events(filename)
|
197
|
+
@common_events = WolfRpg::CommonEvents.new(filename)
|
198
|
+
@common_events.events.each do |event|
|
199
|
+
patch_filename = "dump/common/#{'%03d' % event.id}_#{WolfTrans.escape_path(event.name)}.txt"
|
200
|
+
event.commands.each_with_index do |command, cmd_index|
|
201
|
+
strings_of_command(command) do |string|
|
202
|
+
@strings[string][Context::CommonEvent.from_data(event, cmd_index, command)] ||=
|
203
|
+
Translation.new(patch_filename)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def strings_of_command(command)
|
210
|
+
case command
|
211
|
+
when WolfRpg::Command::Message
|
212
|
+
yield command.text unless command.text.empty?
|
213
|
+
when WolfRpg::Command::Choices
|
214
|
+
command.text.each do |s|
|
215
|
+
yield s
|
216
|
+
end
|
217
|
+
when WolfRpg::Command::StringCondition
|
218
|
+
command.string_args.each do |s|
|
219
|
+
yield s unless s.empty?
|
220
|
+
end
|
221
|
+
when WolfRpg::Command::SetString
|
222
|
+
yield command.text unless command.text.empty?
|
223
|
+
when WolfRpg::Command::Picture
|
224
|
+
if command.type == :text
|
225
|
+
yield command.text unless command.text.empty?
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def patch_command(command, context)
|
231
|
+
case command
|
232
|
+
when WolfRpg::Command::Message
|
233
|
+
yield_translation(command.text, context) do |str|
|
234
|
+
command.text = str
|
235
|
+
end
|
236
|
+
when WolfRpg::Command::Choices
|
237
|
+
command.text.each_with_index do |text, i|
|
238
|
+
yield_translation(text, context) do |str|
|
239
|
+
command.text[i] = str
|
240
|
+
end
|
241
|
+
end
|
242
|
+
when WolfRpg::Command::StringCondition
|
243
|
+
command.string_args.each_with_index do |arg, i|
|
244
|
+
next if arg.empty?
|
245
|
+
yield_translation(arg, context) do |str|
|
246
|
+
command.string_args[i] = str
|
247
|
+
end
|
248
|
+
end
|
249
|
+
when WolfRpg::Command::SetString
|
250
|
+
yield_translation(command.text, context) do |str|
|
251
|
+
command.text = str
|
252
|
+
end
|
253
|
+
when WolfRpg::Command::Picture
|
254
|
+
if command.type == :text
|
255
|
+
yield_translation(command.text, context) do |str|
|
256
|
+
command.text = str
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def patch_game_dat
|
263
|
+
yield_translation(@game_dat.title, Context::GameDat.from_data('Title')) do |str|
|
264
|
+
@game_dat.title = str
|
265
|
+
end
|
266
|
+
yield_translation(@game_dat.version, Context::GameDat.from_data('Version')) do |str|
|
267
|
+
@game_dat.version = str
|
268
|
+
end
|
269
|
+
yield_translation(@game_dat.font, Context::GameDat.from_data('Font')) do |str|
|
270
|
+
@game_dat.font = str
|
271
|
+
end
|
272
|
+
@game_dat.subfonts.each_with_index do |sf, i|
|
273
|
+
name = 'SubFont' + (i + 1).to_s
|
274
|
+
yield_translation(sf, Context::GameDat.from_data(name)) do |str|
|
275
|
+
@game_dat.subfonts[i] = str
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
# Yield a translation for the given string and context if it exists
|
281
|
+
def yield_translation(string, context)
|
282
|
+
return if string.empty?
|
283
|
+
if @strings.include? string
|
284
|
+
unless @strings[string][context].string.empty?
|
285
|
+
yield @strings[string][context].string
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
# Copy normal, non-data files
|
291
|
+
def copy_files(src_dir, src_data_dir, out_dir)
|
292
|
+
Find.find(src_dir) do |path|
|
293
|
+
next if path == src_dir
|
294
|
+
Find.prune if path == src_data_dir
|
295
|
+
short_path = path[src_dir.length+1..-1]
|
296
|
+
Find.prune if @file_blacklist.include? short_path.downcase
|
297
|
+
out_path = "#{out_dir}/#{short_path}"
|
298
|
+
if FileTest.directory? path
|
299
|
+
FileUtils.mkdir_p(out_path)
|
300
|
+
else
|
301
|
+
next if ['thumbs.db', 'desktop.ini', '.ds_store'].include? File.basename(path).downcase
|
302
|
+
FileUtils.cp(path, out_path) unless File.exist? out_path
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# Copy data files
|
308
|
+
def copy_data_files(out_data_dir, dirname, extensions)
|
309
|
+
copy_data_files_from(@game_data_dir, out_data_dir, dirname, extensions)
|
310
|
+
if @patch_data_dir
|
311
|
+
copy_data_files_from(@patch_data_dir, out_data_dir, dirname, extensions)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def copy_data_files_from(src_data_dir, out_data_dir, dirname, extensions)
|
316
|
+
out_dir = File.join(out_data_dir, dirname)
|
317
|
+
FileUtils.mkdir_p(out_dir)
|
318
|
+
|
319
|
+
Find.find(src_data_dir) do |path|
|
320
|
+
if dirname.empty?
|
321
|
+
if FileTest.directory? path
|
322
|
+
Find.prune if path != src_data_dir
|
323
|
+
next
|
324
|
+
end
|
325
|
+
else
|
326
|
+
next if path == src_data_dir
|
327
|
+
if FileTest.directory?(path)
|
328
|
+
Find.prune unless File.basename(path).casecmp(dirname) == 0
|
329
|
+
next
|
330
|
+
end
|
331
|
+
next if File.dirname(path) == src_data_dir
|
332
|
+
end
|
333
|
+
basename = File.basename(path)
|
334
|
+
next unless extensions.include? File.extname(basename)[1..-1]
|
335
|
+
next if @file_blacklist.include? "data/#{dirname.downcase}/#{basename.downcase}"
|
336
|
+
out_name = "#{out_dir}/#{basename}"
|
337
|
+
FileUtils.cp(path, out_name) unless File.exist? out_name
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|