Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 18 additions & 35 deletions file_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,46 +99,29 @@ def list_folders_in_directory(directory):
return folders


# delete a folder and all its subfolders and files
def delete_folder(folder_name):
if os.path.exists(folder_name):
# Use writable-aware deletion so read-only files (e.g. .git objects on Windows) don't cause PermissionError
delete_files_and_subfolders(folder_name)
_make_writable(folder_name)
os.rmdir(folder_name)
def _on_rm_error(func, path, _exc_info):
"""On Windows, clear read-only flag and retry the removal."""
os.chmod(path, stat.S_IWRITE)
func(path)


def _make_writable(path: str) -> None:
"""On Windows, clear read-only so deletion can succeed."""
# TODO - Check if this can be done in a cleaner way.
is_windows = os.name == "nt"
if is_windows:
try:
mode = os.stat(path).st_mode
os.chmod(path, mode | stat.S_IWRITE)
except OSError:
pass
def delete_folder(folder_name):
"""Delete a folder and all its subfolders and files."""
if os.path.exists(folder_name):
shutil.rmtree(folder_name, onerror=_on_rm_error)


def delete_files_and_subfolders(directory):
total_files_deleted = 0
total_folders_deleted = 0

# Walk the directory in reverse order (bottom-up)
for root, dirs, files in os.walk(directory, topdown=False):
# Delete files
for file in files:
file_path = os.path.join(root, file)
_make_writable(file_path)
os.remove(file_path)
total_files_deleted += 1

# Delete directories
for dir_ in dirs:
dir_path = os.path.join(root, dir_)
_make_writable(dir_path)
os.rmdir(dir_path)
total_folders_deleted += 1
"""Delete all contents of a directory but keep the directory itself."""
for entry in os.scandir(directory):
if entry.is_dir(follow_symlinks=False):
shutil.rmtree(entry.path, onerror=_on_rm_error)
else:
try:
os.remove(entry.path)
except PermissionError:
os.chmod(entry.path, stat.S_IWRITE)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the permissions weren't the reason the os.remove fails then this causes the process to crash?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess it would cause the process to crash if there's a different reason. But that would happen now too and we can handle that when we find such a case. Nice find though.

os.remove(entry.path)


def copy_file(source_path, destination_path):
Expand Down
Loading