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

Contents of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.48 - (hide annotations) (download)
Wed Feb 4 09:44:24 2015 UTC (2 months, 3 weeks ago) by ulm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.47: +29 -3 lines
Respect the EVCS_UMASK variable to override the default umask when writing to the repository.

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 ulm 1.48 # $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.47 2014/07/28 14:13:50 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 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     local commit=$(git rev-parse "${local_ref}:${path}")
714    
715     if [[ ! ${commit} ]]; then
716     die "Unable to get commit id for submodule ${subname}"
717     fi
718 mgorny 1.43
719     local subrepos
720     _git-r3_set_subrepos "${url}" "${repos[@]}"
721 mgorny 1.1
722 mgorny 1.19 git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}"
723 mgorny 1.1
724     submodules=( "${submodules[@]:3}" ) # shift
725     done
726     fi
727     }
728    
729     # @FUNCTION: git-r3_checkout
730     # @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]]
731     # @DESCRIPTION:
732     # Check the previously fetched tree to the working copy.
733     #
734     # <repo-uri> specifies the repository URIs, as a space-separated list.
735     # The first URI will be used as repository group identifier
736     # and therefore must be used consistently with git-r3_fetch.
737     # The remaining URIs are not used and therefore may be omitted.
738     # When not specified, defaults to ${EGIT_REPO_URI}.
739     #
740     # <checkout-path> specifies the path to place the checkout. It defaults
741     # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}.
742     #
743     # <local-id> needs to specify the local identifier that was used
744     # for respective git-r3_fetch.
745     #
746     # The checkout operation will write to the working copy, and export
747     # the repository state into the environment. If the repository contains
748     # submodules, they will be checked out recursively.
749     git-r3_checkout() {
750     debug-print-function ${FUNCNAME} "$@"
751    
752 mgorny 1.11 local repos
753     if [[ ${1} ]]; then
754     repos=( ${1} )
755     elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
756     repos=( "${EGIT_REPO_URI[@]}" )
757     else
758     repos=( ${EGIT_REPO_URI} )
759 mgorny 1.9 fi
760    
761 mgorny 1.1 local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}}
762 mgorny 1.20 local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}}
763 mgorny 1.1
764 mgorny 1.24 local -x GIT_DIR
765 mgorny 1.9 _git-r3_set_gitdir "${repos[0]}"
766 mgorny 1.1
767     einfo "Checking out ${repos[0]} to ${out_dir} ..."
768    
769 mgorny 1.24 if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then
770 mgorny 1.1 if [[ ${EVCS_OFFLINE} ]]; then
771     die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE."
772     else
773     die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?"
774     fi
775     fi
776 mgorny 1.24 local remote_ref=$(
777     git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__
778     )
779     local new_commit_id=$(
780     git rev-parse --verify refs/git-r3/"${local_id}"/__main__
781     )
782 mgorny 1.1
783 mgorny 1.24 git-r3_sub_checkout() {
784 mgorny 1.25 local orig_repo=${GIT_DIR}
785 mgorny 1.24 local -x GIT_DIR=${out_dir}/.git
786     local -x GIT_WORK_TREE=${out_dir}
787    
788 mgorny 1.26 mkdir -p "${out_dir}" || die
789    
790     # use git init+fetch instead of clone since the latter doesn't like
791     # non-empty directories.
792    
793     git init --quiet || die
794 mgorny 1.28 # setup 'alternates' to avoid copying objects
795     echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die
796     # now copy the refs
797     # [htn]* safely catches heads, tags, notes without complaining
798     # on non-existing ones, and omits internal 'git-r3' ref
799     cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die
800 mgorny 1.26
801 mgorny 1.28 # (no need to copy HEAD, we will set it via checkout)
802 mgorny 1.25
803 mgorny 1.33 if [[ -f ${orig_repo}/shallow ]]; then
804     cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die
805     fi
806    
807 mgorny 1.24 set -- git checkout --quiet
808     if [[ ${remote_ref} ]]; then
809     set -- "${@}" "${remote_ref#refs/heads/}"
810     else
811     set -- "${@}" "${new_commit_id}"
812     fi
813     echo "${@}" >&2
814     "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed"
815     }
816     git-r3_sub_checkout
817 mgorny 1.22
818 mgorny 1.1 local old_commit_id=$(
819 mgorny 1.24 git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__
820 mgorny 1.1 )
821     if [[ ! ${old_commit_id} ]]; then
822     echo "GIT NEW branch -->"
823     echo " repository: ${repos[0]}"
824     echo " at the commit: ${new_commit_id}"
825     else
826 mgorny 1.24 # diff against previous revision
827 mgorny 1.1 echo "GIT update -->"
828     echo " repository: ${repos[0]}"
829     # write out message based on the revisions
830     if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then
831     echo " updating from commit: ${old_commit_id}"
832     echo " to commit: ${new_commit_id}"
833    
834     git --no-pager diff --stat \
835     ${old_commit_id}..${new_commit_id}
836     else
837     echo " at the commit: ${new_commit_id}"
838     fi
839     fi
840 mgorny 1.24 git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die
841 mgorny 1.1
842     # recursively checkout submodules
843 mgorny 1.24 if [[ -f ${out_dir}/.gitmodules ]]; then
844 mgorny 1.1 local submodules
845     _git-r3_set_submodules \
846 mgorny 1.24 "$(<"${out_dir}"/.gitmodules)"
847 mgorny 1.1
848     while [[ ${submodules[@]} ]]; do
849     local subname=${submodules[0]}
850     local url=${submodules[1]}
851     local path=${submodules[2]}
852 mgorny 1.43 local subrepos
853     _git-r3_set_subrepos "${url}" "${repos[@]}"
854 mgorny 1.19
855 mgorny 1.44 git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \
856 mgorny 1.1 "${local_id}/${subname}"
857    
858     submodules=( "${submodules[@]:3}" ) # shift
859     done
860     fi
861    
862     # keep this *after* submodules
863     export EGIT_DIR=${GIT_DIR}
864     export EGIT_VERSION=${new_commit_id}
865     }
866    
867     # @FUNCTION: git-r3_peek_remote_ref
868     # @USAGE: [<repo-uri> [<remote-ref>]]
869     # @DESCRIPTION:
870     # Peek the reference in the remote repository and print the matching
871     # (newest) commit SHA1.
872     #
873     # <repo-uri> specifies the repository URIs to fetch from, as a space-
874     # -separated list. When not specified, defaults to ${EGIT_REPO_URI}.
875     #
876     # <remote-ref> specifies the remote ref to peek. It is preferred to use
877     # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>'
878     # for tags. Alternatively, 'HEAD' may be used for upstream default
879     # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal
880     # 'HEAD' that is set to a non-null value.
881     #
882     # The operation will be done purely on the remote, without using local
883     # storage. If commit SHA1 is provided as <remote-ref>, the function will
884     # fail due to limitations of git protocol.
885     #
886     # On success, the function returns 0 and writes hexadecimal commit SHA1
887     # to stdout. On failure, the function returns 1.
888     git-r3_peek_remote_ref() {
889     debug-print-function ${FUNCNAME} "$@"
890    
891 mgorny 1.11 local repos
892     if [[ ${1} ]]; then
893     repos=( ${1} )
894     elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then
895     repos=( "${EGIT_REPO_URI[@]}" )
896     else
897     repos=( ${EGIT_REPO_URI} )
898 mgorny 1.9 fi
899    
900 mgorny 1.1 local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}}
901     local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}}
902    
903     [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset"
904    
905     local r success
906 mgorny 1.9 for r in "${repos[@]}"; do
907 mgorny 1.1 einfo "Peeking ${remote_ref} on ${r} ..." >&2
908    
909     local is_branch lookup_ref
910     if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]]
911     then
912     is_branch=1
913     lookup_ref=${remote_ref}
914     else
915     # ls-remote by commit is going to fail anyway,
916     # so we may as well pass refs/tags/ABCDEF...
917     lookup_ref=refs/tags/${remote_ref}
918     fi
919    
920     # split on whitespace
921     local ref=(
922     $(git ls-remote "${r}" "${lookup_ref}")
923     )
924    
925     if [[ ${ref[0]} ]]; then
926     echo "${ref[0]}"
927     return 0
928     fi
929     done
930    
931     return 1
932     }
933    
934     git-r3_src_fetch() {
935     debug-print-function ${FUNCNAME} "$@"
936    
937     if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then
938     ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider"
939     ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use"
940     ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones"
941     ewarn "when git-2 eclass becomes deprecated."
942     fi
943    
944     _git-r3_env_setup
945     git-r3_fetch
946     }
947    
948     git-r3_src_unpack() {
949     debug-print-function ${FUNCNAME} "$@"
950    
951     _git-r3_env_setup
952     git-r3_src_fetch
953     git-r3_checkout
954     }
955    
956     # https://bugs.gentoo.org/show_bug.cgi?id=482666
957     git-r3_pkg_outofdate() {
958     debug-print-function ${FUNCNAME} "$@"
959    
960     local new_commit_id=$(git-r3_peek_remote_ref)
961     ewarn "old: ${EGIT_VERSION}"
962     ewarn "new: ${new_commit_id}"
963     [[ ${new_commit_id} && ${old_commit_id} ]] || return 2
964    
965     [[ ${EGIT_VERSION} != ${new_commit_id} ]]
966     }
967    
968     _GIT_R3=1
969     fi

  ViewVC Help
Powered by ViewVC 1.1.20