/[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.27 Revision 1.41
1# Copyright 1999-2014 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.27 2014/03/02 11:44:19 mgorny Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.41 2014/04/17 20:28:37 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.
27EXPORT_FUNCTIONS src_unpack 27EXPORT_FUNCTIONS src_unpack
28 28
29if [[ ! ${_GIT_R3} ]]; then 29if [[ ! ${_GIT_R3} ]]; then
30 30
31if [[ ! ${_INHERITED_BY_GIT_2} ]]; then 31if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
32 DEPEND="dev-vcs/git" 32 DEPEND=">=dev-vcs/git-1.8.2.1"
33fi 33fi
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+tags' type clones the requested branch and all tags
51# in the repository. All notes are fetched as well. EGIT_COMMIT
52# can safely specify hashes throughout the current branch and all tags.
53# No purging of old references is done (if you often switch branches,
54# you may need to remove stale branches yourself). This mode is intended
55# mostly for use with broken git servers such as Google Code that fail
56# to fetch tags along with the branch in 'single' mode.
57#
58# The 'single' type clones only the requested branch or tag. Tags
59# referencing commits throughout the branch history are fetched as well,
60# and all notes. EGIT_COMMIT can safely specify only hashes
61# in the current branch. No purging of old references is done (if you
62# often switch branches, you may need to remove stale branches
63# yourself). This mode is suitable for general use.
64#
65# The 'shallow' type clones only the newest commit on requested branch
66# or tag. EGIT_COMMIT can only specify tags, and since the history is
67# unavailable calls like 'git describe' will not reference prior tags.
68# No purging of old references is done. This mode is intended mostly for
69# embedded systems with limited disk space.
70: ${EGIT_CLONE_TYPE:=single}
71
72# @ECLASS-VARIABLE: EGIT_MIN_CLONE_TYPE
73# @DESCRIPTION:
74# 'Minimum' clone type supported by the ebuild. Takes same values
75# as EGIT_CLONE_TYPE. When user sets a type that's 'lower' (that is,
76# later on the list) than EGIT_MIN_CLONE_TYPE, the eclass uses
77# EGIT_MIN_CLONE_TYPE instead.
78#
79# This variable is intended to be used by ebuilds only. Users are
80# supposed to set EGIT_CLONE_TYPE instead.
81#
82# A common case is to use 'single' whenever the build system requires
83# access to full branch history, or 'single+tags' when Google Code
84# or a similar remote is used that does not support shallow clones
85# and fetching tags along with commits. Please use sparingly, and to fix
86# fatal errors rather than 'non-pretty versions'.
87: ${EGIT_MIN_CLONE_TYPE:=shallow}
34 88
35# @ECLASS-VARIABLE: EGIT3_STORE_DIR 89# @ECLASS-VARIABLE: EGIT3_STORE_DIR
36# @DESCRIPTION: 90# @DESCRIPTION:
37# Storage directory for git sources. 91# Storage directory for git sources.
38# 92#
39# This is intended to be set by user in make.conf. Ebuilds must not set 93# This is intended to be set by user in make.conf. Ebuilds must not set
40# it. 94# it.
41# 95#
42# EGIT3_STORE_DIR=${DISTDIR}/git3-src 96# EGIT3_STORE_DIR=${DISTDIR}/git3-src
97
98# @ECLASS-VARIABLE: EGIT_MIRROR_URI
99# @DEFAULT_UNSET
100# @DESCRIPTION:
101# 'Top' URI to a local git mirror. If specified, the eclass will try
102# to fetch from the local mirror instead of using the remote repository.
103#
104# The mirror needs to follow EGIT3_STORE_DIR structure. The directory
105# created by eclass can be used for that purpose.
106#
107# Example:
108# @CODE
109# EGIT_MIRROR_URI="git://mirror.lan/"
110# @CODE
43 111
44# @ECLASS-VARIABLE: EGIT_REPO_URI 112# @ECLASS-VARIABLE: EGIT_REPO_URI
45# @REQUIRED 113# @REQUIRED
46# @DESCRIPTION: 114# @DESCRIPTION:
47# URIs to the repository, e.g. git://foo, https://foo. If multiple URIs 115# URIs to the repository, e.g. git://foo, https://foo. If multiple URIs
90# @DESCRIPTION: 158# @DESCRIPTION:
91# Set the eclass variables as necessary for operation. This can involve 159# Set the eclass variables as necessary for operation. This can involve
92# setting EGIT_* to defaults or ${PN}_LIVE_* variables. 160# setting EGIT_* to defaults or ${PN}_LIVE_* variables.
93_git-r3_env_setup() { 161_git-r3_env_setup() {
94 debug-print-function ${FUNCNAME} "$@" 162 debug-print-function ${FUNCNAME} "$@"
163
164 # check the clone type
165 case "${EGIT_CLONE_TYPE}" in
166 mirror|single+tags|single|shallow)
167 ;;
168 *)
169 die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
170 esac
171 case "${EGIT_MIN_CLONE_TYPE}" in
172 shallow)
173 ;;
174 single)
175 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
176 einfo "git-r3: ebuild needs to be cloned in 'single' mode, adjusting"
177 EGIT_CLONE_TYPE=single
178 fi
179 ;;
180 single+tags)
181 if [[ ${EGIT_CLONE_TYPE} == shallow || ${EGIT_CLONE_TYPE} == single ]]; then
182 einfo "git-r3: ebuild needs to be cloned in 'single+tags' mode, adjusting"
183 EGIT_CLONE_TYPE=single+tags
184 fi
185 ;;
186 mirror)
187 if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then
188 einfo "git-r3: ebuild needs to be cloned in 'mirror' mode, adjusting"
189 EGIT_CLONE_TYPE=mirror
190 fi
191 ;;
192 *)
193 die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
194 esac
95 195
96 local esc_pn livevar 196 local esc_pn livevar
97 esc_pn=${PN//[-+]/_} 197 esc_pn=${PN//[-+]/_}
98 198
99 livevar=${esc_pn}_LIVE_REPO 199 livevar=${esc_pn}_LIVE_REPO
205 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die 305 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die
206 ) || die "Unable to create ${EGIT3_STORE_DIR}" 306 ) || die "Unable to create ${EGIT3_STORE_DIR}"
207 fi 307 fi
208 308
209 addwrite "${EGIT3_STORE_DIR}" 309 addwrite "${EGIT3_STORE_DIR}"
210 if [[ -e ${GIT_DIR}/shallow ]]; then
211 einfo "${GIT_DIR} was a shallow clone, recreating..."
212 rm -r "${GIT_DIR}" || die
213 fi
214 if [[ ! -d ${GIT_DIR} ]]; then 310 if [[ ! -d ${GIT_DIR} ]]; then
215 mkdir "${GIT_DIR}" || die 311 mkdir "${GIT_DIR}" || die
216 git init --bare || die 312 git init --bare || die
217 fi 313 fi
218} 314}
268 local uri=${1} 364 local uri=${1}
269 365
270 [[ ${uri} == file://* || ${uri} == /* ]] 366 [[ ${uri} == file://* || ${uri} == /* ]]
271} 367}
272 368
369# @FUNCTION: _git-r3_find_head
370# @USAGE: <head-ref>
371# @INTERNAL
372# @DESCRIPTION:
373# Given a ref to which remote HEAD was fetched, try to find
374# a branch matching the commit. Expects 'git show-ref'
375# or 'git ls-remote' output on stdin.
376_git-r3_find_head() {
377 debug-print-function ${FUNCNAME} "$@"
378
379 local head_ref=${1}
380 local head_hash=$(git rev-parse --verify "${1}" || die)
381 local matching_ref
382
383 # TODO: some transports support peeking at symbolic remote refs
384 # find a way to use that rather than guessing
385
386 # (based on guess_remote_head() in git-1.9.0/remote.c)
387 local h ref
388 while read h ref; do
389 # look for matching head
390 if [[ ${h} == ${head_hash} ]]; then
391 # either take the first matching ref, or master if it is there
392 if [[ ! ${matching_ref} || ${ref} == refs/heads/master ]]; then
393 matching_ref=${ref}
394 fi
395 fi
396 done
397
398 if [[ ! ${matching_ref} ]]; then
399 die "Unable to find a matching branch for remote HEAD (${head_hash})"
400 fi
401
402 echo "${matching_ref}"
403}
404
273# @FUNCTION: git-r3_fetch 405# @FUNCTION: git-r3_fetch
274# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]] 406# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
275# @DESCRIPTION: 407# @DESCRIPTION:
276# Fetch new commits to the local clone of repository. 408# Fetch new commits to the local clone of repository.
277# 409#
320 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" 452 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
321 453
322 local -x GIT_DIR 454 local -x GIT_DIR
323 _git-r3_set_gitdir "${repos[0]}" 455 _git-r3_set_gitdir "${repos[0]}"
324 456
457 # prepend the local mirror if applicable
458 if [[ ${EGIT_MIRROR_URI} ]]; then
459 repos=(
460 "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
461 "${repos[@]}"
462 )
463 fi
464
325 # try to fetch from the remote 465 # try to fetch from the remote
326 local r success 466 local r success
327 for r in "${repos[@]}"; do 467 for r in "${repos[@]}"; do
328 einfo "Fetching ${r} ..." 468 einfo "Fetching ${r} ..."
329 469
470 local fetch_command=( git fetch "${r}" )
471 local clone_type=${EGIT_CLONE_TYPE}
472
473 if [[ ${r} == https://code.google.com/* ]]; then
474 # Google Code has special magic on top of git that:
475 # 1) can't handle shallow clones at all,
476 # 2) fetches duplicately when tags are pulled in with branch
477 # so automatically switch to single+tags mode.
478 if [[ ${clone_type} == shallow ]]; then
479 einfo " Google Code does not support shallow clones"
480 einfo " using EGIT_CLONE_TYPE=single+tags"
481 clone_type=single+tags
482 elif [[ ${clone_type} == single ]]; then
483 einfo " git-r3: Google Code does not send tags properly in 'single' mode"
484 einfo " using EGIT_CLONE_TYPE=single+tags"
485 clone_type=single+tags
486 fi
487 fi
488
489 if [[ ${clone_type} == mirror ]]; then
330 local fetch_command=( 490 fetch_command+=(
331 git fetch --prune "${r}" 491 --prune
332 # mirror the remote branches as local branches 492 # mirror the remote branches as local branches
333 "refs/heads/*:refs/heads/*" 493 "+refs/heads/*:refs/heads/*"
334 # pull tags explicitly in order to prune them properly 494 # pull tags explicitly in order to prune them properly
335 "refs/tags/*:refs/tags/*" 495 "+refs/tags/*:refs/tags/*"
336 # notes in case something needs them 496 # notes in case something needs them
337 "refs/notes/*:refs/notes/*" 497 "+refs/notes/*:refs/notes/*"
498 # and HEAD in case we need the default branch
499 # (we keep it in refs/git-r3 since otherwise --prune interferes)
500 "+HEAD:refs/git-r3/HEAD"
338 ) 501 )
502 else # single or shallow
503 local fetch_l fetch_r
504
505 if [[ ${remote_ref} == HEAD ]]; then
506 # HEAD
507 fetch_l=HEAD
508 elif [[ ${remote_ref} == refs/heads/* ]]; then
509 # regular branch
510 fetch_l=${remote_ref}
511 else
512 # tag or commit...
513 # let ls-remote figure it out
514 local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
515
516 # if it was a tag, ls-remote obtained a hash
517 if [[ ${tagref} ]]; then
518 # tag
519 fetch_l=refs/tags/${remote_ref}
520 else
521 # commit
522 # so we need to fetch the branch
523 if [[ ${branch} ]]; then
524 fetch_l=${branch}
525 else
526 fetch_l=HEAD
527 fi
528
529 # fetching by commit in shallow mode? can't do.
530 if [[ ${clone_type} == shallow ]]; then
531 clone_type=single
532 fi
533 fi
534 fi
535
536 if [[ ${fetch_l} == HEAD ]]; then
537 fetch_r=refs/git-r3/HEAD
538 else
539 fetch_r=${fetch_l}
540 fi
541
542 fetch_command+=(
543 "+${fetch_l}:${fetch_r}"
544 )
545
546 if [[ ${clone_type} == single+tags ]]; then
547 fetch_command+=(
548 # pull tags explicitly as requested
549 "+refs/tags/*:refs/tags/*"
550 )
551 fi
552 fi
553
554 if [[ ${clone_type} == shallow ]]; then
555 if _git-r3_is_local_repo; then
556 # '--depth 1' causes sandbox violations with local repos
557 # bug #491260
558 clone_type=single
559 elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
560 then
561 # use '--depth 1' when fetching a new branch
562 fetch_command+=( --depth 1 )
563 fi
564 else # non-shallow mode
565 if [[ -f ${GIT_DIR}/shallow ]]; then
566 fetch_command+=( --unshallow )
567 fi
568 fi
339 569
340 set -- "${fetch_command[@]}" 570 set -- "${fetch_command[@]}"
341 echo "${@}" >&2 571 echo "${@}" >&2
342 if "${@}"; then 572 if "${@}"; then
573 if [[ ${clone_type} == mirror ]]; then
574 # find remote HEAD and update our HEAD properly
575 git symbolic-ref HEAD \
576 "$(_git-r3_find_head refs/git-r3/HEAD \
577 < <(git show-ref --heads || die))" \
578 || die "Unable to update HEAD"
579 else # single or shallow
580 if [[ ${fetch_l} == HEAD ]]; then
581 # find out what branch we fetched as HEAD
582 local head_branch=$(_git-r3_find_head \
583 refs/git-r3/HEAD \
584 < <(git ls-remote --heads "${r}" || die))
585
586 # and move it to its regular place
587 git update-ref --no-deref "${head_branch}" \
588 refs/git-r3/HEAD \
589 || die "Unable to sync HEAD branch ${head_branch}"
590 git symbolic-ref HEAD "${head_branch}" \
591 || die "Unable to update HEAD"
592 fi
593 fi
594
343 # now let's see what the user wants from us 595 # now let's see what the user wants from us
344 local full_remote_ref=$( 596 local full_remote_ref=$(
345 git rev-parse --verify --symbolic-full-name "${remote_ref}" 597 git rev-parse --verify --symbolic-full-name "${remote_ref}"
346 ) 598 )
347 599
363 break 615 break
364 fi 616 fi
365 done 617 done
366 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" 618 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
367 619
620 # submodules can reference commits in any branch
621 # always use the 'clone' mode to accomodate that, bug #503332
622 local EGIT_CLONE_TYPE=mirror
623
368 # recursively fetch submodules 624 # recursively fetch submodules
369 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then 625 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
370 local submodules 626 local submodules
371 _git-r3_set_submodules \ 627 _git-r3_set_submodules \
372 "$(git cat-file -p "${local_ref}":.gitmodules || die)" 628 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
456 712
457 # use git init+fetch instead of clone since the latter doesn't like 713 # use git init+fetch instead of clone since the latter doesn't like
458 # non-empty directories. 714 # non-empty directories.
459 715
460 git init --quiet || die 716 git init --quiet || die
461 set -- git fetch --update-head-ok "${orig_repo}" \ 717 # setup 'alternates' to avoid copying objects
462 "refs/heads/*:refs/heads/*" \ 718 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
463 "refs/tags/*:refs/tags/*" \ 719 # now copy the refs
464 "refs/notes/*:refs/notes/*" 720 # [htn]* safely catches heads, tags, notes without complaining
721 # on non-existing ones, and omits internal 'git-r3' ref
722 cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die
465 723
466 echo "${@}" >&2 724 # (no need to copy HEAD, we will set it via checkout)
467 "${@}" || die "git fetch into checkout dir failed" 725
726 if [[ -f ${orig_repo}/shallow ]]; then
727 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
728 fi
468 729
469 set -- git checkout --quiet 730 set -- git checkout --quiet
470 if [[ ${remote_ref} ]]; then 731 if [[ ${remote_ref} ]]; then
471 set -- "${@}" "${remote_ref#refs/heads/}" 732 set -- "${@}" "${remote_ref#refs/heads/}"
472 else 733 else

Legend:
Removed from v.1.27  
changed lines
  Added in v.1.41

  ViewVC Help
Powered by ViewVC 1.1.20