extracter 1.2.21

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of extracter might be problematic. Click here for more details.

@@ -0,0 +1,1057 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === Extracter::Extracter
6
+ #
7
+ # The primary purpose of this class is to abstract extracting source files
8
+ # to a target location. You just pass the argument of the file that has
9
+ # to be extracted to this class, and it should handle the rest.
10
+ #
11
+ # The class can be used to "extract" audio files as well, by calling the
12
+ # module ExtractAudio, which is part of MultimediaParadise. You can try
13
+ # this - just pass a .mp4 file as first argument to this class. Make sure
14
+ # to have installed that gem before, via: gem install multimedia_paradise
15
+ #
16
+ # Usage examples:
17
+ #
18
+ # Extracter::Extracter.new(ARGV)
19
+ # Extracter.new('foo.mp3')
20
+ # Extracter.new('xyz-1.0.tar.gz')
21
+ #
22
+ # =========================================================================== #
23
+ # require 'extracter/class/extracter.rb'
24
+ # =========================================================================== #
25
+ require 'extracter/base/base.rb'
26
+
27
+ module Extracter
28
+
29
+ class Extracter < ::Extracter::Base # === Extracter::Extracter
30
+
31
+ require 'fileutils'
32
+ require 'extracter/toplevel_methods/is_this_a_valid_archive.rb'
33
+ require 'extracter/toplevel_methods/misc.rb'
34
+ require 'extracter/version/version.rb'
35
+ require 'extracter/class/extract_this_archive.rb'
36
+
37
+ begin
38
+ require 'opn'
39
+ rescue LoadError; end
40
+
41
+ # ========================================================================= #
42
+ # === NAMESPACE
43
+ # ========================================================================= #
44
+ NAMESPACE = inspect
45
+
46
+ # ========================================================================= #
47
+ # === SHOW_ONLY_THE_SHORT_NAME_OF_THE_ARCHIVE
48
+ #
49
+ # If this constant is set to true then we will only show the shortened
50
+ # name of the archive in question by default.
51
+ # ========================================================================= #
52
+ SHOW_ONLY_THE_SHORT_NAME_OF_THE_ARCHIVE = true
53
+
54
+ # ========================================================================= #
55
+ # === initialize
56
+ #
57
+ # The first argument to this method should be the archive that the user
58
+ # wants to extract. This must be a (locally) existing archive, such as
59
+ # foobar.tar.xz or something similar.
60
+ #
61
+ # The second argument to this method, called `extract_to`, specifies the
62
+ # target location, where this class will extract the archive into, if
63
+ # available. Some keywords and shortcuts exist for this option - for
64
+ # instance, TEMP means $MY_TEMP, which can be set by the user.
65
+ #
66
+ # Specific usage example in pure Ruby:
67
+ #
68
+ # x = Extracter.what_to('pry-0.9.9.4.gem', '/home/Temp')
69
+ #
70
+ # ========================================================================= #
71
+ def initialize(
72
+ commandline_arguments = ARGV,
73
+ extract_to = nil,
74
+ run_already = true,
75
+ &block
76
+ )
77
+ register_sigint
78
+ reset
79
+ @internal_hash[:run_already] = run_already
80
+ set_commandline_arguments(
81
+ commandline_arguments
82
+ )
83
+ if debug? # Some debug-information in this case.
84
+ e "The first argument what is: `#{commandline_arguments}`"
85
+ e "The second argument where_to is: `#{extract_to}`"
86
+ end
87
+ case run_already
88
+ # ======================================================================= #
89
+ # === :dont_run_yet
90
+ # ======================================================================= #
91
+ when :dont_run_yet,
92
+ :do_not_run_yet,
93
+ :default
94
+ @internal_hash[:run_already] = false
95
+ end
96
+ set_extract_to(extract_to) if extract_to
97
+ # ======================================================================= #
98
+ # === Handle blocks next
99
+ # ======================================================================= #
100
+ if block_given?
101
+ yielded = yield
102
+ case yielded
103
+ # ===================================================================== #
104
+ # === :dont_run_yet
105
+ # ===================================================================== #
106
+ when :dont_run_yet,
107
+ :do_not_run_yet,
108
+ :default
109
+ @internal_hash[:run_already] = false
110
+ # ===================================================================== #
111
+ # === :show_the_full_name_of_the_archive
112
+ # ===================================================================== #
113
+ when :show_the_full_name_of_the_archive
114
+ do_show_the_full_name_of_the_archive
115
+ end
116
+ end
117
+ run if run_already?
118
+ end
119
+
120
+ # ========================================================================= #
121
+ # === reset (reset tag)
122
+ # ========================================================================= #
123
+ def reset
124
+ super()
125
+ # ======================================================================= #
126
+ # === :try_to_use_colours
127
+ # ======================================================================= #
128
+ @internal_hash[:try_to_use_colours] = true
129
+ # ======================================================================= #
130
+ # === :colour_to_use_for_directories
131
+ # ======================================================================= #
132
+ @internal_hash[:colour_to_use_for_directories] = 'cyan'
133
+ # ======================================================================= #
134
+ # === :use_opn
135
+ # ======================================================================= #
136
+ @internal_hash[:use_opn] = true # ← Whether to use make use of Opn by default or not.
137
+ # ======================================================================= #
138
+ # === :show_the_full_name_of_the_archive
139
+ # ======================================================================= #
140
+ @internal_hash[:show_the_full_name_of_the_archive] = false
141
+ # ======================================================================= #
142
+ # === :debug
143
+ # ======================================================================= #
144
+ @internal_hash[:debug] = false
145
+ # ======================================================================= #
146
+ # === :append_this_to_the_commandline
147
+ #
148
+ # This variable can always be used to append onto the commandline.
149
+ # That way we can pass additional options to "tar", for instance.
150
+ # ======================================================================= #
151
+ @internal_hash[:append_this_to_the_commandline] = ''.dup
152
+ # ======================================================================= #
153
+ # === :namespace
154
+ #
155
+ # Specify the main namespace to be used. This setting can be modified
156
+ # at "runtime".
157
+ # ======================================================================= #
158
+ @internal_hash[:namespace] = NAMESPACE
159
+ # ======================================================================= #
160
+ # === :be_verbose
161
+ # ======================================================================= #
162
+ @internal_hash[:be_verbose] = true
163
+ # ======================================================================= #
164
+ # === :show_the_name
165
+ #
166
+ # If this variable is true then the name of the class will be shown
167
+ # on the commandline, via opn().
168
+ # ======================================================================= #
169
+ @internal_hash[:show_the_name] = false
170
+ # ======================================================================= #
171
+ # === :show_only_the_short_name_of_the_archive
172
+ # ======================================================================= #
173
+ @internal_hash[:show_only_the_short_name_of_the_archive] =
174
+ SHOW_ONLY_THE_SHORT_NAME_OF_THE_ARCHIVE
175
+ # ======================================================================= #
176
+ # === :run_simulation
177
+ # ======================================================================= #
178
+ @internal_hash[:run_simulation] = false # ← Whether to run in simulation, or for "real".
179
+ # ======================================================================= #
180
+ # === :extract_to
181
+ # ======================================================================= #
182
+ @internal_hash[:extract_to] = return_pwd
183
+ do_show_name # We will show the name usually.
184
+ prepare_the_hash_for_opn
185
+ # ======================================================================= #
186
+ # === :use_colours
187
+ # ======================================================================= #
188
+ enable_colours
189
+ end
190
+
191
+ # ========================================================================= #
192
+ # === do_not_show_name
193
+ #
194
+ # Tells us whether to use opn() or not.
195
+ # ========================================================================= #
196
+ def do_not_show_name
197
+ @internal_hash[:show_the_name] = false
198
+ end
199
+
200
+ # ========================================================================= #
201
+ # === show_the_name?
202
+ # ========================================================================= #
203
+ def show_the_name?
204
+ @internal_hash[:show_the_name]
205
+ end
206
+
207
+ # ========================================================================= #
208
+ # === check_whether_rar_is_available
209
+ #
210
+ # We try to find out whether unrar is available.
211
+ # ========================================================================= #
212
+ def check_whether_rar_is_available
213
+ is_available = false
214
+ ENV['PATH'].split(':').each {|entry|
215
+ is_available = true if File.exist? "#{entry}/unrar"
216
+ }
217
+ unless is_available
218
+ copn; e 'Sorry, unrar is not available. Please install it first.'
219
+ end
220
+ end
221
+
222
+ # ========================================================================= #
223
+ # === debug?
224
+ # ========================================================================= #
225
+ def debug?
226
+ @internal_hash[:debug]
227
+ end
228
+
229
+ # ========================================================================= #
230
+ # === run_already?
231
+ # ========================================================================= #
232
+ def run_already?
233
+ @internal_hash[:run_already]
234
+ end
235
+
236
+ # ========================================================================= #
237
+ # === enable_debug
238
+ # ========================================================================= #
239
+ def enable_debug
240
+ @internal_hash[:debug] = true
241
+ end
242
+
243
+ # ========================================================================= #
244
+ # === return_pwd
245
+ # ========================================================================= #
246
+ def return_pwd
247
+ "#{Dir.pwd}/".squeeze('/')
248
+ end
249
+
250
+ # ========================================================================= #
251
+ # === set_use_opn
252
+ # ========================================================================= #
253
+ def set_use_opn(i = true)
254
+ @internal_hash[:use_opn] = i
255
+ end
256
+
257
+ # ========================================================================= #
258
+ # === use_opn?
259
+ # ========================================================================= #
260
+ def use_opn?
261
+ @internal_hash[:use_opn]
262
+ end
263
+
264
+ # ========================================================================= #
265
+ # === set_commandline_arguments
266
+ # ========================================================================= #
267
+ def set_commandline_arguments(i = '')
268
+ i = [i].flatten.compact
269
+ @commandline_arguments = i
270
+ end
271
+
272
+ # ========================================================================= #
273
+ # === commandline_arguments?
274
+ # ========================================================================= #
275
+ def commandline_arguments?
276
+ @commandline_arguments
277
+ end
278
+
279
+ # ========================================================================= #
280
+ # === first_argument?
281
+ # ========================================================================= #
282
+ def first_argument?
283
+ @commandline_arguments.first
284
+ end; alias first? first_argument? # === first?
285
+
286
+ # ========================================================================= #
287
+ # === padded_extract_to?
288
+ # ========================================================================= #
289
+ def padded_extract_to?
290
+ " -C #{extract_to?} "
291
+ end
292
+
293
+ # ========================================================================= #
294
+ # === set_colour_for_directories
295
+ #
296
+ # Set the colour for directories to use.
297
+ # ========================================================================= #
298
+ def set_colour_for_directories(i)
299
+ @internal_hash[:colour_to_use_for_directories] = ::Colours.beautify(i)
300
+ end
301
+
302
+ # ========================================================================= #
303
+ # === extract_to?
304
+ #
305
+ # Note that this method is guaranteed to return a String.
306
+ # ========================================================================= #
307
+ def extract_to?
308
+ @internal_hash[:extract_to].to_s
309
+ end; alias source_package_location extract_to? # === source_package
310
+ alias extract_to_this_location? extract_to? # === extract_to_this_location?
311
+ alias extracted_to? extract_to? # === extracted_to?
312
+ alias extracted_path? extract_to? # === extracted_path?
313
+
314
+ # ========================================================================= #
315
+ # === opnn
316
+ #
317
+ # This variant will also check whether we should show the name or not.
318
+ # ========================================================================= #
319
+ def opnn(
320
+ use_this_hash = use_this_opn_hash?
321
+ )
322
+ if use_opn? and Object.const_defined?(:Opn) and show_the_name?
323
+ Opn.opn(use_this_hash)
324
+ end
325
+ end; alias opn opnn # === opn
326
+ alias copn opnn # === copn
327
+
328
+ # ========================================================================= #
329
+ # === use_this_opn_hash?
330
+ # ========================================================================= #
331
+ def use_this_opn_hash?
332
+ @internal_hash[:use_this_opn_hash]
333
+ end; alias main_hash? use_this_opn_hash? # === main_hash?
334
+
335
+ # ========================================================================= #
336
+ # === show_help (help tag)
337
+ #
338
+ # This method will show the available - and documented - help options
339
+ # for class Extracter.
340
+ #
341
+ # To call this method via the commandline try:
342
+ #
343
+ # extract --help
344
+ #
345
+ # ========================================================================= #
346
+ def show_help
347
+ e
348
+ opnn; e 'How to extract archives, without helper scripts?'
349
+ e
350
+ e ' tar -zxvf foobar.tar.gz # for .tar.gz'
351
+ e ' tar xvzf foobar.tgz # for .tgz'
352
+ e ' tar xvfJ foobar.tar.xz # for .tar.xz'
353
+ e ' tar jxf foobar.tar.bz2 # for .tar.bz2'
354
+ e ' tar -xf foobar.tar.bz2 # for .tbz'
355
+ e ' tar --lzip -xvf zutils-1.5.tar.lz # for .tar.lz'
356
+ e ' unsquashfs foobar-1.2.3.sxz # for .sxz'
357
+ e ' 7z x -so C:\home\x\src\htop\htop-3.0.5.tar.xz | 6z x -si -ttar # on windows'
358
+ e
359
+ opnn; e 'Furthermore, there are some commandline options '\
360
+ 'that can'
361
+ opnn; e 'be used for this class (class Extracter).'
362
+ e
363
+ e ' --to=/home/Temp # extract into the '\
364
+ 'directory /home/Temp/'
365
+ e
366
+ end
367
+
368
+ # ========================================================================= #
369
+ # === pad (pad tag)
370
+ #
371
+ # This method must be able to deal with ' ' as well as with '()'.
372
+ #
373
+ # The second character is the character that will be used for the
374
+ # padding.
375
+ # ========================================================================= #
376
+ def pad(
377
+ i, with_this_character = "'"
378
+ )
379
+ if i.include?('(') or i.include?(')')
380
+ i.tr!('(','\(')
381
+ i.tr!(')','\)') if i.include? ')'
382
+ i = pad(i, '"')
383
+ else
384
+ return with_this_character+
385
+ i+
386
+ with_this_character
387
+ end
388
+ end
389
+
390
+ # ========================================================================= #
391
+ # === namespace?
392
+ # ========================================================================= #
393
+ def namespace?
394
+ @internal_hash[:namespace]
395
+ end
396
+
397
+ # ========================================================================= #
398
+ # === be_verbose
399
+ # ========================================================================= #
400
+ def be_verbose
401
+ set_be_verbose(true)
402
+ end
403
+
404
+ # ========================================================================= #
405
+ # === be_silent
406
+ # ========================================================================= #
407
+ def be_silent
408
+ set_be_verbose(false)
409
+ end; alias be_quiet be_silent # === be_quiet
410
+
411
+ # ========================================================================= #
412
+ # === set_be_verbose
413
+ #
414
+ # This sets the verbosity level of the class. Use only this method
415
+ # when you wish to modify the @be_verbose instance variable.
416
+ # ========================================================================= #
417
+ def set_be_verbose(i = false)
418
+ @internal_hash[:be_verbose] = i
419
+ end; alias set_verbosity set_be_verbose # === set_verbosity
420
+
421
+ # ========================================================================= #
422
+ # === be_verbose?
423
+ #
424
+ # Getter method for whether we will be verbose or not.
425
+ # ========================================================================= #
426
+ def be_verbose?
427
+ @internal_hash[:be_verbose]
428
+ end
429
+
430
+ # ========================================================================= #
431
+ # === register_sigint
432
+ # ========================================================================= #
433
+ def register_sigint
434
+ Signal.trap('SIGINT') {
435
+ e sfancy('Requesting a graceful exit from ')+
436
+ colour_to_use_for_directories?+
437
+ 'class Extracter'+
438
+ sfancy('. Exiting now.')
439
+ exit
440
+ }
441
+ end
442
+
443
+ # ========================================================================= #
444
+ # === colour_to_use_for_directories?
445
+ # ========================================================================= #
446
+ def colour_to_use_for_directories?
447
+ if use_colours?
448
+ return @internal_hash[:colour_to_use_for_directories]
449
+ else
450
+ return ''
451
+ end
452
+ end
453
+
454
+ # ========================================================================= #
455
+ # === do_show_the_full_name_of_the_archive
456
+ # ========================================================================= #
457
+ def do_show_the_full_name_of_the_archive
458
+ @internal_hash[:show_the_full_name_of_the_archive] = true
459
+ end
460
+
461
+ # ========================================================================= #
462
+ # === prefix_namespace_with
463
+ # ========================================================================= #
464
+ def prefix_namespace_with(i)
465
+ @internal_hash[:namespace] = "#{i}#{@internal_hash[:namespace].dup}"
466
+ update_the_main_hash # Also update the opn-hash here.
467
+ end
468
+
469
+ # ========================================================================= #
470
+ # === pad_opn_with_n_tokens
471
+ # ========================================================================= #
472
+ def pad_opn_with_n_tokens(n_tokens = nil)
473
+ if n_tokens
474
+ determine_default_opn_hash # Update this, just in case.
475
+ main_hash?.update(padding: n_tokens)
476
+ end
477
+ end; alias set_pad_opn_with_n_tokens pad_opn_with_n_tokens # === set_pad_opn_with_n_tokens
478
+
479
+ # ========================================================================= #
480
+ # === prepare_the_hash_for_opn
481
+ # ========================================================================= #
482
+ def prepare_the_hash_for_opn(
483
+ use_this_hash = {
484
+ namespace: namespace?,
485
+ use_colours: use_colours?
486
+ }
487
+ )
488
+ # ======================================================================= #
489
+ # === :use_this_opn_hash
490
+ # ======================================================================= #
491
+ @internal_hash[:use_this_opn_hash] = use_this_hash
492
+ return @internal_hash[:use_this_opn_hash]
493
+ end; alias update_the_opn_hash prepare_the_hash_for_opn # === update_the_opn_hash
494
+ alias determine_default_opn_hash prepare_the_hash_for_opn # === determine_default_opn_hash
495
+ alias determine_the_default_opn_hash prepare_the_hash_for_opn # === determine_the_default_opn_hash
496
+ alias update_the_main_hash prepare_the_hash_for_opn # === update_the_main_hash
497
+
498
+ # ========================================================================= #
499
+ # === show_only_the_short_name_of_the_archive?
500
+ # ========================================================================= #
501
+ def show_only_the_short_name_of_the_archive?
502
+ @internal_hash[:show_only_the_short_name_of_the_archive]
503
+ end
504
+
505
+ # ========================================================================= #
506
+ # === set_run_simulation
507
+ # ========================================================================= #
508
+ def set_run_simulation(i = false) # false is the default here.
509
+ @internal_hash[:run_simulation] = i
510
+ end
511
+
512
+ # ========================================================================= #
513
+ # === run_simulation=
514
+ # ========================================================================= #
515
+ def run_simulation=(i)
516
+ @internal_hash[:run_simulation] = i
517
+ end
518
+
519
+ # ========================================================================= #
520
+ # === run_simulation?
521
+ # ========================================================================= #
522
+ def run_simulation?
523
+ @internal_hash[:run_simulation]
524
+ end
525
+
526
+ # ========================================================================= #
527
+ # === strip_components
528
+ #
529
+ # The first argument to this method will determine how far "down" tar
530
+ # will strip the components.
531
+ # ========================================================================= #
532
+ def strip_components(
533
+ by_n = 1
534
+ )
535
+ @internal_hash[:append_this_to_the_commandline] <<
536
+ " --strip-components=#{by_n}"
537
+ end
538
+
539
+ # ========================================================================= #
540
+ # === do_show_name
541
+ #
542
+ # If this method is called then the class here will show the name of
543
+ # the file on the commandline, via opn().
544
+ # ========================================================================= #
545
+ def do_show_name
546
+ @internal_hash[:show_the_name] = true
547
+ end
548
+
549
+ # ========================================================================= #
550
+ # === enable_colours
551
+ # ========================================================================= #
552
+ def enable_colours
553
+ set_use_colours(true)
554
+ @internal_hash[:colour_to_use_for_directories] = cyan?
555
+ end
556
+
557
+ # ========================================================================= #
558
+ # === report_to_the_user
559
+ #
560
+ # This method reports to the user. Usually this is done only via this
561
+ # file here though.
562
+ # ========================================================================= #
563
+ def report_to_the_user(
564
+ i, extract_to = extract_to?
565
+ )
566
+ if be_verbose?
567
+ opnn; e 'Finished extracting to `'+sdir(
568
+ extract_to+
569
+ remove_file_extension(
570
+ File.basename(i)
571
+ )+ # This is an Array.
572
+ '/'
573
+ )+'`.'
574
+ end
575
+ end
576
+
577
+ # ========================================================================= #
578
+ # === disable_colours
579
+ #
580
+ # Use this method if you want to disable colour-support of this class.
581
+ # ========================================================================= #
582
+ def disable_colours
583
+ set_use_colours(false)
584
+ @internal_hash[:colour_to_use_for_directories] = ''.dup
585
+ end
586
+
587
+ # ========================================================================= #
588
+ # === set_use_colours
589
+ # ========================================================================= #
590
+ def set_use_colours(i)
591
+ # ======================================================================= #
592
+ # We must also sync this towards our main Hash, for opn(). The next
593
+ # line of code achieves precisely that.
594
+ # ======================================================================= #
595
+ main_hash?.update(use_colours: i)
596
+ @internal_hash[:try_to_use_colours] = i
597
+ end
598
+
599
+ # ========================================================================= #
600
+ # === try_to_use_colours?
601
+ # ========================================================================= #
602
+ def try_to_use_colours?
603
+ @internal_hash[:try_to_use_colours]
604
+ end
605
+
606
+ # ========================================================================= #
607
+ # === remove_file_extension
608
+ # ========================================================================= #
609
+ def remove_file_extension(i)
610
+ _ = File.basename(i)
611
+ return ::Extracter.remove_archive_type(_)
612
+ end; alias remove_extension remove_file_extension # === remove_extensions
613
+ alias remove_ext remove_file_extension # === remove_ext
614
+
615
+ # ========================================================================= #
616
+ # === rds
617
+ # ========================================================================= #
618
+ def rds(i)
619
+ return i.squeeze('/') if i.respond_to? :squeeze
620
+ return i
621
+ end
622
+
623
+ # ========================================================================= #
624
+ # === set_extract_to
625
+ #
626
+ # This is the method that should be used to determine into which
627
+ # directory this class will extract archives into.
628
+ #
629
+ # Note that this target can be modified from the commandline, if
630
+ # the user wants to do so.
631
+ # ========================================================================= #
632
+ def set_extract_to(
633
+ i = :temp_dir
634
+ )
635
+ if i.is_a?(Hash) and i.empty?
636
+ i = :temp_dir
637
+ end
638
+ if i.is_a? Hash
639
+ # ===================================================================== #
640
+ # === :run_already
641
+ # ===================================================================== #
642
+ if i.has_key? :run_already
643
+ @internal_hash[:run_already] = i.delete(:run_already)
644
+ end
645
+ # ===================================================================== #
646
+ # === :prepend_this_namespace
647
+ # ===================================================================== #
648
+ if i.has_key? :prepend_this_namespace
649
+ prefix_with_this = i.delete(:prepend_this_namespace) # Get rid of it from the Hash as well.
650
+ prefix_namespace_with(prefix_with_this)
651
+ end
652
+ # ===================================================================== #
653
+ # === :use_colours
654
+ # ===================================================================== #
655
+ if i.has_key? :use_colours
656
+ set_use_colours(i.delete(:use_colours))
657
+ end
658
+ # ===================================================================== #
659
+ # === :verbosity
660
+ #
661
+ # Handle how verbose the class shall be.
662
+ # ===================================================================== #
663
+ if i.has_key? :verbosity
664
+ set_be_verbose(i.delete(:verbosity))
665
+ # ===================================================================== #
666
+ # === :be_verbose
667
+ # ===================================================================== #
668
+ elsif i.has_key? :be_verbose
669
+ set_be_verbose(i.delete(:be_verbose))
670
+ end
671
+ # ===================================================================== #
672
+ # === :append_this_to_the_commandline
673
+ # ===================================================================== #
674
+ if i.has_key? :append_this_to_the_commandline
675
+ @internal_hash[:append_this_to_the_commandline] =
676
+ i.delete(:append_this_to_the_commandline)
677
+ end
678
+ # ===================================================================== #
679
+ # === :use_opn
680
+ # ===================================================================== #
681
+ if i.has_key? :use_opn
682
+ set_use_opn(i.delete(:use_opn))
683
+ end
684
+ # ===================================================================== #
685
+ # === :pad_opn_with_n_tokens
686
+ # ===================================================================== #
687
+ if i.has_key? :pad_opn_with_n_tokens
688
+ set_pad_opn_with_n_tokens(i.delete(:pad_opn_with_n_tokens))
689
+ end
690
+ # ===================================================================== #
691
+ # === :run_simulation
692
+ # ===================================================================== #
693
+ if i.has_key? :run_simulation
694
+ set_run_simulation(i.delete(:run_simulation))
695
+ end
696
+ # ===================================================================== #
697
+ # === :use_colours
698
+ # ===================================================================== #
699
+ if i.has_key? :use_colours
700
+ set_use_colours(i.delete(use_colours))
701
+ end
702
+ # ===================================================================== #
703
+ # === :extract_to
704
+ #
705
+ # This entry point allows the user to specify another extract-to
706
+ # directory. Note that :to is treated the same way as :extract_to.
707
+ #
708
+ # This entry point must come last. The idea is that it will then
709
+ # become the new value for i.
710
+ # ===================================================================== #
711
+ if i.has_key? :extract_to
712
+ i = i.delete(:extract_to)
713
+ # ===================================================================== #
714
+ # === :to
715
+ # ===================================================================== #
716
+ elsif i.has_key? :to
717
+ i = i.delete(:to)
718
+ end
719
+ end
720
+ case i # case tag
721
+ # ======================================================================= #
722
+ # === :default
723
+ # ======================================================================= #
724
+ when :default
725
+ i = return_pwd
726
+ # ======================================================================= #
727
+ # === TEMP
728
+ # ======================================================================= #
729
+ when 'TEMP',
730
+ 'MY_TEMP',
731
+ 'MYTEMP',
732
+ :temp_dir,
733
+ nil
734
+ i = TEMP_DIR
735
+ end
736
+ i = rds(i)
737
+ i.gsub!(/--to=/,'') if i.include? '--to='
738
+ i = i.to_s.dup # We expect a String most definitely.
739
+ @internal_hash[:extract_to] = i
740
+ end; alias set_extract_to_this_location set_extract_to # === set_extract_to_this_location
741
+ alias extract_to= set_extract_to # === extract_to=
742
+ alias extract_to set_extract_to # === extract_to
743
+
744
+ # ========================================================================= #
745
+ # === try_to_extract_this_iso_file
746
+ # ========================================================================= #
747
+ def try_to_extract_this_iso_file(i)
748
+ opnn; e 'Extracting an .iso file is a bit more complicated '\
749
+ 'than extracting a .tar.gz tarball'
750
+ opnn; e 'archive. This class will first create a helper '\
751
+ 'directory; then mount the .iso there,'
752
+ opnn; e 'then copy the content to the main directory.'
753
+ helper_directory = File.dirname(i)+
754
+ '/READ_ONLY_DIRECTORY_'+
755
+ File.basename(
756
+ i.delete_suffix(File.extname(i))
757
+ )+
758
+ '/'
759
+ mkdir(helper_directory) unless File.directory? helper_directory
760
+ esystem 'mount -o loop '+i+' '+helper_directory
761
+ e 'The helper directory in use is '\
762
+ '`'+sdir(File.absolute_path(helper_directory))+'`.'
763
+ main_directory = File.dirname(i)+
764
+ '/'+
765
+ File.basename(
766
+ i.delete_suffix(File.extname(i))
767
+ )+
768
+ '/'
769
+ e 'Next creating the main directory at `'+sdir(main_directory)+'`.'
770
+ mkdir(main_directory) unless File.directory? main_directory
771
+ e 'Next copying the content of the helper directory recursively '
772
+ e 'from `'+sdir(helper_directory)+'`'
773
+ e 'onto `'+sdir(
774
+ main_directory+File.basename(helper_directory)+'/'
775
+ )+'`.'
776
+ cpr(
777
+ helper_directory,
778
+ main_directory+File.basename(helper_directory)+'/'
779
+ )
780
+ a = main_directory+File.basename(helper_directory)+'/'
781
+ e 'Relocating the files next from:'
782
+ e
783
+ e " #{sdir(a)}"
784
+ e
785
+ Dir[a+'*'].each {|entry|
786
+ mv(
787
+ entry,
788
+ main_directory
789
+ )
790
+ }
791
+ # ======================================================================= #
792
+ # And remove the directory:
793
+ # ======================================================================= #
794
+ remove_this_directory(a)
795
+ e 'The content of the extracted (or rather, mounted) archive is:'
796
+ e
797
+ pp Dir["#{main_directory}*"]
798
+ e
799
+ end
800
+
801
+ # ========================================================================= #
802
+ # === work_on_the_given_input
803
+ # ========================================================================= #
804
+ def work_on_the_given_input(
805
+ array = commandline_arguments?,
806
+ extract_to = extract_to?
807
+ )
808
+ # ======================================================================= #
809
+ # If the user supplied a directory then a random entry will be grabbed
810
+ # from said directory.
811
+ # ======================================================================= #
812
+ if array.is_a?(String) and File.directory?(array)
813
+ array = Dir[rds("#{array}/")+'*'].sample
814
+ end
815
+ case extract_to
816
+ when nil
817
+ extract_to = extract_to?
818
+ end
819
+ if array.empty?
820
+ opnn; e 'No archive (input) was provided. Please provide the file'
821
+ opnn; e 'that is to be extracted.'
822
+ else
823
+ array.each {|this_file|
824
+ # =================================================================== #
825
+ # Create the directory if it does not yet exist.
826
+ # =================================================================== #
827
+ create_directory(extract_to) unless File.directory?(extract_to)
828
+ # =================================================================== #
829
+ # Handle the case when the user did input a number.
830
+ # =================================================================== #
831
+ begin
832
+ if this_file =~ /^\d$/
833
+ this_file = Dir['*'][( this_file.to_i - 1 )] unless File.exist?(this_file)
834
+ end
835
+ rescue ArgumentError => error
836
+ e 'Error for '+sfancy(this_file)+':'
837
+ pp error
838
+ end
839
+ # =================================================================== #
840
+ # If the user supplied a directory then a random entry will be
841
+ # grabbed from said directory.
842
+ #
843
+ # Usage example:
844
+ #
845
+ # rubyextracter /home/x/src/htop/
846
+ #
847
+ # =================================================================== #
848
+ if File.directory? this_file
849
+ this_file = Dir[rds("#{this_file}/")+'*'].sample
850
+ end
851
+ extract_this_archive(this_file, extract_to)
852
+ report_to_the_user(this_file, extract_to)
853
+ }
854
+ end
855
+ end
856
+
857
+ # ========================================================================= #
858
+ # === create_directory (mkdir tag)
859
+ #
860
+ # Use this to create directories.
861
+ # ========================================================================= #
862
+ def create_directory(i)
863
+ FileUtils.mkdir_p(i) unless File.directory?(i)
864
+ end; alias mkdir create_directory # === mkdir
865
+
866
+ # ========================================================================= #
867
+ # === notify_the_user_that_this_extension_has_not_been_registered_yet
868
+ # ========================================================================= #
869
+ def notify_the_user_that_this_extension_has_not_been_registered_yet(i)
870
+ opnn; e "The archive at `#{i}` is #{tomato('not')}"
871
+ opnn; e "registered as a permissive extension."
872
+ fail_message_not_registered(i)
873
+ end
874
+
875
+ # ========================================================================= #
876
+ # === fail_message_not_registered
877
+ #
878
+ # Output a fail message when the archive format is not registered.
879
+ # ========================================================================= #
880
+ def fail_message_not_registered(i)
881
+ copn; e "Can not extract `#{sfancy(i)}` - it is not registered."
882
+ end
883
+
884
+ # ========================================================================= #
885
+ # === try_to_extract_this_img_file
886
+ # ========================================================================= #
887
+ def try_to_extract_this_img_file(i)
888
+ opnn; e 'Handling a squashfs .img file format next:'
889
+ name_without_extension = i.delete_suffix(File.extname(i))
890
+ mkdir(name_without_extension) unless File.directory? name_without_extension
891
+ esystem "mount -o loop -t squashfs #{i} #{name_without_extension}"
892
+ e 'The content of the extracted (or rather, mounted) archive is:'
893
+ pp Dir["#{name_without_extension}*"]
894
+ end
895
+
896
+ # ========================================================================= #
897
+ # === menu (menu tag)
898
+ # ========================================================================= #
899
+ def menu(
900
+ i = commandline_arguments?
901
+ )
902
+ if i.is_a? Array
903
+ i.each {|entry| menu(entry) }
904
+ else
905
+ case i
906
+ # ===================================================================== #
907
+ # === --help
908
+ # ===================================================================== #
909
+ when /^-?-?help$/i
910
+ show_help
911
+ exit
912
+ end
913
+ end
914
+ end
915
+
916
+ # ========================================================================= #
917
+ # === esystem (system tag, esystem tag)
918
+ # ========================================================================= #
919
+ def esystem(
920
+ i, try_to_use_colours = try_to_use_colours?
921
+ )
922
+ i = i.dup if i.frozen?
923
+ # ======================================================================= #
924
+ # Next, consider appending something onto the commandline.
925
+ # ======================================================================= #
926
+ _ = @internal_hash[:append_this_to_the_commandline]
927
+ unless _.empty?
928
+ if i.include? ' '
929
+ splitted = i.split(' ')
930
+ splitted[0] << " #{_}"
931
+ i = splitted.join(' ')
932
+ else
933
+ i << " #{_}"
934
+ end
935
+ end
936
+ if run_simulation?
937
+ copn; e 'As we are running in simulation mode, the following command '
938
+ copn; e 'is the one that we would have been used if we were to not run '
939
+ copn; e 'in simulation mode:'
940
+ if be_verbose?
941
+ if try_to_use_colours
942
+ e ::Colours.steelblue(i)
943
+ else
944
+ e i
945
+ end
946
+ end
947
+ else
948
+ if be_verbose?
949
+ if try_to_use_colours
950
+ e ::Colours.steelblue(i)
951
+ else
952
+ e i
953
+ end
954
+ end
955
+ # ===================================================================== #
956
+ # Next, run the sys-command.
957
+ # ===================================================================== #
958
+ begin
959
+ system i
960
+ # =================================================================== #
961
+ # We have to rescue here because unrar might not be available and
962
+ # so on.
963
+ # =================================================================== #
964
+ rescue Exception => error
965
+ e 'An error has happened upon attempting to run this system command:'
966
+ e
967
+ e " #{i}"
968
+ e
969
+ pp error; e '-----------'; pp error.class; e '-----------'
970
+ end
971
+ end
972
+ end; alias run_this_system_command esystem # === run_this_system_command
973
+
974
+ # ========================================================================= #
975
+ # === run (run tag, def tag)
976
+ # ========================================================================= #
977
+ def run
978
+ menu
979
+ work_on_the_given_input
980
+ end
981
+
982
+ # ========================================================================= #
983
+ # === Extracter::Extracter.extract_this
984
+ #
985
+ # This method provides a convenient API to extract something to a
986
+ # specified directory, as a class method. It defaults to the
987
+ # current working directory, as that is by far the most convenient
988
+ # way to extract a source tarball/archive.
989
+ #
990
+ # ========================================================================= #
991
+ def self.extract_this(
992
+ i = ARGV,
993
+ to = {}, # This may also be a String rather than a Hash.
994
+ &block
995
+ )
996
+ ::Extracter::Extracter.new(ARGV, to, &block)
997
+ end; self.instance_eval { alias what_to extract_this } # === Extracter::Extracter.what_to
998
+ self.instance_eval { alias extract extract_this } # === Extracter::Extracter.extract
999
+ self.instance_eval { alias extract_what_to extract_this } # === Extracter::Extracter.extract_what_to
1000
+
1001
+ # ========================================================================= #
1002
+ # === Extracter::Extracter[]
1003
+ # ========================================================================= #
1004
+ def self.[](i = ARGV, extract_where_to = Dir.pwd)
1005
+ new(i, extract_where_to)
1006
+ end
1007
+
1008
+ end
1009
+
1010
+ # ========================================================================= #
1011
+ # === Extracter.extract_what_to
1012
+ #
1013
+ # Useage example goes like this:
1014
+ #
1015
+ # Extracter.extract_what_to('foo-1.0.tar.xz', '/tmp')
1016
+ # Extracter.extract_what_to('/Depot/jjjj/tesseract-5.1.0.tar.xz', Dir.pwd+'/')
1017
+ #
1018
+ # ========================================================================= #
1019
+ def self.extract_what_to(
1020
+ what = ARGV,
1021
+ extract_to = :default, # ← This can also be a Hash. It denotes where we want to extract to.
1022
+ run_already = true, # :do_not_run_yet,
1023
+ &block
1024
+ )
1025
+ _ = ::Extracter::Extracter.new(
1026
+ what,
1027
+ extract_to,
1028
+ run_already,
1029
+ &block
1030
+ )
1031
+ return _ # We must return the class, as other projects may depend on this.
1032
+ end; self.instance_eval { alias extract_this extract_what_to } # === Extracter.extract_this
1033
+ self.instance_eval { alias extract extract_what_to } # === Extracter.extract
1034
+ self.instance_eval { alias what_to extract_what_to } # === Extracter.what_to
1035
+ self.instance_eval { alias new extract_what_to } # === Extracter.new
1036
+ self.instance_eval { alias [] extract_what_to } # === Extracter[]
1037
+
1038
+ end
1039
+
1040
+ if __FILE__ == $PROGRAM_NAME
1041
+ _ = Extracter::Extracter.new(ARGV) { :do_not_run_yet }
1042
+ if ARGV.size > 2
1043
+ _ = Extracter::Extracter.new(ARGV, :default) { :do_not_run_yet }
1044
+ else
1045
+ _ = Extracter::Extracter.new(ARGV[0], ARGV[1]) { :do_not_run_yet }
1046
+ end
1047
+ # _.enable_debug
1048
+ _.be_verbose
1049
+ # _.strip_components # This would be equivalent to: --strip-components=1
1050
+ _.run
1051
+ end # rubyextracter
1052
+ # extracter
1053
+ # extracter htop-1.0.2.tar.xz
1054
+ # extracter xfig-3.2.5.tar.bz2
1055
+ # extract htop* /Depot/
1056
+ # extract recode-3.7.tar.xz /Depot/
1057
+ # extract qt-4.8.6.tar.xz --to=/home/Temp