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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.32 - (show annotations) (download)
Sun Mar 2 11:47:41 2014 UTC (9 months, 4 weeks ago) by mgorny
Branch: MAIN
Changes since 1.31: +94 -26 lines
Support EGIT_CLONE_TYPE=single.

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

  ViewVC Help
Powered by ViewVC 1.1.20