21
21
from contextlib import closing
22
22
from functools import partial , wraps
23
23
24
- from . import copy , errors , fsencode , iotools , tools , walk , wildcard , glob
24
+ from . import copy , errors , fsencode , glob , iotools , tools , walk , wildcard
25
25
from .copy import copy_modified_time
26
26
from .glob import BoundGlobber
27
27
from .mode import validate_open_mode
28
- from .path import abspath , join , normpath
28
+ from .path import abspath , isbase , join , normpath
29
29
from .time import datetime_to_epoch
30
30
from .walk import Walker
31
31
@@ -423,13 +423,17 @@ def copy(
423
423
424
424
"""
425
425
with self ._lock :
426
- if not overwrite and self .exists (dst_path ):
426
+ _src_path = self .validatepath (src_path )
427
+ _dst_path = self .validatepath (dst_path )
428
+ if not overwrite and self .exists (_dst_path ):
427
429
raise errors .DestinationExists (dst_path )
428
- with closing (self .open (src_path , "rb" )) as read_file :
430
+ if _src_path == _dst_path :
431
+ raise errors .IllegalDestination (dst_path )
432
+ with closing (self .open (_src_path , "rb" )) as read_file :
429
433
# FIXME(@althonos): typing complains because open return IO
430
- self .upload (dst_path , read_file ) # type: ignore
434
+ self .upload (_dst_path , read_file ) # type: ignore
431
435
if preserve_time :
432
- copy_modified_time (self , src_path , self , dst_path )
436
+ copy_modified_time (self , _src_path , self , _dst_path )
433
437
434
438
def copydir (
435
439
self ,
@@ -457,11 +461,15 @@ def copydir(
457
461
458
462
"""
459
463
with self ._lock :
460
- if not create and not self .exists (dst_path ):
464
+ _src_path = self .validatepath (src_path )
465
+ _dst_path = self .validatepath (dst_path )
466
+ if isbase (_src_path , _dst_path ):
467
+ raise errors .IllegalDestination (dst_path )
468
+ if not create and not self .exists (_dst_path ):
461
469
raise errors .ResourceNotFound (dst_path )
462
- if not self .getinfo (src_path ).is_dir :
470
+ if not self .getinfo (_src_path ).is_dir :
463
471
raise errors .DirectoryExpected (src_path )
464
- copy .copy_dir (self , src_path , self , dst_path , preserve_time = preserve_time )
472
+ copy .copy_dir (self , _src_path , self , _dst_path , preserve_time = preserve_time )
465
473
466
474
def create (self , path , wipe = False ):
467
475
# type: (Text, bool) -> bool
@@ -1088,6 +1096,12 @@ def movedir(self, src_path, dst_path, create=False, preserve_time=False):
1088
1096
from .move import move_dir
1089
1097
1090
1098
with self ._lock :
1099
+ _src_path = self .validatepath (src_path )
1100
+ _dst_path = self .validatepath (dst_path )
1101
+ if _src_path == _dst_path :
1102
+ return
1103
+ if isbase (_src_path , _dst_path ):
1104
+ raise errors .IllegalDestination (dst_path )
1091
1105
if not create and not self .exists (dst_path ):
1092
1106
raise errors .ResourceNotFound (dst_path )
1093
1107
move_dir (self , src_path , self , dst_path , preserve_time = preserve_time )
@@ -1157,14 +1171,19 @@ def move(self, src_path, dst_path, overwrite=False, preserve_time=False):
1157
1171
``dst_path`` does not exist.
1158
1172
1159
1173
"""
1160
- if not overwrite and self .exists (dst_path ):
1174
+ _src_path = self .validatepath (src_path )
1175
+ _dst_path = self .validatepath (dst_path )
1176
+ if not overwrite and self .exists (_dst_path ):
1161
1177
raise errors .DestinationExists (dst_path )
1162
- if self .getinfo (src_path ).is_dir :
1178
+ if self .getinfo (_src_path ).is_dir :
1163
1179
raise errors .FileExpected (src_path )
1180
+ if _src_path == _dst_path :
1181
+ # early exit when moving a file onto itself
1182
+ return
1164
1183
if self .getmeta ().get ("supports_rename" , False ):
1165
1184
try :
1166
- src_sys_path = self .getsyspath (src_path )
1167
- dst_sys_path = self .getsyspath (dst_path )
1185
+ src_sys_path = self .getsyspath (_src_path )
1186
+ dst_sys_path = self .getsyspath (_dst_path )
1168
1187
except errors .NoSysPath : # pragma: no cover
1169
1188
pass
1170
1189
else :
@@ -1174,15 +1193,15 @@ def move(self, src_path, dst_path, overwrite=False, preserve_time=False):
1174
1193
pass
1175
1194
else :
1176
1195
if preserve_time :
1177
- copy_modified_time (self , src_path , self , dst_path )
1196
+ copy_modified_time (self , _src_path , self , _dst_path )
1178
1197
return
1179
1198
with self ._lock :
1180
- with self .open (src_path , "rb" ) as read_file :
1199
+ with self .open (_src_path , "rb" ) as read_file :
1181
1200
# FIXME(@althonos): typing complains because open return IO
1182
- self .upload (dst_path , read_file ) # type: ignore
1201
+ self .upload (_dst_path , read_file ) # type: ignore
1183
1202
if preserve_time :
1184
- copy_modified_time (self , src_path , self , dst_path )
1185
- self .remove (src_path )
1203
+ copy_modified_time (self , _src_path , self , _dst_path )
1204
+ self .remove (_src_path )
1186
1205
1187
1206
def open (
1188
1207
self ,
0 commit comments