branch: externals/vc-jj
commit b75160031a17ec9fe85e9fd3740278f5329d90d0
Author: Rudi Schlatte <[email protected]>
Commit: Wojciech Siewierski <[email protected]>
Add some tests
Also bind `default-directory` before calling `file-relative-name`
instead of passing a second argument `root` to that function, since a
relative filename gets expanded against default-directory before being
relativized against `root`. If default-directory was not equal to
`root`, the resulting filename would name a file outside of `root`.
Found by a failing test :)
---
vc-jj-tests.el | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
vc-jj.el | 18 +++++------
2 files changed, 104 insertions(+), 9 deletions(-)
diff --git a/vc-jj-tests.el b/vc-jj-tests.el
new file mode 100644
index 0000000000..3a72ecf254
--- /dev/null
+++ b/vc-jj-tests.el
@@ -0,0 +1,95 @@
+;;; vc-jj-tests.el --- tests for vc-jj.el -*- lexical-binding: t;
-*-
+
+;; Copyright (C) 2025 Rudolf Schlatte
+
+;; Author: Rudolf Schlatte <[email protected]>
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert-x)
+(require 'vc)
+(require 'vc-dir)
+(require 'vc-jj)
+
+(defmacro vc-jj-test--with-repo (name &rest body)
+ "Initialize a repository in a temporary directory and evaluate BODY.
+
+The current directory will be set to the top of that repository; NAME
+will be bound to that directory's file name. Once BODY exits, the
+directory will be deleted.
+
+Some environment variables that control jj's behavior will be set
+for the duration of BODY."
+ (declare (indent 1))
+ `(ert-with-temp-directory ,name
+ (let ((default-directory ,name)
+ ;; Note: if we need reproducible repository state, use
+ ;; JJ_RANDOMNESS_SEED=12345 when calling `jj git init', and
+ ;; increase its value by 1 or call `jj config set --repo
+ ;; debug.randomness-seed 12346' etc. between each jj call
+ ;; afterwards -- see
+ ;;
https://github.com/jj-vcs/jj/blob/d79c7a0dd5b8f9d3d6f9436452dcf0e1600b0b14/cli/tests/common/test_environment.rs#L115
+ ;; for other relevant environment variables.
+ (process-environment (append '("[email protected]"
+ "JJ_USER=john")
+ process-environment)))
+ (vc-create-repo 'jj)
+ ,@body)))
+
+(ert-deftest vc-jj-test-add-file ()
+ (vc-jj-test--with-repo repo
+ (write-region "New file" nil "README")
+ (should (vc-jj--file-tracked "README"))
+ (should (vc-jj--file-added "README"))
+ (should (not (vc-jj--file-modified "README")))
+ (should (not (vc-jj--file-conflicted "README")))
+ (should (eq (vc-state "README" 'jj) 'added))))
+
+(ert-deftest vc-jj-test-added-tracked ()
+ (vc-jj-test--with-repo repo
+ (write-region "In first commit" nil "first-file")
+ (vc-jj-checkin '("first-file") "First commit")
+ (write-region "In second commit" nil "second-file")
+ (should (eq (vc-jj-state "second-file") 'added))
+ (should (eq (vc-jj-state "first-file") 'up-to-date))))
+
+(ert-deftest vc-jj-test-conflict ()
+ (vc-jj-test--with-repo repo
+ (let (branch-1 branch-2 branch-merged)
+ ;; the root change id is always zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
+ (shell-command "jj new zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")
+ (setq branch-1 (vc-jj-working-revision "."))
+ (write-region "Unconflicted" nil "unconflicted.txt")
+ (write-region "Branch 1" nil "conflicted.txt")
+ (make-directory "subdir")
+ (write-region "Branch 1" nil "subdir/conflicted.txt")
+ (shell-command "jj new zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")
+ (setq branch-2 (vc-jj-working-revision "."))
+ (write-region "Unconflicted" nil "unconflicted.txt")
+ (write-region "Branch 2" nil "conflicted.txt")
+ (make-directory "subdir")
+ (write-region "Branch 2" nil "subdir/conflicted.txt")
+ (shell-command (concat "jj new " branch-1 " " branch-2))
+ (should (eq (vc-jj-state "unconflicted.txt") 'up-to-date))
+ (should (eq (vc-jj-state "conflicted.txt") 'conflict))
+ (should (eq (vc-jj-state "subdir/conflicted.txt") 'conflict)))))
+
+(provide 'vc-jj-tests)
+;;; vc-jj-tests.el ends here
diff --git a/vc-jj.el b/vc-jj.el
index 6a2111473e..c1599de20f 100644
--- a/vc-jj.el
+++ b/vc-jj.el
@@ -87,15 +87,15 @@
(unless (not (file-exists-p default-directory))
(with-demoted-errors "Error: %S"
(when-let ((root (vc-jj-root file)))
- (let ((relative (file-relative-name file root))
- (default-directory root))
+ (let* ((default-directory root)
+ (relative (file-relative-name file)))
(vc-jj--file-tracked relative)))))))
(defun vc-jj-state (file)
"JJ implementation of `vc-state' for FILE."
(when-let ((root (vc-jj-root file)))
- (let ((relative (file-relative-name file root))
- (default-directory root))
+ (let* ((default-directory root)
+ (relative (file-relative-name file)))
(cond
((vc-jj--file-conflicted relative)
'conflict)
@@ -121,11 +121,11 @@ The list is passed to UPDATE-FUNCTION."
(seq-filter (lambda (file) (string-prefix-p "M " file))
changed-files)))
;; The output of `jj resolve --list' is a list of file names
- ;; plus a conflict description -- rather than trying to be
- ;; fancy and parsing each line (and getting bugs with file
- ;; names with spaces), use `string-prefix-p' later. Also,
- ;; the command errors when there are no conflicts.
- (conflicted (ignore-errors (process-lines "jj" "resolve" "--list"))))
+ ;; plus a conflict description per line -- rather than trying
+ ;; to be fancy and parsing each line (and getting bugs with
+ ;; file names with spaces), use `string-prefix-p' later.
+ ;; Also, the command errors when there are no conflicts.
+ (conflicted (process-lines-ignore-status "jj" "resolve" "--list")))
(let ((result
(mapcar
(lambda (file)