@@ -635,6 +635,203 @@ describe("Path2", function()
635635 end )
636636 end )
637637
638+ describe (" copy" , function ()
639+ after_each (function ()
640+ uv .fs_unlink " a_random_filename.rs"
641+ uv .fs_unlink " not_a_random_filename.rs"
642+ uv .fs_unlink " some_random_filename.rs"
643+ uv .fs_unlink " ../some_random_filename.rs"
644+ Path :new (" src" ):rm { recursive = true }
645+ Path :new (" trg" ):rm { recursive = true }
646+ end )
647+
648+ it_cross_plat (" can copy a file with string destination" , function ()
649+ local p1 = Path :new " a_random_filename.rs"
650+ local p2 = Path :new " not_a_random_filename.rs"
651+ p1 :touch ()
652+ assert .is_true (p1 :exists ())
653+
654+ assert .no_error (function ()
655+ p1 :copy { destination = " not_a_random_filename.rs" }
656+ end )
657+ assert .is_true (p1 :exists ())
658+ assert .are .same (p1 .filename , " a_random_filename.rs" )
659+ assert .are .same (p2 .filename , " not_a_random_filename.rs" )
660+ end )
661+
662+ it_cross_plat (" can copy a file with Path destination" , function ()
663+ local p1 = Path :new " a_random_filename.rs"
664+ local p2 = Path :new " not_a_random_filename.rs"
665+ p1 :touch ()
666+ assert .is_true (p1 :exists ())
667+
668+ assert .no_error (function ()
669+ p1 :copy { destination = p2 }
670+ end )
671+ assert .is_true (p1 :exists ())
672+ assert .is_true (p2 :exists ())
673+ assert .are .same (p1 .filename , " a_random_filename.rs" )
674+ assert .are .same (p2 .filename , " not_a_random_filename.rs" )
675+ end )
676+
677+ it_cross_plat (" can copy to parent dir" , function ()
678+ local p = Path :new " some_random_filename.rs"
679+ p :touch ()
680+ assert .is_true (p :exists ())
681+
682+ assert .no_error (function ()
683+ p :copy { destination = " ../some_random_filename.rs" }
684+ end )
685+ assert .is_true (p :exists ())
686+ end )
687+
688+ it_cross_plat (" cannot copy an existing file if override false" , function ()
689+ local p1 = Path :new " a_random_filename.rs"
690+ local p2 = Path :new " not_a_random_filename.rs"
691+ p1 :touch ()
692+ p2 :touch ()
693+ assert .is_true (p1 :exists ())
694+ assert .is_true (p2 :exists ())
695+
696+ assert (pcall (p1 .copy , p1 , { destination = " not_a_random_filename.rs" , override = false }))
697+ assert .no_error (function ()
698+ p1 :copy { destination = " not_a_random_filename.rs" , override = false }
699+ end )
700+ assert .are .same (p1 .filename , " a_random_filename.rs" )
701+ assert .are .same (p2 .filename , " not_a_random_filename.rs" )
702+ end )
703+
704+ it_cross_plat (" fails when copying folders non-recursively" , function ()
705+ local src_dir = Path :new " src"
706+ src_dir :mkdir ()
707+ src_dir :joinpath (" file1.lua" ):touch ()
708+
709+ local trg_dir = Path :new " trg"
710+ assert .has_error (function ()
711+ src_dir :copy { destination = trg_dir , recursive = false }
712+ end )
713+ end )
714+
715+ describe (" can copy directories recursively" , function ()
716+ local src_dir = Path :new " src"
717+ local trg_dir = Path :new " trg"
718+
719+ local files = { " file1" , " file2" , " .file3" }
720+ -- set up sub directory paths for creation and testing
721+ local sub_dirs = { " sub_dir1" , " sub_dir1/sub_dir2" }
722+ local src_dirs = { src_dir }
723+ local trg_dirs = { trg_dir }
724+ -- {src, trg}_dirs is a table with all directory levels by {src, trg}
725+ for _ , dir in ipairs (sub_dirs ) do
726+ table.insert (src_dirs , src_dir :joinpath (dir ))
727+ table.insert (trg_dirs , trg_dir :joinpath (dir ))
728+ end
729+
730+ -- vim.tbl_flatten doesn't work here as copy doesn't return a list
731+ local function flatten (ret , t )
732+ for _ , v in pairs (t ) do
733+ if type (v ) == " table" then
734+ flatten (ret , v )
735+ else
736+ table.insert (ret , v )
737+ end
738+ end
739+ end
740+
741+ before_each (function ()
742+ -- generate {file}_{level}.lua on every directory level in src
743+ -- src
744+ -- ├── file1_1.lua
745+ -- ├── file2_1.lua
746+ -- ├── .file3_1.lua
747+ -- └── sub_dir1
748+ -- ├── file1_2.lua
749+ -- ├── file2_2.lua
750+ -- ├── .file3_2.lua
751+ -- └── sub_dir2
752+ -- ├── file1_3.lua
753+ -- ├── file2_3.lua
754+ -- └── .file3_3.lua
755+
756+ src_dir :mkdir ()
757+
758+ for _ , file in ipairs (files ) do
759+ for level , dir in ipairs (src_dirs ) do
760+ local p = dir :joinpath (file .. " _" .. level .. " .lua" )
761+ p :touch { parents = true , exists_ok = true }
762+ assert .is_true (p :exists ())
763+ end
764+ end
765+ end )
766+
767+ it_cross_plat (" hidden=true, override=true" , function ()
768+ local success
769+ assert .no_error (function ()
770+ success = src_dir :copy { destination = trg_dir , recursive = true , override = true , hidden = true }
771+ end )
772+
773+ assert .not_nil (success )
774+ assert .are .same (9 , vim .tbl_count (success ))
775+ for _ , res in pairs (success ) do
776+ assert .is_true (res .success )
777+ end
778+ end )
779+
780+ it_cross_plat (" hidden=true, override=false" , function ()
781+ -- setup
782+ assert .no_error (function ()
783+ src_dir :copy { destination = trg_dir , recursive = true , override = true , hidden = true }
784+ end )
785+
786+ local success
787+ assert .no_error (function ()
788+ success = src_dir :copy { destination = trg_dir , recursive = true , override = false , hidden = true }
789+ end )
790+
791+ assert .not_nil (success )
792+ assert .are .same (9 , vim .tbl_count (success ))
793+ for _ , res in pairs (success ) do
794+ assert .is_false (res .success )
795+ assert .not_nil (res .err )
796+ assert .not_nil (res .err :match " ^EEXIST:" )
797+ end
798+ end )
799+
800+ it_cross_plat (" hidden=false, override=true" , function ()
801+ local success
802+ assert .no_error (function ()
803+ success = src_dir :copy { destination = trg_dir , recursive = true , override = true , hidden = false }
804+ end )
805+
806+ assert .not_nil (success )
807+ assert .are .same (6 , vim .tbl_count (success ))
808+ for _ , res in pairs (success ) do
809+ assert .is_true (res .success )
810+ end
811+ end )
812+
813+ it_cross_plat (" hidden=false, override=false" , function ()
814+ -- setup
815+ assert .no_error (function ()
816+ src_dir :copy { destination = trg_dir , recursive = true , override = true , hidden = true }
817+ end )
818+
819+ local success
820+ assert .no_error (function ()
821+ success = src_dir :copy { destination = trg_dir , recursive = true , override = false , hidden = false }
822+ end )
823+
824+ assert .not_nil (success )
825+ assert .are .same (6 , vim .tbl_count (success ))
826+ for _ , res in pairs (success ) do
827+ assert .is_false (res .success )
828+ assert .not_nil (res .err )
829+ assert .not_nil (res .err :match " ^EEXIST:" )
830+ end
831+ end )
832+ end )
833+ end )
834+
638835 describe (" parents" , function ()
639836 it_cross_plat (" should extract the ancestors of the path" , function ()
640837 local p = Path :new (vim .fn .getcwd ())
0 commit comments