/[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.25 Revision 1.51
1# Copyright 1999-2014 Gentoo Foundation 1# Copyright 1999-2015 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.25 2014/02/24 08:43:34 mgorny Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.51 2015/08/08 09:32:50 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 maintenance of live ebuilds using
11# git as remote repository. 11# git as remote repository.
12 12
13case "${EAPI:-0}" in 13case "${EAPI:-0}" in
14 0|1|2|3|4|5) 14 0|1|2|3|4|5)
15 ;; 15 ;;
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 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}
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#
93# This is intended to be set by user in make.conf. Ebuilds must not set
94# it.
95#
39# 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
40 111
41# @ECLASS-VARIABLE: EGIT_REPO_URI 112# @ECLASS-VARIABLE: EGIT_REPO_URI
42# @REQUIRED 113# @REQUIRED
43# @DESCRIPTION: 114# @DESCRIPTION:
44# 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
45# are provided, the eclass will consider them as fallback URIs to try 116# are provided, the eclass will consider them as fallback URIs to try
46# if the first URI does not work. 117# if the first URI does not work. For supported URI syntaxes, read up
118# the manpage for git-clone(1).
47# 119#
48# It can be overriden via env using ${PN}_LIVE_REPO variable. 120# It can be overriden via env using ${PN}_LIVE_REPO variable.
49# 121#
50# Can be a whitespace-separated list or an array. 122# Can be a whitespace-separated list or an array.
51# 123#
57# @ECLASS-VARIABLE: EVCS_OFFLINE 129# @ECLASS-VARIABLE: EVCS_OFFLINE
58# @DEFAULT_UNSET 130# @DEFAULT_UNSET
59# @DESCRIPTION: 131# @DESCRIPTION:
60# If non-empty, this variable prevents any online operations. 132# If non-empty, this variable prevents any online operations.
61 133
134# @ECLASS-VARIABLE: EVCS_UMASK
135# @DEFAULT_UNSET
136# @DESCRIPTION:
137# Set this variable to a custom umask. This is intended to be set by
138# users. By setting this to something like 002, it can make life easier
139# for people who do development as non-root (but are in the portage
140# group), and then switch over to building with FEATURES=userpriv.
141# Or vice-versa. Shouldn't be a security issue here as anyone who has
142# portage group write access already can screw the system over in more
143# creative ways.
144
62# @ECLASS-VARIABLE: EGIT_BRANCH 145# @ECLASS-VARIABLE: EGIT_BRANCH
63# @DEFAULT_UNSET 146# @DEFAULT_UNSET
64# @DESCRIPTION: 147# @DESCRIPTION:
65# The branch name to check out. If unset, the upstream default (HEAD) 148# The branch name to check out. If unset, the upstream default (HEAD)
66# will be used. 149# will be used.
87# @DESCRIPTION: 170# @DESCRIPTION:
88# Set the eclass variables as necessary for operation. This can involve 171# Set the eclass variables as necessary for operation. This can involve
89# setting EGIT_* to defaults or ${PN}_LIVE_* variables. 172# setting EGIT_* to defaults or ${PN}_LIVE_* variables.
90_git-r3_env_setup() { 173_git-r3_env_setup() {
91 debug-print-function ${FUNCNAME} "$@" 174 debug-print-function ${FUNCNAME} "$@"
175
176 # check the clone type
177 case "${EGIT_CLONE_TYPE}" in
178 mirror|single+tags|single|shallow)
179 ;;
180 *)
181 die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
182 esac
183 case "${EGIT_MIN_CLONE_TYPE}" in
184 shallow)
185 ;;
186 single)
187 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
188 einfo "git-r3: ebuild needs to be cloned in '\e[1msingle\e[22m' mode, adjusting"
189 EGIT_CLONE_TYPE=single
190 fi
191 ;;
192 single+tags)
193 if [[ ${EGIT_CLONE_TYPE} == shallow || ${EGIT_CLONE_TYPE} == single ]]; then
194 einfo "git-r3: ebuild needs to be cloned in '\e[1msingle+tags\e[22m' mode, adjusting"
195 EGIT_CLONE_TYPE=single+tags
196 fi
197 ;;
198 mirror)
199 if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then
200 einfo "git-r3: ebuild needs to be cloned in '\e[1mmirror\e[22m' mode, adjusting"
201 EGIT_CLONE_TYPE=mirror
202 fi
203 ;;
204 *)
205 die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
206 esac
92 207
93 local esc_pn livevar 208 local esc_pn livevar
94 esc_pn=${PN//[-+]/_} 209 esc_pn=${PN//[-+]/_}
95 210
96 livevar=${esc_pn}_LIVE_REPO 211 livevar=${esc_pn}_LIVE_REPO
197 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name} 312 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
198 313
199 if [[ ! -d ${EGIT3_STORE_DIR} ]]; then 314 if [[ ! -d ${EGIT3_STORE_DIR} ]]; then
200 ( 315 (
201 addwrite / 316 addwrite /
202 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die 317 mkdir -p "${EGIT3_STORE_DIR}" || die
203 ) || die "Unable to create ${EGIT3_STORE_DIR}" 318 ) || die "Unable to create ${EGIT3_STORE_DIR}"
204 fi 319 fi
205 320
206 addwrite "${EGIT3_STORE_DIR}" 321 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
211 if [[ ! -d ${GIT_DIR} ]]; then 322 if [[ ! -d ${GIT_DIR} ]]; then
323 local saved_umask
324 if [[ ${EVCS_UMASK} ]]; then
325 saved_umask=$(umask)
326 umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
327 fi
212 mkdir "${GIT_DIR}" || die 328 mkdir "${GIT_DIR}" || die
213 git init --bare || die 329 git init --bare || die
330 if [[ ${saved_umask} ]]; then
331 umask "${saved_umask}" || die
332 fi
214 fi 333 fi
215} 334}
216 335
217# @FUNCTION: _git-r3_set_submodules 336# @FUNCTION: _git-r3_set_submodules
218# @USAGE: <file-contents> 337# @USAGE: <file-contents>
251 submodule."${subname}".path || die)" 370 submodule."${subname}".path || die)"
252 ) 371 )
253 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die) 372 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
254} 373}
255 374
375# @FUNCTION: _git-r3_set_subrepos
376# @USAGE: <submodule-uri> <parent-repo-uri>...
377# @INTERNAL
378# @DESCRIPTION:
379# Create 'subrepos' array containing absolute (canonical) submodule URIs
380# for the given <submodule-uri>. If the URI is relative, URIs will be
381# constructed using all <parent-repo-uri>s. Otherwise, this single URI
382# will be placed in the array.
383_git-r3_set_subrepos() {
384 debug-print-function ${FUNCNAME} "$@"
385
386 local suburl=${1}
387 subrepos=( "${@:2}" )
388
389 if [[ ${suburl} == ./* || ${suburl} == ../* ]]; then
390 # drop all possible trailing slashes for consistency
391 subrepos=( "${subrepos[@]%%/}" )
392
393 while true; do
394 if [[ ${suburl} == ./* ]]; then
395 suburl=${suburl:2}
396 elif [[ ${suburl} == ../* ]]; then
397 suburl=${suburl:3}
398
399 # XXX: correctness checking
400
401 # drop the last path component
402 subrepos=( "${subrepos[@]%/*}" )
403 # and then the trailing slashes, again
404 subrepos=( "${subrepos[@]%%/}" )
405 else
406 break
407 fi
408 done
409
410 # append the preprocessed path to the preprocessed URIs
411 subrepos=( "${subrepos[@]/%//${suburl}}")
412 else
413 subrepos=( "${suburl}" )
414 fi
415}
416
417
256# @FUNCTION: _git-r3_is_local_repo 418# @FUNCTION: _git-r3_is_local_repo
257# @USAGE: <repo-uri> 419# @USAGE: <repo-uri>
258# @INTERNAL 420# @INTERNAL
259# @DESCRIPTION: 421# @DESCRIPTION:
260# Determine whether the given URI specifies a local (on-disk) 422# Determine whether the given URI specifies a local (on-disk)
263 debug-print-function ${FUNCNAME} "$@" 425 debug-print-function ${FUNCNAME} "$@"
264 426
265 local uri=${1} 427 local uri=${1}
266 428
267 [[ ${uri} == file://* || ${uri} == /* ]] 429 [[ ${uri} == file://* || ${uri} == /* ]]
430}
431
432# @FUNCTION: _git-r3_find_head
433# @USAGE: <head-ref>
434# @INTERNAL
435# @DESCRIPTION:
436# Given a ref to which remote HEAD was fetched, try to find
437# a branch matching the commit. Expects 'git show-ref'
438# or 'git ls-remote' output on stdin.
439_git-r3_find_head() {
440 debug-print-function ${FUNCNAME} "$@"
441
442 local head_ref=${1}
443 local head_hash=$(git rev-parse --verify "${1}" || die)
444 local matching_ref
445
446 # TODO: some transports support peeking at symbolic remote refs
447 # find a way to use that rather than guessing
448
449 # (based on guess_remote_head() in git-1.9.0/remote.c)
450 local h ref
451 while read h ref; do
452 # look for matching head
453 if [[ ${h} == ${head_hash} ]]; then
454 # either take the first matching ref, or master if it is there
455 if [[ ! ${matching_ref} || ${ref} == refs/heads/master ]]; then
456 matching_ref=${ref}
457 fi
458 fi
459 done
460
461 if [[ ! ${matching_ref} ]]; then
462 die "Unable to find a matching branch for remote HEAD (${head_hash})"
463 fi
464
465 echo "${matching_ref}"
268} 466}
269 467
270# @FUNCTION: git-r3_fetch 468# @FUNCTION: git-r3_fetch
271# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]] 469# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
272# @DESCRIPTION: 470# @DESCRIPTION:
317 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" 515 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
318 516
319 local -x GIT_DIR 517 local -x GIT_DIR
320 _git-r3_set_gitdir "${repos[0]}" 518 _git-r3_set_gitdir "${repos[0]}"
321 519
520 # prepend the local mirror if applicable
521 if [[ ${EGIT_MIRROR_URI} ]]; then
522 repos=(
523 "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
524 "${repos[@]}"
525 )
526 fi
527
322 # try to fetch from the remote 528 # try to fetch from the remote
323 local r success 529 local r success saved_umask
530 if [[ ${EVCS_UMASK} ]]; then
531 saved_umask=$(umask)
532 umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
533 fi
324 for r in "${repos[@]}"; do 534 for r in "${repos[@]}"; do
325 einfo "Fetching ${r} ..." 535 einfo "Fetching \e[1m${r}\e[22m ..."
326 536
537 local fetch_command=( git fetch "${r}" )
538 local clone_type=${EGIT_CLONE_TYPE}
539
540 if [[ ${r} == https://* ]] && ! ROOT=/ has_version 'dev-vcs/git[curl]'; then
541 eerror "git-r3: fetching from https:// requested. In order to support https,"
542 eerror "dev-vcs/git needs to be built with USE=curl. Example solution:"
543 eerror
544 eerror " echo dev-vcs/git curl >> /etc/portage/package.use"
545 eerror " emerge -1v dev-vcs/git"
546 die "dev-vcs/git built with USE=curl required."
547 fi
548
549 if [[ ${r} == https://code.google.com/* ]]; then
550 # Google Code has special magic on top of git that:
551 # 1) can't handle shallow clones at all,
552 # 2) fetches duplicately when tags are pulled in with branch
553 # so automatically switch to single+tags mode.
554 if [[ ${clone_type} == shallow ]]; then
555 einfo " Google Code does not support shallow clones"
556 einfo " using \e[1mEGIT_CLONE_TYPE=single+tags\e[22m"
557 clone_type=single+tags
558 elif [[ ${clone_type} == single ]]; then
559 einfo " git-r3: Google Code does not send tags properly in 'single' mode"
560 einfo " using \e[1mEGIT_CLONE_TYPE=single+tags\e[22m"
561 clone_type=single+tags
562 fi
563 fi
564
565 if [[ ${clone_type} == mirror ]]; then
327 local fetch_command=( 566 fetch_command+=(
328 git fetch --prune "${r}" 567 --prune
329 # mirror the remote branches as local branches 568 # mirror the remote branches as local branches
330 "refs/heads/*:refs/heads/*" 569 "+refs/heads/*:refs/heads/*"
331 # pull tags explicitly in order to prune them properly 570 # pull tags explicitly in order to prune them properly
332 "refs/tags/*:refs/tags/*" 571 "+refs/tags/*:refs/tags/*"
333 # notes in case something needs them 572 # notes in case something needs them
334 "refs/notes/*:refs/notes/*" 573 "+refs/notes/*:refs/notes/*"
574 # and HEAD in case we need the default branch
575 # (we keep it in refs/git-r3 since otherwise --prune interferes)
576 "+HEAD:refs/git-r3/HEAD"
335 ) 577 )
578 else # single or shallow
579 local fetch_l fetch_r
580
581 if [[ ${remote_ref} == HEAD ]]; then
582 # HEAD
583 fetch_l=HEAD
584 elif [[ ${remote_ref} == refs/heads/* ]]; then
585 # regular branch
586 fetch_l=${remote_ref}
587 else
588 # tag or commit...
589 # let ls-remote figure it out
590 local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
591
592 # if it was a tag, ls-remote obtained a hash
593 if [[ ${tagref} ]]; then
594 # tag
595 fetch_l=refs/tags/${remote_ref}
596 else
597 # commit
598 # so we need to fetch the branch
599 if [[ ${branch} ]]; then
600 fetch_l=${branch}
601 else
602 fetch_l=HEAD
603 fi
604
605 # fetching by commit in shallow mode? can't do.
606 if [[ ${clone_type} == shallow ]]; then
607 clone_type=single
608 fi
609 fi
610 fi
611
612 if [[ ${fetch_l} == HEAD ]]; then
613 fetch_r=refs/git-r3/HEAD
614 else
615 fetch_r=${fetch_l}
616 fi
617
618 fetch_command+=(
619 "+${fetch_l}:${fetch_r}"
620 )
621
622 if [[ ${clone_type} == single+tags ]]; then
623 fetch_command+=(
624 # pull tags explicitly as requested
625 "+refs/tags/*:refs/tags/*"
626 )
627 fi
628 fi
629
630 if [[ ${clone_type} == shallow ]]; then
631 if _git-r3_is_local_repo; then
632 # '--depth 1' causes sandbox violations with local repos
633 # bug #491260
634 clone_type=single
635 elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
636 then
637 # use '--depth 1' when fetching a new branch
638 fetch_command+=( --depth 1 )
639 fi
640 else # non-shallow mode
641 if [[ -f ${GIT_DIR}/shallow ]]; then
642 fetch_command+=( --unshallow )
643 fi
644 fi
336 645
337 set -- "${fetch_command[@]}" 646 set -- "${fetch_command[@]}"
338 echo "${@}" >&2 647 echo "${@}" >&2
339 if "${@}"; then 648 if "${@}"; then
649 if [[ ${clone_type} == mirror ]]; then
650 # find remote HEAD and update our HEAD properly
651 git symbolic-ref HEAD \
652 "$(_git-r3_find_head refs/git-r3/HEAD \
653 < <(git show-ref --heads || die))" \
654 || die "Unable to update HEAD"
655 else # single or shallow
656 if [[ ${fetch_l} == HEAD ]]; then
657 # find out what branch we fetched as HEAD
658 local head_branch=$(_git-r3_find_head \
659 refs/git-r3/HEAD \
660 < <(git ls-remote --heads "${r}" || die))
661
662 # and move it to its regular place
663 git update-ref --no-deref "${head_branch}" \
664 refs/git-r3/HEAD \
665 || die "Unable to sync HEAD branch ${head_branch}"
666 git symbolic-ref HEAD "${head_branch}" \
667 || die "Unable to update HEAD"
668 fi
669 fi
670
340 # now let's see what the user wants from us 671 # now let's see what the user wants from us
341 local full_remote_ref=$( 672 local full_remote_ref=$(
342 git rev-parse --verify --symbolic-full-name "${remote_ref}" 673 git rev-parse --verify --symbolic-full-name "${remote_ref}"
343 ) 674 )
344 675
358 689
359 success=1 690 success=1
360 break 691 break
361 fi 692 fi
362 done 693 done
694 if [[ ${saved_umask} ]]; then
695 umask "${saved_umask}" || die
696 fi
363 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" 697 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
698
699 # submodules can reference commits in any branch
700 # always use the 'clone' mode to accomodate that, bug #503332
701 local EGIT_CLONE_TYPE=mirror
364 702
365 # recursively fetch submodules 703 # recursively fetch submodules
366 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then 704 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
367 local submodules 705 local submodules
368 _git-r3_set_submodules \ 706 _git-r3_set_submodules \
370 708
371 while [[ ${submodules[@]} ]]; do 709 while [[ ${submodules[@]} ]]; do
372 local subname=${submodules[0]} 710 local subname=${submodules[0]}
373 local url=${submodules[1]} 711 local url=${submodules[1]}
374 local path=${submodules[2]} 712 local path=${submodules[2]}
713
714 # use only submodules for which path does exist
715 # (this is in par with 'git submodule'), bug #551100
716 # note: git cat-file does not work for submodules
717 if [[ $(git ls-tree -d "${local_ref}" "${path}") ]]
718 then
375 local commit=$(git rev-parse "${local_ref}:${path}") 719 local commit=$(git rev-parse "${local_ref}:${path}" || die)
376 720
377 if [[ ! ${commit} ]]; then 721 if [[ ! ${commit} ]]; then
378 die "Unable to get commit id for submodule ${subname}" 722 die "Unable to get commit id for submodule ${subname}"
379 fi 723 fi
380 if [[ ${url} == ./* || ${url} == ../* ]]; then
381 local subrepos=( "${repos[@]/%//${url}}" )
382 else
383 local subrepos=( "${url}" )
384 fi
385 724
725 local subrepos
726 _git-r3_set_subrepos "${url}" "${repos[@]}"
727
386 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}" 728 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
729 fi
387 730
388 submodules=( "${submodules[@]:3}" ) # shift 731 submodules=( "${submodules[@]:3}" ) # shift
389 done 732 done
390 fi 733 fi
391} 734}
426 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}} 769 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
427 770
428 local -x GIT_DIR 771 local -x GIT_DIR
429 _git-r3_set_gitdir "${repos[0]}" 772 _git-r3_set_gitdir "${repos[0]}"
430 773
431 einfo "Checking out ${repos[0]} to ${out_dir} ..." 774 einfo "Checking out \e[1m${repos[0]}\e[22m to \e[1m${out_dir}\[e22m ..."
432 775
433 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then 776 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
434 if [[ ${EVCS_OFFLINE} ]]; then 777 if [[ ${EVCS_OFFLINE} ]]; then
435 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE." 778 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
436 else 779 else
442 ) 785 )
443 local new_commit_id=$( 786 local new_commit_id=$(
444 git rev-parse --verify refs/git-r3/"${local_id}"/__main__ 787 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
445 ) 788 )
446 789
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() { 790 git-r3_sub_checkout() {
452 local orig_repo=${GIT_DIR} 791 local orig_repo=${GIT_DIR}
453 local -x GIT_DIR=${out_dir}/.git 792 local -x GIT_DIR=${out_dir}/.git
454 local -x GIT_WORK_TREE=${out_dir} 793 local -x GIT_WORK_TREE=${out_dir}
455 794
456 # pull notes 795 mkdir -p "${out_dir}" || die
457 git fetch "${orig_repo}" "refs/notes/*:refs/notes/*" || die 796
797 # use git init+fetch instead of clone since the latter doesn't like
798 # non-empty directories.
799
800 git init --quiet || die
801 # setup 'alternates' to avoid copying objects
802 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
803 # now copy the refs
804 # [htn]* safely catches heads, tags, notes without complaining
805 # on non-existing ones, and omits internal 'git-r3' ref
806 cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die
807
808 # (no need to copy HEAD, we will set it via checkout)
809
810 if [[ -f ${orig_repo}/shallow ]]; then
811 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
812 fi
458 813
459 set -- git checkout --quiet 814 set -- git checkout --quiet
460 if [[ ${remote_ref} ]]; then 815 if [[ ${remote_ref} ]]; then
461 set -- "${@}" "${remote_ref#refs/heads/}" 816 set -- "${@}" "${remote_ref#refs/heads/}"
462 else 817 else
500 while [[ ${submodules[@]} ]]; do 855 while [[ ${submodules[@]} ]]; do
501 local subname=${submodules[0]} 856 local subname=${submodules[0]}
502 local url=${submodules[1]} 857 local url=${submodules[1]}
503 local path=${submodules[2]} 858 local path=${submodules[2]}
504 859
505 if [[ ${url} == ./* || ${url} == ../* ]]; then 860 # use only submodules for which path does exist
506 url=${repos[0]%%/}/${url} 861 # (this is in par with 'git submodule'), bug #551100
507 fi 862 if [[ -d ${out_dir}/${path} ]]; then
863 local subrepos
864 _git-r3_set_subrepos "${url}" "${repos[@]}"
508 865
509 git-r3_checkout "${url}" "${out_dir}/${path}" \ 866 git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \
510 "${local_id}/${subname}" 867 "${local_id}/${subname}"
868 fi
511 869
512 submodules=( "${submodules[@]:3}" ) # shift 870 submodules=( "${submodules[@]:3}" ) # shift
513 done 871 done
514 fi 872 fi
515 873
556 914
557 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" 915 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
558 916
559 local r success 917 local r success
560 for r in "${repos[@]}"; do 918 for r in "${repos[@]}"; do
561 einfo "Peeking ${remote_ref} on ${r} ..." >&2 919 einfo "Peeking \e[1m${remote_ref}\e[22m on \e[1m${r}\e[22m ..." >&2
562 920
563 local is_branch lookup_ref 921 local is_branch lookup_ref
564 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]] 922 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
565 then 923 then
566 is_branch=1 924 is_branch=1
606 git-r3_src_fetch 964 git-r3_src_fetch
607 git-r3_checkout 965 git-r3_checkout
608} 966}
609 967
610# https://bugs.gentoo.org/show_bug.cgi?id=482666 968# https://bugs.gentoo.org/show_bug.cgi?id=482666
611git-r3_pkg_outofdate() { 969git-r3_pkg_needrebuild() {
612 debug-print-function ${FUNCNAME} "$@" 970 debug-print-function ${FUNCNAME} "$@"
613 971
614 local new_commit_id=$(git-r3_peek_remote_ref) 972 local new_commit_id=$(git-r3_peek_remote_ref)
615 ewarn "old: ${EGIT_VERSION}" 973 [[ ${new_commit_id} && ${EGIT_VERSION} ]] || die "Lookup failed"
616 ewarn "new: ${new_commit_id}" 974
617 [[ ${new_commit_id} && ${old_commit_id} ]] || return 2 975 if [[ ${EGIT_VERSION} != ${new_commit_id} ]]; then
976 einfo "Update from \e[1m${EGIT_VERSION}\e[22m to \e[1m${new_commit_id}\e[22m"
977 else
978 einfo "Local and remote at \e[1m${EGIT_VERSION}\e[22m"
979 fi
618 980
619 [[ ${EGIT_VERSION} != ${new_commit_id} ]] 981 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
620} 982}
983
984# 'export' locally until this gets into EAPI
985pkg_needrebuild() { git-r3_pkg_needrebuild; }
621 986
622_GIT_R3=1 987_GIT_R3=1
623fi 988fi

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

  ViewVC Help
Powered by ViewVC 1.1.20