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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


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

1 mgorny 1.24 # Copyright 1999-2014 Gentoo Foundation
2 mgorny 1.1 # Distributed under the terms of the GNU General Public License v2
3 mgorny 1.32 # $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.31 2014/03/02 11:47:10 mgorny Exp $
4 mgorny 1.1
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 mgorny 1.24 # git as remote repository.
12 mgorny 1.1
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 mgorny 1.14 if [[ ! ${_INHERITED_BY_GIT_2} ]]; then
32 mgorny 1.24 DEPEND="dev-vcs/git"
33 mgorny 1.14 fi
34 mgorny 1.13
35 mgorny 1.31 # @ECLASS-VARIABLE: EGIT_CLONE_TYPE
36     # @DESCRIPTION:
37     # Type of clone that should be used against the remote repository.
38 mgorny 1.32 # This can be either of: 'mirror', 'single'.
39 mgorny 1.31 #
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 mgorny 1.32 #
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 mgorny 1.31
55 mgorny 1.1 # @ECLASS-VARIABLE: EGIT3_STORE_DIR
56     # @DESCRIPTION:
57     # Storage directory for git sources.
58     #
59 mgorny 1.27 # This is intended to be set by user in make.conf. Ebuilds must not set
60     # it.
61     #
62 mgorny 1.1 # EGIT3_STORE_DIR=${DISTDIR}/git3-src
63    
64 mgorny 1.30 # @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 mgorny 1.1 # @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 mgorny 1.9 # Can be a whitespace-separated list or an array.
88     #
89 mgorny 1.1 # 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 mgorny 1.31 # check the clone type
131     case "${EGIT_CLONE_TYPE}" in
132 mgorny 1.32 mirror|single)
133 mgorny 1.31 ;;
134     *)
135     die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}"
136     esac
137    
138 mgorny 1.1 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 mgorny 1.7 # strip the trailing slash
215     repo_name=${repo_name%/}
216    
217 mgorny 1.1 # 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 mgorny 1.8 # gnome.org... who else?
222     browse/*) repo_name=${repo_name#browse/};;
223 mgorny 1.1 # 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 mgorny 1.17 mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die
248 mgorny 1.1 ) || die "Unable to create ${EGIT3_STORE_DIR}"
249     fi
250    
251     addwrite "${EGIT3_STORE_DIR}"
252 mgorny 1.24 if [[ -e ${GIT_DIR}/shallow ]]; then
253     einfo "${GIT_DIR} was a shallow clone, recreating..."
254     rm -r "${GIT_DIR}" || die
255     fi
256 mgorny 1.1 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 mgorny 1.15 # skip modules that have 'update = none', bug #487262.
287     local upd=$(echo "${data}" | git config -f /dev/fd/0 \
288 mgorny 1.18 submodule."${subname}".update)
289 mgorny 1.15 [[ ${upd} == none ]] && continue
290    
291 mgorny 1.1 submodules+=(
292     "${subname}"
293     "$(echo "${data}" | git config -f /dev/fd/0 \
294 mgorny 1.17 submodule."${subname}".url || die)"
295 mgorny 1.1 "$(echo "${data}" | git config -f /dev/fd/0 \
296 mgorny 1.17 submodule."${subname}".path || die)"
297 mgorny 1.1 )
298 mgorny 1.17 done < <(echo "${data}" | git config -f /dev/fd/0 -l || die)
299 mgorny 1.1 }
300    
301 mgorny 1.23 # @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 mgorny 1.32 # @FUNCTION: _git-r3_find_head
316     # @USAGE: <head-ref>
317 mgorny 1.29 # @INTERNAL
318     # @DESCRIPTION:
319 mgorny 1.32 # 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 mgorny 1.29 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 mgorny 1.32 done
343 mgorny 1.29
344     if [[ ! ${matching_ref} ]]; then
345     die "Unable to find a matching branch for remote HEAD (${head_hash})"
346     fi
347    
348 mgorny 1.32 echo "${matching_ref}"
349 mgorny 1.29 }
350    
351 mgorny 1.1 # @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 mgorny 1.20 # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}.
372 mgorny 1.1 # 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 mgorny 1.16 [[ ${EVCS_OFFLINE} ]] && return
383    
384 mgorny 1.11 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 mgorny 1.9 fi
392    
393 mgorny 1.1 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
394     local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
395 mgorny 1.20 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
396 mgorny 1.24 local local_ref=refs/git-r3/${local_id}/__main__
397 mgorny 1.1
398     [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
399    
400     local -x GIT_DIR
401 mgorny 1.9 _git-r3_set_gitdir "${repos[0]}"
402 mgorny 1.1
403 mgorny 1.30 # 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 mgorny 1.1 # try to fetch from the remote
412     local r success
413 mgorny 1.9 for r in "${repos[@]}"; do
414 mgorny 1.24 einfo "Fetching ${r} ..."
415 mgorny 1.1
416 mgorny 1.32 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 mgorny 1.1
471 mgorny 1.24 set -- "${fetch_command[@]}"
472     echo "${@}" >&2
473     if "${@}"; then
474 mgorny 1.32 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 mgorny 1.29
496 mgorny 1.24 # 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 mgorny 1.3 else
506 mgorny 1.24 # otherwise, we were likely given a commit id
507     set -- git update-ref --no-deref "${local_ref}" "${remote_ref}"
508 mgorny 1.2 fi
509    
510 mgorny 1.24 echo "${@}" >&2
511     if ! "${@}"; then
512     die "Referencing ${remote_ref} failed (wrong ref?)."
513 mgorny 1.1 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 mgorny 1.19 if [[ ${url} == ./* || ${url} == ../* ]]; then
537     local subrepos=( "${repos[@]/%//${url}}" )
538     else
539     local subrepos=( "${url}" )
540     fi
541 mgorny 1.1
542 mgorny 1.19 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
543 mgorny 1.1
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 mgorny 1.11 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 mgorny 1.9 fi
580    
581 mgorny 1.1 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
582 mgorny 1.20 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
583 mgorny 1.1
584 mgorny 1.24 local -x GIT_DIR
585 mgorny 1.9 _git-r3_set_gitdir "${repos[0]}"
586 mgorny 1.1
587     einfo "Checking out ${repos[0]} to ${out_dir} ..."
588    
589 mgorny 1.24 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
590 mgorny 1.1 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 mgorny 1.24 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 mgorny 1.1
603 mgorny 1.24 git-r3_sub_checkout() {
604 mgorny 1.25 local orig_repo=${GIT_DIR}
605 mgorny 1.24 local -x GIT_DIR=${out_dir}/.git
606     local -x GIT_WORK_TREE=${out_dir}
607    
608 mgorny 1.26 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 mgorny 1.28 # 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 mgorny 1.26
621 mgorny 1.28 # (no need to copy HEAD, we will set it via checkout)
622 mgorny 1.25
623 mgorny 1.24 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 mgorny 1.22
634 mgorny 1.1 local old_commit_id=$(
635 mgorny 1.24 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
636 mgorny 1.1 )
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 mgorny 1.24 # diff against previous revision
643 mgorny 1.1 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 mgorny 1.24 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
657 mgorny 1.1
658     # recursively checkout submodules
659 mgorny 1.24 if [[ -f ${out_dir}/.gitmodules ]]; then
660 mgorny 1.1 local submodules
661     _git-r3_set_submodules \
662 mgorny 1.24 "$(<"${out_dir}"/.gitmodules)"
663 mgorny 1.1
664     while [[ ${submodules[@]} ]]; do
665     local subname=${submodules[0]}
666     local url=${submodules[1]}
667     local path=${submodules[2]}
668    
669 mgorny 1.19 if [[ ${url} == ./* || ${url} == ../* ]]; then
670     url=${repos[0]%%/}/${url}
671     fi
672    
673 mgorny 1.24 git-r3_checkout "${url}" "${out_dir}/${path}" \
674 mgorny 1.1 "${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 mgorny 1.11 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 mgorny 1.9 fi
717    
718 mgorny 1.1 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 mgorny 1.9 for r in "${repos[@]}"; do
725 mgorny 1.1 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