backup_paradise 1.2.37
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 +375 -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 +347 -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 +493 -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 +222 -0
- data/lib/backup_paradise/gui/gtk3/simple_backup_widget/create.rb +64 -0
- data/lib/backup_paradise/gui/gtk3/simple_backup_widget/misc.rb +34 -0
- data/lib/backup_paradise/gui/gtk3/simple_backup_widget/simple_backup_widget.rb +167 -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 +595 -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 +77 -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 +185 -0
- data/lib/backup_paradise/toplevel_methods/opnn.rb +25 -0
- data/lib/backup_paradise/utility_scripts/backup/backup.rb +1389 -0
- data/lib/backup_paradise/utility_scripts/backup/constants.rb +34 -0
- data/lib/backup_paradise/utility_scripts/backup/initialize.rb +71 -0
- data/lib/backup_paradise/utility_scripts/backup/menu.rb +360 -0
- data/lib/backup_paradise/utility_scripts/backup/run.rb +20 -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 +78 -0
- data/lib/backup_paradise.rb +5 -0
- data/test/testing_toplevel_functionality.rb +11 -0
- metadata +198 -0
| @@ -0,0 +1,1389 @@ | |
| 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/utility_scripts/backup/constants.rb'
         | 
| 32 | 
            +
              require 'backup_paradise/utility_scripts/backup/initialize.rb'
         | 
| 33 | 
            +
              require 'backup_paradise/utility_scripts/backup/menu.rb'
         | 
| 34 | 
            +
              require 'backup_paradise/utility_scripts/backup/run.rb'
         | 
| 35 | 
            +
              require 'backup_paradise/toplevel_methods/config.rb'
         | 
| 36 | 
            +
              require 'backup_paradise/toplevel_methods/help.rb'
         | 
| 37 | 
            +
              require 'backup_paradise/toplevel_methods/mountpoint.rb'
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              # ========================================================================= #
         | 
| 40 | 
            +
              # === reset                                                     (reset tag)
         | 
| 41 | 
            +
              # ========================================================================= #
         | 
| 42 | 
            +
              def reset
         | 
| 43 | 
            +
                super()
         | 
| 44 | 
            +
                # ======================================================================= #
         | 
| 45 | 
            +
                # === @mountpoint
         | 
| 46 | 
            +
                # ======================================================================= #
         | 
| 47 | 
            +
                @mountpoint = nil
         | 
| 48 | 
            +
                # ======================================================================= #
         | 
| 49 | 
            +
                # === @internal_hash
         | 
| 50 | 
            +
                # ======================================================================= #
         | 
| 51 | 
            +
                @internal_hash = {}
         | 
| 52 | 
            +
                # ======================================================================= #
         | 
| 53 | 
            +
                # === :simplify_the_directory_layout
         | 
| 54 | 
            +
                #
         | 
| 55 | 
            +
                # If the following variable is set to true then this means that the
         | 
| 56 | 
            +
                # target directory will be slightly simplified. There will not be
         | 
| 57 | 
            +
                # any ':' characters; these will become '_' characters.
         | 
| 58 | 
            +
                #
         | 
| 59 | 
            +
                # This was necessary because windows NTFS seems to struggle with
         | 
| 60 | 
            +
                # ':' characters. 
         | 
| 61 | 
            +
                # ======================================================================= #
         | 
| 62 | 
            +
                @internal_hash[:simplify_the_directory_layout] = true
         | 
| 63 | 
            +
                # ======================================================================= #
         | 
| 64 | 
            +
                # === :perform_backup
         | 
| 65 | 
            +
                #
         | 
| 66 | 
            +
                # The next variable determines whether we will perform a backup
         | 
| 67 | 
            +
                # job or not. By default this will be false - it will be set
         | 
| 68 | 
            +
                # to true through the menu() interface, via its else clause.
         | 
| 69 | 
            +
                # ======================================================================= #
         | 
| 70 | 
            +
                @internal_hash[:perform_backup] = true
         | 
| 71 | 
            +
                # ======================================================================= #
         | 
| 72 | 
            +
                # === :are_we_on_windows
         | 
| 73 | 
            +
                #
         | 
| 74 | 
            +
                # This can be used to overrule any other windows-specific checks.
         | 
| 75 | 
            +
                # ======================================================================= #
         | 
| 76 | 
            +
                @internal_hash[:are_we_on_windows] = nil
         | 
| 77 | 
            +
                # ======================================================================= #
         | 
| 78 | 
            +
                # === :date
         | 
| 79 | 
            +
                # ======================================================================= #
         | 
| 80 | 
            +
                @internal_hash[:date] = dd_mm_yyyy
         | 
| 81 | 
            +
                # ======================================================================= #
         | 
| 82 | 
            +
                # === :show_popup_notification
         | 
| 83 | 
            +
                # ======================================================================= #
         | 
| 84 | 
            +
                @internal_hash[:show_popup_notification] =
         | 
| 85 | 
            +
                  BackupParadise.show_popup_notification?
         | 
| 86 | 
            +
                # ======================================================================= #
         | 
| 87 | 
            +
                # === :last_backup_directory
         | 
| 88 | 
            +
                # ======================================================================= #
         | 
| 89 | 
            +
                @internal_hash[:last_backup_directory] = nil
         | 
| 90 | 
            +
                # ======================================================================= #
         | 
| 91 | 
            +
                # === :array_store_times
         | 
| 92 | 
            +
                #
         | 
| 93 | 
            +
                # The next Array will keep track of how long it took to backup
         | 
| 94 | 
            +
                # the data.
         | 
| 95 | 
            +
                # ======================================================================= #
         | 
| 96 | 
            +
                @internal_hash[:array_store_times] = []
         | 
| 97 | 
            +
                # ======================================================================= #
         | 
| 98 | 
            +
                # === :use_this_as_timestamp
         | 
| 99 | 
            +
                #
         | 
| 100 | 
            +
                # The next variable will keep the timestamp as-is.
         | 
| 101 | 
            +
                #
         | 
| 102 | 
            +
                # This may include ':' characters, which Windows NTFS does not seem
         | 
| 103 | 
            +
                # to like. Thus, since as of September 2020, a slightly simpler
         | 
| 104 | 
            +
                # variant is used here.
         | 
| 105 | 
            +
                # ======================================================================= #
         | 
| 106 | 
            +
                determine_the_current_timestamp
         | 
| 107 | 
            +
                # ======================================================================= #
         | 
| 108 | 
            +
                # === :backup_these_directories
         | 
| 109 | 
            +
                #
         | 
| 110 | 
            +
                # Determine the directories that we wish to back up.
         | 
| 111 | 
            +
                # ======================================================================= #
         | 
| 112 | 
            +
                @internal_hash[:backup_these_directories] = all_important_directories?
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              # ========================================================================= #
         | 
| 116 | 
            +
              # === start_the_gtk3_bindings
         | 
| 117 | 
            +
              #
         | 
| 118 | 
            +
              # To invoke this method, try:
         | 
| 119 | 
            +
              #
         | 
| 120 | 
            +
              #   rbackup --gui
         | 
| 121 | 
            +
              #   rbackup --gtk
         | 
| 122 | 
            +
              #
         | 
| 123 | 
            +
              # ========================================================================= #
         | 
| 124 | 
            +
              def start_the_gtk3_bindings
         | 
| 125 | 
            +
                require 'backup_paradise/gui/gtk3/simple_backup_widget/simple_backup_widget.rb'
         | 
| 126 | 
            +
                BackupParadise::GUI::Gtk::SimpleBackupWidget.run
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              # ========================================================================= #
         | 
| 130 | 
            +
              # === default_tab_title
         | 
| 131 | 
            +
              # ========================================================================= #
         | 
| 132 | 
            +
              def default_tab_title
         | 
| 133 | 
            +
                tab_title('Backup is complete!')
         | 
| 134 | 
            +
              end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
              # ========================================================================= #
         | 
| 137 | 
            +
              # === backup_which_directories?
         | 
| 138 | 
            +
              # ========================================================================= #
         | 
| 139 | 
            +
              def backup_which_directories?
         | 
| 140 | 
            +
                @internal_hash[:backup_these_directories]
         | 
| 141 | 
            +
              end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
              # ========================================================================= #
         | 
| 144 | 
            +
              # === return_this_absolute_directory
         | 
| 145 | 
            +
              # ========================================================================= #
         | 
| 146 | 
            +
              def return_this_absolute_directory(i)
         | 
| 147 | 
            +
                i = case i
         | 
| 148 | 
            +
                # ======================================================================= #
         | 
| 149 | 
            +
                # === DATA_DIRECTORY
         | 
| 150 | 
            +
                # ======================================================================= #
         | 
| 151 | 
            +
                when 'DATA_DIRECTORY'
         | 
| 152 | 
            +
                  DATA_DIRECTORY
         | 
| 153 | 
            +
                # ======================================================================= #
         | 
| 154 | 
            +
                # === SRC_DIRECTORY
         | 
| 155 | 
            +
                # ======================================================================= #
         | 
| 156 | 
            +
                when 'SRC_DIRECTORY',
         | 
| 157 | 
            +
                     'SOURCE_DIRECTORY'
         | 
| 158 | 
            +
                  SOURCE_DIRECTORY
         | 
| 159 | 
            +
                # ======================================================================= #
         | 
| 160 | 
            +
                # === STUDIUM_DIRECTORY
         | 
| 161 | 
            +
                # ======================================================================= #
         | 
| 162 | 
            +
                when 'STUDIUM_DIRECTORY'
         | 
| 163 | 
            +
                  STUDIUM_DIRECTORY
         | 
| 164 | 
            +
                else
         | 
| 165 | 
            +
                  i
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
                i
         | 
| 168 | 
            +
              end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
              # ========================================================================= #
         | 
| 171 | 
            +
              # === return_the_songs_directory
         | 
| 172 | 
            +
              # ========================================================================= #
         | 
| 173 | 
            +
              def return_the_songs_directory
         | 
| 174 | 
            +
                DIRECTORY_CONTAINING_ALL_SONGS
         | 
| 175 | 
            +
              end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
              # ========================================================================= #
         | 
| 178 | 
            +
              # === show_help
         | 
| 179 | 
            +
              # ========================================================================= #
         | 
| 180 | 
            +
              def show_help
         | 
| 181 | 
            +
                BackupParadise.show_help
         | 
| 182 | 
            +
              end; alias display_help show_help # === display_help
         | 
| 183 | 
            +
             | 
| 184 | 
            +
              # ========================================================================= #
         | 
| 185 | 
            +
              # === simplify_the_directory_layout?
         | 
| 186 | 
            +
              # ========================================================================= #
         | 
| 187 | 
            +
              def simplify_the_directory_layout?
         | 
| 188 | 
            +
                @internal_hash[:simplify_the_directory_layout]
         | 
| 189 | 
            +
              end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
              # ========================================================================= #
         | 
| 192 | 
            +
              # === set_commandline_arguments
         | 
| 193 | 
            +
              # ========================================================================= #
         | 
| 194 | 
            +
              def set_commandline_arguments(i = ARGV)
         | 
| 195 | 
            +
                @commandline_arguments = i
         | 
| 196 | 
            +
              end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
              # ========================================================================= #
         | 
| 199 | 
            +
              # === commandline_arguments?
         | 
| 200 | 
            +
              # ========================================================================= #
         | 
| 201 | 
            +
              def commandline_arguments?
         | 
| 202 | 
            +
                @commandline_arguments
         | 
| 203 | 
            +
              end
         | 
| 204 | 
            +
             | 
