/[gentoo-x86]/eclass/git-r3.eclass
Gentoo

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.38 - (show annotations) (download)
Sun Mar 2 11:50:48 2014 UTC (6 months, 2 weeks ago) by mgorny
Branch: MAIN
Changes since 1.37: +7 -1 lines
Clarify where EGIT_CLONE_TYPE and EGIT_MIN_CLONE_TYPE is supposed to be set.

1 # Copyright 1999-2014 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.37 2014/03/02 11:50:23 mgorny Exp $
4
5 # @ECLASS: git-r3.eclass
6 # @MAINTAINER:
7 # Michał Górny <mgorny@gentoo.org>
8 # @BLURB: Eclass for fetching and unpacking git repositories.
9 # @DESCRIPTION:
10 # Third generation eclass for easing maitenance of live ebuilds using
11 # git as remote repository.
12
13 case "${EAPI:-0}" in
14 0|1|2|3|4|5)
15 ;;
16 *)
17 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
18 ;;
19 esac
20
21 if [[ ! ${_GIT_R3} ]]; then
22
23 inherit eutils
24
25 fi
26
27 EXPORT_FUNCTIONS src_unpack
28
29 if [[ ! ${_GIT_R3} ]]; then
30
31 if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
32 DEPEND=">=dev-vcs/git-1.8.2.1"
33 fi
34
35 # @ECLASS-VARIABLE: EGIT_CLONE_TYPE
36 # @DESCRIPTION:
37 # Type of clone that should be used against the remote repository.
38 # This can be either of: 'mirror', 'single', 'shallow'.
39 #
40 # This is intended to be set by user in make.conf. Ebuilds are supposed
41 # to set EGIT_MIN_CLONE_TYPE if necessary instead.
42 #
43 # The 'mirror' type clones all remote branches and tags with complete
44 # history and all notes. EGIT_COMMIT can specify any commit hash.
45 # Upstream-removed branches and tags are purged from the local clone
46 # while fetching. This mode is suitable for cloning the local copy
47 # for development or hosting a local git mirror. However, clones
48 # of repositories with large diverged branches may quickly grow large.
49 #
50 # The 'single' type clones only the requested branch or tag. Tags
51 # referencing commits throughout the branch history are fetched as well,
52 # and all notes. EGIT_COMMIT can safely specify only hashes
53 # in the current branch. No purging of old references is done (if you
54 # often switch branches, you may need to remove stale branches
55 # yourself). This mode is suitable for general use.
56 #
57 # The 'shallow' type clones only the newest commit on requested branch
58 # or tag. EGIT_COMMIT can only specify tags, and since the history is
59 # unavailable calls like 'git describe' will not reference prior tags.
60 # No purging of old references is done. This mode is intended mostly for
61 # embedded systems with limited disk space.
62 : ${EGIT_CLONE_TYPE:=single}
63
64 # @ECLASS-VARIABLE: EGIT_MIN_CLONE_TYPE
65 # @DESCRIPTION:
66 # 'Minimum' clone type supported by the ebuild. Takes same values
67 # as EGIT_CLONE_TYPE. When user sets a type that's 'lower' (that is,
68 # later on the list) than EGIT_MIN_CLONE_TYPE, the eclass uses
69 # EGIT_MIN_CLONE_TYPE instead.
70 #
71 # This variable is intended to be used by ebuilds only. Users are
72 # supposed to set EGIT_CLONE_TYPE instead.
73 #
74 # A common case is to use 'single' whenever the build system requires
75 # access to full branch history or the remote (Google Code) does not
76 # support shallow clones. Please use sparingly, and to fix fatal errors
77 # rather than 'non-pretty versions'.
78 : ${EGIT_MIN_CLONE_TYPE:=shallow}
79
80 # @ECLASS-VARIABLE: EGIT3_STORE_DIR
81 # @DESCRIPTION:
82 # Storage directory for git sources.
83 #
84 # This is intended to be set by user in make.conf. Ebuilds must not set
85 # it.
86 #
87 # EGIT3_STORE_DIR=${DISTDIR}/git3-src
88
89 # @ECLASS-VARIABLE: EGIT_MIRROR_URI
90 # @DEFAULT_UNSET
91 # @DESCRIPTION:
92 # 'Top' URI to a local git mirror. If specified, the eclass will try
93 # to fetch from the local mirror instead of using the remote repository.
94 #
95 # The mirror needs to follow EGIT3_STORE_DIR structure. The directory
96 # created by eclass can be used for that purpose.
97 #
98 # Example:
99 # @CODE
100 # EGIT_MIRROR_URI="git://mirror.lan/"
101 # @CODE
102
103 # @ECLASS-VARIABLE: EGIT_REPO_URI
104 # @REQUIRED
105 # @DESCRIPTION:
106 # URIs to the repository, e.g. git://foo, https://foo. If multiple URIs
107 # are provided, the eclass will consider them as fallback URIs to try
108 # if the first URI does not work.
109 #
110 # It can be overriden via env using ${PN}_LIVE_REPO variable.
111 #
112 # Can be a whitespace-separated list or an array.
113 #
114 # Example:
115 # @CODE
116 # EGIT_REPO_URI="git://a/b.git https://c/d.git"
117 # @CODE
118
119 # @ECLASS-VARIABLE: EVCS_OFFLINE
120 # @DEFAULT_UNSET
121 # @DESCRIPTION:
122 # If non-empty, this variable prevents any online operations.
123
124 # @ECLASS-VARIABLE: EGIT_BRANCH
125 # @DEFAULT_UNSET
126 # @DESCRIPTION:
127 # The branch name to check out. If unset, the upstream default (HEAD)
128 # will be used.
129 #
130 # It can be overriden via env using ${PN}_LIVE_BRANCH variable.
131
132 # @ECLASS-VARIABLE: EGIT_COMMIT
133 # @DEFAULT_UNSET
134 # @DESCRIPTION:
135 # The tag name or commit identifier to check out. If unset, newest
136 # commit from the branch will be used. If set, EGIT_BRANCH will
137 # be ignored.
138 #
139 # It can be overriden via env using ${PN}_LIVE_COMMIT variable.
140
141 # @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
142 # @DESCRIPTION:
143 # The directory to check the git sources out to.
144 #
145 # EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
146
147 # @FUNCTION: _git-r3_env_setup
148 # @INTERNAL
149 # @DESCRIPTION:
150 # Set the eclass variables as necessary for operation. This can involve
151 # setting EGIT_* to defaults or ${PN}_LIVE_* variables.
152 _git-r3_env_setup() {
153 debug-print-function ${FUNCNAME} "$@"
154
155 # check the clone type
156 case "${EGIT_CLONE_TYPE}" in
157 mirror|single|shallow)
158 ;;
159 *)
160 die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
161 esac
162 case "${EGIT_MIN_CLONE_TYPE}" in
163 shallow)
164 ;;
165 single)
166 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
167 einfo "git-r3: ebuild needs to be cloned in 'single' mode, adjusting"
168 EGIT_CLONE_TYPE=single
169 fi
170 ;;
171 mirror)
172 if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then
173 einfo "git-r3: ebuild needs to be cloned in 'mirror' mode, adjusting"
174 EGIT_CLONE_TYPE=mirror
175 fi
176 ;;
177 *)
178 die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
179 esac
180
181 local esc_pn livevar
182 esc_pn=${PN//[-+]/_}
183
184 livevar=${esc_pn}_LIVE_REPO
185 EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}}
186 [[ ${!livevar} ]] \
187 && ewarn "Using ${livevar}, no support will be provided"
188
189 livevar=${esc_pn}_LIVE_BRANCH
190 EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}}
191 [[ ${!livevar} ]] \
192 && ewarn "Using ${livevar}, no support will be provided"
193
194 livevar=${esc_pn}_LIVE_COMMIT
195 EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}}
196 [[ ${!livevar} ]] \
197 && ewarn "Using ${livevar}, no support will be provided"
198
199 # Migration helpers. Remove them when git-2 is removed.
200
201 if [[ ${EGIT_SOURCEDIR} ]]; then
202 eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating"
203 eerror "your ebuild, please check whether the variable is necessary at all"
204 eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}."
205 eerror "Therefore, proper setting of S may be sufficient."
206 die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR."
207 fi
208
209 if [[ ${EGIT_MASTER} ]]; then
210 eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)"
211 eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH"
212 eerror "as necessary."
213 die "EGIT_MASTER has been removed."
214 fi
215
216 if [[ ${EGIT_HAS_SUBMODULES} ]]; then
217 eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs"
218 eerror "to switch the clone type in order to support submodules and therefore"
219 eerror "submodules are detected and fetched automatically."
220 die "EGIT_HAS_SUBMODULES is no longer necessary."
221 fi
222
223 if [[ ${EGIT_PROJECT} ]]; then
224 eerror "EGIT_PROJECT has been removed. Instead, the eclass determines"
225 eerror "the local clone path using path in canonical EGIT_REPO_URI."
226 eerror "If the current algorithm causes issues for you, please report a bug."
227 die "EGIT_PROJECT is no longer necessary."
228 fi
229
230 if [[ ${EGIT_BOOTSTRAP} ]]; then
231 eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()"
232 eerror "instead."
233 die "EGIT_BOOTSTRAP has been removed."
234 fi
235
236 if [[ ${EGIT_NOUNPACK} ]]; then
237 eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default"
238 eerror "unpack function. If necessary, please declare proper src_unpack()."
239 die "EGIT_NOUNPACK has been removed."
240 fi
241 }
242
243 # @FUNCTION: _git-r3_set_gitdir
244 # @USAGE: <repo-uri>
245 # @INTERNAL
246 # @DESCRIPTION:
247 # Obtain the local repository path and set it as GIT_DIR. Creates
248 # a new repository if necessary.
249 #
250 # <repo-uri> may be used to compose the path. It should therefore be
251 # a canonical URI to the repository.
252 _git-r3_set_gitdir() {
253 debug-print-function ${FUNCNAME} "$@"
254
255 local repo_name=${1#*://*/}
256
257 # strip the trailing slash
258 repo_name=${repo_name%/}
259
260 # strip common prefixes to make paths more likely to match
261 # e.g. git://X/Y.git vs https://X/git/Y.git
262 # (but just one of the prefixes)
263 case "${repo_name}" in
264 # gnome.org... who else?
265 browse/*) repo_name=${repo_name#browse/};;
266 # cgit can proxy requests to git
267 cgit/*) repo_name=${repo_name#cgit/};;
268 # pretty common
269 git/*) repo_name=${repo_name#git/};;
270 # gentoo.org
271 gitroot/*) repo_name=${repo_name#gitroot/};;
272 # google code, sourceforge
273 p/*) repo_name=${repo_name#p/};;
274 # kernel.org
275 pub/scm/*) repo_name=${repo_name#pub/scm/};;
276 esac
277 # ensure a .git suffix, same reason
278 repo_name=${repo_name%.git}.git
279 # now replace all the slashes
280 repo_name=${repo_name//\//_}
281
282 local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
283 : ${EGIT3_STORE_DIR:=${distdir}/git3-src}
284
285 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
286
287 if [[ ! -d ${EGIT3_STORE_DIR} ]]; then
288 (
289 addwrite /
290 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die
291 ) || die "Unable to create ${EGIT3_STORE_DIR}"
292 fi
293
294 addwrite "${EGIT3_STORE_DIR}"
295 if [[ ! -d ${GIT_DIR} ]]; then
296 mkdir "${GIT_DIR}" || die
297 git init --bare || die
298 fi
299 }
300
301 # @FUNCTION: _git-r3_set_submodules
302 # @USAGE: <file-contents>
303 # @INTERNAL
304 # @DESCRIPTION:
305 # Parse .gitmodules contents passed as <file-contents>
306 # as in "$(cat .gitmodules)"). Composes a 'submodules' array that
307 # contains in order (name, URL, path) for each submodule.
308 _git-r3_set_submodules() {
309 debug-print-function ${FUNCNAME} "$@"
310
311 local data=${1}
312
313 # ( name url path ... )
314 submodules=()
315
316 local l
317 while read l; do
318 # submodule.<path>.path=<path>
319 # submodule.<path>.url=<url>
320 [[ ${l} == submodule.*.url=* ]] || continue
321
322 l=${l#submodule.}
323 local subname=${l%%.url=*}
324
325 # skip modules that have 'update = none', bug #487262.
326 local upd=$(echo "${data}" | git config -f /dev/fd/0 \
327 submodule."${subname}".update)
328 [[ ${upd} == none ]] && continue
329
330 submodules+=(
331 "${subname}"
332 "$(echo "${data}" | git config -f /dev/fd/0 \
333 submodule."${subname}".url || die)"
334 "$(echo "${data}" | git config -f /dev/fd/0 \
335 submodule."${subname}".path || die)"
336 )
337 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
338 }
339
340 # @FUNCTION: _git-r3_is_local_repo
341 # @USAGE: <repo-uri>
342 # @INTERNAL
343 # @DESCRIPTION:
344 # Determine whether the given URI specifies a local (on-disk)
345 # repository.
346 _git-r3_is_local_repo() {
347 debug-print-function ${FUNCNAME} "$@"
348
349 local uri=${1}
350
351 [[ ${uri} == file://* || ${uri} == /* ]]
352 }
353
354 # @FUNCTION: _git-r3_find_head
355 # @USAGE: <head-ref>
356 # @INTERNAL
357 # @DESCRIPTION:
358 # Given a ref to which remote HEAD was fetched, try to find
359 # a branch matching the commit. Expects 'git show-ref'
360 # or 'git ls-remote' output on stdin.
361 _git-r3_find_head() {
362 debug-print-function ${FUNCNAME} "$@"
363
364 local head_ref=${1}
365 local head_hash=$(git rev-parse --verify "${1}" || die)
366 local matching_ref
367
368 # TODO: some transports support peeking at symbolic remote refs
369 # find a way to use that rather than guessing
370
371 # (based on guess_remote_head() in git-1.9.0/remote.c)
372 local h ref
373 while read h ref; do
374 # look for matching head
375 if [[ ${h} == ${head_hash} ]]; then
376 # either take the first matching ref, or master if it is there
377 if [[ ! ${matching_ref} || ${ref} == refs/heads/master ]]; then
378 matching_ref=${ref}
379 fi
380 fi
381 done
382
383 if [[ ! ${matching_ref} ]]; then
384 die "Unable to find a matching branch for remote HEAD (${head_hash})"
385 fi
386
387 echo "${matching_ref}"
388 }
389
390 # @FUNCTION: git-r3_fetch
391 # @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
392 # @DESCRIPTION:
393 # Fetch new commits to the local clone of repository.
394 #
395 # <repo-uri> specifies the repository URIs to fetch from, as a space-
396 # -separated list. The first URI will be used as repository group
397 # identifier and therefore must be used consistently. When not
398 # specified, defaults to ${EGIT_REPO_URI}.
399 #
400 # <remote-ref> specifies the remote ref or commit id to fetch.
401 # It is preferred to use 'refs/heads/<branch-name>' for branches
402 # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
403 # for upstream default branch and hexadecimal commit SHA1. Defaults
404 # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
405 # is set to a non-null value.
406 #
407 # <local-id> specifies the local branch identifier that will be used to
408 # locally store the fetch result. It should be unique to multiple
409 # fetches within the repository that can be performed at the same time
410 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
411 # This default should be fine unless you are fetching multiple trees
412 # from the same repository in the same ebuild.
413 #
414 # The fetch operation will affect the EGIT_STORE only. It will not touch
415 # the working copy, nor export any environment variables.
416 # If the repository contains submodules, they will be fetched
417 # recursively.
418 git-r3_fetch() {
419 debug-print-function ${FUNCNAME} "$@"
420
421 [[ ${EVCS_OFFLINE} ]] && return
422
423 local repos
424 if [[ ${1} ]]; then
425 repos=( ${1} )
426 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
427 repos=( "${EGIT_REPO_URI[@]}" )
428 else
429 repos=( ${EGIT_REPO_URI} )
430 fi
431
432 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
433 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
434 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
435 local local_ref=refs/git-r3/${local_id}/__main__
436
437 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
438
439 local -x GIT_DIR
440 _git-r3_set_gitdir "${repos[0]}"
441
442 # prepend the local mirror if applicable
443 if [[ ${EGIT_MIRROR_URI} ]]; then
444 repos=(
445 "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
446 "${repos[@]}"
447 )
448 fi
449
450 # try to fetch from the remote
451 local r success
452 for r in "${repos[@]}"; do
453 einfo "Fetching ${r} ..."
454
455 local fetch_command=( git fetch "${r}" )
456
457 if [[ ${EGIT_CLONE_TYPE} == mirror ]]; then
458 fetch_command+=(
459 --prune
460 # mirror the remote branches as local branches
461 "+refs/heads/*:refs/heads/*"
462 # pull tags explicitly in order to prune them properly
463 "+refs/tags/*:refs/tags/*"
464 # notes in case something needs them
465 "+refs/notes/*:refs/notes/*"
466 # and HEAD in case we need the default branch
467 # (we keep it in refs/git-r3 since otherwise --prune interferes)
468 "+HEAD:refs/git-r3/HEAD"
469 )
470 else # single or shallow
471 local fetch_l fetch_r
472
473 if [[ ${remote_ref} == HEAD ]]; then
474 # HEAD
475 fetch_l=HEAD
476 elif [[ ${remote_ref} == refs/heads/* ]]; then
477 # regular branch
478 fetch_l=${remote_ref}
479 else
480 # tag or commit...
481 # let ls-remote figure it out
482 local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
483
484 # if it was a tag, ls-remote obtained a hash
485 if [[ ${tagref} ]]; then
486 # tag
487 fetch_l=refs/tags/${remote_ref}
488 else
489 # commit
490 # so we need to fetch the branch
491 if [[ ${branch} ]]; then
492 fetch_l=${branch}
493 else
494 fetch_l=HEAD
495 fi
496
497 # fetching by commit in shallow mode? can't do.
498 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
499 local EGIT_CLONE_TYPE=single
500 fi
501 fi
502 fi
503
504 if [[ ${fetch_l} == HEAD ]]; then
505 fetch_r=refs/git-r3/HEAD
506 else
507 fetch_r=${fetch_l}
508 fi
509
510 fetch_command+=(
511 "+${fetch_l}:${fetch_r}"
512 )
513 fi
514
515 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
516 if _git-r3_is_local_repo; then
517 # '--depth 1' causes sandbox violations with local repos
518 # bug #491260
519 local EGIT_CLONE_TYPE=single
520 elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
521 then
522 # use '--depth 1' when fetching a new branch
523 fetch_command+=( --depth 1 )
524 fi
525 else # non-shallow mode
526 if [[ -f ${GIT_DIR}/shallow ]]; then
527 fetch_command+=( --unshallow )
528 fi
529 fi
530
531 set -- "${fetch_command[@]}"
532 echo "${@}" >&2
533 if "${@}"; then
534 if [[ ${EGIT_CLONE_TYPE} == mirror ]]; then
535 # find remote HEAD and update our HEAD properly
536 git symbolic-ref HEAD \
537 "$(_git-r3_find_head refs/git-r3/HEAD \
538 < <(git show-ref --heads || die))" \
539 || die "Unable to update HEAD"
540 else # single or shallow
541 if [[ ${fetch_l} == HEAD ]]; then
542 # find out what branch we fetched as HEAD
543 local head_branch=$(_git-r3_find_head \
544 refs/git-r3/HEAD \
545 < <(git ls-remote --heads "${r}" || die))
546
547 # and move it to its regular place
548 git update-ref --no-deref "${head_branch}" \
549 refs/git-r3/HEAD \
550 || die "Unable to sync HEAD branch ${head_branch}"
551 git symbolic-ref HEAD "${head_branch}" \
552 || die "Unable to update HEAD"
553 fi
554 fi
555
556 # now let's see what the user wants from us
557 local full_remote_ref=$(
558 git rev-parse --verify --symbolic-full-name "${remote_ref}"
559 )
560
561 if [[ ${full_remote_ref} ]]; then
562 # when we are given a ref, create a symbolic ref
563 # so that we preserve the actual argument
564 set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
565 else
566 # otherwise, we were likely given a commit id
567 set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
568 fi
569
570 echo "${@}" >&2
571 if ! "${@}"; then
572 die "Referencing ${remote_ref} failed (wrong ref?)."
573 fi
574
575 success=1
576 break
577 fi
578 done
579 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
580
581 # recursively fetch submodules
582 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
583 local submodules
584 _git-r3_set_submodules \
585 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
586
587 while [[ ${submodules[@]} ]]; do
588 local subname=${submodules[0]}
589 local url=${submodules[1]}
590 local path=${submodules[2]}
591 local commit=$(git rev-parse "${local_ref}:${path}")
592
593 if [[ ! ${commit} ]]; then
594 die "Unable to get commit id for submodule ${subname}"
595 fi
596 if [[ ${url} == ./* || ${url} == ../* ]]; then
597 local subrepos=( "${repos[@]/%//${url}}" )
598 else
599 local subrepos=( "${url}" )
600 fi
601
602 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
603
604 submodules=( "${submodules[@]:3}" ) # shift
605 done
606 fi
607 }
608
609 # @FUNCTION: git-r3_checkout
610 # @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
611 # @DESCRIPTION:
612 # Check the previously fetched tree to the working copy.
613 #
614 # <repo-uri> specifies the repository URIs, as a space-separated list.
615 # The first URI will be used as repository group identifier
616 # and therefore must be used consistently with git-r3_fetch.
617 # The remaining URIs are not used and therefore may be omitted.
618 # When not specified, defaults to ${EGIT_REPO_URI}.
619 #
620 # <checkout-path> specifies the path to place the checkout. It defaults
621 # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
622 #
623 # <local-id> needs to specify the local identifier that was used
624 # for respective git-r3_fetch.
625 #
626 # The checkout operation will write to the working copy, and export
627 # the repository state into the environment. If the repository contains
628 # submodules, they will be checked out recursively.
629 git-r3_checkout() {
630 debug-print-function ${FUNCNAME} "$@"
631
632 local repos
633 if [[ ${1} ]]; then
634 repos=( ${1} )
635 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
636 repos=( "${EGIT_REPO_URI[@]}" )
637 else
638 repos=( ${EGIT_REPO_URI} )
639 fi
640
641 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
642 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
643
644 local -x GIT_DIR
645 _git-r3_set_gitdir "${repos[0]}"
646
647 einfo "Checking out ${repos[0]} to ${out_dir} ..."
648
649 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
650 if [[ ${EVCS_OFFLINE} ]]; then
651 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
652 else
653 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
654 fi
655 fi
656 local remote_ref=$(
657 git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
658 )
659 local new_commit_id=$(
660 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
661 )
662
663 git-r3_sub_checkout() {
664 local orig_repo=${GIT_DIR}
665 local -x GIT_DIR=${out_dir}/.git
666 local -x GIT_WORK_TREE=${out_dir}
667
668 mkdir -p "${out_dir}" || die
669
670 # use git init+fetch instead of clone since the latter doesn't like
671 # non-empty directories.
672
673 git init --quiet || die
674 # setup 'alternates' to avoid copying objects
675 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
676 # now copy the refs
677 # [htn]* safely catches heads, tags, notes without complaining
678 # on non-existing ones, and omits internal 'git-r3' ref
679 cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die
680
681 # (no need to copy HEAD, we will set it via checkout)
682
683 if [[ -f ${orig_repo}/shallow ]]; then
684 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
685 fi
686
687 set -- git checkout --quiet
688 if [[ ${remote_ref} ]]; then
689 set -- "${@}" "${remote_ref#refs/heads/}"
690 else
691 set -- "${@}" "${new_commit_id}"
692 fi
693 echo "${@}" >&2
694 "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
695 }
696 git-r3_sub_checkout
697
698 local old_commit_id=$(
699 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
700 )
701 if [[ ! ${old_commit_id} ]]; then
702 echo "GIT NEW branch -->"
703 echo " repository: ${repos[0]}"
704 echo " at the commit: ${new_commit_id}"
705 else
706 # diff against previous revision
707 echo "GIT update -->"
708 echo " repository: ${repos[0]}"
709 # write out message based on the revisions
710 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
711 echo " updating from commit: ${old_commit_id}"
712 echo " to commit: ${new_commit_id}"
713
714 git --no-pager diff --stat \
715 ${old_commit_id}..${new_commit_id}
716 else
717 echo " at the commit: ${new_commit_id}"
718 fi
719 fi
720 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
721
722 # recursively checkout submodules
723 if [[ -f ${out_dir}/.gitmodules ]]; then
724 local submodules
725 _git-r3_set_submodules \
726 "$(<"${out_dir}"/.gitmodules)"
727
728 while [[ ${submodules[@]} ]]; do
729 local subname=${submodules[0]}
730 local url=${submodules[1]}
731 local path=${submodules[2]}
732
733 if [[ ${url} == ./* || ${url} == ../* ]]; then
734 url=${repos[0]%%/}/${url}
735 fi
736
737 git-r3_checkout "${url}" "${out_dir}/${path}" \
738 "${local_id}/${subname}"
739
740 submodules=( "${submodules[@]:3}" ) # shift
741 done
742 fi
743
744 # keep this *after* submodules
745 export EGIT_DIR=${GIT_DIR}
746 export EGIT_VERSION=${new_commit_id}
747 }
748
749 # @FUNCTION: git-r3_peek_remote_ref
750 # @USAGE: [<repo-uri> [<remote-ref>]]
751 # @DESCRIPTION:
752 # Peek the reference in the remote repository and print the matching
753 # (newest) commit SHA1.
754 #
755 # <repo-uri> specifies the repository URIs to fetch from, as a space-
756 # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
757 #
758 # <remote-ref> specifies the remote ref to peek. It is preferred to use
759 # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
760 # for tags. Alternatively, 'HEAD' may be used for upstream default
761 # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
762 # 'HEAD' that is set to a non-null value.
763 #
764 # The operation will be done purely on the remote, without using local
765 # storage. If commit SHA1 is provided as <remote-ref>, the function will
766 # fail due to limitations of git protocol.
767 #
768 # On success, the function returns 0 and writes hexadecimal commit SHA1
769 # to stdout. On failure, the function returns 1.
770 git-r3_peek_remote_ref() {
771 debug-print-function ${FUNCNAME} "$@"
772
773 local repos
774 if [[ ${1} ]]; then
775 repos=( ${1} )
776 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
777 repos=( "${EGIT_REPO_URI[@]}" )
778 else
779 repos=( ${EGIT_REPO_URI} )
780 fi
781
782 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
783 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
784
785 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
786
787 local r success
788 for r in "${repos[@]}"; do
789 einfo "Peeking ${remote_ref} on ${r} ..." >&2
790
791 local is_branch lookup_ref
792 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
793 then
794 is_branch=1
795 lookup_ref=${remote_ref}
796 else
797 # ls-remote by commit is going to fail anyway,
798 # so we may as well pass refs/tags/ABCDEF...
799 lookup_ref=refs/tags/${remote_ref}
800 fi
801
802 # split on whitespace
803 local ref=(
804 $(git ls-remote "${r}" "${lookup_ref}")
805 )
806
807 if [[ ${ref[0]} ]]; then
808 echo "${ref[0]}"
809 return 0
810 fi
811 done
812
813 return 1
814 }
815
816 git-r3_src_fetch() {
817 debug-print-function ${FUNCNAME} "$@"
818
819 if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
820 ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
821 ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
822 ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
823 ewarn "when git-2 eclass becomes deprecated."
824 fi
825
826 _git-r3_env_setup
827 git-r3_fetch
828 }
829
830 git-r3_src_unpack() {
831 debug-print-function ${FUNCNAME} "$@"
832
833 _git-r3_env_setup
834 git-r3_src_fetch
835 git-r3_checkout
836 }
837
838 # https://bugs.gentoo.org/show_bug.cgi?id=482666
839 git-r3_pkg_outofdate() {
840 debug-print-function ${FUNCNAME} "$@"
841
842 local new_commit_id=$(git-r3_peek_remote_ref)
843 ewarn "old: ${EGIT_VERSION}"
844 ewarn "new: ${new_commit_id}"
845 [[ ${new_commit_id} && ${old_commit_id} ]] || return 2
846
847 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
848 }
849
850 _GIT_R3=1
851 fi

  ViewVC Help
Powered by ViewVC 1.1.20