git: 'commit-difference' takes a list of excluded commits.

* guix/git.scm (commit-closure): Add 'visited' optional parameter.
(commit-difference): Add 'excluded' optional parameter; pass second
argument to 'commit-closure'.
* tests/git.scm ("commit-difference, excluded commits"): New test.
This commit is contained in:
Ludovic Courtès 2019-12-27 13:15:00 +01:00
parent 1e43ab2c03
commit 785af04a75
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
2 changed files with 34 additions and 6 deletions

View file

@ -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))

View file

@ -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")