| 205 | 
            +
              # ========================================================================= #
         | 
| 206 | 
            +
              # === first_argument?
         | 
| 207 | 
            +
              # ========================================================================= #
         | 
| 208 | 
            +
              def first_argument?
         | 
| 209 | 
            +
                @commandline_arguments.first
         | 
| 210 | 
            +
              end; alias first? first_argument? # === first?
         | 
| 211 | 
            +
             | 
| 212 | 
            +
              # ========================================================================= #
         | 
| 213 | 
            +
              # === is_target_harddisc_a_ntfs_system?
         | 
| 214 | 
            +
              #
         | 
| 215 | 
            +
              # This method will return a boolean - true or false.
         | 
| 216 | 
            +
              #
         | 
| 217 | 
            +
              # It will return true if the target harddisc is a NTFS system, and
         | 
| 218 | 
            +
              # false otherwise.
         | 
| 219 | 
            +
              # ========================================================================= #
         | 
| 220 | 
            +
              def is_target_harddisc_a_ntfs_system?
         | 
| 221 | 
            +
                return_value = false
         | 
| 222 | 
            +
                _ = '/Mount'
         | 
| 223 | 
            +
                if mount_target?.include? _
         | 
| 224 | 
            +
                  # ===================================================================== #
         | 
| 225 | 
            +
                  # Next, determine what is mounted.
         | 
| 226 | 
            +
                  # ===================================================================== #
         | 
| 227 | 
            +
                  these_may_be_mounted = `df -T -ah`.split(N).select {|line| line.include? _ }
         | 
| 228 | 
            +
                  if these_may_be_mounted and these_may_be_mounted.first and
         | 
| 229 | 
            +
                    these_may_be_mounted.first.include?('fuseblk') # This may mean a NTFS system.
         | 
| 230 | 
            +
                    return_value = true
         | 
| 231 | 
            +
                  end
         | 
| 232 | 
            +
                end
         | 
| 233 | 
            +
                return return_value
         | 
| 234 | 
            +
              end
         | 
| 235 | 
            +
             | 
| 236 | 
            +
              # ========================================================================= #
         | 
| 237 | 
            +
              # === determine_whether_the_target_harddisc_is_a_ntfs_system
         | 
| 238 | 
            +
              # ========================================================================= #
         | 
| 239 | 
            +
              def determine_whether_the_target_harddisc_is_a_ntfs_system
         | 
| 240 | 
            +
                if is_target_harddisc_a_ntfs_system?
         | 
| 241 | 
            +
                  do_use_simplified_directory
         | 
| 242 | 
            +
                end
         | 
| 243 | 
            +
              end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
              # ========================================================================= #
         | 
| 246 | 
            +
              # === return_the_assumed_mountpoint_from_this_input
         | 
| 247 | 
            +
              # ========================================================================= #
         | 
| 248 | 
            +
              def return_the_assumed_mountpoint_from_this_input(i)
         | 
| 249 | 
            +
                BackupParadise.return_the_assumed_mountpoint_from_this_input(i)
         | 
| 250 | 
            +
              end
         | 
| 251 | 
            +
             | 
| 252 | 
            +
              # ========================================================================= #
         | 
| 253 | 
            +
              # === set_mountpoint
         | 
| 254 | 
            +
              # ========================================================================= #
         | 
| 255 | 
            +
              def set_mountpoint(i)
         | 
| 256 | 
            +
                i = i.dup
         | 
| 257 | 
            +
                if BackupParadise.is_this_a_shortcut?(i)
         | 
| 258 | 
            +
                  i = return_the_assumed_mountpoint_from_this_input(i)
         | 
| 259 | 
            +
                end
         | 
| 260 | 
            +
                i = i.dup if i.frozen?
         | 
| 261 | 
            +
                i << '/' unless i.end_with? '/'
         | 
| 262 | 
            +
                @mountpoint = i
         | 
| 263 | 
            +
                # ======================================================================= #
         | 
| 264 | 
            +
                # Sync it back to the toplevel as well:
         | 
| 265 | 
            +
                # ======================================================================= #
         | 
| 266 | 
            +
                determine_the_target_mountpoint(@mountpoint)
         | 
| 267 | 
            +
                determine_where_to_backup_to_exactly
         | 
| 268 | 
            +
              end; alias set_backup_to_this_target set_mountpoint # === set_backup_to_this_target
         | 
| 269 | 
            +
                   alias set_target_mountpoint     set_mountpoint # === set_target_mountpoint
         | 
| 270 | 
            +
             | 
| 271 | 
            +
              # ========================================================================= #
         | 
| 272 | 
            +
              # === determine_the_current_timestamp
         | 
| 273 | 
            +
              # ========================================================================= #
         | 
| 274 | 
            +
              def determine_the_current_timestamp
         | 
| 275 | 
            +
                if @internal_hash[:simplify_the_directory_layout]
         | 
| 276 | 
            +
                  @internal_hash[:use_this_as_timestamp] =
         | 
| 277 | 
            +
                    "#{date?}-#{current_time.tr(':','_')}"
         | 
| 278 | 
            +
                else
         | 
| 279 | 
            +
                  @internal_hash[:use_this_as_timestamp] =
         | 
| 280 | 
            +
                    "#{date?}-#{current_time}"
         | 
| 281 | 
            +
                end
         | 
| 282 | 
            +
              end
         | 
| 283 | 
            +
             | 
| 284 | 
            +
              # ========================================================================= #
         | 
| 285 | 
            +
              # === date?
         | 
| 286 | 
            +
            # ========================================================================= #
         | 
| 287 | 
            +
              def date?
         | 
| 288 | 
            +
                @internal_hash[:date]
         | 
| 289 | 
            +
              end
         | 
| 290 | 
            +
             | 
| 291 | 
            +
              # ========================================================================= #
         | 
| 292 | 
            +
              # === use_this_as_timestamp?
         | 
| 293 | 
            +
              # ========================================================================= #
         | 
| 294 | 
            +
              def use_this_as_timestamp?
         | 
| 295 | 
            +
                @internal_hash[:use_this_as_timestamp]
         | 
| 296 | 
            +
              end
         | 
| 297 | 
            +
             | 
| 298 | 
            +
              # ========================================================================= #
         | 
| 299 | 
            +
              # === sanitize_the_commandline_arguments
         | 
| 300 | 
            +
              # ========================================================================= #
         | 
| 301 | 
            +
              def sanitize_the_commandline_arguments(
         | 
| 302 | 
            +
                  hash = commandline_arguments?
         | 
| 303 | 
            +
                )
         | 
| 304 | 
            +
                copy = hash.dup
         | 
| 305 | 
            +
                # ======================================================================= #
         | 
| 306 | 
            +
                # === :commandline_arguments
         | 
| 307 | 
            +
                # ======================================================================= #
         | 
| 308 | 
            +
                if hash.is_a?(Hash) and hash.has_key?(:commandline_arguments)
         | 
| 309 | 
            +
                  hash[:commandline_arguments].each {|entry|
         | 
| 310 | 
            +
                    if BackupParadise.is_this_a_shortcut?(entry)
         | 
| 311 | 
            +
                      copy[:backup_to_this_target] =
         | 
| 312 | 
            +
                        BackupParadise.return_the_assumed_mountpoint_from_this_input(entry)
         | 
| 313 | 
            +
                      copy[:commandline_arguments].reject! {|inner_entry|
         | 
| 314 | 
            +
                        inner_entry == entry
         | 
| 315 | 
            +
                      }
         | 
| 316 | 
            +
                    end
         | 
| 317 | 
            +
                  }
         | 
| 318 | 
            +
                  set_commandline_arguments(copy)
         | 
| 319 | 
            +
                end
         | 
| 320 | 
            +
              end
         | 
| 321 | 
            +
             | 
| 322 | 
            +
              # ========================================================================= #
         | 
| 323 | 
            +
              # === can_not_backup_this_directory_as_it_does_not_exist
         | 
| 324 | 
            +
              # ========================================================================= #
         | 
| 325 | 
            +
              def can_not_backup_this_directory_as_it_does_not_exist(i)
         | 
| 326 | 
            +
                opnn; e "Can not backup the directory at #{sdir(i)}"
         | 
| 327 | 
            +
                opnn; e 'as it does not exist.'
         | 
| 328 | 
            +
              end
         | 
| 329 | 
            +
             | 
| 330 | 
            +
              # ========================================================================= #
         | 
| 331 | 
            +
              # === try_to_unmount_the_device
         | 
| 332 | 
            +
              #
         | 
| 333 | 
            +
              # This method can be used to automatically unmount the target device
         | 
| 334 | 
            +
              # again.
         | 
| 335 | 
            +
              # ========================================================================= #
         | 
| 336 | 
            +
              def try_to_unmount_the_device
         | 
| 337 | 
            +
                this_is_the_mounted_device = backup_to_this_directory?
         | 
| 338 | 
            +
                # ======================================================================= #
         | 
| 339 | 
            +
                # Change directory to another directory where we can safely
         | 
| 340 | 
            +
                # umount the directory.
         | 
| 341 | 
            +
                # ======================================================================= #
         | 
| 342 | 
            +
                if has_superuser_abilities?
         | 
| 343 | 
            +
                  if BackupParadise.target_mountpoint?.include?('HDD1')
         | 
| 344 | 
            +
                    # =================================================================== #
         | 
| 345 | 
            +
                    # Unmount harddiscs quickly.
         | 
| 346 | 
            +
                    # =================================================================== #
         | 
| 347 | 
            +
                    unmount :hdd # Since as of 17.06.2008 we will unmount the harddisc as well.
         | 
| 348 | 
            +
                  end
         | 
| 349 | 
            +
                  if File.directory? '/Depot/j/'
         | 
| 350 | 
            +
                    cd '/Depot/j/'
         | 
| 351 | 
            +
                  elsif File.directory? '/tmp'
         | 
| 352 | 
            +
                    cd '/tmp'
         | 
| 353 | 
            +
                  elsif File.directory? '/home/Temp'
         | 
| 354 | 
            +
                    cd '/home/Temp'
         | 
| 355 | 
            +
                  else
         | 
| 356 | 
            +
                    cd '/'
         | 
| 357 | 
            +
                  end
         | 
| 358 | 
            +
                  opnn; e "Next unmounting the device at "\
         | 
| 359 | 
            +
                          "`#{sfancy(this_is_the_mounted_device)}`."
         | 
| 360 | 
            +
                  system "umount #{this_is_the_mounted_device}"
         | 
| 361 | 
            +
                end
         | 
| 362 | 
            +
              end
         | 
| 363 | 
            +
             | 
| 364 | 
            +
              # ========================================================================= #
         | 
| 365 | 
            +
              # === consider_renaming_all_old_last_backup_directories
         | 
| 366 | 
            +
              #
         | 
| 367 | 
            +
              # This will rename all "last_directory*" directory entries to their
         | 
| 368 | 
            +
              # corresponding equivalent without the leading 'last_' string.
         | 
| 369 | 
            +
              # ========================================================================= #
         | 
| 370 | 
            +
              def consider_renaming_all_old_last_backup_directories
         | 
| 371 | 
            +
                # ======================================================================= #
         | 
| 372 | 
            +
                # First grab all possible entries, and check that these are all existing
         | 
| 373 | 
            +
                # directories. If there is at the least one entry we will continue to
         | 
| 374 | 
            +
                # operate on it.
         | 
| 375 | 
            +
                # ======================================================================= #
         | 
| 376 | 
            +
                all_possible_entries = Dir["#{mount_target?}last_backup-*"].select {|entry|
         | 
| 377 | 
            +
                  File.directory?(entry)
         | 
| 378 | 
            +
                }
         | 
