em-fs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
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
18
+ spec/data
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create --install 1.9.3@em-fs
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in em_file_utils.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', :version => 2 do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+ # Capybara request specs
17
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
18
+ end
19
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Arthur Leonard Andersen
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,75 @@
1
+ # EM::FS
2
+
3
+ `EM::FS` provides a simple interface to gain simple filesystem access
4
+ in eventmachine via `EM::SystemCommand`.
5
+
6
+ `EM::FileUtils` attempts to mimic the behavoir of the filesystem API
7
+ of the Ruby stdlib. In the background it invokes linux/unix system
8
+ commands - like `rsync`, `mkdir` etc. - via the `em-systemcommand`
9
+ gem.
10
+
11
+ Furthermore `EM::Dir` and `EM::File` provide abstractions to crawl
12
+ directory structures via `find` command without blocking the reactor.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'em-fs'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install em-fs
27
+
28
+ ## Usage
29
+
30
+ ### `EM::FS` using `rsync` and `find`
31
+
32
+ To invoke bare commands you can either use `EM::SystemCommand`
33
+ directly or the methods `EM::FS.rsync` and `EM::FS.find`.
34
+
35
+ ### `EM::FileUtils` for simple filesystem operations
36
+
37
+ The `FileUtils` methods from the Ruby Standard Library may block the
38
+ eventmachine reactor. That´s why `em-fs` uses `EM::SystemCommand` to
39
+ provide a similar non-blocking feature set.
40
+
41
+ EM.run do
42
+ EM::FileUtils.cp 'some_file', 'some_copy' do |on|
43
+ on.exit do |status|
44
+ puts 'Copied!'
45
+ end
46
+ end
47
+ end
48
+
49
+ For a full list of methods, have a look at the documentation.
50
+
51
+ ### Abstraction via `EM::Dir` and `EM::File`
52
+
53
+ `EM::Dir[]` returns a `EM::Dir::Glob` object, containing the
54
+ information for the `find` command. On this object you can invoke
55
+ multiple methods to see the resulting filesystem objects:
56
+
57
+ EM::Dir['./**/*.*'].each do |stat|
58
+ puts "Some stat: #{stat.inspect}"
59
+ end
60
+
61
+ EM::Dir['./**/*.lisp'].each_entry do |entry|
62
+ puts "Some entry: #{entry}"
63
+ end
64
+
65
+ EM::Dir['./**/*.rb'].each_path do |path|
66
+ puts "Some path: #{path}"
67
+ end
68
+
69
+ ## Contributing
70
+
71
+ 1. Fork it
72
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
73
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
74
+ 4. Push to the branch (`git push origin my-new-feature`)
75
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/em-fs.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/em-fs/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Arthur Leonard Andersen"]
6
+ gem.email = ["leoc.git@gmail.com"]
7
+ gem.description = %q{`em-fs` provides libraries to access file system commands through an API similar to the Ruby file API for eventmachine.}
8
+ gem.summary = %q{Invoke filesystem calls without blocking.}
9
+ gem.homepage = "http://github.com/leoc/em-fs"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "em-fs"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = EventMachine::FS::VERSION
17
+
18
+ gem.add_development_dependency 'rake'
19
+ gem.add_development_dependency 'rspec'
20
+ gem.add_development_dependency 'guard'
21
+ gem.add_development_dependency 'guard-rspec'
22
+
23
+ gem.add_dependency 'eventmachine'
24
+ gem.add_dependency 'em-systemcommand'
25
+
26
+ end
@@ -0,0 +1,15 @@
1
+ class Hash
2
+ def extractable_options?
3
+ instance_of?(Hash)
4
+ end
5
+ end
6
+
7
+ class Array
8
+ def extract_options!
9
+ if last.is_a?(Hash) && last.extractable_options?
10
+ pop
11
+ else
12
+ {}
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module EventMachine
2
+ class Dir
3
+ class Glob
4
+
5
+ end
6
+ end
7
+ end
data/lib/em-fs/dir.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'em-fs/dir/glob'
2
+
3
+ module EventMachine
4
+ class Dir
5
+ class << self
6
+
7
+ def glob pattern
8
+ EM::Dir::Glob.new pattern
9
+ end
10
+ alias :[] :glob
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,200 @@
1
+ module EventMachine
2
+ class File
3
+ class Stat
4
+
5
+ STAT_REGEX = /(\d+) (\d+) (\d+) (\d+) (\h+) '([\w\/ ]+)' (\d+) (\d+) (\d+) '(.+)' '(.+)' (\d+) (\d+) (\h+) (\h+) (\d+) (\d+) (\d+) (\d+) (\d+)/.freeze
6
+ STAT_FORMAT = "%a %b %B %d %f '%F' %g %h %i '%m' '%n' %o %s %t %T %u %W %X %Y %Z"
7
+
8
+ # Types
9
+ S_IFBLK = 0b00000001 # block device
10
+ S_IFCHR = 0b00000010 # character device
11
+ S_IFDIR = 0b00000100 # directory
12
+ S_IFIFO = 0b00001000 # FIFO/pipe
13
+ S_IFLNK = 0b00010000 # symlink
14
+ S_IFREG = 0b00100000 # regular file
15
+ S_IFSOCK = 0b01000000 # socket
16
+ S_UNKNOWN = 0b10000000 # unknown
17
+
18
+ # Mode Flags
19
+ S_IRUSR = 0b100000000
20
+ S_IWUSR = 0b010000000
21
+ S_IXUSR = 0b001000000
22
+ S_IRGRP = 0b000100000
23
+ S_IWGRP = 0b000010000
24
+ S_IXGRP = 0b000001000
25
+ S_IROTH = 0b000000100
26
+ S_IWOTH = 0b000000010
27
+ S_IXOTH = 0b000000001
28
+
29
+ class << self
30
+
31
+ ##
32
+ # Parses a given string for file stat information.
33
+ #
34
+ # @param [String] string The String to be parsed.
35
+ # @return [EM::File::Stat] The file stat object.
36
+ def parse str
37
+ if m = str.match(STAT_REGEX)
38
+ ftype = case m[6]
39
+ when 'block device' then S_IFBLK
40
+ when 'character device' then S_IFCHR
41
+ when 'directory' then S_IFDIR
42
+ when 'FIFO/pipe' then S_IFIFO
43
+ when 'symlink' then S_IFLNK
44
+ when 'regular file' then S_IFREG
45
+ when 'socket' then S_IFSOCK
46
+ else
47
+ S_UNKNOWN
48
+ end
49
+ EM::File::Stat.new path: m[11],
50
+ mountpoint: m[10],
51
+ atime: Time.at(Integer(m[18], 10)),
52
+ blksize: Integer(m[3], 10),
53
+ blocks: Integer(m[2], 10),
54
+ ctime: Time.at(Integer(m[20], 10)),
55
+ dev: Integer(m[4], 10),
56
+ dev_major: Integer(m[14], 8),
57
+ dev_minor: Integer(m[15], 8),
58
+ ftype: ftype,
59
+ gid: Integer(m[7], 10),
60
+ ino: Integer(m[9], 10),
61
+ mode: Integer(m[1], 8),
62
+ mtime: Time.at(Integer(m[19], 10)),
63
+ nlink: Integer(m[8], 10),
64
+ size: Integer(m[13], 10),
65
+ uid: Integer(m[16], 10)
66
+ else
67
+ raise "Unable to parse stat string: #{str}"
68
+ end
69
+ end
70
+ end
71
+
72
+ attr_reader :path, :mountpoint, :atime, :blksize, :blocks, :ctime,
73
+ :dev, :dev_major, :dev_minor, :ftype, :gid, :ino, :mtime,
74
+ :nlink, :size, :uid
75
+
76
+ def initialize val = {}
77
+ @path = val[:path]
78
+ @mountpoint = val[:mountpoint]
79
+ @atime = val[:atime]
80
+ @blksize = val[:blksize]
81
+ @blocks = val[:blocks]
82
+ @ctime = val[:ctime]
83
+ @dev = val[:dev]
84
+ @dev_major = val[:dev_major]
85
+ @dev_minor = val[:dev_minor]
86
+ @ftype = val[:ftype]
87
+ @gid = val[:gid]
88
+ @ino = val[:ino]
89
+ @mode = val[:mode]
90
+ @mtime = val[:mtime]
91
+ @nlink = val[:nlink]
92
+ @size = val[:size]
93
+ @uid = val[:uid]
94
+ end
95
+
96
+ def blockdev?
97
+ ftype^S_IFBLK == 0
98
+ end
99
+
100
+ def chardev?
101
+ ftype^S_IFCHR == 0
102
+ end
103
+
104
+ def directory?
105
+ ftype^S_IFDIR == 0
106
+ end
107
+
108
+ def executable?
109
+ return true if Process::UID.rid == 0
110
+ return @mode & S_IXUSR != 0 if rowned?
111
+ return @mode & S_IXGRP != 0 if rgrpowned?
112
+ @mode & S_IXOTH != 0
113
+ end
114
+
115
+ def executable_real?
116
+ return true if Process::UID.rid == 0
117
+ return @mode & S_IXUSR != 0 if rowned?
118
+ return @mode & S_IXGRP != 0 if rgrpowned?
119
+ @mode & S_IXOTH != 0
120
+ end
121
+
122
+ def file?
123
+ ftype^S_IFREG == 0
124
+ end
125
+
126
+ def grpowned?
127
+ gid == Process::GID.eid
128
+ end
129
+
130
+ def rgrpowned?
131
+ gid == Process::GID.rid
132
+ end
133
+
134
+ def mode
135
+ @mode.to_s(8)
136
+ end
137
+
138
+ def owned?
139
+ uid == Process::UID.eid
140
+ end
141
+
142
+ def rowned?
143
+ uid == Process::UID.rid
144
+ end
145
+
146
+ def pipe?
147
+ ftype^S_IFIFO == 0
148
+ end
149
+
150
+ def readable?
151
+ return true if Process::UID.eid == 0
152
+ return @mode & S_IRUSR != 0 if owned?
153
+ return @mode & S_IRGRP != 0 if grpowned?
154
+ @mode & S_IROTH != 0
155
+ end
156
+
157
+ def readable_real?
158
+ return true if Process::UID.rid == 0
159
+ return @mode & S_IRUSR != 0 if rowned?
160
+ return @mode & S_IRGRP != 0 if rgrpowned?
161
+ @mode & S_IROTH != 0
162
+ end
163
+
164
+ def socket?
165
+ ftype^S_IFSOCK == 0
166
+ end
167
+
168
+ def symlink?
169
+ ftype^S_IFLNK == 0
170
+ end
171
+
172
+ def world_readable?
173
+ @mode if @mode & S_IROTH == S_IROTH
174
+ end
175
+
176
+ def world_writable?
177
+ @mode if @mode & S_IWOTH == S_IWOTH
178
+ end
179
+
180
+ def writable?
181
+ return true if Process::UID.rid == 0
182
+ return @mode & S_IWUSR != 0 if owned?
183
+ return @mode & S_IWGRP != 0 if grpowned?
184
+ @mode & S_IWOTH != 0
185
+ end
186
+
187
+ def writable_real?
188
+ return true if Process::UID.rid == 0
189
+ return @mode & S_IWUSR != 0 if rowned?
190
+ return @mode & S_IWGRP != 0 if rgrpowned?
191
+ @mode & S_IWOTH != 0
192
+ end
193
+
194
+ def zero?
195
+ @size == 0
196
+ end
197
+
198
+ end
199
+ end
200
+ end
data/lib/em-fs/file.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'em-fs/file/stat'
2
+
3
+ module EventMachine
4
+ class File
5
+
6
+ class << self
7
+
8
+ def stat path, &block
9
+ EM::SystemCommand.execute 'stat', [:format, EM::File::Stat::STAT_FORMAT], path do |on|
10
+ on.success do |ps|
11
+ block.call EM::File::Stat.parse ps.stdout.output
12
+ end
13
+ on.failure do |ps|
14
+ raise "EM::File::stat failed. Output:\n#{ps.stderr.output}"
15
+ end
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,149 @@
1
+ module EventMachine
2
+ class FileUtils
3
+ class << self
4
+ ##
5
+ # Make directories.
6
+ def mkdir *dirs, &block
7
+ options = { parents: false }.merge dirs.extract_options!
8
+ cmd = EM::SystemCommand.new 'mkdir', &block
9
+ cmd << :p if options[:parents]
10
+ cmd << dirs
11
+ cmd.execute
12
+ end
13
+
14
+ ##
15
+ # Make directories with parents.
16
+ def mkdir_p *dirs, &block
17
+ options = {}.merge dirs.extract_options!
18
+ mkdir *dirs, options.merge(parents: true), &block
19
+ end
20
+
21
+ ##
22
+ # Remove the directories if they are empty.
23
+ def rmdir *dirs, &block
24
+ options = { parents: false }.merge dirs.extract_options!
25
+ cmd = EM::SystemCommand.new 'rmdir'
26
+ cmd << :p if options[:parents]
27
+ cmd << dirs
28
+ cmd.execute &block
29
+ end
30
+
31
+ ##
32
+ # Create link in file system.
33
+ def ln src, dest, options = {}, &block
34
+ options = { symbolic: false, force: false }.merge options
35
+ cmd = EM::SystemCommand.new 'ln'
36
+ cmd << :s if options[:symbolic]
37
+ cmd << :f if options[:force]
38
+ cmd << src << dest
39
+ cmd.execute &block
40
+ end
41
+
42
+ ##
43
+ # Create symbolic link.
44
+ def ln_s src, dest, options = {}, &block
45
+ ln src, dest, options.merge(symbolic: true), &block
46
+ end
47
+
48
+ ##
49
+ # Force symbolic link creation.
50
+ def ln_sf src, dest, options = {}, &block
51
+ ln src, dest, options.merge(symbolic: true, force: true), &block
52
+ end
53
+
54
+ ##
55
+ # Copy files.
56
+ def cp *args, &block
57
+ options = { recursive: false }.merge args.extract_options!
58
+ unless args.length >= 2
59
+ raise 'Too few arguments. Need source and destination at least.'
60
+ end
61
+
62
+ cmd = EM::SystemCommand.new 'cp'
63
+ cmd << :r if options[:recursive]
64
+ cmd << args
65
+ cmd.execute &block
66
+ end
67
+
68
+ ##
69
+ # Recursively copy files.
70
+ def cp_r *args, &block
71
+ options = { recursive: false }.merge args.extract_options!
72
+ cp *args, options.merge(recursive: true), &block
73
+ end
74
+
75
+ ##
76
+ # Move files or directories.
77
+ def mv *args, &block
78
+ options = { recursive: false }.merge args.extract_options!
79
+ unless args.length >= 2
80
+ raise 'Too few arguments. Need source and destination at least.'
81
+ end
82
+
83
+ cmd = EM::SystemCommand.new 'mv'
84
+ cmd << args
85
+ cmd.execute &block
86
+ end
87
+
88
+ ##
89
+ # Remove files or directories.
90
+ def rm *args, &block
91
+ options = { recursive: false, force: false }.merge args.extract_options!
92
+ cmd = EM::SystemCommand.new 'rm'
93
+ cmd << '-r' if options[:recursive]
94
+ cmd << '-f' if options[:force]
95
+ cmd << args
96
+ cmd.execute &block
97
+ end
98
+
99
+ def rm_r target, options = {}, &block
100
+ rm target, options.merge(recursive: true), &block
101
+ end
102
+
103
+ def rm_rf target, options = {}, &block
104
+ rm target, options.merge(recursive: true, force: true), &block
105
+ end
106
+
107
+ def install *args, &block
108
+ options = { mode: '755' }.merge args.extract_options!
109
+ cmd = EM::SystemCommand.new 'install'
110
+ cmd.add '--mode', options[:mode] if options[:mode]
111
+ cmd << args
112
+ cmd.execute &block
113
+ end
114
+
115
+ def chmod mode, *dest, &block
116
+ options = { recursive: false }.merge dest.extract_options!
117
+ cmd = EM::SystemCommand.new 'chmod'
118
+ cmd << :R if options[:recursive]
119
+ cmd << mode << dest
120
+ cmd.execute &block
121
+ end
122
+
123
+ def chmod_R mode, *dest, &block
124
+ options = { recursive: false }.merge dest.extract_options!
125
+ chmod mode, *dest, options.merge(recursive: true), &block
126
+ end
127
+
128
+ def chown user, group, *dest, &block
129
+ options = { recursive: false }.merge dest.extract_options!
130
+ cmd = EM::SystemCommand.new 'chown'
131
+ cmd << :R if options[:recursive]
132
+ cmd << "#{user.to_s}:#{group.to_s}" << dest
133
+ cmd.execute &block
134
+ end
135
+
136
+ def chown_R user, group, *dest, &block
137
+ options = { recursive: false }.merge dest.extract_options!
138
+ chown user, group, dest, options.merge(recursive: true), &block
139
+ end
140
+
141
+ def touch *dest, &block
142
+ options = {}.merge dest.extract_options!
143
+ cmd = EM::SystemCommand.new 'touch'
144
+ cmd << dest
145
+ cmd.execute &block
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,58 @@
1
+ # -*- coding: utf-8 -*-
2
+ module EventMachine
3
+ class FS
4
+ class Command < EM::SystemCommand
5
+
6
+ PROGRESS_REGEXP = /([A-Za-z0-9\.\-\/]+)\n[ ]+(\d+)/.freeze
7
+
8
+ ##
9
+ # Invokes `#execute` of super-class and adds a progress matcher.
10
+ def execute &block
11
+ super &block
12
+
13
+ stdout.match PROGRESS_REGEXP, match: :last, in: :output do |file, bytes|
14
+ receive_progress file, bytes.to_i
15
+ end
16
+
17
+ self
18
+ end
19
+
20
+ ##
21
+ # Is called when ever a `EM::FilesystemCommand` stdout updates the line
22
+ # is matched the `EM::FilesystemCommand::PROGRESS_REGEXP`.
23
+ #
24
+ # Calls all defined callbacks for progress events.
25
+ #
26
+ # @param [String] file The file that´s been updated.
27
+ # @param [Integer] bytes The bytes moved or copied.
28
+ def receive_progress file, bytes
29
+ progress_callbacks.each do |cb|
30
+ cb.call file, bytes
31
+ end
32
+ end
33
+
34
+ ##
35
+ # Defines a progress callback.
36
+ #
37
+ # @yield The block to be stored as callback for progress events.
38
+ # @yieldparam [String] file The file that´s been updated.
39
+ # @yieldparam [Integer] bytes The bytes moved or copied.
40
+ def progress &block
41
+ progress_callbacks << block
42
+ end
43
+
44
+ ##
45
+ # The callbacks for progress events.
46
+ #
47
+ # @return [Array] The array of callbacks for progress events.
48
+ private
49
+ def progress_callbacks
50
+ @progress_callbacks ||= []
51
+ end
52
+
53
+ def progress_regexp
54
+ @progress_regexp ||= /([A-Za-z0-9\.\-\/]+)\n[ ]+(\d+)/.freeze
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,11 @@
1
+ module EventMachine
2
+ class FS
3
+ class RsyncCommand < EM::FS::Command
4
+
5
+ def initialize
6
+ super 'rsync'
7
+ end
8
+
9
+ end
10
+ end
11
+ end
data/lib/em-fs/fs.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'em-fs/fs/command'
2
+ require 'em-fs/fs/rsync_command'
3
+
4
+ module EventMachine
5
+ class FS
6
+ class << self
7
+
8
+ def rsync *args, &block
9
+ options = { }.merge args.extract_options!
10
+ cmd = EM::FS::RsyncCommand.new
11
+ cmd << :progress
12
+ cmd << args
13
+ cmd.execute &block
14
+ end
15
+
16
+ def find *args, &block
17
+ options = { }.merge args.extract_options!
18
+ cmd = EM::SystemCommand.new 'find'
19
+ cmd << args
20
+ cmd.execute &block
21
+ end
22
+
23
+ end
24
+ end
25
+ end