Subject: Re: bug#63470: [PATCH] Use faster option for running vc-hg status

From: Spencer Baugh <[email-masked]>
Date: Tue, 16 May 2023 16:39:49 -0400

Eli Zaretskii <[email-masked]> writes:

>> Date: Fri, 12 May 2023 23:10:05 +0300
>> Cc: [email-masked]
>> From: Dmitry Gutov <[email-masked]>
>> 
>> On 12/05/2023 22:57, Spencer Baugh wrote:
>> > 
>> > I could add a user option to revert to the old behavior, if you want.
>> 
>> We could cache it like we do with vc-git--program-version. That's a 
>> simple memoization that doesn't take the host into account (though that 
>> could be implemented, too).
>
> Yes, that'd be a good-enough solution.
>
>> But it'd really make things easier if we're just allowed to rely on some 
>> new enough versions of Git and Hg.
>
> It isn't easy to be backward-compatible, but we should strive at doing
> that.

OK, revised backwards-compatible patch attached.

>From 69d4a14dc37759ebc20196be00f0b1a6a139e6fd Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Fri, 12 May 2023 15:28:06 -0400
Subject: [PATCH] Use faster option for running vc-hg status (Bug#63470)

In modern Mercurial, removing the "re:" "-I" "." options provides a
10x-20x speedup because it allows the Rust implementation of "hg
status" to be used.

* lisp/vc/vc-hg.el (vc-hg--program-version): Add.
(vc-hg-dir-status-files): Use --config status.relative=1 to make paths
relative when available.
---
 lisp/vc/vc-hg.el | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index 78231a0c954..bc7787d8c6c 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -1377,17 +1377,28 @@ vc-hg-after-dir-status
 ;; Follows vc-exec-after.
 (declare-function vc-set-async-update "vc-dispatcher" (process-buffer))
 
+(defvar vc-hg--program-version nil)
+
+(defun vc-hg--program-version ()
+  (or vc-hg--program-version
+      (setq vc-hg--program-version
+            (with-temp-buffer
+              (condition-case _ (vc-hg-command t 0 nil "version")
+                (error "0")
+                (:success
+                 (goto-char (point-min))
+                 (re-search-forward "Mercurial Distributed SCM (version \\([0-9][0-9.]+\\)")
+                 (string-trim-right (match-string 1) "\\.")))))))
+
 (defun vc-hg-dir-status-files (dir files update-function)
   ;; XXX: We can't pass DIR directly to 'hg status' because that
   ;; returns all ignored files if FILES is non-nil (bug#22481).
   (let ((default-directory dir))
-    ;; TODO: Use "--config 'status.relative=1'" instead of "re:"
-    ;; when we're allowed to depend on Mercurial 4.2+
-    ;; (it's a bit faster).
-    (vc-hg-command (current-buffer) 'async files
-                   "status" "re:" "-I" "."
-                   (concat "-mardu" (if files "i"))
-                   "-C"))
+    (apply #'vc-hg-command (current-buffer) 'async files
+           "status" (concat "-mardu" (if files "i")) "-C"
+           (if (version<= "4.2" (vc-hg--program-version))
+               '("--config" "status.relative=1")
+             '("re:" "-I" "."))))
   (vc-run-delayed
     (vc-hg-after-dir-status update-function)))
 
-- 
2.30.2