Gentoo Archives: gentoo-commits

From: "José María Alonso" <nimiux@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/lisp:master commit in: eclass/
Date: Tue, 29 Nov 2016 22:43:33
Message-Id: 1480459404.00116aee91a1c4af1a3eed3b3dd454c5dbb02809.nimiux@gentoo
1 commit: 00116aee91a1c4af1a3eed3b3dd454c5dbb02809
2 Author: Chema Alonso Josa <nimiux <AT> gentoo <DOT> org>
3 AuthorDate: Tue Nov 29 22:43:24 2016 +0000
4 Commit: José María Alonso <nimiux <AT> gentoo <DOT> org>
5 CommitDate: Tue Nov 29 22:43:24 2016 +0000
6 URL: https://gitweb.gentoo.org/proj/lisp.git/commit/?id=00116aee
7
8 eclass: Adds git-r3 eclass
9
10 eclass/git-r3.eclass | 1041 ++++++++++++++++++++++++++++++++++++++++++++++++++
11 1 file changed, 1041 insertions(+)
12
13 diff --git a/eclass/git-r3.eclass b/eclass/git-r3.eclass
14 new file mode 100644
15 index 0000000..f76f1a7
16 --- /dev/null
17 +++ b/eclass/git-r3.eclass
18 @@ -0,0 +1,1041 @@
19 +# Copyright 1999-2015 Gentoo Foundation
20 +# Distributed under the terms of the GNU General Public License v2
21 +# $Id$
22 +
23 +# @ECLASS: git-r3.eclass
24 +# @MAINTAINER:
25 +# Michał Górny <mgorny@g.o>
26 +# @BLURB: Eclass for fetching and unpacking git repositories.
27 +# @DESCRIPTION:
28 +# Third generation eclass for easing maintenance of live ebuilds using
29 +# git as remote repository.
30 +
31 +case "${EAPI:-0}" in
32 + 0|1|2|3|4|5|6)
33 + ;;
34 + *)
35 + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
36 + ;;
37 +esac
38 +
39 +if [[ ! ${_GIT_R3} ]]; then
40 +
41 +inherit eutils
42 +
43 +fi
44 +
45 +EXPORT_FUNCTIONS src_unpack
46 +
47 +if [[ ! ${_GIT_R3} ]]; then
48 +
49 +if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
50 + DEPEND=">=dev-vcs/git-1.8.2.1"
51 +fi
52 +
53 +# @ECLASS-VARIABLE: EGIT_CLONE_TYPE
54 +# @DESCRIPTION:
55 +# Type of clone that should be used against the remote repository.
56 +# This can be either of: 'mirror', 'single', 'shallow'.
57 +#
58 +# This is intended to be set by user in make.conf. Ebuilds are supposed
59 +# to set EGIT_MIN_CLONE_TYPE if necessary instead.
60 +#
61 +# The 'mirror' type clones all remote branches and tags with complete
62 +# history and all notes. EGIT_COMMIT can specify any commit hash.
63 +# Upstream-removed branches and tags are purged from the local clone
64 +# while fetching. This mode is suitable for cloning the local copy
65 +# for development or hosting a local git mirror. However, clones
66 +# of repositories with large diverged branches may quickly grow large.
67 +#
68 +# The 'single+tags' type clones the requested branch and all tags
69 +# in the repository. All notes are fetched as well. EGIT_COMMIT
70 +# can safely specify hashes throughout the current branch and all tags.
71 +# No purging of old references is done (if you often switch branches,
72 +# you may need to remove stale branches yourself). This mode is intended
73 +# mostly for use with broken git servers such as Google Code that fail
74 +# to fetch tags along with the branch in 'single' mode.
75 +#
76 +# The 'single' type clones only the requested branch or tag. Tags
77 +# referencing commits throughout the branch history are fetched as well,
78 +# and all notes. EGIT_COMMIT can safely specify only hashes
79 +# in the current branch. No purging of old references is done (if you
80 +# often switch branches, you may need to remove stale branches
81 +# yourself). This mode is suitable for general use.
82 +#
83 +# The 'shallow' type clones only the newest commit on requested branch
84 +# or tag. EGIT_COMMIT can only specify tags, and since the history is
85 +# unavailable calls like 'git describe' will not reference prior tags.
86 +# No purging of old references is done. This mode is intended mostly for
87 +# embedded systems with limited disk space.
88 +: ${EGIT_CLONE_TYPE:=single}
89 +
90 +# @ECLASS-VARIABLE: EGIT_MIN_CLONE_TYPE
91 +# @DESCRIPTION:
92 +# 'Minimum' clone type supported by the ebuild. Takes same values
93 +# as EGIT_CLONE_TYPE. When user sets a type that's 'lower' (that is,
94 +# later on the list) than EGIT_MIN_CLONE_TYPE, the eclass uses
95 +# EGIT_MIN_CLONE_TYPE instead.
96 +#
97 +# This variable is intended to be used by ebuilds only. Users are
98 +# supposed to set EGIT_CLONE_TYPE instead.
99 +#
100 +# A common case is to use 'single' whenever the build system requires
101 +# access to full branch history, or 'single+tags' when Google Code
102 +# or a similar remote is used that does not support shallow clones
103 +# and fetching tags along with commits. Please use sparingly, and to fix
104 +# fatal errors rather than 'non-pretty versions'.
105 +: ${EGIT_MIN_CLONE_TYPE:=shallow}
106 +
107 +# @ECLASS-VARIABLE: EGIT3_STORE_DIR
108 +# @DESCRIPTION:
109 +# Storage directory for git sources.
110 +#
111 +# This is intended to be set by user in make.conf. Ebuilds must not set
112 +# it.
113 +#
114 +# EGIT3_STORE_DIR=${DISTDIR}/git3-src
115 +
116 +# @ECLASS-VARIABLE: EGIT_MIRROR_URI
117 +# @DEFAULT_UNSET
118 +# @DESCRIPTION:
119 +# 'Top' URI to a local git mirror. If specified, the eclass will try
120 +# to fetch from the local mirror instead of using the remote repository.
121 +#
122 +# The mirror needs to follow EGIT3_STORE_DIR structure. The directory
123 +# created by eclass can be used for that purpose.
124 +#
125 +# Example:
126 +# @CODE
127 +# EGIT_MIRROR_URI="git://mirror.lan/"
128 +# @CODE
129 +
130 +# @ECLASS-VARIABLE: EGIT_REPO_URI
131 +# @REQUIRED
132 +# @DESCRIPTION:
133 +# URIs to the repository, e.g. git://foo, https://foo. If multiple URIs
134 +# are provided, the eclass will consider them as fallback URIs to try
135 +# if the first URI does not work. For supported URI syntaxes, read up
136 +# the manpage for git-clone(1).
137 +#
138 +# It can be overriden via env using ${PN}_LIVE_REPO variable.
139 +#
140 +# Can be a whitespace-separated list or an array.
141 +#
142 +# Example:
143 +# @CODE
144 +# EGIT_REPO_URI="git://a/b.git https://c/d.git"
145 +# @CODE
146 +
147 +# @ECLASS-VARIABLE: EVCS_OFFLINE
148 +# @DEFAULT_UNSET
149 +# @DESCRIPTION:
150 +# If non-empty, this variable prevents any online operations.
151 +
152 +# @ECLASS-VARIABLE: EVCS_UMASK
153 +# @DEFAULT_UNSET
154 +# @DESCRIPTION:
155 +# Set this variable to a custom umask. This is intended to be set by
156 +# users. By setting this to something like 002, it can make life easier
157 +# for people who do development as non-root (but are in the portage
158 +# group), and then switch over to building with FEATURES=userpriv.
159 +# Or vice-versa. Shouldn't be a security issue here as anyone who has
160 +# portage group write access already can screw the system over in more
161 +# creative ways.
162 +
163 +# @ECLASS-VARIABLE: EGIT_BRANCH
164 +# @DEFAULT_UNSET
165 +# @DESCRIPTION:
166 +# The branch name to check out. If unset, the upstream default (HEAD)
167 +# will be used.
168 +#
169 +# It can be overriden via env using ${PN}_LIVE_BRANCH variable.
170 +
171 +# @ECLASS-VARIABLE: EGIT_COMMIT
172 +# @DEFAULT_UNSET
173 +# @DESCRIPTION:
174 +# The tag name or commit identifier to check out. If unset, newest
175 +# commit from the branch will be used. If set, EGIT_BRANCH will
176 +# be ignored.
177 +#
178 +# It can be overriden via env using ${PN}_LIVE_COMMIT variable.
179 +
180 +# @ECLASS-VARIABLE: EGIT_COMMIT_DATE
181 +# @DEFAULT_UNSET
182 +# @DESCRIPTION:
183 +# Attempt to check out the repository state for the specified timestamp.
184 +# The date should be in format understood by 'git rev-list'.
185 +#
186 +# The eclass will select the last commit with commit date preceding
187 +# the specified date. When merge commits are found, only first parents
188 +# will be considered in order to avoid switching into external branches
189 +# (assuming that merges are done correctly). In other words, each merge
190 +# will be considered alike a single commit with date corresponding
191 +# to the merge commit date.
192 +#
193 +# It can be overriden via env using ${PN}_LIVE_COMMIT_DATE variable.
194 +
195 +# @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
196 +# @DESCRIPTION:
197 +# The directory to check the git sources out to.
198 +#
199 +# EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
200 +
201 +# @ECLASS-VARIABLE: EGIT_SUBMODULES
202 +# @DEFAULT_UNSET
203 +# @DESCRIPTION:
204 +# An array of inclusive and exclusive wildcards on submodule names,
205 +# stating which submodules are fetched and checked out. Exclusions
206 +# start with '-', and exclude previously matched submodules.
207 +#
208 +# If unset, all submodules are enabled. Empty list disables all
209 +# submodules. In order to use an exclude-only list, start the array
210 +# with '*'.
211 +#
212 +# Remember that wildcards need to be quoted in order to prevent filename
213 +# expansion.
214 +#
215 +# Examples:
216 +# @CODE
217 +# # Disable all submodules
218 +# EGIT_SUBMODULES=()
219 +#
220 +# # Include only foo and bar
221 +# EGIT_SUBMODULES=( foo bar )
222 +#
223 +# # Use all submodules except for test-* but include test-lib
224 +# EGIT_SUBMODULES=( '*' '-test-*' test-lib )
225 +# @CODE
226 +
227 +# @FUNCTION: _git-r3_env_setup
228 +# @INTERNAL
229 +# @DESCRIPTION:
230 +# Set the eclass variables as necessary for operation. This can involve
231 +# setting EGIT_* to defaults or ${PN}_LIVE_* variables.
232 +_git-r3_env_setup() {
233 + debug-print-function ${FUNCNAME} "$@"
234 +
235 + # check the clone type
236 + case "${EGIT_CLONE_TYPE}" in
237 + mirror|single+tags|single|shallow)
238 + ;;
239 + *)
240 + die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
241 + esac
242 + case "${EGIT_MIN_CLONE_TYPE}" in
243 + shallow)
244 + ;;
245 + single)
246 + if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
247 + einfo "git-r3: ebuild needs to be cloned in '\e[1msingle\e[22m' mode, adjusting"
248 + EGIT_CLONE_TYPE=single
249 + fi
250 + ;;
251 + single+tags)
252 + if [[ ${EGIT_CLONE_TYPE} == shallow || ${EGIT_CLONE_TYPE} == single ]]; then
253 + einfo "git-r3: ebuild needs to be cloned in '\e[1msingle+tags\e[22m' mode, adjusting"
254 + EGIT_CLONE_TYPE=single+tags
255 + fi
256 + ;;
257 + mirror)
258 + if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then
259 + einfo "git-r3: ebuild needs to be cloned in '\e[1mmirror\e[22m' mode, adjusting"
260 + EGIT_CLONE_TYPE=mirror
261 + fi
262 + ;;
263 + *)
264 + die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
265 + esac
266 +
267 + if [[ ${EGIT_SUBMODULES[@]+1} && $(declare -p EGIT_SUBMODULES) != "declare -a"* ]]
268 + then
269 + die 'EGIT_SUBMODULES must be an array.'
270 + fi
271 +
272 + local esc_pn livevar
273 + esc_pn=${PN//[-+]/_}
274 + [[ ${esc_pn} == [0-9]* ]] && esc_pn=_${esc_pn}
275 +
276 + livevar=${esc_pn}_LIVE_REPO
277 + EGIT_REPO_URI=${!livevar-${EGIT_REPO_URI}}
278 + [[ ${!livevar} ]] \
279 + && ewarn "Using ${livevar}, no support will be provided"
280 +
281 + livevar=${esc_pn}_LIVE_BRANCH
282 + EGIT_BRANCH=${!livevar-${EGIT_BRANCH}}
283 + [[ ${!livevar} ]] \
284 + && ewarn "Using ${livevar}, no support will be provided"
285 +
286 + livevar=${esc_pn}_LIVE_COMMIT
287 + EGIT_COMMIT=${!livevar-${EGIT_COMMIT}}
288 + [[ ${!livevar} ]] \
289 + && ewarn "Using ${livevar}, no support will be provided"
290 +
291 + livevar=${esc_pn}_LIVE_COMMIT_DATE
292 + EGIT_COMMIT_DATE=${!livevar-${EGIT_COMMIT_DATE}}
293 + [[ ${!livevar} ]] \
294 + && ewarn "Using ${livevar}, no support will be provided"
295 +
296 + if [[ ${EGIT_COMMIT} && ${EGIT_COMMIT_DATE} ]]; then
297 + die "EGIT_COMMIT and EGIT_COMMIT_DATE can not be specified simultaneously"
298 + fi
299 +
300 + # Migration helpers. Remove them when git-2 is removed.
301 +
302 + if [[ ${EGIT_SOURCEDIR} ]]; then
303 + eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating"
304 + eerror "your ebuild, please check whether the variable is necessary at all"
305 + eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}."
306 + eerror "Therefore, proper setting of S may be sufficient."
307 + die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR."
308 + fi
309 +
310 + if [[ ${EGIT_MASTER} ]]; then
311 + eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)"
312 + eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH"
313 + eerror "as necessary."
314 + die "EGIT_MASTER has been removed."
315 + fi
316 +
317 + if [[ ${EGIT_HAS_SUBMODULES} ]]; then
318 + eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs"
319 + eerror "to switch the clone type in order to support submodules and therefore"
320 + eerror "submodules are detected and fetched automatically. If you need to"
321 + eerror "disable or filter submodules, see EGIT_SUBMODULES."
322 + die "EGIT_HAS_SUBMODULES is no longer necessary."
323 + fi
324 +
325 + if [[ ${EGIT_PROJECT} ]]; then
326 + eerror "EGIT_PROJECT has been removed. Instead, the eclass determines"
327 + eerror "the local clone path using path in canonical EGIT_REPO_URI."
328 + eerror "If the current algorithm causes issues for you, please report a bug."
329 + die "EGIT_PROJECT is no longer necessary."
330 + fi
331 +
332 + if [[ ${EGIT_BOOTSTRAP} ]]; then
333 + eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()"
334 + eerror "instead."
335 + die "EGIT_BOOTSTRAP has been removed."
336 + fi
337 +
338 + if [[ ${EGIT_NOUNPACK} ]]; then
339 + eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default"
340 + eerror "unpack function. If necessary, please declare proper src_unpack()."
341 + die "EGIT_NOUNPACK has been removed."
342 + fi
343 +}
344 +
345 +# @FUNCTION: _git-r3_set_gitdir
346 +# @USAGE: <repo-uri>
347 +# @INTERNAL
348 +# @DESCRIPTION:
349 +# Obtain the local repository path and set it as GIT_DIR. Creates
350 +# a new repository if necessary.
351 +#
352 +# <repo-uri> may be used to compose the path. It should therefore be
353 +# a canonical URI to the repository.
354 +_git-r3_set_gitdir() {
355 + debug-print-function ${FUNCNAME} "$@"
356 +
357 + local repo_name=${1#*://*/}
358 +
359 + # strip the trailing slash
360 + repo_name=${repo_name%/}
361 +
362 + # strip common prefixes to make paths more likely to match
363 + # e.g. git://X/Y.git vs https://X/git/Y.git
364 + # (but just one of the prefixes)
365 + case "${repo_name}" in
366 + # gnome.org... who else?
367 + browse/*) repo_name=${repo_name#browse/};;
368 + # cgit can proxy requests to git
369 + cgit/*) repo_name=${repo_name#cgit/};;
370 + # pretty common
371 + git/*) repo_name=${repo_name#git/};;
372 + # gentoo.org
373 + gitroot/*) repo_name=${repo_name#gitroot/};;
374 + # sourceforge
375 + p/*) repo_name=${repo_name#p/};;
376 + # kernel.org
377 + pub/scm/*) repo_name=${repo_name#pub/scm/};;
378 + esac
379 + # ensure a .git suffix, same reason
380 + repo_name=${repo_name%.git}.git
381 + # now replace all the slashes
382 + repo_name=${repo_name//\//_}
383 +
384 + local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
385 + : ${EGIT3_STORE_DIR:=${distdir}/git3-src}
386 +
387 + GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
388 +
389 + if [[ ! -d ${EGIT3_STORE_DIR} && ! ${EVCS_OFFLINE} ]]; then
390 + (
391 + addwrite /
392 + mkdir -p "${EGIT3_STORE_DIR}"
393 + ) || die "Unable to create ${EGIT3_STORE_DIR}"
394 + fi
395 +
396 + addwrite "${EGIT3_STORE_DIR}"
397 + if [[ ! -d ${GIT_DIR} ]]; then
398 + if [[ ${EVCS_OFFLINE} ]]; then
399 + eerror "A clone of the following repository is required to proceed:"
400 + eerror " ${1}"
401 + eerror "However, networking activity has been disabled using EVCS_OFFLINE and there"
402 + eerror "is no local clone available."
403 + die "No local clone of ${1}. Unable to proceed with EVCS_OFFLINE."
404 + fi
405 +
406 + local saved_umask
407 + if [[ ${EVCS_UMASK} ]]; then
408 + saved_umask=$(umask)
409 + umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
410 + fi
411 + mkdir "${GIT_DIR}" || die
412 + git init --bare || die
413 + if [[ ${saved_umask} ]]; then
414 + umask "${saved_umask}" || die
415 + fi
416 + fi
417 +}
418 +
419 +# @FUNCTION: _git-r3_set_submodules
420 +# @USAGE: <file-contents>
421 +# @INTERNAL
422 +# @DESCRIPTION:
423 +# Parse .gitmodules contents passed as <file-contents>
424 +# as in "$(cat .gitmodules)"). Composes a 'submodules' array that
425 +# contains in order (name, URL, path) for each submodule.
426 +_git-r3_set_submodules() {
427 + debug-print-function ${FUNCNAME} "$@"
428 +
429 + local data=${1}
430 +
431 + # ( name url path ... )
432 + submodules=()
433 +
434 + local l
435 + while read l; do
436 + # submodule.<path>.path=<path>
437 + # submodule.<path>.url=<url>
438 + [[ ${l} == submodule.*.url=* ]] || continue
439 +
440 + l=${l#submodule.}
441 + local subname=${l%%.url=*}
442 +
443 + # filter out on EGIT_SUBMODULES
444 + if declare -p EGIT_SUBMODULES &>/dev/null; then
445 + local p l_res res=
446 + for p in "${EGIT_SUBMODULES[@]}"; do
447 + if [[ ${p} == -* ]]; then
448 + p=${p#-}
449 + l_res=
450 + else
451 + l_res=1
452 + fi
453 +
454 + [[ ${subname} == ${p} ]] && res=${l_res}
455 + done
456 +
457 + if [[ ! ${res} ]]; then
458 + einfo "Skipping submodule \e[1m${subname}\e[22m"
459 + continue
460 + fi
461 + fi
462 +
463 + # skip modules that have 'update = none', bug #487262.
464 + local upd=$(echo "${data}" | git config -f /dev/fd/0 \
465 + submodule."${subname}".update)
466 + [[ ${upd} == none ]] && continue
467 +
468 + # https://github.com/git/git/blob/master/refs.c#L39
469 + # for now, we just filter /. because of #572312
470 + local enc_subname=${subname//\/.//_}
471 + [[ ${enc_subname} == .* ]] && enc_subname=_${enc_subname#.}
472 +
473 + submodules+=(
474 + "${enc_subname}"
475 + "$(echo "${data}" | git config -f /dev/fd/0 \
476 + submodule."${subname}".url || die)"
477 + "$(echo "${data}" | git config -f /dev/fd/0 \
478 + submodule."${subname}".path || die)"
479 + )
480 + done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
481 +}
482 +
483 +# @FUNCTION: _git-r3_set_subrepos
484 +# @USAGE: <submodule-uri> <parent-repo-uri>...
485 +# @INTERNAL
486 +# @DESCRIPTION:
487 +# Create 'subrepos' array containing absolute (canonical) submodule URIs
488 +# for the given <submodule-uri>. If the URI is relative, URIs will be
489 +# constructed using all <parent-repo-uri>s. Otherwise, this single URI
490 +# will be placed in the array.
491 +_git-r3_set_subrepos() {
492 + debug-print-function ${FUNCNAME} "$@"
493 +
494 + local suburl=${1}
495 + subrepos=( "${@:2}" )
496 +
497 + if [[ ${suburl} == ./* || ${suburl} == ../* ]]; then
498 + # drop all possible trailing slashes for consistency
499 + subrepos=( "${subrepos[@]%%/}" )
500 +
501 + while true; do
502 + if [[ ${suburl} == ./* ]]; then
503 + suburl=${suburl:2}
504 + elif [[ ${suburl} == ../* ]]; then
505 + suburl=${suburl:3}
506 +
507 + # XXX: correctness checking
508 +
509 + # drop the last path component
510 + subrepos=( "${subrepos[@]%/*}" )
511 + # and then the trailing slashes, again
512 + subrepos=( "${subrepos[@]%%/}" )
513 + else
514 + break
515 + fi
516 + done
517 +
518 + # append the preprocessed path to the preprocessed URIs
519 + subrepos=( "${subrepos[@]/%//${suburl}}")
520 + else
521 + subrepos=( "${suburl}" )
522 + fi
523 +}
524 +
525 +
526 +# @FUNCTION: _git-r3_is_local_repo
527 +# @USAGE: <repo-uri>
528 +# @INTERNAL
529 +# @DESCRIPTION:
530 +# Determine whether the given URI specifies a local (on-disk)
531 +# repository.
532 +_git-r3_is_local_repo() {
533 + debug-print-function ${FUNCNAME} "$@"
534 +
535 + local uri=${1}
536 +
537 + [[ ${uri} == file://* || ${uri} == /* ]]
538 +}
539 +
540 +# @FUNCTION: git-r3_fetch
541 +# @USAGE: [<repo-uri> [<remote-ref> [<local-id> [<commit-date>]]]]
542 +# @DESCRIPTION:
543 +# Fetch new commits to the local clone of repository.
544 +#
545 +# <repo-uri> specifies the repository URIs to fetch from, as a space-
546 +# -separated list. The first URI will be used as repository group
547 +# identifier and therefore must be used consistently. When not
548 +# specified, defaults to ${EGIT_REPO_URI}.
549 +#
550 +# <remote-ref> specifies the remote ref or commit id to fetch.
551 +# It is preferred to use 'refs/heads/<branch-name>' for branches
552 +# and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
553 +# for upstream default branch and hexadecimal commit SHA1. Defaults
554 +# to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
555 +# is set to a non-null value.
556 +#
557 +# <local-id> specifies the local branch identifier that will be used to
558 +# locally store the fetch result. It should be unique to multiple
559 +# fetches within the repository that can be performed at the same time
560 +# (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
561 +# This default should be fine unless you are fetching multiple trees
562 +# from the same repository in the same ebuild.
563 +#
564 +# <commit-id> requests attempting to use repository state as of specific
565 +# date. For more details, see EGIT_COMMIT_DATE.
566 +#
567 +# The fetch operation will affect the EGIT_STORE only. It will not touch
568 +# the working copy, nor export any environment variables.
569 +# If the repository contains submodules, they will be fetched
570 +# recursively.
571 +git-r3_fetch() {
572 + debug-print-function ${FUNCNAME} "$@"
573 +
574 + local repos
575 + if [[ ${1} ]]; then
576 + repos=( ${1} )
577 + elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
578 + repos=( "${EGIT_REPO_URI[@]}" )
579 + else
580 + repos=( ${EGIT_REPO_URI} )
581 + fi
582 +
583 + local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
584 + local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
585 + local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
586 + local local_ref=refs/git-r3/${local_id}/__main__
587 + local commit_date=${4:-${EGIT_COMMIT_DATE}}
588 +
589 + [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
590 +
591 + local -x GIT_DIR
592 + _git-r3_set_gitdir "${repos[0]}"
593 +
594 + # prepend the local mirror if applicable
595 + if [[ ${EGIT_MIRROR_URI} ]]; then
596 + repos=(
597 + "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
598 + "${repos[@]}"
599 + )
600 + fi
601 +
602 + # try to fetch from the remote
603 + local r success saved_umask
604 + if [[ ${EVCS_UMASK} ]]; then
605 + saved_umask=$(umask)
606 + umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
607 + fi
608 + for r in "${repos[@]}"; do
609 + if [[ ! ${EVCS_OFFLINE} ]]; then
610 + einfo "Fetching \e[1m${r}\e[22m ..."
611 +
612 + local fetch_command=( git fetch "${r}" )
613 + local clone_type=${EGIT_CLONE_TYPE}
614 +
615 + if [[ ${r} == http://* || ${r} == https://* ]] &&
616 + [[ ! ${EGIT_CURL_WARNED} ]] &&
617 + ! ROOT=/ has_version 'dev-vcs/git[curl]'
618 + then
619 + ewarn "git-r3: fetching from HTTP(S) requested. In order to support HTTP(S),"
620 + ewarn "dev-vcs/git needs to be built with USE=curl. Example solution:"
621 + ewarn
622 + ewarn " echo dev-vcs/git curl >> /etc/portage/package.use"
623 + ewarn " emerge -1v dev-vcs/git"
624 + ewarn
625 + ewarn "HTTP(S) URIs will be skipped."
626 + EGIT_CURL_WARNED=1
627 + fi
628 +
629 + if [[ ${clone_type} == mirror ]]; then
630 + fetch_command+=(
631 + --prune
632 + # mirror the remote branches as local branches
633 + "+refs/heads/*:refs/heads/*"
634 + # pull tags explicitly in order to prune them properly
635 + "+refs/tags/*:refs/tags/*"
636 + # notes in case something needs them
637 + "+refs/notes/*:refs/notes/*"
638 + # and HEAD in case we need the default branch
639 + # (we keep it in refs/git-r3 since otherwise --prune interferes)
640 + "+HEAD:refs/git-r3/HEAD"
641 + )
642 + else # single or shallow
643 + local fetch_l fetch_r
644 +
645 + if [[ ${remote_ref} == HEAD ]]; then
646 + # HEAD
647 + fetch_l=HEAD
648 + elif [[ ${remote_ref} == refs/* ]]; then
649 + # regular branch, tag or some other explicit ref
650 + fetch_l=${remote_ref}
651 + else
652 + # tag or commit id...
653 + # let ls-remote figure it out
654 + local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
655 +
656 + # if it was a tag, ls-remote obtained a hash
657 + if [[ ${tagref} ]]; then
658 + # tag
659 + fetch_l=refs/tags/${remote_ref}
660 + else
661 + # commit id
662 + # so we need to fetch the whole branch
663 + if [[ ${branch} ]]; then
664 + fetch_l=${branch}
665 + else
666 + fetch_l=HEAD
667 + fi
668 +
669 + # fetching by commit in shallow mode? can't do.
670 + if [[ ${clone_type} == shallow ]]; then
671 + clone_type=single
672 + fi
673 + fi
674 + fi
675 +
676 + # checkout by date does not make sense in shallow mode
677 + if [[ ${commit_date} && ${clone_type} == shallow ]]; then
678 + clone_type=single
679 + fi
680 +
681 + if [[ ${fetch_l} == HEAD ]]; then
682 + fetch_r=refs/git-r3/HEAD
683 + else
684 + fetch_r=${fetch_l}
685 + fi
686 +
687 + fetch_command+=(
688 + "+${fetch_l}:${fetch_r}"
689 + )
690 +
691 + if [[ ${clone_type} == single+tags ]]; then
692 + fetch_command+=(
693 + # pull tags explicitly as requested
694 + "+refs/tags/*:refs/tags/*"
695 + )
696 + fi
697 + fi
698 +
699 + if [[ ${clone_type} == shallow ]]; then
700 + if _git-r3_is_local_repo; then
701 + # '--depth 1' causes sandbox violations with local repos
702 + # bug #491260
703 + clone_type=single
704 + elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
705 + then
706 + # use '--depth 1' when fetching a new branch
707 + fetch_command+=( --depth 1 )
708 + fi
709 + else # non-shallow mode
710 + if [[ -f ${GIT_DIR}/shallow ]]; then
711 + fetch_command+=( --unshallow )
712 + fi
713 + fi
714 +
715 + set -- "${fetch_command[@]}"
716 + echo "${@}" >&2
717 + "${@}" || continue
718 +
719 + if [[ ${clone_type} == mirror || ${fetch_l} == HEAD ]]; then
720 + # update our HEAD to match our remote HEAD ref
721 + git symbolic-ref HEAD refs/git-r3/HEAD \
722 + || die "Unable to update HEAD"
723 + fi
724 + fi
725 +
726 + # now let's see what the user wants from us
727 + if [[ ${commit_date} ]]; then
728 + local dated_commit_id=$(
729 + git rev-list --first-parent --before="${commit_date}" \
730 + -n 1 "${remote_ref}"
731 + )
732 + if [[ ${?} -ne 0 ]]; then
733 + die "Listing ${remote_ref} failed (wrong ref?)."
734 + elif [[ ! ${dated_commit_id} ]]; then
735 + die "Unable to find commit for date ${commit_date}."
736 + else
737 + set -- git update-ref --no-deref "${local_ref}" "${dated_commit_id}"
738 + fi
739 + else
740 + local full_remote_ref=$(
741 + git rev-parse --verify --symbolic-full-name "${remote_ref}"
742 + )
743 +
744 + if [[ ${full_remote_ref} ]]; then
745 + # when we are given a ref, create a symbolic ref
746 + # so that we preserve the actual argument
747 + set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
748 + else
749 + # otherwise, we were likely given a commit id
750 + set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
751 + fi
752 + fi
753 +
754 + echo "${@}" >&2
755 + if ! "${@}"; then
756 + if [[ ${EVCS_OFFLINE} ]]; then
757 + eerror "A clone of the following repository is required to proceed:"
758 + eerror " ${r}"
759 + eerror "However, networking activity has been disabled using EVCS_OFFLINE and the local"
760 + eerror "clone does not have requested ref:"
761 + eerror " ${remote_ref}"
762 + die "Local clone of ${r} does not have requested ref: ${remote_ref}. Unable to proceed with EVCS_OFFLINE."
763 + else
764 + die "Referencing ${remote_ref} failed (wrong ref?)."
765 + fi
766 + fi
767 +
768 + success=1
769 + break
770 + done
771 + if [[ ${saved_umask} ]]; then
772 + umask "${saved_umask}" || die
773 + fi
774 + [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
775 +
776 + # submodules can reference commits in any branch
777 + # always use the 'mirror' mode to accomodate that, bug #503332
778 + local EGIT_CLONE_TYPE=mirror
779 +
780 + # recursively fetch submodules
781 + if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
782 + local submodules
783 + _git-r3_set_submodules \
784 + "$(git cat-file -p "${local_ref}":.gitmodules || die)"
785 +
786 + while [[ ${submodules[@]} ]]; do
787 + local subname=${submodules[0]}
788 + local url=${submodules[1]}
789 + local path=${submodules[2]}
790 +
791 + # use only submodules for which path does exist
792 + # (this is in par with 'git submodule'), bug #551100
793 + # note: git cat-file does not work for submodules
794 + if [[ $(git ls-tree -d "${local_ref}" "${path}") ]]
795 + then
796 + local commit=$(git rev-parse "${local_ref}:${path}" || die)
797 +
798 + if [[ ! ${commit} ]]; then
799 + die "Unable to get commit id for submodule ${subname}"
800 + fi
801 +
802 + local subrepos
803 + _git-r3_set_subrepos "${url}" "${repos[@]}"
804 +
805 + git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
806 + fi
807 +
808 + submodules=( "${submodules[@]:3}" ) # shift
809 + done
810 + fi
811 +}
812 +
813 +# @FUNCTION: git-r3_checkout
814 +# @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
815 +# @DESCRIPTION:
816 +# Check the previously fetched tree to the working copy.
817 +#
818 +# <repo-uri> specifies the repository URIs, as a space-separated list.
819 +# The first URI will be used as repository group identifier
820 +# and therefore must be used consistently with git-r3_fetch.
821 +# The remaining URIs are not used and therefore may be omitted.
822 +# When not specified, defaults to ${EGIT_REPO_URI}.
823 +#
824 +# <checkout-path> specifies the path to place the checkout. It defaults
825 +# to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
826 +#
827 +# <local-id> needs to specify the local identifier that was used
828 +# for respective git-r3_fetch.
829 +#
830 +# The checkout operation will write to the working copy, and export
831 +# the repository state into the environment. If the repository contains
832 +# submodules, they will be checked out recursively.
833 +git-r3_checkout() {
834 + debug-print-function ${FUNCNAME} "$@"
835 +
836 + local repos
837 + if [[ ${1} ]]; then
838 + repos=( ${1} )
839 + elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
840 + repos=( "${EGIT_REPO_URI[@]}" )
841 + else
842 + repos=( ${EGIT_REPO_URI} )
843 + fi
844 +
845 + local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
846 + local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
847 +
848 + local -x GIT_DIR
849 + _git-r3_set_gitdir "${repos[0]}"
850 +
851 + einfo "Checking out \e[1m${repos[0]}\e[22m to \e[1m${out_dir}\e[22m ..."
852 +
853 + if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
854 + die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
855 + fi
856 + local remote_ref=$(
857 + git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
858 + )
859 + local new_commit_id=$(
860 + git rev-parse --verify refs/git-r3/"${local_id}"/__main__
861 + )
862 +
863 + git-r3_sub_checkout() {
864 + local orig_repo=${GIT_DIR}
865 + local -x GIT_DIR=${out_dir}/.git
866 + local -x GIT_WORK_TREE=${out_dir}
867 +
868 + mkdir -p "${out_dir}" || die
869 +
870 + # use git init+fetch instead of clone since the latter doesn't like
871 + # non-empty directories.
872 +
873 + git init --quiet || die
874 + # setup 'alternates' to avoid copying objects
875 + echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
876 + # now copy the refs
877 + cp -R "${orig_repo}"/refs/* "${GIT_DIR}"/refs/ || die
878 +
879 + # (no need to copy HEAD, we will set it via checkout)
880 +
881 + if [[ -f ${orig_repo}/shallow ]]; then
882 + cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
883 + fi
884 +
885 + set -- git checkout --quiet
886 + if [[ ${remote_ref} ]]; then
887 + set -- "${@}" "${remote_ref#refs/heads/}"
888 + else
889 + set -- "${@}" "${new_commit_id}"
890 + fi
891 + echo "${@}" >&2
892 + "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
893 + }
894 + git-r3_sub_checkout
895 + unset -f git-r3_sub_checkout
896 +
897 + local old_commit_id=$(
898 + git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
899 + )
900 + if [[ ! ${old_commit_id} ]]; then
901 + echo "GIT NEW branch -->"
902 + echo " repository: ${repos[0]}"
903 + echo " at the commit: ${new_commit_id}"
904 + else
905 + # diff against previous revision
906 + echo "GIT update -->"
907 + echo " repository: ${repos[0]}"
908 + # write out message based on the revisions
909 + if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
910 + echo " updating from commit: ${old_commit_id}"
911 + echo " to commit: ${new_commit_id}"
912 +
913 + git --no-pager diff --stat \
914 + ${old_commit_id}..${new_commit_id}
915 + else
916 + echo " at the commit: ${new_commit_id}"
917 + fi
918 + fi
919 + git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
920 +
921 + # recursively checkout submodules
922 + if [[ -f ${out_dir}/.gitmodules ]]; then
923 + local submodules
924 + _git-r3_set_submodules \
925 + "$(<"${out_dir}"/.gitmodules)"
926 +
927 + while [[ ${submodules[@]} ]]; do
928 + local subname=${submodules[0]}
929 + local url=${submodules[1]}
930 + local path=${submodules[2]}
931 +
932 + # use only submodules for which path does exist
933 + # (this is in par with 'git submodule'), bug #551100
934 + if [[ -d ${out_dir}/${path} ]]; then
935 + local subrepos
936 + _git-r3_set_subrepos "${url}" "${repos[@]}"
937 +
938 + git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \
939 + "${local_id}/${subname}"
940 + fi
941 +
942 + submodules=( "${submodules[@]:3}" ) # shift
943 + done
944 + fi
945 +
946 + # keep this *after* submodules
947 + export EGIT_DIR=${GIT_DIR}
948 + export EGIT_VERSION=${new_commit_id}
949 +}
950 +
951 +# @FUNCTION: git-r3_peek_remote_ref
952 +# @USAGE: [<repo-uri> [<remote-ref>]]
953 +# @DESCRIPTION:
954 +# Peek the reference in the remote repository and print the matching
955 +# (newest) commit SHA1.
956 +#
957 +# <repo-uri> specifies the repository URIs to fetch from, as a space-
958 +# -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
959 +#
960 +# <remote-ref> specifies the remote ref to peek. It is preferred to use
961 +# 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
962 +# for tags. Alternatively, 'HEAD' may be used for upstream default
963 +# branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
964 +# 'HEAD' that is set to a non-null value.
965 +#
966 +# The operation will be done purely on the remote, without using local
967 +# storage. If commit SHA1 is provided as <remote-ref>, the function will
968 +# fail due to limitations of git protocol.
969 +#
970 +# On success, the function returns 0 and writes hexadecimal commit SHA1
971 +# to stdout. On failure, the function returns 1.
972 +git-r3_peek_remote_ref() {
973 + debug-print-function ${FUNCNAME} "$@"
974 +
975 + local repos
976 + if [[ ${1} ]]; then
977 + repos=( ${1} )
978 + elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
979 + repos=( "${EGIT_REPO_URI[@]}" )
980 + else
981 + repos=( ${EGIT_REPO_URI} )
982 + fi
983 +
984 + local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
985 + local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
986 +
987 + [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
988 +
989 + local r success
990 + for r in "${repos[@]}"; do
991 + einfo "Peeking \e[1m${remote_ref}\e[22m on \e[1m${r}\e[22m ..." >&2
992 +
993 + local lookup_ref
994 + if [[ ${remote_ref} == refs/* || ${remote_ref} == HEAD ]]
995 + then
996 + lookup_ref=${remote_ref}
997 + else
998 + # ls-remote by commit is going to fail anyway,
999 + # so we may as well pass refs/tags/ABCDEF...
1000 + lookup_ref=refs/tags/${remote_ref}
1001 + fi
1002 +
1003 + # split on whitespace
1004 + local ref=(
1005 + $(git ls-remote "${r}" "${lookup_ref}")
1006 + )
1007 +
1008 + if [[ ${ref[0]} ]]; then
1009 + echo "${ref[0]}"
1010 + return 0
1011 + fi
1012 + done
1013 +
1014 + return 1
1015 +}
1016 +
1017 +git-r3_src_fetch() {
1018 + debug-print-function ${FUNCNAME} "$@"
1019 +
1020 + if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
1021 + ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
1022 + ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
1023 + ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
1024 + ewarn "when git-2 eclass becomes deprecated."
1025 + fi
1026 +
1027 + _git-r3_env_setup
1028 + git-r3_fetch
1029 +}
1030 +
1031 +git-r3_src_unpack() {
1032 + debug-print-function ${FUNCNAME} "$@"
1033 +
1034 + _git-r3_env_setup
1035 + git-r3_src_fetch
1036 + git-r3_checkout
1037 +}
1038 +
1039 +# https://bugs.gentoo.org/show_bug.cgi?id=482666
1040 +git-r3_pkg_needrebuild() {
1041 + debug-print-function ${FUNCNAME} "$@"
1042 +
1043 + local new_commit_id=$(git-r3_peek_remote_ref)
1044 + [[ ${new_commit_id} && ${EGIT_VERSION} ]] || die "Lookup failed"
1045 +
1046 + if [[ ${EGIT_VERSION} != ${new_commit_id} ]]; then
1047 + einfo "Update from \e[1m${EGIT_VERSION}\e[22m to \e[1m${new_commit_id}\e[22m"
1048 + else
1049 + einfo "Local and remote at \e[1m${EGIT_VERSION}\e[22m"
1050 + fi
1051 +
1052 + [[ ${EGIT_VERSION} != ${new_commit_id} ]]
1053 +}
1054 +
1055 +# 'export' locally until this gets into EAPI
1056 +pkg_needrebuild() { git-r3_pkg_needrebuild; }
1057 +
1058 +_GIT_R3=1
1059 +fi