rsyncbackup 1.0.2 → 2.0.0
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.
- checksums.yaml +4 -4
- data/Guardfile +12 -0
- data/bin/rsyncbackup +5 -12
- data/features/backup.feature +2 -1
- data/features/rsyncbackup.feature +1 -2
- data/features/spaced_file_names.feature +2 -1
- data/lib/rsyncbackup.rb +39 -53
- data/lib/rsyncbackup/utilities.rb +23 -14
- data/lib/rsyncbackup/version.rb +3 -1
- data/rsyncbackup.gemspec +8 -3
- data/spec/rsyncbackup_spec.rb +36 -56
- data/spec/spec_helper.rb +3 -1
- data/spec/utilities_spec.rb +46 -33
- metadata +52 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10705744d2cfcaeb5a89c60a0d772bd951ebd050
|
4
|
+
data.tar.gz: 8493e1056587694f144b1b98c388adb979a9d3e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa458bbd4495d0f0a6463eedd7f5a0d1787def95da6eb0e3e88f2a3a8aeeb42bc4853273589765ed37945f4f9b899da6ee8f3b0b921a42af6f2518270736d2f9
|
7
|
+
data.tar.gz: f37280db214a6999552deb96472785537fc93dea5665d2153f89f6bbddb2caf39ac659c8417ff61cb263a33691d5ad6a3294bf11ce3fb8d83db4be2d079590e6
|
data/Guardfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
guard 'cucumber', :cli => '--color --format pretty' do
|
2
|
+
watch(%r{^features/.+\.feature$})
|
3
|
+
watch(%r{^features/support/.+$}) { 'features' }
|
4
|
+
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
|
5
|
+
end
|
6
|
+
|
7
|
+
guard :rspec, :cli => "--color --format documentation --fail-fast" do
|
8
|
+
watch(%r{^spec/.+_spec\.rb$})
|
9
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
10
|
+
watch('spec/spec_helper.rb') { "spec" }
|
11
|
+
end
|
12
|
+
|
data/bin/rsyncbackup
CHANGED
@@ -8,15 +8,8 @@ class App
|
|
8
8
|
include Methadone::Main
|
9
9
|
include Methadone::CLILogging
|
10
10
|
|
11
|
-
if logger.info?
|
12
|
-
logger.level=Logger::WARN
|
13
|
-
end
|
14
|
-
|
15
|
-
|
16
11
|
main do |source, target|
|
17
|
-
|
18
|
-
options[:target] = target
|
19
|
-
syncer = Rsyncbackup.new(options)
|
12
|
+
syncer = Rsyncbackup.new(source, target, options)
|
20
13
|
syncer.run
|
21
14
|
syncer.finalize
|
22
15
|
end
|
@@ -24,16 +17,16 @@ class App
|
|
24
17
|
description "Yet another rsync backup script, this time in ruby"
|
25
18
|
|
26
19
|
on("-e FILE","--exclusions","Exclusions file")
|
27
|
-
on("-d","--
|
28
|
-
on("
|
29
|
-
|
20
|
+
on("-d","--dry-run","Mark this as a dry run (or not)")
|
21
|
+
on("--verbose","Be chatty")
|
22
|
+
on("--debug","show debug stuff")
|
30
23
|
|
31
24
|
arg :source, "Source to backup from"
|
32
25
|
arg :target, "Target backup directory"
|
33
26
|
|
34
27
|
version Rsyncbackup::VERSION
|
35
28
|
|
36
|
-
use_log_level_option
|
29
|
+
# use_log_level_option
|
37
30
|
|
38
31
|
go!
|
39
32
|
end
|
data/features/backup.feature
CHANGED
@@ -2,6 +2,7 @@ Feature: Perform Backups
|
|
2
2
|
In order to ensure files are correctly backed up
|
3
3
|
I will need to run the backup script
|
4
4
|
|
5
|
+
@announce
|
5
6
|
Scenario: Run a backup from source to target
|
6
7
|
Given a directory named "source"
|
7
8
|
Given a file named "source/one" with:
|
@@ -13,7 +14,7 @@ Feature: Perform Backups
|
|
13
14
|
xxxx
|
14
15
|
"""
|
15
16
|
Given a directory named "target"
|
16
|
-
When I successfully run `rsyncbackup --
|
17
|
+
When I successfully run `rsyncbackup --debug source target`
|
17
18
|
Then a file named "target/.lastfull" should exist
|
18
19
|
And a directory named "target/.incomplete" should not exist
|
19
20
|
|
@@ -9,10 +9,9 @@ Feature: help lists all options and arguments
|
|
9
9
|
And the banner should be present
|
10
10
|
And the banner should document that this app takes options
|
11
11
|
And the following options should be documented:
|
12
|
-
|--
|
12
|
+
|--dry-run |
|
13
13
|
|--exclusions|
|
14
14
|
|--help|
|
15
|
-
|--log-level|
|
16
15
|
|--verbose|
|
17
16
|
|--version|
|
18
17
|
And the banner should document that this app's arguments are:
|
@@ -1,6 +1,7 @@
|
|
1
1
|
Feature: File names with spaces
|
2
2
|
In order to ensure file names with spaces are correctly handled
|
3
3
|
|
4
|
+
@announce
|
4
5
|
Scenario: Use spaces in file names
|
5
6
|
Given a directory named "this source"
|
6
7
|
Given a file named "this source/one" with:
|
@@ -12,7 +13,7 @@ Feature: File names with spaces
|
|
12
13
|
xxxx
|
13
14
|
"""
|
14
15
|
Given a directory named "this target"
|
15
|
-
When I successfully run `rsyncbackup --
|
16
|
+
When I successfully run `rsyncbackup --debug 'this source' 'this target'`
|
16
17
|
Then a file named "this target/.lastfull" should exist
|
17
18
|
And a directory named "this target/.incomplete" should not exist
|
18
19
|
|
data/lib/rsyncbackup.rb
CHANGED
@@ -6,78 +6,64 @@ require 'methadone'
|
|
6
6
|
class Rsyncbackup
|
7
7
|
include Methadone::CLILogging
|
8
8
|
|
9
|
-
attr_accessor :options
|
9
|
+
attr_accessor :source, :target, :options
|
10
|
+
|
11
|
+
def initialize(source, target, opts={})
|
12
|
+
logger.level = Logger::WARN
|
13
|
+
logger.level = Logger::INFO if opts[:verbose]
|
14
|
+
logger.error_level = Logger::DEBUG if opts[:debug]
|
15
|
+
|
16
|
+
raise "Unknown target: #{target}" unless File.exist?(target) or opts[:dry_run]
|
17
|
+
|
18
|
+
@source = strip_trailing_separator_if_any(source,true)
|
19
|
+
@target = strip_trailing_separator_if_any(target)
|
10
20
|
|
11
|
-
def initialize(opts={})
|
12
21
|
@options = {
|
13
|
-
dry_run
|
14
|
-
exclusions
|
15
|
-
archive
|
16
|
-
one_file_system
|
17
|
-
hard_links
|
18
|
-
human_readable
|
19
|
-
inplace
|
20
|
-
numeric_ids
|
21
|
-
delete
|
22
|
-
|
22
|
+
:dry_run => false,
|
23
|
+
:exclusions => DEFAULT_EXCLUSIONS,
|
24
|
+
:archive => true,
|
25
|
+
:one_file_system => true,
|
26
|
+
:hard_links => true,
|
27
|
+
:human_readable => true,
|
28
|
+
:inplace => true,
|
29
|
+
:numeric_ids => true,
|
30
|
+
:delete => true,
|
31
|
+
:link_dest => last_full_backup,
|
32
|
+
:rsync_cmd => rsync_executable
|
23
33
|
}.merge(opts)
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
options[:link_dest] ||= last_full_backup
|
35
|
+
@incomplete = File.join(target,DEFAULT_INCOMPLETE_DIR_NAME)
|
36
|
+
@complete = File.join(target,backup_dir_name)
|
28
37
|
|
29
|
-
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
debug "#{caller[0]}options: #{options.inspect}"
|
38
|
+
|
39
|
+
debug "#{caller(0,1).first} @source: #{@source}, @target: #{@target}, @options: #{@options.inspect}"
|
34
40
|
|
35
41
|
end
|
36
42
|
|
37
43
|
|
38
44
|
def run
|
39
|
-
cmd = build_command
|
45
|
+
@cmd = build_command
|
40
46
|
|
41
|
-
info "
|
42
|
-
|
43
|
-
|
44
|
-
end
|
47
|
+
info "Backing up #{@source} to #{@target} on #{Time.now}"
|
48
|
+
info "Rsync command: #{@cmd}"
|
49
|
+
info "Dry run only" if options[:dry_run]
|
45
50
|
|
46
51
|
if File.exist? temp_target_path
|
47
52
|
warn "Preexisting temporary target. Moving it aside."
|
48
|
-
File.rename temp_target_path, "#{temp_target_path}-#{
|
53
|
+
File.rename temp_target_path, "#{temp_target_path}-#{Time.now.to_i}"
|
49
54
|
end
|
50
55
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
until stderr.eof?
|
58
|
-
errors = stderr.gets
|
59
|
-
end
|
60
|
-
result = wait.value
|
61
|
-
raise "Command failed. Return code: #{result}\n#{errors}" unless result == 0
|
62
|
-
end
|
63
|
-
|
56
|
+
# the dry run option will be passed through to the rsync command,
|
57
|
+
# so we still do want to run it.
|
58
|
+
result = Open3.capture3(@cmd)
|
59
|
+
raise "Rsync Error: exit status: #{s.exit_code}: error: #{e}" unless result[2].success?
|
60
|
+
result
|
64
61
|
end
|
65
62
|
|
66
63
|
def finalize
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
if File.exist?(incomplete) &&
|
72
|
-
!File.exist?(complete)
|
73
|
-
File.rename(incomplete, complete)
|
74
|
-
end
|
75
|
-
|
76
|
-
File.open("#{options[:target]}/.lastfull",'w') do |fh|
|
77
|
-
fh.puts backup_dir_name
|
78
|
-
end
|
79
|
-
|
80
|
-
info "Backup saved in #{options[:target]}/#{backup_dir_name}"
|
64
|
+
File.rename(@incomplete, @complete) if File.exist?(@incomplete)
|
65
|
+
File.write(File.join(@target,DEFAULT_LAST_FULL_DIR_NAME), backup_dir_name)
|
66
|
+
info "Backup saved in #{@complete}"
|
81
67
|
end
|
82
68
|
|
83
69
|
|
@@ -18,7 +18,8 @@ class Rsyncbackup
|
|
18
18
|
|
19
19
|
cmd = []
|
20
20
|
cmd << options[:rsync_cmd]
|
21
|
-
cmd << '--
|
21
|
+
cmd << '--dry-run' if options[:dry_run]
|
22
|
+
cmd << '--verbose --progress --itemize-changes' if (options[:verbose] || options[:debug])
|
22
23
|
cmd << '--archive' if options[:archive]
|
23
24
|
cmd << '--one-file-system' if options[:one_file_system]
|
24
25
|
cmd << '--hard-links' if options[:hard_links]
|
@@ -28,10 +29,10 @@ class Rsyncbackup
|
|
28
29
|
cmd << '--delete' if options[:delete]
|
29
30
|
cmd << "--exclude-file #{options[:exclusions]}" if File.exist?(options[:exclusions])
|
30
31
|
cmd << "--link-dest '#{options[:link_dest]}'" if options[:link_dest]
|
31
|
-
cmd << "
|
32
|
-
cmd << "
|
32
|
+
cmd << ?" + @source + ?"
|
33
|
+
cmd << ?" + temp_target_path + ?"
|
33
34
|
|
34
|
-
cmd.join(' ')
|
35
|
+
cmd.join(' ')
|
35
36
|
|
36
37
|
end
|
37
38
|
|
@@ -39,12 +40,20 @@ class Rsyncbackup
|
|
39
40
|
# returns nil otherwise
|
40
41
|
def last_full_backup
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
unless @last_full_backup
|
44
|
+
lastfull = File.join(@target,DEFAULT_LAST_FULL_DIR_NAME)
|
45
|
+
@last_full_backup = unless File.exist?(lastfull)
|
46
|
+
nil
|
47
|
+
else
|
48
|
+
last_full_directory = IO.readlines(lastfull).first.chomp
|
49
|
+
unless File.exist?(File.join(@target,last_full_directory))
|
50
|
+
nil
|
51
|
+
else
|
52
|
+
last_full_directory
|
53
|
+
end
|
54
|
+
end
|
47
55
|
end
|
56
|
+
@last_full_backup
|
48
57
|
|
49
58
|
end
|
50
59
|
|
@@ -56,12 +65,12 @@ class Rsyncbackup
|
|
56
65
|
|
57
66
|
# returns the full target path, including backup directory name
|
58
67
|
def full_target_path
|
59
|
-
@full_target_path ||=
|
68
|
+
@full_target_path ||= File.join(@target, backup_dir_name)
|
60
69
|
end
|
61
70
|
|
62
71
|
# returns the temporary target path
|
63
72
|
def temp_target_path
|
64
|
-
@temp_target_path ||=
|
73
|
+
@temp_target_path ||= File.join(@target, DEFAULT_INCOMPLETE_DIR_NAME)
|
65
74
|
end
|
66
75
|
|
67
76
|
|
@@ -78,9 +87,9 @@ class Rsyncbackup
|
|
78
87
|
# source or target.
|
79
88
|
#
|
80
89
|
# *s*:: string to strip
|
81
|
-
def strip_trailing_separator_if_any(s)
|
82
|
-
|
83
|
-
s = s.
|
90
|
+
def strip_trailing_separator_if_any(s,keep_if_symlink=false)
|
91
|
+
s = s.to_s
|
92
|
+
s = s.sub(%r{/+$},'') unless keep_if_symlink && File.symlink?(s)
|
84
93
|
end
|
85
94
|
|
86
95
|
end
|
data/lib/rsyncbackup/version.rb
CHANGED
data/rsyncbackup.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'rsyncbackup/version'
|
@@ -16,9 +15,15 @@ Gem::Specification.new do |gem|
|
|
16
15
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
16
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
17
|
gem.require_paths = ["lib"]
|
18
|
+
|
19
19
|
gem.add_development_dependency('rdoc')
|
20
20
|
gem.add_development_dependency('aruba')
|
21
|
-
gem.add_development_dependency('rake'
|
21
|
+
gem.add_development_dependency('rake')
|
22
22
|
gem.add_development_dependency('rspec')
|
23
|
-
gem.
|
23
|
+
gem.add_development_dependency('guard')
|
24
|
+
gem.add_development_dependency('guard-rspec')
|
25
|
+
gem.add_development_dependency('guard-cucumber')
|
26
|
+
|
27
|
+
gem.add_dependency('methadone')
|
28
|
+
|
24
29
|
end
|
data/spec/rsyncbackup_spec.rb
CHANGED
@@ -1,15 +1,38 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rsyncbackup'
|
3
|
+
require 'tempfile'
|
3
4
|
|
4
5
|
describe Rsyncbackup do
|
5
6
|
|
7
|
+
let(:source){Dir.mktmpdir("source")}
|
8
|
+
let(:target){Dir.mktmpdir("target")}
|
9
|
+
before(:each) do
|
10
|
+
Dir.chdir(source) do |pwd|
|
11
|
+
%w{one two three four five}.each do |d|
|
12
|
+
FileUtils.mkdir(File.join(pwd,d))
|
13
|
+
%w{a b c d e f g}.each do |fn|
|
14
|
+
File.open(File.join(d,fn),'w') do |f|
|
15
|
+
f.puts "Test file for #{example.description}"
|
16
|
+
f.puts Time.now.to_s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
6
23
|
context "Interface Checks" do
|
7
|
-
it
|
8
|
-
|
24
|
+
it "should respond to :new" do
|
25
|
+
Rsyncbackup.should respond_to(:new)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be of type Rsyncbackup" do
|
29
|
+
Rsyncbackup.new(source, target, :dry_run => true).should be_a(Rsyncbackup)
|
30
|
+
end
|
31
|
+
|
9
32
|
end
|
10
33
|
|
11
34
|
context "Options Validity" do
|
12
|
-
let(:syncer) { Rsyncbackup.new(source:
|
35
|
+
let(:syncer) { Rsyncbackup.new(source, target, :dry_run => true, :debug => true) }
|
13
36
|
|
14
37
|
it "has a command" do
|
15
38
|
syncer.options[:rsync_cmd].should =~ /rsync/
|
@@ -18,69 +41,26 @@ describe Rsyncbackup do
|
|
18
41
|
end
|
19
42
|
|
20
43
|
context "#run" do
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
mismatch_message = "mismatch!! expected: #{part_of_command}. received: #{command}"
|
25
|
-
case part_of_command
|
26
|
-
when Regexp
|
27
|
-
raise mismatch_message unless command =~ part_of_command
|
28
|
-
when String
|
29
|
-
raise mismatch_message unless command.include?(part_of_command)
|
30
|
-
else
|
31
|
-
raise mismatch_message
|
32
|
-
end
|
33
|
-
end
|
44
|
+
let(:syncer) { Rsyncbackup.new(source, target, :dry_run => true) }
|
45
|
+
it "should respond to :run" do
|
46
|
+
syncer.should respond_to(:run)
|
34
47
|
end
|
35
|
-
|
36
|
-
let(:source) {'features/test_files/source' }
|
37
|
-
let(:target) {'features/test_files/target'}
|
38
|
-
|
39
|
-
let(:syncer) { Rsyncbackup.new(source: source, target: target) }
|
40
|
-
|
41
|
-
it { syncer.should respond_to(:run) }
|
42
|
-
|
43
|
-
it "should allow a different executable" do
|
44
|
-
exec="echo --"
|
45
|
-
syncer.options[:rsync_cmd] = exec
|
46
|
-
expect_command_match(exec)
|
47
|
-
syncer.run
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should allow a different exclusions file" do
|
51
|
-
exclusions=File.expand_path("myexclusions")
|
52
|
-
File.open(exclusions,'w') do |fh|
|
53
|
-
fh.puts "my exclusions go here"
|
54
|
-
end
|
55
|
-
syncer.options[:exclusions]=exclusions
|
56
|
-
expect_command_match("--exclude-file #{exclusions}")
|
57
|
-
syncer.run
|
58
|
-
File.unlink(exclusions)
|
59
|
-
end
|
60
|
-
|
61
48
|
end
|
62
49
|
|
63
50
|
context "#finalize" do
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
let(:syncer) { Rsyncbackup.new(source: source , target: target ) }
|
69
|
-
it { syncer.should respond_to(:finalize) }
|
51
|
+
let(:syncer) { Rsyncbackup.new(source,target) }
|
52
|
+
it "should respond to :finalize" do
|
53
|
+
syncer.should respond_to(:finalize)
|
54
|
+
end
|
70
55
|
|
71
56
|
it "should rename temporary backup directory" do
|
72
57
|
syncer.run
|
73
58
|
syncer.finalize
|
74
|
-
File.exist?(File.join(target,
|
59
|
+
File.exist?(File.join(target,Rsyncbackup::DEFAULT_INCOMPLETE_DIR_NAME)).should be_false
|
60
|
+
File.exist?(File.join(target,Rsyncbackup::DEFAULT_LAST_FULL_DIR_NAME)).should be_true
|
75
61
|
File.directory?(File.join(target,syncer.backup_dir_name)).should be_true
|
76
62
|
File.directory?(File.join(target,syncer.backup_dir_name,File.basename(source))).should be_true
|
77
63
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
64
|
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
65
|
end
|
66
|
+
|
data/spec/spec_helper.rb
CHANGED
@@ -13,5 +13,7 @@ RSpec.configure do |config|
|
|
13
13
|
# order dependency and want to debug it, you can fix the order by providing
|
14
14
|
# the seed, which is printed after each run.
|
15
15
|
# --seed 1234
|
16
|
-
config.order = 'random'
|
16
|
+
# config.order = 'random'
|
17
17
|
end
|
18
|
+
|
19
|
+
require 'rsyncbackup'
|
data/spec/utilities_spec.rb
CHANGED
@@ -9,12 +9,27 @@
|
|
9
9
|
|
10
10
|
=end
|
11
11
|
|
12
|
+
require 'spec_helper.rb'
|
13
|
+
require 'tempfile'
|
14
|
+
require 'tmpdir'
|
15
|
+
|
12
16
|
describe Rsyncbackup do
|
17
|
+
|
18
|
+
let(:source){Dir.mktmpdir("source")}
|
19
|
+
let(:target){Dir.mktmpdir("target")}
|
20
|
+
before(:each) do
|
21
|
+
Dir.chdir(source) do |pwd|
|
22
|
+
%w{one two three four five}.each do |d|
|
23
|
+
FileUtils.mkdir(File.join(pwd,d))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
13
28
|
context "utilities" do
|
14
|
-
|
29
|
+
let(:syncer) { Rsyncbackup.new(source, target, :dry_run => true, :debug => true) }
|
30
|
+
|
15
31
|
context "#build_command" do
|
16
|
-
|
17
|
-
|
32
|
+
|
18
33
|
it { syncer.should respond_to(:build_command) }
|
19
34
|
|
20
35
|
it "should build a valid command" do
|
@@ -26,59 +41,62 @@ describe Rsyncbackup do
|
|
26
41
|
cmd.should =~ /--inplace/
|
27
42
|
cmd.should =~ /--numeric-ids/
|
28
43
|
cmd.should =~ /--delete/
|
29
|
-
cmd.should =~
|
30
|
-
cmd.should =~
|
44
|
+
cmd.should =~ /#{source}/
|
45
|
+
cmd.should =~ /#{File.join(target,Rsyncbackup::DEFAULT_INCOMPLETE_DIR_NAME)}/
|
31
46
|
end
|
32
47
|
end
|
33
48
|
|
34
49
|
context "#last_full_backup" do
|
35
|
-
let (:syncer) { Rsyncbackup.new(source: 'source', target: '/tmp') }
|
36
|
-
|
37
50
|
it { syncer.should respond_to(:last_full_backup) }
|
38
51
|
|
39
52
|
it "should be nil if no last full backup" do
|
40
53
|
syncer.last_full_backup.should be_nil
|
41
54
|
end
|
42
55
|
|
43
|
-
|
44
|
-
last_full_directory
|
45
|
-
last_full_file
|
46
|
-
|
47
|
-
|
48
|
-
|
56
|
+
context "with a last full backup directory" do
|
57
|
+
let(:last_full_directory) {Time.new(2013,01,01,03,10,00).strftime("%FT%H-%M-%S")}
|
58
|
+
let(:last_full_file) {File.join(target, Rsyncbackup::DEFAULT_LAST_FULL_DIR_NAME)}
|
59
|
+
|
60
|
+
before do
|
61
|
+
FileUtils.mkdir(File.join(target,last_full_directory))
|
62
|
+
File.write(last_full_file, last_full_directory)
|
49
63
|
end
|
50
|
-
|
51
|
-
syncer.last_full_backup.should == last_full_directory
|
52
|
-
|
53
|
-
File.unlink last_full_file
|
54
|
-
end
|
55
64
|
|
65
|
+
it "should be the directory name if there was a last full backup marker" do
|
66
|
+
syncer.last_full_backup.should == last_full_directory
|
67
|
+
# File.unlink last_full_file # should not need this using tmpdir
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
56
71
|
end
|
57
72
|
|
58
73
|
context "#backup_dir_name" do
|
59
|
-
let(:syncer) { Rsyncbackup.new(source: 'source', target: 'target') }
|
60
|
-
|
61
74
|
it { syncer.should respond_to(:backup_dir_name) }
|
62
|
-
|
63
75
|
it "should give a valid backup directory name: YYYY-MM-DDTHH-MM-SS" do
|
64
|
-
|
65
|
-
name.should =~ /(\d){4}-(\d){2}-(\d){2}T(\d){2}-(\d){2}-(\d){2}/
|
76
|
+
syncer.backup_dir_name.should match /(\d){4}-(\d){2}-(\d){2}T(\d){2}-(\d){2}-(\d){2}/
|
66
77
|
end
|
67
78
|
end
|
68
79
|
|
69
80
|
context "#strip_trailing_separator_if_any" do
|
81
|
+
it "should respond to #strip_trailing_separator_if_any" do
|
82
|
+
syncer.should respond_to(:strip_trailing_separator_if_any)
|
83
|
+
end
|
70
84
|
|
71
85
|
context "with trailing separators" do
|
72
|
-
let(:syncer) { Rsyncbackup.new(source: 'source/', target: 'target/') }
|
73
|
-
|
74
|
-
it "should respond to #strip_trailing_separator_if_any" do
|
75
|
-
syncer.should respond_to(:strip_trailing_separator_if_any)
|
76
|
-
end
|
77
86
|
|
78
87
|
it "should remove trailing slash from source" do
|
79
88
|
syncer.strip_trailing_separator_if_any('source/').should == 'source'
|
80
89
|
end
|
81
90
|
|
91
|
+
it "should remove trailing slash from source when keep_if_symlink is true" do
|
92
|
+
syncer.strip_trailing_separator_if_any('source/',true).should == 'source'
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should not remove trailing slash from source if source is a symlink" do
|
96
|
+
source_link = Tempfile.new("sourcelink").to_s
|
97
|
+
syncer.strip_trailing_separator_if_any(source_link,true).should == source_link
|
98
|
+
end
|
99
|
+
|
82
100
|
it "should remove trailing slash from target" do
|
83
101
|
syncer.strip_trailing_separator_if_any('target/').should == 'target'
|
84
102
|
end
|
@@ -86,11 +104,6 @@ describe Rsyncbackup do
|
|
86
104
|
end
|
87
105
|
|
88
106
|
context "withOUT trailing separators" do
|
89
|
-
let(:syncer) { Rsyncbackup.new(source: 'source', target: 'target') }
|
90
|
-
|
91
|
-
it "should respond to #strip_trailing_separator_if_any" do
|
92
|
-
syncer.should respond_to(:strip_trailing_separator_if_any)
|
93
|
-
end
|
94
107
|
|
95
108
|
it "should remove trailing slash from source" do
|
96
109
|
syncer.strip_trailing_separator_if_any('source').should == 'source'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsyncbackup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tamara Temple
|
@@ -42,16 +42,16 @@ dependencies:
|
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,20 +66,62 @@ dependencies:
|
|
66
66
|
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: guard-cucumber
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: methadone
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
72
114
|
requirements:
|
73
|
-
- -
|
115
|
+
- - '>='
|
74
116
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
117
|
+
version: '0'
|
76
118
|
type: :runtime
|
77
119
|
prerelease: false
|
78
120
|
version_requirements: !ruby/object:Gem::Requirement
|
79
121
|
requirements:
|
80
|
-
- -
|
122
|
+
- - '>='
|
81
123
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
124
|
+
version: '0'
|
83
125
|
description: Yet another rsyncbackup script, this time in ruby
|
84
126
|
email:
|
85
127
|
- tamouse@gmail.com
|
@@ -91,6 +133,7 @@ files:
|
|
91
133
|
- .gitignore
|
92
134
|
- .rspec
|
93
135
|
- Gemfile
|
136
|
+
- Guardfile
|
94
137
|
- LICENSE.txt
|
95
138
|
- README.md
|
96
139
|
- README.rdoc
|