em-fs 0.0.1
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/.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
|