rsync-adhoc 0.0.1.a.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Simon Menke
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,9 @@
1
+ rsync-adhoc(7) -- semi automatic deployment of rails applications
2
+ ===============================================================
3
+
4
+ ## INSTALL
5
+
6
+ Install with Rubygems:
7
+
8
+ $ [sudo] gem install rsync-adhoc
9
+ $ rsync-adhocd
data/bin/rsync-adhoc ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'rsync-adhoc'
5
+ rescue LoadError
6
+ require 'rubygems'
7
+ $:.unshift(File.expand_path('../../lib', __FILE__))
8
+ require 'rsync-adhoc'
9
+ end
10
+
11
+ RsyncAdhoc::Application.start
@@ -0,0 +1,11 @@
1
+ module RsyncAdhoc
2
+
3
+ require 'thor'
4
+ require 'digest/sha1'
5
+
6
+ require 'rsync-adhoc/version'
7
+ require 'rsync-adhoc/application'
8
+ require 'rsync-adhoc/server'
9
+ require 'rsync-adhoc/client'
10
+
11
+ end
@@ -0,0 +1,17 @@
1
+ class RsyncAdhoc::Application < Thor
2
+
3
+ desc "server DIR USER PASSWORD", "Start the ad hoc rsync server"
4
+ method_option :port, :type => :numeric, :default => 5001
5
+ def server(dir, user, password)
6
+ server = RsyncAdhoc::Server.new(dir, user, password, options.port)
7
+ server.start!
8
+ end
9
+
10
+ desc "pull DIR REMOTE USER PASSWORD", "Pull file from a remote"
11
+ method_option :port, :type => :numeric, :default => 5001
12
+ def pull(dir, remote, user, password)
13
+ client = RsyncAdhoc::Client.new(dir, remote, user, password, options.port)
14
+ client.start!
15
+ end
16
+
17
+ end
@@ -0,0 +1,101 @@
1
+ class RsyncAdhoc::Client
2
+
3
+ require "tempfile"
4
+ require "eventmachine"
5
+
6
+ attr_reader :dir, :remote, :username, :password, :port
7
+
8
+ def initialize(dir, remote, username, password, port)
9
+ @dir, @remote, @username, @password, @port = File.expand_path(dir), remote, username, password, port
10
+ end
11
+
12
+ def start!
13
+ EM.run do
14
+ EM.connect(@remote, @port, SignalClient,
15
+ @dir, @remote, @username, @password)
16
+ end
17
+ end
18
+
19
+ class SignalClient < EM::Connection
20
+ include EM::P::ObjectProtocol
21
+
22
+ attr_accessor :password
23
+
24
+ def initialize(dir, remote, username, password)
25
+ @dir, @remote, @username, @password = dir, remote, username, password
26
+ @sha = Digest::SHA1.hexdigest([@username, @password].join(':'))
27
+ super
28
+ end
29
+
30
+ def post_init
31
+ send_object(@sha)
32
+ end
33
+
34
+ def receive_object(obj)
35
+ if Hash === obj and obj.key?(:port)
36
+ @port = obj[:port].to_i
37
+ sleep 0.5
38
+ boot_rsync!
39
+ else
40
+ close_connection
41
+ end
42
+ end
43
+
44
+ def unbind
45
+ if @pipe
46
+ @pipe.kill!
47
+ end
48
+
49
+ if @password_file
50
+ password_file.close
51
+ File.unlink(password_file.path)
52
+ end
53
+
54
+ EM.stop_event_loop
55
+ end
56
+
57
+ def password_file
58
+ @password_file ||= begin
59
+ f = Tempfile.open(["adhoc-rsync", ".sec"])
60
+ f.puts @password
61
+ f.flush
62
+ f
63
+ end
64
+ end
65
+
66
+ def boot_rsync!
67
+ cmd = %{rsync --stats --progress -avz --password-file=#{password_file.path} --port #{@port} #{@username}@#{@remote}::tmp #{@dir}}
68
+
69
+ @pipe = EM::popen(cmd, PipeHandler, self)
70
+ end
71
+
72
+ end
73
+
74
+ module PipeHandler
75
+
76
+ attr_accessor :client
77
+
78
+ def initialize(client)
79
+ @client = client
80
+ super
81
+ end
82
+
83
+ def post_init
84
+
85
+ end
86
+
87
+ def receive_data(data)
88
+ puts data
89
+ end
90
+
91
+ def unbind
92
+ @client.close_connection
93
+ end
94
+
95
+ def kill!
96
+ Process.kill("INT", get_pid) rescue nil
97
+ end
98
+
99
+ end
100
+
101
+ end
@@ -0,0 +1,139 @@
1
+ class RsyncAdhoc::Server
2
+
3
+ require "tempfile"
4
+ require "eventmachine"
5
+
6
+ attr_reader :dir, :username, :password, :port
7
+
8
+ def initialize(dir, username, password, port)
9
+ @dir, @username, @password, @port = File.expand_path(dir), username, password, port
10
+ end
11
+
12
+ def start!
13
+ EM.run do
14
+ EM.start_server("127.0.0.1", @port, SignalServer,
15
+ @dir, @username, @password, @port)
16
+ end
17
+ end
18
+
19
+ class SignalServer < EM::Connection
20
+ include EM::P::ObjectProtocol
21
+
22
+ attr_reader :port
23
+
24
+ def initialize(dir, username, password, port)
25
+ @dir, @username, @password, @port = dir, username, password, port
26
+ @sha = Digest::SHA1.hexdigest([@username, @password].join(':'))
27
+ super
28
+ end
29
+
30
+ def receive_object(obj)
31
+ if String === obj and @sha == obj
32
+ boot_rsyncd!
33
+ else
34
+ close_connection
35
+ end
36
+ end
37
+
38
+ def unbind
39
+ if @pipe
40
+ @pipe.kill! rescue nil
41
+ end
42
+
43
+ if @password_file
44
+ password_file.close
45
+ File.unlink(password_file.path)
46
+ end
47
+
48
+ if @pid_file
49
+ pid_file.close
50
+ File.unlink(pid_file.path)
51
+ end
52
+
53
+ if @config_file
54
+ config_file.close
55
+ File.unlink(config_file.path)
56
+ end
57
+
58
+ EM.stop_event_loop
59
+ end
60
+
61
+ def boot_rsyncd!
62
+ cmd = %Q{bash -c 'set -e ; rsync --daemon --no-detach --port=#{@port + 1} --config=#{config_file.path} </dev/null'}
63
+
64
+ @pipe = EM::popen(cmd, PipeHandler, self, @port)
65
+ end
66
+
67
+ def password_file
68
+ @password_file ||= begin
69
+ f = Tempfile.open(["adhoc-rsync", ".sec"])
70
+ f.puts "#{@username}:#{@password}"
71
+ f.flush
72
+ f
73
+ end
74
+ end
75
+
76
+ def lock_file
77
+ @lock_file ||= begin
78
+ f = Tempfile.new(["adhoc-rsync", ".lck"])
79
+ f
80
+ end
81
+ end
82
+
83
+ def pid_file
84
+ @pid_file ||= begin
85
+ f = Tempfile.new(["adhoc-rsync", ".pid"])
86
+ f
87
+ end
88
+ end
89
+
90
+ def config_file
91
+ @config_file ||= begin
92
+ f = Tempfile.open(["adhoc-rsync", ".cfg"])
93
+ f.write <<-EOC
94
+ max connections = 1
95
+ lock file = #{lock_file.path}
96
+ pid file = #{pid_file.path}
97
+
98
+ [tmp]
99
+ path = #{@dir}
100
+ comment = Ad hoc Rsync Server
101
+ auth users = #{@username}
102
+ secrets file = #{password_file.path}
103
+ read only = true
104
+ use chroot = false
105
+ EOC
106
+ f.flush
107
+ f
108
+ end
109
+ end
110
+
111
+ end
112
+
113
+ module PipeHandler
114
+
115
+ attr_accessor :server, :port
116
+
117
+ def initialize(server, port)
118
+ @server, @port = server, port
119
+ super
120
+ end
121
+
122
+ def post_init
123
+ @server.send_object({ :port => @port + 1 })
124
+ end
125
+
126
+ def receive_data(data)
127
+ end
128
+
129
+ def unbind
130
+ end
131
+
132
+ def kill!
133
+ pid = File.read(@server.pid_file.path).strip.to_i
134
+ Process.kill("INT", pid)
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -0,0 +1,3 @@
1
+ module RsyncAdhoc
2
+ VERSION = '0.0.1.a.1'
3
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rsync-adhoc
3
+ version: !ruby/object:Gem::Version
4
+ hash: 127
5
+ prerelease: true
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ - a
11
+ - 1
12
+ version: 0.0.1.a.1
13
+ platform: ruby
14
+ authors:
15
+ - Simon Menke
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2010-06-14 00:00:00 +02:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: eventmachine
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - "="
30
+ - !ruby/object:Gem::Version
31
+ hash: 59
32
+ segments:
33
+ - 0
34
+ - 12
35
+ - 10
36
+ version: 0.12.10
37
+ type: :runtime
38
+ version_requirements: *id001
39
+ - !ruby/object:Gem::Dependency
40
+ name: thor
41
+ prerelease: false
42
+ requirement: &id002 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - "="
46
+ - !ruby/object:Gem::Version
47
+ hash: 39
48
+ segments:
49
+ - 0
50
+ - 13
51
+ - 6
52
+ version: 0.13.6
53
+ type: :runtime
54
+ version_requirements: *id002
55
+ description: Ad hoc rsync server.
56
+ email:
57
+ - simon.menke@gmail.com
58
+ executables:
59
+ - rsync-adhoc
60
+ extensions: []
61
+
62
+ extra_rdoc_files: []
63
+
64
+ files:
65
+ - lib/rsync-adhoc/application.rb
66
+ - lib/rsync-adhoc/client.rb
67
+ - lib/rsync-adhoc/server.rb
68
+ - lib/rsync-adhoc/version.rb
69
+ - lib/rsync-adhoc.rb
70
+ - LICENSE
71
+ - README.md
72
+ - bin/rsync-adhoc
73
+ has_rdoc: true
74
+ homepage: http://github.com/fd/rsync-adhoc
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options: []
79
+
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 23
97
+ segments:
98
+ - 1
99
+ - 3
100
+ - 6
101
+ version: 1.3.6
102
+ requirements: []
103
+
104
+ rubyforge_project: rsync-adhoc
105
+ rubygems_version: 1.3.7
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: Ad hoc rsync server
109
+ test_files: []
110
+