diff --git a/guix/git.scm b/guix/git.scm index d7dddde3a7..83af596ef5 100644 --- a/guix/git.scm +++ b/guix/git.scm @@ -347,10 +347,11 @@ (define (print-git-error port key args default-printer) ;;; Commit difference. ;;; -(define (commit-closure commit) - "Return the closure of COMMIT as a set." +(define* (commit-closure commit #:optional (visited (setq))) + "Return the closure of COMMIT as a set. Skip commits contained in VISITED, +a set, and adjoin VISITED to the result." (let loop ((commits (list commit)) - (visited (setq))) + (visited visited)) (match commits (() visited) @@ -360,15 +361,16 @@ (define (commit-closure commit) (loop (append (commit-parents head) tail) (set-insert head visited))))))) -(define (commit-difference new old) +(define* (commit-difference new old #:optional (excluded '())) "Return the list of commits between NEW and OLD, where OLD is assumed to be -an ancestor of NEW. +an ancestor of NEW. Exclude all the commits listed in EXCLUDED along with +their ancestors. Essentially, this computes the set difference between the closure of NEW and that of OLD." (let loop ((commits (list new)) (result '()) - (visited (commit-closure old))) + (visited (commit-closure old (list->setq excluded)))) (match commits (() (reverse result)) diff --git a/tests/git.scm b/tests/git.scm index 8ba10ece51..052f8a79c4 100644 --- a/tests/git.scm +++ b/tests/git.scm @@ -96,4 +96,30 @@ (define-module (test-git) (lset= eq? (commit-difference master4 master2) (list master4 merge master3 devel1 devel2))))))) +(unless (which (git-command)) (test-skip 1)) +(test-assert "commit-difference, excluded commits" + (with-temporary-git-repository directory + '((add "a.txt" "A") + (commit "first commit") + (add "b.txt" "B") + (commit "second commit") + (add "c.txt" "C") + (commit "third commit") + (add "d.txt" "D") + (commit "fourth commit") + (add "e.txt" "E") + (commit "fifth commit")) + (with-repository directory repository + (let ((commit1 (find-commit repository "first")) + (commit2 (find-commit repository "second")) + (commit3 (find-commit repository "third")) + (commit4 (find-commit repository "fourth")) + (commit5 (find-commit repository "fifth"))) + (and (lset= eq? (commit-difference commit4 commit1 (list commit2)) + (list commit3 commit4)) + (lset= eq? (commit-difference commit4 commit1 (list commit3)) + (list commit4)) + (lset= eq? (commit-difference commit4 commit1 (list commit5)) + (list commit2 commit3 commit4))))))) + (test-end "git")