Fix file.remove for windows

The linux version used shutil.rmtree to remove directories. When this hits a
symlink directory in Windows, it removes actual files from the Source.

Created a recursive function to detect symlinks and remove them correctly in
Windows.
This commit is contained in:
twangboy 2015-10-21 17:13:54 -06:00
parent ab18dcf637
commit 2651ce509f

View file

@ -40,6 +40,7 @@ try:
import win32api
import win32file
import win32security
import win32con
from pywintypes import error as pywinerror
HAS_WINDOWS_MODULES = True
except ImportError:
@ -49,7 +50,7 @@ except ImportError:
import salt.utils
from salt.modules.file import (check_hash, # pylint: disable=W0611
directory_exists, get_managed, mkdir, makedirs_, makedirs_perms,
check_managed, check_managed_changes, check_perms, remove, source_list,
check_managed, check_managed_changes, check_perms, source_list,
touch, append, contains, contains_regex, contains_regex_multiline,
contains_glob, find, psed, get_sum, _get_bkroot, _mkstemp_copy,
get_hash, manage_file, file_exists, get_diff, list_backups,
@ -76,7 +77,7 @@ def __virtual__():
global check_perms, get_managed, makedirs_perms, manage_file
global source_list, mkdir, __clean_tmp, makedirs_, file_exists
global check_managed, check_managed_changes, check_file_meta
global remove, append, _error, directory_exists, touch, contains
global append, _error, directory_exists, touch, contains
global contains_regex, contains_regex_multiline, contains_glob
global find, psed, get_sum, check_hash, get_hash, delete_backup
global get_diff, _get_flags, extract_hash, comment_line
@ -95,7 +96,6 @@ def __virtual__():
restore_backup = _namespaced_function(restore_backup, globals())
delete_backup = _namespaced_function(delete_backup, globals())
extract_hash = _namespaced_function(extract_hash, globals())
remove = _namespaced_function(remove, globals())
append = _namespaced_function(append, globals())
check_perms = _namespaced_function(check_perms, globals())
get_managed = _namespaced_function(get_managed, globals())
@ -1035,6 +1035,58 @@ def set_mode(path, mode):
return get_mode(path)
def remove(path, force=False):
'''
Remove the named file or directory
:param str path: The path to the file or directory to remove.
:param bool force: Remove even if marked Read-Only
:return: True if successful, False if unsuccessful
:rtype: bool
CLI Example:
.. code-block:: bash
salt '*' file.remove C:\\Temp
'''
# This must be a recursive function in windows to properly deal with
# Symlinks. The shutil.rmtree function will remove the contents of
# the Symlink source in windows.
path = os.path.expanduser(path)
if not os.path.isabs(path):
raise SaltInvocationError('File path must be absolute.')
# Remove ReadOnly Attribute
if force:
win32api.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL)
try:
if os.path.isfile(path):
# A file and a symlinked file are removed the same way
os.remove(path)
elif is_link(path):
# If it's a symlink directory, use the rmdir command
os.rmdir(path)
else:
for name in os.listdir(path):
item = '{0}\\{1}'.format(path, name)
# If it's a normal directory, recurse to remove it's contents
remove(item)
# rmdir will work now because the directory is empty
os.rmdir(path)
except (OSError, IOError) as exc:
raise CommandExecutionError(
'Could not remove {0!r}: {1}'.format(path, exc)
)
return True
def symlink(src, link):
'''
Create a symbolic link to a file