Skip to content

Commit c0bca33

Browse files
committed
add tests
1 parent 1f134d8 commit c0bca33

File tree

2 files changed

+50
-14
lines changed

2 files changed

+50
-14
lines changed

lua/plenary/path.lua

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,17 @@ function Path:rename(opts)
534534
-- The behavior here may differ, as an error will be thrown regardless.
535535

536536
local self_lstat, new_lstat, status, errmsg
537+
vim.validate { opts = { opts, "t" } }
538+
vim.validate {
539+
["opts.new_name"] = {
540+
opts.new_name,
541+
function(val)
542+
return Path.is_path(val) or (type(val) == "string" and val ~= "")
543+
end,
544+
"string or Path object",
545+
},
546+
}
537547
opts = opts or {}
538-
assert(opts.new_name and opts.new_name ~= "", "Please provide the new name!")
539548
self_lstat, errmsg = uv.fs_lstat(self.filename)
540549

541550
-- Cannot rename a non-existing path (lstat is needed here, `Path:exists()`
@@ -544,6 +553,10 @@ function Path:rename(opts)
544553

545554
local new_path = Path:new(opts.new_name)
546555
new_lstat, errmsg = uv.fs_lstat(new_path.filename)
556+
local same_inode = false
557+
if new_lstat then
558+
same_inode = self_lstat.ino == new_lstat.ino and self_lstat.dev == new_lstat.dev and self_lstat.gen == new_lstat.gen
559+
end
547560

548561
-- The following allows changing only case (e.g. fname -> Fname) on
549562
-- case-insensitive file systems, otherwise throwing if `new_name` exists as
@@ -558,19 +571,14 @@ function Path:rename(opts)
558571
-- idk for certain what happens b/c it needs to be tested on a case-sensitive
559572
-- fs, but it should simply result in a successful no-op according to the
560573
-- `rename(2)` docs, at least on Linux anyway).
561-
assert(not new_lstat or (self_lstat.ino == new_lstat.ino), "File or directory already exists!")
574+
assert(not new_lstat or same_inode, "File or directory already exists!")
562575

563-
status, errmsg = uv.fs_rename(self:absolute(), new_path:absolute())
576+
status, errmsg = uv.fs_rename(tostring(self), tostring(new_path))
564577
assert(status, ("%s: Rename failed!"):format(errmsg))
565578

566579
-- NOTE: `uv.fs_rename()` _can_ return success even if no rename actually
567-
-- occurred (see rename(2)), and this is not an error. So we're not changing
568-
-- `self.filename` if it didn't.
569-
if not uv.fs_lstat(self.filename) then
570-
self = Path:new(new_path.filename)
571-
end
572-
573-
return self
580+
-- occurred (see rename(2)), and this is not an error.
581+
return Path:new(new_path)
574582
end
575583

576584
--- Copy files or folders with defaults akin to GNU's `cp`.

tests/plenary/path_spec.lua

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,6 @@ describe("Path", function()
415415
end)
416416
end)
417417

418-
-- TODO: tests new behavior, allows rename to self
419418
describe("rename", function()
420419
local env = new_env()
421420
after_each(env.cleanup)
@@ -497,7 +496,7 @@ describe("Path", function()
497496
-- BUG: introduced in f71ee45 (#90)
498497
it("should consider bad symlink as existing, and throw", function()
499498
local before, after, non_existing = env.new_path { touch = true }, env.new_path(), env.new_path()
500-
vim.loop.fs_symlink(non_existing.filename, after.filename)
499+
assert(vim.loop.fs_symlink(non_existing.filename, after.filename))
501500
assert.is.True(not not vim.loop.fs_lstat(after.filename))
502501
assert.errors(function()
503502
before:rename { new_name = after }
@@ -511,9 +510,38 @@ describe("Path", function()
511510
assert.is.False(before:exists())
512511
assert.is.True(after:exists())
513512
assert.is.True(Path.is_path(new))
513+
assert.is.True(new:exists())
514514
assert.are.equal(before.filename, before_filename)
515-
assert.are.Not.equal(new, after)
516-
assert.are.Not.equal(new, before)
515+
assert.are.equal(after.filename, new.filename)
516+
end)
517+
518+
it("should allow changing only case of filename, regardless of fs case-sensitivity", function()
519+
local before = env.new_path { filename = ".__some_file" }
520+
assert.is.False(before:exists())
521+
before:touch()
522+
local before_filename_realpath = assert(vim.loop.fs_realpath(before.filename))
523+
local after = env.new_path { filename = before.filename:upper() }
524+
assert.does.Not.error(function()
525+
before:rename { new_name = after }
526+
end)
527+
assert.are.equal(
528+
before_filename_realpath:sub(1, #before_filename_realpath - #before.filename) .. after.filename,
529+
assert(vim.loop.fs_realpath(after.filename))
530+
)
531+
end)
532+
533+
it("rename to hardlink of the same file should be a successful no-op", function()
534+
local before, after = env.new_path { touch = true }, env.new_path {}
535+
assert(vim.loop.fs_link(before.filename, after.filename))
536+
assert.is.True(after:exists())
537+
local new
538+
assert.does.Not.error(function()
539+
new = before:rename { new_name = after }
540+
end)
541+
assert.is.True(before:exists())
542+
assert.is.True(after:exists())
543+
assert.is.True(Path.is_path(new))
544+
assert.are.equal(new.filename, after.filename)
517545
end)
518546
end)
519547

0 commit comments

Comments
 (0)