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

Diff of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.18 Revision 1.25
1# Copyright 1999-2013 Gentoo Foundation 1# Copyright 1999-2014 Gentoo Foundation
2# Distributed under the terms of the GNU General Public License v2 2# Distributed under the terms of the GNU General Public License v2
3# $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.18 2013/10/14 20:30:00 mgorny Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.25 2014/02/24 08:43:34 mgorny Exp $
4 4
5# @ECLASS: git-r3.eclass 5# @ECLASS: git-r3.eclass
6# @MAINTAINER: 6# @MAINTAINER:
7# Michał Górny <mgorny@gentoo.org> 7# Michał Górny <mgorny@gentoo.org>
8# @BLURB: Eclass for fetching and unpacking git repositories. 8# @BLURB: Eclass for fetching and unpacking git repositories.
9# @DESCRIPTION: 9# @DESCRIPTION:
10# Third generation eclass for easing maitenance of live ebuilds using 10# Third generation eclass for easing maitenance of live ebuilds using
11# git as remote repository. The eclass supports lightweight (shallow) 11# git as remote repository.
12# clones and bare clones of submodules.
13 12
14case "${EAPI:-0}" in 13case "${EAPI:-0}" in
15 0|1|2|3|4|5) 14 0|1|2|3|4|5)
16 ;; 15 ;;
17 *) 16 *)
28EXPORT_FUNCTIONS src_unpack 27EXPORT_FUNCTIONS src_unpack
29 28
30if [[ ! ${_GIT_R3} ]]; then 29if [[ ! ${_GIT_R3} ]]; then
31 30
32if [[ ! ${_INHERITED_BY_GIT_2} ]]; then 31if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
33 DEPEND=">=dev-vcs/git-1.8.2.1" 32 DEPEND="dev-vcs/git"
34fi 33fi
35 34
36# @ECLASS-VARIABLE: EGIT3_STORE_DIR 35# @ECLASS-VARIABLE: EGIT3_STORE_DIR
37# @DESCRIPTION: 36# @DESCRIPTION:
38# Storage directory for git sources. 37# Storage directory for git sources.
80# @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR 79# @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
81# @DESCRIPTION: 80# @DESCRIPTION:
82# The directory to check the git sources out to. 81# The directory to check the git sources out to.
83# 82#
84# EGIT_CHECKOUT_DIR=${WORKDIR}/${P} 83# EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
85
86# @ECLASS-VARIABLE: EGIT_NONSHALLOW
87# @DEFAULT_UNSET
88# @DESCRIPTION:
89# Disable performing shallow fetches/clones. Shallow clones have
90# a fair number of limitations. Therefore, if you'd like the eclass to
91# perform complete clones instead, set this to a non-null value.
92#
93# This variable can be set in make.conf and ebuilds. The make.conf
94# value specifies user-specific default, while ebuilds may use it
95# to force deep clones when the server does not support shallow clones
96# (e.g. Google Code).
97 84
98# @FUNCTION: _git-r3_env_setup 85# @FUNCTION: _git-r3_env_setup
99# @INTERNAL 86# @INTERNAL
100# @DESCRIPTION: 87# @DESCRIPTION:
101# Set the eclass variables as necessary for operation. This can involve 88# Set the eclass variables as necessary for operation. This can involve
215 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die 202 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die
216 ) || die "Unable to create ${EGIT3_STORE_DIR}" 203 ) || die "Unable to create ${EGIT3_STORE_DIR}"
217 fi 204 fi
218 205
219 addwrite "${EGIT3_STORE_DIR}" 206 addwrite "${EGIT3_STORE_DIR}"
207 if [[ -e ${GIT_DIR}/shallow ]]; then
208 einfo "${GIT_DIR} was a shallow clone, recreating..."
209 rm -r "${GIT_DIR}" || die
210 fi
220 if [[ ! -d ${GIT_DIR} ]]; then 211 if [[ ! -d ${GIT_DIR} ]]; then
221 mkdir "${GIT_DIR}" || die 212 mkdir "${GIT_DIR}" || die
222 git init --bare || die 213 git init --bare || die
223
224 if [[ ! ${EGIT_NONSHALLOW} ]]; then
225 # avoid auto-unshallow :)
226 touch "${GIT_DIR}"/shallow || die
227 fi
228 fi 214 fi
229} 215}
230 216
231# @FUNCTION: _git-r3_set_submodules 217# @FUNCTION: _git-r3_set_submodules
232# @USAGE: <file-contents> 218# @USAGE: <file-contents>
265 submodule."${subname}".path || die)" 251 submodule."${subname}".path || die)"
266 ) 252 )
267 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die) 253 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
268} 254}
269 255
270# @FUNCTION: _git-r3_smart_fetch 256# @FUNCTION: _git-r3_is_local_repo
271# @USAGE: <git-fetch-args>... 257# @USAGE: <repo-uri>
258# @INTERNAL
272# @DESCRIPTION: 259# @DESCRIPTION:
273# Try fetching without '--depth' and switch to '--depth 1' if that 260# Determine whether the given URI specifies a local (on-disk)
274# will involve less objects fetched. 261# repository.
275_git-r3_smart_fetch() { 262_git-r3_is_local_repo() {
276 debug-print-function ${FUNCNAME} "$@" 263 debug-print-function ${FUNCNAME} "$@"
277 264
278 local sed_regexp='.*Counting objects: \([0-9]*\), done\..*'
279
280 # start the main fetch
281 local cmd=( git fetch --progress "${@}" )
282 echo "${cmd[@]}" >&2
283
284 # we copy the output to the 'sed' pipe for parsing. whenever sed finds
285 # the process count, it quits quickly to avoid delays in writing it.
286 # then, we start a dummy 'cat' to keep the pipe alive
287
288 "${cmd[@]}" 2>&1 \
289 | tee >(
290 sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}" \
291 > "${T}"/git-r3_main.count
292 exec cat >/dev/null
293 ) &
294 local main_pid=${!}
295
296 # start the helper process
297 _git-r3_sub_fetch() {
298 # wait for main fetch to get object count; if the server doesn't
299 # output it, we won't even launch the parallel process
300 while [[ ! -s ${T}/git-r3_main.count ]]; do
301 sleep 0.25
302 done
303
304 # ok, let's see if parallel fetch gives us smaller count
305 # --dry-run will prevent it from writing to the local clone
306 # and sed should terminate git with SIGPIPE
307 local sub_count=$(git fetch --progress --dry-run --depth 1 "${@}" 2>&1 \
308 | sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}")
309 local main_count=$(<"${T}"/git-r3_main.count)
310
311 # let's be real sure that '--depth 1' will be good for us.
312 # note that we have purely objects counts, and '--depth 1'
313 # may involve much bigger objects
314 if [[ ${main_count} && ${main_count} -ge $(( sub_count * 3/2 )) ]]
315 then
316 # signal that we want shallow fetch instead,
317 # and terminate the non-shallow fetch process
318 touch "${T}"/git-r3_want_shallow || die
319 kill ${main_pid} &>/dev/null
320 exit 0
321 fi
322
323 exit 1
324 }
325 _git-r3_sub_fetch "${@}" &
326 local sub_pid=${!} 265 local uri=${1}
327 266
328 # wait for main process to terminate, either of its own 267 [[ ${uri} == file://* || ${uri} == /* ]]
329 # or by signal from subprocess
330 wait ${main_pid}
331 local main_ret=${?}
332
333 # wait for subprocess to terminate, killing it if necessary.
334 # if main fetch finished before it, there's no point in keeping
335 # it alive. if main fetch was killed by it, it's done anyway
336 kill ${sub_pid} &>/dev/null
337 wait ${sub_pid}
338
339 # now see if subprocess wanted to tell us something...
340 if [[ -f ${T}/git-r3_want_shallow ]]; then
341 rm "${T}"/git-r3_want_shallow || die
342
343 # if fetch finished already (wasn't killed), ignore it
344 [[ ${main_ret} -eq 0 ]] && return 0
345
346 # otherwise, restart as shallow fetch
347 einfo "Restarting fetch using --depth 1 to save bandwidth ..."
348 local cmd=( git fetch --progress --depth 1 "${@}" )
349 echo "${cmd[@]}" >&2
350 "${cmd[@]}"
351 main_ret=${?}
352 fi
353
354 return ${main_ret}
355} 268}
356 269
357# @FUNCTION: git-r3_fetch 270# @FUNCTION: git-r3_fetch
358# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]] 271# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
359# @DESCRIPTION: 272# @DESCRIPTION:
372# is set to a non-null value. 285# is set to a non-null value.
373# 286#
374# <local-id> specifies the local branch identifier that will be used to 287# <local-id> specifies the local branch identifier that will be used to
375# locally store the fetch result. It should be unique to multiple 288# locally store the fetch result. It should be unique to multiple
376# fetches within the repository that can be performed at the same time 289# fetches within the repository that can be performed at the same time
377# (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT}. 290# (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
378# This default should be fine unless you are fetching multiple trees 291# This default should be fine unless you are fetching multiple trees
379# from the same repository in the same ebuild. 292# from the same repository in the same ebuild.
380# 293#
381# The fetch operation will affect the EGIT_STORE only. It will not touch 294# The fetch operation will affect the EGIT_STORE only. It will not touch
382# the working copy, nor export any environment variables. 295# the working copy, nor export any environment variables.
396 repos=( ${EGIT_REPO_URI} ) 309 repos=( ${EGIT_REPO_URI} )
397 fi 310 fi
398 311
399 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}} 312 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
400 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}} 313 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
401 local local_id=${3:-${CATEGORY}/${PN}/${SLOT}} 314 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
402 local local_ref=refs/heads/${local_id}/__main__ 315 local local_ref=refs/git-r3/${local_id}/__main__
403 316
404 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" 317 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
405 318
406 local -x GIT_DIR 319 local -x GIT_DIR
407 _git-r3_set_gitdir "${repos[0]}" 320 _git-r3_set_gitdir "${repos[0]}"
408 321
409 # try to fetch from the remote 322 # try to fetch from the remote
410 local r success 323 local r success
411 for r in "${repos[@]}"; do 324 for r in "${repos[@]}"; do
325 einfo "Fetching ${r} ..."
326
327 local fetch_command=(
328 git fetch --prune "${r}"
329 # mirror the remote branches as local branches
330 "refs/heads/*:refs/heads/*"
331 # pull tags explicitly in order to prune them properly
332 "refs/tags/*:refs/tags/*"
333 # notes in case something needs them
334 "refs/notes/*:refs/notes/*"
335 )
336
337 set -- "${fetch_command[@]}"
338 echo "${@}" >&2
339 if "${@}"; then
340 # now let's see what the user wants from us
341 local full_remote_ref=$(
342 git rev-parse --verify --symbolic-full-name "${remote_ref}"
343 )
344
345 if [[ ${full_remote_ref} ]]; then
346 # when we are given a ref, create a symbolic ref
347 # so that we preserve the actual argument
348 set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
349 else
350 # otherwise, we were likely given a commit id
351 set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
352 fi
353
354 echo "${@}" >&2
355 if ! "${@}"; then
356 die "Referencing ${remote_ref} failed (wrong ref?)."
357 fi
358
359 success=1
360 break
361 fi
362 done
363 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
364
365 # recursively fetch submodules
366 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
367 local submodules
368 _git-r3_set_submodules \
369 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
370
371 while [[ ${submodules[@]} ]]; do
372 local subname=${submodules[0]}
373 local url=${submodules[1]}
374 local path=${submodules[2]}
375 local commit=$(git rev-parse "${local_ref}:${path}")
376
377 if [[ ! ${commit} ]]; then
378 die "Unable to get commit id for submodule ${subname}"
379 fi
380 if [[ ${url} == ./* || ${url} == ../* ]]; then
381 local subrepos=( "${repos[@]/%//${url}}" )
382 else
383 local subrepos=( "${url}" )
384 fi
385
386 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
387
388 submodules=( "${submodules[@]:3}" ) # shift
389 done
390 fi
391}
392
393# @FUNCTION: git-r3_checkout
394# @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
395# @DESCRIPTION:
396# Check the previously fetched tree to the working copy.
397#
398# <repo-uri> specifies the repository URIs, as a space-separated list.
399# The first URI will be used as repository group identifier
400# and therefore must be used consistently with git-r3_fetch.
401# The remaining URIs are not used and therefore may be omitted.
402# When not specified, defaults to ${EGIT_REPO_URI}.
403#
404# <checkout-path> specifies the path to place the checkout. It defaults
405# to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
406#
407# <local-id> needs to specify the local identifier that was used
408# for respective git-r3_fetch.
409#
410# The checkout operation will write to the working copy, and export
411# the repository state into the environment. If the repository contains
412# submodules, they will be checked out recursively.
413git-r3_checkout() {
414 debug-print-function ${FUNCNAME} "$@"
415
416 local repos
417 if [[ ${1} ]]; then
418 repos=( ${1} )
419 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
420 repos=( "${EGIT_REPO_URI[@]}" )
421 else
422 repos=( ${EGIT_REPO_URI} )
423 fi
424
425 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
426 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
427
428 local -x GIT_DIR
429 _git-r3_set_gitdir "${repos[0]}"
430
431 einfo "Checking out ${repos[0]} to ${out_dir} ..."
432
433 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
434 if [[ ${EVCS_OFFLINE} ]]; then
435 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
436 else
437 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
438 fi
439 fi
440 local remote_ref=$(
441 git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
442 )
443 local new_commit_id=$(
444 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
445 )
446
447 set -- git clone --quiet --shared --no-checkout "${GIT_DIR}" "${out_dir}"/
448 echo "${@}" >&2
449 "${@}" || die "git clone (for checkout) failed"
450
451 git-r3_sub_checkout() {
452 local orig_repo=${GIT_DIR}
453 local -x GIT_DIR=${out_dir}/.git
454 local -x GIT_WORK_TREE=${out_dir}
455
456 # pull notes
457 git fetch "${orig_repo}" "refs/notes/*:refs/notes/*" || die
458
459 set -- git checkout --quiet
460 if [[ ${remote_ref} ]]; then
461 set -- "${@}" "${remote_ref#refs/heads/}"
462 else
463 set -- "${@}" "${new_commit_id}"
464 fi
465 echo "${@}" >&2
466 "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
467 }
468 git-r3_sub_checkout
469
470 local old_commit_id=$(
471 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
472 )
473 if [[ ! ${old_commit_id} ]]; then
474 echo "GIT NEW branch -->"
475 echo " repository: ${repos[0]}"
476 echo " at the commit: ${new_commit_id}"
477 else
478 # diff against previous revision
479 echo "GIT update -->"
480 echo " repository: ${repos[0]}"
481 # write out message based on the revisions
482 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
483 echo " updating from commit: ${old_commit_id}"
484 echo " to commit: ${new_commit_id}"
485
486 git --no-pager diff --stat \
487 ${old_commit_id}..${new_commit_id}
488 else
489 echo " at the commit: ${new_commit_id}"
490 fi
491 fi
492 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
493
494 # recursively checkout submodules
495 if [[ -f ${out_dir}/.gitmodules ]]; then
496 local submodules
497 _git-r3_set_submodules \
498 "$(<"${out_dir}"/.gitmodules)"
499
500 while [[ ${submodules[@]} ]]; do
501 local subname=${submodules[0]}
502 local url=${submodules[1]}
503 local path=${submodules[2]}
504
505 if [[ ${url} == ./* || ${url} == ../* ]]; then
506 url=${repos[0]%%/}/${url}
507 fi
508
509 git-r3_checkout "${url}" "${out_dir}/${path}" \
510 "${local_id}/${subname}"
511
512 submodules=( "${submodules[@]:3}" ) # shift
513 done
514 fi
515
516 # keep this *after* submodules
517 export EGIT_DIR=${GIT_DIR}
518 export EGIT_VERSION=${new_commit_id}
519}
520
521# @FUNCTION: git-r3_peek_remote_ref
522# @USAGE: [<repo-uri> [<remote-ref>]]
523# @DESCRIPTION:
524# Peek the reference in the remote repository and print the matching
525# (newest) commit SHA1.
526#
527# <repo-uri> specifies the repository URIs to fetch from, as a space-
528# -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
529#
530# <remote-ref> specifies the remote ref to peek. It is preferred to use
531# 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
532# for tags. Alternatively, 'HEAD' may be used for upstream default
533# branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
534# 'HEAD' that is set to a non-null value.
535#
536# The operation will be done purely on the remote, without using local
537# storage. If commit SHA1 is provided as <remote-ref>, the function will
538# fail due to limitations of git protocol.
539#
540# On success, the function returns 0 and writes hexadecimal commit SHA1
541# to stdout. On failure, the function returns 1.
542git-r3_peek_remote_ref() {
543 debug-print-function ${FUNCNAME} "$@"
544
545 local repos
546 if [[ ${1} ]]; then
547 repos=( ${1} )
548 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
549 repos=( "${EGIT_REPO_URI[@]}" )
550 else
551 repos=( ${EGIT_REPO_URI} )
552 fi
553
554 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
555 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
556
557 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
558
559 local r success
560 for r in "${repos[@]}"; do
412 einfo "Fetching ${remote_ref} from ${r} ..." 561 einfo "Peeking ${remote_ref} on ${r} ..." >&2
413 562
414 local is_branch lookup_ref 563 local is_branch lookup_ref
415 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]] 564 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
416 then 565 then
417 is_branch=1 566 is_branch=1
420 # ls-remote by commit is going to fail anyway, 569 # ls-remote by commit is going to fail anyway,
421 # so we may as well pass refs/tags/ABCDEF... 570 # so we may as well pass refs/tags/ABCDEF...
422 lookup_ref=refs/tags/${remote_ref} 571 lookup_ref=refs/tags/${remote_ref}
423 fi 572 fi
424 573
425 # first, try ls-remote to see if ${remote_ref} is a real ref
426 # and not a commit id. if it succeeds, we can pass ${remote_ref}
427 # to 'fetch'. otherwise, we will just fetch everything
428
429 # split on whitespace
430 local ref=(
431 $(git ls-remote "${r}" "${lookup_ref}" || echo __FAIL__)
432 )
433
434 # normally, ref[0] is a hash, so we can do magic strings here
435 [[ ${ref[0]} == __FAIL__ ]] && continue
436
437 local nonshallow=${EGIT_NONSHALLOW}
438 local ref_param=()
439 if [[ ! ${ref[0]} ]]; then
440 nonshallow=1
441 fi
442
443 # 1. if we need a non-shallow clone and we have a shallow one,
444 # we need to unshallow it explicitly.
445 # 2. if we want a shallow clone, we just pass '--depth 1'
446 # to the first fetch in the repo. passing '--depth'
447 # to further requests usually results in more data being
448 # downloaded than without it.
449 # 3. if we update a shallow clone, we try without '--depth'
450 # first since that usually transfers less data. however,
451 # we use git-r3_smart_fetch that can switch into '--depth 1'
452 # if that looks beneficial.
453
454 local fetch_command=( git fetch )
455 if [[ ${nonshallow} ]]; then
456 if [[ -f ${GIT_DIR}/shallow ]]; then
457 ref_param+=( --unshallow )
458 fi
459 # fetch all branches
460 ref_param+=( "refs/heads/*:refs/remotes/origin/*" )
461 else
462 # 'git show-ref --heads' returns 1 when there are no branches
463 if ! git show-ref --heads -q; then
464 ref_param+=( --depth 1 )
465 else
466 fetch_command=( _git-r3_smart_fetch )
467 fi
468 fi
469
470 # now, another important thing. we may only fetch a remote
471 # branch directly to a local branch. Otherwise, we need to fetch
472 # the commit and re-create the branch on top of it.
473
474 if [[ ${ref[0]} ]]; then
475 if [[ ${is_branch} ]]; then
476 ref_param+=( -f "${remote_ref}:${local_id}/__main__" )
477 else
478 ref_param+=( "refs/tags/${remote_ref}" )
479 fi
480 fi
481
482 # if ${remote_ref} is branch or tag, ${ref[@]} will contain
483 # the respective commit id. otherwise, it will be an empty
484 # array, so the following won't evaluate to a parameter.
485 set -- "${fetch_command[@]}" --no-tags "${r}" "${ref_param[@]}"
486 echo "${@}" >&2
487 if "${@}"; then
488 if [[ ! ${is_branch} ]]; then
489 set -- git branch -f "${local_id}/__main__" \
490 "${ref[0]:-${remote_ref}}"
491 echo "${@}" >&2
492 if ! "${@}"; then
493 die "Creating branch for ${remote_ref} failed (wrong ref?)."
494 fi
495 fi
496
497 success=1
498 break
499 fi
500 done
501 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
502
503 # recursively fetch submodules
504 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
505 local submodules
506 _git-r3_set_submodules \
507 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
508
509 while [[ ${submodules[@]} ]]; do
510 local subname=${submodules[0]}
511 local url=${submodules[1]}
512 local path=${submodules[2]}
513 local commit=$(git rev-parse "${local_ref}:${path}")
514
515 if [[ ! ${commit} ]]; then
516 die "Unable to get commit id for submodule ${subname}"
517 fi
518
519 git-r3_fetch "${url}" "${commit}" "${local_id}/${subname}"
520
521 submodules=( "${submodules[@]:3}" ) # shift
522 done
523 fi
524}
525
526# @FUNCTION: git-r3_checkout
527# @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
528# @DESCRIPTION:
529# Check the previously fetched tree to the working copy.
530#
531# <repo-uri> specifies the repository URIs, as a space-separated list.
532# The first URI will be used as repository group identifier
533# and therefore must be used consistently with git-r3_fetch.
534# The remaining URIs are not used and therefore may be omitted.
535# When not specified, defaults to ${EGIT_REPO_URI}.
536#
537# <checkout-path> specifies the path to place the checkout. It defaults
538# to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
539#
540# <local-id> needs to specify the local identifier that was used
541# for respective git-r3_fetch.
542#
543# The checkout operation will write to the working copy, and export
544# the repository state into the environment. If the repository contains
545# submodules, they will be checked out recursively.
546git-r3_checkout() {
547 debug-print-function ${FUNCNAME} "$@"
548
549 local repos
550 if [[ ${1} ]]; then
551 repos=( ${1} )
552 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
553 repos=( "${EGIT_REPO_URI[@]}" )
554 else
555 repos=( ${EGIT_REPO_URI} )
556 fi
557
558 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
559 local local_id=${3:-${CATEGORY}/${PN}/${SLOT}}
560
561 local -x GIT_DIR GIT_WORK_TREE
562 _git-r3_set_gitdir "${repos[0]}"
563 GIT_WORK_TREE=${out_dir}
564 mkdir -p "${GIT_WORK_TREE}" || die
565
566 einfo "Checking out ${repos[0]} to ${out_dir} ..."
567
568 if ! git cat-file -e refs/heads/"${local_id}"/__main__
569 then
570 if [[ ${EVCS_OFFLINE} ]]; then
571 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
572 else
573 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
574 fi
575 fi
576
577 set -- git checkout -f "${local_id}"/__main__ .
578 echo "${@}" >&2
579 "${@}" || die "git checkout ${local_id}/__main__ failed"
580
581 # diff against previous revision (if any)
582 local new_commit_id=$(git rev-parse --verify "${local_id}"/__main__)
583 local old_commit_id=$(
584 git rev-parse --verify "${local_id}"/__old__ 2>/dev/null
585 )
586
587 if [[ ! ${old_commit_id} ]]; then
588 echo "GIT NEW branch -->"
589 echo " repository: ${repos[0]}"
590 echo " at the commit: ${new_commit_id}"
591 else
592 echo "GIT update -->"
593 echo " repository: ${repos[0]}"
594 # write out message based on the revisions
595 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
596 echo " updating from commit: ${old_commit_id}"
597 echo " to commit: ${new_commit_id}"
598
599 git --no-pager diff --stat \
600 ${old_commit_id}..${new_commit_id}
601 else
602 echo " at the commit: ${new_commit_id}"
603 fi
604 fi
605 git branch -f "${local_id}"/{__old__,__main__} || die
606
607 # recursively checkout submodules
608 if [[ -f ${GIT_WORK_TREE}/.gitmodules ]]; then
609 local submodules
610 _git-r3_set_submodules \
611 "$(<"${GIT_WORK_TREE}"/.gitmodules)"
612
613 while [[ ${submodules[@]} ]]; do
614 local subname=${submodules[0]}
615 local url=${submodules[1]}
616 local path=${submodules[2]}
617
618 git-r3_checkout "${url}" "${GIT_WORK_TREE}/${path}" \
619 "${local_id}/${subname}"
620
621 submodules=( "${submodules[@]:3}" ) # shift
622 done
623 fi
624
625 # keep this *after* submodules
626 export EGIT_DIR=${GIT_DIR}
627 export EGIT_VERSION=${new_commit_id}
628}
629
630# @FUNCTION: git-r3_peek_remote_ref
631# @USAGE: [<repo-uri> [<remote-ref>]]
632# @DESCRIPTION:
633# Peek the reference in the remote repository and print the matching
634# (newest) commit SHA1.
635#
636# <repo-uri> specifies the repository URIs to fetch from, as a space-
637# -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
638#
639# <remote-ref> specifies the remote ref to peek. It is preferred to use
640# 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
641# for tags. Alternatively, 'HEAD' may be used for upstream default
642# branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
643# 'HEAD' that is set to a non-null value.
644#
645# The operation will be done purely on the remote, without using local
646# storage. If commit SHA1 is provided as <remote-ref>, the function will
647# fail due to limitations of git protocol.
648#
649# On success, the function returns 0 and writes hexadecimal commit SHA1
650# to stdout. On failure, the function returns 1.
651git-r3_peek_remote_ref() {
652 debug-print-function ${FUNCNAME} "$@"
653
654 local repos
655 if [[ ${1} ]]; then
656 repos=( ${1} )
657 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
658 repos=( "${EGIT_REPO_URI[@]}" )
659 else
660 repos=( ${EGIT_REPO_URI} )
661 fi
662
663 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
664 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
665
666 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
667
668 local r success
669 for r in "${repos[@]}"; do
670 einfo "Peeking ${remote_ref} on ${r} ..." >&2
671
672 local is_branch lookup_ref
673 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
674 then
675 is_branch=1
676 lookup_ref=${remote_ref}
677 else
678 # ls-remote by commit is going to fail anyway,
679 # so we may as well pass refs/tags/ABCDEF...
680 lookup_ref=refs/tags/${remote_ref}
681 fi
682
683 # split on whitespace 574 # split on whitespace
684 local ref=( 575 local ref=(
685 $(git ls-remote "${r}" "${lookup_ref}") 576 $(git ls-remote "${r}" "${lookup_ref}")
686 ) 577 )
687 578

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.25

  ViewVC Help
Powered by ViewVC 1.1.20