refactor: move optional scripts to external repo
This commit is contained in:
parent
ccc60ff900
commit
98eb89255d
9 changed files with 5 additions and 592 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -10,7 +10,6 @@
|
||||||
/tmp
|
/tmp
|
||||||
/vcpkg
|
/vcpkg
|
||||||
/vcpkg_installed
|
/vcpkg_installed
|
||||||
/scripts/**/*.pyc
|
|
||||||
/.cache
|
/.cache
|
||||||
/.venv
|
/.venv
|
||||||
aqtinstall.log
|
aqtinstall.log
|
||||||
|
|
@ -37,3 +36,6 @@ CMakeFiles/*
|
||||||
|
|
||||||
# vscode folder
|
# vscode folder
|
||||||
/.vscode
|
/.vscode
|
||||||
|
|
||||||
|
# scripts folder
|
||||||
|
/scripts
|
||||||
|
|
|
||||||
|
|
@ -1,156 +0,0 @@
|
||||||
# Deskflow -- mouse and keyboard sharing utility
|
|
||||||
# Copyright (C) 2024 Symless Ltd.
|
|
||||||
#
|
|
||||||
# This package is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# found in the file LICENSE that should have accompanied this file.
|
|
||||||
#
|
|
||||||
# This package is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import lib.env as env
|
|
||||||
|
|
||||||
try:
|
|
||||||
import colorama # type: ignore
|
|
||||||
from colorama import Fore # type: ignore
|
|
||||||
|
|
||||||
colorama.init()
|
|
||||||
except ImportError:
|
|
||||||
|
|
||||||
class Fore:
|
|
||||||
RESET = ""
|
|
||||||
YELLOW = ""
|
|
||||||
|
|
||||||
|
|
||||||
def has_command(command):
|
|
||||||
platform = sys.platform
|
|
||||||
if platform == "win32":
|
|
||||||
cmd = f"where {command}"
|
|
||||||
else:
|
|
||||||
cmd = f"which {command}"
|
|
||||||
try:
|
|
||||||
subprocess.check_output(cmd, shell=True)
|
|
||||||
return True
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def strip_continuation_sequences(command, strip_newlines=True):
|
|
||||||
"""
|
|
||||||
Remove the continuation sequences (\\) from a command.
|
|
||||||
|
|
||||||
To spread strings over multiple lines in YAML files, like in bash, a backslash is used at
|
|
||||||
the end of each line as continuation character.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if isinstance(command, list):
|
|
||||||
raise ValueError("List commands are not supported")
|
|
||||||
|
|
||||||
cmd_continuation = " \\"
|
|
||||||
command = command.replace(cmd_continuation, "")
|
|
||||||
|
|
||||||
# Some versions of pyyaml will remove the newlines already, so always stripping
|
|
||||||
# makes the output more consistent.
|
|
||||||
if strip_newlines:
|
|
||||||
command = command.replace("\n", " ")
|
|
||||||
|
|
||||||
return command
|
|
||||||
|
|
||||||
|
|
||||||
def run(
|
|
||||||
command,
|
|
||||||
check=True, # true by default to fail fast
|
|
||||||
shell=False, # false by default for security
|
|
||||||
get_output=False,
|
|
||||||
print_cmd=False, # false by default for security
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Convenience wrapper around `subprocess.run` to:
|
|
||||||
- print the command before running it (if `print_cmd` is True)
|
|
||||||
|
|
||||||
This differs to `subprocess.run` in that by default it:
|
|
||||||
- checks the return code by default
|
|
||||||
- prints list commands as a readable string on failure
|
|
||||||
|
|
||||||
This is the same as `subprocess.run` in that it:
|
|
||||||
- does not use shell by default for security (shell is less secure)
|
|
||||||
|
|
||||||
Args:
|
|
||||||
command (str or list): The command to run.
|
|
||||||
check (bool): Raise an exception if the command fails.
|
|
||||||
shell (bool): Run the command in a shell (false by default for security)
|
|
||||||
get_output (bool): Return the output of the command.
|
|
||||||
print_cmd (bool): Print the command before running it (false by default for security)
|
|
||||||
"""
|
|
||||||
|
|
||||||
is_list_cmd = isinstance(command, list)
|
|
||||||
|
|
||||||
# create string version of list command, only for debugging purposes
|
|
||||||
command_str = command
|
|
||||||
if is_list_cmd:
|
|
||||||
command_str = " ".join(command)
|
|
||||||
|
|
||||||
if print_cmd:
|
|
||||||
print(f"Running: {command_str}")
|
|
||||||
else:
|
|
||||||
print("Running command...")
|
|
||||||
command_str = "***"
|
|
||||||
|
|
||||||
# TODO: You can definitely use a list command with shell=True on Windows,
|
|
||||||
# but can you use a string command with shell=False on Windows?
|
|
||||||
#
|
|
||||||
# The `subprocess.run` function has a little gotcha:
|
|
||||||
# - a string command must be used when `shell=True`
|
|
||||||
# - a list command must be used when shell isn't or `shell=False`
|
|
||||||
# however, it allows you to pass a string command when shell isn't used or `shell=False`
|
|
||||||
# then fails with a vague error message. same problem with list commands and `shell=True`
|
|
||||||
if not env.is_windows() and is_list_cmd and shell:
|
|
||||||
raise ValueError("List commands cannot be used when shell=True on Unix systems")
|
|
||||||
elif not is_list_cmd and not shell:
|
|
||||||
raise ValueError("String commands cannot be used when shell=False or not set")
|
|
||||||
|
|
||||||
# Flush the output to ensure the command is printed before the output of the command,
|
|
||||||
# which seems to happen in the GitHub runner logs.
|
|
||||||
sys.stdout.flush()
|
|
||||||
sys.stderr.flush()
|
|
||||||
|
|
||||||
try:
|
|
||||||
if get_output:
|
|
||||||
result = subprocess.run(
|
|
||||||
command,
|
|
||||||
shell=shell,
|
|
||||||
check=check,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
text=True,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
result = subprocess.run(command, check=check, shell=shell)
|
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
# Take control of how failed commands are printed:
|
|
||||||
# - if `print_cmd` is false, it will print `***` instead of the command
|
|
||||||
# - if the command was a list, the command is printed as a readable string
|
|
||||||
raise RuntimeError(
|
|
||||||
f"Command exited with code {e.returncode}: {command_str}"
|
|
||||||
) from None
|
|
||||||
except Exception:
|
|
||||||
# Take control of how failed commands are printed:
|
|
||||||
# - if `print_cmd` is false, it will print `***` instead of the command
|
|
||||||
# - if the command was a list, the command is printed as a readable string
|
|
||||||
raise RuntimeError(f"Command failed: {command_str}")
|
|
||||||
|
|
||||||
if result.returncode != 0:
|
|
||||||
print(
|
|
||||||
f"{Fore.YELLOW}Command exited with code {result.returncode}:{Fore.RESET} {command_str}",
|
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
# Deskflow -- mouse and keyboard sharing utility
|
|
||||||
# Copyright (C) 2024 Symless Ltd.
|
|
||||||
#
|
|
||||||
# This package is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# found in the file LICENSE that should have accompanied this file.
|
|
||||||
#
|
|
||||||
# This package is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import colorama # type: ignore
|
|
||||||
from colorama import Fore # type: ignore
|
|
||||||
|
|
||||||
colorama.init()
|
|
||||||
|
|
||||||
SUCCESS_TEXT = f"{Fore.LIGHTGREEN_EX}Success:{Fore.RESET}"
|
|
||||||
ERROR_TEXT = f"{Fore.LIGHTRED_EX}Error:{Fore.RESET}"
|
|
||||||
WARNING_TEXT = f"{Fore.LIGHTYELLOW_EX}Warning:{Fore.RESET}"
|
|
||||||
HINT_TEXT = f"{Fore.LIGHTBLUE_EX}Hint:{Fore.RESET}"
|
|
||||||
|
|
@ -1,269 +0,0 @@
|
||||||
# Deskflow -- mouse and keyboard sharing utility
|
|
||||||
# Copyright (C) 2024 Symless Ltd.
|
|
||||||
#
|
|
||||||
# This package is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# found in the file LICENSE that should have accompanied this file.
|
|
||||||
#
|
|
||||||
# This package is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import os, sys, subprocess
|
|
||||||
import lib.cmd_utils as cmd_utils
|
|
||||||
|
|
||||||
# The `.venv` dir seems to be most common for virtual environments.
|
|
||||||
VENV_DIR = ".venv"
|
|
||||||
|
|
||||||
|
|
||||||
def check_module(module):
|
|
||||||
try:
|
|
||||||
__import__(module)
|
|
||||||
return True
|
|
||||||
except ImportError:
|
|
||||||
print(f"Python is missing {module} module", file=sys.stderr)
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_os():
|
|
||||||
"""Detects the operating system."""
|
|
||||||
if sys.platform == "win32":
|
|
||||||
return "windows"
|
|
||||||
elif sys.platform == "darwin":
|
|
||||||
return "mac"
|
|
||||||
elif sys.platform.startswith("linux"):
|
|
||||||
return "linux"
|
|
||||||
else:
|
|
||||||
raise RuntimeError(f"Unsupported platform: {sys.platform}")
|
|
||||||
|
|
||||||
|
|
||||||
def is_windows():
|
|
||||||
return get_os() == "windows"
|
|
||||||
|
|
||||||
|
|
||||||
def is_mac():
|
|
||||||
return get_os() == "mac"
|
|
||||||
|
|
||||||
|
|
||||||
def is_linux():
|
|
||||||
return get_os() == "linux"
|
|
||||||
|
|
||||||
|
|
||||||
def get_linux_distro():
|
|
||||||
"""Detects the Linux distro."""
|
|
||||||
os_file = "/etc/os-release"
|
|
||||||
name = None
|
|
||||||
name_like = None
|
|
||||||
version_id = None
|
|
||||||
version_codename = None
|
|
||||||
|
|
||||||
if os.path.isfile(os_file):
|
|
||||||
with open(os_file) as f:
|
|
||||||
for line in f:
|
|
||||||
if line.startswith("ID="):
|
|
||||||
name = line.strip().split("=")[1].strip('"')
|
|
||||||
elif line.startswith("ID_LIKE="):
|
|
||||||
name_like = line.strip().split("=")[1].strip('"')
|
|
||||||
elif line.startswith("VERSION_ID="):
|
|
||||||
version_id = line.strip().split("=")[1].strip('"')
|
|
||||||
elif line.startswith("VERSION_CODENAME="):
|
|
||||||
version_codename = line.strip().split("=")[1].strip('"')
|
|
||||||
|
|
||||||
return name, name_like, version_id or version_codename
|
|
||||||
|
|
||||||
|
|
||||||
def get_env(name, required=True, default=None):
|
|
||||||
"""
|
|
||||||
Returns an env var (stripped) or optionally raises an error if not set.
|
|
||||||
|
|
||||||
If `default` is set, it will be returned even if `required` is True.
|
|
||||||
"""
|
|
||||||
value = os.getenv(name)
|
|
||||||
if value:
|
|
||||||
value = value.strip()
|
|
||||||
|
|
||||||
if not value:
|
|
||||||
if default:
|
|
||||||
return default
|
|
||||||
elif required:
|
|
||||||
raise ValueError(f"Required env var not set: {name}")
|
|
||||||
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
def get_env_bool(name, default=False):
|
|
||||||
"""Returns a boolean value from an env var (stripped)."""
|
|
||||||
value = os.getenv(name)
|
|
||||||
if value:
|
|
||||||
value = value.strip()
|
|
||||||
|
|
||||||
if value is None:
|
|
||||||
return default
|
|
||||||
|
|
||||||
return value.lower() in ["true", "1", "yes"]
|
|
||||||
|
|
||||||
|
|
||||||
def get_venv_executable(binary="python"):
|
|
||||||
if sys.platform == "win32":
|
|
||||||
return os.path.join(VENV_DIR, "Scripts", binary)
|
|
||||||
else:
|
|
||||||
return os.path.join(VENV_DIR, "bin", binary)
|
|
||||||
|
|
||||||
|
|
||||||
def in_venv():
|
|
||||||
"""Returns True if the script is running in a Python virtual environment."""
|
|
||||||
return sys.prefix != sys.base_prefix
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_in_venv(script_file, create_venv=False):
|
|
||||||
"""
|
|
||||||
Ensures the script is running in a Python virtual environment (venv).
|
|
||||||
If the script is not running in a venv, it will create one and re-run the script in the venv.
|
|
||||||
"""
|
|
||||||
|
|
||||||
check_dependencies(raise_error=True)
|
|
||||||
import venv
|
|
||||||
|
|
||||||
if in_venv():
|
|
||||||
print(f"Running in venv, executable: {sys.executable}", flush=True)
|
|
||||||
return
|
|
||||||
|
|
||||||
if create_venv and not os.path.exists(VENV_DIR):
|
|
||||||
print(f"Creating virtual environment at {VENV_DIR}")
|
|
||||||
venv.create(VENV_DIR, with_pip=True)
|
|
||||||
|
|
||||||
if os.path.exists(VENV_DIR):
|
|
||||||
script_file_abs = os.path.abspath(script_file)
|
|
||||||
print(f"Using virtual environment for: {script_file_abs}", flush=True)
|
|
||||||
python_executable = get_venv_executable()
|
|
||||||
result = subprocess.run([python_executable, script_file_abs] + sys.argv[1:])
|
|
||||||
sys.exit(result.returncode)
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
"The Python virtual environment (.venv) needs to be created before you can "
|
|
||||||
"run this script.\n"
|
|
||||||
"Please run: scripts/setup_venv.py"
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def install_requirements():
|
|
||||||
"""
|
|
||||||
Uses `pip` to install required Python modules from the `requirements.txt` file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
check_dependencies(raise_error=True)
|
|
||||||
|
|
||||||
print("Updating pip...")
|
|
||||||
cmd_utils.run(
|
|
||||||
[sys.executable, "-m", "pip", "install", "--upgrade", "pip"],
|
|
||||||
shell=False,
|
|
||||||
print_cmd=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
print("Installing required modules...")
|
|
||||||
cmd_utils.run(
|
|
||||||
[sys.executable, "-m", "pip", "install", "-e", "scripts"],
|
|
||||||
shell=False,
|
|
||||||
print_cmd=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def check_dependencies(raise_error=False):
|
|
||||||
"""
|
|
||||||
Returns True if pip and venv are available.
|
|
||||||
"""
|
|
||||||
|
|
||||||
has_pip = check_module("pip")
|
|
||||||
has_venv = check_module("venv")
|
|
||||||
|
|
||||||
if raise_error:
|
|
||||||
if not has_pip:
|
|
||||||
raise RuntimeError("Python is missing pip")
|
|
||||||
if not has_venv:
|
|
||||||
raise RuntimeError("Python is missing venv")
|
|
||||||
else:
|
|
||||||
return has_pip and has_venv
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_dependencies():
|
|
||||||
"""
|
|
||||||
Ensures that pip and venv are available, and installs them if they are not.
|
|
||||||
This is normally only installs on Linux, as Windows and Mac usually come with pip and venv.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if check_dependencies():
|
|
||||||
return
|
|
||||||
|
|
||||||
print("Installing Python dependencies...")
|
|
||||||
|
|
||||||
os = get_os()
|
|
||||||
if os != "linux":
|
|
||||||
# should not be a problem, since windows and mac come with pip and venv
|
|
||||||
raise RuntimeError(f"Unable to install Python dependencies on {os}")
|
|
||||||
|
|
||||||
has_sudo = cmd_utils.has_command("sudo")
|
|
||||||
sudo = "sudo" if has_sudo else ""
|
|
||||||
|
|
||||||
distro, distro_like, _version = get_linux_distro()
|
|
||||||
if not distro_like:
|
|
||||||
distro_like = distro
|
|
||||||
|
|
||||||
update_cmd = None
|
|
||||||
install_cmd = None
|
|
||||||
if distro == "rhel" or "rhel" in distro_like:
|
|
||||||
update_cmd = "yum check-update"
|
|
||||||
install_cmd = "yum install -y python3-pip" # rhel-like has venv already
|
|
||||||
elif "debian" in distro_like:
|
|
||||||
update_cmd = "apt update"
|
|
||||||
install_cmd = "apt install -y python3-pip python3-venv"
|
|
||||||
elif "fedora" in distro_like:
|
|
||||||
update_cmd = "dnf check-update"
|
|
||||||
install_cmd = "dnf install -y python3-pip python3-virtualenv"
|
|
||||||
elif "arch" in distro_like:
|
|
||||||
install_cmd = "pacman -Syu --noconfirm python-pip python-virtualenv"
|
|
||||||
elif "opensuse" in distro_like:
|
|
||||||
update_cmd = "zypper refresh"
|
|
||||||
install_cmd = "zypper install -y python3-pip python3-virtualenv"
|
|
||||||
else:
|
|
||||||
raise RuntimeError(f"Unable to install Python dependencies on {distro}")
|
|
||||||
|
|
||||||
if update_cmd:
|
|
||||||
# don't check the return code, as some package managers return non-zero exit codes
|
|
||||||
# under normal circumstances (e.g. dnf check-update returns 100 when there are
|
|
||||||
# updates available).
|
|
||||||
cmd_utils.run(
|
|
||||||
f"{sudo} {update_cmd}".strip(), check=False, shell=True, print_cmd=True
|
|
||||||
)
|
|
||||||
|
|
||||||
cmd_utils.run(f"{sudo} {install_cmd}".strip(), shell=True, print_cmd=True)
|
|
||||||
|
|
||||||
|
|
||||||
def import_colors():
|
|
||||||
import lib.colors as colors
|
|
||||||
|
|
||||||
return colors
|
|
||||||
|
|
||||||
|
|
||||||
def persist_lock_file(path):
|
|
||||||
"""
|
|
||||||
Persists a lock file and ensures the directory part of the path exists.
|
|
||||||
"""
|
|
||||||
dir_path = os.path.dirname(path)
|
|
||||||
if not os.path.exists(dir_path):
|
|
||||||
os.makedirs(dir_path, exist_ok=True)
|
|
||||||
|
|
||||||
with open(path, "w") as f:
|
|
||||||
f.write(str(os.getpid()))
|
|
||||||
|
|
||||||
|
|
||||||
def remove_lock_file(path):
|
|
||||||
"""
|
|
||||||
Removes a lock file if it exists.
|
|
||||||
"""
|
|
||||||
if os.path.exists(path):
|
|
||||||
os.remove(path)
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
# Deskflow -- mouse and keyboard sharing utility
|
|
||||||
# Copyright (C) 2024 Symless Ltd.
|
|
||||||
#
|
|
||||||
# This package is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# found in the file LICENSE that should have accompanied this file.
|
|
||||||
#
|
|
||||||
# This package is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import os, fnmatch
|
|
||||||
|
|
||||||
|
|
||||||
def find_files(search_dirs, include_files, exclude_dirs=[]):
|
|
||||||
"""Recursively find files, excluding specified directories"""
|
|
||||||
matches = []
|
|
||||||
for dir in search_dirs:
|
|
||||||
for root, dirnames, filenames in os.walk(dir):
|
|
||||||
dirnames[:] = [d for d in dirnames if d not in exclude_dirs]
|
|
||||||
|
|
||||||
for pattern in include_files:
|
|
||||||
for filename in fnmatch.filter(filenames, pattern):
|
|
||||||
matches.append(os.path.join(root, filename))
|
|
||||||
return matches
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# Deskflow -- mouse and keyboard sharing utility
|
|
||||||
# Copyright (C) 2024 Symless Ltd.
|
|
||||||
#
|
|
||||||
# This package is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# found in the file LICENSE that should have accompanied this file.
|
|
||||||
#
|
|
||||||
# This package is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import lib.env as env
|
|
||||||
|
|
||||||
env.ensure_in_venv(__file__)
|
|
||||||
|
|
||||||
import argparse, sys
|
|
||||||
import lib.fs as fs
|
|
||||||
from clang_format import clang_format # type: ignore
|
|
||||||
|
|
||||||
include_files = [
|
|
||||||
"*.h",
|
|
||||||
"*.c",
|
|
||||||
"*.hpp",
|
|
||||||
"*.cpp",
|
|
||||||
"*.m",
|
|
||||||
"*.mm",
|
|
||||||
]
|
|
||||||
|
|
||||||
dirs = ["src"]
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
"""
|
|
||||||
Cross-platform equivalent of using find and xargs with clang-format.
|
|
||||||
Lints by performing a dry run (--dry-run) which fails when formatting is needed.
|
|
||||||
"""
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"-f",
|
|
||||||
"--format",
|
|
||||||
action="store_true",
|
|
||||||
help="In-place format all files",
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
cmd_args = ["-i"] if args.format else ["--dry-run", "--Werror"]
|
|
||||||
files_recursive = fs.find_files(dirs, include_files)
|
|
||||||
|
|
||||||
if args.format:
|
|
||||||
print("Formatting files with Clang formatter:")
|
|
||||||
else:
|
|
||||||
print("Checking files with Clang formatter:")
|
|
||||||
|
|
||||||
for file in files_recursive:
|
|
||||||
print(file)
|
|
||||||
|
|
||||||
if files_recursive:
|
|
||||||
sys.argv = [""] + cmd_args + files_recursive
|
|
||||||
result = clang_format()
|
|
||||||
if result == 0:
|
|
||||||
print("Clang lint passed")
|
|
||||||
|
|
||||||
sys.exit(result)
|
|
||||||
else:
|
|
||||||
print("No files for Clang to process", file=sys.stderr)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
[project]
|
|
||||||
name = "scripts"
|
|
||||||
version = "0.0.1"
|
|
||||||
description = "Scripts to assist with development of Deskflow"
|
|
||||||
requires-python = ">=3.9"
|
|
||||||
dependencies = [
|
|
||||||
"clang-format",
|
|
||||||
"python-dotenv",
|
|
||||||
"colorama",
|
|
||||||
]
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# Deskflow -- mouse and keyboard sharing utility
|
|
||||||
# Copyright (C) 2024 Symless Ltd.
|
|
||||||
#
|
|
||||||
# This package is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# found in the file LICENSE that should have accompanied this file.
|
|
||||||
#
|
|
||||||
# This package is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import lib.env as env
|
|
||||||
|
|
||||||
env.ensure_in_venv(__file__, create_venv=True)
|
|
||||||
env.install_requirements()
|
|
||||||
|
|
||||||
import lib.colors as colors
|
|
||||||
|
|
||||||
print(colors.SUCCESS_TEXT, "Python virtual environment is ready.")
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
sonar.organization=deskflow
|
sonar.organization=deskflow
|
||||||
sonar.projectKey=deskflow_deskflow
|
sonar.projectKey=deskflow_deskflow
|
||||||
sonar.sources=scripts,src/apps,src/lib
|
sonar.sources=src/apps,src/lib
|
||||||
sonar.tests=src/test
|
sonar.tests=src/test
|
||||||
sonar.exclusions=subprojects/**,build/**
|
sonar.exclusions=subprojects/**,build/**
|
||||||
sonar.coverage.exclusions=subprojects/**,scripts/**,src/test/**,src/apps/deskflow-gui/**,src/apps/res/**
|
sonar.coverage.exclusions=subprojects/**,src/test/**,src/apps/deskflow-gui/**,src/apps/res/**
|
||||||
sonar.cpd.exclusions=**/*Test*.cpp
|
sonar.cpd.exclusions=**/*Test*.cpp
|
||||||
sonar.host.url=https://sonarcloud.io
|
sonar.host.url=https://sonarcloud.io
|
||||||
sonar.coverageReportPaths=${{ steps.coverage-paths.outputs.csv }}
|
sonar.coverageReportPaths=${{ steps.coverage-paths.outputs.csv }}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue