bc3 0.1.0 → 0.1.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.
- data/BCSS_Binary_Format.txt +46 -39
- data/bin/bc3_merge.rb +7 -4
- data/bin/bc3_search.rb +342 -0
- data/lib/bc3.rb +5 -5
- data/lib/bc3/file.rb +87 -8
- data/lib/bc3/folder.rb +93 -44
- data/lib/bc3/helper.rb +12 -0
- data/lib/bc3/parse.rb +50 -25
- data/lib/bc3/snapshot.rb +241 -13
- data/unittest/unittest_bc3_file.rb +6 -0
- data/unittest/unittest_bc3_folder.rb +32 -6
- data/unittest/unittest_bc3_merge.rb +4 -1
- data/unittest/unittest_bc3_search.rb +231 -0
- data/unittest/unittest_bc3_snapshot.rb +218 -30
- metadata +11 -6
data/BCSS_Binary_Format.txt
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
-------------------------------------------------------------------------------
|
2
2
|
Beyond Compare Snapshot Format Version 1.1
|
3
|
+
January 25, 2011
|
4
|
+
Copyright (c) 2001-2011 Scooter Software, Inc.
|
5
|
+
This document may be redistributed.
|
6
|
+
For newer versions contact support@scootersoftware.com
|
3
7
|
-------------------------------------------------------------------------------
|
4
8
|
|
5
9
|
Beyond Compare snapshots (.bcss) are binary files containing the file metadata
|
@@ -9,6 +13,46 @@ record sizes are variable, so there's no way to seek to arbitrary records
|
|
9
13
|
without reading all of the records before it.
|
10
14
|
|
11
15
|
|
16
|
+
==========
|
17
|
+
Data Types
|
18
|
+
==========
|
19
|
+
|
20
|
+
All integer values are stored in little-endian format.
|
21
|
+
|
22
|
+
UByte:
|
23
|
+
Unsigned 8-bit value
|
24
|
+
|
25
|
+
UInt16:
|
26
|
+
Unsigned 16-bit value
|
27
|
+
|
28
|
+
Int32:
|
29
|
+
Signed 32-bit value
|
30
|
+
|
31
|
+
UInt32:
|
32
|
+
Unsigned 32-bit value
|
33
|
+
|
34
|
+
Int64:
|
35
|
+
Signed 64-bit value
|
36
|
+
|
37
|
+
char[]:
|
38
|
+
Variable length single-byte character array (ANSI or UTF-8).
|
39
|
+
|
40
|
+
FileTime:
|
41
|
+
Windows FILETIME structure. 64-bit value representing the number of
|
42
|
+
100-nanosecond intervals since January 1, 1601 UTC. Stored in local time.
|
43
|
+
|
44
|
+
ShortString:
|
45
|
+
Variable length single-byte character string (ANSI or UTF-8). Not null
|
46
|
+
terminated.
|
47
|
+
|
48
|
+
Length : UByte
|
49
|
+
Data : char[Length]
|
50
|
+
|
51
|
+
FileExString:
|
52
|
+
Variable length single-byte character string (UTF-8). See "File Extended
|
53
|
+
Header" section for details.
|
54
|
+
|
55
|
+
|
12
56
|
===========
|
13
57
|
File Header
|
14
58
|
===========
|
@@ -60,44 +104,6 @@ original OS's ANSI codepage (Windows). In that case any paths may be stored a
|
|
60
104
|
second time as UTF-8 in extended headers.
|
61
105
|
|
62
106
|
|
63
|
-
==========
|
64
|
-
Data Types
|
65
|
-
==========
|
66
|
-
|
67
|
-
UByte:
|
68
|
-
Unsigned 8-bit value
|
69
|
-
|
70
|
-
UInt16:
|
71
|
-
Unsigned 16-bit value
|
72
|
-
|
73
|
-
Int32:
|
74
|
-
Signed 32-bit value
|
75
|
-
|
76
|
-
UInt32:
|
77
|
-
Unsigned 32-bit value
|
78
|
-
|
79
|
-
Int64:
|
80
|
-
Signed 64-bit value
|
81
|
-
|
82
|
-
char[]:
|
83
|
-
Variable length single-byte character array (ANSI or UTF-8).
|
84
|
-
|
85
|
-
FileTime:
|
86
|
-
Windows FILETIME structure. 64-bit value representing the number of
|
87
|
-
100-nanosecond intervals since January 1, 1601 UTC. Stored in local time.
|
88
|
-
|
89
|
-
ShortString:
|
90
|
-
Variable length single-byte character string (ANSI or UTF-8). Not null
|
91
|
-
terminated.
|
92
|
-
|
93
|
-
Length : UByte
|
94
|
-
Data : char[Length]
|
95
|
-
|
96
|
-
FileExString:
|
97
|
-
Variable length single-byte character string (UTF-8). See "File Extended
|
98
|
-
Header" section for details.
|
99
|
-
|
100
|
-
|
101
107
|
===============
|
102
108
|
Content Records
|
103
109
|
===============
|
@@ -201,7 +207,8 @@ File Extended Headers
|
|
201
207
|
=====================
|
202
208
|
|
203
209
|
Like extended headers, file extended headers should be written in ascending
|
204
|
-
numeric order.
|
210
|
+
numeric order. Multiple headers may occur within a single ID_FILE_EX record,
|
211
|
+
and compliant parsers should break once they read a type they don't recognize.
|
205
212
|
|
206
213
|
FILE_EX_VERSION (0x01)
|
207
214
|
String representation of an executable file's Major/Minor/Maint/Build
|
data/bin/bc3_merge.rb
CHANGED
@@ -94,7 +94,7 @@ opts.on("-s", "--source SOURCE", "Set source path for the snapshot") { |v|
|
|
94
94
|
=begin
|
95
95
|
Set target name.
|
96
96
|
=end
|
97
|
-
opts.on("-t", "--target TARGET", "Set target file name") { |v|
|
97
|
+
opts.on("-t", "--target TARGET", "Set target file name (must be .yaml or .bcss)") { |v|
|
98
98
|
$options[:target] = v
|
99
99
|
}
|
100
100
|
|
@@ -113,6 +113,8 @@ opts.on("-i", "--initial SNAPSHOT_MASK", "Add snapshots without source-informati
|
|
113
113
|
$options[:initial] << v
|
114
114
|
}
|
115
115
|
|
116
|
+
|
117
|
+
$log.info("Start bc_merge #{BC3::VERSION}")
|
116
118
|
#Parsen der Parameter mit Exception bei ung�ltigen Parametern
|
117
119
|
begin
|
118
120
|
opts.parse!
|
@@ -122,6 +124,7 @@ rescue OptionParser::MissingArgument, OptionParser::InvalidOption => err
|
|
122
124
|
puts "Error:\t#{err}"
|
123
125
|
#Ausgabe der Schnittstelle
|
124
126
|
puts opts
|
127
|
+
exit
|
125
128
|
end
|
126
129
|
|
127
130
|
snapshot = BC3::Snapshot.new( $options[:source] )
|
@@ -131,7 +134,7 @@ $options[:root].each{|mask|
|
|
131
134
|
Dir[mask].each{|file|
|
132
135
|
snap = BC3::SnapshotParser.new(file)
|
133
136
|
snapshot << folder = BC3::Folder.new( snap.snapshot.path, snap.timestamp)
|
134
|
-
snap.snapshot.each{|key, x| folder << x }
|
137
|
+
snap.snapshot.each(:folders, :files, :rootonly ){|key, x| folder << x }
|
135
138
|
}
|
136
139
|
}
|
137
140
|
|
@@ -140,14 +143,14 @@ $options[:root].each{|mask|
|
|
140
143
|
Dir[mask].each{|file|
|
141
144
|
snap = BC3::SnapshotParser.new(file)
|
142
145
|
snapshot << folder = BC3::Folder.new( File.basename(snap.snapshot.path), snap.timestamp )
|
143
|
-
snap.snapshot.each{|key, x| folder << x }
|
146
|
+
snap.snapshot.each(:folders, :files, :rootonly ){|key, x| folder << x }
|
144
147
|
}
|
145
148
|
}
|
146
149
|
|
147
150
|
$options[:initial].each{|mask|
|
148
151
|
puts "Add #{mask} in raw-mode"
|
149
152
|
Dir[mask].each{|file|
|
150
|
-
BC3::SnapshotParser.new(file).snapshot.each{|key, x| snapshot << x }
|
153
|
+
BC3::SnapshotParser.new(file).snapshot.each(:folders, :files, :rootonly ){|key, x| snapshot << x }
|
151
154
|
}
|
152
155
|
}
|
153
156
|
|
data/bin/bc3_search.rb
ADDED
@@ -0,0 +1,342 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin rdoc
|
3
|
+
Search inside bc3-snapshots.
|
4
|
+
|
5
|
+
Please remember:
|
6
|
+
BC3 offers itself a search function.
|
7
|
+
|
8
|
+
This bc3_merge may be usefull, if you want to search in
|
9
|
+
many snapshots for specific files or directories.
|
10
|
+
|
11
|
+
Usage:
|
12
|
+
bc3_search.rb 'pattern' *.bcss [options]
|
13
|
+
|
14
|
+
The ' around $pattern are needed, else the shell may expand the pattern as shell glob.
|
15
|
+
|
16
|
+
Search is only possible on basenames (no pathes).
|
17
|
+
|
18
|
+
==Pattern
|
19
|
+
The search pattern handles the following parameters:
|
20
|
+
* * Matches any character
|
21
|
+
* ? Matches exactly one character
|
22
|
+
* [] and {} may make problems.
|
23
|
+
|
24
|
+
The pattern is translated to a regular expression.
|
25
|
+
With option -r the pattern is used as a regular expression,
|
26
|
+
no conversion is made.
|
27
|
+
|
28
|
+
==Report the Result
|
29
|
+
===YAML-File
|
30
|
+
Use option -y
|
31
|
+
|
32
|
+
===BC3-Snapshot
|
33
|
+
Use option -b (or --bcss) and the search result is
|
34
|
+
saved as a snapshot.
|
35
|
+
bc_search -b extract *.bcss
|
36
|
+
Creates snapshots with the search result.
|
37
|
+
The Filename is the original name with an additional 'extract'".
|
38
|
+
|
39
|
+
bc_search *.bcss -b
|
40
|
+
Filename will get a "_extract_YYYY-MM-DD-hhmm".
|
41
|
+
The option -b must be at the end (else the *.bcss will be taken to build a new filename)
|
42
|
+
|
43
|
+
|
44
|
+
Use option -B (or --BCSS) and the global search result is
|
45
|
+
saved as a snapshot.
|
46
|
+
bc_search -B extract.bcss *.bcss
|
47
|
+
Creates a snapshot 'extract.bcss' with all collected search results.
|
48
|
+
|
49
|
+
bc_search *.bcss -B
|
50
|
+
Filename will get a "bc3_search_YYYY-MM-DD-hhmm.bcss".
|
51
|
+
The option -B must be at the end (else the *.bcss will be taken to build a new filename)
|
52
|
+
|
53
|
+
==Duplicates
|
54
|
+
With option -d (or --duplicates) you can restrict the
|
55
|
+
results on duplicates inside a snapshot.
|
56
|
+
|
57
|
+
With option -D (or --Duplicates) you can restrict the
|
58
|
+
results on duplicates in the snapshots.
|
59
|
+
Only files with a duplicate in another (or the same) snapshot
|
60
|
+
are listed.
|
61
|
+
|
62
|
+
The duplicate search can be combined with yaml or bcss-option.
|
63
|
+
|
64
|
+
===BC3 method
|
65
|
+
Beyond Compare offers itself a way to find duplicates:
|
66
|
+
<em>
|
67
|
+
The only way to find duplicate files is to flatten your folder structure so that all the files appear to be at the same level. You then can enable/show the CRC column, sort by it, then manually scan the file list for files with the same size and CRC code. I wouldn't advise it for a large number of files and folders, though. It could take a while to calculate all the CRC values, and it would be a tedious process to manually look through them all for duplicates.
|
68
|
+
</em>
|
69
|
+
http://www.scootersoftware.com/vbulletin/showpost.php?p=27736&postcount=4
|
70
|
+
|
71
|
+
|
72
|
+
==Examples:
|
73
|
+
bc3_search.rb '*.rbw' *.bcss
|
74
|
+
Search for rbw-files in all snapshots.
|
75
|
+
|
76
|
+
===duplicate option
|
77
|
+
bc3_search.rb -d '*' *.bcss
|
78
|
+
bc3_search.rb --duplicates '*' *.bcss
|
79
|
+
Search for duplicates inside all snapshots.
|
80
|
+
Use the pattern '*' to check all files.
|
81
|
+
|
82
|
+
bc3_search.rb -d '*.rb' *.bcss
|
83
|
+
Search for duplicate ruby scripts in all snapshots.
|
84
|
+
|
85
|
+
|
86
|
+
bc3_search.rb -D '*' *.bcss
|
87
|
+
bc3_search.rb --Duplicates '*' *.bcss
|
88
|
+
Search for duplicates inside snapshots.
|
89
|
+
Each snapshot lists all files, where you can find a duplicate
|
90
|
+
in the same or another selected snapshot.
|
91
|
+
|
92
|
+
|
93
|
+
===regexp option
|
94
|
+
bc3_search.rb -r '[ab].*\\.rbw' *.bcss
|
95
|
+
bc3_search.rb --regexp '[ab].*\\.rbw' *.bcss
|
96
|
+
Search for rbw-files starting with an a or a b.
|
97
|
+
The option -r switch to regular expression.
|
98
|
+
|
99
|
+
===yaml option
|
100
|
+
bc3_search.rb '*.rbw' *.bcss -y
|
101
|
+
bc3_search.rb '*.rbw' *.bcss -yaml
|
102
|
+
Search for rbw-files in all snapshots and
|
103
|
+
return the result in a yaml-list.
|
104
|
+
|
105
|
+
=end
|
106
|
+
|
107
|
+
=begin
|
108
|
+
fixme/test:
|
109
|
+
duplicates
|
110
|
+
save as snapshot.
|
111
|
+
=end
|
112
|
+
|
113
|
+
$testmode = false
|
114
|
+
#~ $testmode = true
|
115
|
+
if $testmode
|
116
|
+
puts "!!Testmode"
|
117
|
+
#~ ARGV = %w{* ../unittest/test_search.bcss}
|
118
|
+
#~ ARGV = %w{-r .* ../unittest/test_search.bcss}
|
119
|
+
#~ ARGV = %w{-y * ../unittest/test_search.bcss}
|
120
|
+
#~ ARGV = %w{-d * ../unittest/test_search.bcss}
|
121
|
+
#~ ARGV = %w{-B * ../unittest/test_search.bcss}
|
122
|
+
#~ ARGV = %w{-d * ../unittest/test_search.bcss -b}
|
123
|
+
$:.unshift('../lib')
|
124
|
+
end
|
125
|
+
|
126
|
+
require 'optparse'
|
127
|
+
require 'bc3'
|
128
|
+
#~ $log.level = Log4r::DEBUG
|
129
|
+
$log.level = Log4r::WARN
|
130
|
+
|
131
|
+
|
132
|
+
#Collector
|
133
|
+
$options = {
|
134
|
+
duplicates: false,
|
135
|
+
yaml: false,
|
136
|
+
}
|
137
|
+
|
138
|
+
=begin
|
139
|
+
Create a Parser for command line
|
140
|
+
=end
|
141
|
+
opts = OptionParser.new()
|
142
|
+
opts.banner = "Usage: bc3_search.rb pattern snapshots [options]" #Usage-zeile
|
143
|
+
opts.separator("Search inside Beyond Compare Snapshots")
|
144
|
+
|
145
|
+
=begin
|
146
|
+
Pattern is a regular expression.
|
147
|
+
=end
|
148
|
+
opts.on('-r', "--[no-]regexp", "Use a ruby-regular expression") { |v|
|
149
|
+
$log.debug("Set usage of regular expression")
|
150
|
+
$options[:regexp] = v
|
151
|
+
}
|
152
|
+
|
153
|
+
=begin
|
154
|
+
Define search for duplicates
|
155
|
+
=end
|
156
|
+
opts.on("-d", "--[no-]duplicates", "Restrict on duplicates inside snapshot") { |v|
|
157
|
+
$options[:duplicates] = v
|
158
|
+
}
|
159
|
+
opts.on("-D", "--Duplicates", "Search duplicates in all snapshots") { |v|
|
160
|
+
$options[:Duplicates] = true
|
161
|
+
}
|
162
|
+
|
163
|
+
|
164
|
+
=begin
|
165
|
+
Puts result in yaml-style
|
166
|
+
=end
|
167
|
+
opts.on("-y", "--[no-]yaml", "Give result in yaml-style") { |v|
|
168
|
+
$options[:yaml] = v
|
169
|
+
}
|
170
|
+
|
171
|
+
=begin
|
172
|
+
Save result as bcss-file
|
173
|
+
=end
|
174
|
+
opts.on("-b", "--bcss [FILENAME_ADDITION]", "Save result as bcss-file") { |v|
|
175
|
+
$options[:bcss] = v ? v : "extract_#{Time.now.strftime('%Y-%m-%d_%H%M')}"
|
176
|
+
}
|
177
|
+
opts.on("-B", "--BCSS [FILENAME]", "Save result as bcss-file") { |v|
|
178
|
+
$options[:BCSS] = v ? v : "bc3_search_#{Time.now.strftime('%Y-%m-%d_%H%M')}.bcss"
|
179
|
+
}
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
$log.info("Start bc_search #{BC3::VERSION}")
|
184
|
+
#Parsen der Parameter mit Exception bei ung�ltigen Parametern
|
185
|
+
begin
|
186
|
+
opts.parse!
|
187
|
+
# rescue OptionParser::MissingArgument => err
|
188
|
+
# rescue OptionParser::InvalidOption => err
|
189
|
+
rescue OptionParser::MissingArgument, OptionParser::InvalidOption => err
|
190
|
+
puts "Error:\t#{err}"
|
191
|
+
#Ausgabe der Schnittstelle
|
192
|
+
puts opts
|
193
|
+
exit
|
194
|
+
end
|
195
|
+
|
196
|
+
if ARGV.empty?
|
197
|
+
puts "No search pattern and no Snapshot found"
|
198
|
+
exit
|
199
|
+
end
|
200
|
+
|
201
|
+
#Build regexp from pattern
|
202
|
+
pattern = ARGV.shift.dup #ARGV-parameter are frozen -> dup
|
203
|
+
if ! $options[:regexp]
|
204
|
+
pattern.gsub!(/\./, '\.')
|
205
|
+
pattern.gsub!(/\*/, '.*')
|
206
|
+
pattern.gsub!(/\?/, '.')
|
207
|
+
end
|
208
|
+
begin
|
209
|
+
searchpattern = Regexp.new(pattern)
|
210
|
+
rescue RegexpError
|
211
|
+
puts "Argument Error - Searchpattern has error"
|
212
|
+
exit
|
213
|
+
end
|
214
|
+
|
215
|
+
puts "Start bc3_search for pattern <#{searchpattern.source}>"
|
216
|
+
if ARGV.empty?
|
217
|
+
puts "No Snapshot found"
|
218
|
+
end
|
219
|
+
|
220
|
+
if $options[:BCSS] and File.exist?($options[:BCSS])
|
221
|
+
puts "Target Snapshot #{$options[:BCSS]} already exists"
|
222
|
+
exit
|
223
|
+
end
|
224
|
+
|
225
|
+
puts "Restrict on global duplicates" if $options[:Duplicates]
|
226
|
+
|
227
|
+
=begin
|
228
|
+
Loop on non-option arguments and create snapshots.
|
229
|
+
|
230
|
+
With option -D (or --Duplicates) a glogal crc-overview is generated.
|
231
|
+
=end
|
232
|
+
$snapshots = {}
|
233
|
+
crc_list = {}
|
234
|
+
ARGV.each{|filename|
|
235
|
+
if ! File.exist?(filename)
|
236
|
+
puts "Snapshot #{filename} not found"
|
237
|
+
next
|
238
|
+
end
|
239
|
+
$snapshots[filename] = BC3::SnapshotParser.new(filename).snapshot
|
240
|
+
if $options[:Duplicates]
|
241
|
+
$snapshots[filename].each(:files){|path, file|
|
242
|
+
( crc_list[file.crc] ||= [] ) << path
|
243
|
+
}
|
244
|
+
end
|
245
|
+
}
|
246
|
+
|
247
|
+
$global_duplicates = []
|
248
|
+
crc_list.each{| crc, filelist| $global_duplicates.concat(filelist) if filelist.size > 1 }
|
249
|
+
|
250
|
+
#Collector for global hits
|
251
|
+
$bcss = BC3::Snapshot.new( Time.now.strftime('bc3_search_%Y-%m-%d_%H%M.bcss'))
|
252
|
+
|
253
|
+
|
254
|
+
=begin
|
255
|
+
Loop on snapshots
|
256
|
+
=end
|
257
|
+
$snapshots.each{|file, snapshot|
|
258
|
+
puts "Analyse #{file} (#{snapshot.path})"
|
259
|
+
count = Hash.new(0)
|
260
|
+
bcss = BC3::Snapshot.new( snapshot.path + '_extract' )
|
261
|
+
|
262
|
+
=begin
|
263
|
+
Prepare duplicate search if needed.
|
264
|
+
=end
|
265
|
+
if $options[:duplicates]
|
266
|
+
snapshot.build_index
|
267
|
+
crc_list = snapshot.statistic['duplicates_by_crc']
|
268
|
+
|
269
|
+
duplicates = []
|
270
|
+
if crc_list != 0
|
271
|
+
crc_list.each{| crc, filelist| duplicates.concat(filelist) }
|
272
|
+
else
|
273
|
+
puts "No duplicates found"
|
274
|
+
end
|
275
|
+
end
|
276
|
+
=begin
|
277
|
+
Loop on snapshot content
|
278
|
+
=end
|
279
|
+
folders = []
|
280
|
+
snapshot.each(:recursive, :files, :folders){|key, element|
|
281
|
+
next unless File.basename(key) =~ searchpattern
|
282
|
+
next if $options[:duplicates] and ! duplicates.include?(key)
|
283
|
+
next if $options[:Duplicates] and ! $global_duplicates.include?(key)
|
284
|
+
|
285
|
+
#Copy folder, but without content (content is no hit, only the folder itself).
|
286
|
+
if element.kind_of?(BC3::Folder)
|
287
|
+
element = BC3::Folder.new( element.dirname, element.timestamp, element.attributes )
|
288
|
+
folders << key #separated collection of folders.
|
289
|
+
end
|
290
|
+
#Add to result
|
291
|
+
if key =~ /\/./
|
292
|
+
$bcss.basefolder.add_with_path(File.dirname(key), element)
|
293
|
+
bcss.basefolder.add_with_path(File.dirname(key), element)
|
294
|
+
else
|
295
|
+
$bcss << element
|
296
|
+
bcss << element
|
297
|
+
end
|
298
|
+
|
299
|
+
} #snapshot
|
300
|
+
|
301
|
+
if $options[:yaml]
|
302
|
+
puts bcss.to_hash.to_yaml
|
303
|
+
else
|
304
|
+
folders.each{|key|
|
305
|
+
puts "\t#{key}"
|
306
|
+
}
|
307
|
+
bcss.each{|key,element| #only files
|
308
|
+
puts "\t#{key}"
|
309
|
+
}
|
310
|
+
{
|
311
|
+
:file => bcss.statistic['files'],
|
312
|
+
:folder => folders.size,
|
313
|
+
}.each{|key, value|
|
314
|
+
next if value == 0
|
315
|
+
puts "Found %3i %s%s in %s" % [ value, key, value > 1 ? 's' : '', file ]
|
316
|
+
}
|
317
|
+
end
|
318
|
+
|
319
|
+
=begin
|
320
|
+
Create extract as snapshot.
|
321
|
+
=end
|
322
|
+
if $options[:bcss]
|
323
|
+
filename = File.basename(file, '.bcss') + "_#{$options[:bcss]}.bcss"
|
324
|
+
if File.exist?(filename)
|
325
|
+
puts "Target Snapshot #{filename} already exists"
|
326
|
+
next
|
327
|
+
end
|
328
|
+
|
329
|
+
puts "Save result in #{filename}"
|
330
|
+
bcss.save(filename)
|
331
|
+
end
|
332
|
+
|
333
|
+
puts '' #space for next snapshot
|
334
|
+
} #snapshots
|
335
|
+
|
336
|
+
=begin
|
337
|
+
Create extract as snapshot.
|
338
|
+
=end
|
339
|
+
if $options[:BCSS]
|
340
|
+
puts "Save result in #{$options[:BCSS]}"
|
341
|
+
$bcss.save($options[:BCSS])
|
342
|
+
end
|