[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/vc-jj 6b7aea2731 1/3: Avoid modifying fileset expressio
From: |
ELPA Syncer |
Subject: |
[elpa] externals/vc-jj 6b7aea2731 1/3: Avoid modifying fileset expressions in vc-jj-do-command |
Date: |
Fri, 18 Apr 2025 10:57:18 -0400 (EDT) |
branch: externals/vc-jj
commit 6b7aea27312df164c44f191514267aea86c1e20d
Author: Rudi Schlatte <rudi@constantly.at>
Commit: Rudi Schlatte <rudi@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."