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.
- checksums.yaml +7 -0
- data/README.md +408 -0
- data/backup_paradise.gemspec +50 -0
- data/bin/backup_for_ingrid +10 -0
- data/bin/backup_paradise +7 -0
- data/bin/windows_backup_paradise +9 -0
- data/doc/README.gen +368 -0
- data/doc/TODO.md +130 -0
- data/lib/backup_paradise/actions/README.md +2 -0
- data/lib/backup_paradise/actions/backup.rb +62 -0
- data/lib/backup_paradise/base/base.rb +502 -0
- data/lib/backup_paradise/base/colours.rb +137 -0
- data/lib/backup_paradise/base/namespace.rb +16 -0
- data/lib/backup_paradise/base/tab.rb +47 -0
- data/lib/backup_paradise/colours/colours.rb +88 -0
- data/lib/backup_paradise/constants/constants.rb +162 -0
- data/lib/backup_paradise/gui/glimmer/libui/backup_for_ingrid/backup_for_ingrid.rb +87 -0
- data/lib/backup_paradise/gui/gtk2/OLD_backup.rb +220 -0
- data/lib/backup_paradise/gui/gtk3/simple_backup_widget/create.rb +70 -0
- data/lib/backup_paradise/gui/gtk3/simple_backup_widget/misc.rb +33 -0
- data/lib/backup_paradise/gui/gtk3/simple_backup_widget/simple_backup_widget.rb +160 -0
- data/lib/backup_paradise/gui/libui/backup_for_ingrid/backup_for_ingrid.rb +99 -0
- data/lib/backup_paradise/gui/libui/simple_backup_widget/simple_backup_widget.rb +119 -0
- data/lib/backup_paradise/gui/shared_code/simple_backup_widget/simple_backup_widget_module.rb +587 -0
- data/lib/backup_paradise/gui/tk/backup.rb +108 -0
- data/lib/backup_paradise/images/BACKUP_IMAGE.png +0 -0
- data/lib/backup_paradise/images/right_arrow.png +0 -0
- data/lib/backup_paradise/project/project.rb +40 -0
- data/lib/backup_paradise/requires/require_the_backup_paradise_project.rb +18 -0
- data/lib/backup_paradise/requires/require_yaml.rb +7 -0
- data/lib/backup_paradise/tab/tab.rb +87 -0
- data/lib/backup_paradise/toplevel_methods/cliner.rb +16 -0
- data/lib/backup_paradise/toplevel_methods/config.rb +86 -0
- data/lib/backup_paradise/toplevel_methods/create_and_remove.rb +63 -0
- data/lib/backup_paradise/toplevel_methods/e.rb +16 -0
- data/lib/backup_paradise/toplevel_methods/esystem.rb +19 -0
- data/lib/backup_paradise/toplevel_methods/files_and_directories.rb +181 -0
- data/lib/backup_paradise/toplevel_methods/help.rb +93 -0
- data/lib/backup_paradise/toplevel_methods/misc.rb +153 -0
- data/lib/backup_paradise/toplevel_methods/mountpoint.rb +188 -0
- data/lib/backup_paradise/toplevel_methods/opnn.rb +27 -0
- data/lib/backup_paradise/utility_scripts/backup/backup.rb +1901 -0
- data/lib/backup_paradise/version/version.rb +19 -0
- data/lib/backup_paradise/windows/README.md +1 -0
- data/lib/backup_paradise/windows/windows.rb +101 -0
- data/lib/backup_paradise/www/backup.cgi +63 -0
- data/lib/backup_paradise/yaml/config.yml +82 -0
- data/lib/backup_paradise.rb +5 -0
- data/test/testing_toplevel_functionality.rb +11 -0
- 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
|