From 659a651aa294c335e519b4c72bbd052b3199a793 Mon Sep 17 00:00:00 2001 From: Patrick J Cherry Date: Tue, 31 Jan 2017 12:12:23 +0000 Subject: First pass with rubocop --- .rubocop.yml | 9 ++++ bin/byteback-backup | 108 +++++++++++++++++--------------------- bin/byteback-prune | 20 +++---- bin/byteback-receive | 62 +++++++++++----------- bin/byteback-restore | 61 ++++++++++----------- bin/byteback-setup-client | 6 +-- bin/byteback-setup-client-receive | 2 +- bin/byteback-snapshot | 4 +- lib/byteback/backup_directory.rb | 14 +++-- lib/byteback/disk_free_history.rb | 4 +- lib/byteback/log.rb | 17 +++--- lib/byteback/restore.rb | 45 +++++++--------- lib/byteback/restore_file.rb | 70 +++++++++++------------- lib/byteback/util.rb | 9 ++-- test/tc_byteback_snapshot.rb | 2 +- test/tc_restore.rb | 22 ++++---- test/tc_restore_file.rb | 8 ++- test/ts_byteback.rb | 4 +- 18 files changed, 218 insertions(+), 249 deletions(-) create mode 100644 .rubocop.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..0532db5 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,9 @@ +AllCops: + TargetRubyVersion: 1.9 + Exclude: + - lib/trollop.rb + - lib/ffi-xattr.rb + - lib/ffi-xattr/**/* + - lib/sys/filesystem.rb + - misc/**/* + - debian/**/* diff --git a/bin/byteback-backup b/bin/byteback-backup index 8268353..713c127 100644 --- a/bin/byteback-backup +++ b/bin/byteback-backup @@ -16,8 +16,6 @@ require 'byteback/log' include Byteback::Util include Byteback::Log - - # # Run an ssh-command. # @@ -40,8 +38,6 @@ def ssh(*ssh_args) log_system(*args) end - - # # Call rsync to copy certain sources, returns exit status (see man rsync) # @@ -60,8 +56,7 @@ def rsync(*sources) # # Add on the I/O-timeout # - args += ['--timeout', @io_timeout.to_s ] unless ( @io_timeout.nil? ) - + args += ['--timeout', @io_timeout.to_s] unless @io_timeout.nil? args += ['--rsh', "ssh -o BatchMode=yes -x -a -i #{@ssh_key} -l #{@destination_user}"] args << '--verbose' if @verbose @@ -96,18 +91,16 @@ def rsync(*sources) log_system(*args) end - # # Run all the executable-scripts in the specified directory. # def run_parts(dir) if File.directory? dir - args = ['run-parts', dir ] - log_system(*args) + args = ['run-parts', dir] + log_system(*args) end end - ## ## Entry-point to our code. ## @@ -119,42 +112,41 @@ if __FILE__ == $PROGRAM_NAME banner "#{ME}: Back up this system to a byteback-enabled server\n " opt :destination, 'Backup destination (i.e. user@host:/path)', - :type => :string + type: :string opt :source, 'Source paths', - :type => :strings, - :default => ['/'] + type: :strings, + default: ['/'] opt :exclude, 'Paths to exclude', - :type => :strings, - :short => 'x' + type: :strings, + short: 'x' opt :verbose, 'Show debugging messages' opt :retry_number, 'Number of retries on error', - :type => :integer, - :default => 3 + type: :integer, + default: 3 opt :io_timeout, 'Number of seconds to allow I/O timeout for', - :type => :integer, - :default => 10800 + type: :integer, + default: 10_800 opt :retry_delay, 'Number of seconds between retries after an error', - :type => :integer, - :default => 300 + type: :integer, + default: 300 opt :ssh_key, 'SSH key filename', - :type => :string, - :default => '/etc/byteback/key', - :short => 'k' + type: :string, + default: '/etc/byteback/key', + short: 'k' opt :help, 'Show this message', - :short => 'h' + short: 'h' banner "\nAdditional excludes can be specified using /etc/byteback/rsync_filter, which is an rsync filter file. See the rsync man page for information on how this works.\n" end - # # Abort if we're already running. # @@ -169,28 +161,26 @@ if __FILE__ == $PROGRAM_NAME @retry_delay = opts[:retry_delay] @io_timeout = opts[:io_timeout] if opts[:io_timeout] - # Read the default destination if File.exist?('/etc/byteback/destination') @destination = File.read('/etc/byteback/destination').chomp end # Set the default SSH key - if File.exist?('/etc/byteback/key') - @ssh_key = '/etc/byteback/key' - end + @ssh_key = '/etc/byteback/key' if File.exist?('/etc/byteback/key') # If we have a local timeout-file then use that if File.exist?('/etc/byteback/io_timeout') @io_timeout = File.foreach('/etc/byteback/io_timeout').first.to_i end - # # Check our destination # if @destination =~ /^(?:(.+)@)?([^@:]+):(.+)?$/ - @destination_user, @destination_host, @destination_path = [Regexp.last_match(1), Regexp.last_match(2), Regexp.last_match(3)] + @destination_user = Regexp.last_match(1) + @destination_host = Regexp.last_match(2) + @destination_path = Regexp.last_match(3) else fatal('Destination must be a remote path, e.g. ssh@host.com:/store/backups') end @@ -215,28 +205,28 @@ if __FILE__ == $PROGRAM_NAME if @excludes.nil? PROBABLY_LOCAL = %w( - btrfs - ext2 - ext3 - ext4 - reiserfs - xfs - nilfs - jfs - reiser4 - zfs - rootfs - ) + btrfs + ext2 + ext3 + ext4 + reiserfs + xfs + nilfs + jfs + reiser4 + zfs + rootfs + ).freeze COMMON_JUNK = %w( - /swap.file - /tmp/ - /var/backups/localhost/ - /var/cache/apt/archives/ - /var/lib/php5/ - /var/tmp/ - /var/lib/mysql/ - ) + /swap.file + /tmp/ + /var/backups/localhost/ + /var/cache/apt/archives/ + /var/lib/php5/ + /var/tmp/ + /var/lib/mysql/ + ).freeze MOUNT_HEADINGS = %w( spec file vfstype mntops freq passno ).map(&:to_sym) @@ -261,27 +251,24 @@ if __FILE__ == $PROGRAM_NAME # fatal("Could not read ssh key #{@ssh_key}") unless File.readable?(@ssh_key) - # # Run our pre-backup actions, if any # - run_parts( "/etc/byteback/pre-backup.d/" ) + run_parts('/etc/byteback/pre-backup.d/') - # # Test ssh connection is good before we start - # + # fatal("Could not connect to #{@destination}") unless ssh('byteback-receive', '--ping', @verbose) == 0 - # # We treat exit statuses 0 and 24 as success; 0 is "Success"; 24 is "Partial # transfer due to vanished source files", which we treat as success otherwise # on some hosts the backup process never finishes. # - RSYNC_EXIT_STATUSES_TO_ACCEPT = [0, 24] - RSYNC_EXIT_STATUSES_TO_RETRY_ON = [10, 11, 20, 21, 22, 23, 30] + RSYNC_EXIT_STATUSES_TO_ACCEPT = [0, 24].freeze + RSYNC_EXIT_STATUSES_TO_RETRY_ON = [10, 11, 20, 21, 22, 23, 30].freeze # Run the file copy, retrying if necessary # @@ -314,11 +301,10 @@ if __FILE__ == $PROGRAM_NAME fatal('Backup could not be marked complete') unless ssh('byteback-receive', '--complete', @verbose) == 0 - # # Run our completion-actions, if any. # - run_parts( "/etc/byteback/post-backup.d/" ) + run_parts('/etc/byteback/post-backup.d/') info('Finished') end diff --git a/bin/byteback-prune b/bin/byteback-prune index a0cd0fb..3fef2c4 100755 --- a/bin/byteback-prune +++ b/bin/byteback-prune @@ -1,4 +1,5 @@ #!/usr/bin/ruby +# frozen_string_literal: true # # Program to free up space on the backup-storage volume, by removing # backups (whether by age, or importance). @@ -17,12 +18,12 @@ opts = Trollop.options do banner "Prune old backup directories to ensure there's enough space" opt :minpercent, 'Start prune when disk has less than this %age free', - :type => :integer, - :default => 5 + type: :integer, + default: 5 opt :maxpercent, 'Stop prune when disk has more than this %age free', - :type => :integer, - :default => 10 + type: :integer, + default: 10 opt :list, 'List backups in pruning order, no other action' @@ -31,8 +32,8 @@ opts = Trollop.options do opt :prune_force, 'Prune the next backup regardless' opt :order, "Order backups by 'age' or 'importance'", - :type => :string, - :default => 'importance' + type: :string, + default: 'importance' opt :verbose, 'Show debugging messages' end @@ -80,7 +81,7 @@ gradient_30m = @df_history.gradient(1800) # Check whether we should still be pruning # @free = @df_history.list.last.percent_free -PRUNING_FLAG = "#{ENV['HOME']}/.byteback.pruning" +PRUNING_FLAG = "#{ENV['HOME']}/.byteback.pruning".freeze if @do_prune_force info('Forcing prune') @@ -127,14 +128,13 @@ unless @do_prune_force # # Do not prune unless at least one snapshot is a week old # - last_week = Time.now - (7*86400) - unless snapshots.any?{|snapshot| last_week > snapshot.time} + last_week = Time.now - (7 * 86_400) + unless snapshots.any? { |snapshot| last_week > snapshot.time } warn('There are no snapshots older than a week. Not pruning.') exit 0 end end - exit 0 unless (@do_prune && File.exist?(PRUNING_FLAG)) || @do_prune_force diff --git a/bin/byteback-receive b/bin/byteback-receive index 1326bba..8cdb6ee 100755 --- a/bin/byteback-receive +++ b/bin/byteback-receive @@ -25,13 +25,13 @@ fatal("#{byteback_root} does not exist") unless File.directory?(byteback_root) # # Calling byteback-restore really needs rsync to restore the files. # -if (ARGV[0] == 'byteback-restore') +if ARGV[0] == 'byteback-restore' # # Ignore the first arg # ARGV.shift - args = ["rsync"] + args = ['rsync'] snapshot = nil verbose = false all = false @@ -39,25 +39,25 @@ if (ARGV[0] == 'byteback-restore') # # Mangle the arguments, and pull out any that are not-rsync compatible. # - while(arg = ARGV.shift) + while (arg = ARGV.shift) case arg - when "." - break - when /^-([^-]*v[^-]*|-verbose)$/ - verbose = true - args << arg - when "--snapshot" - snapshot = ARGV.shift - when "--all" - all = true - else - args << arg + when '.' + break + when /^-([^-]*v[^-]*|-verbose)$/ + verbose = true + args << arg + when '--snapshot' + snapshot = ARGV.shift + when '--all' + all = true + else + args << arg end end # Always exclude the current directory, because it can change the # ownership at the restorers end. - args << "--exclude=." + args << '--exclude=.' # # Search for certain files @@ -67,25 +67,25 @@ if (ARGV[0] == 'byteback-restore') restore = Byteback::Restore.new(byteback_root) restore.snapshot = snapshot if snapshot - restore.find(paths, :all => all) + restore.find(paths, all: all) Dir.chdir(byteback_host) - args << "." + args << '.' restore.results.each do |r| - args << File.join(".", r.snapshot, r.path) + args << File.join('.', r.snapshot, r.path) end if restore.results.empty? - STDERR.puts "** Sorry. There were no files matching:" - STDERR.puts "--> "+paths.join("\n--> ") + STDERR.puts '** Sorry. There were no files matching:' + STDERR.puts '--> ' + paths.join("\n--> ") exit 1 end - STDERR.puts "Restoring:" + STDERR.puts 'Restoring:' STDERR.puts restore.list - STDERR.puts(args.join(" ")) if verbose + STDERR.puts(args.join(' ')) if verbose exec(*args) @@ -94,11 +94,11 @@ elsif ARGV[0] == 'rsync' exec(*ARGV) elsif ARGV[0] == 'byteback-snapshot' - ARGV.concat(['--root', "#{byteback_root}"]) + ARGV.concat(['--root', byteback_root.to_s]) exec(*ARGV) -elsif ARGV[0] == "restore" - puts "** Your byteback package needs to be updated. Please update and try again." +elsif ARGV[0] == 'restore' + puts '** Your byteback package needs to be updated. Please update and try again.' exit(1) end @@ -108,15 +108,15 @@ opts = Trollop.options do opt :complete, 'Mark current backup as complete' opt :list, 'Show backed up files matching the given pattern' opt :all, 'Show all stored versions of a file' - opt :snapshot, 'Show backed up files in a certain snapshot.', :default => '*' + opt :snapshot, 'Show backed up files in a certain snapshot.', default: '*' opt :verbose, 'Print diagnostics' end # # Make sure we don't get crazy option combinations. # -n_modes = opts.keys.inject(0) do |s,m| - [:ping, :complete, :list].include?(m) ? s += 1 : s +n_modes = opts.keys.inject(0) do |s, m| + [:ping, :complete, :list].include?(m) ? s += 1 : s end error('Please only choose one mode') unless n_modes == 1 @@ -129,11 +129,11 @@ elsif opts[:list] restore = Byteback::Restore.new(byteback_root) restore.snapshot = opts[:snapshot] - restore.find(args, :all => opts[:all], :verbose => opts[:verbose]) + restore.find(args, all: opts[:all], verbose: opts[:verbose]) if restore.results.empty? - puts "** Sorry. There were no files matching:" - puts "--> "+args.join("\n--> ") + puts '** Sorry. There were no files matching:' + puts '--> ' + args.join("\n--> ") else puts restore.list end diff --git a/bin/byteback-restore b/bin/byteback-restore index 2cd54c5..ef9e40b 100755 --- a/bin/byteback-restore +++ b/bin/byteback-restore @@ -31,13 +31,13 @@ def ssh(*ssh_args) ] + ssh_args.map { |a| a ? a : '' } - puts args.join(" " ) if @verbose + puts args.join(' ') if @verbose system(*args) end def list_files(pattern, snapshot, all) args = ['byteback-receive', '--snapshot', snapshot, '--list'] - args << "--all" if all + args << '--all' if all args << @verbose if @verbose args += Byteback::Restore.encode_args(pattern) ssh(*args) @@ -60,28 +60,28 @@ def restore_files(paths, snapshot, all) # # Add on the I/O-timeout # - args += ['--timeout', @io_timeout.to_s ] unless ( @io_timeout.nil? ) + args += ['--timeout', @io_timeout.to_s] unless @io_timeout.nil? args += ['--rsh', "ssh -o BatchMode=yes -x -a -i #{@ssh_key} -l #{@destination_user}"] args << '--verbose' if @verbose - args += ['--rsync-path', "byteback-restore --fake-super --snapshot #{snapshot}" + (all ? " --all" : "")] + args += ['--rsync-path', "byteback-restore --fake-super --snapshot #{snapshot}" + (all ? ' --all' : '')] # # To add extra rsync flags, a file can be used. This can have flags all on one line, or one per line. # - if File.exists?("/etc/byteback/rsync_flags") - args += File.readlines("/etc/byteback/rsync_flags").map(&:chomp) + if File.exist?('/etc/byteback/rsync_flags') + args += File.readlines('/etc/byteback/rsync_flags').map(&:chomp) end dst = "#{@destination_user}@#{@destination_host}:" paths.each do |path| path = Byteback::Restore.encode_args(path).first - args << File.join(dst,path) - dst = ":" + args << File.join(dst, path) + dst = ':' end - args << "." - puts args.join(" ") if @verbose + args << '.' + puts args.join(' ') if @verbose system(*args) end @@ -98,36 +98,35 @@ if __FILE__ == $PROGRAM_NAME opts = Trollop.options do banner "#{ME}: Restore a file to this system from a byteback-enabled server\n " - opt :list, "List or find files on the backup server. This is the default mode." + opt :list, 'List or find files on the backup server. This is the default mode.' - opt :restore, "Restore files from the backup server." + opt :restore, 'Restore files from the backup server.' - opt :snapshot, "The specific snapshot to use", - :type => :string, :default => "*" + opt :snapshot, 'The specific snapshot to use', + type: :string, default: '*' opt :destination, 'Backup destination (i.e. user@host:/path)', - :type => :string + type: :string opt :io_timeout, 'Number of seconds to allow I/O to timeout', - :type => :integer, - :default => 300 + type: :integer, + default: 300 opt :ssh_key, 'SSH key filename', - :type => :string, - :default => '/etc/byteback/key', - :short => 'k' + type: :string, + default: '/etc/byteback/key', + short: 'k' opt :all, 'List or restore all versrions of each file', - :short => 'a' + short: 'a' opt :verbose, 'Show more output' - end # # Make sure we know what we're doing. # - fatal("Please choose either --list or --restore") if opts[:list] and opts[:restore] + fatal('Please choose either --list or --restore') if opts[:list] && opts[:restore] @verbose = opts[:verbose] ? '--verbose' : nil @io_timeout = opts[:io_timeout] if opts[:io_timeout] @@ -138,9 +137,7 @@ if __FILE__ == $PROGRAM_NAME end # Set the default SSH key - if File.exist?('/etc/byteback/key') - @ssh_key = '/etc/byteback/key' - end + @ssh_key = '/etc/byteback/key' if File.exist?('/etc/byteback/key') # # Allow the command-line to override them. @@ -157,7 +154,9 @@ if __FILE__ == $PROGRAM_NAME # Check our destination is well-formed # if @destination =~ /^(?:(.+)@)?([^@:]+):(.+)?$/ - @destination_user, @destination_host, @destination_path = [Regexp.last_match(1), Regexp.last_match(2), Regexp.last_match(3)] + @destination_user = Regexp.last_match(1) + @destination_host = Regexp.last_match(2) + @destination_path = Regexp.last_match(3) else fatal('Destination must be a remote path, e.g. ssh@host.com:/store/backups') end @@ -171,18 +170,16 @@ if __FILE__ == $PROGRAM_NAME # If the user didn't specify a file then we're not restoring anything, # and we should abort. # - if ARGV.empty? - fatal('You must specify a file to search/restore') - end + fatal('You must specify a file to search/restore') if ARGV.empty? if opts[:restore] # # Restore a file # - restore_files(ARGV.collect{|a| File.expand_path(a)}, opts[:snapshot], opts[:all]) + restore_files(ARGV.collect { |a| File.expand_path(a) }, opts[:snapshot], opts[:all]) exit(0) end - list_files(ARGV.collect{|a| File.expand_path(a)}, opts[:snapshot], opts[:all]) + list_files(ARGV.collect { |a| File.expand_path(a) }, opts[:snapshot], opts[:all]) exit(0) end diff --git a/bin/byteback-setup-client b/bin/byteback-setup-client index 988d4b8..c81ca1f 100755 --- a/bin/byteback-setup-client +++ b/bin/byteback-setup-client @@ -23,17 +23,17 @@ end opts = Trollop.options do opt :hostname, 'Set host name for backups', - :type => :string + type: :string opt :destination, 'Backup destination (i.e. user@host:/path)', - :type => :string + type: :string end @destination = opts[:destination] @hostname = opts[:hostname] _dummy, @destination_user, @destination_host, colon, @destination_path = - /^(.*)?(?:@)([^:]+)(:)(.*)?$/.match(@destination).to_a + /^(.*)?(?:@)([^:]+)(:)(.*)?$/.match(@destination).to_a @destination_user ||= 'byteback' @destination_path ||= '' diff --git a/bin/byteback-setup-client-receive b/bin/byteback-setup-client-receive index 528ccc9..0afc595 100755 --- a/bin/byteback-setup-client-receive +++ b/bin/byteback-setup-client-receive @@ -44,7 +44,7 @@ if File.exist?('.ssh/authorized_keys') && else File.open('.ssh/authorized_keys', 'a+') do |fh| - fh.print <<-LINE.gsub(/\n/, '') + "\n" + fh.print <<-LINE.delete("\n") + "\n" command="byteback-receive", from="#{@client_ip}", environment="BYTEBACK_HOST=#{@hostname}" diff --git a/bin/byteback-snapshot b/bin/byteback-snapshot index 18a7a67..c7cb920 100755 --- a/bin/byteback-snapshot +++ b/bin/byteback-snapshot @@ -13,7 +13,7 @@ include Byteback::Log opts = Trollop.options do opt :root, 'Backups directory (must be a btrfs subvolume)', - :type => :string + type: :string opt :snapshot, '(ignored for compatibility)' @@ -23,7 +23,7 @@ end @root = opts[:root] @verbose = opts[:verbose] -fatal('--root not readable') unless File.directory?("#{@root}") +fatal('--root not readable') unless File.directory?(@root.to_s) @backups = BackupDirectory.new(@root) snapshots = @backups.snapshots diff --git a/lib/byteback/backup_directory.rb b/lib/byteback/backup_directory.rb index a39cf84..8c0521b 100644 --- a/lib/byteback/backup_directory.rb +++ b/lib/byteback/backup_directory.rb @@ -3,7 +3,6 @@ require 'byteback/utils' module Byteback # Represents a particular timestamped backup directory class Snapshot - include Byteback::Util class << self @@ -12,10 +11,10 @@ module Byteback # Order backups by their closeness to defined backup times, which are # listed in a set order (i.e. today's backup is more important than yesterday's). # - BACKUP_IMPORTANCE = [1, 2, 7, 14, 21, 28, 56, 112] + BACKUP_IMPORTANCE = [1, 2, 7, 14, 21, 28, 56, 112].freeze def sort_by_importance(snapshots_unsorted, now = Time.now) - return snapshots_unsorted if snapshots_unsorted.size < 1 + return snapshots_unsorted if snapshots_unsorted.size < 1 # # Keep the last 7 days backups @@ -78,11 +77,10 @@ module Byteback # host was more recent, i.e. we've reached the oldest, and are # bouncing back again. # - if last_nearest[host].nil? || last_nearest[host].time > nearest.time - last_nearest[host] = nearest - snapshots_by_host[host] -= [nearest] - snapshots_sorted << nearest - end + next unless last_nearest[host].nil? || last_nearest[host].time > nearest.time + last_nearest[host] = nearest + snapshots_by_host[host] -= [nearest] + snapshots_sorted << nearest end end diff --git a/lib/byteback/disk_free_history.rb b/lib/byteback/disk_free_history.rb index 5f45f14..db7f45a 100644 --- a/lib/byteback/disk_free_history.rb +++ b/lib/byteback/disk_free_history.rb @@ -67,8 +67,8 @@ module Byteback list.reverse.each do |reading| if later_reading difference = - value_from_reading.call(reading) - - value_from_reading.call(later_reading) + yield reading - + yield later_reading total += difference end readings += 1 diff --git a/lib/byteback/log.rb b/lib/byteback/log.rb index 6753ca8..83679e6 100644 --- a/lib/byteback/log.rb +++ b/lib/byteback/log.rb @@ -2,7 +2,6 @@ require 'logger' require 'syslog' module Byteback - # # Translates Ruby's Logger calls to similar calls to Syslog # (implemented in Ruby 2.0 as Syslog::Logger). @@ -18,15 +17,15 @@ module Byteback def info(m) log_nopc(Syslog::LOG_INFO, m) end - + def warn(m) log_nopc(Syslog::LOG_WARNING, m) end - + def error(m) log_nopc(Syslog::LOG_ERR, m) end - + # # syslog(3) says: # @@ -52,7 +51,6 @@ module Byteback module Log @@me = File.expand_path($PROGRAM_NAME).split('/').last - # # If we're running interactively then we have simple logging. # @@ -80,24 +78,23 @@ module Byteback @@logger = SyslogProxy end - def debug(*a) @@logger.__send__(:debug, *a) end - + def info(*a) @@logger.__send__(:info, *a) end - + def warn(*a) @@logger.__send__(:warn, *a) end - + def fatal(*a) @@logger.__send__(:fatal, *a) exit 1 end - + def error(*a) @@logger.__send__(:error, *a) end diff --git a/lib/byteback/restore.rb b/lib/byteback/restore.rb index 7055be3..259e108 100644 --- a/lib/byteback/restore.rb +++ b/lib/byteback/restore.rb @@ -2,14 +2,12 @@ require 'byteback/restore_file' module Byteback - class Restore - def self.find(byteback_root, snapshot, paths) x = Byteback::Restore.new(byteback_root) x.snapshot = snapshot x.find(paths) - return x + x end # @@ -19,7 +17,7 @@ module Byteback # Returns an array of encoded strings. # def self.encode_args(args) - [args].flatten.collect{|s| [s].pack("M").gsub(" ","=20").gsub("=\n","")} + [args].flatten.collect { |s| [s].pack('M').gsub(' ', '=20').gsub("=\n", '') } end # @@ -29,17 +27,17 @@ module Byteback # Returns an array of decoded strings. # def self.decode_args(args) - [args].flatten.collect{|s| (s + "=\n").unpack("M")}.flatten + [args].flatten.collect { |s| (s + "=\n").unpack('M') }.flatten end def initialize(byteback_root) - # + # # We use expand_path here to make sure we have a full path, with no # trailing slash. # @byteback_root = File.expand_path(byteback_root) - @now = Time.now - @snapshot = "*" + @now = Time.now + @snapshot = '*' @results = [] end @@ -51,16 +49,14 @@ module Byteback end end - def results - @results - end + attr_reader :results def find(paths, opts = {}) results = [] # # Make sure we've an array, and that we get rid of any ".." nonsense. # - paths = [paths].flatten.collect{|p| File.expand_path(p, "/")} + paths = [paths].flatten.collect { |p| File.expand_path(p, '/') } seen = [] @results = paths.collect do |path| @@ -72,19 +68,19 @@ module Byteback # # If we want an unpruned list, return it now. # - if opts == true or (opts.is_a?(Hash) and opts[:verbose]) - @results = @results.sort{|a,b| [a.path, a.snapshot_time] <=> [b.path, b.snapshot_time]} + if opts == true || (opts.is_a?(Hash) && opts[:verbose]) + @results = @results.sort { |a, b| [a.path, a.snapshot_time] <=> [b.path, b.snapshot_time] } return @results end - @results = @results.sort{|a,b| [a.path, b.snapshot_time] <=> [b.path, a.snapshot_time]} + @results = @results.sort { |a, b| [a.path, b.snapshot_time] <=> [b.path, a.snapshot_time] } pruned_results = [] @results.each do |r| - if (opts.is_a?(Hash) and opts[:all]) + if opts.is_a?(Hash) && opts[:all] pruned_results << r unless pruned_results.include?(r) else - pruned_results << r unless pruned_results.any?{|pr| pr.path == r.path} + pruned_results << r unless pruned_results.any? { |pr| pr.path == r.path } end end @@ -95,14 +91,12 @@ module Byteback heading = %w(snapshot modestring size uid gid mtime path) listings = [heading] @results.sort.each do |r| - listing = heading.collect{|m| r.__send__(m.to_sym).to_s } - if r.symlink? - listing[-1] << " -> "+r.readlink - end + listing = heading.collect { |m| r.__send__(m.to_sym).to_s } + listing[-1] << ' -> ' + r.readlink if r.symlink? listings << listing end - field_sizes = [0]*heading.length + field_sizes = [0] * heading.length listings.each do |fields| fields.each_with_index do |field, i| @@ -110,9 +104,9 @@ module Byteback end end - fmt = field_sizes.collect{|i| "%-#{i}.#{i}s"}.join(" ") + fmt = field_sizes.collect { |i| "%-#{i}.#{i}s" }.join(' ') - bar = "-"*field_sizes.inject(field_sizes.length){|m,s| m+=s} + bar = '-' * field_sizes.inject(field_sizes.length) { |m, s| m += s } output = [] listings.each do |fields| @@ -123,8 +117,7 @@ module Byteback end end - return output.join("\n") + output.join("\n") end - end end diff --git a/lib/byteback/restore_file.rb b/lib/byteback/restore_file.rb index daceb83..2015eb0 100644 --- a/lib/byteback/restore_file.rb +++ b/lib/byteback/restore_file.rb @@ -35,7 +35,7 @@ module Byteback include Comparable - def initialize(full_path, byteback_root=".", now = Time.now) + def initialize(full_path, byteback_root = '.', now = Time.now) @full_path = full_path @byteback_root = byteback_root @now = now @@ -43,7 +43,7 @@ module Byteback # # The snapshot is the first directory after the byteback_root # - @snapshot = full_path.sub(%r(^#{Regexp.escape @byteback_root}),'').split("/")[1] + @snapshot = full_path.sub(/^#{Regexp.escape @byteback_root}/, '').split('/')[1] # # If we can parse the time, use it, otherwise assume "now". @@ -57,13 +57,13 @@ module Byteback # # Restore path # - @path = full_path.sub(%r(^#{Regexp.escape @byteback_root}/#{Regexp.escape @snapshot}),'') + @path = full_path.sub(%r{^#{Regexp.escape @byteback_root}/#{Regexp.escape @snapshot}}, '') @stat = @mode = @dev_major = @dev_minor = @uid = @gid = nil end def <=>(other) - [self.path, self.mtime.to_i, self.size] <=> [other.path, other.mtime.to_i, other.size] + [path, mtime.to_i, size] <=> [other.path, other.mtime.to_i, other.size] end def stat @@ -71,36 +71,30 @@ module Byteback @stat end - def snapshot - @snapshot - end + attr_reader :snapshot - def snapshot_time - @snapshot_time - end + attr_reader :snapshot_time - def path - @path - end + attr_reader :path def to_s - sprintf("%10s %i %4i %4i %s %s %s", self.modestring, self.size, self.uid, self.gid, self.mtime.strftime("%b %2d %H:%M"), @snapshot, @path) + sprintf('%10s %i %4i %4i %s %s %s', modestring, size, uid, gid, mtime.strftime('%b %2d %H:%M'), @snapshot, @path) end def read_rsync_xattrs - xattr = Xattr.new(@full_path, :no_follow => false) - rsync_xattrs = xattr["user.rsync.%stat"] + xattr = Xattr.new(@full_path, no_follow: false) + rsync_xattrs = xattr['user.rsync.%stat'] if rsync_xattrs - @mode, @dev_major, @dev_minor, @uid, @gid = rsync_xattrs.scanf("%o %d,%d %d:%d") - raise ArgumentError, "Corrupt rsync stat xattr found for #{@full_path} (#{rsync_xattrs})" unless [@mode, @dev_major, @dev_minor, @uid, @gid].all?{|i| i.is_a?(Integer)} + @mode, @dev_major, @dev_minor, @uid, @gid = rsync_xattrs.scanf('%o %d,%d %d:%d') + fail ArgumentError, "Corrupt rsync stat xattr found for #{@full_path} (#{rsync_xattrs})" unless [@mode, @dev_major, @dev_minor, @uid, @gid].all? { |i| i.is_a?(Integer) } else - warn "No rsync stat xattr found for #{@full_path}" - @mode, @dev_major, @dev_minor, @uid, @gid = %w(mode dev_major dev_minor uid gid).collect{|m| self.stat.__send__(m.to_sym)} + warn "No rsync stat xattr found for #{@full_path}" + @mode, @dev_major, @dev_minor, @uid, @gid = %w(mode dev_major dev_minor uid gid).collect { |m| stat.__send__(m.to_sym) } end end def mode - return self.stat.mode if self.stat.symlink? + return stat.mode if stat.symlink? read_rsync_xattrs unless @mode @mode end @@ -130,22 +124,22 @@ module Byteback # def ftypelet if file? - "-" + '-' elsif directory? - "d" + 'd' elsif blockdev? - "b" + 'b' elsif chardev? - "c" + 'c' elsif symlink? - "l" + 'l' elsif fifo? - "p" + 'p' elsif socket? - "s" + 's' else - "?" - end + '?' + end end # @@ -153,7 +147,7 @@ module Byteback # This has mostly been copied from strmode from filemode.h in coreutils. # def modestring - str = "" + str = '' str << ftypelet str << ((mode & S_IRUSR == S_IRUSR) ? 'r' : '-') str << ((mode & S_IWUSR == S_IWUSR) ? 'w' : '-') @@ -170,7 +164,7 @@ module Byteback str << ((mode & S_ISVTX == S_ISVTX) ? ((mode & S_IXOTH == S_IXOTH) ? 't' : 'T') : ((mode & S_IXOTH == S_IXOTH) ? 'x' : '-')) - return str + str end def socket? @@ -178,7 +172,7 @@ module Byteback end def symlink? - self.stat.symlink? || (mode & S_IFMT) == S_IFLNK + stat.symlink? || (mode & S_IFMT) == S_IFLNK end def file? @@ -202,17 +196,17 @@ module Byteback end def readlink - if self.stat.symlink? + if stat.symlink? File.readlink(@full_path) else File.read(@full_path).chomp end end - def method_missing(m, *args, &blk) - return self.stat.__send__(m) if self.stat.respond_to?(m) + def method_missing(m, *_args, &_blk) + return stat.__send__(m) if stat.respond_to?(m) - raise NoMethodError, m - end + fail NoMethodError, m + end end end diff --git a/lib/byteback/util.rb b/lib/byteback/util.rb index ebf5ca5..7678d81 100644 --- a/lib/byteback/util.rb +++ b/lib/byteback/util.rb @@ -15,7 +15,7 @@ module Byteback if File.exist? @@lockfile # check the lockfile is sane exist_pid = File.read(@@lockfile).to_i - if exist_pid > 1 && exist_pid < (File.read('/proc/sys/kernel/pid_max').to_i) + if exist_pid > 1 && exist_pid < File.read('/proc/sys/kernel/pid_max').to_i begin Process.getpgid(exist_pid) # if no exception, process is running, abort @@ -40,7 +40,7 @@ module Byteback lockfile.puts Process.pid end rescue => _ex - fatal("Failed to open lockfile - are you running as root?") + fatal('Failed to open lockfile - are you running as root?') end end @@ -51,7 +51,7 @@ module Byteback end def log_system(*args) - debug('system: ' + args.map { |a| / /.match(a) ? "\"#{a}\"" : a }.join(' ')) + debug('system: ' + args.map { |a| / / =~ a ? "\"#{a}\"" : a }.join(' ')) rd, wr = IO.pipe pid = fork if pid.nil? # child @@ -71,8 +71,7 @@ module Byteback %w(/bin/btrfs /sbin/btrfs).each do |path| return path if File.exist?(path) end - raise Errno::ENOENT, 'btrfs' + fail Errno::ENOENT, 'btrfs' end - end end diff --git a/test/tc_byteback_snapshot.rb b/test/tc_byteback_snapshot.rb index 71f8c39..0200369 100644 --- a/test/tc_byteback_snapshot.rb +++ b/test/tc_byteback_snapshot.rb @@ -49,7 +49,7 @@ class SnapshotTest < Test::Unit::TestCase targets = ((0..6).to_a + [7,14,21,28].to_a.collect{|i| i + now.wday} + - [2*28 + mod_28]).select{|t| t < day}.first(limit).reverse + [2*28 + mod_28]).find{|t| t < day}(limit).reverse assert_equal(targets - offsets, [], "Failed after day #{day} (#{now.wday}) for a limit of #{limit} backups") diff --git a/test/tc_restore.rb b/test/tc_restore.rb index 03e98ad..57f7fb9 100644 --- a/test/tc_restore.rb +++ b/test/tc_restore.rb @@ -5,7 +5,6 @@ require 'time' require 'fileutils' class RestoreTest < Test::Unit::TestCase - def setup @byteback_root = Dir.mktmpdir end @@ -19,7 +18,7 @@ class RestoreTest < Test::Unit::TestCase end def test_no_barf_on_non_timestamp_snapshot_name - create_snapshot_and_check_results("saved-hacked-do-not-delete") + create_snapshot_and_check_results('saved-hacked-do-not-delete') end def create_snapshot_and_check_results(snapshot) @@ -31,20 +30,19 @@ class RestoreTest < Test::Unit::TestCase FileUtils.mkdir_p(File.join(@byteback_root, snapshot, File.dirname(f))) FileUtils.touch(File.join(@byteback_root, snapshot, f)) system("setfattr --name user.rsync.%stat -v \"41755 12,34 56:78\" #{File.join(@byteback_root, snapshot, f)}") - assert_equal(0, $?.exitstatus) + assert_equal(0, $CHILD_STATUS.exitstatus) end - r = Byteback::Restore.find(@byteback_root, "*", "/srv/foo.com/public/htdocs/*.html") - assert(r.results.all?{|f| f.path =~ %r{/srv/foo.com/public/htdocs/.*.html}}, "Results returned did not match requested pattern") - assert(r.results.all?{|f| f.snapshot == snapshot}, "Results returned were not from the correct snapshot") + r = Byteback::Restore.find(@byteback_root, '*', '/srv/foo.com/public/htdocs/*.html') + assert(r.results.all? { |f| f.path =~ %r{/srv/foo.com/public/htdocs/.*.html} }, 'Results returned did not match requested pattern') + assert(r.results.all? { |f| f.snapshot == snapshot }, 'Results returned were not from the correct snapshot') # Now check that we're getting the correct stuff from the rsync attr. f = r.results.first - assert_equal(041755, f.mode, "Incorrect mode returned") - assert_equal(12, f.dev_major, "Incorrect dev_major returned") - assert_equal(34, f.dev_minor, "Incorrect dev_minor returned") - assert_equal(56, f.uid, "Incorrect UID returned") - assert_equal(78, f.gid, "Inocrrect GID returned") + assert_equal(041755, f.mode, 'Incorrect mode returned') + assert_equal(12, f.dev_major, 'Incorrect dev_major returned') + assert_equal(34, f.dev_minor, 'Incorrect dev_minor returned') + assert_equal(56, f.uid, 'Incorrect UID returned') + assert_equal(78, f.gid, 'Inocrrect GID returned') end - end diff --git a/test/tc_restore_file.rb b/test/tc_restore_file.rb index 8284275..9c12635 100644 --- a/test/tc_restore_file.rb +++ b/test/tc_restore_file.rb @@ -4,12 +4,11 @@ require 'tempfile' require 'tmpdir' class BytebackFileTest < Test::Unit::TestCase - def setup @byteback_root = Dir.mktmpdir now = Time.now @snapshot = Time.local(now.year, now.month, now.day, now.hour, now.min) - @snapshot_path = File.join(@byteback_root, @snapshot.strftime("%Y-%m-%dT%H:%M%z")) + @snapshot_path = File.join(@byteback_root, @snapshot.strftime('%Y-%m-%dT%H:%M%z')) FileUtils.mkdir_p(@snapshot_path) end @@ -18,7 +17,7 @@ class BytebackFileTest < Test::Unit::TestCase end def test_general - f = Tempfile.new("restore-file-", @snapshot_path) + f = Tempfile.new('restore-file-', @snapshot_path) system("setfattr --name user.rsync.%stat -v \"41755 12,34 56:78\" #{f.path}") b = Byteback::RestoreFile.new(f.path, @byteback_root) assert_equal(041755, b.mode) @@ -26,9 +25,8 @@ class BytebackFileTest < Test::Unit::TestCase assert_equal(34, b.dev_minor) assert_equal(56, b.uid) assert_equal(78, b.gid) - assert_equal("drwxr-xr-t", b.modestring) + assert_equal('drwxr-xr-t', b.modestring) assert_equal(@snapshot, b.snapshot_time) assert_kind_of(Time, f.mtime) end - end diff --git a/test/ts_byteback.rb b/test/ts_byteback.rb index ccee796..98ef121 100644 --- a/test/ts_byteback.rb +++ b/test/ts_byteback.rb @@ -1,6 +1,6 @@ -$: << File.dirname(__FILE__) -$: << File.dirname(__FILE__)+"/../lib" +$LOAD_PATH << File.dirname(__FILE__) +$LOAD_PATH << File.dirname(__FILE__) + '/../lib' require 'tc_restore.rb' require 'tc_restore_file.rb' -- cgit v1.2.1