1 # Copyright 1999-2018 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 # @ECLASS: git-r3.eclass
6 # Michał Górny <mgorny@gentoo.org>
7 # @BLURB: Eclass for fetching and unpacking git repositories.
9 # Third generation eclass for easing maintenance of live ebuilds using
10 # git as remote repository.
16 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
20 EXPORT_FUNCTIONS src_unpack
22 if [[ ! ${_GIT_R3} ]]; then
24 if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
25 if [[ ${EAPI:-0} != [0123456] ]]; then
26 BDEPEND=">=dev-vcs/git-1.8.2.1"
28 DEPEND=">=dev-vcs/git-1.8.2.1"
32 # @ECLASS-VARIABLE: EGIT_CLONE_TYPE
34 # Type of clone that should be used against the remote repository.
35 # This can be either of: 'mirror', 'single', 'shallow'.
37 # This is intended to be set by user in make.conf. Ebuilds are supposed
38 # to set EGIT_MIN_CLONE_TYPE if necessary instead.
40 # The 'mirror' type clones all remote branches and tags with complete
41 # history and all notes. EGIT_COMMIT can specify any commit hash.
42 # Upstream-removed branches and tags are purged from the local clone
43 # while fetching. This mode is suitable for cloning the local copy
44 # for development or hosting a local git mirror. However, clones
45 # of repositories with large diverged branches may quickly grow large.
47 # The 'single+tags' type clones the requested branch and all tags
48 # in the repository. All notes are fetched as well. EGIT_COMMIT
49 # can safely specify hashes throughout the current branch and all tags.
50 # No purging of old references is done (if you often switch branches,
51 # you may need to remove stale branches yourself). This mode is intended
52 # mostly for use with broken git servers such as Google Code that fail
53 # to fetch tags along with the branch in 'single' mode.
55 # The 'single' type clones only the requested branch or tag. Tags
56 # referencing commits throughout the branch history are fetched as well,
57 # and all notes. EGIT_COMMIT can safely specify only hashes
58 # in the current branch. No purging of old references is done (if you
59 # often switch branches, you may need to remove stale branches
60 # yourself). This mode is suitable for general use.
62 # The 'shallow' type clones only the newest commit on requested branch
63 # or tag. EGIT_COMMIT can only specify tags, and since the history is
64 # unavailable calls like 'git describe' will not reference prior tags.
65 # No purging of old references is done. This mode is intended mostly for
66 # embedded systems with limited disk space.
67 : ${EGIT_CLONE_TYPE:=single}
69 # @ECLASS-VARIABLE: EGIT_MIN_CLONE_TYPE
71 # 'Minimum' clone type supported by the ebuild. Takes same values
72 # as EGIT_CLONE_TYPE. When user sets a type that's 'lower' (that is,
73 # later on the list) than EGIT_MIN_CLONE_TYPE, the eclass uses
74 # EGIT_MIN_CLONE_TYPE instead.
76 # This variable is intended to be used by ebuilds only. Users are
77 # supposed to set EGIT_CLONE_TYPE instead.
79 # A common case is to use 'single' whenever the build system requires
80 # access to full branch history, or 'single+tags' when Google Code
81 # or a similar remote is used that does not support shallow clones
82 # and fetching tags along with commits. Please use sparingly, and to fix
83 # fatal errors rather than 'non-pretty versions'.
84 : ${EGIT_MIN_CLONE_TYPE:=shallow}
86 # @ECLASS-VARIABLE: EGIT3_STORE_DIR
88 # Storage directory for git sources.
90 # This is intended to be set by user in make.conf. Ebuilds must not set
93 # EGIT3_STORE_DIR=${DISTDIR}/git3-src
95 # @ECLASS-VARIABLE: EGIT_MIRROR_URI
98 # 'Top' URI to a local git mirror. If specified, the eclass will try
99 # to fetch from the local mirror instead of using the remote repository.
101 # The mirror needs to follow EGIT3_STORE_DIR structure. The directory
102 # created by eclass can be used for that purpose.
106 # EGIT_MIRROR_URI="git://mirror.lan/"
109 # @ECLASS-VARIABLE: EGIT_REPO_URI
112 # URIs to the repository, e.g. https://foo. If multiple URIs are
113 # provided, the eclass will consider the remaining URIs as fallbacks
114 # to try if the first URI does not work. For supported URI syntaxes,
115 # read the manpage for git-clone(1).
117 # URIs should be using https:// whenever possible. http:// and git://
118 # URIs are completely unsecured and their use (even if only as
119 # a fallback) renders the ebuild completely vulnerable to MITM attacks.
121 # It can be overridden via env using ${PN}_LIVE_REPO variable.
123 # Can be a whitespace-separated list or an array.
127 # EGIT_REPO_URI="https://a/b.git https://c/d.git"
130 # @ECLASS-VARIABLE: EVCS_OFFLINE
133 # If non-empty, this variable prevents any online operations.
135 # @ECLASS-VARIABLE: EVCS_UMASK
138 # Set this variable to a custom umask. This is intended to be set by
139 # users. By setting this to something like 002, it can make life easier
140 # for people who do development as non-root (but are in the portage
141 # group), and then switch over to building with FEATURES=userpriv.
142 # Or vice-versa. Shouldn't be a security issue here as anyone who has
143 # portage group write access already can screw the system over in more
146 # @ECLASS-VARIABLE: EGIT_BRANCH
149 # The branch name to check out. If unset, the upstream default (HEAD)
152 # It can be overridden via env using ${PN}_LIVE_BRANCH variable.
154 # @ECLASS-VARIABLE: EGIT_COMMIT
157 # The tag name or commit identifier to check out. If unset, newest
158 # commit from the branch will be used. Note that if set to a commit
159 # not on HEAD branch, EGIT_BRANCH needs to be set to a branch on which
160 # the commit is available.
162 # It can be overridden via env using ${PN}_LIVE_COMMIT variable.
164 # @ECLASS-VARIABLE: EGIT_COMMIT_DATE
167 # Attempt to check out the repository state for the specified timestamp.
168 # The date should be in format understood by 'git rev-list'. The commits
169 # on EGIT_BRANCH will be considered.
171 # The eclass will select the last commit with commit date preceding
172 # the specified date. When merge commits are found, only first parents
173 # will be considered in order to avoid switching into external branches
174 # (assuming that merges are done correctly). In other words, each merge
175 # will be considered alike a single commit with date corresponding
176 # to the merge commit date.
178 # It can be overridden via env using ${PN}_LIVE_COMMIT_DATE variable.
180 # @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
182 # The directory to check the git sources out to.
184 # EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
186 # @ECLASS-VARIABLE: EGIT_SUBMODULES
189 # An array of inclusive and exclusive wildcards on submodule names,
190 # stating which submodules are fetched and checked out. Exclusions
191 # start with '-', and exclude previously matched submodules.
193 # If unset, all submodules are enabled. Empty list disables all
194 # submodules. In order to use an exclude-only list, start the array
197 # Remember that wildcards need to be quoted in order to prevent filename
202 # # Disable all submodules
205 # # Include only foo and bar
206 # EGIT_SUBMODULES=( foo bar )
208 # # Use all submodules except for test-* but include test-lib
209 # EGIT_SUBMODULES=( '*' '-test-*' test-lib )
212 # @FUNCTION: _git-r3_env_setup
215 # Set the eclass variables as necessary for operation. This can involve
216 # setting EGIT_* to defaults or ${PN}_LIVE_* variables.
217 _git-r3_env_setup() {
218 debug-print-function ${FUNCNAME} "$@"
220 # check the clone type
221 case "${EGIT_CLONE_TYPE}" in
222 mirror|single+tags|single|shallow)
225 die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
227 case "${EGIT_MIN_CLONE_TYPE}" in
231 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
232 einfo "git-r3: ebuild needs to be cloned in '\e[1msingle\e[22m' mode, adjusting"
233 EGIT_CLONE_TYPE=single
237 if [[ ${EGIT_CLONE_TYPE} == shallow || ${EGIT_CLONE_TYPE} == single ]]; then
238 einfo "git-r3: ebuild needs to be cloned in '\e[1msingle+tags\e[22m' mode, adjusting"
239 EGIT_CLONE_TYPE=single+tags
243 if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then
244 einfo "git-r3: ebuild needs to be cloned in '\e[1mmirror\e[22m' mode, adjusting"
245 EGIT_CLONE_TYPE=mirror
249 die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
252 if [[ ${EGIT_SUBMODULES[@]+1} && $(declare -p EGIT_SUBMODULES) != "declare -a"* ]]
254 die 'EGIT_SUBMODULES must be an array.'
259 [[ ${esc_pn} == [0-9]* ]] && esc_pn=_${esc_pn}
261 livevar=${esc_pn}_LIVE_REPO
262 EGIT_REPO_URI=${!livevar-${EGIT_REPO_URI}}
264 && ewarn "Using ${livevar}, no support will be provided"
266 livevar=${esc_pn}_LIVE_BRANCH
267 EGIT_BRANCH=${!livevar-${EGIT_BRANCH}}
269 && ewarn "Using ${livevar}, no support will be provided"
271 livevar=${esc_pn}_LIVE_COMMIT
272 EGIT_COMMIT=${!livevar-${EGIT_COMMIT}}
274 && ewarn "Using ${livevar}, no support will be provided"
276 livevar=${esc_pn}_LIVE_COMMIT_DATE
277 EGIT_COMMIT_DATE=${!livevar-${EGIT_COMMIT_DATE}}
279 && ewarn "Using ${livevar}, no support will be provided"
281 if [[ ${EGIT_COMMIT} && ${EGIT_COMMIT_DATE} ]]; then
282 die "EGIT_COMMIT and EGIT_COMMIT_DATE can not be specified simultaneously"
285 # Migration helpers. Remove them when git-2 is removed.
287 if [[ ${EGIT_SOURCEDIR} ]]; then
288 eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating"
289 eerror "your ebuild, please check whether the variable is necessary at all"
290 eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}."
291 eerror "Therefore, proper setting of S may be sufficient."
292 die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR."
295 if [[ ${EGIT_MASTER} ]]; then
296 eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)"
297 eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH"
298 eerror "as necessary."
299 die "EGIT_MASTER has been removed."
302 if [[ ${EGIT_HAS_SUBMODULES} ]]; then
303 eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs"
304 eerror "to switch the clone type in order to support submodules and therefore"
305 eerror "submodules are detected and fetched automatically. If you need to"
306 eerror "disable or filter submodules, see EGIT_SUBMODULES."
307 die "EGIT_HAS_SUBMODULES is no longer necessary."
310 if [[ ${EGIT_PROJECT} ]]; then
311 eerror "EGIT_PROJECT has been removed. Instead, the eclass determines"
312 eerror "the local clone path using path in canonical EGIT_REPO_URI."
313 eerror "If the current algorithm causes issues for you, please report a bug."
314 die "EGIT_PROJECT is no longer necessary."
317 if [[ ${EGIT_BOOTSTRAP} ]]; then
318 eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()"
320 die "EGIT_BOOTSTRAP has been removed."
323 if [[ ${EGIT_NOUNPACK} ]]; then
324 eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default"
325 eerror "unpack function. If necessary, please declare proper src_unpack()."
326 die "EGIT_NOUNPACK has been removed."
330 # @FUNCTION: _git-r3_set_gitdir
334 # Obtain the local repository path and set it as GIT_DIR. Creates
335 # a new repository if necessary.
337 # <repo-uri> may be used to compose the path. It should therefore be
338 # a canonical URI to the repository.
339 _git-r3_set_gitdir() {
340 debug-print-function ${FUNCNAME} "$@"
342 local repo_name=${1#*://*/}
344 # strip the trailing slash
345 repo_name=${repo_name%/}
347 # strip common prefixes to make paths more likely to match
348 # e.g. git://X/Y.git vs https://X/git/Y.git
349 # (but just one of the prefixes)
350 case "${repo_name}" in
351 # gnome.org... who else?
352 browse/*) repo_name=${repo_name#browse/};;
353 # cgit can proxy requests to git
354 cgit/*) repo_name=${repo_name#cgit/};;
356 git/*) repo_name=${repo_name#git/};;
358 gitroot/*) repo_name=${repo_name#gitroot/};;
360 p/*) repo_name=${repo_name#p/};;
362 pub/scm/*) repo_name=${repo_name#pub/scm/};;
364 # ensure a .git suffix, same reason
365 repo_name=${repo_name%.git}.git
366 # now replace all the slashes
367 repo_name=${repo_name//\//_}
369 local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
370 : ${EGIT3_STORE_DIR:=${distdir}/git3-src}
372 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
374 if [[ ! -d ${EGIT3_STORE_DIR} && ! ${EVCS_OFFLINE} ]]; then
377 mkdir -p "${EGIT3_STORE_DIR}"
378 ) || die "Unable to create ${EGIT3_STORE_DIR}"
381 addwrite "${EGIT3_STORE_DIR}"
382 if [[ ! -d ${GIT_DIR} ]]; then
383 if [[ ${EVCS_OFFLINE} ]]; then
384 eerror "A clone of the following repository is required to proceed:"
386 eerror "However, networking activity has been disabled using EVCS_OFFLINE and there"
387 eerror "is no local clone available."
388 die "No local clone of ${1}. Unable to proceed with EVCS_OFFLINE."
392 if [[ ${EVCS_UMASK} ]]; then
394 umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
396 mkdir "${GIT_DIR}" || die
397 git init --bare || die
398 if [[ ${saved_umask} ]]; then
399 umask "${saved_umask}" || die
404 # @FUNCTION: _git-r3_set_submodules
405 # @USAGE: <file-contents>
408 # Parse .gitmodules contents passed as <file-contents>
409 # as in "$(cat .gitmodules)"). Composes a 'submodules' array that
410 # contains in order (name, URL, path) for each submodule.
411 _git-r3_set_submodules() {
412 debug-print-function ${FUNCNAME} "$@"
416 # ( name url path ... )
421 # submodule.<path>.path=<path>
422 # submodule.<path>.url=<url>
423 [[ ${l} == submodule.*.url=* ]] || continue
426 local subname=${l%%.url=*}
428 # filter out on EGIT_SUBMODULES
429 if declare -p EGIT_SUBMODULES &>/dev/null; then
431 for p in "${EGIT_SUBMODULES[@]}"; do
432 if [[ ${p} == -* ]]; then
439 [[ ${subname} == ${p} ]] && res=${l_res}
442 if [[ ! ${res} ]]; then
443 einfo "Skipping submodule \e[1m${subname}\e[22m"
448 # skip modules that have 'update = none', bug #487262.
449 local upd=$(echo "${data}" | git config -f /dev/fd/0 \
450 submodule."${subname}".update)
451 [[ ${upd} == none ]] && continue
453 # https://github.com/git/git/blob/master/refs.c#L31
454 # we are more restrictive than git itself but that should not
455 # cause any issues, #572312, #606950
456 # TODO: check escaped names for collisions
457 local enc_subname=${subname//[^a-zA-Z0-9-]/_}
461 "$(echo "${data}" | git config -f /dev/fd/0 \
462 submodule."${subname}".url || die)"
463 "$(echo "${data}" | git config -f /dev/fd/0 \
464 submodule."${subname}".path || die)"
466 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
469 # @FUNCTION: _git-r3_set_subrepos
470 # @USAGE: <submodule-uri> <parent-repo-uri>...
473 # Create 'subrepos' array containing absolute (canonical) submodule URIs
474 # for the given <submodule-uri>. If the URI is relative, URIs will be
475 # constructed using all <parent-repo-uri>s. Otherwise, this single URI
476 # will be placed in the array.
477 _git-r3_set_subrepos() {
478 debug-print-function ${FUNCNAME} "$@"
481 subrepos=( "${@:2}" )
483 if [[ ${suburl} == ./* || ${suburl} == ../* ]]; then
484 # drop all possible trailing slashes for consistency
485 subrepos=( "${subrepos[@]%%/}" )
488 if [[ ${suburl} == ./* ]]; then
490 elif [[ ${suburl} == ../* ]]; then
493 # XXX: correctness checking
495 # drop the last path component
496 subrepos=( "${subrepos[@]%/*}" )
497 # and then the trailing slashes, again
498 subrepos=( "${subrepos[@]%%/}" )
504 # append the preprocessed path to the preprocessed URIs
505 subrepos=( "${subrepos[@]/%//${suburl}}")
507 subrepos=( "${suburl}" )
512 # @FUNCTION: _git-r3_is_local_repo
516 # Determine whether the given URI specifies a local (on-disk)
518 _git-r3_is_local_repo() {
519 debug-print-function ${FUNCNAME} "$@"
523 [[ ${uri} == file://* || ${uri} == /* ]]
526 # @FUNCTION: git-r3_fetch
527 # @USAGE: [<repo-uri> [<remote-ref> [<local-id> [<commit-date>]]]]
529 # Fetch new commits to the local clone of repository.
531 # <repo-uri> specifies the repository URIs to fetch from, as a space-
532 # -separated list. The first URI will be used as repository group
533 # identifier and therefore must be used consistently. When not
534 # specified, defaults to ${EGIT_REPO_URI}.
536 # <remote-ref> specifies the remote ref or commit id to fetch.
537 # It is preferred to use 'refs/heads/<branch-name>' for branches
538 # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
539 # for upstream default branch and hexadecimal commit SHA1. Defaults
540 # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
541 # is set to a non-null value.
543 # <local-id> specifies the local branch identifier that will be used to
544 # locally store the fetch result. It should be unique to multiple
545 # fetches within the repository that can be performed at the same time
546 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
547 # This default should be fine unless you are fetching multiple trees
548 # from the same repository in the same ebuild.
550 # <commit-id> requests attempting to use repository state as of specific
551 # date. For more details, see EGIT_COMMIT_DATE.
553 # The fetch operation will affect the EGIT_STORE only. It will not touch
554 # the working copy, nor export any environment variables.
555 # If the repository contains submodules, they will be fetched
558 debug-print-function ${FUNCNAME} "$@"
560 # process repos first since we create repo_name from it
564 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
565 repos=( "${EGIT_REPO_URI[@]}" )
567 repos=( ${EGIT_REPO_URI} )
570 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
573 for r in "${repos[@]}"; do
574 if [[ ${r} == git:* || ${r} == http:* ]]; then
575 ewarn "git-r3: ${r%%:*} protocol is completely unsecure and may render the ebuild"
576 ewarn "easily susceptible to MITM attacks (even if used only as fallback). Please"
577 ewarn "use https instead."
583 _git-r3_set_gitdir "${repos[0]}"
585 # prepend the local mirror if applicable
586 if [[ ${EGIT_MIRROR_URI} ]]; then
588 "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
593 # get the default values for the common variables and override them
594 local branch_name=${EGIT_BRANCH}
595 local commit_id=${2:-${EGIT_COMMIT}}
596 local commit_date=${4:-${EGIT_COMMIT_DATE}}
598 # support new override API for EAPI 6+
599 if ! has "${EAPI:-0}" 0 1 2 3 4 5; then
600 # get the name and do some more processing:
601 # 1) kill .git suffix,
602 # 2) underscore (remaining) non-variable characters,
603 # 3) add preceding underscore if it starts with a digit,
605 local override_name=${GIT_DIR##*/}
606 override_name=${override_name%.git}
607 override_name=${override_name//[^a-zA-Z0-9_]/_}
608 override_name=${override_name^^}
614 COMMIT_DATE:commit_date
617 local localvar livevar live_warn=
618 for localvar in "${varmap[@]}"; do
619 livevar=EGIT_OVERRIDE_${localvar%:*}_${override_name}
620 localvar=${localvar#*:}
622 if [[ -n ${!livevar} ]]; then
623 [[ ${localvar} == repos ]] && repos=()
625 ewarn "Using ${livevar}=${!livevar}"
626 declare "${localvar}=${!livevar}"
630 if [[ ${live_warn} ]]; then
631 ewarn "No support will be provided."
635 # set final variables after applying overrides
636 local branch=${branch_name:+refs/heads/${branch_name}}
637 local remote_ref=${commit_id:-${branch:-HEAD}}
638 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
639 local local_ref=refs/git-r3/${local_id}/__main__
641 # try to fetch from the remote
642 local success saved_umask
643 if [[ ${EVCS_UMASK} ]]; then
645 umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
647 for r in "${repos[@]}"; do
648 if [[ ! ${EVCS_OFFLINE} ]]; then
649 einfo "Fetching \e[1m${r}\e[22m ..."
651 local fetch_command=( git fetch "${r}" )
652 local clone_type=${EGIT_CLONE_TYPE}
654 if [[ ${r} == http://* || ${r} == https://* ]] &&
655 [[ ! ${EGIT_CURL_WARNED} ]]
659 ROOT=/ has_version 'dev-vcs/git[curl]';;
661 has_version --host-root 'dev-vcs/git[curl]';;
663 has_version -b 'dev-vcs/git[curl]';;
666 if [[ ${?} -ne 0 ]]; then
667 ewarn "git-r3: fetching from HTTP(S) requested. In order to support HTTP(S),"
668 ewarn "dev-vcs/git needs to be built with USE=curl. Example solution:"
670 ewarn " echo dev-vcs/git curl >> /etc/portage/package.use"
671 ewarn " emerge -1v dev-vcs/git"
673 ewarn "HTTP(S) URIs will be skipped."
679 if [[ ${clone_type} == mirror ]]; then
682 # mirror the remote branches as local branches
683 "+refs/heads/*:refs/heads/*"
684 # pull tags explicitly in order to prune them properly
685 "+refs/tags/*:refs/tags/*"
686 # notes in case something needs them
687 "+refs/notes/*:refs/notes/*"
688 # and HEAD in case we need the default branch
689 # (we keep it in refs/git-r3 since otherwise --prune interferes)
690 "+HEAD:refs/git-r3/HEAD"
692 else # single or shallow
693 local fetch_l fetch_r
695 if [[ ${remote_ref} == HEAD ]]; then
698 elif [[ ${remote_ref} == refs/* ]]; then
699 # regular branch, tag or some other explicit ref
700 fetch_l=${remote_ref}
702 # tag or commit id...
703 # let ls-remote figure it out
704 local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
706 # if it was a tag, ls-remote obtained a hash
707 if [[ ${tagref} ]]; then
709 fetch_l=refs/tags/${remote_ref}
712 # so we need to fetch the whole branch
713 if [[ ${branch} ]]; then
719 # fetching by commit in shallow mode? can't do.
720 if [[ ${clone_type} == shallow ]]; then
726 # checkout by date does not make sense in shallow mode
727 if [[ ${commit_date} && ${clone_type} == shallow ]]; then
731 if [[ ${fetch_l} == HEAD ]]; then
732 fetch_r=refs/git-r3/HEAD
738 "+${fetch_l}:${fetch_r}"
741 if [[ ${clone_type} == single+tags ]]; then
743 # pull tags explicitly as requested
744 "+refs/tags/*:refs/tags/*"
749 if [[ ${clone_type} == shallow ]]; then
750 if _git-r3_is_local_repo; then
751 # '--depth 1' causes sandbox violations with local repos
754 elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
756 # use '--depth 1' when fetching a new branch
757 fetch_command+=( --depth 1 )
759 else # non-shallow mode
760 if [[ -f ${GIT_DIR}/shallow ]]; then
761 fetch_command+=( --unshallow )
765 set -- "${fetch_command[@]}"
769 if [[ ${clone_type} == mirror || ${fetch_l} == HEAD ]]; then
770 # update our HEAD to match our remote HEAD ref
771 git symbolic-ref HEAD refs/git-r3/HEAD \
772 || die "Unable to update HEAD"
776 # now let's see what the user wants from us
777 if [[ ${commit_date} ]]; then
778 local dated_commit_id=$(
779 git rev-list --first-parent --before="${commit_date}" \
782 if [[ ${?} -ne 0 ]]; then
783 die "Listing ${remote_ref} failed (wrong ref?)."
784 elif [[ ! ${dated_commit_id} ]]; then
785 die "Unable to find commit for date ${commit_date}."
787 set -- git update-ref --no-deref "${local_ref}" "${dated_commit_id}"
790 local full_remote_ref=$(
791 git rev-parse --verify --symbolic-full-name "${remote_ref}"
794 if [[ ${full_remote_ref} ]]; then
795 # when we are given a ref, create a symbolic ref
796 # so that we preserve the actual argument
797 set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
799 # otherwise, we were likely given a commit id
800 set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
806 if [[ ${EVCS_OFFLINE} ]]; then
807 eerror "A clone of the following repository is required to proceed:"
809 eerror "However, networking activity has been disabled using EVCS_OFFLINE and the local"
810 eerror "clone does not have requested ref:"
811 eerror " ${remote_ref}"
812 die "Local clone of ${r} does not have requested ref: ${remote_ref}. Unable to proceed with EVCS_OFFLINE."
814 die "Referencing ${remote_ref} failed (wrong ref?)."
821 if [[ ${saved_umask} ]]; then
822 umask "${saved_umask}" || die
824 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
826 # submodules can reference commits in any branch
827 # always use the 'mirror' mode to accomodate that, bug #503332
828 local EGIT_CLONE_TYPE=mirror
830 # recursively fetch submodules
831 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
833 _git-r3_set_submodules \
834 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
836 while [[ ${submodules[@]} ]]; do
837 local subname=${submodules[0]}
838 local url=${submodules[1]}
839 local path=${submodules[2]}
841 # use only submodules for which path does exist
842 # (this is in par with 'git submodule'), bug #551100
843 # note: git cat-file does not work for submodules
844 if [[ $(git ls-tree -d "${local_ref}" "${path}") ]]
846 local commit=$(git rev-parse "${local_ref}:${path}" || die)
848 if [[ ! ${commit} ]]; then
849 die "Unable to get commit id for submodule ${subname}"
853 _git-r3_set_subrepos "${url}" "${repos[@]}"
855 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
858 submodules=( "${submodules[@]:3}" ) # shift
863 # @FUNCTION: git-r3_checkout
864 # @USAGE: [<repo-uri> [<checkout-path> [<local-id> [<checkout-paths>...]]]]
866 # Check the previously fetched tree to the working copy.
868 # <repo-uri> specifies the repository URIs, as a space-separated list.
869 # The first URI will be used as repository group identifier
870 # and therefore must be used consistently with git-r3_fetch.
871 # The remaining URIs are not used and therefore may be omitted.
872 # When not specified, defaults to ${EGIT_REPO_URI}.
874 # <checkout-path> specifies the path to place the checkout. It defaults
875 # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
877 # <local-id> needs to specify the local identifier that was used
878 # for respective git-r3_fetch.
880 # If <checkout-paths> are specified, then the specified paths are passed
881 # to 'git checkout' to effect a partial checkout. Please note that such
882 # checkout will not cause the repository to switch branches,
883 # and submodules will be skipped at the moment. The submodules matching
884 # those paths might be checked out in a future version of the eclass.
886 # The checkout operation will write to the working copy, and export
887 # the repository state into the environment. If the repository contains
888 # submodules, they will be checked out recursively.
890 debug-print-function ${FUNCNAME} "$@"
895 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
896 repos=( "${EGIT_REPO_URI[@]}" )
898 repos=( ${EGIT_REPO_URI} )
901 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
902 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
903 local checkout_paths=( "${@:4}" )
906 _git-r3_set_gitdir "${repos[0]}"
908 einfo "Checking out \e[1m${repos[0]}\e[22m to \e[1m${out_dir}\e[22m ..."
910 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
911 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
914 git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
916 local new_commit_id=$(
917 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
920 git-r3_sub_checkout() {
921 local orig_repo=${GIT_DIR}
922 local -x GIT_DIR=${out_dir}/.git
923 local -x GIT_WORK_TREE=${out_dir}
925 mkdir -p "${out_dir}" || die
927 # use git init+fetch instead of clone since the latter doesn't like
928 # non-empty directories.
930 git init --quiet || die
931 # setup 'alternates' to avoid copying objects
932 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
934 cp -R "${orig_repo}"/refs/* "${GIT_DIR}"/refs/ || die
935 if [[ -f ${orig_repo}/packed-refs ]]; then
936 cp "${orig_repo}"/packed-refs "${GIT_DIR}"/packed-refs || die
939 # (no need to copy HEAD, we will set it via checkout)
941 if [[ -f ${orig_repo}/shallow ]]; then
942 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
945 set -- git checkout --quiet
946 if [[ ${remote_ref} ]]; then
947 set -- "${@}" "${remote_ref#refs/heads/}"
949 set -- "${@}" "${new_commit_id}"
951 if [[ ${checkout_paths[@]} ]]; then
952 set -- "${@}" -- "${checkout_paths[@]}"
955 "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
958 unset -f git-r3_sub_checkout
960 local old_commit_id=$(
961 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
963 if [[ ! ${old_commit_id} ]]; then
964 echo "GIT NEW branch -->"
965 echo " repository: ${repos[0]}"
966 echo " at the commit: ${new_commit_id}"
968 # diff against previous revision
969 echo "GIT update -->"
970 echo " repository: ${repos[0]}"
971 # write out message based on the revisions
972 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
973 echo " updating from commit: ${old_commit_id}"
974 echo " to commit: ${new_commit_id}"
976 set -- git --no-pager diff --stat \
977 ${old_commit_id}..${new_commit_id}
978 if [[ ${checkout_paths[@]} ]]; then
979 set -- "${@}" -- "${checkout_paths[@]}"
983 echo " at the commit: ${new_commit_id}"
986 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
988 # recursively checkout submodules
989 if [[ -f ${out_dir}/.gitmodules && ! ${checkout_paths} ]]; then
991 _git-r3_set_submodules \
992 "$(<"${out_dir}"/.gitmodules)"
994 while [[ ${submodules[@]} ]]; do
995 local subname=${submodules[0]}
996 local url=${submodules[1]}
997 local path=${submodules[2]}
999 # use only submodules for which path does exist
1000 # (this is in par with 'git submodule'), bug #551100
1001 if [[ -d ${out_dir}/${path} ]]; then
1003 _git-r3_set_subrepos "${url}" "${repos[@]}"
1005 git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \
1006 "${local_id}/${subname}"
1009 submodules=( "${submodules[@]:3}" ) # shift
1013 # keep this *after* submodules
1014 export EGIT_DIR=${GIT_DIR}
1015 export EGIT_VERSION=${new_commit_id}
1018 # @FUNCTION: git-r3_peek_remote_ref
1019 # @USAGE: [<repo-uri> [<remote-ref>]]
1021 # Peek the reference in the remote repository and print the matching
1022 # (newest) commit SHA1.
1024 # <repo-uri> specifies the repository URIs to fetch from, as a space-
1025 # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
1027 # <remote-ref> specifies the remote ref to peek. It is preferred to use
1028 # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
1029 # for tags. Alternatively, 'HEAD' may be used for upstream default
1030 # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
1031 # 'HEAD' that is set to a non-null value.
1033 # The operation will be done purely on the remote, without using local
1034 # storage. If commit SHA1 is provided as <remote-ref>, the function will
1035 # fail due to limitations of git protocol.
1037 # On success, the function returns 0 and writes hexadecimal commit SHA1
1038 # to stdout. On failure, the function returns 1.
1039 git-r3_peek_remote_ref() {
1040 debug-print-function ${FUNCNAME} "$@"
1045 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
1046 repos=( "${EGIT_REPO_URI[@]}" )
1048 repos=( ${EGIT_REPO_URI} )
1051 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
1052 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
1054 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
1057 for r in "${repos[@]}"; do
1058 einfo "Peeking \e[1m${remote_ref}\e[22m on \e[1m${r}\e[22m ..." >&2
1061 if [[ ${remote_ref} == refs/* || ${remote_ref} == HEAD ]]
1063 lookup_ref=${remote_ref}
1065 # ls-remote by commit is going to fail anyway,
1066 # so we may as well pass refs/tags/ABCDEF...
1067 lookup_ref=refs/tags/${remote_ref}
1070 # split on whitespace
1072 $(git ls-remote "${r}" "${lookup_ref}")
1075 if [[ ${ref[0]} ]]; then
1084 git-r3_src_fetch() {
1085 debug-print-function ${FUNCNAME} "$@"
1087 if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
1088 ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
1089 ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
1090 ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
1091 ewarn "when git-2 eclass becomes deprecated."
1098 git-r3_src_unpack() {
1099 debug-print-function ${FUNCNAME} "$@"
1106 # https://bugs.gentoo.org/show_bug.cgi?id=482666
1107 git-r3_pkg_needrebuild() {
1108 debug-print-function ${FUNCNAME} "$@"
1110 local new_commit_id=$(git-r3_peek_remote_ref)
1111 [[ ${new_commit_id} && ${EGIT_VERSION} ]] || die "Lookup failed"
1113 if [[ ${EGIT_VERSION} != ${new_commit_id} ]]; then
1114 einfo "Update from \e[1m${EGIT_VERSION}\e[22m to \e[1m${new_commit_id}\e[22m"
1116 einfo "Local and remote at \e[1m${EGIT_VERSION}\e[22m"
1119 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
1122 # 'export' locally until this gets into EAPI
1123 pkg_needrebuild() { git-r3_pkg_needrebuild; }