| 379 | 
            +
                if all_possible_entries.size > 0
         | 
| 380 | 
            +
                  # ===================================================================== #
         | 
| 381 | 
            +
                  # Batch-rename these directories in that case:
         | 
| 382 | 
            +
                  # ===================================================================== #
         | 
| 383 | 
            +
                  all_possible_entries.each {|this_directory|
         | 
| 384 | 
            +
                    new_name_of_the_new_target_directory = this_directory.sub(/^last_/,'')
         | 
| 385 | 
            +
                    opnn; e "Now renaming `#{sdir(this_directory)}` "\
         | 
| 386 | 
            +
                            "to `#{sdir(new_name_of_the_new_target_directory)}`."
         | 
| 387 | 
            +
                    rename(this_directory, new_name_of_the_new_target_directory)
         | 
| 388 | 
            +
                  }
         | 
| 389 | 
            +
                end
         | 
| 390 | 
            +
              end
         | 
| 391 | 
            +
             | 
| 392 | 
            +
              # ========================================================================= #
         | 
| 393 | 
            +
              # === verbose_create_a_directory_at_this_position
         | 
| 394 | 
            +
              #
         | 
| 395 | 
            +
              # The first argument to this method should be the target directory,
         | 
| 396 | 
            +
              # a path, that is where you wish to create that directory.
         | 
| 397 | 
            +
              #
         | 
| 398 | 
            +
              # The second argument to this method, which is optional, denotes the
         | 
| 399 | 
            +
              # permission that is to be used.
         | 
| 400 | 
            +
              # ========================================================================= #
         | 
| 401 | 
            +
              def verbose_create_a_directory_at_this_position(
         | 
| 402 | 
            +
                  this_position, use_this_permission = 0754
         | 
| 403 | 
            +
                )
         | 
| 404 | 
            +
                e "Creating a directory at `#{sdir(this_position)}` next."
         | 
| 405 | 
            +
                mkdir(this_position, use_this_permission)
         | 
| 406 | 
            +
              end
         | 
| 407 | 
            +
             | 
| 408 | 
            +
              # ========================================================================= #
         | 
| 409 | 
            +
              # === show_the_logfile
         | 
| 410 | 
            +
              #
         | 
| 411 | 
            +
              # To invoke this method from the commandline, try:
         | 
| 412 | 
            +
              #
         | 
| 413 | 
            +
              #   advanced_backup --logfile?
         | 
| 414 | 
            +
              #
         | 
| 415 | 
            +
              # ========================================================================= #
         | 
| 416 | 
            +
              def show_the_logfile
         | 
| 417 | 
            +
                _ = FILE_BACKUP_LOG
         | 
| 418 | 
            +
                if File.exist? _
         | 
| 419 | 
            +
                  opnn; e "Now reading the dataset from the file `#{sfile(_)}`:"
         | 
| 420 | 
            +
                  e
         | 
| 421 | 
            +
                  File.readlines(_).each {|line|
         | 
| 422 | 
            +
                    e orangered("  #{line.chomp}")
         | 
| 423 | 
            +
                  }
         | 
| 424 | 
            +
                  e
         | 
| 425 | 
            +
                else
         | 
| 426 | 
            +
                  opnn; e no_file_exists_at(_)
         | 
| 427 | 
            +
                end
         | 
| 428 | 
            +
              end
         | 
| 429 | 
            +
             | 
| 430 | 
            +
              # ========================================================================= #
         | 
| 431 | 
            +
              # === show_popup_notification?
         | 
| 432 | 
            +
              # ========================================================================= #
         | 
| 433 | 
            +
              def show_popup_notification?
         | 
| 434 | 
            +
                @internal_hash[:show_popup_notification]
         | 
| 435 | 
            +
              end
         | 
| 436 | 
            +
             | 
| 437 | 
            +
              # ========================================================================= #
         | 
| 438 | 
            +
              # === do_show_popup
         | 
| 439 | 
            +
              # ========================================================================= #
         | 
| 440 | 
            +
              def do_show_popup
         | 
| 441 | 
            +
                @internal_hash[:show_popup_notification] = true
         | 
| 442 | 
            +
              end; alias show_popup do_show_popup # === show_popup
         | 
| 443 | 
            +
             | 
| 444 | 
            +
              # ========================================================================= #
         | 
| 445 | 
            +
              # === determine_where_to_backup_to_exactly
         | 
| 446 | 
            +
              #
         | 
| 447 | 
            +
              # This is automatically called whenever set_mountpoint() is called.
         | 
| 448 | 
            +
              # ========================================================================= #
         | 
| 449 | 
            +
              def determine_where_to_backup_to_exactly(
         | 
| 450 | 
            +
                  i = @mountpoint
         | 
| 451 | 
            +
                )
         | 
| 452 | 
            +
                backup_to_this_target = i
         | 
| 453 | 
            +
                @backup_to_this_target = backup_to_this_target.dup
         | 
| 454 | 
            +
                @backup_to_this_target << "/backup-#{return_current_date_and_time}/"
         | 
| 455 | 
            +
                @backup_to_this_target = @backup_to_this_target.squeeze('/')
         | 
| 456 | 
            +
                @backup_to_this_target.tr!(':','_') if simplify_the_directory_layout?
         | 
| 457 | 
            +
                set_last_backup_directory(@backup_to_this_target)
         | 
| 458 | 
            +
              end
         | 
| 459 | 
            +
             | 
| 460 | 
            +
              # ========================================================================= #
         | 
| 461 | 
            +
              # === mountpoint?
         | 
| 462 | 
            +
              # ========================================================================= #
         | 
| 463 | 
            +
              def mountpoint?
         | 
| 464 | 
            +
                @mountpoint
         | 
| 465 | 
            +
              end; alias mounted_at?            mountpoint? # === mounted_at?
         | 
| 466 | 
            +
                   alias target_base_directory? mountpoint? # === target_base_directory?
         | 
| 467 | 
            +
             | 
| 468 | 
            +
              # ========================================================================= #
         | 
| 469 | 
            +
              # === opnn
         | 
| 470 | 
            +
              # ========================================================================= #
         | 
| 471 | 
            +
              def opnn(i = NAMESPACE)
         | 
| 472 | 
            +
                if i.is_a? String
         | 
| 473 | 
            +
                  i = { namespace: i }
         | 
| 474 | 
            +
                end
         | 
| 475 | 
            +
                super(i)
         | 
| 476 | 
            +
              end
         | 
| 477 | 
            +
             | 
| 478 | 
            +
              # ========================================================================= #
         | 
| 479 | 
            +
              # === backup_the_audio_directory_then_exit
         | 
| 480 | 
            +
              #
         | 
| 481 | 
            +
              # Backup the audio directory, then exit the program.
         | 
| 482 | 
            +
              # ========================================================================= #
         | 
| 483 | 
            +
              def backup_the_audio_directory_then_exit
         | 
| 484 | 
            +
                backup_the_audio_directory
         | 
| 485 | 
            +
                exit_program
         | 
| 486 | 
            +
              end
         | 
| 487 | 
            +
             | 
| 488 | 
            +
              # ========================================================================= #
         | 
| 489 | 
            +
              # === do_use_simplified_directory
         | 
| 490 | 
            +
              #
         | 
| 491 | 
            +
              # The old code used to be like this:
         | 
| 492 | 
            +
              #
         | 
| 493 | 
            +
              #   set_last_backup_directory(mount_point?+'last_backup')
         | 
| 494 | 
            +
              #
         | 
| 495 | 
            +
              # ========================================================================= #
         | 
| 496 | 
            +
              def do_use_simplified_directory
         | 
| 497 | 
            +
                @internal_hash[:simplify_the_directory_layout] = true
         | 
| 498 | 
            +
                determine_the_current_timestamp # Must sync it back again.
         | 
| 499 | 
            +
              end
         | 
| 500 | 
            +
             | 
| 501 | 
            +
              # ========================================================================= #
         | 
| 502 | 
            +
              # === create_file_keeping_track_of_when_the_last_backup_happened
         | 
| 503 | 
            +
              #
         | 
| 504 | 
            +
              # This method will store date-information into a file, when the last
         | 
| 505 | 
            +
              # backup happened.
         | 
| 506 | 
            +
              #
         | 
| 507 | 
            +
              # It is normally found in a place such as:
         | 
| 508 | 
            +
              #
         | 
| 509 | 
            +
              #    /home/x/data/LAST_BACKUP.md
         | 
| 510 | 
            +
              #
         | 
| 511 | 
            +
              # Since Dec 2012, we will also append the date to the name of said file.
         | 
| 512 | 
            +
              # ========================================================================= #
         | 
| 513 | 
            +
              def create_file_keeping_track_of_when_the_last_backup_happened(
         | 
| 514 | 
            +
                  use_this_as_timestamp = use_this_as_timestamp?
         | 
| 515 | 
            +
                )
         | 
| 516 | 
            +
                base_target = "#{data_directory?}LAST_BACKUP"
         | 
| 517 | 
            +
                target = "#{base_target}_#{date?}.md" # Append the date here.
         | 
| 518 | 
            +
                e N+'Storing '+sfile(use_this_as_timestamp)+' into '+
         | 
| 519 | 
            +
                  sfile(target)+' to note'
         | 
| 520 | 
            +
                e 'down when the last backup was performed.'
         | 
| 521 | 
            +
                write_what_into(use_this_as_timestamp, target)
         | 
| 522 | 
            +
                # ======================================================================= #
         | 
| 523 | 
            +
                # Next, obtain an array with potential similar names. We will have
         | 
| 524 | 
            +
                # to delete stray entries so as to not clutter our original home
         | 
| 525 | 
            +
                # directory there.
         | 
| 526 | 
            +
                # ======================================================================= #
         | 
| 527 | 
            +
                array_all_last_backup_files = Dir["#{base_target}*"]
         | 
| 528 | 
            +
                if array_all_last_backup_files.size > 1
         | 
| 529 | 
            +
                  array_all_last_backup_files = array_all_last_backup_files.sort_by {|d|
         | 
| 530 | 
            +
                    d.split('.').reverse
         | 
| 531 | 
            +
                  } # Keep it sorted.
         | 
| 532 | 
            +
                  e N+'We found more than one entry in '+
         | 
| 533 | 
            +
                    sdir(File.dirname(base_target)+'/')+', thus removing'
         | 
| 534 | 
            +
                  e 'the extra-entries next.'
         | 
| 535 | 
            +
                  array_all_last_backup_files[0..-2].each {|my_file|
         | 
| 536 | 
            +
                    e "Removing `#{sfile(my_file)}` next."
         | 
| 537 | 
            +
                    remove_file(my_file)
         | 
| 538 | 
            +
                  }
         | 
| 539 | 
            +
                end
         | 
| 540 | 
            +
              end; alias store_when_was_the_last_backup create_file_keeping_track_of_when_the_last_backup_happened # === store_when_was_the_last_backup
         | 
| 541 | 
            +
             | 
| 542 | 
            +
              # ========================================================================= #
         | 
| 543 | 
            +
              # === show_available_mountpoints
         | 
| 544 | 
            +
              #
         | 
| 545 | 
            +
              # This helper-method can show the available mountpoints, at the least
         | 
| 546 | 
            +
              # on a linux system.
         | 
| 547 | 
            +
              #
         | 
| 548 | 
            +
              # To invoke this, try:
         | 
| 549 | 
            +
              #
         | 
| 550 | 
            +
              #   rbackup --mountpoints
         | 
