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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.33 - (hide annotations) (download)
Sun Mar 2 11:48:05 2014 UTC (9 months, 3 weeks ago) by mgorny
Branch: MAIN
Changes since 1.32: +28 -10 lines
Support EGIT_CLONE_TYPE=shallow.

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

  ViewVC Help
Powered by ViewVC 1.1.20