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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.42 - (show annotations) (download)
Fri May 23 07:09:07 2014 UTC (6 months, 4 weeks ago) by mgorny
Branch: MAIN
Changes since 1.41: +10 -1 lines
Give an explanatory error when trying to fetch https:// with dev-vcs/git[-curl]. Bug #510768.

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.41 2014/04/17 20:28:37 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 -m0755 -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_is_local_repo
356 # @USAGE: <repo-uri>
357 # @INTERNAL
358 # @DESCRIPTION:
359 # Determine whether the given URI specifies a local (on-disk)
360 # repository.
361 _git-r3_is_local_repo() {
362 debug-print-function ${FUNCNAME} "$@"
363
364 local uri=${1}
365
366 [[ ${uri} == file://* || ${uri} == /* ]]
367 }
368
369 # @FUNCTION: _git-r3_find_head
370 # @USAGE: <head-ref>
371 # @INTERNAL
372 # @DESCRIPTION:
373 # Given a ref to which remote HEAD was fetched, try to find
374 # a branch matching the commit. Expects 'git show-ref'
375 # or 'git ls-remote' output on stdin.
376 _git-r3_find_head() {
377 debug-print-function ${FUNCNAME} "$@"
378
379 local head_ref=${1}
380 local head_hash=$(git rev-parse --verify "${1}" || die)
381 local matching_ref
382
383 # TODO: some transports support peeking at symbolic remote refs
384 # find a way to use that rather than guessing
385
386 # (based on guess_remote_head() in git-1.9.0/remote.c)
387 local h ref
388 while read h ref; do
389 # look for matching head
390 if [[ ${h} == ${head_hash} ]]; then
391 # either take the first matching ref, or master if it is there
392 if [[ ! ${matching_ref} || ${ref} == refs/heads/master ]]; then
393 matching_ref=${ref}
394 fi
395 fi
396 done
397
398 if [[ ! ${matching_ref} ]]; then
399 die "Unable to find a matching branch for remote HEAD (${head_hash})"
400 fi
401
402 echo "${matching_ref}"
403 }
404
405 # @FUNCTION: git-r3_fetch
406 # @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
407 # @DESCRIPTION:
408 # Fetch new commits to the local clone of repository.
409 #
410 # <repo-uri> specifies the repository URIs to fetch from, as a space-
411 # -separated list. The first URI will be used as repository group
412 # identifier and therefore must be used consistently. When not
413 # specified, defaults to ${EGIT_REPO_URI}.
414 #
415 # <remote-ref> specifies the remote ref or commit id to fetch.
416 # It is preferred to use 'refs/heads/<branch-name>' for branches
417 # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
418 # for upstream default branch and hexadecimal commit SHA1. Defaults
419 # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
420 # is set to a non-null value.
421 #
422 # <local-id> specifies the local branch identifier that will be used to
423 # locally store the fetch result. It should be unique to multiple
424 # fetches within the repository that can be performed at the same time
425 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
426 # This default should be fine unless you are fetching multiple trees
427 # from the same repository in the same ebuild.
428 #
429 # The fetch operation will affect the EGIT_STORE only. It will not touch
430 # the working copy, nor export any environment variables.
431 # If the repository contains submodules, they will be fetched
432 # recursively.
433 git-r3_fetch() {
434 debug-print-function ${FUNCNAME} "$@"
435
436 [[ ${EVCS_OFFLINE} ]] && return
437
438 local repos
439 if [[ ${1} ]]; then
440 repos=( ${1} )
441 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
442 repos=( "${EGIT_REPO_URI[@]}" )
443 else
444 repos=( ${EGIT_REPO_URI} )
445 fi
446
447 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
448 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
449 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
450 local local_ref=refs/git-r3/${local_id}/__main__
451
452 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
453
454 local -x GIT_DIR
455 _git-r3_set_gitdir "${repos[0]}"
456
457 # prepend the local mirror if applicable
458 if [[ ${EGIT_MIRROR_URI} ]]; then
459 repos=(
460 "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}"
461 "${repos[@]}"
462 )
463 fi
464
465 # try to fetch from the remote
466 local r success
467 for r in "${repos[@]}"; do
468 einfo "Fetching ${r} ..."
469
470 local fetch_command=( git fetch "${r}" )
471 local clone_type=${EGIT_CLONE_TYPE}
472
473 if [[ ${r} == https://* ]] && ! has_version 'dev-vcs/git[curl]'; then
474 eerror "git-r3: fetching from https:// requested. In order to support https,"
475 eerror "dev-vcs/git needs to be built with USE=curl. Example solution:"
476 eerror
477 eerror " echo dev-vcs/git curl >> /etc/portage/package.use"
478 eerror " emerge -1v dev-vcs/git"
479 die "dev-vcs/git built with USE=curl required."
480 fi
481
482 if [[ ${r} == https://code.google.com/* ]]; then
483 # Google Code has special magic on top of git that:
484 # 1) can't handle shallow clones at all,
485 # 2) fetches duplicately when tags are pulled in with branch
486 # so automatically switch to single+tags mode.
487 if [[ ${clone_type} == shallow ]]; then
488 einfo " Google Code does not support shallow clones"
489 einfo " using EGIT_CLONE_TYPE=single+tags"
490 clone_type=single+tags
491 elif [[ ${clone_type} == single ]]; then
492 einfo " git-r3: Google Code does not send tags properly in 'single' mode"
493 einfo " using EGIT_CLONE_TYPE=single+tags"
494 clone_type=single+tags
495 fi
496 fi
497
498 if [[ ${clone_type} == mirror ]]; then
499 fetch_command+=(
500 --prune
501 # mirror the remote branches as local branches
502 "+refs/heads/*:refs/heads/*"
503 # pull tags explicitly in order to prune them properly
504 "+refs/tags/*:refs/tags/*"
505 # notes in case something needs them
506 "+refs/notes/*:refs/notes/*"
507 # and HEAD in case we need the default branch
508 # (we keep it in refs/git-r3 since otherwise --prune interferes)
509 "+HEAD:refs/git-r3/HEAD"
510 )
511 else # single or shallow
512 local fetch_l fetch_r
513
514 if [[ ${remote_ref} == HEAD ]]; then
515 # HEAD
516 fetch_l=HEAD
517 elif [[ ${remote_ref} == refs/heads/* ]]; then
518 # regular branch
519 fetch_l=${remote_ref}
520 else
521 # tag or commit...
522 # let ls-remote figure it out
523 local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}")
524
525 # if it was a tag, ls-remote obtained a hash
526 if [[ ${tagref} ]]; then
527 # tag
528 fetch_l=refs/tags/${remote_ref}
529 else
530 # commit
531 # so we need to fetch the branch
532 if [[ ${branch} ]]; then
533 fetch_l=${branch}
534 else
535 fetch_l=HEAD
536 fi
537
538 # fetching by commit in shallow mode? can't do.
539 if [[ ${clone_type} == shallow ]]; then
540 clone_type=single
541 fi
542 fi
543 fi
544
545 if [[ ${fetch_l} == HEAD ]]; then
546 fetch_r=refs/git-r3/HEAD
547 else
548 fetch_r=${fetch_l}
549 fi
550
551 fetch_command+=(
552 "+${fetch_l}:${fetch_r}"
553 )
554
555 if [[ ${clone_type} == single+tags ]]; then
556 fetch_command+=(
557 # pull tags explicitly as requested
558 "+refs/tags/*:refs/tags/*"
559 )
560 fi
561 fi
562
563 if [[ ${clone_type} == shallow ]]; then
564 if _git-r3_is_local_repo; then
565 # '--depth 1' causes sandbox violations with local repos
566 # bug #491260
567 clone_type=single
568 elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]]
569 then
570 # use '--depth 1' when fetching a new branch
571 fetch_command+=( --depth 1 )
572 fi
573 else # non-shallow mode
574 if [[ -f ${GIT_DIR}/shallow ]]; then
575 fetch_command+=( --unshallow )
576 fi
577 fi
578
579 set -- "${fetch_command[@]}"
580 echo "${@}" >&2
581 if "${@}"; then
582 if [[ ${clone_type} == mirror ]]; then
583 # find remote HEAD and update our HEAD properly
584 git symbolic-ref HEAD \
585 "$(_git-r3_find_head refs/git-r3/HEAD \
586 < <(git show-ref --heads || die))" \
587 || die "Unable to update HEAD"
588 else # single or shallow
589 if [[ ${fetch_l} == HEAD ]]; then
590 # find out what branch we fetched as HEAD
591 local head_branch=$(_git-r3_find_head \
592 refs/git-r3/HEAD \
593 < <(git ls-remote --heads "${r}" || die))
594
595 # and move it to its regular place
596 git update-ref --no-deref "${head_branch}" \
597 refs/git-r3/HEAD \
598 || die "Unable to sync HEAD branch ${head_branch}"
599 git symbolic-ref HEAD "${head_branch}" \
600 || die "Unable to update HEAD"
601 fi
602 fi
603
604 # now let's see what the user wants from us
605 local full_remote_ref=$(
606 git rev-parse --verify --symbolic-full-name "${remote_ref}"
607 )
608
609 if [[ ${full_remote_ref} ]]; then
610 # when we are given a ref, create a symbolic ref
611 # so that we preserve the actual argument
612 set -- git symbolic-ref "${local_ref}" "${full_remote_ref}"
613 else
614 # otherwise, we were likely given a commit id
615 set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
616 fi
617
618 echo "${@}" >&2
619 if ! "${@}"; then
620 die "Referencing ${remote_ref} failed (wrong ref?)."
621 fi
622
623 success=1
624 break
625 fi
626 done
627 [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI"
628
629 # submodules can reference commits in any branch
630 # always use the 'clone' mode to accomodate that, bug #503332
631 local EGIT_CLONE_TYPE=mirror
632
633 # recursively fetch submodules
634 if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then
635 local submodules
636 _git-r3_set_submodules \
637 "$(git cat-file -p "${local_ref}":.gitmodules || die)"
638
639 while [[ ${submodules[@]} ]]; do
640 local subname=${submodules[0]}
641 local url=${submodules[1]}
642 local path=${submodules[2]}
643 local commit=$(git rev-parse "${local_ref}:${path}")
644
645 if [[ ! ${commit} ]]; then
646 die "Unable to get commit id for submodule ${subname}"
647 fi
648 if [[ ${url} == ./* || ${url} == ../* ]]; then
649 local subrepos=( "${repos[@]/%//${url}}" )
650 else
651 local subrepos=( "${url}" )
652 fi
653
654 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
655
656 submodules=( "${submodules[@]:3}" ) # shift
657 done
658 fi
659 }
660
661 # @FUNCTION: git-r3_checkout
662 # @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
663 # @DESCRIPTION:
664 # Check the previously fetched tree to the working copy.
665 #
666 # <repo-uri> specifies the repository URIs, as a space-separated list.
667 # The first URI will be used as repository group identifier
668 # and therefore must be used consistently with git-r3_fetch.
669 # The remaining URIs are not used and therefore may be omitted.
670 # When not specified, defaults to ${EGIT_REPO_URI}.
671 #
672 # <checkout-path> specifies the path to place the checkout. It defaults
673 # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
674 #
675 # <local-id> needs to specify the local identifier that was used
676 # for respective git-r3_fetch.
677 #
678 # The checkout operation will write to the working copy, and export
679 # the repository state into the environment. If the repository contains
680 # submodules, they will be checked out recursively.
681 git-r3_checkout() {
682 debug-print-function ${FUNCNAME} "$@"
683
684 local repos
685 if [[ ${1} ]]; then
686 repos=( ${1} )
687 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
688 repos=( "${EGIT_REPO_URI[@]}" )
689 else
690 repos=( ${EGIT_REPO_URI} )
691 fi
692
693 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
694 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
695
696 local -x GIT_DIR
697 _git-r3_set_gitdir "${repos[0]}"
698
699 einfo "Checking out ${repos[0]} to ${out_dir} ..."
700
701 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
702 if [[ ${EVCS_OFFLINE} ]]; then
703 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
704 else
705 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
706 fi
707 fi
708 local remote_ref=$(
709 git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
710 )
711 local new_commit_id=$(
712 git rev-parse --verify refs/git-r3/"${local_id}"/__main__
713 )
714
715 git-r3_sub_checkout() {
716 local orig_repo=${GIT_DIR}
717 local -x GIT_DIR=${out_dir}/.git
718 local -x GIT_WORK_TREE=${out_dir}
719
720 mkdir -p "${out_dir}" || die
721
722 # use git init+fetch instead of clone since the latter doesn't like
723 # non-empty directories.
724
725 git init --quiet || die
726 # setup 'alternates' to avoid copying objects
727 echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
728 # now copy the refs
729 # [htn]* safely catches heads, tags, notes without complaining
730 # on non-existing ones, and omits internal 'git-r3' ref
731 cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die
732
733 # (no need to copy HEAD, we will set it via checkout)
734
735 if [[ -f ${orig_repo}/shallow ]]; then
736 cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
737 fi
738
739 set -- git checkout --quiet
740 if [[ ${remote_ref} ]]; then
741 set -- "${@}" "${remote_ref#refs/heads/}"
742 else
743 set -- "${@}" "${new_commit_id}"
744 fi
745 echo "${@}" >&2
746 "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
747 }
748 git-r3_sub_checkout
749
750 local old_commit_id=$(
751 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
752 )
753 if [[ ! ${old_commit_id} ]]; then
754 echo "GIT NEW branch -->"
755 echo " repository: ${repos[0]}"
756 echo " at the commit: ${new_commit_id}"
757 else
758 # diff against previous revision
759 echo "GIT update -->"
760 echo " repository: ${repos[0]}"
761 # write out message based on the revisions
762 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
763 echo " updating from commit: ${old_commit_id}"
764 echo " to commit: ${new_commit_id}"
765
766 git --no-pager diff --stat \
767 ${old_commit_id}..${new_commit_id}
768 else
769 echo " at the commit: ${new_commit_id}"
770 fi
771 fi
772 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
773
774 # recursively checkout submodules
775 if [[ -f ${out_dir}/.gitmodules ]]; then
776 local submodules
777 _git-r3_set_submodules \
778 "$(<"${out_dir}"/.gitmodules)"
779
780 while [[ ${submodules[@]} ]]; do
781 local subname=${submodules[0]}
782 local url=${submodules[1]}
783 local path=${submodules[2]}
784
785 if [[ ${url} == ./* || ${url} == ../* ]]; then
786 url=${repos[0]%%/}/${url}
787 fi
788
789 git-r3_checkout "${url}" "${out_dir}/${path}" \
790 "${local_id}/${subname}"
791
792 submodules=( "${submodules[@]:3}" ) # shift
793 done
794 fi
795
796 # keep this *after* submodules
797 export EGIT_DIR=${GIT_DIR}
798 export EGIT_VERSION=${new_commit_id}
799 }
800
801 # @FUNCTION: git-r3_peek_remote_ref
802 # @USAGE: [<repo-uri> [<remote-ref>]]
803 # @DESCRIPTION:
804 # Peek the reference in the remote repository and print the matching
805 # (newest) commit SHA1.
806 #
807 # <repo-uri> specifies the repository URIs to fetch from, as a space-
808 # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
809 #
810 # <remote-ref> specifies the remote ref to peek. It is preferred to use
811 # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
812 # for tags. Alternatively, 'HEAD' may be used for upstream default
813 # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
814 # 'HEAD' that is set to a non-null value.
815 #
816 # The operation will be done purely on the remote, without using local
817 # storage. If commit SHA1 is provided as <remote-ref>, the function will
818 # fail due to limitations of git protocol.
819 #
820 # On success, the function returns 0 and writes hexadecimal commit SHA1
821 # to stdout. On failure, the function returns 1.
822 git-r3_peek_remote_ref() {
823 debug-print-function ${FUNCNAME} "$@"
824
825 local repos
826 if [[ ${1} ]]; then
827 repos=( ${1} )
828 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
829 repos=( "${EGIT_REPO_URI[@]}" )
830 else
831 repos=( ${EGIT_REPO_URI} )
832 fi
833
834 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
835 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
836
837 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
838
839 local r success
840 for r in "${repos[@]}"; do
841 einfo "Peeking ${remote_ref} on ${r} ..." >&2
842
843 local is_branch lookup_ref
844 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
845 then
846 is_branch=1
847 lookup_ref=${remote_ref}
848 else
849 # ls-remote by commit is going to fail anyway,
850 # so we may as well pass refs/tags/ABCDEF...
851 lookup_ref=refs/tags/${remote_ref}
852 fi
853
854 # split on whitespace
855 local ref=(
856 $(git ls-remote "${r}" "${lookup_ref}")
857 )
858
859 if [[ ${ref[0]} ]]; then
860 echo "${ref[0]}"
861 return 0
862 fi
863 done
864
865 return 1
866 }
867
868 git-r3_src_fetch() {
869 debug-print-function ${FUNCNAME} "$@"
870
871 if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
872 ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
873 ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
874 ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
875 ewarn "when git-2 eclass becomes deprecated."
876 fi
877
878 _git-r3_env_setup
879 git-r3_fetch
880 }
881
882 git-r3_src_unpack() {
883 debug-print-function ${FUNCNAME} "$@"
884
885 _git-r3_env_setup
886 git-r3_src_fetch
887 git-r3_checkout
888 }
889
890 # https://bugs.gentoo.org/show_bug.cgi?id=482666
891 git-r3_pkg_outofdate() {
892 debug-print-function ${FUNCNAME} "$@"
893
894 local new_commit_id=$(git-r3_peek_remote_ref)
895 ewarn "old: ${EGIT_VERSION}"
896 ewarn "new: ${new_commit_id}"
897 [[ ${new_commit_id} && ${old_commit_id} ]] || return 2
898
899 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
900 }
901
902 _GIT_R3=1
903 fi

  ViewVC Help
Powered by ViewVC 1.1.20