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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23 - (show annotations) (download)
Fri Nov 15 23:03:23 2013 UTC (12 months, 1 week ago) by mgorny
Branch: MAIN
Changes since 1.22: +19 -1 lines
Use shallow clones for local repos. Bug #491260.

1 # Copyright 1999-2013 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.22 2013/10/30 19:21:12 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. The eclass supports lightweight (shallow)
12 # clones and bare clones of submodules.
13
14 case "${EAPI:-0}" in
15 0|1|2|3|4|5)
16 ;;
17 *)
18 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
19 ;;
20 esac
21
22 if [[ ! ${_GIT_R3} ]]; then
23
24 inherit eutils
25
26 fi
27
28 EXPORT_FUNCTIONS src_unpack
29
30 if [[ ! ${_GIT_R3} ]]; then
31
32 if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
33 DEPEND=">=dev-vcs/git-1.8.2.1"
34 fi
35
36 # @ECLASS-VARIABLE: EGIT3_STORE_DIR
37 # @DESCRIPTION:
38 # Storage directory for git sources.
39 #
40 # EGIT3_STORE_DIR=${DISTDIR}/git3-src
41
42 # @ECLASS-VARIABLE: EGIT_REPO_URI
43 # @REQUIRED
44 # @DESCRIPTION:
45 # URIs to the repository, e.g. git://foo, https://foo. If multiple URIs
46 # are provided, the eclass will consider them as fallback URIs to try
47 # if the first URI does not work.
48 #
49 # It can be overriden via env using ${PN}_LIVE_REPO variable.
50 #
51 # Can be a whitespace-separated list or an array.
52 #
53 # Example:
54 # @CODE
55 # EGIT_REPO_URI="git://a/b.git https://c/d.git"
56 # @CODE
57
58 # @ECLASS-VARIABLE: EVCS_OFFLINE
59 # @DEFAULT_UNSET
60 # @DESCRIPTION:
61 # If non-empty, this variable prevents any online operations.
62
63 # @ECLASS-VARIABLE: EGIT_BRANCH
64 # @DEFAULT_UNSET
65 # @DESCRIPTION:
66 # The branch name to check out. If unset, the upstream default (HEAD)
67 # will be used.
68 #
69 # It can be overriden via env using ${PN}_LIVE_BRANCH variable.
70
71 # @ECLASS-VARIABLE: EGIT_COMMIT
72 # @DEFAULT_UNSET
73 # @DESCRIPTION:
74 # The tag name or commit identifier to check out. If unset, newest
75 # commit from the branch will be used. If set, EGIT_BRANCH will
76 # be ignored.
77 #
78 # It can be overriden via env using ${PN}_LIVE_COMMIT variable.
79
80 # @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR
81 # @DESCRIPTION:
82 # The directory to check the git sources out to.
83 #
84 # EGIT_CHECKOUT_DIR=${WORKDIR}/${P}
85
86 # @ECLASS-VARIABLE: EGIT_NONSHALLOW
87 # @DEFAULT_UNSET
88 # @DESCRIPTION:
89 # Disable performing shallow fetches/clones. Shallow clones have
90 # a fair number of limitations. Therefore, if you'd like the eclass to
91 # perform complete clones instead, set this to a non-null value.
92 #
93 # This variable can be set in make.conf and ebuilds. The make.conf
94 # value specifies user-specific default, while ebuilds may use it
95 # to force deep clones when the server does not support shallow clones
96 # (e.g. Google Code).
97
98 # @FUNCTION: _git-r3_env_setup
99 # @INTERNAL
100 # @DESCRIPTION:
101 # Set the eclass variables as necessary for operation. This can involve
102 # setting EGIT_* to defaults or ${PN}_LIVE_* variables.
103 _git-r3_env_setup() {
104 debug-print-function ${FUNCNAME} "$@"
105
106 local esc_pn livevar
107 esc_pn=${PN//[-+]/_}
108
109 livevar=${esc_pn}_LIVE_REPO
110 EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}}
111 [[ ${!livevar} ]] \
112 && ewarn "Using ${livevar}, no support will be provided"
113
114 livevar=${esc_pn}_LIVE_BRANCH
115 EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}}
116 [[ ${!livevar} ]] \
117 && ewarn "Using ${livevar}, no support will be provided"
118
119 livevar=${esc_pn}_LIVE_COMMIT
120 EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}}
121 [[ ${!livevar} ]] \
122 && ewarn "Using ${livevar}, no support will be provided"
123
124 # Migration helpers. Remove them when git-2 is removed.
125
126 if [[ ${EGIT_SOURCEDIR} ]]; then
127 eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating"
128 eerror "your ebuild, please check whether the variable is necessary at all"
129 eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}."
130 eerror "Therefore, proper setting of S may be sufficient."
131 die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR."
132 fi
133
134 if [[ ${EGIT_MASTER} ]]; then
135 eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)"
136 eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH"
137 eerror "as necessary."
138 die "EGIT_MASTER has been removed."
139 fi
140
141 if [[ ${EGIT_HAS_SUBMODULES} ]]; then
142 eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs"
143 eerror "to switch the clone type in order to support submodules and therefore"
144 eerror "submodules are detected and fetched automatically."
145 die "EGIT_HAS_SUBMODULES is no longer necessary."
146 fi
147
148 if [[ ${EGIT_PROJECT} ]]; then
149 eerror "EGIT_PROJECT has been removed. Instead, the eclass determines"
150 eerror "the local clone path using path in canonical EGIT_REPO_URI."
151 eerror "If the current algorithm causes issues for you, please report a bug."
152 die "EGIT_PROJECT is no longer necessary."
153 fi
154
155 if [[ ${EGIT_BOOTSTRAP} ]]; then
156 eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()"
157 eerror "instead."
158 die "EGIT_BOOTSTRAP has been removed."
159 fi
160
161 if [[ ${EGIT_NOUNPACK} ]]; then
162 eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default"
163 eerror "unpack function. If necessary, please declare proper src_unpack()."
164 die "EGIT_NOUNPACK has been removed."
165 fi
166 }
167
168 # @FUNCTION: _git-r3_set_gitdir
169 # @USAGE: <repo-uri>
170 # @INTERNAL
171 # @DESCRIPTION:
172 # Obtain the local repository path and set it as GIT_DIR. Creates
173 # a new repository if necessary.
174 #
175 # <repo-uri> may be used to compose the path. It should therefore be
176 # a canonical URI to the repository.
177 _git-r3_set_gitdir() {
178 debug-print-function ${FUNCNAME} "$@"
179
180 local repo_name=${1#*://*/}
181
182 # strip the trailing slash
183 repo_name=${repo_name%/}
184
185 # strip common prefixes to make paths more likely to match
186 # e.g. git://X/Y.git vs https://X/git/Y.git
187 # (but just one of the prefixes)
188 case "${repo_name}" in
189 # gnome.org... who else?
190 browse/*) repo_name=${repo_name#browse/};;
191 # cgit can proxy requests to git
192 cgit/*) repo_name=${repo_name#cgit/};;
193 # pretty common
194 git/*) repo_name=${repo_name#git/};;
195 # gentoo.org
196 gitroot/*) repo_name=${repo_name#gitroot/};;
197 # google code, sourceforge
198 p/*) repo_name=${repo_name#p/};;
199 # kernel.org
200 pub/scm/*) repo_name=${repo_name#pub/scm/};;
201 esac
202 # ensure a .git suffix, same reason
203 repo_name=${repo_name%.git}.git
204 # now replace all the slashes
205 repo_name=${repo_name//\//_}
206
207 local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
208 : ${EGIT3_STORE_DIR:=${distdir}/git3-src}
209
210 GIT_DIR=${EGIT3_STORE_DIR}/${repo_name}
211
212 if [[ ! -d ${EGIT3_STORE_DIR} ]]; then
213 (
214 addwrite /
215 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die
216 ) || die "Unable to create ${EGIT3_STORE_DIR}"
217 fi
218
219 addwrite "${EGIT3_STORE_DIR}"
220 if [[ ! -d ${GIT_DIR} ]]; then
221 mkdir "${GIT_DIR}" || die
222 git init --bare || die
223
224 if [[ ! ${EGIT_NONSHALLOW} ]]; then
225 # avoid auto-unshallow :)
226 touch "${GIT_DIR}"/shallow || die
227 fi
228 fi
229 }
230
231 # @FUNCTION: _git-r3_set_submodules
232 # @USAGE: <file-contents>
233 # @INTERNAL
234 # @DESCRIPTION:
235 # Parse .gitmodules contents passed as <file-contents>
236 # as in "$(cat .gitmodules)"). Composes a 'submodules' array that
237 # contains in order (name, URL, path) for each submodule.
238 _git-r3_set_submodules() {
239 debug-print-function ${FUNCNAME} "$@"
240
241 local data=${1}
242
243 # ( name url path ... )
244 submodules=()
245
246 local l
247 while read l; do
248 # submodule.<path>.path=<path>
249 # submodule.<path>.url=<url>
250 [[ ${l} == submodule.*.url=* ]] || continue
251
252 l=${l#submodule.}
253 local subname=${l%%.url=*}
254
255 # skip modules that have 'update = none', bug #487262.
256 local upd=$(echo "${data}" | git config -f /dev/fd/0 \
257 submodule."${subname}".update)
258 [[ ${upd} == none ]] && continue
259
260 submodules+=(
261 "${subname}"
262 "$(echo "${data}" | git config -f /dev/fd/0 \
263 submodule."${subname}".url || die)"
264 "$(echo "${data}" | git config -f /dev/fd/0 \
265 submodule."${subname}".path || die)"
266 )
267 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
268 }
269
270 # @FUNCTION: _git-r3_smart_fetch
271 # @USAGE: <git-fetch-args>...
272 # @DESCRIPTION:
273 # Try fetching without '--depth' and switch to '--depth 1' if that
274 # will involve less objects fetched.
275 _git-r3_smart_fetch() {
276 debug-print-function ${FUNCNAME} "$@"
277
278 local sed_regexp='.*Counting objects: \([0-9]*\), done\..*'
279
280 # start the main fetch
281 local cmd=( git fetch --progress "${@}" )
282 echo "${cmd[@]}" >&2
283
284 # we copy the output to the 'sed' pipe for parsing. whenever sed finds
285 # the process count, it quits quickly to avoid delays in writing it.
286 # then, we start a dummy 'cat' to keep the pipe alive
287
288 "${cmd[@]}" 2>&1 \
289 | tee >(
290 sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}" \
291 > "${T}"/git-r3_main.count
292 exec cat >/dev/null
293 ) &
294 local main_pid=${!}
295
296 # start the helper process
297 _git-r3_sub_fetch() {
298 # wait for main fetch to get object count; if the server doesn't
299 # output it, we won't even launch the parallel process
300 while [[ ! -s ${T}/git-r3_main.count ]]; do
301 sleep 0.25
302 done
303
304 # ok, let's see if parallel fetch gives us smaller count
305 # --dry-run will prevent it from writing to the local clone
306 # and sed should terminate git with SIGPIPE
307 local sub_count=$(git fetch --progress --dry-run --depth 1 "${@}" 2>&1 \
308 | sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}")
309 local main_count=$(<"${T}"/git-r3_main.count)
310
311 # let's be real sure that '--depth 1' will be good for us.
312 # note that we have purely objects counts, and '--depth 1'
313 # may involve much bigger objects
314 if [[ ${main_count} && ${main_count} -ge $(( sub_count * 3/2 )) ]]
315 then
316 # signal that we want shallow fetch instead,
317 # and terminate the non-shallow fetch process
318 touch "${T}"/git-r3_want_shallow || die
319 kill ${main_pid} &>/dev/null
320 exit 0
321 fi
322
323 exit 1
324 }
325 _git-r3_sub_fetch "${@}" &
326 local sub_pid=${!}
327
328 # wait for main process to terminate, either of its own
329 # or by signal from subprocess
330 wait ${main_pid}
331 local main_ret=${?}
332
333 # wait for subprocess to terminate, killing it if necessary.
334 # if main fetch finished before it, there's no point in keeping
335 # it alive. if main fetch was killed by it, it's done anyway
336 kill ${sub_pid} &>/dev/null
337 wait ${sub_pid}
338
339 # now see if subprocess wanted to tell us something...
340 if [[ -f ${T}/git-r3_want_shallow ]]; then
341 rm "${T}"/git-r3_want_shallow || die
342
343 # if fetch finished already (wasn't killed), ignore it
344 [[ ${main_ret} -eq 0 ]] && return 0
345
346 # otherwise, restart as shallow fetch
347 einfo "Restarting fetch using --depth 1 to save bandwidth ..."
348 local cmd=( git fetch --progress --depth 1 "${@}" )
349 echo "${cmd[@]}" >&2
350 "${cmd[@]}"
351 main_ret=${?}
352 fi
353
354 return ${main_ret}
355 }
356
357 # @FUNCTION: _git-r3_is_local_repo
358 # @USAGE: <repo-uri>
359 # @INTERNAL
360 # @DESCRIPTION:
361 # Determine whether the given URI specifies a local (on-disk)
362 # repository.
363 _git-r3_is_local_repo() {
364 debug-print-function ${FUNCNAME} "$@"
365
366 local uri=${1}
367
368 [[ ${uri} == file://* || ${uri} == /* ]]
369 }
370
371 # @FUNCTION: git-r3_fetch
372 # @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
373 # @DESCRIPTION:
374 # Fetch new commits to the local clone of repository.
375 #
376 # <repo-uri> specifies the repository URIs to fetch from, as a space-
377 # -separated list. The first URI will be used as repository group
378 # identifier and therefore must be used consistently. When not
379 # specified, defaults to ${EGIT_REPO_URI}.
380 #
381 # <remote-ref> specifies the remote ref or commit id to fetch.
382 # It is preferred to use 'refs/heads/<branch-name>' for branches
383 # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD'
384 # for upstream default branch and hexadecimal commit SHA1. Defaults
385 # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that
386 # is set to a non-null value.
387 #
388 # <local-id> specifies the local branch identifier that will be used to
389 # locally store the fetch result. It should be unique to multiple
390 # fetches within the repository that can be performed at the same time
391 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
392 # This default should be fine unless you are fetching multiple trees
393 # from the same repository in the same ebuild.
394 #
395 # The fetch operation will affect the EGIT_STORE only. It will not touch
396 # the working copy, nor export any environment variables.
397 # If the repository contains submodules, they will be fetched
398 # recursively.
399 git-r3_fetch() {
400 debug-print-function ${FUNCNAME} "$@"
401
402 [[ ${EVCS_OFFLINE} ]] && return
403
404 local repos
405 if [[ ${1} ]]; then
406 repos=( ${1} )
407 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
408 repos=( "${EGIT_REPO_URI[@]}" )
409 else
410 repos=( ${EGIT_REPO_URI} )
411 fi
412
413 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
414 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
415 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
416 local local_ref=refs/heads/${local_id}/__main__
417
418 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
419
420 local -x GIT_DIR
421 _git-r3_set_gitdir "${repos[0]}"
422
423 # try to fetch from the remote
424 local r success
425 for r in "${repos[@]}"; do
426 einfo "Fetching ${remote_ref} from ${r} ..."
427
428 local is_branch lookup_ref
429 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
430 then
431 is_branch=1
432 lookup_ref=${remote_ref}
433 else
434 # ls-remote by commit is going to fail anyway,
435 # so we may as well pass refs/tags/ABCDEF...
436 lookup_ref=refs/tags/${remote_ref}
437 fi
438
439 # first, try ls-remote to see if ${remote_ref} is a real ref
440 # and not a commit id. if it succeeds, we can pass ${remote_ref}
441 # to 'fetch'. otherwise, we will just fetch everything
442
443 # split on whitespace
444 local ref=(
445 $(git ls-remote "${r}" "${lookup_ref}" || echo __FAIL__)
446 )
447
448 # normally, ref[0] is a hash, so we can do magic strings here
449 [[ ${ref[0]} == __FAIL__ ]] && continue
450
451 local nonshallow=${EGIT_NONSHALLOW}
452 local ref_param=()
453 if [[ ! ${ref[0]} ]]; then
454 nonshallow=1
455 fi
456
457 # trying to do a shallow clone of a local repo makes git try to
458 # write to the repo. we don't want that to happen.
459 _git-r3_is_local_repo "${r}" && nonshallow=1
460
461 # 1. if we need a non-shallow clone and we have a shallow one,
462 # we need to unshallow it explicitly.
463 # 2. if we want a shallow clone, we just pass '--depth 1'
464 # to the first fetch in the repo. passing '--depth'
465 # to further requests usually results in more data being
466 # downloaded than without it.
467 # 3. if we update a shallow clone, we try without '--depth'
468 # first since that usually transfers less data. however,
469 # we use git-r3_smart_fetch that can switch into '--depth 1'
470 # if that looks beneficial.
471
472 local fetch_command=( git fetch )
473 if [[ ${nonshallow} ]]; then
474 if [[ -f ${GIT_DIR}/shallow ]]; then
475 ref_param+=( --unshallow )
476 fi
477 # fetch all branches
478 ref_param+=( "refs/heads/*:refs/remotes/origin/*" )
479 else
480 # 'git show-ref --heads' returns 1 when there are no branches
481 if ! git show-ref --heads -q; then
482 ref_param+=( --depth 1 )
483 else
484 fetch_command=( _git-r3_smart_fetch )
485 fi
486 fi
487
488 # now, another important thing. we may only fetch a remote
489 # branch directly to a local branch. Otherwise, we need to fetch
490 # the commit and re-create the branch on top of it.
491
492 if [[ ${ref[0]} ]]; then
493 if [[ ${is_branch} ]]; then
494 ref_param+=( -f "${remote_ref}:${local_id}/__main__" )
495 else
496 ref_param+=( "refs/tags/${remote_ref}" )
497 fi
498 fi
499
500 # if ${remote_ref} is branch or tag, ${ref[@]} will contain
501 # the respective commit id. otherwise, it will be an empty
502 # array, so the following won't evaluate to a parameter.
503 set -- "${fetch_command[@]}" --no-tags "${r}" "${ref_param[@]}"
504 echo "${@}" >&2
505 if "${@}"; then
506 if [[ ! ${is_branch} ]]; then
507 set -- git branch -f "${local_id}/__main__" \
508 "${ref[0]:-${remote_ref}}"
509 echo "${@}" >&2
510 if ! "${@}"; then
511 die "Creating branch for ${remote_ref} failed (wrong ref?)."
512 fi
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 GIT_WORK_TREE
585 _git-r3_set_gitdir "${repos[0]}"
586 GIT_WORK_TREE=${out_dir}
587 mkdir -p "${GIT_WORK_TREE}" || die
588
589 einfo "Checking out ${repos[0]} to ${out_dir} ..."
590
591 if ! git cat-file -e refs/heads/"${local_id}"/__main__
592 then
593 if [[ ${EVCS_OFFLINE} ]]; then
594 die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
595 else
596 die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
597 fi
598 fi
599
600 # Note: this is a hack to avoid parallel checkout issues.
601 # I will try to handle it without locks when I have more time.
602 local lockfile=${GIT_DIR}/.git-r3_checkout_lock
603 local lockfile_l=${lockfile}.${BASHPID}
604 touch "${lockfile_l}" || die
605 until ln "${lockfile_l}" "${lockfile}" &>/dev/null; do
606 sleep 1
607 done
608 rm "${lockfile_l}" || die
609
610 set -- git checkout -f "${local_id}"/__main__ .
611 echo "${@}" >&2
612 "${@}"
613 local ret=${?}
614
615 # Remove the lock!
616 rm "${lockfile}" || die
617
618 [[ ${ret} == 0 ]] || die "git checkout ${local_id}/__main__ failed"
619
620 # diff against previous revision (if any)
621 local new_commit_id=$(git rev-parse --verify "${local_id}"/__main__)
622 local old_commit_id=$(
623 git rev-parse --verify "${local_id}"/__old__ 2>/dev/null
624 )
625
626 if [[ ! ${old_commit_id} ]]; then
627 echo "GIT NEW branch -->"
628 echo " repository: ${repos[0]}"
629 echo " at the commit: ${new_commit_id}"
630 else
631 echo "GIT update -->"
632 echo " repository: ${repos[0]}"
633 # write out message based on the revisions
634 if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
635 echo " updating from commit: ${old_commit_id}"
636 echo " to commit: ${new_commit_id}"
637
638 git --no-pager diff --stat \
639 ${old_commit_id}..${new_commit_id}
640 else
641 echo " at the commit: ${new_commit_id}"
642 fi
643 fi
644 git branch -f "${local_id}"/{__old__,__main__} || die
645
646 # recursively checkout submodules
647 if [[ -f ${GIT_WORK_TREE}/.gitmodules ]]; then
648 local submodules
649 _git-r3_set_submodules \
650 "$(<"${GIT_WORK_TREE}"/.gitmodules)"
651
652 while [[ ${submodules[@]} ]]; do
653 local subname=${submodules[0]}
654 local url=${submodules[1]}
655 local path=${submodules[2]}
656
657 if [[ ${url} == ./* || ${url} == ../* ]]; then
658 url=${repos[0]%%/}/${url}
659 fi
660
661 git-r3_checkout "${url}" "${GIT_WORK_TREE}/${path}" \
662 "${local_id}/${subname}"
663
664 submodules=( "${submodules[@]:3}" ) # shift
665 done
666 fi
667
668 # keep this *after* submodules
669 export EGIT_DIR=${GIT_DIR}
670 export EGIT_VERSION=${new_commit_id}
671
672 # create a fake '.git' directory to satisfy 'git rev-parse HEAD'
673 GIT_DIR=${GIT_WORK_TREE}/.git
674 git init || die
675 echo "${EGIT_VERSION}" > "${GIT_WORK_TREE}"/.git/HEAD || die
676 }
677
678 # @FUNCTION: git-r3_peek_remote_ref
679 # @USAGE: [<repo-uri> [<remote-ref>]]
680 # @DESCRIPTION:
681 # Peek the reference in the remote repository and print the matching
682 # (newest) commit SHA1.
683 #
684 # <repo-uri> specifies the repository URIs to fetch from, as a space-
685 # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
686 #
687 # <remote-ref> specifies the remote ref to peek. It is preferred to use
688 # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
689 # for tags. Alternatively, 'HEAD' may be used for upstream default
690 # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
691 # 'HEAD' that is set to a non-null value.
692 #
693 # The operation will be done purely on the remote, without using local
694 # storage. If commit SHA1 is provided as <remote-ref>, the function will
695 # fail due to limitations of git protocol.
696 #
697 # On success, the function returns 0 and writes hexadecimal commit SHA1
698 # to stdout. On failure, the function returns 1.
699 git-r3_peek_remote_ref() {
700 debug-print-function ${FUNCNAME} "$@"
701
702 local repos
703 if [[ ${1} ]]; then
704 repos=( ${1} )
705 elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
706 repos=( "${EGIT_REPO_URI[@]}" )
707 else
708 repos=( ${EGIT_REPO_URI} )
709 fi
710
711 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
712 local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
713
714 [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
715
716 local r success
717 for r in "${repos[@]}"; do
718 einfo "Peeking ${remote_ref} on ${r} ..." >&2
719
720 local is_branch lookup_ref
721 if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
722 then
723 is_branch=1
724 lookup_ref=${remote_ref}
725 else
726 # ls-remote by commit is going to fail anyway,
727 # so we may as well pass refs/tags/ABCDEF...
728 lookup_ref=refs/tags/${remote_ref}
729 fi
730
731 # split on whitespace
732 local ref=(
733 $(git ls-remote "${r}" "${lookup_ref}")
734 )
735
736 if [[ ${ref[0]} ]]; then
737 echo "${ref[0]}"
738 return 0
739 fi
740 done
741
742 return 1
743 }
744
745 git-r3_src_fetch() {
746 debug-print-function ${FUNCNAME} "$@"
747
748 if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
749 ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
750 ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
751 ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
752 ewarn "when git-2 eclass becomes deprecated."
753 fi
754
755 _git-r3_env_setup
756 git-r3_fetch
757 }
758
759 git-r3_src_unpack() {
760 debug-print-function ${FUNCNAME} "$@"
761
762 _git-r3_env_setup
763 git-r3_src_fetch
764 git-r3_checkout
765 }
766
767 # https://bugs.gentoo.org/show_bug.cgi?id=482666
768 git-r3_pkg_outofdate() {
769 debug-print-function ${FUNCNAME} "$@"
770
771 local new_commit_id=$(git-r3_peek_remote_ref)
772 ewarn "old: ${EGIT_VERSION}"
773 ewarn "new: ${new_commit_id}"
774 [[ ${new_commit_id} && ${old_commit_id} ]] || return 2
775
776 [[ ${EGIT_VERSION} != ${new_commit_id} ]]
777 }
778
779 _GIT_R3=1
780 fi

  ViewVC Help
Powered by ViewVC 1.1.20