em-fs 0.0.1 → 0.1.0

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.
@@ -2,6 +2,80 @@ module EventMachine
2
2
  class Dir
3
3
  class Glob
4
4
 
5
+ FORMAT = "%m %D '%y' %G %n %i '%p' %s %U %A@ %T@ %C@\\n"
6
+
7
+ def initialize pattern
8
+ @weight = nil
9
+ parse pattern
10
+ end
11
+
12
+ def parse pattern
13
+ root = []
14
+
15
+ *path, name = pattern.split(::File::SEPARATOR)
16
+
17
+ if name.index("*").nil?
18
+ path << name
19
+ name = "*"
20
+ end
21
+
22
+ root << path.shift while path[0] and path[0].index("*").nil?
23
+
24
+ @name = name
25
+ @path = path.join(::File::SEPARATOR).gsub '**', '*'
26
+ @root = root.join(::File::SEPARATOR)
27
+
28
+ if path.length == 0
29
+ @weight = 1
30
+ end
31
+
32
+ @root = '.' if @root == ''
33
+ end
34
+
35
+ def each options = {}, &block
36
+ options = {
37
+ depth: :inf
38
+ }.merge options
39
+ EM::SystemCommand.execute find_command(options) do |on|
40
+ on.stdout.line do |line|
41
+ block.call File::Stat.parse line
42
+ end
43
+ end
44
+ end
45
+
46
+ def each_entry options = {}, &block
47
+ options = {
48
+ depth: 1
49
+ }.merge options
50
+ each options do |stat|
51
+ block.call ::File.basename(stat.path)
52
+ end
53
+ end
54
+
55
+ def each_path options = {}, &block
56
+ options = {
57
+ depth: :inf
58
+ }.merge options
59
+ each options do |stat|
60
+ block.call stat.path
61
+ end
62
+ end
63
+
64
+ private
65
+ def find_command options = {}
66
+ options = {
67
+ depth: (@weight || :inf)
68
+ }.merge options
69
+
70
+ builder = EM::SystemCommand::Builder.new 'find'
71
+ builder << @root
72
+ builder << [ :path, @path ] unless @path == "*" or @path == ''
73
+ builder << [ :name, @name ] unless @name == "*"
74
+ builder << [ :maxdepth, options[:depth] ] unless options[:depth] == :inf
75
+ builder << [ :printf, FORMAT ]
76
+ builder.to_s.gsub(/-+(\w)/, "-\\1")
77
+ end
78
+
5
79
  end
6
80
  end
7
81
  end
@@ -2,8 +2,30 @@ module EventMachine
2
2
  class File
3
3
  class Stat
4
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"
5
+ STAT_REGEX = /(\d+) (\d+) '([\w\/ ]+)' (\d+) (\d+) (\d+) '(.+)' (\d+) (\d+) ([\d.]+) ([\d.]+) ([\d.]+)/.freeze
6
+
7
+ # access rights octal
8
+ # ---number of blocks allocated
9
+ # ---the size in bytes of each block reported by %b
10
+ # device number in decimal
11
+ # ---raw mode in hex
12
+ # file type
13
+ # group id
14
+ # number of hardlinks
15
+ # inode number
16
+ # ---mount point
17
+ # file name
18
+ # ---optimal IO transfer size hint
19
+ # total size in bytes
20
+ # --major device type in hex
21
+ # --minor device type in hex
22
+ # user id
23
+ # --time of birth
24
+ # time of last access
25
+ # time of last mod
26
+ # time of last change
27
+ STAT_FORMAT =
28
+ "%a %d '%F' %g %h %i '%n' %s %u %X %Y %Z"
7
29
 
8
30
  # Types
9
31
  S_IFBLK = 0b00000001 # block device
@@ -35,7 +57,7 @@ module EventMachine
35
57
  # @return [EM::File::Stat] The file stat object.
36
58
  def parse str
37
59
  if m = str.match(STAT_REGEX)
38
- ftype = case m[6]
60
+ ftype = case m[3]
39
61
  when 'block device' then S_IFBLK
40
62
  when 'character device' then S_IFCHR
