all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
blob 867cade2c42c044e6cf81e2d4fd086593399c717 5731 bytes (raw)
name: guix/build/git.scm 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
 
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2014, 2016, 2019, 2023 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

(define-module (guix build git)
  #:use-module (guix build utils)
  #:autoload   (guix build download-nar) (download-nar)
  #:autoload   (guix swh) (%verify-swh-certificate? swh-download)
  #:use-module (srfi srfi-34)
  #:use-module (ice-9 format)
  #:export (git-fetch
            git-fetch-with-fallback))

;;; Commentary:
;;;
;;; This is the build-side support code of (guix git-download).  It allows a
;;; Git repository to be cloned and checked out at a specific commit.
;;;
;;; Code:

(define* (git-fetch url commit directory
                    #:key (git-command "git")
                    lfs? recursive?)
  "Fetch COMMIT from URL into DIRECTORY.  COMMIT must be a valid Git commit
identifier.  When LFS? is true, configure Git to also fetch Large File
Storage (LFS) files; it assumes that the @code{git-lfs} extension is available
in the environment.  When RECURSIVE? is true, all the sub-modules of URL are
fetched, recursively.  Return #t on success, #f otherwise."

  ;; Disable TLS certificate verification.  The hash of the checkout is known
  ;; in advance anyway.
  (setenv "GIT_SSL_NO_VERIFY" "true")

  (mkdir-p directory)

  (guard (c ((invoke-error? c)
             (format (current-error-port)
                     "git-fetch: '~a~{ ~a~}' failed with exit code ~a~%"
                     (invoke-error-program c)
                     (invoke-error-arguments c)
                     (or (invoke-error-exit-status c) ;XXX: not quite accurate
                         (invoke-error-stop-signal c)
                         (invoke-error-term-signal c)))
             (delete-file-recursively directory)
             #f))
    (with-directory-excursion directory
      (invoke git-command "init" "--initial-branch=main")
      (invoke git-command "remote" "add" "origin" url)

      (when lfs?
        (setenv "HOME" "/tmp")
        (invoke git-command "lfs" "install"))

      (if (zero? (system* git-command "fetch" "--depth" "1" "origin" commit))
          (invoke git-command "checkout" "FETCH_HEAD")
          (begin
            (setvbuf (current-output-port) 'line)
            (format #t "Failed to do a shallow fetch; retrying a full fetch...~%")
            (invoke git-command "fetch" "origin")
            (invoke git-command "checkout" commit)))
      (when recursive?
        ;; Now is the time to fetch sub-modules.
        (invoke git-command "submodule" "update" "--init" "--recursive")

        ;; In sub-modules, '.git' is a flat file, not a directory,
        ;; so we can use 'find-files' here.
        (for-each delete-file-recursively
                  (find-files directory "^\\.git$")))

      ;; The contents of '.git' vary as a function of the current
      ;; status of the Git repo.  Since we want a fixed output, this
      ;; directory needs to be taken out.
      (delete-file-recursively ".git")
      #t)))


(define* (git-fetch-with-fallback url commit directory
                                  #:key (git-command "git")
                                  lfs? recursive?)
  "Like 'git-fetch', fetch COMMIT from URL into DIRECTORY, but fall back to
alternative methods when fetching from URL fails: attempt to download a nar,
and if that also fails, download from the Software Heritage archive."
  (or (git-fetch url commit directory
                 #:lfs? lfs?
                 #:recursive? recursive?
                 #:git-command git-command)
      (download-nar directory)

      ;; As a last resort, attempt to download from Software Heritage.
      ;; Disable X.509 certificate verification to avoid depending
      ;; on nss-certs--we're authenticating the checkout anyway.
      ;; XXX: Currently recursive checkouts are not supported.
      (and (not recursive?)
           (parameterize ((%verify-swh-certificate? #f))
             (format (current-error-port)
                     "Trying to download from Software Heritage...~%")

             (swh-download url commit directory)
             (when (file-exists?
                    (string-append directory "/.gitattributes"))
               ;; Perform CR/LF conversion and other changes
               ;; specificied by '.gitattributes'.
               (invoke git-command "-C" directory "init")
               (invoke git-command "-C" directory "config" "--local"
                       "user.email" "you@example.org")
               (invoke git-command "-C" directory "config" "--local"
                       "user.name" "Your Name")
               (invoke git-command "-C" directory "add" ".")
               (invoke git-command "-C" directory "commit" "-am" "init")
               (invoke git-command "-C" directory "read-tree" "--empty")
               (invoke git-command "-C" directory "reset" "--hard")
               (delete-file-recursively
                (string-append directory "/.git")))))))

;;; git.scm ends here

debug log:

solving 867cade2c4 ...
found 867cade2c4 in https://git.savannah.gnu.org/cgit/guix.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.