easy_sync 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cea7195f628ae1bb09b15c6fc14d8a97217d20f8
4
+ data.tar.gz: 6bdd4d0fb5a0ad7149196b817aadcc5d367d2a7d
5
+ SHA512:
6
+ metadata.gz: 9977a20cc1c688e8e5d1767c4b8533643da3b071f990d59ba6b037bb95f76d3f70844b741ad28aea86316fef7899ac3441390eed7377a7173be95384135143f2
7
+ data.tar.gz: 22bac584e4ba65fad6d642aaf758b401864b6d615697af1b28b25c00bde5705bea7ef8c2ad7d6ec99723e39b6bfdfe2cde36be9d0d2744b839f44e0564636b45
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,56 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ easy_sync (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ celluloid (0.15.2)
10
+ timers (~> 1.1.0)
11
+ celluloid-io (0.15.0)
12
+ celluloid (>= 0.15.0)
13
+ nio4r (>= 0.5.0)
14
+ coderay (1.1.0)
15
+ ffi (1.9.3)
16
+ formatador (0.2.4)
17
+ guard (2.4.0)
18
+ formatador (>= 0.2.4)
19
+ listen (~> 2.1)
20
+ lumberjack (~> 1.0)
21
+ pry (>= 0.9.12)
22
+ thor (>= 0.18.1)
23
+ guard-minitest (2.2.0)
24
+ guard (~> 2.0)
25
+ minitest (>= 3.0)
26
+ listen (2.5.0)
27
+ celluloid (>= 0.15.2)
28
+ celluloid-io (>= 0.15.0)
29
+ rb-fsevent (>= 0.9.3)
30
+ rb-inotify (>= 0.9)
31
+ lumberjack (1.0.4)
32
+ method_source (0.8.2)
33
+ minitest (5.2.3)
34
+ nio4r (1.0.0)
35
+ pry (0.9.12.6)
36
+ coderay (~> 1.0)
37
+ method_source (~> 0.8)
38
+ slop (~> 3.4)
39
+ rake (10.1.1)
40
+ rb-fsevent (0.9.4)
41
+ rb-inotify (0.9.3)
42
+ ffi (>= 0.5.0)
43
+ slop (3.4.7)
44
+ terminal-notifier-guard (1.5.3)
45
+ thor (0.18.1)
46
+ timers (1.1.0)
47
+
48
+ PLATFORMS
49
+ ruby
50
+
51
+ DEPENDENCIES
52
+ bundler (~> 1.5)
53
+ easy_sync!
54
+ guard-minitest
55
+ rake
56
+ terminal-notifier-guard
data/Guardfile ADDED
@@ -0,0 +1,28 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :minitest do
5
+ # with Minitest::Unit
6
+ #watch(%r{^test/(.*)\/?test_(.*)\.rb$})
7
+ #watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
8
+ #watch(%r{^test/test_helper\.rb$}) { 'test' }
9
+
10
+ # with Minitest::Spec
11
+ watch(%r{^spec/(.*)_spec\.rb$})
12
+ #watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
13
+ watch(%r{^spec/spec_helper\.rb$}) { 'spec' }
14
+
15
+ # Rails 4
16
+ # watch(%r{^app/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
17
+ # watch(%r{^app/controllers/application_controller\.rb$}) { 'test/controllers' }
18
+ # watch(%r{^app/controllers/(.+)_controller\.rb$}) { |m| "test/integration/#{m[1]}_test.rb" }
19
+ # watch(%r{^app/views/(.+)_mailer/.+}) { |m| "test/mailers/#{m[1]}_mailer_test.rb" }
20
+ # watch(%r{^lib/(.+)\.rb$}) { |m| "test/lib/#{m[1]}_test.rb" }
21
+ # watch(%r{^test/.+_test\.rb$})
22
+ # watch(%r{^test/test_helper\.rb$}) { 'test' }
23
+
24
+ # Rails < 4
25
+ # watch(%r{^app/controllers/(.*)\.rb$}) { |m| "test/functional/#{m[1]}_test.rb" }
26
+ # watch(%r{^app/helpers/(.*)\.rb$}) { |m| "test/helpers/#{m[1]}_test.rb" }
27
+ # watch(%r{^app/models/(.*)\.rb$}) { |m| "test/unit/#{m[1]}_test.rb" }
28
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Carlos Espejo
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ easy_sync
2
+ =========
3
+
4
+ ### Why?
5
+ * Did you just get a shiny new 1TB 2.5 inch external hard drive and suddenly have the urge to back :poop: up?
6
+ * Did you just hear about [CryptoLocker](http://en.wikipedia.org/wiki/CryptoLocker) and thought crap how can i protect my friends and family?
7
+
8
+ **Note:** Once you get [CryptoLocker](http://en.wikipedia.org/wiki/CryptoLocker) it will encrypt the crap out
9
+ of any drive letter it can find including mapped network shares :cry:
10
+
11
+ Now if you use **Ruby** plus **Rsync** you can easily have many cold snapshots to restore from :thumbsup:
12
+
13
+
14
+ ### Installation
15
+ gem install easy_sync
16
+
17
+
18
+ ### Requirements
19
+ * rsync 2.5.6 and up
20
+
21
+
22
+ ### Usage
23
+ Just run easy_sync to generate a template mapping file, configure
24
+ your paths and next time you run **easy_sync** it will create the first
25
+ backup. After first backup it will create incremental backups.
26
+
27
+
28
+ ### Todo
29
+ * ~~Given a source and destination a snapshot should be created.~~
30
+ * ~~It should use the latest backup for Rsync's --link-dest option and create a new snapshot with the files that changed.~~
31
+ * ~~Add logging~~
32
+ * If source or destination doesn't exists don't run rsync
33
+ * ~~excluded list~~
34
+ * ~~Support multiple source and destination configurations by using a yaml config file.~~
35
+ * ~~Convert to a gem and create a easy_sync bin file~~
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "rake/testtask"
2
+ require "bundler/gem_tasks"
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "lib"
6
+ t.libs << "spec"
7
+ t.pattern = "spec/**/*_spec.rb"
8
+ end
9
+
10
+ task :default => :test
data/bin/easy_sync ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'easy_sync'
4
+ EasySync::SyncRunner.new.run
data/easy_sync.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'easy_sync/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "easy_sync"
8
+ spec.version = EasySync::VERSION
9
+ spec.authors = ["Carlos Espejo"]
10
+ spec.email = ["carlosespejo@gmail.com"]
11
+ spec.summary = %q{Ruby wrapper around rsync to easily create incremental backups.}
12
+ #spec.description = %q{TODO: Write a longer description. Optional.}
13
+ spec.homepage = "https://github.com/CarlosEspejo/easy_sync"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "guard-minitest"
24
+ spec.add_development_dependency "terminal-notifier-guard"
25
+
26
+ end
File without changes
@@ -0,0 +1,46 @@
1
+ require 'logger'
2
+
3
+ module EasySync
4
+
5
+ class Rsync
6
+ attr_reader :sync_name, :source, :destination, :exclude_file, :last_snapshot, :current, :logging
7
+
8
+ def initialize(options)
9
+ @sync_name = options[:sync_name]
10
+ @source = options[:source]
11
+ @destination = options[:destination]
12
+ @exclude_file = options[:exclude_file]
13
+ @logging = options.fetch(:logging){:off}
14
+ end
15
+
16
+ def latest_snapshot
17
+ @last_snapshot = Dir["#{destination}/*"].max_by{|s| File.mtime s}
18
+ end
19
+
20
+ def current_snapshot
21
+ @current = File.join destination, Time.now.strftime("%Y-%m-%d")
22
+ end
23
+
24
+ def sync
25
+ commands = [
26
+ "rsync",
27
+ "-avhiPH",
28
+ "--exclude-from", "#{exclude_file}",
29
+ "--link-dest", "#{latest_snapshot}"
30
+ ]
31
+
32
+ commands << ['--log-file', "#{ENV['HOME']}/easy_sync.log" ] if logging == :on
33
+ commands << ["#{source}", "#{current_snapshot}"]
34
+ commands = commands.flatten
35
+
36
+ name = "\n\n\n------------------ Running #{sync_name} ------------------\n\n\n"
37
+ puts name
38
+
39
+ IO.popen(commands).each_line do |l|
40
+ puts l
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,20 @@
1
+ require 'logger'
2
+
3
+
4
+ module EasySync
5
+
6
+ class SyncLogger
7
+ attr_reader :log
8
+
9
+ def initialize(path)
10
+ @log = Logger.new(path)
11
+ end
12
+
13
+ def info(message)
14
+ puts message
15
+ log.info message
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,44 @@
1
+ require 'yaml'
2
+
3
+ module EasySync
4
+
5
+ class SyncRunner
6
+ attr_reader :config
7
+
8
+ def initialize()
9
+ handle_config
10
+ end
11
+
12
+ def run
13
+ config[:tasks].each do |c|
14
+ c[:logging] = config[:logging]
15
+ Rsync.new(c).sync
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def handle_config
22
+ path = "#{ENV["HOME"]}/.easy_syncrc.yml"
23
+ generate_yaml(path) unless File.exist? path
24
+ @config = YAML.load_file path
25
+ end
26
+
27
+ def generate_yaml(path)
28
+ File.open(path, 'w') do |f|
29
+ h = {:logging => :on,
30
+ :tasks => [{
31
+ sync_name: "sample_sync",
32
+ source: "[/example/path]",
33
+ destination: "[/example/path]",
34
+ exclude_file: "[/example/path]"
35
+ }]}
36
+ f.puts h.to_yaml
37
+ end
38
+
39
+ $stderr.puts "Generated sample config file: #{path}\n\n"
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,3 @@
1
+ module EasySync
2
+ VERSION = '0.0.1'
3
+ end
data/lib/easy_sync.rb ADDED
@@ -0,0 +1,4 @@
1
+ require_relative 'easy_sync/version'
2
+ require_relative 'easy_sync/sync_runner'
3
+ require_relative 'easy_sync/rsync'
4
+ require_relative 'easy_sync/sync_logger'
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rsync do
4
+
5
+ let(:task){config_file_data[:tasks].first}
6
+
7
+ it "should find the latest snapshot directory" do
8
+ Rsync.new(task) \
9
+ .latest_snapshot.must_equal File.join(destination_directory, "2013-12-30")
10
+ end
11
+
12
+ it "should create the new snapshot directory" do
13
+ Rsync.new(task) \
14
+ .current_snapshot.must_equal File.join(destination_directory, Time.now.strftime("%Y-%m-%d"))
15
+ end
16
+
17
+ it "should log to a file" do
18
+ log_file = "#{temp_directory}/easy_sync.log"
19
+ task[:logging] = :on
20
+
21
+ Rsync.new(task).sync
22
+ File.exist?(log_file).must_equal true
23
+ end
24
+
25
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe SyncRunner do
4
+
5
+ it "should create template config if no config file passed" do
6
+ SyncRunner.new
7
+ config = YAML.load_file default_config_path
8
+ config.must_equal blank_config
9
+ end
10
+
11
+ it "should use default config file" do
12
+ File.open(default_config_path, "w"){|f| f.puts config_file_data.merge({logging: :off}).to_yaml}
13
+ SyncRunner.new.config[:logging].must_equal :off
14
+ end
15
+
16
+ it "should sync files between source and destination" do
17
+ create_config_file
18
+ SyncRunner.new.run
19
+ Dir["#{File.join(destination_directory, Time.now.strftime("%Y-%m-%d"))}/*"].map{|f| File.basename f}.must_equal ["file1.txt", "file2.txt", "file3.txt", "file4.txt"]
20
+ end
21
+
22
+ it "should create hard links to the files that didn't change in the new snapshot directory" do
23
+ create_config_file
24
+ SyncRunner.new.run
25
+
26
+ snapshot_file = Dir["#{File.join(destination_directory, "2013-12-30")}/*"].first
27
+ new_file = Dir["#{File.join(destination_directory, Time.now.strftime("%Y-%m-%d"))}/*"].first
28
+
29
+ File.stat(snapshot_file).ino.must_equal File.stat(new_file).ino
30
+ end
31
+
32
+ it "should use exclude-from option" do
33
+ exclude_file = "#{destination_directory}/exclude.txt"
34
+ File.open(exclude_file, "w"){|f| f.puts "file4.txt"}
35
+
36
+ config_file_data[:tasks].first[:exclude_file] = exclude_file
37
+ File.open(default_config_path, 'w'){|f| f.puts config_file_data.to_yaml}
38
+
39
+ SyncRunner.new.run
40
+
41
+ Dir["#{File.join(destination_directory, Time.now.strftime("%Y-%m-%d"))}/*"].map{|f| File.basename f}.must_equal ["file1.txt", "file2.txt", "file3.txt"]
42
+ end
43
+
44
+ it "should apply log setting to all task" do
45
+ log_file = "#{temp_directory}/easy_sync.log"
46
+ create_config_file
47
+ s = SyncRunner.new
48
+ s.config[:logging] = :on
49
+ s.run
50
+
51
+ File.exist?(log_file).must_equal true
52
+ end
53
+
54
+ end
@@ -0,0 +1,33 @@
1
+ require "minitest/autorun"
2
+ require "minitest/pride"
3
+ require 'pry'
4
+
5
+ require 'easy_sync'
6
+ require_relative 'support'
7
+
8
+ include EasySync
9
+
10
+ class MiniTest::Spec
11
+
12
+ before do
13
+ create_root_directory
14
+ create_source_directory
15
+ create_destination_directory
16
+ create_snapshot_directories
17
+ create_source_files
18
+ copy_to_latest
19
+
20
+ # Silences output, comment out to debug test cases
21
+ $stdout = StringIO.new
22
+ $stderr = StringIO.new
23
+ ENV['HOME'] = temp_directory
24
+ end
25
+
26
+
27
+ after do
28
+ FileUtils.rm_r temp_directory
29
+ $stdout = STDOUT
30
+ $stderr = STDERR
31
+ end
32
+
33
+ end
data/spec/support.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+ require 'time'
4
+
5
+
6
+ def create_root_directory
7
+ @temp_directory = Dir.mktmpdir('test_data', File.expand_path('./', File.dirname(__FILE__)))
8
+ end
9
+
10
+ def temp_directory
11
+ @temp_directory
12
+ end
13
+
14
+ def create_source_directory
15
+ @source_directory = File.join(temp_directory, 'source')
16
+ Dir.mkdir @source_directory
17
+ end
18
+
19
+ def create_destination_directory
20
+ @destination_directory = File.join(temp_directory, 'backup')
21
+ Dir.mkdir @destination_directory
22
+ end
23
+
24
+ def source_directory
25
+ "#{@source_directory}/"
26
+ end
27
+
28
+ def destination_directory
29
+ @destination_directory
30
+ end
31
+
32
+ def create_snapshot_directories
33
+ %w{2013-12-30 2013-11-10 2013-10-10 2013-11-07}.each do |date|
34
+ path = File.join destination_directory, date
35
+
36
+ Dir.mkdir path
37
+ time = Time.parse date
38
+
39
+ File.utime(time, time, path)
40
+
41
+ end
42
+ end
43
+
44
+ def create_source_files
45
+ %w{file1.txt file2.txt file3.txt file4.txt}.each do |file|
46
+ File.open(File.join(source_directory, file), 'w'){|f| f.puts "This is some sample text"}
47
+ end
48
+
49
+ end
50
+
51
+ def copy_to_latest
52
+ %w{file1.txt file2.txt file3.txt}.each do |file|
53
+ FileUtils.cp File.join(source_directory, file), File.join(destination_directory, "2013-12-30")
54
+ end
55
+ end
56
+
57
+ def blank_config
58
+ @blank_config ||= {
59
+ logging: :on,
60
+ tasks: [{
61
+ sync_name: "sample_sync",
62
+ source: "[/example/path]",
63
+ destination: "[/example/path]",
64
+ exclude_file: "[/example/path]"
65
+ }]
66
+ }
67
+ end
68
+
69
+ def config_file_data
70
+ @config_file_data ||= {
71
+ logging: :off,
72
+ tasks: [
73
+ {
74
+ sync_name: "test_sync",
75
+ source: "#{source_directory}",
76
+ destination: "#{destination_directory}",
77
+ exclude_file: ""
78
+ }]
79
+ }
80
+ end
81
+
82
+ def create_config_file
83
+ File.open(default_config_path, 'w'){|f| f.puts config_file_data.to_yaml}
84
+ default_config_path
85
+ end
86
+
87
+ def default_config_path
88
+ "#{temp_directory}/.easy_syncrc.yml"
89
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: easy_sync
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Carlos Espejo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: terminal-notifier-guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email:
71
+ - carlosespejo@gmail.com
72
+ executables:
73
+ - easy_sync
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - Guardfile
81
+ - LICENSE
82
+ - README.md
83
+ - Rakefile
84
+ - bin/easy_sync
85
+ - easy_sync.gemspec
86
+ - lib/easy_sync.rb
87
+ - lib/easy_sync/cli.rb
88
+ - lib/easy_sync/rsync.rb
89
+ - lib/easy_sync/sync_logger.rb
90
+ - lib/easy_sync/sync_runner.rb
91
+ - lib/easy_sync/version.rb
92
+ - spec/easy_sync/rsync_spec.rb
93
+ - spec/easy_sync/sync_runner_spec.rb
94
+ - spec/spec_helper.rb
95
+ - spec/support.rb
96
+ homepage: https://github.com/CarlosEspejo/easy_sync
97
+ licenses:
98
+ - MIT
99
+ metadata: {}
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubyforge_project:
116
+ rubygems_version: 2.2.2
117
+ signing_key:
118
+ specification_version: 4
119
+ summary: Ruby wrapper around rsync to easily create incremental backups.
120
+ test_files:
121
+ - spec/easy_sync/rsync_spec.rb
122
+ - spec/easy_sync/sync_runner_spec.rb
123
+ - spec/spec_helper.rb
124
+ - spec/support.rb