dir_sync 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.rdoc +9 -3
- data/README.rdoc +8 -3
- data/Rakefile +15 -7
- data/bin/dir_sync +2 -11
- data/bin/drain +3 -17
- data/features/backup.feature +76 -0
- data/features/step_definitions/dir_sync_steps.rb +22 -0
- data/features/support/env.rb +7 -0
- data/lib/{change_log_file_system.rb → dir_sync/change_log_file_system.rb} +5 -2
- data/lib/{change_resolver.rb → dir_sync/change_resolver.rb} +5 -2
- data/lib/{historical_traverser.rb → dir_sync/history_traverser.rb} +5 -2
- data/lib/{traverser.rb → dir_sync/traverser.rb} +5 -2
- data/lib/dir_sync.rb +40 -0
- data/spec/dir_sync/change_log_file_system_spec.rb +24 -0
- data/spec/{change_resolver_spec.rb → dir_sync/change_resolver_spec.rb} +3 -3
- data/spec/dir_sync/history_traverser_spec.rb +25 -0
- data/spec/{traverser_spec.rb → dir_sync/traverser_spec.rb} +4 -4
- data/spec/{synchroniser_spec.rb → dir_sync_spec.rb} +10 -10
- metadata +43 -29
- data/lib/synchroniser.rb +0 -15
data/HISTORY.rdoc
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
= 0.1.
|
1
|
+
= 0.1.1 Sun 29 Jan 2012 14:40:03 EST
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
* moved everything into a DirSync module to prevent any namespace collisions.
|
4
|
+
* explicitly stated support for ruby 1.9 only in gem specification
|
5
|
+
* changed drain script to accept any number of parameters
|
6
|
+
|
7
|
+
= 0.1.0 Fri 27 Jan 2012 20:57:18 EST
|
8
|
+
|
9
|
+
* initial release
|
10
|
+
* performs multidirectional synchronisation for any number of local directories
|
data/README.rdoc
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[![Build Status](https://secure.travis-ci.org/markryall/dir_sync.png)](http://travis-ci.org/markryall/dir_sync)
|
2
|
+
|
1
3
|
= dir_sync
|
2
4
|
|
3
5
|
Produce a script to synchronise two directories. Kind of like unison but a bit simpler.
|
@@ -12,10 +14,13 @@ in subsequent synchronisations to detect deletions. You can then review the com
|
|
12
14
|
before executing them (in case they seem likely to do something undesirable). Note that
|
13
15
|
files that differ only in modification time will be overwritten with the most recent one.
|
14
16
|
|
15
|
-
drain
|
17
|
+
drain script1 script2
|
16
18
|
|
17
|
-
This simply runs each line in the specified
|
18
|
-
|
19
|
+
This simply runs each line in the specified scripts rewriting the script as each
|
20
|
+
command is succesfully executed. This is just so if the script is interrupted or
|
21
|
+
killed, you can resume. Note that the new file will be written to a temp file first
|
22
|
+
(in case the rewriting is interrupted), each command must appear on a single line
|
23
|
+
and it is likely that the command interrupted will be rexecuted.
|
19
24
|
|
20
25
|
Together, these scripts can be used as follows:
|
21
26
|
|
data/Rakefile
CHANGED
@@ -1,12 +1,20 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
|
3
|
-
task :default => :
|
4
|
-
task :test => [:spec, :features]
|
3
|
+
task :default => [:spec, :cucumber]
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
RSpec::Core::RakeTask.new
|
7
|
+
|
8
|
+
require 'cucumber/rake/task'
|
9
|
+
namespace :cucumber do
|
10
|
+
Cucumber::Rake::Task.new :strict do |task|
|
11
|
+
task.cucumber_opts = '-p strict'
|
12
|
+
end
|
13
|
+
|
14
|
+
Cucumber::Rake::Task.new :wip do |task|
|
15
|
+
task.cucumber_opts = '-p wip'
|
16
|
+
end
|
8
17
|
end
|
9
18
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
19
|
+
desc 'Run all Cucumber features'
|
20
|
+
task :cucumber => ['cucumber:wip', 'cucumber:strict']
|
data/bin/dir_sync
CHANGED
@@ -1,13 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
2
|
$: << File.dirname(__FILE__)+'/../lib'
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
if ARGV.size < 3
|
8
|
-
puts "usage: #{__FILE__} name directory1 directory2 ..."
|
9
|
-
puts " set DEBUG for verbose output"
|
10
|
-
exit 1
|
11
|
-
end
|
12
|
-
|
13
|
-
Synchroniser.iterate *ARGV
|
3
|
+
require 'dir_sync'
|
4
|
+
DirSync.sync *ARGV
|
data/bin/drain
CHANGED
@@ -1,18 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
puts "usage: #{__FILE__} script"
|
6
|
-
exit 1
|
7
|
-
end
|
8
|
-
|
9
|
-
file = ARGV.shift
|
10
|
-
lines = File.readlines(file).map {|s| s.chomp.strip }.select {|s| !s.empty? and !s.start_with?('#')}
|
11
|
-
|
12
|
-
loop do
|
13
|
-
break if lines.empty?
|
14
|
-
lines.shift.tap {|s| puts "> #{s}" }.tap {|s| puts `#{s}` }
|
15
|
-
File.open("#{file}.tmp", 'w') {|f| f.puts lines.join "\n" }
|
16
|
-
`mv #{file}.tmp #{file}`
|
17
|
-
end
|
18
|
-
`rm #{file}`
|
2
|
+
$: << File.dirname(__FILE__)+'/../lib'
|
3
|
+
require 'dir_sync'
|
4
|
+
DirSync.drain *ARGV
|
@@ -0,0 +1,76 @@
|
|
1
|
+
Feature: Synchonising folders
|
2
|
+
As a practical, intelligent and charismatic person
|
3
|
+
I want to synchronise folders
|
4
|
+
So that I can keep multiple backup copies of my work
|
5
|
+
|
6
|
+
Scenario: Syncing two empty directories
|
7
|
+
Given a directory named "a"
|
8
|
+
And a directory named "b"
|
9
|
+
When I successfully run `dir_sync test a b`
|
10
|
+
Then the stdout should contain exactly:
|
11
|
+
"""
|
12
|
+
|
13
|
+
"""
|
14
|
+
|
15
|
+
Scenario: Syncing two non existant directories
|
16
|
+
When I successfully run `dir_sync test a b`
|
17
|
+
Then the stdout should contain exactly:
|
18
|
+
"""
|
19
|
+
|
20
|
+
"""
|
21
|
+
And a directory named "a" should exist
|
22
|
+
And a directory named "b" should exist
|
23
|
+
|
24
|
+
Scenario: Syncing a single file from left to right
|
25
|
+
Given a directory named "a"
|
26
|
+
And I write to "a/readme.txt" with:
|
27
|
+
"""
|
28
|
+
The content
|
29
|
+
"""
|
30
|
+
When I successfully run `dir_sync test a b`
|
31
|
+
Then the stdout should contain exactly:
|
32
|
+
"""
|
33
|
+
cp -p "a/readme.txt" "b/readme.txt"
|
34
|
+
|
35
|
+
"""
|
36
|
+
|
37
|
+
Scenario: Syncing a single file from right to left
|
38
|
+
Given a directory named "b"
|
39
|
+
And I write to "b/readme.txt" with:
|
40
|
+
"""
|
41
|
+
The content
|
42
|
+
"""
|
43
|
+
When I successfully run `dir_sync test a b`
|
44
|
+
Then the stdout should contain exactly:
|
45
|
+
"""
|
46
|
+
cp -p "b/readme.txt" "a/readme.txt"
|
47
|
+
|
48
|
+
"""
|
49
|
+
|
50
|
+
Scenario: Do nothing when files are already in sync with history
|
51
|
+
Given the file system:
|
52
|
+
| path | time |
|
53
|
+
| a/readme.txt | 1000 |
|
54
|
+
| b/readme.txt | 1000 |
|
55
|
+
And past synchronisation history:
|
56
|
+
| path | time |
|
57
|
+
| readme.txt | 1000 |
|
58
|
+
When I successfully run `dir_sync test a b`
|
59
|
+
Then the stdout should contain exactly:
|
60
|
+
"""
|
61
|
+
|
62
|
+
"""
|
63
|
+
|
64
|
+
Scenario: Detecting a deletion from past history
|
65
|
+
Given the file system:
|
66
|
+
| path | time |
|
67
|
+
| b/readme.txt | 1000 |
|
68
|
+
And past synchronisation history:
|
69
|
+
| path | time |
|
70
|
+
| readme.txt | 1000 |
|
71
|
+
When I successfully run `dir_sync test a b`
|
72
|
+
Then the stdout should contain exactly:
|
73
|
+
"""
|
74
|
+
rm "b/readme.txt"
|
75
|
+
|
76
|
+
"""
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Given /^the file system:$/ do |table|
|
2
|
+
`mkdir -p tmp/aruba`
|
3
|
+
Dir.chdir 'tmp/aruba' do
|
4
|
+
table.hashes.each do |row|
|
5
|
+
path, time = row['path'], row['time'].to_i
|
6
|
+
formatted_time = Time.at(time).strftime '%Y%m%d%H%M.%S'
|
7
|
+
`mkdir -p #{File.dirname path}`
|
8
|
+
`touch -t #{formatted_time} #{path}`
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^past synchronisation history:$/ do |table|
|
14
|
+
home = File.expand_path '~'
|
15
|
+
`mkdir #{home}/.dir_sync`
|
16
|
+
File.open("#{home}/.dir_sync/test", 'w') do |f|
|
17
|
+
table.hashes.each do |row|
|
18
|
+
path, time = row['path'], row['time'].to_i
|
19
|
+
f.puts "#{path}:#{time}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
module DirSync
|
2
|
+
end
|
3
|
+
|
4
|
+
class DirSync::HistoryTraverser
|
2
5
|
attr_reader :name, :ts, :base, :description
|
3
6
|
REGEXP = /:(\d+)$/
|
4
7
|
|
@@ -43,4 +46,4 @@ class HistoricalTraverser
|
|
43
46
|
def empty?
|
44
47
|
@description.nil?
|
45
48
|
end
|
46
|
-
end
|
49
|
+
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
|
3
|
-
|
3
|
+
module DirSync
|
4
|
+
end
|
5
|
+
|
6
|
+
class DirSync::Traverser
|
4
7
|
attr_reader :base
|
5
8
|
|
6
9
|
TOLERANCE=5
|
@@ -57,4 +60,4 @@ class Traverser
|
|
57
60
|
def equivalent? traverser
|
58
61
|
name == traverser.name and (ts - traverser.ts).abs <= TOLERANCE
|
59
62
|
end
|
60
|
-
end
|
63
|
+
end
|
data/lib/dir_sync.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'dir_sync/change_log_file_system'
|
2
|
+
require 'dir_sync/traverser'
|
3
|
+
require 'dir_sync/history_traverser'
|
4
|
+
require 'dir_sync/change_resolver'
|
5
|
+
|
6
|
+
module DirSync
|
7
|
+
def self.sync name, *paths
|
8
|
+
if paths.count < 2
|
9
|
+
puts "usage: #{__FILE__} name directory1 directory2 ..."
|
10
|
+
puts " set DEBUG for verbose output"
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
file_system = DirSync::ChangeLogFileSystem.new $stdout
|
14
|
+
traversers = paths.map {|path| DirSync::Traverser.new path, file_system }
|
15
|
+
history = DirSync::HistoryTraverser.new name
|
16
|
+
resolver = DirSync::ChangeResolver.new history, *traversers
|
17
|
+
loop { break unless resolver.iterate }
|
18
|
+
history.close
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.drain *paths
|
22
|
+
if paths.empty?
|
23
|
+
puts "usage: #{__FILE__} *scripts"
|
24
|
+
puts " Runs a set of single line commands one by one (so that you can interrupt and the script will resume)"
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
paths.each do |path|
|
29
|
+
lines = File.readlines(path).map {|s| s.chomp.strip }.select {|s| !s.empty? and !s.start_with?('#')}
|
30
|
+
|
31
|
+
loop do
|
32
|
+
break if lines.empty?
|
33
|
+
lines.shift.tap {|s| puts "> #{s}" }.tap {|s| puts `#{s}` }
|
34
|
+
File.open("#{path}.tmp", 'w') {|f| f.puts lines.join "\n" }
|
35
|
+
`mv #{path}.tmp #{path}`
|
36
|
+
end
|
37
|
+
`rm #{path}`
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$: << File.dirname(__FILE__)+'/../lib'
|
2
|
+
|
3
|
+
require 'dir_sync/change_log_file_system'
|
4
|
+
|
5
|
+
describe DirSync::ChangeLogFileSystem do
|
6
|
+
let(:io) { stub 'io' }
|
7
|
+
let(:file_system) { DirSync::ChangeLogFileSystem.new io }
|
8
|
+
|
9
|
+
it 'should cp a file' do
|
10
|
+
io.should_receive(:puts).with 'cp -p "from" "to"'
|
11
|
+
file_system.cp 'from', 'to'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should mkdir for cp when parent does not exist' do
|
15
|
+
io.should_receive(:puts).with 'mkdir -p "a/b/c"'
|
16
|
+
io.should_receive(:puts).with 'cp -p "from" "a/b/c/to"'
|
17
|
+
file_system.cp 'from', 'a/b/c/to'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should rm a file' do
|
21
|
+
io.should_receive(:puts).with 'rm "file"'
|
22
|
+
file_system.rm 'file'
|
23
|
+
end
|
24
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
$: << File.dirname(__FILE__)+'/../lib'
|
2
2
|
|
3
|
-
require 'change_resolver'
|
3
|
+
require 'dir_sync/change_resolver'
|
4
4
|
|
5
|
-
describe ChangeResolver do
|
5
|
+
describe DirSync::ChangeResolver do
|
6
6
|
let(:history) { stub 'history', name: nil, base: nil, description: nil, report: nil, advance: nil }
|
7
7
|
let(:traversers) { [] }
|
8
|
-
let(:resolver) { ChangeResolver.new history, *traversers }
|
8
|
+
let(:resolver) { DirSync::ChangeResolver.new history, *traversers }
|
9
9
|
|
10
10
|
def stub_history hash
|
11
11
|
hash.each do |meth,ret|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$: << File.dirname(__FILE__)+'/../lib'
|
2
|
+
|
3
|
+
require 'dir_sync/history_traverser'
|
4
|
+
|
5
|
+
describe DirSync::HistoryTraverser do
|
6
|
+
let(:dir_sync_path) { stub 'dir_sync_path', mkpath: nil }
|
7
|
+
let(:new_path) { stub 'new_path' }
|
8
|
+
let(:traverser) { DirSync::HistoryTraverser.new 'test' }
|
9
|
+
|
10
|
+
before do
|
11
|
+
File.stub!(:expand_path).with('~').and_return '/home/user'
|
12
|
+
Pathname.stub!(:new).with('/home/user/.dir_sync').and_return dir_sync_path
|
13
|
+
File.stub!(:open).with('/home/user/.dir_sync/test.new', 'w').and_return new_path
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should create the ~/.dir_sync directory' do
|
17
|
+
dir_sync_path.should_receive :mkpath
|
18
|
+
traverser
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should open the new file for capturing new state' do
|
22
|
+
File.should_receive(:open).with '/home/user/.dir_sync/test.new', 'w'
|
23
|
+
traverser
|
24
|
+
end
|
25
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
$: << File.dirname(__FILE__)+'/../lib'
|
2
2
|
|
3
|
-
require 'traverser'
|
3
|
+
require 'dir_sync/traverser'
|
4
4
|
|
5
|
-
describe Traverser do
|
5
|
+
describe DirSync::Traverser do
|
6
6
|
let(:pathname) { stub 'pathname', mkpath: nil, find: nil}
|
7
7
|
let(:file_system) { stub 'file_system'}
|
8
|
-
let(:traverser) { Traverser.new 'a', file_system }
|
8
|
+
let(:traverser) { DirSync::Traverser.new 'a', file_system }
|
9
9
|
|
10
10
|
before do
|
11
11
|
Pathname.should_receive(:new).with('a').and_return pathname
|
@@ -55,4 +55,4 @@ describe Traverser do
|
|
55
55
|
file_system.should_receive(:cp).with 'a/1.txt', 'b/1.txt'
|
56
56
|
traverser.cp other_traverser
|
57
57
|
end
|
58
|
-
end
|
58
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
$: << File.dirname(__FILE__)+'/../lib'
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'dir_sync'
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe DirSync do
|
6
6
|
let(:file_system) { stub 'file_system' }
|
7
7
|
let(:resolver) { stub 'resolver'}
|
8
8
|
let(:history) { stub 'history', close: nil }
|
@@ -10,22 +10,22 @@ describe Synchroniser do
|
|
10
10
|
let(:traverser_b) { stub 'traverser_b' }
|
11
11
|
|
12
12
|
before do
|
13
|
-
ChangeLogFileSystem.should_receive(:new).with($stdout).and_return file_system
|
14
|
-
|
15
|
-
Traverser.should_receive(:new).with('a', file_system).and_return traverser_a
|
16
|
-
Traverser.should_receive(:new).with('b', file_system).and_return traverser_b
|
17
|
-
ChangeResolver.should_receive(:new).with(history, traverser_a, traverser_b).and_return resolver
|
13
|
+
DirSync::ChangeLogFileSystem.should_receive(:new).with($stdout).and_return file_system
|
14
|
+
DirSync::HistoryTraverser.should_receive(:new).with('test').and_return history
|
15
|
+
DirSync::Traverser.should_receive(:new).with('a', file_system).and_return traverser_a
|
16
|
+
DirSync::Traverser.should_receive(:new).with('b', file_system).and_return traverser_b
|
17
|
+
DirSync::ChangeResolver.should_receive(:new).with(history, traverser_a, traverser_b).and_return resolver
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should call iterate once resolved if it returns false' do
|
21
21
|
resolver.should_receive(:iterate).and_return false
|
22
|
-
|
22
|
+
DirSync.sync 'test', 'a', 'b'
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'should repeatedly call iterate on resolved until it returns false' do
|
26
26
|
resolver.should_receive(:iterate).and_return true
|
27
27
|
resolver.should_receive(:iterate).and_return true
|
28
28
|
resolver.should_receive(:iterate).and_return false
|
29
|
-
|
29
|
+
DirSync.sync 'test', 'a', 'b'
|
30
30
|
end
|
31
|
-
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dir_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Mark Ryall
|
9
|
+
- James Ottaway
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
13
|
+
date: 2012-01-29 00:00:00.000000000Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: rake
|
16
|
-
requirement: &
|
17
|
+
requirement: &70170387871540 !ruby/object:Gem::Requirement
|
17
18
|
none: false
|
18
19
|
requirements:
|
19
20
|
- - ~>
|
@@ -21,10 +22,10 @@ dependencies:
|
|
21
22
|
version: '0'
|
22
23
|
type: :development
|
23
24
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
+
version_requirements: *70170387871540
|
25
26
|
- !ruby/object:Gem::Dependency
|
26
27
|
name: rspec
|
27
|
-
requirement: &
|
28
|
+
requirement: &70170387870300 !ruby/object:Gem::Requirement
|
28
29
|
none: false
|
29
30
|
requirements:
|
30
31
|
- - ~>
|
@@ -32,10 +33,10 @@ dependencies:
|
|
32
33
|
version: '2'
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
+
version_requirements: *70170387870300
|
36
37
|
- !ruby/object:Gem::Dependency
|
37
38
|
name: guard
|
38
|
-
requirement: &
|
39
|
+
requirement: &70170387869340 !ruby/object:Gem::Requirement
|
39
40
|
none: false
|
40
41
|
requirements:
|
41
42
|
- - ! '>='
|
@@ -43,10 +44,10 @@ dependencies:
|
|
43
44
|
version: '0'
|
44
45
|
type: :development
|
45
46
|
prerelease: false
|
46
|
-
version_requirements: *
|
47
|
+
version_requirements: *70170387869340
|
47
48
|
- !ruby/object:Gem::Dependency
|
48
49
|
name: guard-rspec
|
49
|
-
requirement: &
|
50
|
+
requirement: &70170387868340 !ruby/object:Gem::Requirement
|
50
51
|
none: false
|
51
52
|
requirements:
|
52
53
|
- - ! '>='
|
@@ -54,10 +55,21 @@ dependencies:
|
|
54
55
|
version: '0'
|
55
56
|
type: :development
|
56
57
|
prerelease: false
|
57
|
-
version_requirements: *
|
58
|
+
version_requirements: *70170387868340
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: growl
|
61
|
+
requirement: &70170387867260 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *70170387867260
|
58
70
|
- !ruby/object:Gem::Dependency
|
59
71
|
name: aruba
|
60
|
-
requirement: &
|
72
|
+
requirement: &70170387866340 !ruby/object:Gem::Requirement
|
61
73
|
none: false
|
62
74
|
requirements:
|
63
75
|
- - ! '>='
|
@@ -65,8 +77,8 @@ dependencies:
|
|
65
77
|
version: '0'
|
66
78
|
type: :development
|
67
79
|
prerelease: false
|
68
|
-
version_requirements: *
|
69
|
-
description: ! '
|
80
|
+
version_requirements: *70170387866340
|
81
|
+
description: ! 'Multidirectional directory synchronisation for any number of directories
|
70
82
|
|
71
83
|
'
|
72
84
|
email: mark@ryall.name
|
@@ -76,21 +88,26 @@ executables:
|
|
76
88
|
extensions: []
|
77
89
|
extra_rdoc_files: []
|
78
90
|
files:
|
79
|
-
- lib/change_log_file_system.rb
|
80
|
-
- lib/change_resolver.rb
|
81
|
-
- lib/historical_traverser.rb
|
82
|
-
- lib/synchroniser.rb
|
83
|
-
- lib/traverser.rb
|
84
|
-
- spec/change_resolver_spec.rb
|
85
|
-
- spec/synchroniser_spec.rb
|
86
|
-
- spec/traverser_spec.rb
|
87
91
|
- bin/dir_sync
|
88
92
|
- bin/drain
|
89
|
-
-
|
90
|
-
-
|
93
|
+
- features/backup.feature
|
94
|
+
- features/step_definitions/dir_sync_steps.rb
|
95
|
+
- features/support/env.rb
|
96
|
+
- lib/dir_sync/change_log_file_system.rb
|
97
|
+
- lib/dir_sync/change_resolver.rb
|
98
|
+
- lib/dir_sync/history_traverser.rb
|
99
|
+
- lib/dir_sync/traverser.rb
|
100
|
+
- lib/dir_sync.rb
|
101
|
+
- spec/dir_sync/change_log_file_system_spec.rb
|
102
|
+
- spec/dir_sync/change_resolver_spec.rb
|
103
|
+
- spec/dir_sync/history_traverser_spec.rb
|
104
|
+
- spec/dir_sync/traverser_spec.rb
|
105
|
+
- spec/dir_sync_spec.rb
|
106
|
+
- .gemtest
|
91
107
|
- HISTORY.rdoc
|
108
|
+
- MIT-LICENSE
|
92
109
|
- Rakefile
|
93
|
-
- .
|
110
|
+
- README.rdoc
|
94
111
|
homepage: http://github.com/markryall/dir_sync
|
95
112
|
licenses: []
|
96
113
|
post_install_message:
|
@@ -102,10 +119,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
102
119
|
requirements:
|
103
120
|
- - ! '>='
|
104
121
|
- !ruby/object:Gem::Version
|
105
|
-
version: '
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
hash: -2227443201844382087
|
122
|
+
version: '1.9'
|
109
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
124
|
none: false
|
111
125
|
requirements:
|
@@ -114,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
128
|
version: '0'
|
115
129
|
segments:
|
116
130
|
- 0
|
117
|
-
hash: -
|
131
|
+
hash: -3613376495215102755
|
118
132
|
requirements: []
|
119
133
|
rubyforge_project:
|
120
134
|
rubygems_version: 1.8.10
|
data/lib/synchroniser.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'traverser'
|
2
|
-
require 'historical_traverser'
|
3
|
-
require 'change_resolver'
|
4
|
-
require 'change_log_file_system'
|
5
|
-
|
6
|
-
module Synchroniser
|
7
|
-
def self.iterate name, *paths
|
8
|
-
file_system = ChangeLogFileSystem.new $stdout
|
9
|
-
traversers = paths.map {|path| Traverser.new path, file_system }
|
10
|
-
history = HistoricalTraverser.new name
|
11
|
-
resolver = ChangeResolver.new history, *traversers
|
12
|
-
loop { break unless resolver.iterate }
|
13
|
-
history.close
|
14
|
-
end
|
15
|
-
end
|