From d8277a9a4a72887bbb0d3440870a21a9e55aa431 Mon Sep 17 00:00:00 2001
From: Timothee 'TTimo' Besset <ttimo@ttimo.net>
Date: Thu, 2 Nov 2023 16:30:20 -0500
Subject: [PATCH] support cygwin installed in any (default) location, no longer
 require C:\cygwin64

---
 client/devkit_client/__init__.py | 18 +++++++++++++++---
 setup/package-windows.py         |  6 +++++-
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/client/devkit_client/__init__.py b/client/devkit_client/__init__.py
index e3800d1..670e02a 100644
--- a/client/devkit_client/__init__.py
+++ b/client/devkit_client/__init__.py
@@ -55,6 +55,7 @@ import tempfile
 import pathlib
 import re
 import threading
+import winreg
 
 import appdirs
 
@@ -236,15 +237,26 @@ def _locate_external_tool(name):
         assert os.path.exists(ret)
         return ret
     # Running from source:
-    # Locate a cygwin version. That's what we package. Windows ssh.exe isn't a compatible transport for rsync for instance
-    # NOTE: we could do better at locating the cygwin install
+    # Locate cygwin. That's what we package. Windows ssh.exe isn't a compatible transport for rsync for instance
+    # This is the installation we recommend in the readme, since there can be multiple cygwin installs it's best to check first
     ret = os.path.join(r'C:\cygwin64\bin', name)
     if os.path.exists(ret):
         return ret
-    # Last ditch attempt, look for the first thing in PATH
+    # Look for the first thing in PATH, that would be the 'preferred' cygwin install if that's setup
     ret = shutil.which(name)
     if ret is not None:
         return ret
+    # Go poke at the registry then
+    CYGWIN_KEY = "SOFTWARE\\Cygwin\\setup"
+    for hk in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER):
+        try:
+            key = winreg.OpenKey(hk, CYGWIN_KEY)
+        except FileNotFoundError as e:
+            continue
+        root = winreg.QueryValueEx(key, "rootdir")[0]
+        ret = os.path.join(root, 'bin', name)
+        if os.path.exists(ret):
+            return ret
     raise Exception('Required external tool not found: {!r}'.format(name))
 
 def locate_external_tools():
diff --git a/setup/package-windows.py b/setup/package-windows.py
index 12144b8..fac8c50 100644
--- a/setup/package-windows.py
+++ b/setup/package-windows.py
@@ -16,6 +16,10 @@ CLIENT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), r'..\client
 BUILD_DIR = os.path.join(ROOT_DIR, 'build')
 DIST_DIR = os.path.join(ROOT_DIR, 'dist')
 
+# cursed, but delicious
+sys.path.append(CLIENT_DIR)
+from devkit_client import locate_external_tools
+sys.path.pop()
 
 # don't let python buffering get in the way or readable output
 # https://stackoverflow.com/questions/107705/disable-output-buffering
@@ -60,7 +64,7 @@ if __name__ == '__main__':
         dir_path = os.path.join(CLIENT_DIR, name)
         shutil.copytree(dir_path, os.path.join(DIST_DIR, name), dirs_exist_ok=True)
 
-    cygroot = r'C:\cygwin64\bin'
+    cygroot =  os.path.dirname(locate_external_tools()[0])
     assert os.path.isdir(cygroot)
     cygwin_dst_dir = os.path.join(DIST_DIR, 'cygroot/bin')
     os.makedirs(cygwin_dst_dir, exist_ok=True)
-- 
GitLab