git.scm 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (guix tests git)
  19. #:use-module (git)
  20. #:use-module ((guix git) #:select (with-repository))
  21. #:use-module (guix utils)
  22. #:use-module (guix build utils)
  23. #:use-module (ice-9 match)
  24. #:use-module (ice-9 control)
  25. #:export (git-command
  26. with-temporary-git-repository
  27. find-commit))
  28. (define git-command
  29. (make-parameter "git"))
  30. (define (populate-git-repository directory directives)
  31. "Initialize a new Git checkout and repository in DIRECTORY and apply
  32. DIRECTIVES. Each element of DIRECTIVES is an sexp like:
  33. (add \"foo.txt\" \"hi!\")
  34. Return DIRECTORY on success."
  35. ;; Note: As of version 0.2.0, Guile-Git lacks the necessary bindings to do
  36. ;; all this, so resort to the "git" command.
  37. (define (git command . args)
  38. (apply invoke (git-command) "-C" directory
  39. command args))
  40. (mkdir-p directory)
  41. (git "init")
  42. (let loop ((directives directives))
  43. (match directives
  44. (()
  45. directory)
  46. ((('add file contents) rest ...)
  47. (let ((file (string-append directory "/" file)))
  48. (mkdir-p (dirname file))
  49. (call-with-output-file file
  50. (lambda (port)
  51. (display (if (string? contents)
  52. contents
  53. (with-repository directory repository
  54. (contents repository)))
  55. port)))
  56. (git "add" file)
  57. (loop rest)))
  58. ((('commit text) rest ...)
  59. (git "commit" "-m" text)
  60. (loop rest))
  61. ((('tag name) rest ...)
  62. (git "tag" name)
  63. (loop rest))
  64. ((('branch name) rest ...)
  65. (git "branch" name)
  66. (loop rest))
  67. ((('checkout branch) rest ...)
  68. (git "checkout" branch)
  69. (loop rest))
  70. ((('merge branch message) rest ...)
  71. (git "merge" branch "-m" message)
  72. (loop rest)))))
  73. (define (call-with-temporary-git-repository directives proc)
  74. (call-with-temporary-directory
  75. (lambda (directory)
  76. (populate-git-repository directory directives)
  77. (proc directory))))
  78. (define-syntax-rule (with-temporary-git-repository directory
  79. directives exp ...)
  80. "Evaluate EXP in a context where DIRECTORY contains a checkout populated as
  81. per DIRECTIVES."
  82. (call-with-temporary-git-repository directives
  83. (lambda (directory)
  84. exp ...)))
  85. (define (find-commit repository message)
  86. "Return the commit in REPOSITORY whose message includes MESSAGE, a string."
  87. (let/ec return
  88. (fold-commits (lambda (commit _)
  89. (and (string-contains (commit-message commit)
  90. message)
  91. (return commit)))
  92. #f
  93. repository)
  94. (error "commit not found" message)))