rsync 0.0.1 → 0.0.2
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.
- data/README.md +2 -0
- data/lib/rsync.rb +5 -1
- data/lib/rsync/change.rb +154 -115
- data/lib/rsync/command.rb +6 -0
- data/lib/rsync/result.rb +18 -1
- data/lib/rsync/version.rb +2 -1
- data/spec/rsync/change_spec.rb +18 -24
- metadata +48 -73
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Rsync
|
2
2
|
|
3
3
|
[](https://travis-ci.org/jbussdieker/ruby-rsync)
|
4
|
+
[](https://codeclimate.com/github/jbussdieker/ruby-rsync)
|
5
|
+
[](http://badge.fury.io/rb/rsync)
|
4
6
|
|
5
7
|
Ruby/Rsync is a Ruby library that can syncronize files between remote hosts by wrapping a call to the rsync binary.
|
6
8
|
|
data/lib/rsync.rb
CHANGED
@@ -2,8 +2,12 @@ require "rsync/version"
|
|
2
2
|
require "rsync/command"
|
3
3
|
require "rsync/result"
|
4
4
|
|
5
|
+
# The main interface to rsync
|
5
6
|
module Rsync
|
6
|
-
|
7
|
+
# Creates and runs an rsync {Command} and return the {Result}
|
8
|
+
# @return {Result}
|
9
|
+
# @yield {Result}
|
10
|
+
def self.command(args, &block)
|
7
11
|
output = Command.new(args).run
|
8
12
|
exitcode = $?
|
9
13
|
result = Result.new(output, exitcode)
|
data/lib/rsync/change.rb
CHANGED
@@ -1,146 +1,185 @@
|
|
1
1
|
module Rsync
|
2
|
+
# Provides details about changes made to a specific file.
|
3
|
+
#
|
4
|
+
# Change Flags:
|
5
|
+
#
|
6
|
+
# :no_change
|
7
|
+
# :identical
|
8
|
+
# :new
|
9
|
+
# :unknown
|
10
|
+
# :changed
|
2
11
|
class Change
|
3
|
-
|
4
|
-
|
5
|
-
def initialize(raw)
|
6
|
-
@raw = raw
|
12
|
+
def initialize(data)
|
13
|
+
@data = data
|
7
14
|
end
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
detail = Detail.new(line)
|
14
|
-
yield(detail) if detail.changed?
|
15
|
-
end
|
16
|
-
end
|
16
|
+
# The filename associated with this change.
|
17
|
+
# @return [String]
|
18
|
+
def filename
|
19
|
+
@data[12..-1]
|
17
20
|
end
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
# Whether the file was changed or not.
|
23
|
+
# @return [Boolean]
|
24
|
+
def changed?
|
25
|
+
if update_type == :message
|
26
|
+
return true
|
27
|
+
elsif update_type == :recv
|
28
|
+
return true
|
26
29
|
end
|
30
|
+
false
|
31
|
+
end
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
+
# Simple description of the change.
|
34
|
+
# @return [String]
|
35
|
+
def summary
|
36
|
+
if update_type == :message
|
37
|
+
message
|
38
|
+
elsif update_type == :recv and @data[2,9] == "+++++++++"
|
39
|
+
"creating"
|
40
|
+
elsif update_type == :recv
|
41
|
+
"updating"
|
42
|
+
else
|
43
|
+
changes = []
|
44
|
+
#[:checksum, :size, :timestamp, :permissions, :owner, :group, :acl].each do |prop|
|
45
|
+
[:checksum, :size, :permissions, :owner, :group, :acl].each do |prop|
|
46
|
+
changes << prop if send(prop) == :changed
|
33
47
|
end
|
34
|
-
|
48
|
+
changes.join(", ")
|
35
49
|
end
|
50
|
+
end
|
36
51
|
|
37
|
-
|
38
|
-
if update_type == :message
|
39
|
-
message
|
40
|
-
elsif update_type == :recv and @raw[2,9] == "+++++++++"
|
41
|
-
"creating"
|
42
|
-
elsif update_type == :recv
|
43
|
-
"updating"
|
44
|
-
else
|
45
|
-
changes = []
|
46
|
-
#[:checksum, :size, :timestamp, :permissions, :owner, :group, :acl].each do |prop|
|
47
|
-
[:checksum, :size, :permissions, :owner, :group, :acl].each do |prop|
|
48
|
-
changes << prop if send(prop) == :changed
|
49
|
-
end
|
50
|
-
changes.join(", ")
|
51
|
-
end
|
52
|
-
end
|
52
|
+
# @!group Change Flags
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
# The change, if any, to the checksum of the file.
|
55
|
+
# @return [Symbol]
|
56
|
+
def checksum
|
57
|
+
attribute_prop(2)
|
58
|
+
end
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
60
|
+
# The change, if any, to the size of the file.
|
61
|
+
# @return [Symbol]
|
62
|
+
def size
|
63
|
+
attribute_prop(3)
|
64
|
+
end
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
|
66
|
+
# The change, if any, to the timestamp of the file.
|
67
|
+
# @return [Symbol]
|
68
|
+
def timestamp
|
69
|
+
attribute_prop(4)
|
70
|
+
end
|
65
71
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
:identical
|
72
|
-
when '+'
|
73
|
-
:new
|
74
|
-
when '?'
|
75
|
-
:unknown
|
76
|
-
else
|
77
|
-
:changed
|
78
|
-
end
|
79
|
-
end
|
72
|
+
# The change, if any, to the file permissions.
|
73
|
+
# @return [Symbol]
|
74
|
+
def permissions
|
75
|
+
attribute_prop(5)
|
76
|
+
end
|
80
77
|
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
# The change, if any, to the owner of the file.
|
79
|
+
# @return [Symbol]
|
80
|
+
def owner
|
81
|
+
attribute_prop(6)
|
82
|
+
end
|
84
83
|
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
# The change, if any, to the group of the file.
|
85
|
+
# @return [Symbol]
|
86
|
+
def group
|
87
|
+
attribute_prop(7)
|
88
|
+
end
|
88
89
|
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
# The change, if any, to the file ACL.
|
91
|
+
# @return [Symbol]
|
92
|
+
def acl
|
93
|
+
attribute_prop(9)
|
94
|
+
end
|
92
95
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
+
# The change, if any, to the file's extended attributes.
|
97
|
+
# @return [Symbol]
|
98
|
+
def ext_attr
|
99
|
+
attribute_prop(10)
|
100
|
+
end
|
96
101
|
|
97
|
-
|
98
|
-
|
102
|
+
# @!endgroup
|
103
|
+
|
104
|
+
# The type of update made to the file.
|
105
|
+
#
|
106
|
+
# :sent
|
107
|
+
# :recv
|
108
|
+
# :change
|
109
|
+
# :hard_link
|
110
|
+
# :no_update
|
111
|
+
# :message
|
112
|
+
#
|
113
|
+
# @return [Symbol]
|
114
|
+
def update_type
|
115
|
+
case raw_update_type
|
116
|
+
when '<'
|
117
|
+
:sent
|
118
|
+
when '>'
|
119
|
+
:recv
|
120
|
+
when 'c'
|
121
|
+
:change
|
122
|
+
when 'h'
|
123
|
+
:hard_link
|
124
|
+
when '.'
|
125
|
+
:no_update
|
126
|
+
when '*'
|
127
|
+
:message
|
99
128
|
end
|
129
|
+
end
|
100
130
|
|
101
|
-
|
102
|
-
|
131
|
+
# The type of file.
|
132
|
+
#
|
133
|
+
# :file
|
134
|
+
# :directory
|
135
|
+
# :symlink
|
136
|
+
# :device
|
137
|
+
# :special
|
138
|
+
#
|
139
|
+
# @return [Symbol]
|
140
|
+
def file_type
|
141
|
+
case raw_file_type
|
142
|
+
when 'f'
|
143
|
+
:file
|
144
|
+
when 'd'
|
145
|
+
:directory
|
146
|
+
when 'L'
|
147
|
+
:symlink
|
148
|
+
when 'D'
|
149
|
+
:device
|
150
|
+
when 'S'
|
151
|
+
:special
|
103
152
|
end
|
153
|
+
end
|
104
154
|
|
105
|
-
|
106
|
-
attribute_prop(9)
|
107
|
-
end
|
155
|
+
private
|
108
156
|
|
109
|
-
|
110
|
-
|
111
|
-
|
157
|
+
def message
|
158
|
+
@data[1..10].strip
|
159
|
+
end
|
112
160
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
:sent
|
117
|
-
when '>'
|
118
|
-
:recv
|
119
|
-
when 'c'
|
120
|
-
:change
|
121
|
-
when 'h'
|
122
|
-
:hard_link
|
123
|
-
when '.'
|
124
|
-
:no_update
|
125
|
-
when '*'
|
126
|
-
:message
|
127
|
-
end
|
128
|
-
end
|
161
|
+
def raw_update_type
|
162
|
+
@data[0,1]
|
163
|
+
end
|
129
164
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
165
|
+
def raw_file_type
|
166
|
+
@data[1,1]
|
167
|
+
end
|
168
|
+
|
169
|
+
def attribute_prop(index)
|
170
|
+
case @data[index,1]
|
171
|
+
when '.'
|
172
|
+
:no_change
|
173
|
+
when ' '
|
174
|
+
:identical
|
175
|
+
when '+'
|
176
|
+
:new
|
177
|
+
when '?'
|
178
|
+
:unknown
|
179
|
+
else
|
180
|
+
:changed
|
143
181
|
end
|
144
182
|
end
|
183
|
+
|
145
184
|
end
|
146
185
|
end
|
data/lib/rsync/command.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
module Rsync
|
2
|
+
# An rsync command to be run
|
2
3
|
class Command
|
3
4
|
def initialize(args)
|
4
5
|
@args = args.join(" ")
|
5
6
|
end
|
6
7
|
|
8
|
+
# Runs the rsync job and returns the results
|
9
|
+
#
|
10
|
+
# @return {Result}
|
7
11
|
def run
|
8
12
|
run_command("rsync --itemize-changes #{@args}")
|
9
13
|
end
|
10
14
|
|
15
|
+
private
|
16
|
+
|
11
17
|
def run_command(cmd, &block)
|
12
18
|
if block_given?
|
13
19
|
IO.popen("#{cmd} 2>&1", &block)
|
data/lib/rsync/result.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
require 'rsync/change'
|
2
2
|
|
3
3
|
module Rsync
|
4
|
+
# The result of a sync.
|
4
5
|
class Result
|
6
|
+
# @!visibility private
|
5
7
|
def initialize(raw, exitcode)
|
6
8
|
@raw = raw
|
7
9
|
@exitcode = exitcode
|
8
10
|
end
|
9
11
|
|
12
|
+
# Whether the rsync job was run without errors.
|
13
|
+
# @return Boolean
|
10
14
|
def success?
|
11
15
|
@exitcode.to_i == 0
|
12
16
|
end
|
13
17
|
|
18
|
+
# The error message based on exit code.
|
19
|
+
# @return String
|
14
20
|
def error
|
15
21
|
case @exitcode.exitstatus
|
16
22
|
when 0
|
@@ -58,8 +64,19 @@ module Rsync
|
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
67
|
+
# List of changes made during this run.
|
68
|
+
#
|
69
|
+
# @return {Array<Change>}
|
61
70
|
def changes
|
62
|
-
|
71
|
+
list = []
|
72
|
+
@raw.split("\n").each do |line|
|
73
|
+
#if line =~ /^([<>ch.*][fdLDS][ .+\?cstTpoguax]{9}) (.*)$/
|
74
|
+
if line =~ /^([<>ch.\*].{10}) (.*)$/
|
75
|
+
detail = Change.new(line)
|
76
|
+
list << detail if detail.changed?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
list
|
63
80
|
end
|
64
81
|
end
|
65
82
|
end
|
data/lib/rsync/version.rb
CHANGED
data/spec/rsync/change_spec.rb
CHANGED
@@ -1,42 +1,36 @@
|
|
1
1
|
require 'rsync/change'
|
2
2
|
|
3
3
|
describe Rsync::Change do
|
4
|
-
it "should handle example" do
|
5
|
-
Rsync::Change.new(".f blah2.txt")
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
describe Rsync::Change::Detail do
|
10
4
|
it "should handle filename" do
|
11
|
-
Rsync::Change
|
5
|
+
Rsync::Change.new(" filename").filename.should eql("filename")
|
12
6
|
end
|
13
7
|
|
14
8
|
it "should handle message type" do
|
15
|
-
Rsync::Change
|
9
|
+
Rsync::Change.new("*deleting ").summary.should eql("deleting")
|
16
10
|
end
|
17
11
|
|
18
12
|
it "should handle update types" do
|
19
|
-
Rsync::Change
|
20
|
-
Rsync::Change
|
21
|
-
Rsync::Change
|
22
|
-
Rsync::Change
|
23
|
-
Rsync::Change
|
24
|
-
Rsync::Change
|
13
|
+
Rsync::Change.new("< ").update_type.should eql(:sent)
|
14
|
+
Rsync::Change.new("> ").update_type.should eql(:recv)
|
15
|
+
Rsync::Change.new("c ").update_type.should eql(:change)
|
16
|
+
Rsync::Change.new("h ").update_type.should eql(:hard_link)
|
17
|
+
Rsync::Change.new(". ").update_type.should eql(:no_update)
|
18
|
+
Rsync::Change.new("* ").update_type.should eql(:message)
|
25
19
|
end
|
26
20
|
|
27
21
|
it "should handle file types" do
|
28
|
-
Rsync::Change
|
29
|
-
Rsync::Change
|
30
|
-
Rsync::Change
|
31
|
-
Rsync::Change
|
32
|
-
Rsync::Change
|
22
|
+
Rsync::Change.new(" f ").file_type.should eql(:file)
|
23
|
+
Rsync::Change.new(" d ").file_type.should eql(:directory)
|
24
|
+
Rsync::Change.new(" L ").file_type.should eql(:symlink)
|
25
|
+
Rsync::Change.new(" D ").file_type.should eql(:device)
|
26
|
+
Rsync::Change.new(" S ").file_type.should eql(:special)
|
33
27
|
end
|
34
28
|
|
35
29
|
it "should handle checksum info" do
|
36
|
-
Rsync::Change
|
37
|
-
Rsync::Change
|
38
|
-
Rsync::Change
|
39
|
-
Rsync::Change
|
40
|
-
Rsync::Change
|
30
|
+
Rsync::Change.new(" c ").checksum.should eql(:changed)
|
31
|
+
Rsync::Change.new(" . ").checksum.should eql(:no_change)
|
32
|
+
Rsync::Change.new(" ").checksum.should eql(:identical)
|
33
|
+
Rsync::Change.new(" + ").checksum.should eql(:new)
|
34
|
+
Rsync::Change.new(" ? ").checksum.should eql(:unknown)
|
41
35
|
end
|
42
36
|
end
|
metadata
CHANGED
@@ -1,75 +1,56 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsync
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 1
|
10
|
-
version: 0.0.1
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Joshua Bussdieker
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-07-24 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: bundler
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &7909780 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
18
|
+
requirements:
|
26
19
|
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
segments:
|
30
|
-
- 1
|
31
|
-
- 3
|
32
|
-
version: "1.3"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
33
22
|
type: :development
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: rake
|
37
23
|
prerelease: false
|
38
|
-
|
24
|
+
version_requirements: *7909780
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &7909000 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
version: "0"
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
47
33
|
type: :development
|
48
|
-
version_requirements: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: rspec
|
51
34
|
prerelease: false
|
52
|
-
|
35
|
+
version_requirements: *7909000
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &7908040 !ruby/object:Gem::Requirement
|
53
39
|
none: false
|
54
|
-
requirements:
|
55
|
-
- -
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
segments:
|
59
|
-
- 0
|
60
|
-
version: "0"
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
61
44
|
type: :development
|
62
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *7908040
|
63
47
|
description:
|
64
|
-
email:
|
48
|
+
email:
|
65
49
|
- jbussdieker@gmail.com
|
66
50
|
executables: []
|
67
|
-
|
68
51
|
extensions: []
|
69
|
-
|
70
52
|
extra_rdoc_files: []
|
71
|
-
|
72
|
-
files:
|
53
|
+
files:
|
73
54
|
- .gitignore
|
74
55
|
- .travis.yml
|
75
56
|
- Gemfile
|
@@ -84,37 +65,31 @@ files:
|
|
84
65
|
- rsync.gemspec
|
85
66
|
- spec/rsync/change_spec.rb
|
86
67
|
homepage: http://github.com/jbussdieker/ruby-rsync
|
87
|
-
licenses:
|
68
|
+
licenses:
|
88
69
|
- MIT
|
89
70
|
post_install_message:
|
90
71
|
rdoc_options: []
|
91
|
-
|
92
|
-
require_paths:
|
72
|
+
require_paths:
|
93
73
|
- lib
|
94
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
75
|
none: false
|
96
|
-
requirements:
|
97
|
-
- -
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
|
100
|
-
|
101
|
-
- 0
|
102
|
-
version: "0"
|
103
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
81
|
none: false
|
105
|
-
requirements:
|
106
|
-
- -
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
|
109
|
-
segments:
|
110
|
-
- 0
|
111
|
-
version: "0"
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
112
86
|
requirements: []
|
113
|
-
|
114
87
|
rubyforge_project:
|
115
|
-
rubygems_version: 1.8.
|
88
|
+
rubygems_version: 1.8.17
|
116
89
|
signing_key:
|
117
90
|
specification_version: 3
|
118
|
-
summary: Ruby/Rsync is a Ruby library that can syncronize files between remote hosts
|
119
|
-
|
91
|
+
summary: Ruby/Rsync is a Ruby library that can syncronize files between remote hosts
|
92
|
+
by wrapping a call to the rsync binary.
|
93
|
+
test_files:
|
120
94
|
- spec/rsync/change_spec.rb
|
95
|
+
has_rdoc:
|