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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.50 - (hide annotations) (download)
Thu Jul 9 20:21:05 2015 UTC (3 weeks, 4 days ago) by mgorny
Branch: MAIN
CVS Tags: HEAD
Changes since 1.49: +24 -12 lines
Do not attempt to use submodules for which the checkout path does not exist (has been removed), bug #551100.

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

  ViewVC Help
Powered by ViewVC 1.1.20