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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.39 - (show annotations) (download)
Mon Mar 3 21:45:06 2014 UTC (6 months, 3 weeks ago) by mgorny
Branch: MAIN
Changes since 1.38: +5 -1 lines
Force EGIT_CLONE_TYPE=mirror for submodules since they can reference commits in any branch without explicitly naming the branch, bug #503332.

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

  ViewVC Help
Powered by ViewVC 1.1.20