em-fs 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Guardfile +19 -0
- data/LICENSE +22 -0
- data/README.md +75 -0
- data/Rakefile +2 -0
- data/em-fs.gemspec +26 -0
- data/lib/em-fs/core_ext.rb +15 -0
- data/lib/em-fs/dir/glob.rb +7 -0
- data/lib/em-fs/dir.rb +14 -0
- data/lib/em-fs/file/stat.rb +200 -0
- data/lib/em-fs/file.rb +21 -0
- data/lib/em-fs/fileutils.rb +149 -0
- data/lib/em-fs/fs/command.rb +58 -0
- data/lib/em-fs/fs/rsync_command.rb +11 -0
- data/lib/em-fs/fs.rb +25 -0
- data/lib/em-fs/version.rb +5 -0
- data/lib/em-fs.rb +9 -0
- data/spec/dir/glob_spec.rb +5 -0
- data/spec/dir_spec.rb +16 -0
- data/spec/file/stat_spec.rb +45 -0
- data/spec/file_spec.rb +19 -0
- data/spec/fileutils_spec.rb +432 -0
- data/spec/fs/rsync_command_spec.rb +79 -0
- data/spec/fs_spec.rb +28 -0
- data/spec/spec_helper.rb +30 -0
- metadata +184 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create --install 1.9.3@em-fs
|
data/Gemfile
ADDED
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
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
|
data/lib/em-fs/dir.rb
ADDED
@@ -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
|
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
|