Skip to content

Commit 31e8416

Browse files
committed
Workingish version.
1 parent 99ef9e7 commit 31e8416

File tree

7 files changed

+287
-4
lines changed

7 files changed

+287
-4
lines changed

Rakefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
require "bundler/gem_tasks"
2+
require 'rspec/core/rake_task'
3+
4+
RSpec::Core::RakeTask.new(:spec)

lib/rsync.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
require "rsync/version"
2+
require "rsync/command"
3+
require "rsync/result"
24

35
module Rsync
4-
# Your code goes here...
6+
def self.command(args = [], &block)
7+
output = Command.new(args).run
8+
exitcode = $?
9+
result = Result.new(output, exitcode)
10+
yield(result) if block_given?
11+
result
12+
end
513
end

lib/rsync/change.rb

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
module Rsync
2+
class Change
3+
include Enumerable
4+
5+
def initialize(raw)
6+
@raw = raw
7+
end
8+
9+
def each(&block)
10+
@raw.split("\n").each do |line|
11+
#if line =~ /^([<>ch.*][fdLDS][ .+\?cstTpoguax]{9}) (.*)$/
12+
if line =~ /^([<>ch.\*].{10}) (.*)$/
13+
detail = Detail.new(line)
14+
yield(detail) if detail.changed?
15+
end
16+
end
17+
end
18+
19+
class Detail
20+
def initialize(raw)
21+
@raw = raw
22+
end
23+
24+
def filename
25+
@raw[12..-1]
26+
end
27+
28+
def changed?
29+
if update_type == :message
30+
return true
31+
elsif update_type == :recv
32+
return true
33+
end
34+
false
35+
end
36+
37+
def summary
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
53+
54+
def message
55+
@raw[1..10].strip
56+
end
57+
58+
def raw_update_type
59+
@raw[0]
60+
end
61+
62+
def raw_file_type
63+
@raw[1]
64+
end
65+
66+
def attribute_prop(index)
67+
case @raw[index]
68+
when '.'
69+
:no_change
70+
when ' '
71+
:identical
72+
when '+'
73+
:new
74+
when '?'
75+
:unknown
76+
else
77+
:changed
78+
end
79+
end
80+
81+
def checksum
82+
attribute_prop(2)
83+
end
84+
85+
def size
86+
attribute_prop(3)
87+
end
88+
89+
def timestamp
90+
attribute_prop(4)
91+
end
92+
93+
def permissions
94+
attribute_prop(5)
95+
end
96+
97+
def owner
98+
attribute_prop(6)
99+
end
100+
101+
def group
102+
attribute_prop(7)
103+
end
104+
105+
def acl
106+
attribute_prop(9)
107+
end
108+
109+
def ext_attr
110+
attribute_prop(10)
111+
end
112+
113+
def update_type
114+
case raw_update_type
115+
when '<'
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
129+
130+
def file_type
131+
case raw_file_type
132+
when 'f'
133+
:file
134+
when 'd'
135+
:directory
136+
when 'L'
137+
:symlink
138+
when 'D'
139+
:device
140+
when 'S'
141+
:special
142+
end
143+
end
144+
end
145+
end
146+
end

lib/rsync/command.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module Rsync
2+
class Command
3+
def initialize(args)
4+
@args = args.join(" ")
5+
end
6+
7+
def run
8+
run_command("rsync --itemize-changes #{@args}")
9+
end
10+
11+
def run_command(cmd, &block)
12+
if block_given?
13+
IO.popen("#{cmd} 2>&1", &block)
14+
else
15+
`#{cmd} 2>&1`
16+
end
17+
end
18+
end
19+
end

