backup_paradise 1.3.1

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

Potentially problematic release.


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

Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +408 -0
  3. data/backup_paradise.gemspec +50 -0
  4. data/bin/backup_for_ingrid +10 -0
  5. data/bin/backup_paradise +7 -0
  6. data/bin/windows_backup_paradise +9 -0
  7. data/doc/README.gen +368 -0
  8. data/doc/TODO.md +130 -0
  9. data/lib/backup_paradise/actions/README.md +2 -0
  10. data/lib/backup_paradise/actions/backup.rb +62 -0
  11. data/lib/backup_paradise/base/base.rb +502 -0
  12. data/lib/backup_paradise/base/colours.rb +137 -0
  13. data/lib/backup_paradise/base/namespace.rb +16 -0
  14. data/lib/backup_paradise/base/tab.rb +47 -0
  15. data/lib/backup_paradise/colours/colours.rb +88 -0
  16. data/lib/backup_paradise/constants/constants.rb +162 -0
  17. data/lib/backup_paradise/gui/glimmer/libui/backup_for_ingrid/backup_for_ingrid.rb +87 -0
  18. data/lib/backup_paradise/gui/gtk2/OLD_backup.rb +220 -0
  19. data/lib/backup_paradise/gui/gtk3/simple_backup_widget/create.rb +70 -0
  20. data/lib/backup_paradise/gui/gtk3/simple_backup_widget/misc.rb +33 -0
  21. data/lib/backup_paradise/gui/gtk3/simple_backup_widget/simple_backup_widget.rb +160 -0
  22. data/lib/backup_paradise/gui/libui/backup_for_ingrid/backup_for_ingrid.rb +99 -0
  23. data/lib/backup_paradise/gui/libui/simple_backup_widget/simple_backup_widget.rb +119 -0
  24. data/lib/backup_paradise/gui/shared_code/simple_backup_widget/simple_backup_widget_module.rb +587 -0
  25. data/lib/backup_paradise/gui/tk/backup.rb +108 -0
  26. data/lib/backup_paradise/images/BACKUP_IMAGE.png +0 -0
  27. data/lib/backup_paradise/images/right_arrow.png +0 -0
  28. data/lib/backup_paradise/project/project.rb +40 -0
  29. data/lib/backup_paradise/requires/require_the_backup_paradise_project.rb +18 -0
  30. data/lib/backup_paradise/requires/require_yaml.rb +7 -0
  31. data/lib/backup_paradise/tab/tab.rb +87 -0
  32. data/lib/backup_paradise/toplevel_methods/cliner.rb +16 -0
  33. data/lib/backup_paradise/toplevel_methods/config.rb +86 -0
  34. data/lib/backup_paradise/toplevel_methods/create_and_remove.rb +63 -0
  35. data/lib/backup_paradise/toplevel_methods/e.rb +16 -0
  36. data/lib/backup_paradise/toplevel_methods/esystem.rb +19 -0
  37. data/lib/backup_paradise/toplevel_methods/files_and_directories.rb +181 -0
  38. data/lib/backup_paradise/toplevel_methods/help.rb +93 -0
  39. data/lib/backup_paradise/toplevel_methods/misc.rb +153 -0
  40. data/lib/backup_paradise/toplevel_methods/mountpoint.rb +188 -0
  41. data/lib/backup_paradise/toplevel_methods/opnn.rb +27 -0
  42. data/lib/backup_paradise/utility_scripts/backup/backup.rb +1901 -0
  43. data/lib/backup_paradise/version/version.rb +19 -0
  44. data/lib/backup_paradise/windows/README.md +1 -0
  45. data/lib/backup_paradise/windows/windows.rb +101 -0
  46. data/lib/backup_paradise/www/backup.cgi +63 -0
  47. data/lib/backup_paradise/yaml/config.yml +82 -0
  48. data/lib/backup_paradise.rb +5 -0
  49. data/test/testing_toplevel_functionality.rb +11 -0
  50. metadata +194 -0
