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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.47 - (show annotations) (download)
Mon Jul 28 14:13:50 2014 UTC (2 months ago) by mgorny
Branch: MAIN
CVS Tags: HEAD
Changes since 1.46: +3 -2 lines
Mention git-clone man page for URI syntax, bug #511636.

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.46 2014/07/28 14:12:22 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 # 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
89 # @ECLASS-VARIABLE: EGIT3_STORE_DIR
90 # @DESCRIPTION:
91 # Storage directory for git sources.
92 #
93 # This is intended to be set by user in make.conf. Ebuilds must not set
94 # it.
95 #
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
111
112 # @ECLASS-VARIABLE: EGIT_REPO_URI
113 # @REQUIRED
114 # @DESCRIPTION:
115 # URIs to the repository, e.g. git://foo, https://foo. If multiple URIs
116 # are provided, the eclass will consider them as fallback URIs to try
117 # if the first URI does not work. For supported URI syntaxes, read up
118 # the manpage for git-clone(1).
119 #
120 # It can be overriden via env using ${PN}_LIVE_REPO variable.
121 #
122 # Can be a whitespace-separated list or an array.
123 #
124 # Example:
125 # @CODE
126 # EGIT_REPO_URI="git://a/b.git https://c/d.git"
127 # @CODE
128
129 # @ECLASS-VARIABLE: EVCS_OFFLINE
130 # @DEFAULT_UNSET
131 # @DESCRIPTION:
132 # If non-empty, this variable prevents any online operations.
133
134 # @ECLASS-VARIABLE: EGIT_BRANCH
135 # @DEFAULT_UNSET
136 # @DESCRIPTION:
137 # The branch name to check out. If unset, the upstream default (HEAD)
138 # will be used.
139 #
140 # It can be overriden via env using ${PN}_LIVE_BRANCH variable.
141
142 # @ECLASS-VARIABLE: EGIT_COMMIT
143 # @DEFAULT_UNSET
144 # @DESCRIPTION:
145 # The tag name or commit identifier to check out. If unset, newest
146 # commit from the branch will be used. If set, EGIT_BRANCH will
147 # be ignored.
148 #
149 # It can be overriden via env using ${PN}_LIVE_COMMIT variable.
150
151 # @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
152 # @DESCRIPTION:
153 # The directory to check the git sources out to.
154 #
155 # EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
156
157 # @FUNCTION: _git-r3_env_setup
158 # @INTERNAL
159 # @DESCRIPTION:
160 # Set the eclass variables as necessary for operation. This can involve
161 # setting EGIT_* to defaults or ${PN}_LIVE_* variables.
162 _git-r3_env_setup() {
163 debug-print-function ${FUNCNAME} "$@"
164
165 # check the clone type
166 case "${EGIT_CLONE_TYPE}" in
167 mirror|single+tags|single|shallow)
168 ;;
169 *)
170 die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
171 esac
172 case "${EGIT_MIN_CLONE_TYPE}" in
173 shallow)
174 ;;
175 single)
176 if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then
177 einfo "git-r3: ebuild needs to be cloned in 'single' mode, adjusting"
178 EGIT_CLONE_TYPE=single
179 fi
180 ;;
181 single+tags)
182 if [[ ${EGIT_CLONE_TYPE} == shallow || ${EGIT_CLONE_TYPE} == single ]]; then
183 einfo "git-r3: ebuild needs to be cloned in 'single+tags' mode, adjusting"
184 EGIT_CLONE_TYPE=single+tags
185 fi
186 ;;
187 mirror)
188 if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then
189 einfo "git-r3: ebuild needs to be cloned in 'mirror' mode, adjusting"
190 EGIT_CLONE_TYPE=mirror
191 fi
192 ;;
193 *)
194 die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
195 esac
196
197 local esc_pn livevar
198 esc_pn=${PN//[-+]/_}
199
200 livevar=${esc_pn}_LIVE_REPO
201 EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}}
202 [[ ${!livevar} ]] \
203 && ewarn "Using ${livevar}, no support will be provided"
204
205 livevar=${esc_pn}_LIVE_BRANCH
206 EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}}
207 [[ ${!livevar} ]] \
208 && ewarn "Using ${livevar}, no support will be provided"
209
210 livevar=${esc_pn}_LIVE_COMMIT
211 EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}}
212 [[ ${!livevar} ]] \
213 && ewarn "Using ${livevar}, no support will be provided"
214
215 # Migration helpers. Remove them when git-2 is removed.
216
217 if [[ ${EGIT_SOURCEDIR} ]]; then
218 eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating"
219 eerror "your ebuild, please check whether the variable is necessary at all"
220 eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}."
221 eerror "Therefore, proper setting of S may be sufficient."
222 die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR."
223 fi
224
225 if [[ ${EGIT_MASTER} ]]; then
226 eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)"
227 eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH"
228 eerror "as necessary."
229 die "EGIT_MASTER has been removed."
230 fi
231
232 if [[ ${EGIT_HAS_SUBMODULES} ]]; then
233 eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs"
234 eerror "to switch the clone type in order to support submodules and therefore"
235 eerror "submodules are detected and fetched automatically."
236 die "EGIT_HAS_SUBMODULES is no longer necessary."
237 fi
238
239 if [[ ${EGIT_PROJECT} ]]; then
240 eerror "EGIT_PROJECT has been removed. Instead, the eclass determines"
241 eerror "the local clone path using path in canonical EGIT_REPO_URI."
242 eerror "If the current algorithm causes issues for you, please report a bug."
243 die "EGIT_PROJECT is no longer necessary."
244 fi
245
246 if [[ ${EGIT_BOOTSTRAP} ]]; then
247 eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()"
248 eerror "instead."
249 die "EGIT_BOOTSTRAP has been removed."
250 fi
251
252 if [[ ${EGIT_NOUNPACK} ]]; then
253 eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default"
254 eerror "unpack function. If necessary, please declare proper src_unpack()."
255 die "EGIT_NOUNPACK has been removed."
256 fi
257 }
258
259 # @FUNCTION: _git-r3_set_gitdir
260 # @USAGE: <repo-uri>
261 # @INTERNAL
262 # @DESCRIPTION:
263 # Obtain the local repository path and set it as GIT_DIR. Creates
264 # a new repository if necessary.
265 #
266 # <repo-uri> may be used to compose the path. It should therefore be
267 # a canonical URI to the repository.
268 _git-r3_set_gitdir() {
269 debug-print-function ${FUNCNAME} "$@"
270
271 local repo_name=${1#*://*/}
272
273 # strip the trailing slash
274 repo_name=${repo_name%/}
275
276 # strip common prefixes to make paths more likely to match
277 # e.g. git://X/Y.git vs https://X/git/Y.git
278 # (but just one of the prefixes)
279 case "${repo_name}" in
280 # gnome.org... who else?
281 browse/*) repo_name=${repo_name#browse/};;
282 # cgit can proxy requests to git
283 cgit/*) repo_name=${repo_name#cgit/};;
284 # pretty common
285 git/*) repo_name=${repo_name#git/};;
286 # gentoo.org
287 gitroot/*) repo_name=${repo_name#gitroot/};;
288 # google code, sourceforge
289 p/*) repo_name=${repo_name#p/};;
290 # kernel.org
291 pub/scm/*) repo_name=${repo_name#pub/scm/};;
292 esac
293 # ensure a .git suffix, same reason
294 repo_name=${repo_name%.git}.git
295 # now replace all the slashes
296 repo_name=${repo_name//\//_}
297
298 local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
299 : ${EGIT3_STORE_DIR:=${distdir}/git3-src}
300
301 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
302
303 if [[ ! -d ${EGIT3_STORE_DIR} ]]; then
304 (
305 addwrite /
306 mkdir -p "${EGIT3_STORE_DIR}" || die
307 ) || die "Unable to create ${EGIT3_STORE_DIR}"
308 fi
309
310 addwrite "${EGIT3_STORE_DIR}"
311 if [[ ! -d ${GIT_DIR} ]]; then
312 mkdir "${GIT_DIR}" || die
313 git init --bare || die
314 fi
315 }
316
317 # @FUNCTION: _git-r3_set_submodules
318 # @USAGE: <file-contents>
319 # @INTERNAL
320 # @DESCRIPTION:
321 # Parse .gitmodules contents passed as <file-contents>
322 # as in "$(cat .gitmodules)"). Composes a 'submodules' array that
323 # contains in order (name, URL, path) for each submodule.
324 _git-r3_set_submodules() {
325 debug-print-function ${FUNCNAME} "$@"
326
327 local data=${1}
328
329 # ( name url path ... )
330 submodules=()
331
332 local l
333 while read l; do
334 # submodule.<path>.path=<path>
335 # submodule.<path>.url=<url>
336 [[ ${l} == submodule.*.url=* ]] || continue
337
338 l=${l#submodule.}
339 local subname=${l%%.url=*}
340
341 # skip modules that have 'update = none', bug #487262.
342 local upd=$(echo "${data}" | git config -f /dev/fd/0 \
343 submodule."${subname}".update)
344 [[ ${upd} == none ]] && continue
345
346 submodules+=(
347 "${subname}"
348 "$(echo "${data}" | git config -f /dev/fd/0 \
349 submodule."${subname}".url || die)"
350 "$(echo "${data}" | git config -f /dev/fd/0 \
351 submodule."${subname}".path || die)"
352 )
353 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
354 }
355
356 # @FUNCTION: _git-r3_set_subrepos
357 # @USAGE: <submodule-uri> <parent-repo-uri>...
358 # @INTERNAL
359 # @DESCRIPTION:
360 # Create 'subrepos' array containing absolute (canonical) submodule URIs
361 # for the given <submodule-uri>. If the URI is relative, URIs will be
362 # constructed using all <parent-repo-uri>s. Otherwise, this single URI
363 # will be placed in the array.
364 _git-r3_set_subrepos() {
365 debug-print-function ${FUNCNAME} "$@"
366
367 local suburl=${1}
368 subrepos=( "${@:2}" )
369
370 if [[ ${suburl} == ./* || ${suburl} == ../* ]]; then
371 # drop all possible trailing slashes for consistency
372 subrepos=( "${subrepos[@]%%/}" )
373
374 while true; do
375 if [[ ${suburl} == ./* ]]; then
376 suburl=${suburl:2}
377 elif [[ ${suburl} == ../* ]]; then
378 suburl=${suburl:3}
379
380 # XXX: correctness checking
381
382 # drop the last path component
383 subrepos=( "${subrepos[@]%/*}" )
384 # and then the trailing slashes, again
385 subrepos=( "${subrepos[@]%%/}" )
386 else
387 break
388 fi
389 done
390
391 # append the preprocessed path to the preprocessed URIs
392 subrepos=( "${subrepos[@]/%//${suburl}}")
393 else
394 subrepos=( "${suburl}" )
395 fi
396 }
397
398
399 # @FUNCTION: _git-r3_is_local_repo
400 # @USAGE: <repo-uri>
401 # @INTERNAL
402 # @DESCRIPTION:
403 # Determine whether the given URI specifies a local (on-disk)
404 # repository.
405 _git-r3_is_local_repo() {
406 debug-print-function ${FUNCNAME} "$@"
407
408 local uri=${1}
409
410 [[ ${uri} == file://* || ${uri} == /* ]]
411 }
412
413 # @FUNCTION: _git-r3_find_head
414 # @USAGE: <head-ref>
415 # @INTERNAL
416 # @DESCRIPTION:
417 # Given a ref to which remote HEAD was fetched, try to find
418 # a branch matching the commit. Expects 'git show-ref'
419 # or 'git ls-remote' output on stdin.
420 _git-r3_find_head() {
421 debug-print-function ${FUNCNAME} "$@"
422
423 local head_ref=${1}
424 local head_hash=$(git rev-parse --verify "${1}" || die)
425 local matching_ref
426
427 # TODO: some transports support peeking at symbolic remote refs
428 # find a way to use that rather than guessing
429
430 # (based on guess_remote_head() in git-1.9.0/remote.c)
431 local h ref
432 while read h ref; do
433 # look for matching head
434 if [[ ${h} == ${head_hash} ]]; then
435 # either take the first matching ref, or master if it is there
436 if [[ ! ${matching_ref} || ${ref} == refs/heads/master ]]; then
437 matching_ref=${ref}
438 fi
439 fi
440 done
441
442 if [[ ! ${matching_ref} ]]; then
443 die "Unable to find a matching branch for remote HEAD (${head_hash})"
444 fi
445
446 echo "${matching_ref}"
447 }
448
449 # @FUNCTION: git-r3_fetch
450 # @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
451 # @DESCRIPTION:
452 # Fetch new commits to the local clone of repository.
453 #
454 # <repo-uri> specifies the repository URIs to fetch from, as a space-
455 # -separated list. The first URI will be used as repository group
456 # identifier and therefore must be used consistently. When not
457 # specified, defaults to ${EGIT_REPO_URI}.
458 #
459 # <remote-ref> specifies the remote ref or commit id to fetch.
460 # It is preferred to use 'refs/heads/<branch-name>' for branches
461 # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
462 # for upstream default branch and hexadecimal commit SHA1. Defaults
463 # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
464 # is set to a non-null value.
465 #
466 # <local-id> specifies the local branch identifier that will be used to
467 # locally store the fetch result. It should be unique to multiple
468 # fetches within the repository that can be performed at the same time
469 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
470 # This default should be fine unless you are fetching multiple trees
471 # from the same repository in the same ebuild.
472 #
473 # The fetch operation will affect the EGIT_STORE only. It will not touch
474 # the working copy, nor export any environment variables.
475 # If the repository contains submodules, they will be fetched
476 # recursively.
477 git-r3_fetch() {
478 debug-print-function ${FUNCNAME} "$@"
479
480 [[ ${EVCS_OFFLINE} ]] && return
481
482 local repos
483 if [[ ${1} ]]; then
484 repos=( ${1} )
485 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
486 repos=( "${EGIT_REPO_URI[@]}" )
487 else
488 repos=( ${EGIT_REPO_URI} )
489 fi
490
491 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
492 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
493 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
494 local local_ref=refs/git-r3/${local_id}/__main__
495
496 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
497
498 local -x GIT_DIR
499 _git-r3_set_gitdir "${repos[0]}"
500
501 # prepend the local mirror if applicable
502 if [[ ${EGIT_MIRROR_URI} ]]; then
503 repos=(
504 "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
505 "${repos[@]}"
506 )
507 fi
508
509 # try to fetch from the remote
510 local r success
511 for r in "${repos[@]}"; do
512 einfo "Fetching ${r} ..."
513
514 local fetch_command=( git fetch "${r}" )
515 local clone_type=${EGIT_CLONE_TYPE}
516
517 if [[ ${r} == https://* ]] && ! ROOT=/ has_version 'dev-vcs/git[curl]'; then
518 eerror "git-r3: fetching from https:// requested. In order to support https,"
519 eerror "dev-vcs/git needs to be built with USE=curl. Example solution:"
520 eerror
521 eerror " echo dev-vcs/git curl >> /etc/portage/package.use"
522 eerror " emerge -1v dev-vcs/git"
523 die "dev-vcs/git built with USE=curl required."
524 fi
525
526 if [[ ${r} == https://code.google.com/* ]]; then
527 # Google Code has special magic on top of git that:
528 # 1) can't handle shallow clones at all,
529 # 2) fetches duplicately when tags are pulled in with branch
530 # so automatically switch to single+tags mode.
531 if [[ ${clone_type} == shallow ]]; then
532 einfo " Google Code does not support shallow clones"
533 einfo " using EGIT_CLONE_TYPE=single+tags"
534 clone_type=single+tags
535 elif [[ ${clone_type} == single ]]; then
536 einfo " git-r3: Google Code does not send tags properly in 'single' mode"
537 einfo " using EGIT_CLONE_TYPE=single+tags"
538 clone_type=single+tags
539 fi
540 fi
541
542 if [[ ${clone_type} == mirror ]]; then
543 fetch_command+=(
544 --prune
545 # mirror the remote branches as local branches
546 "+refs/heads/*:refs/heads/*"
547 # pull tags explicitly in order to prune them properly
548 "+refs/tags/*:refs/tags/*"
549 # notes in case something needs them
550 "+refs/notes/*:refs/notes/*"
551 # and HEAD in case we need the default branch
552 # (we keep it in refs/git-r3 since otherwise --prune interferes)
553 "+HEAD:refs/git-r3/HEAD"
554 )
555 else # single or shallow
556 local fetch_l fetch_r
557
558 if [[ ${remote_ref} == HEAD ]]; then
559 # HEAD
560 fetch_l=HEAD
561 elif [[ ${remote_ref} == refs/heads/* ]]; then
562 # regular branch
563 fetch_l=${remote_ref}
564 else
565 # tag or commit...
566 # let ls-remote figure it out
567 local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
568
569 # if it was a tag, ls-remote obtained a hash
570 if [[ ${tagref} ]]; then
571 # tag
572 fetch_l=refs/tags/${remote_ref}
573 else
574 # commit
575 # so we need to fetch the branch
576 if [[ ${branch} ]]; then
577 fetch_l=${branch}
578 else
579 fetch_l=HEAD
580 fi
581
582 # fetching by commit in shallow mode? can't do.
583 if [[ ${clone_type} == shallow ]]; then
584 clone_type=single
585 fi
586 fi
587 fi
588
589 if [[ ${fetch_l} == HEAD ]]; then
590 fetch_r=refs/git-r3/HEAD
591 else
592 fetch_r=${fetch_l}
593 fi
594
595 fetch_command+=(
596 "+${fetch_l}:${fetch_r}"
597 )
598
599 if [[ ${clone_type} == single+tags ]]; then
600 fetch_command+=(
601 # pull tags explicitly as requested
602 "+refs/tags/*:refs/tags/*"
603 )
604 fi
605 fi
606
607 if [[ ${clone_type} == shallow ]]; then
608 if _git-r3_is_local_repo; then
609 # '--depth 1' causes sandbox violations with local repos
610 # bug #491260
611 clone_type=single
612 elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
613 then
614 # use '--depth 1' when fetching a new branch
615 fetch_command+=( --depth 1 )
616 fi
617 else # non-shallow mode
618 if [[ -f ${GIT_DIR}/shallow ]]; then
619 fetch_command+=( --unshallow )
620 fi
621 fi
622
623 set -- "${fetch_command[@]}"
624 echo "${@}" >&2
625 if "${@}"; then
626 if [[ ${clone_type} == mirror ]]; then
627 # find remote HEAD and update our HEAD properly
628 git symbolic-ref HEAD \
629 "$(_git-r3_find_head refs/git-r3/HEAD \
630 < <(git show-ref --heads || die))" \
631 || die "Unable to update HEAD"
632 else # single or shallow
633 if [[ ${fetch_l} == HEAD ]]; then
634 # find out what branch we fetched as HEAD
635 local head_branch=$(_git-r3_find_head \
636 refs/git-r3/HEAD \
637 < <(git ls-remote --heads "${r}" || die))
638
639 # and move it to its regular place
640 git update-ref --no-deref "${head_branch}" \
641 refs/git-r3/HEAD \
642 || die "Unable to sync HEAD branch ${head_branch}"
643 git symbolic-ref HEAD "${head_branch}" \
644 || die "Unable to update HEAD"
645 fi
646 fi
647
648 # now let's see what the user wants from us
649 local full_remote_ref=$(
650 git rev-parse --verify --symbolic-full-name "${remote_ref}"
651 )
652
653 if [[ ${full_remote_ref} ]]; then
654 # when we are given a ref, create a symbolic ref
655 # so that we preserve the actual argument
656 set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
657 else
658 # otherwise, we were likely given a commit id
659 set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
660 fi
661
662 echo "${@}" >&2
663 if ! "${@}"; then
664 die "Referencing ${remote_ref} failed (wrong ref?)."
665 fi
666
667 success=1
668 break
669 fi
670 done
671 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
672
673 # submodules can reference commits in any branch
674 # always use the 'clone' mode to accomodate that, bug #503332
675 local EGIT_CLONE_TYPE=mirror
676
677 # recursively fetch submodules
678 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
679 local submodules
680 _git-r3_set_submodules \
681 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
682
683 while [[ ${submodules[@]} ]]; do
684 local subname=${submodules[0]}
685 local url=${submodules[1]}
686 local path=${submodules[2]}
687 local commit=$(git rev-parse "${local_ref}:${path}")
688
689 if [[ ! ${commit} ]]; then
690 die "Unable to get commit id for submodule ${subname}"
691 fi
692
693 local subrepos
694 _git-r3_set_subrepos "${url}" "${repos[@]}"
695
696 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
697
698 submodules=( "${submodules[@]:3}" ) # shift
699 done
700 fi
701 }
702
703 # @FUNCTION: git-r3_checkout
704 # @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
705 # @DESCRIPTION:
706 # Check the previously fetched tree to the working copy.
707 #
708 # <repo-uri> specifies the repository URIs, as a space-separated list.
709 # The first URI will be used as repository group identifier
710 # and therefore must be used consistently with git-r3_fetch.
711 # The remaining URIs are not used and therefore may be omitted.
712 # When not specified, defaults to ${EGIT_REPO_URI}.
713 #
714 # <checkout-path> specifies the path to place the checkout. It defaults
715 # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
716 #
717 # <local-id> needs to specify the local identifier that was used
718 # for respective git-r3_fetch.
719 #
720 # The checkout operation will write to the working copy, and export
721 # the repository state into the environment. If the repository contains
722 # submodules, they will be checked out recursively.
723 git-r3_checkout() {
724 debug-print-function ${FUNCNAME} "$@"
725
726 local repos
727 if [[ ${1} ]]; then
728 repos=( ${1} )
729 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
730 repos=( "${EGIT_REPO_URI[@]}" )
731 else
732 repos=( ${EGIT_REPO_URI} )
733 fi
734
735 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
736 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
737
738 local -x GIT_DIR
739 _git-r3_set_gitdir "${repos[0]}"
740
741 einfo "Checking out ${repos[0]} to ${out_dir} ..."
742
743 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
744 if [[ ${EVCS_OFFLINE} ]]; then
745 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
746 else
747 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
748 fi
749 fi
750 local remote_ref=$(
751 git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
752 )
753 local new_commit_id=$(
754 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
755 )
756
757 git-r3_sub_checkout() {
758 local orig_repo=${GIT_DIR}
759 local -x GIT_DIR=${out_dir}/.git
760 local -x GIT_WORK_TREE=${out_dir}
761
762 mkdir -p "${out_dir}" || die
763
764 # use git init+fetch instead of clone since the latter doesn't like
765 # non-empty directories.
766
767 git init --quiet || die
768 # setup 'alternates' to avoid copying objects
769 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
770 # now copy the refs
771 # [htn]* safely catches heads, tags, notes without complaining
772 # on non-existing ones, and omits internal 'git-r3' ref
773 cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die
774
775 # (no need to copy HEAD, we will set it via checkout)
776
777 if [[ -f ${orig_repo}/shallow ]]; then
778 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
779 fi
780
781 set -- git checkout --quiet
782 if [[ ${remote_ref} ]]; then
783 set -- "${@}" "${remote_ref#refs/heads/}"
784 else
785 set -- "${@}" "${new_commit_id}"
786 fi
787 echo "${@}" >&2
788 "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
789 }
790 git-r3_sub_checkout
791
792 local old_commit_id=$(
793 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
794 )
795 if [[ ! ${old_commit_id} ]]; then
796 echo "GIT NEW branch -->"
797 echo " repository: ${repos[0]}"
798 echo " at the commit: ${new_commit_id}"
799 else
800 # diff against previous revision
801 echo "GIT update -->"
802 echo " repository: ${repos[0]}"
803 # write out message based on the revisions
804 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
805 echo " updating from commit: ${old_commit_id}"
806 echo " to commit: ${new_commit_id}"
807
808 git --no-pager diff --stat \
809 ${old_commit_id}..${new_commit_id}
810 else
811 echo " at the commit: ${new_commit_id}"
812 fi
813 fi
814 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
815
816 # recursively checkout submodules
817 if [[ -f ${out_dir}/.gitmodules ]]; then
818 local submodules
819 _git-r3_set_submodules \
820 "$(<"${out_dir}"/.gitmodules)"
821
822 while [[ ${submodules[@]} ]]; do
823 local subname=${submodules[0]}
824 local url=${submodules[1]}
825 local path=${submodules[2]}
826 local subrepos
827 _git-r3_set_subrepos "${url}" "${repos[@]}"
828
829 git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \
830 "${local_id}/${subname}"
831
832 submodules=( "${submodules[@]:3}" ) # shift
833 done
834 fi
835
836 # keep this *after* submodules
837 export EGIT_DIR=${GIT_DIR}
838 export EGIT_VERSION=${new_commit_id}
839 }
840
841 # @FUNCTION: git-r3_peek_remote_ref
842 # @USAGE: [<repo-uri> [<remote-ref>]]
843 # @DESCRIPTION:
844 # Peek the reference in the remote repository and print the matching
845 # (newest) commit SHA1.
846 #
847 # <repo-uri> specifies the repository URIs to fetch from, as a space-
848 # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
849 #
850 # <remote-ref> specifies the remote ref to peek. It is preferred to use
851 # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
852 # for tags. Alternatively, 'HEAD' may be used for upstream default
853 # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
854 # 'HEAD' that is set to a non-null value.
855 #
856 # The operation will be done purely on the remote, without using local
857 # storage. If commit SHA1 is provided as <remote-ref>, the function will
858 # fail due to limitations of git protocol.
859 #
860 # On success, the function returns 0 and writes hexadecimal commit SHA1
861 # to stdout. On failure, the function returns 1.
862 git-r3_peek_remote_ref() {
863 debug-print-function ${FUNCNAME} "$@"
864
865 local repos
866 if [[ ${1} ]]; then
867 repos=( ${1} )
868 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
869 repos=( "${EGIT_REPO_URI[@]}" )
870 else
871 repos=( ${EGIT_REPO_URI} )
872 fi
873
874 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
875 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
876
877 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
878
879 local r success
880 for r in "${repos[@]}"; do
881 einfo "Peeking ${remote_ref} on ${r} ..." >&2
882
883 local is_branch lookup_ref
884 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
885 then
886 is_branch=1
887 lookup_ref=${remote_ref}
888 else
889 # ls-remote by commit is going to fail anyway,
890 # so we may as well pass refs/tags/ABCDEF...
891 lookup_ref=refs/tags/${remote_ref}
892 fi
893
894 # split on whitespace
895 local ref=(
896 $(git ls-remote "${r}" "${lookup_ref}")
897 )
898
899 if [[ ${ref[0]} ]]; then
900 echo "${ref[0]}"
901 return 0
902 fi
903 done
904
905 return 1
906 }
907
908 git-r3_src_fetch() {
909 debug-print-function ${FUNCNAME} "$@"
910
911 if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
912 ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
913 ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
914 ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
915 ewarn "when git-2 eclass becomes deprecated."
916 fi
917
918 _git-r3_env_setup
919 git-r3_fetch
920 }
921
922 git-r3_src_unpack() {
923 debug-print-function ${FUNCNAME} "$@"
924
925 _git-r3_env_setup
926 git-r3_src_fetch
927 git-r3_checkout
928 }
929
930 # https://bugs.gentoo.org/show_bug.cgi?id=482666
931 git-r3_pkg_outofdate() {
932 debug-print-function ${FUNCNAME} "$@"
933
934 local new_commit_id=$(git-r3_peek_remote_ref)
935 ewarn "old: ${EGIT_VERSION}"
936 ewarn "new: ${new_commit_id}"
937 [[ ${new_commit_id} && ${old_commit_id} ]] || return 2
938
939 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
940 }
941
942 _GIT_R3=1
943 fi

  ViewVC Help
Powered by ViewVC 1.1.20