1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2019, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
3 ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz
5 ;;; This file is part of GNU Guix.
7 ;;; GNU Guix is free software; you can redistribute it and/or modify it
8 ;;; under the terms of the GNU General Public License as published by
9 ;;; the Free Software Foundation; either version 3 of the License, or (at
10 ;;; your option) any later version.
12 ;;; GNU Guix is distributed in the hope that it will be useful, but
13 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;;; GNU General Public License for more details.
17 ;;; You should have received a copy of the GNU General Public License
18 ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
20 (define-module (test-git)
22 #:use-module (guix git)
23 #:use-module (guix tests git)
24 #:use-module (guix build utils)
25 #:use-module ((guix utils) #:select (call-with-temporary-directory))
26 #:use-module (srfi srfi-1)
27 #:use-module (srfi srfi-64)
28 #:use-module (srfi srfi-71)
29 #:use-module (ice-9 popen)
30 #:use-module (ice-9 textual-ports))
32 ;; Test the (guix git) tools.
36 ;; 'with-temporary-git-repository' relies on the 'git' command.
37 (unless (which (git-command)) (test-skip 1))
38 (test-assert "commit-difference, linear history"
39 (with-temporary-git-repository directory
41 (commit "first commit")
43 (commit "second commit")
45 (commit "third commit")
47 (commit "fourth commit"))
48 (with-repository directory repository
49 (let ((commit1 (find-commit repository "first"))
50 (commit2 (find-commit repository "second"))
51 (commit3 (find-commit repository "third"))
52 (commit4 (find-commit repository "fourth")))
53 (and (lset= eq? (commit-difference commit4 commit1)
54 (list commit2 commit3 commit4))
55 (lset= eq? (commit-difference commit4 commit2)
56 (list commit3 commit4))
57 (equal? (commit-difference commit3 commit2)
60 ;; COMMIT4 is not an ancestor of COMMIT1 so we should get the
62 (null? (commit-difference commit1 commit4)))))))
64 (unless (which (git-command)) (test-skip 1))
65 (test-assert "commit-difference, fork"
66 (with-temporary-git-repository directory
68 (commit "first commit")
71 (add "devel/1.txt" "1")
72 (commit "first devel commit")
73 (add "devel/2.txt" "2")
74 (commit "second devel commit")
77 (commit "second commit")
79 (commit "third commit")
80 (merge "devel" "merge")
82 (commit "fourth commit"))
83 (with-repository directory repository
84 (let ((master1 (find-commit repository "first commit"))
85 (master2 (find-commit repository "second commit"))
86 (master3 (find-commit repository "third commit"))
87 (master4 (find-commit repository "fourth commit"))
88 (devel1 (find-commit repository "first devel"))
89 (devel2 (find-commit repository "second devel"))
90 (merge (find-commit repository "merge")))
91 (and (equal? (commit-difference master4 merge)
93 (lset= eq? (commit-difference master3 master1)
94 (list master3 master2))
95 (lset= eq? (commit-difference devel2 master1)
98 ;; The merge occurred between MASTER2 and MASTER4 so here we
99 ;; expect to see all the commits from the "devel" branch in
100 ;; addition to those on "master".
101 (lset= eq? (commit-difference master4 master2)
102 (list master4 merge master3 devel1 devel2)))))))
104 (unless (which (git-command)) (test-skip 1))
105 (test-assert "commit-difference, excluded commits"
106 (with-temporary-git-repository directory
108 (commit "first commit")
110 (commit "second commit")
112 (commit "third commit")
114 (commit "fourth commit")
116 (commit "fifth commit"))
117 (with-repository directory repository
118 (let ((commit1 (find-commit repository "first"))
119 (commit2 (find-commit repository "second"))
120 (commit3 (find-commit repository "third"))
121 (commit4 (find-commit repository "fourth"))
122 (commit5 (find-commit repository "fifth")))
123 (and (lset= eq? (commit-difference commit4 commit1 (list commit2))
124 (list commit3 commit4))
125 (lset= eq? (commit-difference commit4 commit1 (list commit3))
127 (null? (commit-difference commit4 commit1 (list commit5))))))))
129 (unless (which (git-command)) (test-skip 1))
130 (test-equal "commit-relation"
131 '(self ;master3 master3
132 ancestor ;master1 master3
133 descendant ;master3 master1
134 unrelated ;master2 branch1
135 unrelated ;branch1 master2
136 ancestor ;branch1 merge
137 descendant ;merge branch1
138 ancestor ;master1 merge
139 descendant) ;merge master1
140 (with-temporary-git-repository directory
142 (commit "first commit")
146 (commit "branch commit")
149 (commit "second commit")
151 (commit "third commit")
152 (merge "hack" "merge"))
153 (with-repository directory repository
154 (let ((master1 (find-commit repository "first"))
155 (master2 (find-commit repository "second"))
156 (master3 (find-commit repository "third"))
157 (branch1 (find-commit repository "branch"))
158 (merge (find-commit repository "merge")))
159 (list (commit-relation master3 master3)
160 (commit-relation master1 master3)
161 (commit-relation master3 master1)
162 (commit-relation master2 branch1)
163 (commit-relation branch1 master2)
164 (commit-relation branch1 merge)
165 (commit-relation merge branch1)
166 (commit-relation master1 merge)
167 (commit-relation merge master1))))))
169 (unless (which (git-command)) (test-skip 1))
170 (test-equal "commit-descendant?"
171 '((master3 master3 => #t)
172 (master1 master3 => #f)
173 (master3 master1 => #t)
174 (master2 branch1 => #f)
175 (master2 branch1 master1 => #t)
176 (branch1 master2 => #f)
177 (branch1 merge => #f)
178 (merge branch1 => #t)
179 (master1 merge => #f)
180 (merge master1 => #t))
181 (with-temporary-git-repository directory
183 (commit "first commit")
187 (commit "branch commit")
190 (commit "second commit")
192 (commit "third commit")
193 (merge "hack" "merge"))
194 (with-repository directory repository
195 (let ((master1 (find-commit repository "first"))
196 (master2 (find-commit repository "second"))
197 (master3 (find-commit repository "third"))
198 (branch1 (find-commit repository "branch"))
199 (merge (find-commit repository "merge")))
200 (letrec-syntax ((verify
203 ((_ (new old ...) rest ...)
204 (cons `(new old ... =>
205 ,(commit-descendant? new
207 (verify rest ...))))))
208 (verify (master3 master3)
212 (master2 branch1 master1)
217 (merge master1)))))))
219 (unless (which (git-command)) (test-skip 1))
220 (test-equal "remote-refs"
221 '("refs/heads/develop" "refs/heads/master"
222 "refs/tags/v1.0" "refs/tags/v1.1")
223 (with-temporary-git-repository directory
225 (commit "First commit")
226 (tag "v1.0" "release-1.0")
230 (commit "Second commit")
231 (tag "v1.1" "release-1.1"))
232 (remote-refs directory)))
234 (unless (which (git-command)) (test-skip 1))
235 (test-equal "remote-refs: only tags"
236 '("refs/tags/v1.0" "refs/tags/v1.1")
237 (with-temporary-git-repository directory
239 (commit "First commit")
240 (tag "v1.0" "Release 1.0")
242 (commit "Second commit")
243 (tag "v1.1" "Release 1.1"))
244 (remote-refs directory #:tags? #t)))
246 (unless (which (git-command)) (test-skip 1))
247 (test-assert "update-cached-checkout, tag"
248 (call-with-temporary-directory
250 (with-temporary-git-repository directory
252 (commit "First commit")
253 (tag "v1.0" "release-1.0")
257 (commit "Second commit")
258 (tag "v1.1" "release-1.1"))
259 (let ((directory commit relation
260 (update-cached-checkout directory
261 #:ref '(tag . "v1.1")
262 #:cache-directory cache))
263 (head (let* ((pipe (open-pipe* OPEN_READ (git-command)
266 (str (get-string-all pipe)))
268 (string-trim-right str))))
269 ;; COMMIT should be the ID of the commit object, not that of the tag.
270 (string=? commit head))))))