@@ -0,0 +1,1901 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === BackupParadise::Backup
6
+ #
7
+ # This is the main class that will be used for making a backup, usually
8
+ # onto an external USB device, but optionally also to another (second)
9
+ # harddisc (HDD).
10
+ #
11
+ # Note that this class will still store some information on the toplevel
12
+ # namespace where we will backup to.
13
+ #
14
+ # For a listing of specific options have a look at the file "help.rb",
15
+ # or do "rbackup help" from the commandline.
16
+ #
17
+ # Usage example:
18
+ #
19
+ # BackupParadise::Backup.new(ARGV)
20
+ #
21
+ # =========================================================================== #
22
+ # require 'backup_paradise/utility_scripts/backup/backup.rb'
23
+ # BackupParadise::Backup.new(hash)
24
+ # =========================================================================== #
25
+ require 'backup_paradise/base/base.rb'
26
+
27
+ module BackupParadise
28
+
29
+ class Backup < ::BackupParadise::Base # === BackupParadise::Backup
30
+
31
+ require 'backup_paradise/toplevel_methods/config.rb'
32
+ require 'backup_paradise/toplevel_methods/help.rb'
33
+ require 'backup_paradise/toplevel_methods/mountpoint.rb'
34
+ require 'backup_paradise/version/version.rb'
35
+
36
+ # ========================================================================= #
37
+ # === NAMESPACE
38
+ # ========================================================================= #
39
+ NAMESPACE = inspect
40
+
41
+ # ========================================================================= #
42
+ # === MINIMAL_FILESIZE
43
+ # ========================================================================= #
44
+ MINIMAL_FILESIZE = 5 * (1000 ** 3) # 5 * 1024 * 1024 * 1024
45
+
46
+ # ========================================================================= #
47
+ # === FILE_BACKUP_LOG
48
+ #
49
+ # Denote where to keep the backup.log file, if we log that is.
50
+ # ========================================================================= #
51
+ if File.directory? '/home/Temp/'
52
+ FILE_BACKUP_LOG = '/home/Temp/backup.log'
53
+ else
54
+ FILE_BACKUP_LOG = '/tmp/backup.log'
55
+ end
56
+
57
+ # ========================================================================= #
58
+ # === TRY_TO_SHOW_BACKUP_COMPLETE_MESSAGE_VIA_LIBUI
59
+ #
60
+ # If the following constant is true then this class will try to make
61
+ # use of libui and the libui_paradise gem to show a little libui
62
+ # message box (a window) about how the backup action is now
63
+ # complete.
64
+ # ========================================================================= #
65
+ TRY_TO_SHOW_BACKUP_COMPLETE_MESSAGE_VIA_LIBUI = true
66
+
67
+ # ========================================================================= #
68
+ # === initialize
69
+ #
70
+ # Invocation example:
71
+ #
72
+ # x = BackupParadise::Backup.new(nil, :do_not_run_yet)
73
+ #
74
+ # ========================================================================= #
75
+ def initialize(
76
+ commandline_arguments = nil,
77
+ run_already = true,
78
+ &block
79
+ )
80
+ register_sigint
81
+ reset
82
+ if commandline_arguments
83
+ if commandline_arguments.is_a?(Symbol)
84
+ case commandline_arguments
85
+ # =================================================================== #
86
+ # === :do_not_run_yet
87
+ # =================================================================== #
88
+ when :do_not_run_yet
89
+ run_already = false
90
+ end
91
+ else
92
+ set_commandline_arguments(
93
+ commandline_arguments
94
+ )
95
+ end
96
+ end
97
+ case run_already
98
+ # ======================================================================= #
99
+ # === :do_not_run_yet
100
+ # ======================================================================= #
101
+ when :do_not_run_yet
102
+ run_already = false
103
+ end
104
+ # ======================================================================= #
105
+ # === Handle blocks given next
106
+ # ======================================================================= #
107
+ if block_given?
108
+ yielded = yield
109
+ case yielded
110
+ # ===================================================================== #
111
+ # === :do_not_run_yet
112
+ # ===================================================================== #
113
+ when :do_not_run_yet
114
+ run_already = false
115
+ # ===================================================================== #
116
+ # === :we_are_on_windows
117
+ # ===================================================================== #
118
+ when :we_are_on_windows
119
+ @internal_hash[:are_we_on_windows] = true
120
+ end
121
+ end
122
+ run if run_already
123
+ end
124
+
125
+ # ========================================================================= #
126
+ # === reset (reset tag)
127
+ # ========================================================================= #
128
+ def reset
129
+ super()
130
+ # ======================================================================= #
131
+ # === @mountpoint
132
+ # ======================================================================= #
133
+ @mountpoint = nil
134
+ # ======================================================================= #
135
+ # === @internal_hash
136
+ # ======================================================================= #
137
+ @internal_hash = {}
138
+ # ======================================================================= #
139
+ # === :simplify_the_directory_layout
140
+ #
141
+ # If the following variable is set to true then this means that the
142
+ # target directory will be slightly simplified. There will not be
143
+ # any ':' characters; these will become '_' characters.
144
+ #
145
+ # This was necessary because windows NTFS seems to struggle with
146
+ # ':' characters.
147
+ # ======================================================================= #
148
+ @internal_hash[:simplify_the_directory_layout] = true
149
+ # ======================================================================= #
150
+ # === :perform_backup
151
+ #
152
+ # The next variable determines whether we will perform a backup
153
+ # job or not. By default this will be false - it will be set
154
+ # to true through the menu() interface, via its else clause.
155
+ # ======================================================================= #
156
+ @internal_hash[:perform_backup] = true
157
+ # ======================================================================= #
158
+ # === :are_we_on_windows
159
+ #
160
+ # This can be used to overrule any other windows-specific checks.
161
+ # ======================================================================= #
162
+ @internal_hash[:are_we_on_windows] = nil
163
+ # ======================================================================= #
164
+ # === :date
165
+ # ======================================================================= #
166
+ @internal_hash[:date] = dd_mm_yyyy
167
+ # ======================================================================= #
168
+ # === :show_popup_notification
169
+ # ======================================================================= #
170
+ @internal_hash[:show_popup_notification] =
171
+ BackupParadise.show_popup_notification?
172
+ # ======================================================================= #
173
+ # === :last_backup_directory
174
+ # ======================================================================= #
175
+ @internal_hash[:last_backup_directory] = nil
176
+ # ======================================================================= #
177
+ # === :array_store_times
178
+ #
179
+ # The next Array will keep track of how long it took to backup
180
+ # the data.
181
+ # ======================================================================= #
182
+ @internal_hash[:array_store_times] = []
183
+ # ======================================================================= #
184
+ # === :use_this_as_timestamp
185
+ #
186
+ # The next variable will keep the timestamp as-is.
187
+ #
188
+ # This may include ':' characters, which Windows NTFS does not seem
189
+ # to like. Thus, since as of September 2020, a slightly simpler
190
+ # variant is used here.
191
+ # ======================================================================= #
192
+ determine_the_current_timestamp
193
+ # ======================================================================= #
194
+ # === :backup_these_directories
195
+ #
196
+ # Determine the directories that we wish to back up.
197
+ # ======================================================================= #
198
+ @internal_hash[:backup_these_directories] = all_important_directories?
199
+ end
200
+
201
+ # ========================================================================= #
202
+ # === start_the_gtk3_bindings
203
+ #
204
+ # To invoke this method, try:
205
+ #
206
+ # rbackup --gui
207
+ # rbackup --gtk
208
+ #
209
+ # ========================================================================= #
210
+ def start_the_gtk3_bindings
211
+ require 'backup_paradise/gui/gtk3/simple_backup_widget/simple_backup_widget.rb'
212
+ BackupParadise::GUI::Gtk::SimpleBackupWidget.run
213
+ end
214
+
215
+ # ========================================================================= #
216
+ # === default_tab_title
217
+ # ========================================================================= #
218
+ def default_tab_title
219
+ tab_title('Backup is complete!')
220
+ end
221
+
222
+ # ========================================================================= #
223
+ # === backup_which_directories?
224
+ # ========================================================================= #
225
+ def backup_which_directories?
226
+ @internal_hash[:backup_these_directories]
227
+ end
228
+
229
+ # ========================================================================= #
230
+ # === return_this_absolute_directory
231
+ # ========================================================================= #
232
+ def return_this_absolute_directory(i)
233
+ i = case i
234
+ # ======================================================================= #
235
+ # === DATA_DIRECTORY
236
+ # ======================================================================= #
237
+ when 'DATA_DIRECTORY'
238
+ DATA_DIRECTORY
239
+ # ======================================================================= #
240
+ # === SRC_DIRECTORY
241
+ # ======================================================================= #
242
+ when 'SRC_DIRECTORY',
243
+ 'SOURCE_DIRECTORY'
244
+ SOURCE_DIRECTORY
245
+ # ======================================================================= #
246
+ # === STUDIUM_DIRECTORY
247
+ # ======================================================================= #
248
+ when 'STUDIUM_DIRECTORY'
249
+ STUDIUM_DIRECTORY
250
+ else
251
+ i
252
+ end
253
+ i
254
+ end
255
+
256
+ # ========================================================================= #
257
+ # === return_the_songs_directory
258
+ # ========================================================================= #
259
+ def return_the_songs_directory
260
+ DIRECTORY_CONTAINING_ALL_SONGS
261
+ end
262
+
263
+ # ========================================================================= #
264
+ # === show_help
265
+ # ========================================================================= #
266
+ def show_help
267
+ BackupParadise.show_help
268
+ end; alias display_help show_help # === display_help
269
+
270
+ # ========================================================================= #
271
+ # === simplify_the_directory_layout?
272
+ # ========================================================================= #
273
+ def simplify_the_directory_layout?
274
+ @internal_hash[:simplify_the_directory_layout]
275
+ end
276
+
277
+ # ========================================================================= #
278
+ # === set_commandline_arguments
279
+ # ========================================================================= #
280
+ def set_commandline_arguments(i = ARGV)
281
+ @commandline_arguments = i
282
+ end
283
+
284
+ # ========================================================================= #
285
+ # === commandline_arguments?
286
+ # ========================================================================= #
287
+ def commandline_arguments?
288
+ @commandline_arguments
289
+ end
290
+
291
+ # ========================================================================= #
292
+ # === first_argument?
293
+ # ========================================================================= #
294
+ def first_argument?
295
+ @commandline_arguments.first
296
+ end; alias first? first_argument? # === first?
297
+
298
+ # ========================================================================= #
299
+ # === is_target_harddisc_a_ntfs_system?
300
+ #
301
+ # This method will return a boolean - true or false.
302
+ #
303
+ # It will return true if the target harddisc is a NTFS system, and
304
+ # false otherwise.
305
+ # ========================================================================= #
306
+ def is_target_harddisc_a_ntfs_system?
307
+ return_value = false
308
+ _ = '/Mount'
309
+ if mount_target?.include? _
310
+ # ===================================================================== #
311
+ # Next, determine what is mounted.
312
+ # ===================================================================== #
313
+ these_may_be_mounted = `df -T -ah`.split(N).select {|line| line.include? _ }
314
+ if these_may_be_mounted and these_may_be_mounted.first and
315
+ these_may_be_mounted.first.include?('fuseblk') # This may mean a NTFS system.
316
+ return_value = true
317
+ end
318
+ end
319
+ return return_value
320
+ end
321
+
322
+ # ========================================================================= #
323
+ # === determine_whether_the_target_harddisc_is_a_ntfs_system
324
+ # ========================================================================= #
325
+ def determine_whether_the_target_harddisc_is_a_ntfs_system
326
+ if is_target_harddisc_a_ntfs_system?
327
+ do_use_simplified_directory
328
+ end
329
+ end
330
+
331
+ # ========================================================================= #
332
+ # === return_the_assumed_mountpoint_from_this_input
333
+ # ========================================================================= #
334
+ def return_the_assumed_mountpoint_from_this_input(i)
335
+ BackupParadise.return_the_assumed_mountpoint_from_this_input(i)
336
+ end
337
+
338
+ # ========================================================================= #
339
+ # === set_mountpoint
340
+ # ========================================================================= #
341
+ def set_mountpoint(i)
342
+ i = i.dup
343
+ if BackupParadise.is_this_a_shortcut?(i)
344
+ i = return_the_assumed_mountpoint_from_this_input(i)
345
+ end
346
+ i = i.dup if i.frozen?
347
+ i << '/' unless i.end_with? '/'
348
+ @mountpoint = i
349
+ # ======================================================================= #
350
+ # Sync it back to the toplevel as well:
351
+ # ======================================================================= #
352
+ determine_the_target_mountpoint(@mountpoint)
353
+ determine_where_to_backup_to_exactly
354
+ end; alias set_backup_to_this_target set_mountpoint # === set_backup_to_this_target
355
+ alias set_target_mountpoint set_mountpoint # === set_target_mountpoint
356
+
357
+ # ========================================================================= #
358
+ # === determine_the_current_timestamp
359
+ # ========================================================================= #
360
+ def determine_the_current_timestamp
361
+ if @internal_hash[:simplify_the_directory_layout]
362
+ @internal_hash[:use_this_as_timestamp] =
363
+ "#{date?}-#{current_time.tr(':','_')}"
364
+ else
365
+ @internal_hash[:use_this_as_timestamp] =
366
+ "#{date?}-#{current_time}"
367
+ end
368
+ end
369
+
370
+ # ========================================================================= #
371
+ # === date?
372
+ # ========================================================================= #
373
+ def date?
374
+ @internal_hash[:date]
375
+ end
376
+
377
+ # ========================================================================= #
378
+ # === use_this_as_timestamp?
379
+ # ========================================================================= #
380
+ def use_this_as_timestamp?
381
+ @internal_hash[:use_this_as_timestamp]
382
+ end
383
+
384
+ # ========================================================================= #
385
+ # === sanitize_the_commandline_arguments
386
+ #
387
+ # This method will try to make sense of the passed arguments.
388
+ # ========================================================================= #
389
+ def sanitize_the_commandline_arguments(
390
+ hash = commandline_arguments?
391
+ )
392
+ copy = hash.dup
393
+ # ======================================================================= #
394
+ # === :commandline_arguments
395
+ # ======================================================================= #
396
+ if hash.is_a?(Hash) and hash.has_key?(:commandline_arguments)
397
+ hash[:commandline_arguments].each {|entry|
398
+ if BackupParadise.is_this_a_shortcut?(entry)
399
+ copy[:backup_to_this_target] =
400
+ BackupParadise.return_the_assumed_mountpoint_from_this_input(entry)
401
+ copy[:commandline_arguments].reject! {|inner_entry|
402
+ inner_entry == entry
403
+ }
404
+ end
405
+ }
406
+ set_commandline_arguments(copy)
407
+ end
408
+ end
409
+
410
+ # ========================================================================= #
411
+ # === can_not_backup_this_directory_as_it_does_not_exist
412
+ # ========================================================================= #
413
+ def can_not_backup_this_directory_as_it_does_not_exist(i)
414
+ opnn; e "Can not backup the directory at #{sdir(i)}"
415
+ opnn; e 'as it does not exist.'
416
+ end
417
+
418
+ # ========================================================================= #
419
+ # === try_to_unmount_the_device
420
+ #
421
+ # This method can be used to automatically unmount the target device
422
+ # again.
423
+ # ========================================================================= #
424
+ def try_to_unmount_the_device
425
+ this_is_the_mounted_device = backup_to_this_directory?
426
+ # ======================================================================= #
427
+ # Change directory to another directory where we can safely
428
+ # umount the directory.
429
+ # ======================================================================= #
430
+ if has_superuser_abilities?
431
+ if BackupParadise.target_mountpoint?.include?('HDD1')
432
+ # =================================================================== #
433
+ # Unmount harddiscs quickly.
434
+ # =================================================================== #
435
+ unmount :hdd # Since as of 17.06.2008 we will unmount the harddisc as well.
436
+ end
437
+ if File.directory? '/Depot/j/'
438
+ cd '/Depot/j/'
439
+ elsif File.directory? '/tmp'
440
+ cd '/tmp'
441
+ elsif File.directory? '/home/Temp'
442
+ cd '/home/Temp'
443
+ else
444
+ cd '/'
445
+ end
446
+ opnn; e "Next unmounting the device at "\
447
+ "`#{sfancy(this_is_the_mounted_device)}`."
448
+ system "umount #{this_is_the_mounted_device}"
449
+ end
450
+ end
451
+
452
+ # ========================================================================= #
453
+ # === consider_renaming_all_old_last_backup_directories
454
+ #
455
+ # This will rename all "last_directory*" directory entries to their
456
+ # corresponding equivalent without the leading 'last_' string.
457
+ # ========================================================================= #
458
+ def consider_renaming_all_old_last_backup_directories
459
+ # ======================================================================= #
460
+ # First grab all possible entries, and check that these are all existing
461
+ # directories. If there is at the least one entry we will continue to
462
+ # operate on it.
463
+ # ======================================================================= #
464
+ all_possible_entries = Dir["#{mount_target?}last_backup-*"].select {|entry|
465
+ File.directory?(entry)
466
+ }
467
+ if all_possible_entries.size > 0
468
+ # ===================================================================== #
469
+ # Batch-rename these directories in that case:
470
+ # ===================================================================== #
471
+ all_possible_entries.each {|this_directory|
472
+ new_name_of_the_new_target_directory = this_directory.sub(/^last_/,'')
473
+ opnn; e "Now renaming `#{sdir(this_directory)}` "\
474
+ "to `#{sdir(new_name_of_the_new_target_directory)}`."
475
+ rename(this_directory, new_name_of_the_new_target_directory)
476
+ }
477
+ end
478
+ end
479
+
480
+ # ========================================================================= #
481
+ # === verbose_create_a_directory_at_this_position
482
+ #
483
+ # The first argument to this method should be the target directory,
484
+ # a path, that is where you wish to create that directory.
485
+ #
486
+ # The second argument to this method, which is optional, denotes the
487
+ # permission that is to be used.
488
+ # ========================================================================= #
489
+ def verbose_create_a_directory_at_this_position(
490
+ this_position, use_this_permission = 0754
491
+ )
492
+ e "Creating a directory at `#{sdir(this_position)}` next."
493
+ mkdir(this_position, use_this_permission)
494
+ end
495
+
496
+ # ========================================================================= #
497
+ # === show_the_logfile
498
+ #
499
+ # To invoke this method from the commandline, try:
500
+ #
501
+ # advanced_backup --logfile?
502
+ #
503
+ # ========================================================================= #
504
+ def show_the_logfile
505
+ _ = FILE_BACKUP_LOG
506
+ if File.exist? _
507
+ opnn; e "Now reading the dataset from the file `#{sfile(_)}`:"
508
+ e
509
+ File.readlines(_).each {|line|
510
+ e orangered(" #{line.chomp}")
511
+ }
512
+ e
513
+ else
514
+ opnn; e no_file_exists_at(_)
515
+ end
516
+ end
517
+
518
+ # ========================================================================= #
519
+ # === show_popup_notification?
520
+ # ========================================================================= #
521
+ def show_popup_notification?
522
+ @internal_hash[:show_popup_notification]
523
+ end
524
+
525
+ # ========================================================================= #
526
+ # === do_show_popup
527
+ # ========================================================================= #
528
+ def do_show_popup
529
+ @internal_hash[:show_popup_notification] = true
530
+ end; alias show_popup do_show_popup # === show_popup
531
+
532
+ # ========================================================================= #
533
+ # === determine_where_to_backup_to_exactly
534
+ #
535
+ # This is automatically called whenever set_mountpoint() is called.
536
+ # ========================================================================= #
537
+ def determine_where_to_backup_to_exactly(
538
+ i = @mountpoint
539
+ )
540
+ backup_to_this_target = i
541
+ @backup_to_this_target = backup_to_this_target.dup
542
+ @backup_to_this_target << "/backup-#{return_current_date_and_time}/"
543
+ @backup_to_this_target = @backup_to_this_target.squeeze('/')
544
+ @backup_to_this_target.tr!(':','_') if simplify_the_directory_layout?
545
+ set_last_backup_directory(@backup_to_this_target)
546
+ end
547
+
548
+ # ========================================================================= #
549
+ # === mountpoint?
550
+ # ========================================================================= #
551
+ def mountpoint?
552
+ @mountpoint
553
+ end; alias mounted_at? mountpoint? # === mounted_at?
554
+ alias target_base_directory? mountpoint? # === target_base_directory?
555
+
556
+ # ========================================================================= #
557
+ # === opnn
558
+ # ========================================================================= #
559
+ def opnn(i = NAMESPACE)
560
+ if i.is_a? String
561
+ i = { namespace: i }
562
+ end
563
+ super(i)
564
+ end
565
+
566
+ # ========================================================================= #
567
+ # === backup_the_audio_directory_then_exit
568
+ #
569
+ # Backup the audio directory, then exit the program.
570
+ # ========================================================================= #
571
+ def backup_the_audio_directory_then_exit
572
+ backup_the_audio_directory
573
+ exit_program
574
+ end
575
+
576
+ # ========================================================================= #
577
+ # === do_use_simplified_directory
578
+ #
579
+ # The old code used to be like this:
580
+ #
581
+ # set_last_backup_directory(mount_point?+'last_backup')
582
+ #
583
+ # ========================================================================= #
584
+ def do_use_simplified_directory
585
+ @internal_hash[:simplify_the_directory_layout] = true
586
+ determine_the_current_timestamp # Must sync it back again.
587
+ end
588
+
589
+ # ========================================================================= #
590
+ # === create_file_keeping_track_of_when_the_last_backup_happened
591
+ #
592
+ # This method will store date-information into a file, when the last
593
+ # backup happened.
594
+ #
595
+ # It is normally found in a place such as:
596
+ #
597
+ # /home/x/data/LAST_BACKUP.md
598
+ #
599
+ # Since Dec 2012, we will also append the date to the name of said file.
600
+ # ========================================================================= #
601
+ def create_file_keeping_track_of_when_the_last_backup_happened(
602
+ use_this_as_timestamp = use_this_as_timestamp?
603
+ )
604
+ base_target = "#{data_directory?}LAST_BACKUP"
605
+ target = "#{base_target}_#{date?}.md" # Append the date here.
606
+ e N+'Storing '+sfile(use_this_as_timestamp)+' into '+
607
+ sfile(target)+' to note'
608
+ e 'down when the last backup was performed.'
609
+ write_what_into(use_this_as_timestamp, target)
610
+ # ======================================================================= #
611
+ # Next, obtain an array with potential similar names. We will have
612
+ # to delete stray entries so as to not clutter our original home
613
+ # directory there.
614
+ # ======================================================================= #
615
+ array_all_last_backup_files = Dir["#{base_target}*"]
616
+ if array_all_last_backup_files.size > 1
617
+ array_all_last_backup_files = array_all_last_backup_files.sort_by {|d|
618
+ d.split('.').reverse
619
+ } # Keep it sorted.
620
+ e N+'We found more than one entry in '+
621
+ sdir(File.dirname(base_target)+'/')+', thus removing'
622
+ e 'the extra-entries next.'
623
+ array_all_last_backup_files[0..-2].each {|my_file|
624
+ e "Removing `#{sfile(my_file)}` next."
625
+ remove_file(my_file)
626
+ }
627
+ end
628
+ end; alias store_when_was_the_last_backup create_file_keeping_track_of_when_the_last_backup_happened # === store_when_was_the_last_backup
629
+
630
+ # ========================================================================= #
631
+ # === show_available_mountpoints
632
+ #
633
+ # This helper-method can show the available mountpoints, at the least
634
+ # on a linux system.
635
+ #
636
+ # To invoke this, try:
637
+ #
638
+ # rbackup --mountpoints
639
+ #
640
+ # ========================================================================= #
641
+ def show_available_mountpoints
642
+ begin
643
+ require 'mountpoints'
644
+ rescue LoadError; end
645
+ if Mountpoints.is_any_mountpoint_available?
646
+ opnn; e 'The available (and mounted) USB devices are:'
647
+ e
648
+ Mountpoints[].each {|this_usb_device|
649
+ e " #{sfancy(this_usb_device)}"
650
+ }
651
+ e
652
+ else
653
+ opnn; e 'No external USB devices appear to be mounted.'
654
+ end
655
+ end
656
+
657
+ # ========================================================================= #
658
+ # === show_available_mountpoints_then_exit
659
+ # ========================================================================= #
660
+ def show_available_mountpoints_then_exit
661
+ show_available_mountpoints
662
+ exit_program
663
+ end
664
+
665
+ # ========================================================================= #
666
+ # === report_time_difference
667
+ #
668
+ # This method will report to the user how long it took this class
669
+ # to backup the system, e. g. 30 minutes or something like that.
670
+ # ========================================================================= #
671
+ def report_time_difference
672
+ if @internal_hash[:array_store_times].size > 1
673
+ start_time = @internal_hash[:array_store_times][-2]
674
+ end_time = @internal_hash[:array_store_times].last
675
+ time_difference = end_time - start_time # This will result in a Float.
676
+ if time_difference.respond_to? :round
677
+ time_difference = time_difference.round(3)
678
+ end
679
+ n_minutes = (time_difference.to_f / 60.0).round(2).to_s
680
+ opnn; e "#{tomato('Time required')} for this backup-operation: "\
681
+ "#{sfancy(time_difference.to_s)}"\
682
+ " seconds (#{royalblue(n_minutes)} minutes)."
683
+ consider_creating_a_log_file(time_difference)
684
+ end
685
+ end
686
+
687
+ # ========================================================================= #
688
+ # === show_welcome_message
689
+ # ========================================================================= #
690
+ def show_welcome_message
691
+ print_rev
692
+ cliner
693
+ e "Welcome to the #{lightcoral('BackupParadise')} #{rev}project!"
694
+ report_todays_date
695
+ cliner
696
+ e "Starting to backup into the target at `#{sdir(main_target?)}`."
697
+ cliner
698
+ end
699
+
700
+ # ========================================================================= #
701
+ # === consider_removing_all_but_one_log_file
702
+ # ========================================================================= #
703
+ def consider_removing_all_but_one_log_file
704
+ log_files = return_all_log_files
705
+ if log_files.size > 1
706
+ opnn; e 'More than one log file has been found. We will delete'
707
+ opnn; e 'all but one next.'
708
+ log_files.pop
709
+ delete_files(log_files, :be_verbose)
710
+ end
711
+ end
712
+
713
+ # ========================================================================= #
714
+ # === return_all_log_files
715
+ # ========================================================================= #
716
+ def return_all_log_files(
717
+ from_where = mounted_at?
718
+ )
719
+ Dir["#{from_where}log_last_backup_*"].select {|entry|
720
+ File.file? entry # We only want files.
721
+ }
722
+ end
723
+
724
+ # ========================================================================= #
725
+ # === popup_notification
726
+ #
727
+ # Use this method to send a graphical popup to the user. Only invoke
728
+ # it when we set @show_popup_notification to true.
729
+ # ========================================================================= #
730
+ def popup_notification(
731
+ what = :backup_complete
732
+ )
733
+ case what
734
+ when :backup_complete
735
+ esystem 'xmessage -center Backup finished!'
736
+ end
737
+ end
738
+
739
+ # ========================================================================= #
740
+ # === determine_the_starting_time
741
+ # ========================================================================= #
742
+ def determine_the_starting_time
743
+ @internal_hash[:array_store_times] << Time.now
744
+ end; alias determine_starting_time determine_the_starting_time # === determine_starting_time
745
+
746
+ # ========================================================================= #
747
+ # === determine_end_time
748
+ # ========================================================================= #
749
+ def determine_end_time
750
+ @internal_hash[:array_store_times] << Time.now
751
+ end
752
+
753
+ # ========================================================================= #
754
+ # === backup_the_programs_directory
755
+ #
756
+ # This method can be used to backup the /Programs directory.
757
+ # ========================================================================= #
758
+ def backup_the_programs_directory(
759
+ target_directory = PROGRAMS_DIRECTORY
760
+ )
761
+ if File.directory? target_directory
762
+ cliner
763
+ e 'Now backing up the Programs/ directory from '+
764
+ sfancy(target_directory)+' into '+
765
+ sfile(main_target?+File.basename(target_directory))
766
+ cliner
767
+ report_total_size_of(target_directory)
768
+ if target_hdd_does_not_have_enough_space_left?
769
+ opnn; e "We have to skip backing up #{sdir(target_directory)}"
770
+ opnn; e 'as it does not have enough space left (Threshold: '+
771
+ MINIMAL_FILESIZE+' bytes)'
772
+ else
773
+ backup_this_directory_if_it_exists(
774
+ target_directory, :default, :do_not_continue
775
+ )
776
+ end
777
+ else
778
+ can_not_backup_this_directory_as_it_does_not_exist(target_directory)
779
+ end
780
+ end
781
+
782
+ # ========================================================================= #
783
+ # === return_default_target_directory_from_this_input
784
+ # ========================================================================= #
785
+ def return_default_target_directory_from_this_input(i)
786
+ rds(
787
+ main_target?+
788
+ File.basename(i)+
789
+ '/'
790
+ )
791
+ end
792
+
793
+ # ========================================================================= #
794
+ # === determine_the_target_mountpoint
795
+ #
796
+ # This method will determine the target base mountpoint that
797
+ # is to be used.
798
+ # ========================================================================= #
799
+ def determine_the_target_mountpoint(
800
+ i = '/Mount/USB1/'
801
+ )
802
+ BackupParadise.target_mountpoint = i
803
+ end
804
+
805
+ # ========================================================================= #
806
+ # === create_the_directory_containing_the_last_backup
807
+ # ========================================================================= #
808
+ def create_the_directory_containing_the_last_backup
809
+ target = "#{main_target?}backup-#{use_this_as_timestamp?}"
810
+ # ======================================================================= #
811
+ # Next, create the last_backup directory:
812
+ # ======================================================================= #
813
+ begin
814
+ mkdir(target, 0755)
815
+ rescue Errno::EINVAL
816
+ target.tr!(':','_')
817
+ mkdir(target, 0755)
818
+ end
819
+ @internal_hash[:last_backup_directory] = rds(target+'/')
820
+ opnn; e "Creating a directory at "\
821
+ "`#{sdir(@internal_hash[:last_backup_directory])}`."
822
+ end
823
+
824
+ # ========================================================================= #
825
+ # === create_a_symlink_pointing_to_that_directory_that_was_just_created
826
+ #
827
+ # This method will create a symlink to the last_backup/ directory.
828
+ #
829
+ # This is synonymous to the following ruby code:
830
+ #
831
+ # File.symlink('last_backup-13.08.2018-22:12:26/','last_backup')
832
+ #
833
+ # ========================================================================= #
834
+ def create_a_symlink_pointing_to_that_directory_that_was_just_created
835
+ cd_to_the_mounted_device
836
+ create_a_symlink_here = "#{backup_to_this_directory?}last_backup"
837
+ from_this_target = File.basename(@internal_hash[:last_backup_directory])
838
+ from_this_target.chop! if from_this_target.end_with? '/'
839
+ # ========================================================================= #
840
+ # First, delete the old symlink if it exists. The method delete_symlink()
841
+ # will do that check for us.
842
+ # ========================================================================= #
843
+ delete_symlink(create_a_symlink_here)
844
+ # ========================================================================= #
845
+ # The next action can fail on e. g. vfat filesystems, with the error
846
+ # being Errno::EPERM. Hence we must rescue here.
847
+ # ========================================================================= #
848
+ begin
849
+ do_symlink(from_this_target, create_a_symlink_here)
850
+ if File.exist? create_a_symlink_here
851
+ points_towards = File.readlink(create_a_symlink_here)
852
+ opnn; e 'Next setting a symlink at `'+sfancy(create_a_symlink_here)+
853
+ '` pointing'
854
+ opnn; e "towards `#{sfile(points_towards)}`."
855
+ else
856
+ opnn; e no_file_exists_at(create_a_symlink_here)
857
+ end
858
+ rescue Errno::EPERM
859
+ end
860
+ end; alias create_symlink_to_last_backup_directory create_a_symlink_pointing_to_that_directory_that_was_just_created # === create_symlink_to_last_backup_directory
861
+
862
+ # ========================================================================= #
863
+ # === do_sync
864
+ #
865
+ # The do_sync() method, also aliased towards synchronize(), will sync
866
+ # the data onto USB items, by using the sync command.
867
+ # ========================================================================= #
868
+ def do_sync
869
+ opnn; e 'Starting to '+steelblue('sync data')+' ...'
870
+ system 'sync' # Be silent since May 2014.
871
+ opnn; e "> Syncing finished. (At: "\
872
+ "#{rosybrown(return_current_date_and_time.to_s)})"
873
+ end; alias synchronize do_sync # === synchronize
874
+
875
+ # ========================================================================= #
876
+ # === backup_this_directory
877
+ #
878
+ # This method will quickly backup a given directory.
879
+ #
880
+ # The second argument will be the target-directory onto which
881
+ # we will copy our files.
882
+ # ========================================================================= #
883
+ def backup_this_directory(
884
+ i,
885
+ copy_to_this_target_directory = nil,
886
+ shall_we_sync = true
887
+ )
888
+ case shall_we_sync
889
+ when :do_not_sync
890
+ shall_we_sync = false
891
+ end
892
+ case copy_to_this_target_directory
893
+ when nil,
894
+ :default
895
+ copy_to_this_target_directory = return_default_target_directory_from_this_input(i)
896
+ end
897
+ unless File.directory? copy_to_this_target_directory
898
+ mkdir(copy_to_this_target_directory)
899
+ end
900
+ cd copy_to_this_target_directory
901
+ opnn; e 'Now copying '+sdir(i)+
902
+ ' to '+sdir(copy_to_this_target_directory)+'.'
903
+ if File.directory?(i)
904
+ i << '*'
905
+ end
906
+ cpr(
907
+ i, copy_to_this_target_directory
908
+ )
909
+ do_sync if shall_we_sync
910
+ end
911
+
912
+ # ========================================================================= #
913
+ # === backup_the_system_directory
914
+ #
915
+ # This method can be used to backup the "/System/Settings/" directory,
916
+ # as it may be found in GoboLinux.
917
+ # ========================================================================= #
918
+ def backup_the_system_directory(
919
+ target_directory = SYSTEM_SETTINGS_DIRECTORY
920
+ )
921
+ if File.directory? target_directory
922
+ cliner
923
+ e 'Now backing up the system-settings directory from '+
924
+ sfancy(target_directory)+' into '+
925
+ sfile(main_target?+File.basename(target_directory))
926
+ cliner
927
+ report_total_size_of(target_directory)
928
+ cpr(
929
+ target_directory,
930
+ backup_to_this_target?
931
+ )
932
+ else
933
+ can_not_backup_this_directory_as_it_does_not_exist(target_directory)
934
+ end
935
+ end; alias backup_system_directory backup_the_system_directory # === backup_system_directory
936
+
937
+ # ========================================================================= #
938
+ # === backup_to_this_target?
939
+ # ========================================================================= #
940
+ def backup_to_this_target?
941
+ @backup_to_this_target
942
+ end
943
+
944
+ # ========================================================================= #
945
+ # === backup_the_data_directory_then_exit
946
+ #
947
+ # Backup only Data directory.
948
+ # ========================================================================= #
949
+ def backup_the_data_directory_then_exit
950
+ backup_data_directory
951
+ exit_program
952
+ end; alias backup_data_directory_then_exit backup_the_data_directory_then_exit # === backup_data_directory_then_exit
953
+
954
+ # ========================================================================= #
955
+ # === backup_the_data_directory (data tag)
956
+ #
957
+ # This method will backup the DATA directory, e. g. the one that is
958
+ # at "/home/x/DATA/" on my home system.
959
+ # ========================================================================= #
960
+ def backup_the_data_directory(
961
+ target_directory = DATA_DIRECTORY
962
+ )
963
+ if File.directory? target_directory
964
+ mountpoint_target = main_target?+File.basename(target_directory)
965
+ print rev
966
+ cliner
967
+ e "#{rev}Now backing up the DATA directory from "\
968
+ "#{sfancy(target_directory)} into "\
969
+ "#{sfile(mountpoint_target)}."
970
+ cliner
971
+ report_total_size_of(target_directory)
972
+ unless File.directory? mountpoint_target
973
+ create_directory(mountpoint_target, 0755)
974
+ end
975
+ mkdir(backup_to_this_target?+File.basename(target_directory))
976
+ cpr(
977
+ target_directory,
978
+ backup_to_this_target?
979
+ )
980
+ else
981
+ can_not_backup_this_directory_as_it_does_not_exist(target_directory)
982
+ end
983
+ end; alias backup_only_data_directory backup_the_data_directory # === backup_only_data_directory
984
+ alias backup_data_directory backup_the_data_directory # === backup_data_directory
985
+
986
+ # ========================================================================= #
987
+ # === ensure_trailing_backslash_for
988
+ # ========================================================================= #
989
+ def ensure_trailing_backslash_for(i)
990
+ i = i.dup
991
+ i << '/' unless i.end_with? '/'
992
+ return i
993
+ end
994
+
995
+ # ========================================================================= #
996
+ # === backup_the_studium_directory
997
+ # ========================================================================= #
998
+ def backup_the_studium_directory(
999
+ target_directory = STUDIUM_DIRECTORY
1000
+ )
1001
+ target_directory = ensure_trailing_backslash_for(target_directory)
1002
+ if File.directory? target_directory
1003
+ tab_title('Backing up the '+target_directory+' directory.')
1004
+ cliner
1005
+ e 'Now backing up the studium/ directory from '+
1006
+ sfancy(target_directory)+' into '+
1007
+ sfile(main_target?+File.basename(target_directory))
1008
+ cliner
1009
+ report_total_size_of(target_directory)
1010
+ mkdir(backup_to_this_target?+File.basename(target_directory))
1011
+ cpr(
1012
+ target_directory,
1013
+ backup_to_this_target?
1014
+ )
1015
+ else
1016
+ can_not_backup_this_directory_as_it_does_not_exist(target_directory)
1017
+ end
1018
+ end
1019
+
1020
+ # ========================================================================= #
1021
+ # === backup_the_video_directory
1022
+ # ========================================================================= #
1023
+ def backup_the_video_directory(
1024
+ target_directory = VIDEO_DIRECTORY
1025
+ )
1026
+ target_directory = ensure_trailing_backslash_for(target_directory)
1027
+ if File.directory? target_directory
1028
+ cliner
1029
+ e 'Now backing up the Video directory from '+
1030
+ sfancy(target_directory)+' into '+
1031
+ sfile(main_target?+File.basename(target_directory))
1032
+ cliner
1033
+ tab_title('Backing up the directory '+target_directory+' next.')
1034
+ report_total_size_of(target_directory)
1035
+ set_backup_to_this_target(target_base_directory?)
1036
+ mkdir(
1037
+ target_base_directory?+File.basename(target_directory)
1038
+ )
1039
+ cpr(
1040
+ target_directory,
1041
+ target_base_directory?
1042
+ )
1043
+ show_all_is_done_message
1044
+ default_tab_title
1045
+ else
1046
+ can_not_backup_this_directory_as_it_does_not_exist(target_directory)
1047
+ end
1048
+ end
1049
+
1050
+ # ========================================================================= #
1051
+ # === BackupParadise::Backup[]
1052
+ # ========================================================================= #
1053
+ def self.[](i = '')
1054
+ new(i)
1055
+ end
1056
+
1057
+ # ========================================================================= #
1058
+ # === try_to_backup_the_autogenerated_directory
1059
+ # ========================================================================= #
1060
+ def try_to_backup_the_autogenerated_directory(
1061
+ i = AUTOGENERATED_DIRECTORY
1062
+ )
1063
+ i = ensure_trailing_backslash_for(i)
1064
+ if File.directory? i
1065
+ opnn; e 'Now trying to backup the AUTOGENERATED '\
1066
+ 'directory at `'+sdir(i)+'`.'
1067
+ new_target = @mountpoint.squeeze('/')
1068
+ n_gigabytes = BackupParadise.size_in_gigabytes?(i).to_s
1069
+ opnn; e 'This directory has a total of '+
1070
+ sfancy(n_files_in?(i).to_s)+' entries '\
1071
+ '(Total size: '+n_gigabytes+' GB).'
1072
+ unless File.directory? new_target
1073
+ verbose_create_a_directory_at_this_position(new_target)
1074
+ end
1075
+ tab_title('Backing up the AUTOGENERATED directory.')
1076
+ cpr(i, new_target)
1077
+ else
1078
+ can_not_backup_this_directory_as_it_does_not_exist(i)
1079
+ end
1080
+ end; alias backup_autogenerated_directory try_to_backup_the_autogenerated_directory # === backup_autogenerated_directory
1081
+ alias backup_the_autogenerated_directory try_to_backup_the_autogenerated_directory # === backup_the_autogenerated_directory
1082
+
1083
+ # ========================================================================= #
1084
+ # === backup_into_the_default_chroot_directory (chroot tag)
1085
+ # ========================================================================= #
1086
+ def backup_into_the_default_chroot_directory(
1087
+ i = :chroot
1088
+ )
1089
+ e
1090
+ e "#{rev}Setting the target to #{sdir(i)} next."
1091
+ e
1092
+ set_target_mountpoint(i) # Set to the above Chroot target. We could also use :chroot.
1093
+ set_main_target(
1094
+ "#{main_target?.dup}#{home_dir_of_user_x?.dup}"
1095
+ )
1096
+ # ======================================================================= #
1097
+ # Must copy the autogenerated directory first:
1098
+ # ======================================================================= #
1099
+ try_to_backup_the_autogenerated_directory
1100
+ all_important_directories?.each {|this_directory|
1101
+ tab_title 'Now backing up the '+this_directory+' directory ...'
1102
+ new_target = main_target?+File.basename(this_directory)
1103
+ mkdir(new_target)
1104
+ cpr(this_directory, main_target?)
1105
+ }
1106
+ all_done_message
1107
+ end
1108
+
1109
+ # ========================================================================= #
1110
+ # === backup_src_directory (src tag)
1111
+ #
1112
+ # This method will backup the SRC/ directory, aka "/home/x/src/". It
1113
+ # is evidently geared towards the system at my home setup.
1114
+ #
1115
+ # To invoke this method from the commandline, try:
1116
+ #
1117
+ # rbackup --src-dir
1118
+ #
1119
+ # ========================================================================= #
1120
+ def backup_the_source_directory(
1121
+ target_directory = SOURCE_DIRECTORY
1122
+ )
1123
+ target_directory = ensure_trailing_backslash_for(target_directory)
1124
+ if File.directory? target_directory
1125
+ tab_title('Backing up the '+target_directory+' directory.')
1126
+ cliner
1127
+ e 'Now backing up the '+sdir('src/')+' directory from '+
1128
+ sfancy(target_directory)+' into '+
1129
+ sfile(main_target?+File.basename(target_directory))
1130
+ cliner
1131
+ report_total_size_of(target_directory)
1132
+ mkdir(backup_to_this_target?+File.basename(target_directory))
1133
+ cpr(
1134
+ target_directory,
1135
+ backup_to_this_target?
1136
+ )
1137
+ else
1138
+ can_not_backup_this_directory_as_it_does_not_exist(target_directory)
1139
+ end
1140
+ end
1141
+
1142
+ # ========================================================================= #
1143
+ # === backup_the_books_directory (data tag)
1144
+ #
1145
+ # This method will backup the BOOKS directory, e. g. the one that is
1146
+ # at "/home/x/books/" on my home system.
1147
+ # ========================================================================= #
1148
+ def backup_the_books_directory(
1149
+ target_directory = BOOKS_DIRECTORY
1150
+ )
1151
+ target_directory = ensure_trailing_backslash_for(target_directory)
1152
+ if File.directory? target_directory
1153
+ tab_title('Backing up the '+target_directory+' directory.')
1154
+ cliner
1155
+ e 'Now backing up the books/ directory from '+
1156
+ sfancy(target_directory)+' into '+
1157
+ sfile(main_target?+File.basename(target_directory))
1158
+ cliner
1159
+ report_total_size_of(target_directory)
1160
+ unless File.directory? backup_to_this_target?+File.basename(target_directory)
1161
+ opnn; verbose_create_a_directory_at_this_position(
1162
+ backup_to_this_target?+File.basename(target_directory),
1163
+ 0755
1164
+ )
1165
+ end
1166
+ cpr(
1167
+ target_directory,
1168
+ backup_to_this_target?
1169
+ )
1170
+ rename_tab('.')
1171
+ else
1172
+ can_not_backup_this_directory_as_it_does_not_exist(target_directory)
1173
+ end
1174
+ end; alias backup_only_books_directory backup_the_books_directory # === backup_only_books_directory
1175
+ alias backup_books_directory backup_the_books_directory # === backup_books_directory
1176
+
1177
+ # ========================================================================= #
1178
+ # === do_not_perform_the_regular_backup_routine
1179
+ # ========================================================================= #
1180
+ def do_not_perform_the_regular_backup_routine
1181
+ @internal_hash[:perform_backup] = false
1182
+ end
1183
+
1184
+ # ========================================================================= #
1185
+ # === perform_the_regular_backup_routine?
1186
+ # ========================================================================= #
1187
+ def perform_the_regular_backup_routine?
1188
+ @internal_hash[:perform_backup]
1189
+ end
1190
+
1191
+ # ========================================================================= #
1192
+ # === report_todays_date
1193
+ # ========================================================================= #
1194
+ def report_todays_date
1195
+ e "Today is the #{sfancy(date?)}."
1196
+ end
1197
+
1198
+ # ========================================================================= #
1199
+ # === create_the_log_last_backup_file (log tag)
1200
+ #
1201
+ # We also have to remove all prior log files should they exist.
1202
+ # ========================================================================= #
1203
+ def create_the_log_last_backup_file
1204
+ _ = return_all_log_files
1205
+ target = main_target?+'log_last_backup_'+use_this_as_timestamp?
1206
+ what = dd_mm_yyyy
1207
+ opnn; e "Keeping a backup file (a log) at"
1208
+ opnn; e "`#{sfile(target)}`."
1209
+ write_what_into(what, target)
1210
+ unless _.empty?
1211
+ # ===================================================================== #
1212
+ # Remove all old log files next.
1213
+ # ===================================================================== #
1214
+ remove_these_files(_)
1215
+ end
1216
+ end; alias create_log_file create_the_log_last_backup_file # === create_log_file
1217
+
1218
+ # ========================================================================= #
1219
+ # === last_backup_directory?
1220
+ # ========================================================================= #
1221
+ def last_backup_directory?
1222
+ @internal_hash[:last_backup_directory]
1223
+ end
1224
+
1225
+ # ========================================================================= #
1226
+ # === set_last_backup_directory
1227
+ # ========================================================================= #
1228
+ def set_last_backup_directory(i)
1229
+ @internal_hash[:last_backup_directory] = i
1230
+ end
1231
+
1232
+ # ========================================================================= #
1233
+ # === consider_creating_a_log_file
1234
+ #
1235
+ # This method will create a .log file.
1236
+ #
1237
+ # It accepts an argument, which should be an Integer or Float, denoting,
1238
+ # in seconds, how long it took to make a backup.
1239
+ # ========================================================================= #
1240
+ def consider_creating_a_log_file(
1241
+ n_seconds
1242
+ )
1243
+ if File.directory? '/Depot/Temp/'
1244
+ n_minutes = (n_seconds.to_f / 60).round(1).to_s
1245
+ # ===================================================================== #
1246
+ # Make the seconds a bit prettier next, via trailing '0'.
1247
+ # ===================================================================== #
1248
+ n_seconds = '%.3f' % n_seconds
1249
+ what = "#{return_full_date}: Backing up the system took #{n_seconds} "\
1250
+ "seconds (#{n_minutes} minutes).\n"
1251
+ into = FILE_BACKUP_LOG
1252
+ opnn; e "Storing the time it took to backup "\
1253
+ "into the file `#{sfile(into)}`."
1254
+ append_what_into(what, into)
1255
+ end
1256
+ end
1257
+
1258
+ # ========================================================================= #
1259
+ # === backup_the_audio_directory (audio tag, audio dir tag)
1260
+ #
1261
+ # This method can be used to backup my audio directory, which normally
1262
+ # resides at "/home/x/songs/".
1263
+ #
1264
+ # Two arguments can be supplied to this method:
1265
+ #
1266
+ # (1) The first argument specifies which directory is used as the
1267
+ # input directory, where the songs that are to be copied
1268
+ # should reside.
1269
+ #
1270
+ # (2) If the second argument is true then only those audio files
1271
+ # that are missing will be copied.
1272
+ #
1273
+ # ========================================================================= #
1274
+ def backup_the_audio_directory(
1275
+ i = DIRECTORY_CONTAINING_ALL_SONGS,
1276
+ copy_only_missing_audio_files = true
1277
+ )
1278
+ if File.directory? i
1279
+ copied_n_files = 0
1280
+ print rev
1281
+ cliner
1282
+ new_target = @mountpoint.squeeze('/')
1283
+ opnn; e "Now trying to backup the Audio directory "\
1284
+ "at `#{sdir(i)}`."
1285
+ colourized_target = sdir("#{new_target}#{File.basename(i)}/")
1286
+ opnn; e "The target for this will be at "\
1287
+ "`#{colourized_target}`."
1288
+ n_gigabytes = BackupParadise.size_in_gigabytes?(i).to_s
1289
+ opnn; e 'This directory has a total of '+
1290
+ sfancy(n_files_in?(i).to_s)+' entries '\
1291
+ '(Total size: '+n_gigabytes+' GB).'
1292
+ cliner
1293
+ unless File.directory? "#{new_target}#{File.basename(i)}/"
1294
+ opnn; verbose_create_a_directory_at_this_position(
1295
+ "#{new_target}#{File.basename(i)}/"
1296
+ )
1297
+ end
1298
+ tab_title('Backing up the main audio directory.')
1299
+ # ===================================================================== #
1300
+ # Else we will copy only the audio files that are missing. In order
1301
+ # to do so we have to obtain all audio-files - we will simply
1302
+ # pick all files, anyway. We will keep these entries sorted, too.
1303
+ # ===================================================================== #
1304
+ these_audio_files_may_be_copied = Dir[
1305
+ rds("#{i.delete('*')}/*")
1306
+ ].sort
1307
+ if copy_only_missing_audio_files
1308
+ these_audio_files_may_be_copied.each {|this_file|
1309
+ totally_new_target =
1310
+ "#{new_target}#{File.basename(i)}/#{File.basename(this_file)}"
1311
+ # ================================================================= #
1312
+ # We check whether the target-file exists. Only if it does not
1313
+ # exist will it be copied.
1314
+ # ================================================================= #
1315
+ unless File.exist? totally_new_target
1316
+ copied_n_files += 1
1317
+ # =============================================================== #
1318
+ # Pad the display.
1319
+ # =============================================================== #
1320
+ padded_file = this_file.ljust(40)
1321
+ padded_target = totally_new_target.ljust(40)
1322
+ e "Copying `#{sfile(padded_file)}` to"
1323
+ e " `#{sfile(padded_target)}`."
1324
+ copy_this_file(this_file, totally_new_target)
1325
+ end
1326
+ }
1327
+ # =================================================================== #
1328
+ # Ok, now, if we removed a file from /Depot/Audio, then the Audio/
1329
+ # directory at the mounted USB device may still have such a file.
1330
+ # So we will warn the user about this.
1331
+ # =================================================================== #
1332
+ target = "#{new_target}#{File.basename(i)}/" # This will be something like "/Mount/USB1/songs/"
1333
+ unless these_audio_files_may_be_copied.size == Dir["#{target}*"].size
1334
+ opnn; e 'It seems as if we have an unequal amount of Audio files in '
1335
+ opnn; e 'the two directories.'
1336
+ opnn; e 'This usually means that the original directory '+
1337
+ sdir(i)+' has some files'
1338
+ opnn; e 'deleted, but the target directory at '+sdir(target)+' does not.'
1339
+ opnn; e 'The old directory has '+simp(i.size.to_s)+' entries.'
1340
+ end
1341
+ else
1342
+ cpr(i, new_target)
1343
+ end
1344
+ _ = "#{new_target}#{File.basename(i)}/"
1345
+ if copied_n_files == 0
1346
+ opnn; e "No file was copied into the directory #{sdir(_)}."
1347
+ opnn; e 'This may indicate that the target audio-directory already'
1348
+ opnn; e 'contains all necessary audio-files.'
1349
+ else
1350
+ opnn; e "Finished backing up the directory "\
1351
+ "#{sdir(i.delete('*'))} into "\
1352
+ "#{sdir(_)}."
1353
+ end
1354
+ default_tab_title
1355
+ else
1356
+ can_not_backup_this_directory_as_it_does_not_exist(i)
1357
+ end
1358
+ end; alias try_to_backup_the_audio_directory backup_the_audio_directory # === alias try_to_backup_the_audio_directory
1359
+ alias backup_audio_directory backup_the_audio_directory # === backup_audio_directory
1360
+
1361
+ # ========================================================================= #
1362
+ # === unmount
1363
+ #
1364
+ # Use this to unmount something. Right now, we unmount only the HDD.
1365
+ # ========================================================================= #
1366
+ def unmount(
1367
+ what = :hdd
1368
+ )
1369
+ case what.to_sym
1370
+ when :hdd
1371
+ system "umount -l #{ENV['FIRST_HD']}"
1372
+ end
1373
+ end
1374
+
1375
+ # ========================================================================= #
1376
+ # === show_backup_complete_message
1377
+ #
1378
+ # This variant will show that the backup has been complete on the
1379
+ # commandline. Since September 2022 there is also a backup-complete
1380
+ # message for LibuiParadise.
1381
+ # ========================================================================= #
1382
+ def show_backup_complete_message
1383
+ e "#{BackupParadise.steelblue('Backup complete!')}#{rev}" # The old colour was cyan, up until 2021.
1384
+ if TRY_TO_SHOW_BACKUP_COMPLETE_MESSAGE_VIA_LIBUI
1385
+ try_to_show_backup_complete_message_via_libui
1386
+ end
1387
+ end; alias all_done show_backup_complete_message # === all_done
1388
+ alias show_all_is_done_message show_backup_complete_message # === show_all_is_done_message
1389
+ alias all_done_message show_backup_complete_message # === all_done_message
1390
+
1391
+ # ========================================================================= #
1392
+ # === try_to_show_backup_complete_message_via_libui
1393
+ #
1394
+ # This method will describe the libui-widget that we will use for
1395
+ # notifying the user.
1396
+ # ========================================================================= #
1397
+ def try_to_show_backup_complete_message_via_libui
1398
+ begin
1399
+ require 'libui_paradise'
1400
+ text = LibuiParadise.text('Backup complete!')
1401
+ ::LibuiParadise.run_in_the_background
1402
+ LibuiParadise.generic_window(
1403
+ text, :create_a_quit_button
1404
+ ) {{
1405
+ width: 420,
1406
+ height: 120,
1407
+ title: 'Backup is complete now!'
1408
+ }}
1409
+ rescue LoadError; end
1410
+ end
1411
+
1412
+ # ========================================================================= #
1413
+ # === menu (menu tag)
1414
+ # ========================================================================= #
1415
+ def menu(
1416
+ i = commandline_arguments?
1417
+ )
1418
+ return if i.nil?
1419
+ # ======================================================================= #
1420
+ # === Handle Hashes
1421
+ #
1422
+ # Note that this is the default entry point.
1423
+ #
1424
+ # An example for how this may be used is given next:
1425
+ #
1426
+ # BackupParadise::Actions.backup(
1427
+ # backup_these_directories: i,
1428
+ # where_to: to
1429
+ # )
1430
+ #
1431
+ # ======================================================================= #
1432
+ if i.is_a? Hash
1433
+ # ===================================================================== #
1434
+ # === :backup_to_this_target
1435
+ #
1436
+ # The next check must come early, on top.
1437
+ # ===================================================================== #
1438
+ # ===================================================================== #
1439
+ # === :where_to
1440
+ # ===================================================================== #
1441
+ if i.has_key? :where_to
1442
+ set_backup_to_this_target(i[:where_to])
1443
+ elsif i.has_key? :backup_to_this_target
1444
+ set_backup_to_this_target(i[:backup_to_this_target])
1445
+ end
1446
+ # ===================================================================== #
1447
+ # === :commandline_arguments
1448
+ # ===================================================================== #
1449
+ if i.has_key? :commandline_arguments
1450
+ menu(i[:commandline_arguments])
1451
+ # ===================================================================== #
1452
+ # === :backup_these_directories
1453
+ # ===================================================================== #
1454
+ elsif i.has_key? :backup_these_directories
1455
+ menu(i[:backup_these_directories])
1456
+ end
1457
+ # ======================================================================= #
1458
+ # === Handle Arrays
1459
+ # ======================================================================= #
1460
+ elsif i.is_a? Array
1461
+ i.each {|entry| menu(entry) }
1462
+ else
1463
+ case i # case tag
1464
+ # ===================================================================== #
1465
+ # === rbackup --audio-dir
1466
+ #
1467
+ # This entry point can be used to specifically backup the
1468
+ # audio-directory - that is, the local directory that
1469
+ # contains all songs.
1470
+ #
1471
+ # Usage example:
1472
+ #
1473
+ # rbackup --audio-dir
1474
+ #
1475
+ # A more advanced invocation example is:
1476
+ #
1477
+ # rbackup --backup-to=/opt/ --audio-dir
1478
+ #
1479
+ # ===================================================================== #
1480
+ when /^-?-?audio(-| |_)?dir$/i,
1481
+ /^-?-?audio$/i,
1482
+ /^-?-?aud$/i,
1483
+ /^-?-?audi$/i,
1484
+ /^-?-?aonly$/i,
1485
+ /^-?-?audio(-| |_)?only$/i
1486
+ determine_whether_the_target_harddisc_is_a_ntfs_system
1487
+ backup_the_audio_directory
1488
+ do_not_perform_the_regular_backup_routine
1489
+ # ===================================================================== #
1490
+ # === rbackup --libui
1491
+ # ===================================================================== #
1492
+ when /^-?-?lib-?ui$/i,
1493
+ /^-?-?gui2$/i
1494
+ require 'backup_paradise/gui/libui/backup_for_ingrid/backup_for_ingrid.rb'
1495
+ BackupParadise::GUI::LibUI::BackupForIngrid.new
1496
+ exit
1497
+ # ===================================================================== #
1498
+ # === rbackup --gui
1499
+ #
1500
+ # Alternatively use rbackup --gtk3.
1501
+ # ===================================================================== #
1502
+ when /^-?-?gui$/i,
1503
+ /^-?-?gtk3$/i,
1504
+ /^-?-?gtk$/i,
1505
+ /^-?-?gui1$/i
1506
+ start_the_gtk3_bindings
1507
+ do_not_perform_the_regular_backup_routine
1508
+ # ===================================================================== #
1509
+ # === rbackup --version?
1510
+ # ===================================================================== #
1511
+ when /^-?-?version\??$/i
1512
+ e BackupParadise::VERSION
1513
+ do_not_perform_the_regular_backup_routine
1514
+ # ===================================================================== #
1515
+ # === rbackup --are-we-on-windows?
1516
+ # ===================================================================== #
1517
+ when /^-?-?are(-| |_)?we(-| |_)?on(-| |_)?windows\??$/i
1518
+ e rev+'Are we on windows? '+
1519
+ steelblue(are_we_on_windows?.to_s)
1520
+ do_not_perform_the_regular_backup_routine
1521
+ # ===================================================================== #
1522
+ # === rbackup --help
1523
+ #
1524
+ # The user can use this entry point to obtain helpful information in
1525
+ # how to use this class, on the commandline.
1526
+ # ===================================================================== #
1527
+ when /help/i,
1528
+ /^-?-?show(-| |_)?help$/i,
1529
+ 'hel',
1530
+ 'he','h','?','*'
1531
+ show_help
1532
+ do_not_perform_the_regular_backup_routine
1533
+ # ===================================================================== #
1534
+ # === rbackup --video-dir
1535
+ # ===================================================================== #
1536
+ when /^-?-?video(-| |_)?dir$/i,
1537
+ /^-?-?video(-| |_)?directory$/i,
1538
+ /^-?-?video$/i
1539
+ backup_the_video_directory
1540
+ do_not_perform_the_regular_backup_routine
1541
+ # ===================================================================== #
1542
+ # === rbackup --books
1543
+ #
1544
+ # This entry point allows the user to backup the /home/x/books/
1545
+ # directory.
1546
+ # ===================================================================== #
1547
+ when /^-?-?books$/i,
1548
+ /^-?-?books(-| |_)?directory$/i
1549
+ backup_the_books_directory
1550
+ do_not_perform_the_regular_backup_routine
1551
+ # ===================================================================== #
1552
+ # === rbackup --source-dir
1553
+ # === rbackup --source-directory
1554
+ # === rbackup --source
1555
+ # === rbackup --src-dir
1556
+ # === rbackup --src
1557
+ #
1558
+ # This entry point allows the user to backup the /home/x/src/
1559
+ # directory.
1560
+ # ===================================================================== #
1561
+ when /^-?-?source(-| |_)?dir$/i,
1562
+ /^-?-?source(-| |_)?directory$/i,
1563
+ /^-?-?source$/i,
1564
+ /^-?-?src(-| |_)?dir$/i,
1565
+ /^-?-?src$/i
1566
+ backup_the_source_directory
1567
+ do_not_perform_the_regular_backup_routine
1568
+ # ===================================================================== #
1569
+ # === Backup all relevant entries to the chroot-directory
1570
+ #
1571
+ # This entry point is mostly used for my local Chroot directory. We
1572
+ # will quickly backup the important files to that directory, which
1573
+ # then allows us to cd into a better chroot-environment.
1574
+ #
1575
+ # Invocation examples:
1576
+ #
1577
+ # rbackup --chroot
1578
+ # rbackup --to-chroot
1579
+ #
1580
+ # ===================================================================== #
1581
+ when /^-?-?chroot$/i,
1582
+ /^-?-?to(-| |_)?chroot$/i,
1583
+ /^-?-?into(-| |_)?chroot$/i
1584
+ backup_into_the_default_chroot_directory
1585
+ do_not_perform_the_regular_backup_routine
1586
+ # ===================================================================== #
1587
+ # === rbackup --studium-dir
1588
+ # === rbackup --studium-directory
1589
+ # === rbackup --studium
1590
+ #
1591
+ # This entry point allows the user to backup the /home/x/studium/
1592
+ # directory, by making use of the constant STUDIUM_DIRECTORY.
1593
+ # ===================================================================== #
1594
+ when /^-?-?studium(-| |_)?dir$/i,
1595
+ /^-?-?studium(-| |_)?directory$/i,
1596
+ /^-?-?studium$/i
1597
+ backup_the_studium_directory
1598
+ do_not_perform_the_regular_backup_routine
1599
+ # ===================================================================== #
1600
+ # === rbackup --data-dir
1601
+ # ===================================================================== #
1602
+ when /^-?-?data(-| |_)?dir$/i,
1603
+ /^-?-?data(-| |_)?directory$/i,
1604
+ /^-?-?data$/i,
1605
+ /^-?-?ONLY(-| |_)?DATA$/i,
1606
+ /^-?-?DATA(-| |_)?ONLY$/i,
1607
+ /^-?-?donly$/i
1608
+ backup_the_data_directory_then_exit
1609
+ # ===================================================================== #
1610
+ # === rbackup --system-dir
1611
+ # ===================================================================== #
1612
+ when /^-?-?system(-| |_)?dir$/i,
1613
+ /^-?-?system(-| |_)?directory$/i,
1614
+ /^-?-?system$/i
1615
+ backup_the_system_directory
1616
+ do_not_perform_the_regular_backup_routine
1617
+ # ===================================================================== #
1618
+ # === rbackup --programs-dir
1619
+ #
1620
+ # This entry point can be used to backup /home/Programs/ specifically.
1621
+ # ===================================================================== #
1622
+ when /^-?-?programs(-| |_)?dir$/i,
1623
+ /^-?-?programs$/i
1624
+ backup_the_programs_directory
1625
+ do_not_perform_the_regular_backup_routine
1626
+ # ===================================================================== #
1627
+ # === rbackup default
1628
+ # ===================================================================== #
1629
+ when 'default' # Default entry point is for /Mount/USB1 aka :usb1.
1630
+ set_target_mountpoint(:usb1)
1631
+ # ===================================================================== #
1632
+ # === rbackup --mountpoints
1633
+ # ===================================================================== #
1634
+ when /^-?-?mountpoints/
1635
+ show_available_mountpoints_then_exit
1636
+ # ===================================================================== #
1637
+ # === rbackup --logfile
1638
+ # ===================================================================== #
1639
+ when /^-?-?logfile\??$/i
1640
+ show_the_logfile
1641
+ do_not_perform_the_regular_backup_routine
1642
+ # ===================================================================== #
1643
+ # === rbackup --show-file-size-of-popular_directories
1644
+ # === rbackup --overview
1645
+ # ===================================================================== #
1646
+ when /^-?-?show(-| |_)?file(-| |_)?size(-| |_)?of(-| |_)?popular(-| |_)?directories$/i,
1647
+ /^-?-?overview$/i
1648
+ use_this_array = [
1649
+ return_the_songs_directory,
1650
+ PROGRAMS_DIRECTORY,
1651
+ VIDEO_DIRECTORY,
1652
+ STUDIUM_DIRECTORY,
1653
+ DATA_DIRECTORY,
1654
+ SOURCE_DIRECTORY
1655
+ ].map {|entry|
1656
+ return_this_absolute_directory(entry)
1657
+ }
1658
+ use_this_array.each {|this_entry|
1659
+ report_file_size_of(this_entry)
1660
+ }
1661
+ do_not_perform_the_regular_backup_routine
1662
+ # ===================================================================== #
1663
+ # === rbackup --use-this-as-target-for-backup=/opt/
1664
+ # === rbackup --use-this-as-target=/opt/
1665
+ # === rbackup --backup-to=/opt/
1666
+ #
1667
+ # This entry point allows the user to specify another target to
1668
+ # be used from the commandline.
1669
+ # ===================================================================== #
1670
+ when /^-?-?backup(-| |_)?to=(.+)$/i,
1671
+ /^-?-?use(-| |_)?this(-| |_)?as(-| |_)?target=(.+)$/i,
1672
+ /^-?-?use(-| |_)?this(-| |_)?as(-| |_)?target(-| |_)?for(-| |_)?backup=(.+)$/i
1673
+ _ = $2.to_s.dup
1674
+ _ = $4.to_s.dup if $4
1675
+ _ = $6.to_s.dup if $6
1676
+ opnn; e 'The target device will be at '+sfancy(_)+'.'
1677
+ set_target_device(_)
1678
+ # ===================================================================== #
1679
+ # === Use a shorter name for the backup-directory
1680
+ #
1681
+ # This entry point has been created to allow simpler backup onto
1682
+ # NTFS devices. I ran into a problem with a too-long, and special
1683
+ # name for a directory.
1684
+ #
1685
+ # Usage example:
1686
+ #
1687
+ # rbackup --use-shorter-name
1688
+ # rbackup tousb1 --use-shorter-name
1689
+ #
1690
+ # ===================================================================== #
1691
+ when /^-?-?use(-| |_)?shorter(-| |_)?name$/i,
1692
+ /^-?-?windows$/i,
1693
+ /^-?-?sane-symlink$/i
1694
+ do_use_simplified_directory
1695
+ # ===================================================================== #
1696
+ # === rbackup --pwd
1697
+ # ===================================================================== #
1698
+ when /^-?-?pwd$/i
1699
+ current_directory = (Dir.pwd+'/').squeeze('/')
1700
+ set_target_mountpoint(current_directory)
1701
+ # ===================================================================== #
1702
+ # === rbackup --autogenerated
1703
+ # ===================================================================== #
1704
+ when /^-?-?autogen$/,
1705
+ 'agen',
1706
+ 'autog',
1707
+ /^-?-?autogenerated$/i
1708
+ determine_whether_the_target_harddisc_is_a_ntfs_system
1709
+ try_to_backup_the_autogenerated_directory
1710
+ do_not_perform_the_regular_backup_routine
1711
+ else # else tag
1712
+ # =================================================================== #
1713
+ # === Backup an existing directory
1714
+ #
1715
+ # This entry point allows us to quickly backup an existing
1716
+ # directory.
1717
+ #
1718
+ # Usage example:
1719
+ #
1720
+ # rbackup /home/x/data/rpg/
1721
+ #
1722
+ # =================================================================== #
1723
+ if File.directory?(i)
1724
+ i = File.absolute_path(i)
1725
+ i << '/' unless i.end_with? '/'
1726
+ new_target = @mountpoint.squeeze('/')
1727
+ cpr(i, new_target)
1728
+ all_done_message
1729
+ do_not_perform_the_regular_backup_routine
1730
+ # =================================================================== #
1731
+ # === Backup individual .h files quickly
1732
+ #
1733
+ # This is a short circuit action here - we just backup an existing
1734
+ # .h file quickly.
1735
+ #
1736
+ # Invocation example:
1737
+ #
1738
+ # rbackup /usr/include/xvid.h
1739
+ #
1740
+ # =================================================================== #
1741
+ elsif File.exist?(i) and i.end_with?('.h')
1742
+ base_directory = '/BACKUP/include/'
1743
+ verbose_create_a_directory_at_this_position(base_directory)
1744
+ target = "#{base_directory}#{File.basename(i)}"
1745
+ opnn; e "Backing up towards `#{sfile(target)}` (a mere copy operation)."
1746
+ copy_file(i, target)
1747
+ do_not_perform_the_regular_backup_routine
1748
+ else
1749
+ if i and i.start_with?('--')
1750
+ e "Option #{i} was not found. Exiting now."
1751
+ exit
1752
+ end
1753
+ end
1754
+ end
1755
+ end
1756
+ end
1757
+
1758
+ # ========================================================================= #
1759
+ # === do_perform_the_backup_tasks (all tag)
1760
+ #
1761
+ # This method is the main powerhouse of this class. It connects all the
1762
+ # various steps together, one after the other.
1763
+ # ========================================================================= #
1764
+ def do_perform_the_backup_tasks
1765
+ determine_the_starting_time
1766
+ show_welcome_message
1767
+ create_file_keeping_track_of_when_the_last_backup_happened
1768
+ determine_whether_the_target_harddisc_is_a_ntfs_system
1769
+ if is_on_roebe? and are_we_trying_to_backup_to_a_local_harddisc?
1770
+ # ===================================================================== #
1771
+ # So in this case we want to backup to a local harddisc, such
1772
+ # as /Mount/HDD1. In this case we must find out whether the
1773
+ # harddisc is already mounted or not. If not then we will
1774
+ # mount it here.
1775
+ # ===================================================================== #
1776
+ if is_the_harddisc_properly_mounted? # In this case assume all is already mounted.
1777
+ # =================================================================== #
1778
+ # All is fine in this case - we do not have to do anything. At the
1779
+ # least we assume this is the case.
1780
+ # =================================================================== #
1781
+ else
1782
+ # =================================================================== #
1783
+ # Here we must mount it still. For now this uses a hardcoded approach.
1784
+ # =================================================================== #
1785
+ target = mountpoint?
1786
+ e 'Mounting '+steelblue('/dev/sdb3')+' towards '+steelblue(target)+'.'
1787
+ esystem('mount /dev/sdb3 '+target)
1788
+ end
1789
+ end
1790
+ tab_title 'Backing up some data next, onto '+backup_to_this_target?.to_s+' ...'
1791
+ cd last_backup_directory?
1792
+ # ======================================================================= #
1793
+ # Remove some log-files next, if necessary.
1794
+ # ======================================================================= #
1795
+ consider_removing_all_but_one_log_file
1796
+ # ======================================================================= #
1797
+ # The next method will rename entries such as:
1798
+ #
1799
+ # "last_backup-13.10.2018-21:07:20/"
1800
+ #
1801
+ # to
1802
+ #
1803
+ # "backup-13.10.2018-21:07:20/"
1804
+ #
1805
+ # specifically.
1806
+ #
1807
+ # This is necessary so that we can only have one such directory
1808
+ # name, after we are done with this method here.
1809
+ # ======================================================================= #
1810
+ consider_renaming_all_old_last_backup_directories
1811
+ # ======================================================================= #
1812
+ # We will also create a log file, to denote when we started to
1813
+ # do this current backup-operation.
1814
+ # ======================================================================= #
1815
+ create_the_log_last_backup_file
1816
+ create_the_directory_containing_the_last_backup
1817
+ create_a_symlink_pointing_to_that_directory_that_was_just_created
1818
+ # ======================================================================= #
1819
+ # === Back up the AUTOGENERATED directory
1820
+ #
1821
+ # We will next attempt to backup the directory at /AUTOGENERATED/.
1822
+ # This must come before we create a new directory at the mounted
1823
+ # USB device, simply because we may not copy anything at all,
1824
+ # or some error may happen that causes an interrupt.
1825
+ # ======================================================================= #
1826
+ try_to_backup_the_autogenerated_directory
1827
+ # ======================================================================= #
1828
+ # === Back up the audio directory as well
1829
+ # ======================================================================= #
1830
+ try_to_backup_the_audio_directory
1831
+ unless File.directory? backup_to_this_target?
1832
+ FileUtils.mkdir_p(backup_to_this_target?)
1833
+ end
1834
+ # ======================================================================= #
1835
+ # Next, iterate over the directories that we wish to backup.
1836
+ # ======================================================================= #
1837
+ backup_which_directories?.each {|this_directory|
1838
+ this_directory = ensure_trailing_backslash_for(this_directory)
1839
+ tab_title("Backing up #{this_directory}.")
1840
+ this_directory = this_directory.dup if this_directory.frozen?
1841
+ # ===================================================================== #
1842
+ # Ensure that we have a trailing '/' character here.
1843
+ # ===================================================================== #
1844
+ this_directory << '/' unless this_directory.end_with?('/')
1845
+ e "#{rev}Now backing up the directory #{sdir(this_directory)}"+
1846
+ ' onto '+
1847
+ steelblue(
1848
+ backup_to_this_target?+
1849
+ File.basename(this_directory)
1850
+ )+'.'
1851
+ cpr(this_directory, backup_to_this_target?)
1852
+ }
1853
+ popup_notification(:backup_complete) if show_popup_notification?
1854
+ do_sync # Synchronize the USB devices here, before we determine the end time.
1855
+ determine_end_time
1856
+ report_time_difference
1857
+ try_to_unmount_the_device
1858
+ show_backup_complete_message
1859
+ tab_title('Backup is complete!')
1860
+ # or: tab_title ''
1861
+ end; alias start_backup do_perform_the_backup_tasks # === start_backup
1862
+ alias backup_everything do_perform_the_backup_tasks # === backup_everything
1863
+ alias do_backup do_perform_the_backup_tasks # === do_backup
1864
+
1865
+ # ========================================================================= #
1866
+ # === are_we_trying_to_backup_to_a_local_harddisc?
1867
+ # ========================================================================= #
1868
+ def are_we_trying_to_backup_to_a_local_harddisc?
1869
+ case mountpoint?
1870
+ when /HDD/ # e g. @mountpoint="/Mount/HDD1/"
1871
+ true
1872
+ else
1873
+ false
1874
+ end
1875
+ end
1876
+
1877
+ # ========================================================================= #
1878
+ # === is_the_harddisc_properly_mounted?
1879
+ # ========================================================================= #
1880
+ def is_the_harddisc_properly_mounted?
1881
+ result_of_df_T = `df -T`
1882
+ return result_of_df_T.include? '/Mount/HDD'
1883
+ end
1884
+
1885
+ # ========================================================================= #
1886
+ # === run (run tag)
1887
+ # ========================================================================= #
1888
+ def run
1889
+ sanitize_the_commandline_arguments
1890
+ menu
1891
+ do_perform_the_backup_tasks if perform_the_regular_backup_routine?
1892
+ end
1893
+
1894
+ end; end
1895
+
1896
+ if __FILE__ == $PROGRAM_NAME
1897
+ BackupParadise::Backup.new(ARGV)
1898
+ end # rbackup
1899
+ # rbackup --help
1900
+ # rbackup --data_only
1901
+ # rbackup data_only