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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.45 - (show annotations) (download)
Mon Jul 7 14:41:56 2014 UTC (4 months, 2 weeks ago) by mgorny
Branch: MAIN
Changes since 1.44: +2 -2 lines
Stop forcing -m0755 on EGIT3_STORE_DIR and parents, bug #516508.

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

  ViewVC Help
Powered by ViewVC 1.1.20