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

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

  ViewVC Help
Powered by ViewVC 1.1.20