41
63
  when 'directory' then S_IFDIR
@@ -46,43 +68,32 @@ module EventMachine
46
68
  else
47
69
  S_UNKNOWN
48
70
  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),
71
+ EM::File::Stat.new path: m[7],
72
+ atime: Time.at(Integer(m[10].split('.')[0], 10)),
73
+ ctime: Time.at(Integer(m[12].split('.')[0], 10)),
74
+ dev: Integer(m[2], 10),
58
75
  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)
76
+ gid: Integer(m[4], 10),
77
+ ino: Integer(m[6], 10),
78
+ mode: Integer(m[1], 8),
79
+ mtime: Time.at(Integer(m[11].split('.')[0], 10)),
80
+ nlink: Integer(m[5], 10),
81
+ size: Integer(m[8], 10),
82
+ uid: Integer(m[9], 10)
66
83
  else
67
84
  raise "Unable to parse stat string: #{str}"
68
85
  end
69
86
  end
70
87
  end
71
88
 
72
- attr_reader :path, :mountpoint, :atime, :blksize, :blocks, :ctime,
73
- :dev, :dev_major, :dev_minor, :ftype, :gid, :ino, :mtime,
74
- :nlink, :size, :uid
89
+ attr_reader :path, :atime, :ctime, :dev, :ftype, :gid,
90
+ :ino, :mtime, :nlink, :size, :uid
75
91
 
76
92
  def initialize val = {}
77
93
  @path = val[:path]
78
- @mountpoint = val[:mountpoint]
79
94
  @atime = val[:atime]
80
- @blksize = val[:blksize]
81
- @blocks = val[:blocks]
82
95
  @ctime = val[:ctime]
83
96
  @dev = val[:dev]
84
- @dev_major = val[:dev_major]
85
- @dev_minor = val[:dev_minor]
86
97
  @ftype = val[:ftype]
87
98
  @gid = val[:gid]
88
99
  @ino = val[:ino]
data/lib/em-fs/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module EventMachine
2
2
  class FS
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -1,5 +1,186 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'spec_helper'
2
3
 
3
4
  describe EM::Dir::Glob do
5
+ before :all do
6
+ dirs = [ 'a', 'b/a', 'b/b', 'c/a/a', 'c/a/b' ].map { |p|
7
+ File.join(SPEC_ROOT, 'data', p)
8
+ }
9
+ files = [ 'a/x', 'b/x', 'b/a/x', 'b/a/y', 'b/a/z' ].map { |p|
10
+ File.join(SPEC_ROOT, 'data', p)
11
+ }
12
+ FileUtils.touch files
13
+ FileUtils.mkdir_p dirs
14
+ end
4
15
 
