Skip to content

Commit 652df9c

Browse files
committed
Fix File.cp/3 in case of a file coping to itself
1 parent dcefbca commit 652df9c

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

lib/elixir/lib/file.ex

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,13 @@ defmodule File do
471471
end
472472
end
473473

474+
defp path_differs?(path, path),
475+
do: false
476+
477+
defp path_differs?(p1, p2) do
478+
Path.expand(p1) !== Path.expand(p2)
479+
end
480+
474481
@doc """
475482
The same as `cp/3`, but raises `File.CopyError` if it fails.
476483
Returns the list of copied files otherwise.
@@ -598,9 +605,7 @@ defmodule File do
598605
copy_file_mode!(src, dest)
599606
[dest|acc]
600607
{:error, :eexist} ->
601-
if callback.(src, dest) do
602-
# If rm/1 fails, copy/2 will fail
603-
_ = rm(dest)
608+
if path_differs?(src, dest) and callback.(src, dest) do
604609
case copy(src, dest) do
605610
{:ok, _} ->
606611
copy_file_mode!(src, dest)
@@ -620,8 +625,8 @@ defmodule File do
620625
:ok ->
621626
[dest|acc]
622627
{:error, :eexist} ->
623-
if callback.(src, dest) do
624-
# If rm/1 fails, iF.make_symlink/2 will fail
628+
if path_differs?(src, dest) and callback.(src, dest) do
629+
# If rm/1 fails, F.make_symlink/2 will fail
625630
_ = rm(dest)
626631
case F.make_symlink(link, dest) do
627632
:ok -> [dest|acc]

lib/elixir/test/elixir/file_test.exs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,19 @@ defmodule FileTest do
129129
end
130130
end
131131

132+
test :cp_file_to_itself do
133+
src = dest = tmp_path("tmp.file")
134+
135+
File.write!(src, "here")
136+
137+
try do
138+
assert File.cp(src, dest) == :ok
139+
assert File.read!(dest) == "here"
140+
after
141+
File.rm(dest)
142+
end
143+
end
144+
132145
test :cp_r_with_src_file_and_dest_file do
133146
src = fixture_path("file.txt")
134147
dest = tmp_path("sample.txt")

0 commit comments

Comments
 (0)