| 551 | 
            +
              #
         | 
| 552 | 
            +
              # ========================================================================= #
         | 
| 553 | 
            +
              def show_available_mountpoints
         | 
| 554 | 
            +
                begin
         | 
| 555 | 
            +
                  require 'mountpoints'
         | 
| 556 | 
            +
                rescue LoadError; end
         | 
| 557 | 
            +
                if Mountpoints.is_any_mountpoint_available?
         | 
| 558 | 
            +
                  opnn; e 'The available (and mounted) USB devices are:'
         | 
| 559 | 
            +
                  e
         | 
| 560 | 
            +
                  Mountpoints[].each {|this_usb_device|
         | 
| 561 | 
            +
                    e "  #{sfancy(this_usb_device)}"
         | 
| 562 | 
            +
                  }
         | 
| 563 | 
            +
                  e
         | 
| 564 | 
            +
                else
         | 
| 565 | 
            +
                  opnn; e 'No external USB devices appear to be mounted.'
         | 
| 566 | 
            +
                end
         | 
| 567 | 
            +
              end
         | 
| 568 | 
            +
             | 
| 569 | 
            +
              # ========================================================================= #
         | 
| 570 | 
            +
              # === show_available_mountpoints_then_exit
         | 
| 571 | 
            +
              # ========================================================================= #
         | 
| 572 | 
            +
              def show_available_mountpoints_then_exit
         | 
| 573 | 
            +
                show_available_mountpoints
         | 
| 574 | 
            +
                exit_program
         | 
| 575 | 
            +
              end
         | 
| 576 | 
            +
             | 
| 577 | 
            +
              # ========================================================================= #
         | 
| 578 | 
            +
              # === report_time_difference
         | 
| 579 | 
            +
              #
         | 
| 580 | 
            +
              # This method will report to the user how long it took this class
         | 
| 581 | 
            +
              # to backup the system, e. g. 30 minutes or something like that.
         | 
| 582 | 
            +
              # ========================================================================= #
         | 
| 583 | 
            +
              def report_time_difference
         | 
| 584 | 
            +
                if @internal_hash[:array_store_times].size > 1
         | 
| 585 | 
            +
                  start_time = @internal_hash[:array_store_times][-2]
         | 
| 586 | 
            +
                  end_time   = @internal_hash[:array_store_times].last
         | 
| 587 | 
            +
                  time_difference = end_time - start_time # This will result in a Float.
         | 
| 588 | 
            +
                  if time_difference.respond_to? :round
         | 
| 589 | 
            +
                    time_difference = time_difference.round(3)
         | 
| 590 | 
            +
                  end
         | 
| 591 | 
            +
                  n_minutes = (time_difference.to_f / 60.0).round(2).to_s
         | 
| 592 | 
            +
                  opnn; e "#{tomato('Time required')} for this backup-operation: "\
         | 
| 593 | 
            +
                          "#{sfancy(time_difference.to_s)}"\
         | 
| 594 | 
            +
                          " seconds (#{royalblue(n_minutes)} minutes)."
         | 
| 595 | 
            +
                  consider_creating_a_log_file(time_difference)
         | 
| 596 | 
            +
                end
         | 
| 597 | 
            +
              end
         | 
| 598 | 
            +
             | 
| 599 | 
            +
              # ========================================================================= #
         | 
| 600 | 
            +
              # === show_welcome_message
         | 
| 601 | 
            +
              # ========================================================================= #
         | 
| 602 | 
            +
              def show_welcome_message
         | 
| 603 | 
            +
                print_rev
         | 
| 604 | 
            +
                cliner
         | 
| 605 | 
            +
                e "Welcome to the #{lightcoral('BackupParadise')} #{rev}project!"
         | 
| 606 | 
            +
                report_todays_date
         | 
| 607 | 
            +
                cliner
         | 
| 608 | 
            +
                e "Starting to backup into the target at `#{sdir(main_target?)}`."
         | 
| 609 | 
            +
                cliner
         | 
| 610 | 
            +
              end
         | 
| 611 | 
            +
             | 
| 612 | 
            +
              # ========================================================================= #
         | 
| 613 | 
            +
              # === consider_removing_all_but_one_log_file
         | 
| 614 | 
            +
              # ========================================================================= #
         | 
| 615 | 
            +
              def consider_removing_all_but_one_log_file
         | 
| 616 | 
            +
                log_files = return_all_log_files
         | 
| 617 | 
            +
                if log_files.size > 1
         | 
| 618 | 
            +
                  opnn; e 'More than one log file has been found. We will delete'
         | 
| 619 | 
            +
                  opnn; e 'all but one next.'
         | 
| 620 | 
            +
                  log_files.pop
         | 
| 621 | 
            +
                  delete_files(log_files, :be_verbose)
         | 
| 622 | 
            +
                end
         | 
| 623 | 
            +
              end
         | 
| 624 | 
            +
             | 
| 625 | 
            +
              # ========================================================================= #
         | 
| 626 | 
            +
              # === return_all_log_files
         | 
| 627 | 
            +
              # ========================================================================= #
         | 
| 628 | 
            +
              def return_all_log_files(
         | 
| 629 | 
            +
                  from_where = mounted_at?
         | 
| 630 | 
            +
                )
         | 
| 631 | 
            +
                Dir["#{from_where}log_last_backup_*"].select {|entry|
         | 
| 632 | 
            +
                  File.file? entry # We only want files.
         | 
| 633 | 
            +
                }
         | 
| 634 | 
            +
              end
         | 
| 635 | 
            +
             | 
| 636 | 
            +
              # ========================================================================= #
         | 
| 637 | 
            +
              # === popup_notification
         | 
| 638 | 
            +
              #
         | 
| 639 | 
            +
              # Use this method to send a graphical popup to the user. Only invoke
         | 
| 640 | 
            +
              # it when we set @show_popup_notification to true.
         | 
| 641 | 
            +
              # ========================================================================= #
         | 
| 642 | 
            +
              def popup_notification(
         | 
| 643 | 
            +
                  what = :backup_complete
         | 
| 644 | 
            +
                )
         | 
| 645 | 
            +
                case what
         | 
| 646 | 
            +
                when :backup_complete
         | 
| 647 | 
            +
                  esystem 'xmessage -center Backup finished!'
         | 
| 648 | 
            +
                end
         | 
| 649 | 
            +
              end
         | 
| 650 | 
            +
             | 
| 651 | 
            +
              # ========================================================================= #
         | 
| 652 | 
            +
              # === determine_the_starting_time
         | 
| 653 | 
            +
              # ========================================================================= #
         | 
| 654 | 
            +
              def determine_the_starting_time
         | 
| 655 | 
            +
                @internal_hash[:array_store_times] << Time.now
         | 
| 656 | 
            +
              end; alias determine_starting_time determine_the_starting_time # === determine_starting_time
         | 
| 657 | 
            +
             | 
| 658 | 
            +
              # ========================================================================= #
         | 
| 659 | 
            +
              # === determine_end_time
         | 
| 660 | 
            +
              # ========================================================================= #
         | 
| 661 | 
            +
              def determine_end_time
         | 
| 662 | 
            +
                @internal_hash[:array_store_times] << Time.now
         | 
| 663 | 
            +
              end
         | 
| 664 | 
            +
             | 
| 665 | 
            +
              # ========================================================================= #
         | 
| 666 | 
            +
              # === backup_the_programs_directory
         | 
| 667 | 
            +
              #  
         | 
| 668 | 
            +
              # This method can be used to backup the /Programs directory.
         | 
| 669 | 
            +
              # ========================================================================= #
         | 
| 670 | 
            +
              def backup_the_programs_directory(
         | 
| 671 | 
            +
                  target_directory = PROGRAMS_DIRECTORY
         | 
| 672 | 
            +
                )
         | 
| 673 | 
            +
                if File.directory? target_directory
         | 
| 674 | 
            +
                  cliner
         | 
| 675 | 
            +
                  e 'Now backing up the Programs/ directory from '+
         | 
| 676 | 
            +
                     sfancy(target_directory)+' into '+
         | 
| 677 | 
            +
                     sfile(main_target?+File.basename(target_directory))
         | 
| 678 | 
            +
                  cliner
         | 
| 679 | 
            +
                  report_total_size_of(target_directory)
         | 
| 680 | 
            +
                  if target_hdd_does_not_have_enough_space_left?
         | 
| 681 | 
            +
                    opnn; e "We have to skip backing up #{sdir(target_directory)}"
         | 
| 682 | 
            +
                    opnn; e 'as it does not have enough space left (Threshold: '+
         | 
| 683 | 
            +
                             MINIMAL_FILESIZE+' bytes)' 
         | 
| 684 | 
            +
                  else    
         | 
| 685 | 
            +
                    backup_this_directory_if_it_exists(
         | 
| 686 | 
            +
                      target_directory, :default, :do_not_continue
         | 
| 687 | 
            +
                    )
         | 
| 688 | 
            +
                  end
         | 
| 689 | 
            +
                else
         | 
| 690 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(target_directory)
         | 
| 691 | 
            +
                end
         | 
| 692 | 
            +
              end
         | 
| 693 | 
            +
             | 
| 694 | 
            +
              # ========================================================================= #
         | 
| 695 | 
            +
              # === return_default_target_directory_from_this_input
         | 
| 696 | 
            +
              # ========================================================================= #
         | 
| 697 | 
            +
              def return_default_target_directory_from_this_input(i)
         | 
| 698 | 
            +
                rds(
         | 
| 699 | 
            +
                  main_target?+
         | 
| 700 | 
            +
                  File.basename(i)+
         | 
| 701 | 
            +
                  '/'
         | 
| 702 | 
            +
                )
         | 
| 703 | 
            +
              end
         | 
| 704 | 
            +
             | 
| 705 | 
            +
              # ========================================================================= #
         | 
| 706 | 
            +
              # === determine_the_target_mountpoint
         | 
| 707 | 
            +
              #
         | 
| 708 | 
            +
              # This method will determine the target base mountpoint that
         | 
| 709 | 
            +
              # is to be used.
         | 
| 710 | 
            +
              # ========================================================================= # 
         | 
| 711 | 
            +
              def determine_the_target_mountpoint(
         | 
| 712 | 
            +
                  i = '/Mount/USB1/'
         | 
| 713 | 
            +
                )
         | 
| 714 | 
            +
                BackupParadise.target_mountpoint = i
         | 
| 715 | 
            +
              end
         | 
| 716 | 
            +
             | 
| 717 | 
            +
              # ========================================================================= #
         | 
| 718 | 
            +
              # === create_the_directory_containing_the_last_backup
         | 
| 719 | 
            +
              # ========================================================================= #
         | 
| 720 | 
            +
              def create_the_directory_containing_the_last_backup
         | 
| 721 | 
            +
                target = "#{main_target?}backup-#{use_this_as_timestamp?}"
         | 
| 722 | 
            +
                # ======================================================================= #
         | 
| 723 | 
            +
                # Next, create the last_backup directory:
         | 
| 724 | 
            +
                # ======================================================================= #
         | 
| 725 | 
            +
                begin
         | 
| 726 | 
            +
                  mkdir(target, 0755)
         | 
| 727 | 
            +
                rescue Errno::EINVAL
         | 
| 728 | 
            +
                  target.tr!(':','_')
         | 
| 729 | 
            +
                  mkdir(target, 0755)
         | 
| 730 | 
            +
                end
         | 
| 731 | 
            +
                @internal_hash[:last_backup_directory] = rds(target+'/')
         | 
| 732 | 
            +
                opnn; e "Creating a directory at "\
         | 
