branch: externals/vc-jj
commit ba94d8b13df37d7ca4d34151247a7d802d2e0109
Author: Rudi Schlatte <[email protected]>
Commit: Rudi Schlatte <[email protected]>

    Return full change id from vc-jj-(next|previous)-revision
    
    - Use 'first_parent' or 'ancestors' in vc-jj-previous-revision
    
    - Use 'children' or 'descendants' in vc-jj-next-revision
    
    - Add some tests
    
    See #112
---
 vc-jj-tests.el | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 vc-jj.el       | 38 +++++++++++++++++++++-----------------
 2 files changed, 70 insertions(+), 17 deletions(-)

diff --git a/vc-jj-tests.el b/vc-jj-tests.el
index 4944daf393..d728b775ca 100644
--- a/vc-jj-tests.el
+++ b/vc-jj-tests.el
@@ -278,5 +278,54 @@ See https://codeberg.org/emacs-jj-vc/vc-jj.el/issues/63.";
       (should (eq (vc-jj-dir-status-files repo nil (lambda (x y) x))
                   nil)))))
 
+(ert-deftest vc-jj-previous-revision-in-merge ()
+  "Test vc-previous-revision for a change with multiple parents.
+We expect this function to return the first parent specified."
+  (vc-jj-test-with-repo repo
+    (let ((root "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz")
+          branch-1 branch-2 branch-merged
+          branch-parent branch-parent-with-file)
+      ;; - construct a diamond graph
+      ;; - add a file to the second parent of the merge commit
+      ;; - check that we find the first parent
+      ;; - check that we find the second parent when looking for a
+      ;;   parent with the new file
+      (shell-command (concat "jj new " root))
+      (write-region "Hello!" nil "README")
+      (setq branch-1 (vc-jj-working-revision "README"))
+      (shell-command (concat "jj new " root))
+      (write-region "Hello!" nil "README")
+      (write-region "Hello!" nil "README-onlyhere")
+      (setq branch-2 (vc-jj-working-revision "README"))
+      (shell-command (concat "jj new " branch-1 " " branch-2))
+      (setq branch-merged (vc-jj-working-revision "README"))
+      (setq branch-parent (vc-jj-previous-revision nil branch-merged))
+      (setq branch-parent-with-file (vc-jj-previous-revision "README-onlyhere" 
branch-merged))
+      (should (string= branch-parent branch-1))
+      (should (string= branch-parent-with-file branch-2)))))
+
+(ert-deftest vc-jj-next-revision-in-merge ()
+  "Test vc-next-revision for a change with multiple children.
+We check that we get the revision where a given file was added."
+  (vc-jj-test-with-repo repo
+    (let ( branch-root branch-1 branch-2 branch-child branch-child-1 
branch-child-2)
+      (write-region "Hello!" nil "README")
+      (setq branch-root (vc-jj-working-revision "README"))
+      (shell-command (concat "jj new " branch-root))
+      (write-region "Hello!" nil "README-onlyhere")
+      (setq branch-1 (vc-jj-working-revision "README-onlyhere"))
+      (shell-command (concat "jj new " branch-root))
+      (write-region "Persisting branch 2" nil "README-branch2")
+      (setq branch-2 (vc-jj-working-revision "README-branch2"))
+      (setq branch-child (vc-jj-next-revision nil branch-root))
+      ;; Slight pun: these files only exist in the child branches
+      (setq branch-child-1 (vc-jj-next-revision "README-onlyhere" branch-root))
+      (setq branch-child-2 (vc-jj-next-revision "README-branch2" branch-root))
+      ;; We don't want to rely on the exact order in which the
+      ;; children are printed
+      (should (or (string= branch-child branch-1) (string= branch-child 
branch-2)))
+      (should (string= branch-child-1 branch-1))
+      (should (string= branch-child-2 branch-2)))))
+
 (provide 'vc-jj-tests)
 ;;; vc-jj-tests.el ends here
diff --git a/vc-jj.el b/vc-jj.el
index d14b4c7164..05bd1f4a24 100644
--- a/vc-jj.el
+++ b/vc-jj.el
@@ -605,29 +605,33 @@ If REV is not specified, revert the file as with 
`vc-jj-revert'."
 
 (defun vc-jj-previous-revision (file rev)
   "JJ-specific version of `vc-previous-revision'."
-  ;; TODO: here and in `vc-jj-next-revision', check how (concat
-  ;; revision "-") works with merge commits; do we get multiple change
-  ;; ids in a multi-line string, and does this break users of these
-  ;; functions?
   (if file
-      (vc-jj--command-parseable "log" "--no-graph" "-n" "1"
-                                "-r" (concat ".." rev "-")
-                                "-T" "change_id.shortest()"
+      (vc-jj--command-parseable "log" "--no-graph" "--limit" "1"
+                                "-r" (concat "ancestors(" rev ")")
+                                "-T" "change_id"
                                 "--" (vc-jj--filename-to-fileset file))
-    (vc-jj--command-parseable "log" "--no-graph" "-n" "1"
-                              "-r" (concat rev "-")
-                              "-T" "change_id.shortest()"
-                              )))
+    ;; The jj manual states that "for merges, [first_parent] only
+    ;; returns the first parent instead of returning all parents";
+    ;; given the choice, we do want to return the first parent of a
+    ;; merge change.
+    (vc-jj--command-parseable "log" "--no-graph"
+                              "-r" (concat "first_parent(" rev ")")
+                              "-T" "change_id")))
 
 (defun vc-jj-next-revision (file rev)
   "JJ-specific version of `vc-next-revision'."
   (if file
-      (vc-jj--command-parseable "log" "--no-graph" "-n" "1"
-                                "-r" (format "roots(files(\"%s\") ~ ::%s)" 
file rev)
-                                "-T" "change_id.shortest()")
-    (vc-jj--command-parseable "log" "--no-graph" "-n" "1"
-                              "-r" (concat rev "+")
-                              "-T" "change_id.shortest()")))
+      (vc-jj--command-parseable "log" "--no-graph" "--limit" "1"
+                                "-r" (concat "descendants(" rev ")")
+                                 "-T" "change_id"
+                                 "--" (vc-jj--filename-to-fileset file))
+    ;; Note: experimentally, jj (as of 0.35.0) prints children in LIFO
+    ;; order (newest child first), but we should not rely on that
+    ;; behavior and since none of the children of a change are
+    ;; special, we return an arbitrary one.
+    (car (vc-jj--process-lines "log" "--no-graph"
+                                 "-r" (concat "children(" rev ")")
+                                 "-T" "change_id ++ \"\n\""))))
 
 (defun vc-jj-get-change-comment (_files rev)
   (vc-jj--command-parseable "log" "--no-graph" "-n" "1"

Reply via email to