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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.48 - (show annotations) (download)
Wed Feb 4 09:44:24 2015 UTC (3 months ago) by ulm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.47: +29 -3 lines
Respect the EVCS_UMASK variable to override the default umask when writing to the repository.

1 # Copyright 1999-2015 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.47 2014/07/28 14:13:50 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: 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
145 # @ECLASS-VARIABLE: EGIT_BRANCH
146 # @DEFAULT_UNSET
147 # @DESCRIPTION:
148 # The branch name to check out. If unset, the upstream default (HEAD)
149 # will be used.
150 #
151 # It can be overriden via env using ${PN}_LIVE_BRANCH variable.
152
153 # @ECLASS-VARIABLE: EGIT_COMMIT
154 # @DEFAULT_UNSET
155 # @DESCRIPTION:
156 # The tag name or commit identifier to check out. If unset, newest
157 # commit from the branch will be used. If set, EGIT_BRANCH will
158 # be ignored.
159 #
160 # It can be overriden via env using ${PN}_LIVE_COMMIT variable.
161
162 # @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
163 # @DESCRIPTION:
164 # The directory to check the git sources out to.
165 #
166 # EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
167
168 # @FUNCTION: _git-r3_env_setup
169 # @INTERNAL
170 # @DESCRIPTION:
171 # Set the eclass variables as necessary for operation. This can involve
172 # setting EGIT_* to defaults or ${PN}_LIVE_* variables.
173 _git-r3_env_setup() {
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 'single' 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 'single+tags' 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 'mirror' mode, adjusting"
201 EGIT_CLONE_TYPE=mirror
202 fi
203 ;;
204 *)
205 die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}"
206 esac
207
208 local esc_pn livevar
209 esc_pn=${PN//[-+]/_}
210
211 livevar=${esc_pn}_LIVE_REPO
212 EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}}
213 [[ ${!livevar} ]] \
214 && ewarn "Using ${livevar}, no support will be provided"
215
216 livevar=${esc_pn}_LIVE_BRANCH
217 EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}}
218 [[ ${!livevar} ]] \
219 && ewarn "Using ${livevar}, no support will be provided"
220
221 livevar=${esc_pn}_LIVE_COMMIT
222 EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}}
223 [[ ${!livevar} ]] \
224 && ewarn "Using ${livevar}, no support will be provided"
225
226 # Migration helpers. Remove them when git-2 is removed.
227
228 if [[ ${EGIT_SOURCEDIR} ]]; then
229 eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating"
230 eerror "your ebuild, please check whether the variable is necessary at all"
231 eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}."
232 eerror "Therefore, proper setting of S may be sufficient."
233 die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR."
234 fi
235
236 if [[ ${EGIT_MASTER} ]]; then
237 eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)"
238 eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH"
239 eerror "as necessary."
240 die "EGIT_MASTER has been removed."
241 fi
242
243 if [[ ${EGIT_HAS_SUBMODULES} ]]; then
244 eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs"
245 eerror "to switch the clone type in order to support submodules and therefore"
246 eerror "submodules are detected and fetched automatically."
247 die "EGIT_HAS_SUBMODULES is no longer necessary."
248 fi
249
250 if [[ ${EGIT_PROJECT} ]]; then
251 eerror "EGIT_PROJECT has been removed. Instead, the eclass determines"
252 eerror "the local clone path using path in canonical EGIT_REPO_URI."
253 eerror "If the current algorithm causes issues for you, please report a bug."
254 die "EGIT_PROJECT is no longer necessary."
255 fi
256
257 if [[ ${EGIT_BOOTSTRAP} ]]; then
258 eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()"
259 eerror "instead."
260 die "EGIT_BOOTSTRAP has been removed."
261 fi
262
263 if [[ ${EGIT_NOUNPACK} ]]; then
264 eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default"
265 eerror "unpack function. If necessary, please declare proper src_unpack()."
266 die "EGIT_NOUNPACK has been removed."
267 fi
268 }
269
270 # @FUNCTION: _git-r3_set_gitdir
271 # @USAGE: <repo-uri>
272 # @INTERNAL
273 # @DESCRIPTION:
274 # Obtain the local repository path and set it as GIT_DIR. Creates
275 # a new repository if necessary.
276 #
277 # <repo-uri> may be used to compose the path. It should therefore be
278 # a canonical URI to the repository.
279 _git-r3_set_gitdir() {
280 debug-print-function ${FUNCNAME} "$@"
281
282 local repo_name=${1#*://*/}
283
284 # strip the trailing slash
285 repo_name=${repo_name%/}
286
287 # strip common prefixes to make paths more likely to match
288 # e.g. git://X/Y.git vs https://X/git/Y.git
289 # (but just one of the prefixes)
290 case "${repo_name}" in
291 # gnome.org... who else?
292 browse/*) repo_name=${repo_name#browse/};;
293 # cgit can proxy requests to git
294 cgit/*) repo_name=${repo_name#cgit/};;
295 # pretty common
296 git/*) repo_name=${repo_name#git/};;
297 # gentoo.org
298 gitroot/*) repo_name=${repo_name#gitroot/};;
299 # google code, sourceforge
300 p/*) repo_name=${repo_name#p/};;
301 # kernel.org
302 pub/scm/*) repo_name=${repo_name#pub/scm/};;
303 esac
304 # ensure a .git suffix, same reason
305 repo_name=${repo_name%.git}.git
306 # now replace all the slashes
307 repo_name=${repo_name//\//_}
308
309 local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
310 : ${EGIT3_STORE_DIR:=${distdir}/git3-src}
311
312 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
313
314 if [[ ! -d ${EGIT3_STORE_DIR} ]]; then
315 (
316 addwrite /
317 mkdir -p "${EGIT3_STORE_DIR}" || die
318 ) || die "Unable to create ${EGIT3_STORE_DIR}"
319 fi
320
321 addwrite "${EGIT3_STORE_DIR}"
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
328 mkdir "${GIT_DIR}" || die
329 git init --bare || die
330 if [[ ${saved_umask} ]]; then
331 umask "${saved_umask}" || die
332 fi
333 fi
334 }
335
336 # @FUNCTION: _git-r3_set_submodules
337 # @USAGE: <file-contents>
338 # @INTERNAL
339 # @DESCRIPTION:
340 # Parse .gitmodules contents passed as <file-contents>
341 # as in "$(cat .gitmodules)"). Composes a 'submodules' array that
342 # contains in order (name, URL, path) for each submodule.
343 _git-r3_set_submodules() {
344 debug-print-function ${FUNCNAME} "$@"
345
346 local data=${1}
347
348 # ( name url path ... )
349 submodules=()
350
351 local l
352 while read l; do
353 # submodule.<path>.path=<path>
354 # submodule.<path>.url=<url>
355 [[ ${l} == submodule.*.url=* ]] || continue
356
357 l=${l#submodule.}
358 local subname=${l%%.url=*}
359
360 # skip modules that have 'update = none', bug #487262.
361 local upd=$(echo "${data}" | git config -f /dev/fd/0 \
362 submodule."${subname}".update)
363 [[ ${upd} == none ]] && continue
364
365 submodules+=(
366 "${subname}"
367 "$(echo "${data}" | git config -f /dev/fd/0 \
368 submodule."${subname}".url || die)"
369 "$(echo "${data}" | git config -f /dev/fd/0 \
370 submodule."${subname}".path || die)"
371 )
372 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
373 }
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
418 # @FUNCTION: _git-r3_is_local_repo
419 # @USAGE: <repo-uri>
420 # @INTERNAL
421 # @DESCRIPTION:
422 # Determine whether the given URI specifies a local (on-disk)
423 # repository.
424 _git-r3_is_local_repo() {
425 debug-print-function ${FUNCNAME} "$@"
426
427 local uri=${1}
428
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}"
466 }
467
468 # @FUNCTION: git-r3_fetch
469 # @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
470 # @DESCRIPTION:
471 # Fetch new commits to the local clone of repository.
472 #
473 # <repo-uri> specifies the repository URIs to fetch from, as a space-
474 # -separated list. The first URI will be used as repository group
475 # identifier and therefore must be used consistently. When not
476 # specified, defaults to ${EGIT_REPO_URI}.
477 #
478 # <remote-ref> specifies the remote ref or commit id to fetch.
479 # It is preferred to use 'refs/heads/<branch-name>' for branches
480 # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
481 # for upstream default branch and hexadecimal commit SHA1. Defaults
482 # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
483 # is set to a non-null value.
484 #
485 # <local-id> specifies the local branch identifier that will be used to
486 # locally store the fetch result. It should be unique to multiple
487 # fetches within the repository that can be performed at the same time
488 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
489 # This default should be fine unless you are fetching multiple trees
490 # from the same repository in the same ebuild.
491 #
492 # The fetch operation will affect the EGIT_STORE only. It will not touch
493 # the working copy, nor export any environment variables.
494 # If the repository contains submodules, they will be fetched
495 # recursively.
496 git-r3_fetch() {
497 debug-print-function ${FUNCNAME} "$@"
498
499 [[ ${EVCS_OFFLINE} ]] && return
500
501 local repos
502 if [[ ${1} ]]; then
503 repos=( ${1} )
504 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
505 repos=( "${EGIT_REPO_URI[@]}" )
506 else
507 repos=( ${EGIT_REPO_URI} )
508 fi
509
510 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
511 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
512 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
513 local local_ref=refs/git-r3/${local_id}/__main__
514
515 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
516
517 local -x GIT_DIR
518 _git-r3_set_gitdir "${repos[0]}"
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
528 # try to fetch from the remote
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
534 for r in "${repos[@]}"; do
535 einfo "Fetching ${r} ..."
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 EGIT_CLONE_TYPE=single+tags"
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 EGIT_CLONE_TYPE=single+tags"
561 clone_type=single+tags
562 fi
563 fi
564
565 if [[ ${clone_type} == mirror ]]; then
566 fetch_command+=(
567 --prune
568 # mirror the remote branches as local branches
569 "+refs/heads/*:refs/heads/*"
570 # pull tags explicitly in order to prune them properly
571 "+refs/tags/*:refs/tags/*"
572 # notes in case something needs them
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"
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
645
646 set -- "${fetch_command[@]}"
647 echo "${@}" >&2
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
671 # now let's see what the user wants from us
672 local full_remote_ref=$(
673 git rev-parse --verify --symbolic-full-name "${remote_ref}"
674 )
675
676 if [[ ${full_remote_ref} ]]; then
677 # when we are given a ref, create a symbolic ref
678 # so that we preserve the actual argument
679 set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
680 else
681 # otherwise, we were likely given a commit id
682 set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
683 fi
684
685 echo "${@}" >&2
686 if ! "${@}"; then
687 die "Referencing ${remote_ref} failed (wrong ref?)."
688 fi
689
690 success=1
691 break
692 fi
693 done
694 if [[ ${saved_umask} ]]; then
695 umask "${saved_umask}" || die
696 fi
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
702
703 # recursively fetch submodules
704 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
705 local submodules
706 _git-r3_set_submodules \
707 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
708
709 while [[ ${submodules[@]} ]]; do
710 local subname=${submodules[0]}
711 local url=${submodules[1]}
712 local path=${submodules[2]}
713 local commit=$(git rev-parse "${local_ref}:${path}")
714
715 if [[ ! ${commit} ]]; then
716 die "Unable to get commit id for submodule ${subname}"
717 fi
718
719 local subrepos
720 _git-r3_set_subrepos "${url}" "${repos[@]}"
721
722 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
723
724 submodules=( "${submodules[@]:3}" ) # shift
725 done
726 fi
727 }
728
729 # @FUNCTION: git-r3_checkout
730 # @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
731 # @DESCRIPTION:
732 # Check the previously fetched tree to the working copy.
733 #
734 # <repo-uri> specifies the repository URIs, as a space-separated list.
735 # The first URI will be used as repository group identifier
736 # and therefore must be used consistently with git-r3_fetch.
737 # The remaining URIs are not used and therefore may be omitted.
738 # When not specified, defaults to ${EGIT_REPO_URI}.
739 #
740 # <checkout-path> specifies the path to place the checkout. It defaults
741 # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
742 #
743 # <local-id> needs to specify the local identifier that was used
744 # for respective git-r3_fetch.
745 #
746 # The checkout operation will write to the working copy, and export
747 # the repository state into the environment. If the repository contains
748 # submodules, they will be checked out recursively.
749 git-r3_checkout() {
750 debug-print-function ${FUNCNAME} "$@"
751
752 local repos
753 if [[ ${1} ]]; then
754 repos=( ${1} )
755 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
756 repos=( "${EGIT_REPO_URI[@]}" )
757 else
758 repos=( ${EGIT_REPO_URI} )
759 fi
760
761 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
762 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
763
764 local -x GIT_DIR
765 _git-r3_set_gitdir "${repos[0]}"
766
767 einfo "Checking out ${repos[0]} to ${out_dir} ..."
768
769 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
770 if [[ ${EVCS_OFFLINE} ]]; then
771 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
772 else
773 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
774 fi
775 fi
776 local remote_ref=$(
777 git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
778 )
779 local new_commit_id=$(
780 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
781 )
782
783 git-r3_sub_checkout() {
784 local orig_repo=${GIT_DIR}
785 local -x GIT_DIR=${out_dir}/.git
786 local -x GIT_WORK_TREE=${out_dir}
787
788 mkdir -p "${out_dir}" || die
789
790 # use git init+fetch instead of clone since the latter doesn't like
791 # non-empty directories.
792
793 git init --quiet || die
794 # setup 'alternates' to avoid copying objects
795 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
796 # now copy the refs
797 # [htn]* safely catches heads, tags, notes without complaining
798 # on non-existing ones, and omits internal 'git-r3' ref
799 cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die
800
801 # (no need to copy HEAD, we will set it via checkout)
802
803 if [[ -f ${orig_repo}/shallow ]]; then
804 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
805 fi
806
807 set -- git checkout --quiet
808 if [[ ${remote_ref} ]]; then
809 set -- "${@}" "${remote_ref#refs/heads/}"
810 else
811 set -- "${@}" "${new_commit_id}"
812 fi
813 echo "${@}" >&2
814 "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
815 }
816 git-r3_sub_checkout
817
818 local old_commit_id=$(
819 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
820 )
821 if [[ ! ${old_commit_id} ]]; then
822 echo "GIT NEW branch -->"
823 echo " repository: ${repos[0]}"
824 echo " at the commit: ${new_commit_id}"
825 else
826 # diff against previous revision
827 echo "GIT update -->"
828 echo " repository: ${repos[0]}"
829 # write out message based on the revisions
830 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
831 echo " updating from commit: ${old_commit_id}"
832 echo " to commit: ${new_commit_id}"
833
834 git --no-pager diff --stat \
835 ${old_commit_id}..${new_commit_id}
836 else
837 echo " at the commit: ${new_commit_id}"
838 fi
839 fi
840 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
841
842 # recursively checkout submodules
843 if [[ -f ${out_dir}/.gitmodules ]]; then
844 local submodules
845 _git-r3_set_submodules \
846 "$(<"${out_dir}"/.gitmodules)"
847
848 while [[ ${submodules[@]} ]]; do
849 local subname=${submodules[0]}
850 local url=${submodules[1]}
851 local path=${submodules[2]}
852 local subrepos
853 _git-r3_set_subrepos "${url}" "${repos[@]}"
854
855 git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \
856 "${local_id}/${subname}"
857
858 submodules=( "${submodules[@]:3}" ) # shift
859 done
860 fi
861
862 # keep this *after* submodules
863 export EGIT_DIR=${GIT_DIR}
864 export EGIT_VERSION=${new_commit_id}
865 }
866
867 # @FUNCTION: git-r3_peek_remote_ref
868 # @USAGE: [<repo-uri> [<remote-ref>]]
869 # @DESCRIPTION:
870 # Peek the reference in the remote repository and print the matching
871 # (newest) commit SHA1.
872 #
873 # <repo-uri> specifies the repository URIs to fetch from, as a space-
874 # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
875 #
876 # <remote-ref> specifies the remote ref to peek. It is preferred to use
877 # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
878 # for tags. Alternatively, 'HEAD' may be used for upstream default
879 # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
880 # 'HEAD' that is set to a non-null value.
881 #
882 # The operation will be done purely on the remote, without using local
883 # storage. If commit SHA1 is provided as <remote-ref>, the function will
884 # fail due to limitations of git protocol.
885 #
886 # On success, the function returns 0 and writes hexadecimal commit SHA1
887 # to stdout. On failure, the function returns 1.
888 git-r3_peek_remote_ref() {
889 debug-print-function ${FUNCNAME} "$@"
890
891 local repos
892 if [[ ${1} ]]; then
893 repos=( ${1} )
894 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
895 repos=( "${EGIT_REPO_URI[@]}" )
896 else
897 repos=( ${EGIT_REPO_URI} )
898 fi
899
900 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
901 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
902
903 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
904
905 local r success
906 for r in "${repos[@]}"; do
907 einfo "Peeking ${remote_ref} on ${r} ..." >&2
908
909 local is_branch lookup_ref
910 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
911 then
912 is_branch=1
913 lookup_ref=${remote_ref}
914 else
915 # ls-remote by commit is going to fail anyway,
916 # so we may as well pass refs/tags/ABCDEF...
917 lookup_ref=refs/tags/${remote_ref}
918 fi
919
920 # split on whitespace
921 local ref=(
922 $(git ls-remote "${r}" "${lookup_ref}")
923 )
924
925 if [[ ${ref[0]} ]]; then
926 echo "${ref[0]}"
927 return 0
928 fi
929 done
930
931 return 1
932 }
933
934 git-r3_src_fetch() {
935 debug-print-function ${FUNCNAME} "$@"
936
937 if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
938 ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
939 ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
940 ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
941 ewarn "when git-2 eclass becomes deprecated."
942 fi
943
944 _git-r3_env_setup
945 git-r3_fetch
946 }
947
948 git-r3_src_unpack() {
949 debug-print-function ${FUNCNAME} "$@"
950
951 _git-r3_env_setup
952 git-r3_src_fetch
953 git-r3_checkout
954 }
955
956 # https://bugs.gentoo.org/show_bug.cgi?id=482666
957 git-r3_pkg_outofdate() {
958 debug-print-function ${FUNCNAME} "$@"
959
960 local new_commit_id=$(git-r3_peek_remote_ref)
961 ewarn "old: ${EGIT_VERSION}"
962 ewarn "new: ${new_commit_id}"
963 [[ ${new_commit_id} && ${old_commit_id} ]] || return 2
964
965 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
966 }
967
968 _GIT_R3=1
969 fi

  ViewVC Help
Powered by ViewVC 1.1.20