Files
deskflow/scripts/lib/file_utils.py
Nick Bolton 6399feb324 Solve low hanging reliability and maintainability issues (#7403)
* Add missing atom ctor init

* Init members with `None`

* Use in-class init and delcare getter inside if init

* Temp revert of changes ahead of unit test repair

* Move IPC header to shared, restore X clipboard test, simplify test cmake, new X clipboard unit test

* Suppress sonar for undefs

* Remove base dir include

* Revert "Temp revert of changes ahead of unit test repair"

This reverts commit 8f84b6ea5d5828f1be1362de3809279bcacb8cc8.

* Use new accessor

* Use default dtor

* Beef up to 32 core

* Use enum class

* Make IPC protocol headers const at all levels

* Use enum class and const char for better type safety

* Use unique_ptr for m_clipboard

* Use `-j` instead of `-j8` to utilize full parallelism

* Increase thread count for sonar-scanner

* Use 32 threads

* Use in-class init for IpcClientProxy members

* Use const instead of #define

* Remove ctor member inits

* Use unique_ptr on win

* Implement temp bin dir for windows with more robust post-build copy

* Fixed missing iostream

* Add warning about copy errors

* Only run clean-gcda on Linux

* Use in-class init for IPC mutex

* Do no-op on Windows

* Hide clean-gcda task

* Move flakey test to integtests

* Delete dead code

* Test

* Temp disable post_config_all

* Disable post config step

* Revert "Disable post config step"

This reverts commit 2f956a7714ba9bedacd4b39d4ae00940c3d565d6.

* Revert "Temp disable post_config_all"

This reverts commit b44ed72e44f838bfe1309f6e9672d2f1c6f21b75.

* Restore -j8

* Simplify error handling

* Use const for test port

* Remove python check

* Update changelog

* Fixed order

* Fixed bad issue number

* Fixed bin copy source path

* Remove redundant except
2024-07-18 08:04:39 +01:00

81 lines
2.1 KiB
Python

import glob, os, shutil, sys
import colorama # type: ignore
from colorama import Fore # type: ignore
colorama.init()
class CopyOptions:
def __init__(self, ignore_errors, verbose):
self.ignore_errors = ignore_errors
self.verbose = verbose
class CopyContext:
def __init__(self):
self.errors = 0
self.permission_error = False
def copy(source, target, options):
"""Copy files and directories from source to target."""
context = CopyContext()
if options.verbose:
print(f"Copying files from {source} to {target}")
for match in glob.glob(source):
if os.path.isfile(match):
copy_file(match, target, options, context)
elif os.path.isdir(match):
copy_dir(match, target, options, context)
else:
raise RuntimeError(f"Path {match} is not a file or directory")
if context.errors and options.ignore_errors:
print(
f"{Fore.YELLOW}WARNING:{Fore.RESET} Ignored {context.errors} copy error(s)"
)
if context.permission_error:
print(
f"{Fore.BLUE}HINT:{Fore.RESET} A permission error may mean that the file is in use"
)
def copy_dir(match, target, options, context):
if options.verbose:
print(f"Copying directory {match} to {target}")
try:
shutil.copytree(match, target, dirs_exist_ok=True)
except PermissionError as e:
context.permission_error = True
handle_copy_error(e, options, context)
except Exception as e:
handle_copy_error(e, options, context)
def copy_file(match, target, options, context):
if options.verbose:
print(f"Copying file {match} to {target}")
try:
shutil.copy(match, target)
except PermissionError as e:
context.permission_error = True
handle_copy_error(e, options, context)
except Exception as e:
handle_copy_error(e, options, context)
def handle_copy_error(e, options, context):
context.errors += 1
if not options.ignore_errors:
raise e
else:
print(f"{Fore.YELLOW}WARNING:{Fore.RESET} Copy failed: {e}", file=sys.stderr)