| 733 | 
            +
                        "`#{sdir(@internal_hash[:last_backup_directory])}`."
         | 
| 734 | 
            +
              end
         | 
| 735 | 
            +
             | 
| 736 | 
            +
              # ========================================================================= #
         | 
| 737 | 
            +
              # === create_a_symlink_pointing_to_that_directory_that_was_just_created
         | 
| 738 | 
            +
              #
         | 
| 739 | 
            +
              # This method will create a symlink to the last_backup/ directory.
         | 
| 740 | 
            +
              #
         | 
| 741 | 
            +
              # This is synonymous to the following ruby code:
         | 
| 742 | 
            +
              #
         | 
| 743 | 
            +
              #   File.symlink('last_backup-13.08.2018-22:12:26/','last_backup')
         | 
| 744 | 
            +
              #
         | 
| 745 | 
            +
              # ========================================================================= #
         | 
| 746 | 
            +
              def create_a_symlink_pointing_to_that_directory_that_was_just_created
         | 
| 747 | 
            +
                cd_to_the_mounted_device
         | 
| 748 | 
            +
                create_a_symlink_here = "#{backup_to_this_directory?}last_backup"
         | 
| 749 | 
            +
                from_this_target = File.basename(@internal_hash[:last_backup_directory])
         | 
| 750 | 
            +
                from_this_target.chop! if from_this_target.end_with? '/'
         | 
| 751 | 
            +
                # ========================================================================= #
         | 
| 752 | 
            +
                # First, delete the old symlink if it exists. The method delete_symlink()
         | 
| 753 | 
            +
                # will do that check for us.
         | 
| 754 | 
            +
                # ========================================================================= #
         | 
| 755 | 
            +
                delete_symlink(create_a_symlink_here)
         | 
| 756 | 
            +
                # ========================================================================= #
         | 
| 757 | 
            +
                # The next action can fail on e. g. vfat filesystems, with the error
         | 
| 758 | 
            +
                # being Errno::EPERM. Hence we must rescue here.
         | 
| 759 | 
            +
                # ========================================================================= #
         | 
| 760 | 
            +
                begin
         | 
| 761 | 
            +
                  do_symlink(from_this_target, create_a_symlink_here)
         | 
| 762 | 
            +
                  if File.exist? create_a_symlink_here
         | 
| 763 | 
            +
                    points_towards = File.readlink(create_a_symlink_here)
         | 
| 764 | 
            +
                    opnn; e 'Next setting a symlink at `'+sfancy(create_a_symlink_here)+
         | 
| 765 | 
            +
                            '` pointing'
         | 
| 766 | 
            +
                    opnn; e "towards `#{sfile(points_towards)}`."
         | 
| 767 | 
            +
                  else
         | 
| 768 | 
            +
                    opnn; e no_file_exists_at(create_a_symlink_here)
         | 
| 769 | 
            +
                  end
         | 
| 770 | 
            +
                rescue Errno::EPERM
         | 
| 771 | 
            +
                end
         | 
| 772 | 
            +
              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
         | 
| 773 | 
            +
             | 
| 774 | 
            +
              # ========================================================================= #
         | 
| 775 | 
            +
              # === do_sync
         | 
| 776 | 
            +
              #
         | 
| 777 | 
            +
              # The do_sync() method, also aliased towards synchronize(), will sync
         | 
| 778 | 
            +
              # the data onto USB items, by using the sync command.
         | 
| 779 | 
            +
              # ========================================================================= #
         | 
| 780 | 
            +
              def do_sync
         | 
| 781 | 
            +
                opnn; e 'Starting to '+steelblue('sync data')+' ...'
         | 
| 782 | 
            +
                system 'sync' # Be silent since May 2014.
         | 
| 783 | 
            +
                opnn; e "> Syncing finished. (At: "\
         | 
| 784 | 
            +
                        "#{rosybrown(return_current_date_and_time.to_s)})"
         | 
| 785 | 
            +
              end; alias synchronize do_sync # === synchronize
         | 
| 786 | 
            +
             | 
| 787 | 
            +
              # ========================================================================= #
         | 
| 788 | 
            +
              # === backup_this_directory
         | 
| 789 | 
            +
              #
         | 
| 790 | 
            +
              # This method will quickly backup a given directory.
         | 
| 791 | 
            +
              #
         | 
| 792 | 
            +
              # The second argument will be the target-directory onto which
         | 
| 793 | 
            +
              # we will copy our files.
         | 
| 794 | 
            +
              # ========================================================================= #
         | 
| 795 | 
            +
              def backup_this_directory(
         | 
| 796 | 
            +
                  i,
         | 
| 797 | 
            +
                  copy_to_this_target_directory = nil,
         | 
| 798 | 
            +
                  shall_we_sync = true
         | 
| 799 | 
            +
                )
         | 
| 800 | 
            +
                case shall_we_sync
         | 
| 801 | 
            +
                when :do_not_sync
         | 
| 802 | 
            +
                  shall_we_sync = false
         | 
| 803 | 
            +
                end
         | 
| 804 | 
            +
                case copy_to_this_target_directory
         | 
| 805 | 
            +
                when nil,
         | 
| 806 | 
            +
                     :default
         | 
| 807 | 
            +
                  copy_to_this_target_directory = return_default_target_directory_from_this_input(i)
         | 
| 808 | 
            +
                end
         | 
| 809 | 
            +
                unless File.directory? copy_to_this_target_directory
         | 
| 810 | 
            +
                  mkdir(copy_to_this_target_directory)
         | 
| 811 | 
            +
                end
         | 
| 812 | 
            +
                cd copy_to_this_target_directory
         | 
| 813 | 
            +
                opnn; e 'Now copying '+sdir(i)+
         | 
| 814 | 
            +
                        ' to '+sdir(copy_to_this_target_directory)+'.'
         | 
| 815 | 
            +
                if File.directory?(i)
         | 
| 816 | 
            +
                  i << '*'
         | 
| 817 | 
            +
                end
         | 
| 818 | 
            +
                cpr(
         | 
| 819 | 
            +
                  i, copy_to_this_target_directory
         | 
| 820 | 
            +
                )
         | 
| 821 | 
            +
                do_sync if shall_we_sync
         | 
| 822 | 
            +
              end
         | 
| 823 | 
            +
             | 
| 824 | 
            +
              # ========================================================================= #
         | 
| 825 | 
            +
              # === backup_the_system_directory
         | 
| 826 | 
            +
              #  
         | 
| 827 | 
            +
              # This method can be used to backup the "/System/Settings/" directory,
         | 
| 828 | 
            +
              # as it may be found in GoboLinux.
         | 
| 829 | 
            +
              # ========================================================================= #
         | 
| 830 | 
            +
              def backup_the_system_directory(
         | 
| 831 | 
            +
                  target_directory = SYSTEM_SETTINGS_DIRECTORY
         | 
| 832 | 
            +
                )
         | 
| 833 | 
            +
                if File.directory? target_directory
         | 
| 834 | 
            +
                  cliner
         | 
| 835 | 
            +
                  e 'Now backing up the system-settings directory from '+
         | 
| 836 | 
            +
                     sfancy(target_directory)+' into '+
         | 
| 837 | 
            +
                     sfile(main_target?+File.basename(target_directory))
         | 
| 838 | 
            +
                  cliner
         | 
| 839 | 
            +
                  report_total_size_of(target_directory)
         | 
| 840 | 
            +
                  cpr(
         | 
| 841 | 
            +
                    target_directory, 
         | 
| 842 | 
            +
                    backup_to_this_target?
         | 
| 843 | 
            +
                  )
         | 
| 844 | 
            +
                else
         | 
| 845 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(target_directory)
         | 
| 846 | 
            +
                end
         | 
| 847 | 
            +
              end; alias backup_system_directory backup_the_system_directory # === backup_system_directory
         | 
| 848 | 
            +
             | 
| 849 | 
            +
              # ========================================================================= #
         | 
| 850 | 
            +
              # === backup_to_this_target?
         | 
| 851 | 
            +
              # ========================================================================= #
         | 
| 852 | 
            +
              def backup_to_this_target?
         | 
| 853 | 
            +
                @backup_to_this_target
         | 
| 854 | 
            +
              end
         | 
| 855 | 
            +
             | 
| 856 | 
            +
              # ========================================================================= #
         | 
| 857 | 
            +
              # === backup_the_data_directory_then_exit
         | 
| 858 | 
            +
              #
         | 
| 859 | 
            +
              # Backup only Data directory.
         | 
| 860 | 
            +
              # ========================================================================= #
         | 
| 861 | 
            +
              def backup_the_data_directory_then_exit
         | 
| 862 | 
            +
                backup_data_directory
         | 
| 863 | 
            +
                exit_program
         | 
| 864 | 
            +
              end; alias backup_data_directory_then_exit backup_the_data_directory_then_exit # === backup_data_directory_then_exit
         | 
| 865 | 
            +
             | 
| 866 | 
            +
              # ========================================================================= #
         | 
| 867 | 
            +
              # === backup_the_data_directory                                  (data tag)
         | 
| 868 | 
            +
              #
         | 
| 869 | 
            +
              # This method will backup the DATA directory, e. g. the one that is
         | 
| 870 | 
            +
              # at "/home/x/DATA/" on my home system.
         | 
| 871 | 
            +
              # ========================================================================= #
         | 
| 872 | 
            +
              def backup_the_data_directory(
         | 
| 873 | 
            +
                  target_directory = DATA_DIRECTORY
         | 
| 874 | 
            +
                )
         | 
| 875 | 
            +
                if File.directory? target_directory
         | 
| 876 | 
            +
                  mountpoint_target = main_target?+File.basename(target_directory)
         | 
| 877 | 
            +
                  cliner
         | 
| 878 | 
            +
                  e "Now backing up the DATA directory from "\
         | 
| 879 | 
            +
                    "#{sfancy(target_directory)} into "\
         | 
| 880 | 
            +
                    "#{sfile(mountpoint_target)}."
         | 
| 881 | 
            +
                  cliner
         | 
| 882 | 
            +
                  report_total_size_of(target_directory)
         | 
| 883 | 
            +
                  unless File.directory? mountpoint_target
         | 
| 884 | 
            +
                    create_directory(mountpoint_target, 0755)
         | 
| 885 | 
            +
                  end
         | 
| 886 | 
            +
                  mkdir(backup_to_this_target?+File.basename(target_directory))
         | 
| 887 | 
            +
                  cpr(
         | 
| 888 | 
            +
                    target_directory, 
         | 
| 889 | 
            +
                    backup_to_this_target?
         | 
| 890 | 
            +
                  )
         | 
| 891 | 
            +
                else
         | 
| 892 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(target_directory)
         | 
| 893 | 
            +
                end
         | 
| 894 | 
            +
              end; alias backup_only_data_directory backup_the_data_directory # === backup_only_data_directory
         | 
| 895 | 
            +
                   alias backup_data_directory      backup_the_data_directory # === backup_data_directory
         | 
| 896 | 
            +
             | 
| 897 | 
            +
              # ========================================================================= #
         | 
| 898 | 
            +
              # === ensure_trailing_backslash_for
         | 
| 899 | 
            +
              # ========================================================================= #
         | 
| 900 | 
            +
              def ensure_trailing_backslash_for(i)
         | 
| 901 | 
            +
                i = i.dup
         | 
| 902 | 
            +
                i << '/' unless i.end_with? '/'
         | 
| 903 | 
            +
                return i
         | 
| 904 | 
            +
              end
         | 
| 905 | 
            +
             | 
