branch: externals/vc-jj
commit 6b7aea27312df164c44f191514267aea86c1e20d
Author: Rudi Schlatte <r...@constantly.at>
Commit: Rudi Schlatte <r...@constantly.at>

    Avoid modifying fileset expressions in vc-jj-do-command
    
    vc-do-command normalizes its filename arguments, but we already
    converted them to jujutsu fileset expressions; pass them at the end of
    the flags argument instead.
    
    Fixes #38
---
 vc-jj-tests.el | 47 ++++++++++++++++++++++++++++++++++-------------
 vc-jj.el       | 51 ++++++++++++++++++++++++++++++++-------------------
 2 files changed, 66 insertions(+), 32 deletions(-)

diff --git a/vc-jj-tests.el b/vc-jj-tests.el
index e4f1145f84..1cabdca062 100644
--- a/vc-jj-tests.el
+++ b/vc-jj-tests.el
@@ -149,19 +149,25 @@ is needed."
 
 (ert-deftest vc-jj-ignore ()
   (vc-jj-test-with-repo repo
-    (write-region "xxx" nil "root-ignored.txt")
-    (make-directory "subdir")
-    (write-region "xxx" nil "subdir/subdir-ignored.txt")
-    (should (eq (vc-jj-state "root-ignored.txt") 'added))
-    (should (eq (vc-jj-state "subdir/subdir-ignored.txt") 'added))
-    (vc-jj-ignore "root-ignored.txt")
-    (vc-jj-ignore "subdir/subdir-ignored.txt")
-    (should (eq (vc-jj-state "root-ignored.txt") 'ignored))
-    (should (eq (vc-jj-state "subdir/subdir-ignored.txt") 'ignored))
-    (vc-jj-ignore "root-ignored.txt" nil t)
-    (vc-jj-ignore "subdir/subdir-ignored.txt" nil t)
-    (should (eq (vc-jj-state "root-ignored.txt") 'added))
-    (should (eq (vc-jj-state "subdir/subdir-ignored.txt") 'added))))
+    (let (gitignore-buffer)
+      (unwind-protect
+          (progn
+            (setq gitignore-buffer (find-file ".gitignore"))
+            (write-region "xxx" nil "root-ignored.txt")
+            (make-directory "subdir")
+            (write-region "xxx" nil "subdir/subdir-ignored.txt")
+            (should (eq (vc-jj-state "root-ignored.txt") 'added))
+            (should (eq (vc-jj-state "subdir/subdir-ignored.txt") 'added))
+            (vc-jj-ignore "root-ignored.txt")
+            (vc-jj-ignore "subdir/subdir-ignored.txt")
+            (should (eq (vc-jj-state "root-ignored.txt") 'ignored))
+            (should (eq (vc-jj-state "subdir/subdir-ignored.txt") 'ignored))
+            (vc-jj-ignore "root-ignored.txt" nil t)
+            (vc-jj-ignore "subdir/subdir-ignored.txt" nil t)
+            (should (eq (vc-jj-state "root-ignored.txt") 'added))
+            (should (eq (vc-jj-state "subdir/subdir-ignored.txt") 'added)))
+        (when (buffer-live-p gitignore-buffer)
+          (kill-buffer gitignore-buffer))))))
 
 (ert-deftest vc-jj-list-files ()
   (vc-jj-test-with-repo repo
@@ -189,5 +195,20 @@ is needed."
       (should (equal (vc-jj-dir-status-files (expand-file-name "subdir/" repo) 
nil (lambda (x y) x))
                      '(("conflicted.txt" conflict)))))))
 
+(ert-deftest vc-jj-funky-filename ()
+  ;; https://codeberg.org/emacs-jj-vc/vc-jj.el/issues/38
+  (vc-jj-test-with-repo repo
+    (write-region "Hello" nil "TEST=TEST.txt")
+    (write-region "Hello" nil "with'apostrophe.txt")
+    (write-region "Hello" nil "with\"quotation.txt")
+    (should (eq (vc-jj-state "TEST=TEST.txt") 'added))
+    (should (eq (vc-jj-state "with'apostrophe.txt") 'added))
+    (should (eq (vc-jj-state "with\"quotation.txt") 'added))
+    (should (seq-set-equal-p
+             (vc-jj-dir-status-files repo nil (lambda (x y) x))
+             '(("TEST=TEST.txt" added)
+               ("with'apostrophe.txt" added)
+               ("with\"quotation.txt" added))))))
+
 (provide 'vc-jj-tests)
 ;;; vc-jj-tests.el ends here
diff --git a/vc-jj.el b/vc-jj.el
index d778c6d05e..91f387fb16 100644
--- a/vc-jj.el
+++ b/vc-jj.el
@@ -95,6 +95,17 @@ If nil, use the value of `vc-diff-switches'.  If t, use no 
switches."
                 (string :tag "Argument String")
                 (repeat :tag "Argument List" :value ("") string)))
 
+(defun vc-jj--filename-to-fileset (filename &optional root)
+  "Convert FILENAME to a JJ fileset expression.
+If ROOT is given, the result is relative to the repository root,
+otherwise it is relative to the current directory."
+  (if root
+      (concat "root-file:\""
+          (string-replace "\"" "\\\"" (file-relative-name filename root))
+          "\"")
+    (concat "cwd-file:\""
+            (string-replace "\"" "\\\"" (file-relative-name filename)) "\"")))
+
 (defun vc-jj-command (buffer okstatus file-or-list &rest flags)
   "Execute `vc-jj-program', notifying the user and checking for errors.
 
@@ -115,11 +126,17 @@ the command line before the filename(s).
 
 Return the return value of the command in the synchronous case, and the
 process object in the asynchronous case."
-  (apply #'vc-do-command (or buffer "*vc*") okstatus vc-jj-program
-    file-or-list
-    (if (stringp vc-jj-global-switches)
-        (cons vc-jj-global-switches flags)
-      (append vc-jj-global-switches flags))))
+  (let* ((filesets (mapcar #'vc-jj--filename-to-fileset
+                           (if (listp file-or-list) file-or-list (list 
file-or-list))))
+         (global-switches (if (stringp vc-jj-global-switches)
+                              (list vc-jj-global-switches)
+                            vc-jj-global-switches)))
+    (apply #'vc-do-command (or buffer "*vc*") okstatus vc-jj-program
+           ;; Note that we pass NIL for FILE-OR-LIST to avoid
+           ;; vc-do-command mangling of filenames; we pass the fileset
+           ;; expressions in ARGS instead.
+           nil
+           (append global-switches flags filesets))))
 
 ;;;###autoload (defun vc-jj-registered (file)
 ;;;###autoload   "Return non-nil if FILE is registered with jj."
@@ -128,17 +145,14 @@ process object in the asynchronous case."
 ;;;###autoload       (progn
 ;;;###autoload         (load "vc-jj" nil t)
 ;;;###autoload         (vc-jj-registered file))))
-
 (defun vc-jj-registered (file)
   "Check whether FILE is registered with jj."
-  (when (executable-find vc-jj-program)
-    (unless (not (file-exists-p default-directory))
-      (with-demoted-errors "Error: %S"
-        (when-let* ((default-directory (vc-jj-root file))
-                    (relative (file-relative-name file)))
-          (with-temp-buffer
-            (and (= 0 (vc-jj-command t 0 file "file" "list" "--"))
-                 (not (= (point-min) (point-max))))))))))
+  (and-let* ((vc-jj-program (executable-find vc-jj-program))
+             (default-directory (vc-jj-root file)))
+    (with-temp-buffer
+      (and (= 0 (call-process vc-jj-program nil (list t nil) nil
+                              "file" "list" "--" (vc-jj--filename-to-fileset 
file)))
+           (/= (point-min) (point-max))))))
 
 (defun vc-jj-state (file)
   "JJ implementation of `vc-state' for FILE."
@@ -331,8 +345,8 @@ self.immutable(), \"\\n\"
 (defun vc-jj-checkin (files comment &optional _rev)
   "Run \"jj commit\" with supplied FILES and COMMENT."
   (setq comment (replace-regexp-in-string "\\`Summary: " "" comment))
-  (let ((args (append (vc-switches 'jj 'checkin) (list "--"))))
-    (apply #'vc-jj-command nil 0 files "commit" "-m" comment args)))
+  (let ((args (append (vc-switches 'jj 'checkin) (list "commit" "-m" 
comment))))
+    (apply #'vc-jj-command nil 0 files args)))
 
 (defun vc-jj-find-revision (file rev buffer)
   "Read revision REV of FILE into BUFFER and return the buffer."
@@ -344,13 +358,12 @@ self.immutable(), \"\\n\"
 If REV is not specified, revert the file as with `vc-jj-revert'."
   ;; TODO: check that this does the right thing: if REV is not
   ;; specified, should we revert or leave FILE unchanged?
-  (let ((args (append (and rev (list "--from" rev))
-                      (list "--"))))
+  (let ((args (append (and rev (list "--from" rev)))))
     (apply #'vc-jj-command nil 0 file "restore" args)))
 
 (defun vc-jj-revert (file &optional _contents-done)
   "Restore FILE to the state from its parent(s), via \"jj restore\"."
-  (vc-jj-command nil 0 file "restore" "--"))
+  (vc-jj-command nil 0 file "restore"))
 
 (defun vc-jj-print-log (files buffer &optional _shortlog start-revision limit)
   "Print commit log associated with FILES into specified BUFFER."

Reply via email to