Skip to content

Commit 8de1d8e

Browse files
Sijaysbaddaden
authored andcommittedAug 13, 2017
Implemented yielding Dir.each_child (#4811)
* Renamed Dir.foreach to Dir.each_entry * Renamed Dir#each to Dir#each_entry * Added Dir#entries and Dir#each_child/children instance methods * Added Dir#each_child iterator
1 parent a75e3c4 commit 8de1d8e

File tree

6 files changed

+118
-46
lines changed

6 files changed

+118
-46
lines changed
 

Diff for: ‎spec/std/dir_spec.cr

+18-3
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ describe "Dir" do
234234
filenames = [] of String
235235

236236
dir = Dir.new(__DIR__)
237-
dir.each do |filename|
237+
dir.each_entry do |filename|
238238
filenames << filename
239239
end.should be_nil
240240
dir.close
@@ -246,7 +246,7 @@ describe "Dir" do
246246
filenames = [] of String
247247

248248
Dir.open(__DIR__) do |dir|
249-
dir.each do |filename|
249+
dir.each_entry do |filename|
250250
filenames << filename
251251
end.should be_nil
252252
end
@@ -272,11 +272,26 @@ describe "Dir" do
272272
it "gets dir iterator" do
273273
filenames = [] of String
274274

275-
iter = Dir.new(__DIR__).each
275+
iter = Dir.new(__DIR__).each_entry
276276
iter.each do |filename|
277277
filenames << filename
278278
end
279279

280+
filenames.includes?(".").should be_true
281+
filenames.includes?("..").should be_true
282+
filenames.includes?("dir_spec.cr").should be_true
283+
end
284+
285+
it "gets child iterator" do
286+
filenames = [] of String
287+
288+
iter = Dir.new(__DIR__).each_child
289+
iter.each do |filename|
290+
filenames << filename
291+
end
292+
293+
filenames.includes?(".").should be_false
294+
filenames.includes?("..").should be_false
280295
filenames.includes?("dir_spec.cr").should be_true
281296
end
282297

Diff for: ‎src/compiler/crystal/codegen/cache_dir.cr

+1-3
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,7 @@ module Crystal
114114
end
115115

116116
private def gather_cache_entries(dir)
117-
Dir.entries(dir)
118-
.reject { |name| name == "." || name == ".." }
119-
.map! { |name| File.join(dir, name) }
117+
Dir.children(dir).map! { |name| File.join(dir, name) }
120118
end
121119
end
122120
end

Diff for: ‎src/compiler/crystal/crystal_path.cr

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,11 @@ module Crystal
127127
files = [] of String
128128
dirs = [] of String
129129

130-
Dir.foreach(dir) do |filename|
130+
Dir.each_child(dir) do |filename|
131131
full_name = "#{dir}/#{filename}"
132132

133133
if File.directory?(full_name)
134-
if filename != "." && filename != ".." && recursive
134+
if recursive
135135
dirs << filename
136136
end
137137
else

Diff for: ‎src/dir.cr

+89-21
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Dir
4848
# File.write("testdir/config.h", "")
4949
#
5050
# d = Dir.new("testdir")
51-
# d.each { |x| puts "Got #{x}" }
51+
# d.each_entry { |x| puts "Got #{x}" }
5252
# ```
5353
#
5454
# produces:
@@ -58,16 +58,62 @@ class Dir
5858
# Got ..
5959
# Got config.h
6060
# ```
61-
def each : Nil
61+
def each_entry : Nil
6262
while entry = read
6363
yield entry
6464
end
6565
end
6666

67-
def each
67+
def each_entry
6868
EntryIterator.new(self)
6969
end
7070

71+
# Returns an array containing all of the filenames in the given directory.
72+
def entries : Array(String)
73+
entries = [] of String
74+
each_entry do |filename|
75+
entries << filename
76+
end
77+
entries
78+
end
79+
80+
# Calls the block once for each entry except for `.` and `..` in this directory,
81+
# passing the filename of each entry as a parameter to the block.
82+
#
83+
# ```
84+
# Dir.mkdir("testdir")
85+
# File.write("testdir/config.h", "")
86+
#
87+
# d = Dir.new("testdir")
88+
# d.each_entry { |x| puts "Got #{x}" }
89+
# ```
90+
#
91+
# produces:
92+
#
93+
# ```text
94+
# Got config.h
95+
# ```
96+
def each_child : Nil
97+
excluded = {".", ".."}
98+
while entry = read
99+
yield entry unless excluded.includes?(entry)
100+
end
101+
end
102+
103+
def each_child
104+
ChildIterator.new(self)
105+
end
106+
107+
# Returns an array containing all of the filenames except for `.` and `..`
108+
# in the given directory.
109+
def children : Array(String)
110+
entries = [] of String
111+
each_child do |filename|
112+
entries << filename
113+
end
114+
entries
115+
end
116+
71117
# Reads the next entry from dir and returns it as a string. Returns `nil` at the end of the stream.
72118
#
73119
# ```
@@ -135,34 +181,36 @@ class Dir
135181
end
136182
end
137183

138-
# Calls the block once for each entry in the named directory,
139-
# passing the filename of each entry as a parameter to the block.
140-
def self.foreach(dirname)
184+
# See `#each_entry`.
185+
def self.each_entry(dirname)
141186
Dir.open(dirname) do |dir|
142-
dir.each do |filename|
187+
dir.each_entry do |filename|
143188
yield filename
144189
end
145190
end
146191
end
147192

148-
# Returns an array containing all of the filenames in the given directory.
193+
# See `#entries`.
149194
def self.entries(dirname) : Array(String)
150-
entries = [] of String
151-
foreach(dirname) do |filename|
152-
entries << filename
195+
Dir.open(dirname) do |dir|
196+
return dir.entries
153197
end
154-
entries
155198
end
156199

157-
# Returns an array containing all of the filenames except for `.` and `..`
158-
# in the given directory.
200+
# See `#each_child`.
201+
def self.each_child(dirname)
202+
Dir.open(dirname) do |dir|
203+
dir.each_child do |filename|
204+
yield filename
205+
end
206+
end
207+
end
208+
209+
# See `#children`.
159210
def self.children(dirname) : Array(String)
160-
excluded = {".", ".."}
161-
entries = [] of String
162-
foreach(dirname) do |filename|
163-
entries << filename unless excluded.includes?(filename)
211+
Dir.open(dirname) do |dir|
212+
return dir.children
164213
end
165-
entries
166214
end
167215

168216
# Returns `true` if the given path exists and is a directory
@@ -189,8 +237,8 @@ class Dir
189237
def self.empty?(path) : Bool
190238
raise Errno.new("Error determining size of '#{path}'") unless exists?(path)
191239

192-
foreach(path) do |f|
193-
return false unless {".", ".."}.includes?(f)
240+
each_child(path) do |f|
241+
return false
194242
end
195243
true
196244
end
@@ -261,6 +309,26 @@ class Dir
261309
self
262310
end
263311
end
312+
313+
private struct ChildIterator
314+
include Iterator(String)
315+
316+
def initialize(@dir : Dir)
317+
end
318+
319+
def next
320+
excluded = {".", ".."}
321+
while entry = @dir.read
322+
return entry unless excluded.includes?(entry)
323+
end
324+
stop
325+
end
326+
327+
def rewind
328+
@dir.rewind
329+
self
330+
end
331+
end
264332
end
265333

266334
require "./dir/*"

Diff for: ‎src/file_utils.cr

+7-15
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,10 @@ module FileUtils
136136
def cp_r(src_path : String, dest_path : String)
137137
if Dir.exists?(src_path)
138138
Dir.mkdir(dest_path)
139-
Dir.open(src_path) do |dir|
140-
dir.each do |entry|
141-
if entry != "." && entry != ".."
142-
src = File.join(src_path, entry)
143-
dest = File.join(dest_path, entry)
144-
cp_r(src, dest)
145-
end
146-
end
139+
Dir.each_child(src_path) do |entry|
140+
src = File.join(src_path, entry)
141+
dest = File.join(dest_path, entry)
142+
cp_r(src, dest)
147143
end
148144
else
149145
cp(src_path, dest_path)
@@ -268,13 +264,9 @@ module FileUtils
268264
# ```
269265
def rm_r(path : String) : Nil
270266
if Dir.exists?(path) && !File.symlink?(path)
271-
Dir.open(path) do |dir|
272-
dir.each do |entry|
273-
if entry != "." && entry != ".."
274-
src = File.join(path, entry)
275-
rm_r(src)
276-
end
277-
end
267+
Dir.each_child(path) do |entry|
268+
src = File.join(path, entry)
269+
rm_r(src)
278270
end
279271
Dir.rmdir(path)
280272
else

Diff for: ‎src/http/server/handlers/static_file_handler.html

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
<h2>Directory listing for <%= HTML.escape request_path %></h2>
88
<hr/>
99
<ul>
10-
<% Dir.foreach(path) do |entry| %>
11-
<% next if entry == "." || entry == ".." %>
10+
<% Dir.each_child(path) do |entry| %>
1211
<li>
1312
<a href="<%= request_path == "/" ? "" : escaped_request_path %>/<%= URI.escape entry %>"><%= HTML.escape entry %></a>
1413
</li>

0 commit comments

Comments
 (0)
Please sign in to comment.