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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.37 - (show annotations) (download)
Sun Mar 2 11:50:23 2014 UTC (6 months, 2 weeks ago) by mgorny
Branch: MAIN
Changes since 1.36: +7 -3 lines
Do not try shallow clones on local repositories.

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

  ViewVC Help
Powered by ViewVC 1.1.20