diff --git a/hyfetch/__main__.py b/hyfetch/__main__.py new file mode 100644 index 00000000..debf90a4 --- /dev/null +++ b/hyfetch/__main__.py @@ -0,0 +1,4 @@ +from hyfetch import main + +if __name__ == '__main__': + main.run() diff --git a/hyfetch/constants.py b/hyfetch/constants.py index 076831ae..b6ff702c 100644 --- a/hyfetch/constants.py +++ b/hyfetch/constants.py @@ -46,3 +46,5 @@ class GlobalConfig: GLOBAL_CFG = GlobalConfig(color_mode='8bit', override_distro=None, debug=False, is_light=False) + +MINGIT_URL = 'https://github.com/git-for-windows/git/releases/download/v2.37.2.windows.2/MinGit-2.37.2.2-busybox-32-bit.zip' diff --git a/hyfetch/main.py b/hyfetch/main.py index ecfaf3cc..b3e04fcf 100755 --- a/hyfetch/main.py +++ b/hyfetch/main.py @@ -336,6 +336,7 @@ def run(): parser.add_argument('--debug', action='store_true', help=f'Debug mode') parser.add_argument('--test-distro', help=f'Test for a specific distro') parser.add_argument('--test-print', action='store_true', help=f'Test print distro ascii art only') + parser.add_argument('--ask-exit', action='store_true', help=f'Ask before exitting') args = parser.parse_args() @@ -343,6 +344,10 @@ def run(): print(f'Version is {VERSION}') return + # Ensure git bash for windows + ensure_git_bash() + check_windows_cmd() + # Test distro ascii art if args.test_distro: print(f'Setting distro to {args.test_distro}') @@ -385,3 +390,6 @@ def run(): # Run run_neofetch(preset, config.color_align) + + if args.ask_exit: + input('Press any key to exit...') diff --git a/hyfetch/neofetch_util.py b/hyfetch/neofetch_util.py index 92d2e52e..6a6269c0 100644 --- a/hyfetch/neofetch_util.py +++ b/hyfetch/neofetch_util.py @@ -6,16 +6,19 @@ import platform import re import shlex import subprocess +import zipfile from dataclasses import dataclass from pathlib import Path from subprocess import check_output from tempfile import TemporaryDirectory +from urllib.request import urlretrieve import pkg_resources +import psutil from typing_extensions import Literal from hyfetch.color_util import color -from .constants import GLOBAL_CFG +from .constants import GLOBAL_CFG, MINGIT_URL from .presets import ColorProfile from .serializer import from_dict @@ -142,6 +145,53 @@ def get_command_path() -> str: return pkg_resources.resource_filename(__name__, 'scripts/neowofetch') +def ensure_git_bash() -> Path: + """ + Ensure git bash installation for windows + + :returns git bash path + """ + if platform.system() == 'Windows': + # Find installation in default path + def_path = Path(r'C:\Program Files\Git\bin\bash.exe') + if def_path.is_file(): + return def_path + + # Find installation in PATH (C:\Program Files\Git\cmd should be in path) + pth = (os.environ.get('PATH') or '').lower().split(';') + pth = [p for p in pth if p.endswith(r'\git\cmd')] + if pth: + return Path(pth[0]).parent / r'bin\bash.exe' + + # Previously downloaded portable installation + path = Path(__file__).parent / 'min_git' + pkg_path = path / 'package.zip' + if path.is_dir(): + return path / r'bin\bash.exe' + + # No installation found, download a portable installation + print('Git installation not found. Git is required to use HyFetch/neofetch on Windows') + print('Downloading a minimal portable package for Git...') + urlretrieve(MINGIT_URL, pkg_path) + print('Download finished! Extracting...') + with zipfile.ZipFile(pkg_path, 'r') as zip_ref: + zip_ref.extractall(path) + print('Done!') + return path / r'bin\bash.exe' + + +def check_windows_cmd(): + """ + Check if this script is running under cmd.exe. If so, launch an external window with git bash + since cmd doesn't support RGB colors. + """ + if psutil.Process(os.getppid()).name().lower().strip() == 'cmd.exe': + print("cmd.exe doesn't support RGB colors, restarting in MinTTY...") + cmd = f'"{ensure_git_bash().parent.parent / "usr/bin/mintty.exe"}" -s 110,40 -e python -m hyfetch --ask-exit' + os.system(cmd) + exit() + + def run_command(args: str, pipe: bool = False) -> str | None: """ Run neofetch command @@ -153,7 +203,7 @@ def run_command(args: str, pipe: bool = False) -> str | None: cmd = get_command_path().replace("\\", "/").replace("C:/", "/c/") args = args.replace('\\', '/').replace('C:/', '/c/') - full_cmd = ['C:\\Program Files\\Git\\bin\\bash.exe', '-c', f'{cmd} {args}'] + full_cmd = [ensure_git_bash(), '-c', f'{cmd} {args}'] # print(full_cmd) if pipe: @@ -162,7 +212,6 @@ def run_command(args: str, pipe: bool = False) -> str | None: subprocess.run(full_cmd) - def get_distro_ascii(distro: str | None = None) -> str: """ Get the distro ascii of the current distro. Or if distro is specified, get the specific distro's diff --git a/neofetch b/neofetch index fdfe0ff8..33fdd2ac 100755 --- a/neofetch +++ b/neofetch @@ -1138,14 +1138,8 @@ get_distro() { elif [[ -d /system/app/ && -d /system/priv-app ]]; then distro="Android $(getprop ro.build.version.release)" - - # Chrome OS doesn't conform to the /etc/*-release standard. - # While the file is a series of variables they can't be sourced - # by the shell since the values aren't quoted. - elif [[ -f /etc/lsb-release && $(< /etc/lsb-release) == *CHROMEOS* ]]; then - distro='Chrome OS' - elif [[ -f /etc/vzlinux-release ]]; then + elif [[ -f /etc/vzlinux-release ]]; then distro='VzLinux' elif type -p guix >/dev/null; then @@ -1208,14 +1202,19 @@ get_distro() { *) distro+=" on Windows $windows_version" ;; esac + # Chrome OS doesn't conform to the /etc/*-release standard. + # While the file is a series of variables they can't be sourced + # by the shell since the values aren't quoted. + elif [[ -f /etc/lsb-release && $(< /etc/lsb-release) == *CHROMEOS* ]]; then + distro='Chrome OS' + elif [[ $(< /proc/version) == *chrome-bot* || -f /dev/cros_ec ]]; then [[ $distro != *Chrome* ]] && case $distro_shorthand in - on) distro+=" [Chrome OS]" ;; + on) distro="Chrome OS $distro" ;; tiny) distro="Chrome OS" ;; - *) distro+=" on Chrome OS" ;; + *) distro="Chrome OS $distro" ;; esac - distro=${distro## on } fi distro=$(trim_quotes "$distro")