| 906 | 
            +
              # ========================================================================= #
         | 
| 907 | 
            +
              # === backup_the_studium_directory
         | 
| 908 | 
            +
              # ========================================================================= #
         | 
| 909 | 
            +
              def backup_the_studium_directory(
         | 
| 910 | 
            +
                  target_directory = STUDIUM_DIRECTORY
         | 
| 911 | 
            +
                )
         | 
| 912 | 
            +
                target_directory = ensure_trailing_backslash_for(target_directory)
         | 
| 913 | 
            +
                if File.directory? target_directory
         | 
| 914 | 
            +
                  tab_title('Backing up the '+target_directory+' directory.')
         | 
| 915 | 
            +
                  cliner
         | 
| 916 | 
            +
                  e 'Now backing up the studium/ directory from '+
         | 
| 917 | 
            +
                     sfancy(target_directory)+' into '+
         | 
| 918 | 
            +
                     sfile(main_target?+File.basename(target_directory))
         | 
| 919 | 
            +
                  cliner
         | 
| 920 | 
            +
                  report_total_size_of(target_directory)
         | 
| 921 | 
            +
                  mkdir(backup_to_this_target?+File.basename(target_directory))
         | 
| 922 | 
            +
                  cpr(
         | 
| 923 | 
            +
                    target_directory, 
         | 
| 924 | 
            +
                    backup_to_this_target?
         | 
| 925 | 
            +
                  )
         | 
| 926 | 
            +
                else
         | 
| 927 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(target_directory)
         | 
| 928 | 
            +
                end
         | 
| 929 | 
            +
              end
         | 
| 930 | 
            +
             | 
| 931 | 
            +
              # ========================================================================= #
         | 
| 932 | 
            +
              # === backup_the_video_directory
         | 
| 933 | 
            +
              # ========================================================================= #
         | 
| 934 | 
            +
              def backup_the_video_directory(
         | 
| 935 | 
            +
                  target_directory = VIDEO_DIRECTORY
         | 
| 936 | 
            +
                )
         | 
| 937 | 
            +
                target_directory = ensure_trailing_backslash_for(target_directory)
         | 
| 938 | 
            +
                if File.directory? target_directory
         | 
| 939 | 
            +
                  cliner
         | 
| 940 | 
            +
                  e 'Now backing up the Video directory from '+
         | 
| 941 | 
            +
                     sfancy(target_directory)+' into '+
         | 
| 942 | 
            +
                     sfile(main_target?+File.basename(target_directory))
         | 
| 943 | 
            +
                  cliner
         | 
| 944 | 
            +
                  tab_title('Backing up the directory '+target_directory+' next.')
         | 
| 945 | 
            +
                  report_total_size_of(target_directory)
         | 
| 946 | 
            +
                  set_backup_to_this_target(target_base_directory?)
         | 
| 947 | 
            +
                  mkdir(
         | 
| 948 | 
            +
                    target_base_directory?+File.basename(target_directory)
         | 
| 949 | 
            +
                  )
         | 
| 950 | 
            +
                  cpr(
         | 
| 951 | 
            +
                    target_directory, 
         | 
| 952 | 
            +
                    target_base_directory?
         | 
| 953 | 
            +
                  )
         | 
| 954 | 
            +
                  show_all_is_done_message
         | 
| 955 | 
            +
                  default_tab_title
         | 
| 956 | 
            +
                else
         | 
| 957 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(target_directory)
         | 
| 958 | 
            +
                end
         | 
| 959 | 
            +
              end
         | 
| 960 | 
            +
             | 
| 961 | 
            +
              # ========================================================================= #
         | 
| 962 | 
            +
              # === BackupParadise::Backup[]
         | 
| 963 | 
            +
              # ========================================================================= #
         | 
| 964 | 
            +
              def self.[](i = '')
         | 
| 965 | 
            +
                new(i)
         | 
| 966 | 
            +
              end
         | 
| 967 | 
            +
             | 
| 968 | 
            +
              # ========================================================================= #
         | 
| 969 | 
            +
              # === try_to_backup_the_autogenerated_directory
         | 
| 970 | 
            +
              # ========================================================================= #
         | 
| 971 | 
            +
              def try_to_backup_the_autogenerated_directory(
         | 
| 972 | 
            +
                  i = AUTOGENERATED_DIRECTORY
         | 
| 973 | 
            +
                )
         | 
| 974 | 
            +
                i = ensure_trailing_backslash_for(i)
         | 
| 975 | 
            +
                if File.directory? i
         | 
| 976 | 
            +
                  opnn; e 'Now trying to backup the AUTOGENERATED '\
         | 
| 977 | 
            +
                          'directory at `'+sdir(i)+'`.'
         | 
| 978 | 
            +
                  new_target = @mountpoint.squeeze('/')
         | 
| 979 | 
            +
                  n_gigabytes = BackupParadise.size_in_gigabytes?(i).to_s
         | 
| 980 | 
            +
                  opnn; e 'This directory has a total of '+
         | 
| 981 | 
            +
                          sfancy(n_files_in?(i).to_s)+' entries '\
         | 
| 982 | 
            +
                          '(Total size: '+n_gigabytes+' GB).'
         | 
| 983 | 
            +
                  unless File.directory? new_target
         | 
| 984 | 
            +
                    verbose_create_a_directory_at_this_position(new_target)
         | 
| 985 | 
            +
                  end
         | 
| 986 | 
            +
                  tab_title('Backing up the AUTOGENERATED directory.')
         | 
| 987 | 
            +
                  cpr(i, new_target)
         | 
| 988 | 
            +
                else
         | 
| 989 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(i)
         | 
| 990 | 
            +
                end
         | 
| 991 | 
            +
              end; alias backup_autogenerated_directory     try_to_backup_the_autogenerated_directory # === backup_autogenerated_directory
         | 
| 992 | 
            +
                   alias backup_the_autogenerated_directory try_to_backup_the_autogenerated_directory # === backup_the_autogenerated_directory
         | 
| 993 | 
            +
             | 
| 994 | 
            +
              # ========================================================================= #
         | 
| 995 | 
            +
              # === backup_into_the_default_chroot_directory                 (chroot tag)
         | 
| 996 | 
            +
              # ========================================================================= #
         | 
| 997 | 
            +
              def backup_into_the_default_chroot_directory(
         | 
| 998 | 
            +
                  i = :chroot
         | 
| 999 | 
            +
                )
         | 
| 1000 | 
            +
                e
         | 
| 1001 | 
            +
                e "#{rev}Setting the target to #{sdir(i)} next."
         | 
| 1002 | 
            +
                e
         | 
| 1003 | 
            +
                set_target_mountpoint(i) # Set to the above Chroot target. We could also use :chroot.
         | 
| 1004 | 
            +
                set_main_target(
         | 
| 1005 | 
            +
                  "#{main_target?.dup}#{home_dir_of_user_x?.dup}"
         | 
| 1006 | 
            +
                )
         | 
| 1007 | 
            +
                # ======================================================================= #
         | 
| 1008 | 
            +
                # Must copy the autogenerated directory first:
         | 
| 1009 | 
            +
                # ======================================================================= #
         | 
| 1010 | 
            +
                try_to_backup_the_autogenerated_directory
         | 
| 1011 | 
            +
                all_important_directories?.each {|this_directory|
         | 
| 1012 | 
            +
                  tab_title 'Now backing up the '+this_directory+' directory ...'
         | 
| 1013 | 
            +
                  new_target = main_target?+File.basename(this_directory)
         | 
| 1014 | 
            +
                  mkdir(new_target)
         | 
| 1015 | 
            +
                  cpr(this_directory, main_target?)
         | 
| 1016 | 
            +
                }
         | 
| 1017 | 
            +
                all_done_message
         | 
| 1018 | 
            +
              end
         | 
| 1019 | 
            +
             | 
| 1020 | 
            +
              # ========================================================================= #
         | 
| 1021 | 
            +
              # === backup_src_directory                                        (src tag)
         | 
| 1022 | 
            +
              #
         | 
| 1023 | 
            +
              # This method will backup the SRC/ directory, aka "/home/x/src/". It
         | 
| 1024 | 
            +
              # is evidently geared towards the system at my home setup.
         | 
| 1025 | 
            +
              #
         | 
| 1026 | 
            +
              # To invoke this method from the commandline, try:
         | 
| 1027 | 
            +
              #
         | 
| 1028 | 
            +
              #   rbackup --src-dir
         | 
| 1029 | 
            +
              #
         | 
| 1030 | 
            +
              # ========================================================================= #
         | 
| 1031 | 
            +
              def backup_the_source_directory(
         | 
| 1032 | 
            +
                  target_directory = SOURCE_DIRECTORY
         | 
| 1033 | 
            +
                )
         | 
| 1034 | 
            +
                target_directory = ensure_trailing_backslash_for(target_directory)
         | 
| 1035 | 
            +
                if File.directory? target_directory
         | 
| 1036 | 
            +
                  tab_title('Backing up the '+target_directory+' directory.')
         | 
| 1037 | 
            +
                  cliner
         | 
| 1038 | 
            +
                  e 'Now backing up the '+sdir('src/')+' directory from '+
         | 
| 1039 | 
            +
                     sfancy(target_directory)+' into '+
         | 
| 1040 | 
            +
                     sfile(main_target?+File.basename(target_directory))
         | 
| 1041 | 
            +
                  cliner
         | 
| 1042 | 
            +
                  report_total_size_of(target_directory)
         | 
| 1043 | 
            +
                  mkdir(backup_to_this_target?+File.basename(target_directory))
         | 
| 1044 | 
            +
                  cpr(
         | 
| 1045 | 
            +
                    target_directory, 
         | 
| 1046 | 
            +
                    backup_to_this_target?
         | 
| 1047 | 
            +
                  )
         | 
| 1048 | 
            +
                else
         | 
| 1049 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(target_directory)
         | 
| 1050 | 
            +
                end
         | 
| 1051 | 
            +
              end
         | 
| 1052 | 
            +
             | 
| 1053 | 
            +
              # ========================================================================= #
         | 
| 1054 | 
            +
              # === backup_the_books_directory                                 (data tag)
         | 
| 1055 | 
            +
              #
         | 
| 1056 | 
            +
              # This method will backup the BOOKS directory, e. g. the one that is
         | 
| 1057 | 
            +
              # at "/home/x/books/" on my home system.
         | 
| 1058 | 
            +
              # ========================================================================= #
         | 
| 1059 | 
            +
              def backup_the_books_directory(
         | 
| 1060 | 
            +
                  target_directory = BOOKS_DIRECTORY
         | 
| 1061 | 
            +
                )
         | 
| 1062 | 
            +
                target_directory = ensure_trailing_backslash_for(target_directory)
         | 
| 1063 | 
            +
                if File.directory? target_directory
         | 
| 1064 | 
            +
                  tab_title('Backing up the '+target_directory+' directory.')
         | 
| 1065 | 
            +
                  cliner
         | 
| 1066 | 
            +
                  e 'Now backing up the books/ directory from '+
         | 
| 1067 | 
            +
                     sfancy(target_directory)+' into '+
         | 
| 1068 | 
            +
                     sfile(main_target?+File.basename(target_directory))
         | 
| 1069 | 
            +
                  cliner
         | 
| 1070 | 
            +
                  report_total_size_of(target_directory)
         | 
| 1071 | 
            +
                  unless File.directory? backup_to_this_target?+File.basename(target_directory)
         | 
| 1072 | 
            +
                    opnn; verbose_create_a_directory_at_this_position(
         | 
| 1073 | 
            +
                            backup_to_this_target?+File.basename(target_directory),
         | 
| 1074 | 
            +
                            0755
         | 
| 1075 | 
            +
                          )
         | 
| 1076 | 
            +
                  end
         | 
| 1077 | 
            +
                  cpr(
         | 
| 1078 | 
            +
                    target_directory, 
         | 
| 1079 | 
            +
                    backup_to_this_target?
         | 
| 1080 | 
            +
                  )
         | 
| 1081 | 
            +
                  rename_tab('.')
         | 
| 1082 | 
            +
                else
         | 
| 1083 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(target_directory)
         | 
| 1084 | 
            +
                end
         | 
| 1085 | 
            +
              end; alias backup_only_books_directory backup_the_books_directory # === backup_only_books_directory
         | 
| 1086 | 
            +
                   alias backup_books_directory      backup_the_books_directory # === backup_books_directory
         | 
| 1087 | 
            +
             | 
| 1088 | 
            +
              # ========================================================================= #
         | 
| 1089 | 
            +
              # === show_backup_complete_message
         | 
| 1090 | 
            +
              # ========================================================================= #
         | 
| 1091 | 
            +
              def show_backup_complete_message
         | 
| 1092 | 
            +
                e "#{BackupParadise.steelblue('Backup complete!')}#{rev}" # The old colour was cyan, up until 2021.
         | 
| 1093 | 
            +
              end; alias all_done                 show_backup_complete_message # === all_done
         | 
| 1094 | 
            +
                   alias show_all_is_done_message show_backup_complete_message # === show_all_is_done_message
         | 
| 1095 | 
            +
                   alias all_done_message         show_backup_complete_message # === all_done_message
         | 
| 1096 | 
            +
             | 
| 1097 | 
            +
              # ========================================================================= #
         | 
| 1098 | 
            +
              # === do_not_perform_the_regular_backup_routine
         | 
| 1099 | 
            +
              # ========================================================================= #
         | 
| 1100 | 
            +
              def do_not_perform_the_regular_backup_routine
         | 
| 1101 | 
            +
                @internal_hash[:perform_backup] = false
         | 
| 1102 | 
            +
              end
         | 
| 1103 | 
            +
             | 
| 1104 | 
            +
              # ========================================================================= #
         | 
| 1105 | 
            +
              # === perform_the_regular_backup_routine?
         | 
| 1106 | 
            +
              # ========================================================================= #
         | 
| 1107 | 
            +
              def perform_the_regular_backup_routine?
         | 
| 1108 | 
            +
                @internal_hash[:perform_backup]
         | 
| 1109 | 
            +
              end
         | 
| 1110 | 
            +
             | 
| 1111 | 
            +
              # ========================================================================= #
         | 
| 1112 | 
            +
              # === report_todays_date
         | 
| 1113 | 
            +
              # ========================================================================= #
         | 
| 1114 | 
            +
              def report_todays_date
         | 
| 1115 | 
            +
                e "Today is the #{sfancy(date?)}."
         | 
| 1116 | 
            +
              end
         | 
| 1117 | 
            +
             | 
| 1118 | 
            +
              # ========================================================================= #
         | 
| 1119 | 
            +
              # === create_the_log_last_backup_file                             (log tag)
         | 
| 1120 | 
            +
              #
         | 
| 1121 | 
            +
              # We also have to remove all prior log files should they exist.
         | 
| 1122 | 
            +
              # ========================================================================= #
         | 
| 1123 | 
            +
              def create_the_log_last_backup_file
         | 
| 1124 | 
            +
                _ = return_all_log_files
         | 
| 1125 | 
            +
                target = main_target?+'log_last_backup_'+use_this_as_timestamp?
         | 
| 1126 | 
            +
                what = dd_mm_yyyy
         | 
| 1127 | 
            +
                opnn; e "Keeping a backup file (a log) at"
         | 
| 1128 | 
            +
                opnn; e "`#{sfile(target)}`."
         | 
| 1129 | 
            +
                write_what_into(what, target)
         | 
| 1130 | 
            +
                unless _.empty?
         | 
| 1131 | 
            +
                  # ===================================================================== #
         | 
| 1132 | 
            +
                  # Remove all old log files next.
         | 
| 1133 | 
            +
                  # ===================================================================== #
         | 
| 1134 | 
            +
                  remove_these_files(_)
         | 
| 1135 | 
            +
                end
         | 
| 1136 | 
            +
              end; alias create_log_file create_the_log_last_backup_file # === create_log_file
         | 
| 1137 | 
            +
             | 
| 1138 | 
            +
              # ========================================================================= #
         | 
| 1139 | 
            +
              # === last_backup_directory?
         | 
| 1140 | 
            +
              # ========================================================================= #
         | 
| 1141 | 
            +
              def last_backup_directory?
         | 
| 1142 | 
            +
                @internal_hash[:last_backup_directory]
         | 
| 1143 | 
            +
              end
         | 
| 1144 | 
            +
             | 
| 1145 | 
            +
              # ========================================================================= #
         | 
| 1146 | 
            +
              # === set_last_backup_directory
         | 
| 1147 | 
            +
              # ========================================================================= #
         | 
| 1148 | 
            +
              def set_last_backup_directory(i)
         | 
| 1149 | 
            +
                @internal_hash[:last_backup_directory] = i
         | 
| 1150 | 
            +
              end
         | 
| 1151 | 
            +
             | 
| 1152 | 
            +
              # ========================================================================= #
         | 
| 1153 | 
            +
              # === consider_creating_a_log_file
         | 
| 1154 | 
            +
              #
         | 
| 1155 | 
            +
              # This method will create a .log file.
         | 
| 1156 | 
            +
              #
         | 
| 1157 | 
            +
              # It accepts an argument, which should be an Integer or Float, denoting,
         | 
| 1158 | 
            +
              # in seconds, how long it took to make a backup.
         | 
| 1159 | 
            +
              # ========================================================================= #
         | 
| 1160 | 
            +
              def consider_creating_a_log_file(
         | 
| 1161 | 
            +
                  n_seconds
         | 
| 1162 | 
            +
                )
         | 
| 1163 | 
            +
                if File.directory? '/Depot/Temp/'
         | 
| 1164 | 
            +
                  n_minutes = (n_seconds.to_f / 60).round(1).to_s
         | 
| 1165 | 
            +
                  # ===================================================================== #
         | 
| 1166 | 
            +
                  # Make the seconds a bit prettier next, via trailing '0'.
         | 
| 1167 | 
            +
                  # ===================================================================== #
         | 
| 1168 | 
            +
                  n_seconds = '%.3f' % n_seconds
         | 
| 1169 | 
            +
                  what = "#{return_full_date}: Backing up the system took #{n_seconds} "\
         | 
| 1170 | 
            +
                         "seconds (#{n_minutes} minutes).\n"
         | 
| 1171 | 
            +
                  into = FILE_BACKUP_LOG
         | 
| 1172 | 
            +
                  opnn; e "Storing the time it took to backup "\
         | 
| 1173 | 
            +
                          "into the file `#{sfile(into)}`."
         | 
| 1174 | 
            +
                  append_what_into(what, into)
         | 
| 1175 | 
            +
                end
         | 
| 1176 | 
            +
              end
         | 
| 1177 | 
            +
             | 
| 1178 | 
            +
              # ========================================================================= #
         | 
| 1179 | 
            +
              # === backup_the_audio_directory                (audio tag, audio dir tag)
         | 
| 1180 | 
            +
              #
         | 
| 1181 | 
            +
              # This method can be used to backup my audio directory, which normally
         | 
| 1182 | 
            +
              # resides at "/home/x/songs/".
         | 
| 1183 | 
            +
              #
         | 
| 1184 | 
            +
              # Two arguments can be supplied to this method:
         | 
| 1185 | 
            +
              #
         | 
| 1186 | 
            +
              # (1) The first argument specifies which directory is used as the
         | 
| 1187 | 
            +
              #     input directory, where the songs that are to be copied
         | 
| 1188 | 
            +
              #     should reside.
         | 
| 1189 | 
            +
              #
         | 
| 1190 | 
            +
              # (2) If the second argument is true then only those audio files
         | 
| 1191 | 
            +
              #     that are missing will be copied.
         | 
| 1192 | 
            +
              #
         | 
| 1193 | 
            +
              # ========================================================================= #
         | 
| 1194 | 
            +
              def backup_the_audio_directory(
         | 
| 1195 | 
            +
                  i                             = DIRECTORY_CONTAINING_ALL_SONGS,
         | 
| 1196 | 
            +
                  copy_only_missing_audio_files = true
         | 
| 1197 | 
            +
                )
         | 
| 1198 | 
            +
                if File.directory? i
         | 
| 1199 | 
            +
                  copied_n_files = 0
         | 
| 1200 | 
            +
                  print rev
         | 
| 1201 | 
            +
                  cliner
         | 
| 1202 | 
            +
                  new_target = @mountpoint.squeeze('/')
         | 
| 1203 | 
            +
                  opnn; e "Now trying to backup the Audio directory "\
         | 
| 1204 | 
            +
                          "at `#{sdir(i)}`."
         | 
| 1205 | 
            +
                  colourized_target = sdir("#{new_target}#{File.basename(i)}/")
         | 
| 1206 | 
            +
                  opnn; e "The target for this will be at "\
         | 
| 1207 | 
            +
                          "`#{colourized_target}`."
         | 
| 1208 | 
            +
                  n_gigabytes = BackupParadise.size_in_gigabytes?(i).to_s
         | 
| 1209 | 
            +
                  opnn; e 'This directory has a total of '+
         | 
| 1210 | 
            +
                          sfancy(n_files_in?(i).to_s)+' entries '\
         | 
| 1211 | 
            +
                          '(Total size: '+n_gigabytes+' GB).'
         | 
| 1212 | 
            +
                  cliner
         | 
| 1213 | 
            +
                  unless File.directory? "#{new_target}#{File.basename(i)}/"
         | 
| 1214 | 
            +
                    opnn; verbose_create_a_directory_at_this_position(
         | 
| 1215 | 
            +
                            "#{new_target}#{File.basename(i)}/"
         | 
| 1216 | 
            +
                          )
         | 
| 1217 | 
            +
                  end
         | 
| 1218 | 
            +
                  tab_title('Backing up the main audio directory.')
         | 
| 1219 | 
            +
                  # ===================================================================== #
         | 
| 1220 | 
            +
                  # Else we will copy only the audio files that are missing. In order
         | 
| 1221 | 
            +
                  # to do so we have to obtain all audio-files - we will simply
         | 
| 1222 | 
            +
                  # pick all files, anyway. We will keep these entries sorted, too.
         | 
| 1223 | 
            +
                  # ===================================================================== #
         | 
| 1224 | 
            +
                  these_audio_files_may_be_copied = Dir[
         | 
| 1225 | 
            +
                    rds("#{i.delete('*')}/*")
         | 
| 1226 | 
            +
                  ].sort
         | 
| 1227 | 
            +
                  if copy_only_missing_audio_files
         | 