16
+ describe '#find_command' do
17
+ it 'should parse relative pattern' do
18
+ cmd = EM::Dir['./*.rb'].send :find_command
19
+ cmd.should == "find . -name '*.rb' -maxdepth 1 -printf '%m %D '\\''%y'\\'' %G %n %i '\\''%p'\\'' %s %U %A@ %T@ %C@\\n'"
20
+ end
21
+
22
+ it 'should parse relative pattern with path wildcard' do
23
+ cmd = EM::Dir['./**/*.rb'].send :find_command
24
+ cmd.should == "find . -name '*.rb' -printf '%m %D '\\''%y'\\'' %G %n %i '\\''%p'\\'' %s %U %A@ %T@ %C@\\n'"
25
+ end
26
+ end
27
+
28
+ describe '#each' do
29
+ context 'with depth = 0' do
30
+ before :all do
31
+ @entries = []
32
+ pattern = File.join(SPEC_ROOT, 'data', '**', '*')
33
+ EM.run do
34
+ cmd = EM::Dir[pattern].each depth: 1 do |entry|
35
+ @entries << entry.path
36
+ end
37
+
38
+ cmd.exit do
39
+ EM.stop_event_loop
40
+ end
41
+ end
42
+ end
43
+
44
+ it 'should execute the block for each entry' do
45
+ @entries.should == [
46
+ "/home/arthur/projects/em-fs/spec/data",
47
+ "/home/arthur/projects/em-fs/spec/data/b",
48
+ "/home/arthur/projects/em-fs/spec/data/c",
49
+ "/home/arthur/projects/em-fs/spec/data/test2",
50
+ "/home/arthur/projects/em-fs/spec/data/test",
51
+ "/home/arthur/projects/em-fs/spec/data/a",
52
+ "/home/arthur/projects/em-fs/spec/data/test3"
53
+ ]
54
+ end
55
+ end
56
+
57
+ context 'with depth = 2' do
58
+ before :all do
59
+ @entries = []
60
+ pattern = File.join(SPEC_ROOT, 'data', '**', '*')
61
+ EM.run do
62
+ cmd = EM::Dir[pattern].each depth: 2 do |entry|
63
+ @entries << entry.path
64
+ end
65
+
66
+ cmd.exit do
67
+ EM.stop_event_loop
68
+ end
69
+ end
70
+ end
71
+
72
+ it 'should execute the block for each entry and directory´s entry' do
73
+ @entries.should == [
74
+ "/home/arthur/projects/em-fs/spec/data",
75
+ "/home/arthur/projects/em-fs/spec/data/b",
76
+ "/home/arthur/projects/em-fs/spec/data/b/b",
77
+ "/home/arthur/projects/em-fs/spec/data/b/x",
78
+ "/home/arthur/projects/em-fs/spec/data/b/a",
79
+ "/home/arthur/projects/em-fs/spec/data/c",
80
+ "/home/arthur/projects/em-fs/spec/data/c/a",
81
+ "/home/arthur/projects/em-fs/spec/data/test2",
82
+ "/home/arthur/projects/em-fs/spec/data/test",
83
+ "/home/arthur/projects/em-fs/spec/data/a",
84
+ "/home/arthur/projects/em-fs/spec/data/a/x",
85
+ "/home/arthur/projects/em-fs/spec/data/test3"
86
+ ]
87
+ end
88
+ end
89
+
90
+ context 'with depth = :inf' do
91
+ before :all do
92
+ @entries = []
93
+ pattern = File.join(SPEC_ROOT, 'data', '**', '*')
94
+ EM.run do
95
+ cmd = EM::Dir[pattern].each depth: :inf do |entry|
96
+ @entries << entry.path
97
+ end
98
+
99
+ cmd.exit do
100
+ EM.stop_event_loop
101
+ end
102
+ end
103
+ end
104
+
105
+ it 'should execute the block for each entry in tree' do
106
+ @entries.should == [
107
+ "/home/arthur/projects/em-fs/spec/data",
108
+ "/home/arthur/projects/em-fs/spec/data/b",
109
+ "/home/arthur/projects/em-fs/spec/data/b/b",
110
+ "/home/arthur/projects/em-fs/spec/data/b/x",
111
+ "/home/arthur/projects/em-fs/spec/data/b/a",
112
+ "/home/arthur/projects/em-fs/spec/data/b/a/x",
113
+ "/home/arthur/projects/em-fs/spec/data/b/a/z",
114
+ "/home/arthur/projects/em-fs/spec/data/b/a/y",
115
+ "/home/arthur/projects/em-fs/spec/data/c",
116
+ "/home/arthur/projects/em-fs/spec/data/c/a",
117
+ "/home/arthur/projects/em-fs/spec/data/c/a/b",
118
+ "/home/arthur/projects/em-fs/spec/data/c/a/a",
119
+ "/home/arthur/projects/em-fs/spec/data/test2",
120
+ "/home/arthur/projects/em-fs/spec/data/test",
121
+ "/home/arthur/projects/em-fs/spec/data/a",
122
+ "/home/arthur/projects/em-fs/spec/data/a/x",
123
+ "/home/arthur/projects/em-fs/spec/data/test3"
124
+ ]
125
+ end
126
+ end
127
+ end
128
+
129
+ describe '#each_entry' do
130
+ before :all do
131
+ @entries = []
132
+ pattern = File.join(SPEC_ROOT, 'data', '**', '*')
133
+ EM.run do
134
+ cmd = EM::Dir[pattern].each_entry do |entry|
135
+ @entries << entry
136
+ end
137
+
138
+ cmd.exit do
139
+ EM.stop_event_loop
140
+ end
141
+ end
142
+ end
143
+
144
+ it 'should execute a block with file name for each entry' do
145
+ @entries.should == [ "data", "b", "c", "test2", "test", "a", "test3" ]
146
+ end
147
+ end
148
+
149
+ describe '#each_path' do
150
+ before :all do
151
+ @entries = []
152
+ pattern = File.join(SPEC_ROOT, 'data', '**', '*')
153
+ EM.run do
154
+ cmd = EM::Dir[pattern].each_path do |path|
155
+ @entries << path
156
+ end
157
+
158
+ cmd.exit do
159
+ EM.stop_event_loop
160
+ end
161
+ end
162
+ end
163
+
164
+ it 'should execute a block with full path for each entry' do
165
+ @entries.should == [
166
+ "/home/arthur/projects/em-fs/spec/data",
167
+ "/home/arthur/projects/em-fs/spec/data/b",
168
+ "/home/arthur/projects/em-fs/spec/data/b/b",
169
+ "/home/arthur/projects/em-fs/spec/data/b/x",
170
+ "/home/arthur/projects/em-fs/spec/data/b/a",
171
+ "/home/arthur/projects/em-fs/spec/data/b/a/x",
172
+ "/home/arthur/projects/em-fs/spec/data/b/a/z",
173
+ "/home/arthur/projects/em-fs/spec/data/b/a/y",
174
+ "/home/arthur/projects/em-fs/spec/data/c",
175
+ "/home/arthur/projects/em-fs/spec/data/c/a",
176
+ "/home/arthur/projects/em-fs/spec/data/c/a/b",
177
+ "/home/arthur/projects/em-fs/spec/data/c/a/a",
178
+ "/home/arthur/projects/em-fs/spec/data/test2",
179
+ "/home/arthur/projects/em-fs/spec/data/test",
180
+ "/home/arthur/projects/em-fs/spec/data/a",
181
+ "/home/arthur/projects/em-fs/spec/data/a/x",
182
+ "/home/arthur/projects/em-fs/spec/data/test3"
183
+ ]
184
+ end
185
+ end
5
186
  end
