backup_paradise 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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