| 1228 | 
            +
                    these_audio_files_may_be_copied.each {|this_file|
         | 
| 1229 | 
            +
                      totally_new_target =
         | 
| 1230 | 
            +
                        "#{new_target}#{File.basename(i)}/#{File.basename(this_file)}"
         | 
| 1231 | 
            +
                      # ================================================================= #
         | 
| 1232 | 
            +
                      # We check whether the target-file exists. Only if it does not
         | 
| 1233 | 
            +
                      # exist will it be copied.
         | 
| 1234 | 
            +
                      # ================================================================= #
         | 
| 1235 | 
            +
                      unless File.exist? totally_new_target
         | 
| 1236 | 
            +
                        copied_n_files += 1
         | 
| 1237 | 
            +
                        # =============================================================== #
         | 
| 1238 | 
            +
                        # Pad the display.
         | 
| 1239 | 
            +
                        # =============================================================== #
         | 
| 1240 | 
            +
                        padded_file   = this_file.ljust(40)
         | 
| 1241 | 
            +
                        padded_target = totally_new_target.ljust(40)
         | 
| 1242 | 
            +
                        e "Copying `#{sfile(padded_file)}` to"
         | 
| 1243 | 
            +
                        e "        `#{sfile(padded_target)}`."
         | 
| 1244 | 
            +
                        copy_this_file(this_file, totally_new_target)
         | 
| 1245 | 
            +
                      end
         | 
| 1246 | 
            +
                    }
         | 
| 1247 | 
            +
                    # =================================================================== #
         | 
| 1248 | 
            +
                    # Ok, now, if we removed a file from /Depot/Audio, then the Audio/
         | 
| 1249 | 
            +
                    # directory at the mounted USB device may still have such a file.
         | 
| 1250 | 
            +
                    # So we will warn the user about this.
         | 
| 1251 | 
            +
                    # =================================================================== #
         | 
| 1252 | 
            +
                    target = "#{new_target}#{File.basename(i)}/" # This will be something like "/Mount/USB1/songs/"
         | 
| 1253 | 
            +
                    unless these_audio_files_may_be_copied.size == Dir["#{target}*"].size
         | 
| 1254 | 
            +
                      opnn; e 'It seems as if we have an unequal amount of Audio files in '
         | 
| 1255 | 
            +
                      opnn; e 'the two directories.'
         | 
| 1256 | 
            +
                      opnn; e 'This usually means that the original directory '+
         | 
| 1257 | 
            +
                              sdir(i)+' has some files'
         | 
| 1258 | 
            +
                      opnn; e 'deleted, but the target directory at '+sdir(target)+' does not.'
         | 
| 1259 | 
            +
                      opnn; e 'The old directory has '+simp(i.size.to_s)+' entries.'
         | 
| 1260 | 
            +
                    end
         | 
| 1261 | 
            +
                  else
         | 
| 1262 | 
            +
                    cpr(i, new_target)
         | 
| 1263 | 
            +
                  end
         | 
| 1264 | 
            +
                  _ = "#{new_target}#{File.basename(i)}/"
         | 
| 1265 | 
            +
                  if copied_n_files == 0
         | 
| 1266 | 
            +
                    opnn; e "No file was copied into the directory #{sdir(_)}."
         | 
| 1267 | 
            +
                    opnn; e 'This may indicate that the target audio-directory already'
         | 
| 1268 | 
            +
                    opnn; e 'contains all necessary audio-files.' 
         | 
| 1269 | 
            +
                  else
         | 
| 1270 | 
            +
                    opnn; e "Finished backing up the directory "\
         | 
| 1271 | 
            +
                            "#{sdir(i.delete('*'))} into "\
         | 
| 1272 | 
            +
                            "#{sdir(_)}."
         | 
| 1273 | 
            +
                  end
         | 
| 1274 | 
            +
                  default_tab_title
         | 
| 1275 | 
            +
                else
         | 
| 1276 | 
            +
                  can_not_backup_this_directory_as_it_does_not_exist(i)
         | 
| 1277 | 
            +
                end
         | 
| 1278 | 
            +
              end; alias try_to_backup_the_audio_directory backup_the_audio_directory # === alias try_to_backup_the_audio_directory
         | 
| 1279 | 
            +
                   alias backup_audio_directory            backup_the_audio_directory # === backup_audio_directory
         | 
| 1280 | 
            +
             | 
| 1281 | 
            +
              # ========================================================================= #
         | 
| 1282 | 
            +
              # === unmount
         | 
| 1283 | 
            +
              #
         | 
| 1284 | 
            +
              # Use this to unmount something. Right now, we unmount only the HDD.
         | 
| 1285 | 
            +
              # ========================================================================= #
         | 
| 1286 | 
            +
              def unmount(
         | 
| 1287 | 
            +
                  what = :hdd
         | 
| 1288 | 
            +
                )
         | 
| 1289 | 
            +
                case what.to_sym
         | 
| 1290 | 
            +
                when :hdd
         | 
| 1291 | 
            +
                  system "umount -l #{ENV['FIRST_HD']}"
         | 
| 1292 | 
            +
                end
         | 
| 1293 | 
            +
              end
         | 
| 1294 | 
            +
             | 
| 1295 | 
            +
              # ========================================================================= #
         | 
| 1296 | 
            +
              # === do_perform_the_backup_tasks                                 (all tag)
         | 
| 1297 | 
            +
              #
         | 
| 1298 | 
            +
              # This method is the main powerhorse of this class. It connects all the
         | 
| 1299 | 
            +
              # various steps together, one after the other.
         | 
| 1300 | 
            +
              # ========================================================================= #
         | 
| 1301 | 
            +
              def do_perform_the_backup_tasks
         | 
| 1302 | 
            +
                determine_the_starting_time
         | 
| 1303 | 
            +
                show_welcome_message
         | 
| 1304 | 
            +
                create_file_keeping_track_of_when_the_last_backup_happened
         | 
| 1305 | 
            +
                determine_whether_the_target_harddisc_is_a_ntfs_system
         | 
| 1306 | 
            +
                tab_title 'Backing up some data next, onto '+backup_to_this_target?.to_s+' ...'
         | 
| 1307 | 
            +
                cd last_backup_directory?
         | 
| 1308 | 
            +
                # ======================================================================= #
         | 
| 1309 | 
            +
                # Remove some log-files next, if necessary.
         | 
| 1310 | 
            +
                # ======================================================================= #
         | 
| 1311 | 
            +
                consider_removing_all_but_one_log_file
         | 
| 1312 | 
            +
                # ======================================================================= #
         | 
| 1313 | 
            +
                # The next method will rename entries such as:
         | 
| 1314 | 
            +
                #
         | 
| 1315 | 
            +
                #   "last_backup-13.10.2018-21:07:20/"
         | 
| 1316 | 
            +
                #
         | 
| 1317 | 
            +
                # to
         | 
| 1318 | 
            +
                #
         | 
| 1319 | 
            +
                #   "backup-13.10.2018-21:07:20/"
         | 
| 1320 | 
            +
                #
         | 
| 1321 | 
            +
                # specifically.
         | 
| 1322 | 
            +
                #
         | 
| 1323 | 
            +
                # This is necessary so that we can only have one such directory
         | 
| 1324 | 
            +
                # name, after we are done with this method here.
         | 
| 1325 | 
            +
                # ======================================================================= #
         | 
| 1326 | 
            +
                consider_renaming_all_old_last_backup_directories
         | 
| 1327 | 
            +
                # ======================================================================= #
         | 
| 1328 | 
            +
                # We will also create a log file, to denote when we started to
         | 
| 1329 | 
            +
                # do this current backup-operation.
         | 
| 1330 | 
            +
                # ======================================================================= #
         | 
| 1331 | 
            +
                create_the_log_last_backup_file
         | 
| 1332 | 
            +
                create_the_directory_containing_the_last_backup
         | 
| 1333 | 
            +
                create_a_symlink_pointing_to_that_directory_that_was_just_created
         | 
| 1334 | 
            +
                # ======================================================================= #
         | 
| 1335 | 
            +
                # === Back up the AUTOGENERATED directory
         | 
| 1336 | 
            +
                #
         | 
| 1337 | 
            +
                # We will next attempt to backup the directory at /AUTOGENERATED/.
         | 
| 1338 | 
            +
                # This must come before we create a new directory at the mounted
         | 
| 1339 | 
            +
                # USB device, simply because we may not copy anything at all,
         | 
| 1340 | 
            +
                # or some error may happen that causes an interrupt.
         | 
| 1341 | 
            +
                # ======================================================================= #
         | 
| 1342 | 
            +
                try_to_backup_the_autogenerated_directory
         | 
| 1343 | 
            +
                # ======================================================================= #
         | 
| 1344 | 
            +
                # === Back up the audio directory as well
         | 
| 1345 | 
            +
                # ======================================================================= #
         | 
| 1346 | 
            +
                try_to_backup_the_audio_directory
         | 
| 1347 | 
            +
                unless File.directory? backup_to_this_target?
         | 
| 1348 | 
            +
                  FileUtils.mkdir_p(backup_to_this_target?)
         | 
| 1349 | 
            +
                end
         | 
| 1350 | 
            +
                # ======================================================================= #
         | 
| 1351 | 
            +
                # Next, iterate over the directories that we wish to backup.
         | 
| 1352 | 
            +
                # ======================================================================= #
         | 
| 1353 | 
            +
                backup_which_directories?.each {|this_directory|
         | 
| 1354 | 
            +
                  this_directory = ensure_trailing_backslash_for(this_directory)
         | 
| 1355 | 
            +
                  tab_title("Backing up #{this_directory}.")
         | 
| 1356 | 
            +
                  this_directory = this_directory.dup if this_directory.frozen?
         | 
| 1357 | 
            +
                  # ===================================================================== #
         | 
| 1358 | 
            +
                  # Ensure that we have a trailing '/' character here.
         | 
| 1359 | 
            +
                  # ===================================================================== #
         | 
| 1360 | 
            +
                  this_directory << '/' unless this_directory.end_with?('/')
         | 
| 1361 | 
            +
                  e "#{::Colours.rev}Now backing up the directory "+
         | 
| 1362 | 
            +
                    sdir(this_directory)+
         | 
| 1363 | 
            +
                    ' onto '+
         | 
| 1364 | 
            +
                    steelblue(
         | 
| 1365 | 
            +
                      backup_to_this_target?+
         | 
| 1366 | 
            +
                      File.basename(this_directory)
         | 
| 1367 | 
            +
                    )+'.'
         | 
| 1368 | 
            +
                  cpr(this_directory, backup_to_this_target?)
         | 
| 1369 | 
            +
                }
         | 
| 1370 | 
            +
                popup_notification(:backup_complete) if show_popup_notification?
         | 
| 1371 | 
            +
                do_sync # Synchronize the USB devices here, before we determine the end time.
         | 
| 1372 | 
            +
                determine_end_time
         | 
| 1373 | 
            +
                report_time_difference
         | 
| 1374 | 
            +
                try_to_unmount_the_device
         | 
| 1375 | 
            +
                show_backup_complete_message
         | 
| 1376 | 
            +
                tab_title('Backup is complete!')
         | 
| 1377 | 
            +
                # or: tab_title ''
         | 
| 1378 | 
            +
              end; alias start_backup      do_perform_the_backup_tasks # === start_backup
         | 
| 1379 | 
            +
                   alias backup_everything do_perform_the_backup_tasks # === backup_everything
         | 
| 1380 | 
            +
                   alias do_backup         do_perform_the_backup_tasks # === do_backup
         | 
| 1381 | 
            +
             | 
| 1382 | 
            +
            end; end
         | 
| 1383 | 
            +
             | 
| 1384 | 
            +
            if __FILE__ == $PROGRAM_NAME
         | 
| 1385 | 
            +
              BackupParadise::Backup.new(ARGV)
         | 
| 1386 | 
            +
            end # rbackup
         | 
| 1387 | 
            +
                # rbackup --help
         | 
| 1388 | 
            +
                # rbackup --data_only
         | 
| 1389 | 
            +
                # rbackup data_only
         |