@@ -4,18 +4,14 @@ describe EM::File::Stat do
4
4
  describe '.parse' do
5
5
  context 'parsed stat' do
6
6
  subject do
7
- EM::File::Stat.parse "644 427272 512 2050 81a4 'regular file' 100 1 2623327 '/' '/home/arthur/test' 4096 218759168 0 0 1000 0 1340357826 1340357846 1340357846 802h 2050d"
7
+ EM::File::Stat.parse "644 2050 'regular file' 100 1 2623327 '/home/arthur/test' 218759168 1000 1340357826 1340357846 1340357846"
8
8
  end
9
9
 
10
10
  its(:atime) { should == Time.at(1340357826) }
11
- its(:blksize) { should == 512 }
12
11
  its(:blockdev?) { should == false }
13
- its(:blocks) { should == 427272 }
14
12
  its(:chardev?) { should == false }
15
13
  its(:ctime) { should == Time.at(1340357846) }
16
14
  its(:dev) { should == 2050 }
17
- its(:dev_major) { should == 0 }
18
- its(:dev_minor) { should == 0 }
19
15
  its(:directory?) { should == false }
20
16
  its(:executable?) { should == false }
21
17
  its(:executable_real?) { should == false }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-fs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -157,7 +157,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
157
  version: '0'
158
158
  segments:
159
159
  - 0
160
- hash: 392820138852039063
160
+ hash: 4225417122368326630
161
161
  required_rubygems_version: !ruby/object:Gem::Requirement
162
162
  none: false
163
163
  requirements:
@@ -166,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
166
  version: '0'
167
167
  segments:
168
168
  - 0
169
- hash: 392820138852039063
169
+ hash: 4225417122368326630
170
170
  requirements: []
171
171
  rubyforge_project:
172
172
  rubygems_version: 1.8.24