lib/rsync/result.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
require 'rsync/change'
2+
3+
module Rsync
4+
class Result
5+
def initialize(raw, exitcode)
6+
@raw = raw
7+
@exitcode = exitcode
8+
end
9+
10+
def success?
11+
@exitcode.to_i == 0
12+
end
13+
14+
def error
15+
case @exitcode.exitstatus
16+
when 0
17+
"Success"
18+
when 1
19+
"Syntax or usage error"
20+
when 2
21+
"Protocol incompatibility"
22+
when 3
23+
"Errors selecting input/output files, dirs"
24+
when 4
25+
"Requested action not supported: an attempt was made to manipulate 64-bit files on a platform that can not support them; or an option was specified that is supported by the client and not by the server."
26+
when 5
27+
"Error starting client-server protocol"
28+
when 6
29+
"Daemon unable to append to log-file"
30+
when 10
31+
"Error in socket I/O"
32+
when 11
33+
"Error in file I/O"
34+
when 12
35+
"Error in rsync protocol data stream"
36+
when 13
37+
"Errors with program diagnostics"
38+
when 14
39+
"Error in IPC code"
40+
when 20
41+
"Received SIGUSR1 or SIGINT"
42+
when 21
43+
"Some error returned by waitpid()"
44+
when 22
45+
"Error allocating core memory buffers"
46+
when 23
47+
"Partial transfer due to error"
48+
when 24
49+
"Partial transfer due to vanished source files"
50+
when 25
51+
"The --max-delete limit stopped deletions"
52+
when 30
53+
"Timeout in data send/receive"
54+
when 35
55+
"Timeout waiting for daemon connection"
56+
else
57+
"Unknown Error"
58+
end
59+
end
60+
61+
def changes
62+
Change.new(@raw)
63+
end
64+
end
65+
end

rsync.gemspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ Gem::Specification.new do |spec|
88
spec.version = Rsync::VERSION
99
spec.authors = ["Joshua Bussdieker"]
1010
spec.email = ["[email protected]"]
11-
spec.description = %q{TODO: Write a gem description}
12-
spec.summary = %q{TODO: Write a gem summary}
13-
spec.homepage = ""
11+
spec.summary = %q{Ruby/Rsync is a Ruby library that can syncronize files between remote hosts by wrapping a call to the rsync binary.}
12+
spec.homepage = "http://github.com/jbussdieker/ruby-rsync"
1413
spec.license = "MIT"
1514

1615
spec.files = `git ls-files`.split($/)
@@ -20,4 +19,5 @@ Gem::Specification.new do |spec|
2019

2120
spec.add_development_dependency "bundler", "~> 1.3"
2221
spec.add_development_dependency "rake"
22+
spec.add_development_dependency "rspec"
2323
end

spec/rsync/change_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require 'rsync/change'
2+
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+
it "should handle filename" do
11+
Rsync::Change::Detail.new(" filename").filename.should eql("filename")
12+
end
13+
14+
it "should handle message type" do
15+
Rsync::Change::Detail.new("*deleting ").message.should eql("deleting")
16+
end
17+
18+
it "should handle update types" do
19+
Rsync::Change::Detail.new("< ").update_type.should eql(:sent)
20+
Rsync::Change::Detail.new("> ").update_type.should eql(:recv)
21+
Rsync::Change::Detail.new("c ").update_type.should eql(:change)
22+
Rsync::Change::Detail.new("h ").update_type.should eql(:hard_link)
23+
Rsync::Change::Detail.new(". ").update_type.should eql(:no_update)
24+
Rsync::Change::Detail.new("* ").update_type.should eql(:message)
25+
end
26+
27+
it "should handle file types" do
28+
Rsync::Change::Detail.new(" f ").file_type.should eql(:file)
29+
Rsync::Change::Detail.new(" d ").file_type.should eql(:directory)
30+
Rsync::Change::Detail.new(" L ").file_type.should eql(:symlink)
31+
Rsync::Change::Detail.new(" D ").file_type.should eql(:device)
32+
Rsync::Change::Detail.new(" S ").file_type.should eql(:special)
33+
end
34+
35+
it "should handle checksum info" do
36+
Rsync::Change::Detail.new(" c ").checksum.should eql(:changed)
37+
Rsync::Change::Detail.new(" . ").checksum.should eql(:no_change)
38+
Rsync::Change::Detail.new(" ").checksum.should eql(:identical)
39+
Rsync::Change::Detail.new(" + ").checksum.should eql(:new)
40+
Rsync::Change::Detail.new(" ? ").checksum.should eql(:unknown)
41+
end
42+
end

0 commit comments

Comments
 (0)