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

Diff of /eclass/git-r3.eclass

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.2 Revision 1.7
1# Copyright 1999-2013 Gentoo Foundation 1# Copyright 1999-2013 Gentoo Foundation
2# Distributed under the terms of the GNU General Public License v2 2# Distributed under the terms of the GNU General Public License v2
3# $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.2 2013/09/05 22:40:12 mgorny Exp $ 3# $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.7 2013/09/19 09:42:32 mgorny Exp $
4 4
5# @ECLASS: git-r3.eclass 5# @ECLASS: git-r3.eclass
6# @MAINTAINER: 6# @MAINTAINER:
7# Michał Górny <mgorny@gentoo.org> 7# Michał Górny <mgorny@gentoo.org>
8# @BLURB: Eclass for fetching and unpacking git repositories. 8# @BLURB: Eclass for fetching and unpacking git repositories.
168# a canonical URI to the repository. 168# a canonical URI to the repository.
169_git-r3_set_gitdir() { 169_git-r3_set_gitdir() {
170 debug-print-function ${FUNCNAME} "$@" 170 debug-print-function ${FUNCNAME} "$@"
171 171
172 local repo_name=${1#*://*/} 172 local repo_name=${1#*://*/}
173
174 # strip the trailing slash
175 repo_name=${repo_name%/}
173 176
174 # strip common prefixes to make paths more likely to match 177 # strip common prefixes to make paths more likely to match
175 # e.g. git://X/Y.git vs https://X/git/Y.git 178 # e.g. git://X/Y.git vs https://X/git/Y.git
176 # (but just one of the prefixes) 179 # (but just one of the prefixes)
177 case "${repo_name}" in 180 case "${repo_name}" in
206 addwrite "${EGIT3_STORE_DIR}" 209 addwrite "${EGIT3_STORE_DIR}"
207 if [[ ! -d ${GIT_DIR} ]]; then 210 if [[ ! -d ${GIT_DIR} ]]; then
208 mkdir "${GIT_DIR}" || die 211 mkdir "${GIT_DIR}" || die
209 git init --bare || die 212 git init --bare || die
210 213
214 if [[ ! ${EGIT_NONSHALLOW} ]]; then
211 # avoid auto-unshallow :) 215 # avoid auto-unshallow :)
212 touch "${GIT_DIR}"/shallow || die 216 touch "${GIT_DIR}"/shallow || die
217 fi
213 fi 218 fi
214} 219}
215 220
216# @FUNCTION: _git-r3_set_submodules 221# @FUNCTION: _git-r3_set_submodules
217# @USAGE: <file-contents> 222# @USAGE: <file-contents>
243 submodule."${subname}".url)" 248 submodule."${subname}".url)"
244 "$(echo "${data}" | git config -f /dev/fd/0 \ 249 "$(echo "${data}" | git config -f /dev/fd/0 \
245 submodule."${subname}".path)" 250 submodule."${subname}".path)"
246 ) 251 )
247 done < <(echo "${data}" | git config -f /dev/fd/0 -l) 252 done < <(echo "${data}" | git config -f /dev/fd/0 -l)
253}
254
255# @FUNCTION: _git-r3_smart_fetch
256# @USAGE: <git-fetch-args>...
257# @DESCRIPTION:
258# Try fetching without '--depth' and switch to '--depth 1' if that
259# will involve less objects fetched.
260_git-r3_smart_fetch() {
261 debug-print-function ${FUNCNAME} "$@"
262
263 local sed_regexp='.*Counting objects: \([0-9]*\), done\..*'
264
265 # start the main fetch
266 local cmd=( git fetch --progress "${@}" )
267 echo "${cmd[@]}" >&2
268
269 # we copy the output to the 'sed' pipe for parsing. whenever sed finds
270 # the process count, it quits quickly to avoid delays in writing it.
271 # then, we start a dummy 'cat' to keep the pipe alive
272
273 "${cmd[@]}" 2>&1 \
274 | tee >(
275 sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}" \
276 > "${T}"/git-r3_main.count
277 exec cat >/dev/null
278 ) &
279 local main_pid=${!}
280
281 # start the helper process
282 _git-r3_sub_fetch() {
283 # wait for main fetch to get object count; if the server doesn't
284 # output it, we won't even launch the parallel process
285 while [[ ! -s ${T}/git-r3_main.count ]]; do
286 sleep 0.25
287 done
288
289 # ok, let's see if parallel fetch gives us smaller count
290 # --dry-run will prevent it from writing to the local clone
291 # and sed should terminate git with SIGPIPE
292 local sub_count=$(git fetch --progress --dry-run --depth 1 "${@}" 2>&1 \
293 | sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}")
294 local main_count=$(<"${T}"/git-r3_main.count)
295
296 # let's be real sure that '--depth 1' will be good for us.
297 # note that we have purely objects counts, and '--depth 1'
298 # may involve much bigger objects
299 if [[ ${main_count} && ${main_count} -ge $(( sub_count * 3/2 )) ]]
300 then
301 # signal that we want shallow fetch instead,
302 # and terminate the non-shallow fetch process
303 touch "${T}"/git-r3_want_shallow || die
304 kill ${main_pid} &>/dev/null
305 exit 0
306 fi
307
308 exit 1
309 }
310 _git-r3_sub_fetch "${@}" &
311 local sub_pid=${!}
312
313 # wait for main process to terminate, either of its own
314 # or by signal from subprocess
315 wait ${main_pid}
316 local main_ret=${?}
317
318 # wait for subprocess to terminate, killing it if necessary.
319 # if main fetch finished before it, there's no point in keeping
320 # it alive. if main fetch was killed by it, it's done anyway
321 kill ${sub_pid} &>/dev/null
322 wait ${sub_pid}
323
324 # now see if subprocess wanted to tell us something...
325 if [[ -f ${T}/git-r3_want_shallow ]]; then
326 rm "${T}"/git-r3_want_shallow || die
327
328 # if fetch finished already (wasn't killed), ignore it
329 [[ ${main_ret} -eq 0 ]] && return 0
330
331 # otherwise, restart as shallow fetch
332 einfo "Restarting fetch using --depth 1 to save bandwidth ..."
333 local cmd=( git fetch --progress --depth 1 "${@}" )
334 echo "${cmd[@]}" >&2
335 "${cmd[@]}"
336 main_ret=${?}
337 fi
338
339 return ${main_ret}
248} 340}
249 341
250# @FUNCTION: git-r3_fetch 342# @FUNCTION: git-r3_fetch
251# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]] 343# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]]
252# @DESCRIPTION: 344# @DESCRIPTION:
309 # and not a commit id. if it succeeds, we can pass ${remote_ref} 401 # and not a commit id. if it succeeds, we can pass ${remote_ref}
310 # to 'fetch'. otherwise, we will just fetch everything 402 # to 'fetch'. otherwise, we will just fetch everything
311 403
312 # split on whitespace 404 # split on whitespace
313 local ref=( 405 local ref=(
314 $(git ls-remote "${r}" "${lookup_ref}") 406 $(git ls-remote "${r}" "${lookup_ref}" || echo __FAIL__)
315 ) 407 )
316 408
409 # normally, ref[0] is a hash, so we can do magic strings here
410 [[ ${ref[0]} == __FAIL__ ]] && continue
411
412 local nonshallow=${EGIT_NONSHALLOW}
317 local ref_param=() 413 local ref_param=()
318 if [[ ! ${ref[0]} ]]; then 414 if [[ ! ${ref[0]} ]]; then
319 local EGIT_NONSHALLOW=1 415 nonshallow=1
320 fi 416 fi
321 417
322 # 1. if we need a non-shallow clone and we have a shallow one, 418 # 1. if we need a non-shallow clone and we have a shallow one,
323 # we need to unshallow it explicitly. 419 # we need to unshallow it explicitly.
324 # 2. if we want a shallow clone, we just pass '--depth 1' 420 # 2. if we want a shallow clone, we just pass '--depth 1'
325 # to the first fetch in the repo. passing '--depth' 421 # to the first fetch in the repo. passing '--depth'
326 # to further requests usually results in more data being 422 # to further requests usually results in more data being
327 # downloaded than without it. 423 # downloaded than without it.
328 # 3. in any other case, we just do plain 'git fetch' and let 424 # 3. if we update a shallow clone, we try without '--depth'
329 # git to do its best (on top of shallow or non-shallow repo). 425 # first since that usually transfers less data. however,
426 # we use git-r3_smart_fetch that can switch into '--depth 1'
427 # if that looks beneficial.
330 428
331 if [[ ${EGIT_NONSHALLOW} ]]; then 429 local fetch_command=( git fetch )
430 if [[ ${nonshallow} ]]; then
332 if [[ -f ${GIT_DIR}/shallow ]]; then 431 if [[ -f ${GIT_DIR}/shallow ]]; then
333 ref_param+=( --unshallow ) 432 ref_param+=( --unshallow )
334 fi 433 fi
335 else 434 else
336 # 'git show-ref --heads' returns 1 when there are no branches 435 # 'git show-ref --heads' returns 1 when there are no branches
337 if ! git show-ref --heads -q; then 436 if ! git show-ref --heads -q; then
338 ref_param+=( --depth 1 ) 437 ref_param+=( --depth 1 )
438 else
439 fetch_command=( _git-r3_smart_fetch )
339 fi 440 fi
340 fi 441 fi
341 442
342 # now, another important thing. we may only fetch a remote 443 # now, another important thing. we may only fetch a remote
343 # branch directly to a local branch. Otherwise, we need to fetch 444 # branch directly to a local branch. Otherwise, we need to fetch
352 fi 453 fi
353 454
354 # if ${remote_ref} is branch or tag, ${ref[@]} will contain 455 # if ${remote_ref} is branch or tag, ${ref[@]} will contain
355 # the respective commit id. otherwise, it will be an empty 456 # the respective commit id. otherwise, it will be an empty
356 # array, so the following won't evaluate to a parameter. 457 # array, so the following won't evaluate to a parameter.
357 set -- git fetch --no-tags "${r}" "${ref_param[@]}" 458 set -- "${fetch_command[@]}" --no-tags "${r}" "${ref_param[@]}"
358 echo "${@}" >&2 459 echo "${@}" >&2
359 if "${@}"; then 460 if "${@}"; then
360 if [[ ! ${is_branch} ]]; then 461 if [[ ! ${is_branch} ]]; then
361 set -- git branch -f "${local_id}/__main__" \ 462 set -- git branch -f "${local_id}/__main__" \
362 "${ref[0]:-${remote_ref}}" 463 "${ref[0]:-${remote_ref}}"

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.7

  ViewVC Help
Powered by ViewVC 1.1.20