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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.42 - (hide annotations) (download)
Fri May 23 07:09:07 2014 UTC (13 months, 1 week ago) by mgorny
Branch: MAIN
Changes since 1.41: +10 -1 lines
Give an explanatory error when trying to fetch https:// with dev-vcs/git[-curl]. Bug #510768.

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

  ViewVC Help
Powered by ViewVC 1.1.20