Skip to content

Commit

Permalink
Added unix-like commands to FileUtils (#3420)
Browse files Browse the repository at this point in the history
ghivert authored and Ary Borenszweig committed Oct 15, 2016

Verified

This commit was signed with the committer’s verified signature.
1 parent bad73b0 commit 6aa58a3
Showing 2 changed files with 454 additions and 1 deletion.
270 changes: 270 additions & 0 deletions spec/std/file_utils_spec.cr
Original file line number Diff line number Diff line change
@@ -2,6 +2,38 @@ require "spec"
require "file_utils"

describe "FileUtils" do
describe "cd" do
it "should work" do
cwd = Dir.current
FileUtils.cd("..")
Dir.current.should_not eq(cwd)
FileUtils.cd(cwd)
Dir.current.should eq(cwd)
end

it "raises" do
expect_raises do
FileUtils.cd("/nope")
end
end

it "accepts a block" do
cwd = Dir.current

FileUtils.cd("..") do
Dir.current.should_not eq(cwd)
end

Dir.current.should eq(cwd)
end
end

describe "pwd" do
it "returns the current working directory" do
FileUtils.pwd.should eq(Dir.current)
end
end

describe "cmp" do
it "compares two equal files" do
FileUtils.cmp(
@@ -124,4 +156,242 @@ describe "FileUtils" do
end
end
end

describe "rm_rf" do
it "delete recursively a directory" do
path = "/tmp/crystal_rm_rftest_#{Process.pid}/"
FileUtils.mkdir(path)
File.write(File.join(path, "a"), "")
FileUtils.mkdir(File.join(path, "b"))
FileUtils.rm_rf(path).should be_nil
Dir.exists?(path).should be_false
end

it "delete recursively multiple directory" do
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/"
FileUtils.mkdir(path1)
FileUtils.mkdir(path2)
File.write(File.join(path1, "a"), "")
File.write(File.join(path2, "a"), "")
FileUtils.mkdir(File.join(path1, "b"))
FileUtils.mkdir(File.join(path2, "b"))
FileUtils.rm_rf([path1, path2]).should be_nil
Dir.exists?(path1).should be_false
Dir.exists?(path2).should be_false
end

it "doesn't return error on non existing file" do
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = File.join(path1, "a")
FileUtils.mkdir(path1)
FileUtils.rm_rf([path1, path2]).should be_nil
end
end

describe "mv" do
it "moves a file from one place to another" do
begin
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/"
FileUtils.mkdir([path1, path2])
path1 = File.join(path1, "a")
path2 = File.join(path2, "b")
File.write(path1, "")
FileUtils.mv(path1, path2).should be_nil
File.exists?(path1).should be_false
File.exists?(path2).should be_true
ensure
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/"
FileUtils.rm_rf([path1, path2])
end
end

it "raises an error if non correct arguments" do
expect_raises Errno do
FileUtils.mv("/tmp/crystal_mv_test/a", "/tmp/crystal_mv_test/b")
end
end

it "moves multiple files to one place" do
begin
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/"
path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/"
FileUtils.mkdir([path1, path2, path3])
path1 = File.join(path1, "a")
path2 = File.join(path2, "b")
File.write(path1, "")
File.write(path2, "")
FileUtils.mv([path1, path2], path3).should be_nil
File.exists?(path1).should be_false
File.exists?(path2).should be_false
File.exists?(File.join(path3, "a")).should be_true
File.exists?(File.join(path3, "b")).should be_true
ensure
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/"
path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/"
FileUtils.rm_rf([path1, path2, path3])
end
end

it "raises an error if dest is non correct" do
expect_raises ArgumentError do
FileUtils.mv(["/tmp/crystal_mv_test/a", "/tmp/crystal_mv_test/b"], "/tmp/crystal_not_here")
end
end

it "moves all existing files to destination" do
begin
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/"
path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/"
path4 = "/tmp/crystal_rm_rftest_#{Process.pid + 3}/a"
FileUtils.mkdir([path1, path2, path3])
path1 = File.join(path1, "a")
path2 = File.join(path2, "b")
File.write(path1, "")
File.write(path2, "")
FileUtils.mv([path1, path2, path4], path3).should be_nil
File.exists?(path1).should be_false
File.exists?(path2).should be_false
File.exists?(File.join(path3, "a")).should be_true
File.exists?(File.join(path3, "b")).should be_true
ensure
path1 = "/tmp/crystal_rm_rftest_#{Process.pid}/"
path2 = "/tmp/crystal_rm_rftest_#{Process.pid + 1}/"
path3 = "/tmp/crystal_rm_rftest_#{Process.pid + 2}/"
FileUtils.rm_rf([path1, path2, path3])
end
end
end

it "tests mkdir and rmdir with a new path" do
path = "/tmp/crystal_mkdir_test_#{Process.pid}/"
FileUtils.mkdir(path, 0o700).should be_nil
Dir.exists?(path).should be_true
FileUtils.rmdir(path).should be_nil
Dir.exists?(path).should be_false
end

it "tests mkdir and rmdir with multiple new paths" do
path1 = "/tmp/crystal_mkdir_test_#{Process.pid}/"
path2 = "/tmp/crystal_mkdir_test_#{Process.pid + 1}/"
FileUtils.mkdir([path1, path2], 0o700).should be_nil
Dir.exists?(path1).should be_true
Dir.exists?(path2).should be_true
FileUtils.rmdir([path1, path2]).should be_nil
Dir.exists?(path1).should be_false
Dir.exists?(path2).should be_false
end

it "tests mkdir with an existing path" do
expect_raises Errno do
Dir.mkdir(__DIR__, 0o700)
end
end

it "tests mkdir with multiples existing paths" do
expect_raises Errno do
FileUtils.mkdir([__DIR__, __DIR__], 0o700)
end
expect_raises Errno do
FileUtils.mkdir(["/tmp/crystal_mkdir_test_#{Process.pid}/", __DIR__], 0o700)
end
end

it "tests mkdir_p with a new path" do
path = "/tmp/crystal_mkdir_ptest_#{Process.pid}/"
FileUtils.mkdir_p(path).should be_nil
Dir.exists?(path).should be_true
path = File.join({path, "a", "b", "c"})
FileUtils.mkdir_p(path).should be_nil
Dir.exists?(path).should be_true
end

it "tests mkdir_p with multiples new path" do
path1 = "/tmp/crystal_mkdir_ptest_#{Process.pid}/"
path2 = "/tmp/crystal_mkdir_ptest_#{Process.pid + 1}"
FileUtils.mkdir_p([path1, path2]).should be_nil
Dir.exists?(path1).should be_true
Dir.exists?(path2).should be_true
path1 = File.join({path1, "a", "b", "c"})
path2 = File.join({path2, "a", "b", "c"})
FileUtils.mkdir_p([path1, path2]).should be_nil
Dir.exists?(path1).should be_true
Dir.exists?(path2).should be_true
end

it "tests mkdir_p with an existing path" do
FileUtils.mkdir_p(__DIR__).should be_nil
expect_raises Errno do
FileUtils.mkdir_p(__FILE__)
end
end

it "tests mkdir_p with multiple existing path" do
FileUtils.mkdir_p([__DIR__, __DIR__]).should be_nil
expect_raises Errno do
FileUtils.mkdir_p([__FILE__, "/tmp/crystal_mkdir_ptest_#{Process.pid}/"])
end
end

it "tests rmdir with an non existing path" do
expect_raises Errno do
FileUtils.rmdir("/tmp/crystal_mkdir_test_#{Process.pid}/tmp/")
end
end

it "tests rmdir with multiple non existing path" do
expect_raises Errno do
FileUtils.rmdir(["/tmp/crystal_mkdir_test_#{Process.pid}/tmp/", "/tmp/crystal_mkdir_test_#{Process.pid + 1}/tmp/"])
end
end

it "tests rmdir with a path that cannot be removed" do
expect_raises Errno do
FileUtils.rmdir(__DIR__)
end
end

it "tests rmdir with multiple path that cannot be removed" do
expect_raises Errno do
FileUtils.rmdir([__DIR__, __DIR__])
end
end

it "tests rm with an existing path" do
path = "/tmp/crystal_rm_test_#{Process.pid}"
File.write(path, "")
FileUtils.rm(path).should be_nil
File.exists?(path).should be_false
end

it "tests rm with non existing path" do
expect_raises Errno do
FileUtils.rm("/tmp/crystal_rm_test_#{Process.pid}")
end
end

it "tests rm with multiple existing paths" do
path1 = "/tmp/crystal_rm_test_#{Process.pid}"
path2 = "/tmp/crystal_rm_test_#{Process.pid + 1}"
File.write(path1, "")
File.write(path2, "")
FileUtils.rm([path1, path2]).should be_nil
File.exists?(path1).should be_false
File.exists?(path2).should be_false
end

it "tests rm with some non existing paths" do
expect_raises Errno do
path1 = "/tmp/crystal_rm_test_#{Process.pid}"
path2 = "/tmp/crystal_rm_test_#{Process.pid + 1}"
File.write(path1, "")
File.write(path2, "")
FileUtils.rm([path1, path2, path2])
end
end
end
185 changes: 184 additions & 1 deletion src/file_utils.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
module FileUtils
extend self

# Changes the current working directory of the process to the given string *path*.
# Alias of Dir.cd.
# ```
# FileUtils.cd("to/directory")
# ```
def cd(path : String)
Dir.cd(path)
end

# Changes the current working firectory of the process to the given string *path*
# and invoked the block, restoring the original working directory when the block exits.
# Alias of Dir.cd with block.
# ```
# FileUtils.cd("to/directory") { puts "Do something useful here!" }
# ```
def cd(path : String)
Dir.cd(path) { yield }
end

# Compares two files *filename1* to *filename2* to determine if they are identical.
# Returns true if content are the same, false otherwise.
# ```
# FileUtils.cmp("foo.cr", "bar.cr")
# ```
def cmp(filename1 : String, filename2 : String)
return false unless File.size(filename1) == File.size(filename2)

@@ -11,6 +35,11 @@ module FileUtils
end
end

# Compares two streams *stream1* to *stream2* to determine if they are identical.
# Returns true if content are the same, false otherwise.
# ```
# FileUtils.cmp(stream1 : IO, stream2 : IO)
# ```
def cmp(stream1 : IO, stream2 : IO)
buf1 = uninitialized UInt8[1024]
buf2 = uninitialized UInt8[1024]
@@ -74,13 +103,108 @@ module FileUtils
end
end

# Creates a new directory at the given *path*. The linux-style permission *mode*
# can be specified, with a default of 777 (0o777).
# Alias of Dir.mkdir
# ```
# FileUtils.mkdir("foo")
# ```
def mkdir(path : String, mode = 0o777) : Nil
Dir.mkdir(path, mode)
end

# Creates a new directory at the given *paths*. The linux-style permission *mode*
# can be specified, with a default of 777 (0o777).
# ```
# FileUtils.mkdir(["foo", "bar"])
# ```
def mkdir(paths : Enumerable(String), mode = 0o777) : Nil
paths.each do |path|
Dir.mkdir(path, mode)
end
end

# Creates a new directory at the given *path*, including any non-existing
# intermediate directories. The linux-style permission *mode* can be specified,
# with a default of 777 (0o777).
# Alias of Dir.mkdir_p
# ```
# FileUtils.mkdir_p("foo")
# ```
def mkdir_p(path : String, mode = 0o777) : Nil
Dir.mkdir_p(path, mode)
end

# Creates a new directory at the given *paths*, including any non-existing
# intermediate directories. The linux-style permission *mode* can be specified,
# with a default of 777 (0o777).
# ```
# FileUtils.mkdir_p(["foo", "bar"])
# ```
def mkdir_p(paths : Enumerable(String), mode = 0o777) : Nil
paths.each do |path|
Dir.mkdir_p(path, mode)
end
end

# Moves *src_path* to *dest_path*.
# Alias of File.rename
# ```
# FileUtils.mv("afile", "afile.cr")
# ```
def mv(src_path : String, dest_path : String) : Nil
File.rename(src_path, dest_path)
end

# Moves every *srcs* to *dest*.
# ```
# FileUtils.mv(["afile", "foo", "bar"], "src")
# ```
def mv(srcs : Enumerable(String), dest : String) : Nil
raise ArgumentError.new("no such directory : #{dest}") unless Dir.exists?(dest)
srcs.each do |src|
begin
mv(src, File.join(dest, File.basename(src)))
rescue Errno
end
end
end

# Returns the current working directory.
# Alias of Dir.current
# ```
# FileUtils.pwd
# ```
def pwd : String
Dir.current
end

# Deletes the *path* file given.
# Alias of File.delete
# ```
# FileUtils.rm("afile.cr")
# ```
def rm(path : String) : Nil
File.delete(path)
end

# Deletes all *paths* file given.
# ```
# FileUtils.rm(["afile.cr", "bfile.cr"])
# ```
def rm(paths : Enumerable(String)) : Nil
paths.each do |path|
File.delete(path)
end
end

# Deletes a file or directory *path*
# If *path* is a directory, this method removes all its contents recursively
# ```
# FileUtils.rm_r("dir")
# FileUtils.rm_r("file.cr")
# ```
def rm_r(path : String)
def rm_r(path : String) : Nil
if Dir.exists?(path) && !File.symlink?(path)
Dir.open(path) do |dir|
dir.each do |entry|
@@ -95,4 +219,63 @@ module FileUtils
File.delete(path)
end
end

# Deletes a list of files or directories *paths*
# If one path is a directory, this method removes all its contents recursively
# ```
# FileUtils.rm_r(["dir", "file.cr"])
# ```
def rm_r(paths : Enumerable(String)) : Nil
paths.each do |path|
rm_r(path)
end
end

# Deletes a file or directory *path*
# If *path* is a directory, this method removes all its contents recursively
# Ignore all errors.
# ```
# FileUtils.rm_rf("dir")
# FileUtils.rm_rf("file.cr")
# FileUtils.rm_rf("non_existent_file")
# ```
def rm_rf(path : String) : Nil
begin
rm_r(path)
rescue Errno
end
end

# Deletes a list of files or directories *paths*
# If one path is a directory, this method removes all its contents recursively
# Ignore all errors.
# ```
# FileUtils.rm_rf(["dir", "file.cr", "non_existent_file"])
# ```
def rm_rf(paths : Enumerable(String)) : Nil
paths.each do |path|
begin
rm_r(path)
rescue Errno
end
end
end

# Removes the directory at the given *path*.
# Alias of Dir.rmdir
# ```
# FileUtils.rmdir("dir")
# ```
def rmdir(path : String) : Nil
Dir.rmdir(path)
end

# Removes all directories at the given *paths*.
# ```
# FileUtils.rmdir(["dir1", "dir2", "dir3"])
def rmdir(paths : Enumerable(String)) : Nil
paths.each do |path|
Dir.rmdir(path)
end
end
end

0 comments on commit 6aa58a3

Please sign in to comment.