branch: externals/forgejo
commit 7d5903668a7ee13184e8172062d8dd015823d12e
Author: Thanos Apollo <[email protected]>
Commit: Thanos Apollo <[email protected]>

    vc: Add per-repo remote selection for multi-remote setups
---
 lisp/forgejo-vc.el | 64 +++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 56 insertions(+), 8 deletions(-)

diff --git a/lisp/forgejo-vc.el b/lisp/forgejo-vc.el
index dca4f90bd6..0838508195 100644
--- a/lisp/forgejo-vc.el
+++ b/lisp/forgejo-vc.el
@@ -160,15 +160,37 @@ Also syncs repo metadata if not yet cached."
           (match-string 2 remote-url)
           (match-string 3 remote-url)))))
 
+(defun forgejo-vc--all-forge-remotes ()
+  "Return all git remotes that parse as forge URLs.
+Each element is (HOST OWNER REPO REMOTE-NAME)."
+  (cl-loop for remote in (forgejo-vc--remotes)
+           for url = (forgejo-vc--remote-url remote)
+           for parsed = (and url (forgejo-vc--parse-remote-url url))
+           when parsed collect (append parsed (list remote))))
+
+(defvar forgejo-vc--selected-remotes (make-hash-table :test 'equal)
+  "Selected remote name per repo root directory.")
+
+(defun forgejo-vc--repo-root ()
+  "Return git toplevel for `default-directory', or nil."
+  (vc-git-root default-directory))
+
+(defun forgejo-vc--selected-remote ()
+  "Return the user-selected remote for the current repo, or nil."
+  (when-let* ((root (forgejo-vc--repo-root)))
+    (gethash root forgejo-vc--selected-remotes)))
+
 (defun forgejo-vc--repo-from-remote ()
-  "Detect host, owner, repo, and remote name from any git remote.
-Tries all remotes and returns the first that parses as a forge URL.
+  "Detect host, owner, repo, and remote name from a git remote.
+When a remote has been selected via `forgejo-vc-select-remote',
+prefer that remote.  Otherwise return the first forge remote.
 Returns (HOST OWNER REPO REMOTE-NAME) or nil."
-  (cl-some (lambda (remote)
-             (when-let* ((url (forgejo-vc--remote-url remote))
-                         (parsed (forgejo-vc--parse-remote-url url)))
-               (append parsed (list remote))))
-           (forgejo-vc--remotes)))
+  (let ((all (forgejo-vc--all-forge-remotes))
+        (selected (forgejo-vc--selected-remote)))
+    (or (and selected
+             (cl-find selected all
+                      :key (lambda (r) (nth 3 r)) :test #'string=))
+        (car all))))
 
 (defun forgejo-vc--upstream-branch (branch)
   "Return the upstream remote/branch for BRANCH, or nil."
@@ -552,6 +574,25 @@ and mark it as manually merged after a successful push."
   (cl-destructuring-bind (host owner repo) (forgejo-vc--require-repo)
     (forgejo-utils-browse-repo host owner repo)))
 
+;;; Remote selection
+
+(defun forgejo-vc--multiple-remotes-p ()
+  "Return non-nil when more than one forge remote exists."
+  (> (length (forgejo-vc--all-forge-remotes)) 1))
+
+(defun forgejo-vc-select-remote ()
+  "Select which forge remote to use for this repository."
+  (interactive)
+  (let* ((all (forgejo-vc--all-forge-remotes))
+         (candidates (mapcar (lambda (r)
+                               (format "%s (%s/%s)" (nth 3 r) (nth 1 r) (nth 2 
r)))
+                             all))
+         (choice (completing-read "Remote: " candidates nil t))
+         (idx (cl-position choice candidates :test #'string=))
+         (root (forgejo-vc--repo-root)))
+    (puthash root (nth 3 (nth idx all)) forgejo-vc--selected-remotes)
+    (setq forgejo-vc--repo-key nil)))
+
 ;;; Popup keymap
 
 (defun forgejo-vc--no-remote-p ()
@@ -592,7 +633,14 @@ and mark it as manually merged after a successful push."
        :inapt-if (lambda () (forgejo-vc--no-remote-p)))
   :group "Actions"
   "S" ("Settings" forgejo-settings)
-  "b" ("Browse repo" forgejo-vc-browse))
+  "b" ("Browse repo" forgejo-vc-browse)
+  "r" ((lambda ()
+         (format "Remote %s" (propertize
+                              (or (forgejo-vc--selected-remote)
+                                  (nth 3 (car 
(forgejo-vc--all-forge-remotes))))
+                              'face 'keymap-popup-value)))
+       forgejo-vc-select-remote
+       :if (lambda () (forgejo-vc--multiple-remotes-p))))
 
 ;;;###autoload
 (defun forgejo-vc ()

Reply via email to