Lines 8-15
Link Here
|
8 |
# @BLURB: Eclass for fetching and unpacking git repositories. |
8 |
# @BLURB: Eclass for fetching and unpacking git repositories. |
9 |
# @DESCRIPTION: |
9 |
# @DESCRIPTION: |
10 |
# Third generation eclass for easing maitenance of live ebuilds using |
10 |
# Third generation eclass for easing maitenance of live ebuilds using |
11 |
# git as remote repository. The eclass supports lightweight (shallow) |
11 |
# git as remote repository. |
12 |
# clones and bare clones of submodules. |
|
|
13 |
|
12 |
|
14 |
case "${EAPI:-0}" in |
13 |
case "${EAPI:-0}" in |
15 |
0|1|2|3|4|5) |
14 |
0|1|2|3|4|5) |
Lines 83-100
fi
Link Here
|
83 |
# |
82 |
# |
84 |
# EGIT_CHECKOUT_DIR=${WORKDIR}/${P} |
83 |
# EGIT_CHECKOUT_DIR=${WORKDIR}/${P} |
85 |
|
84 |
|
86 |
# @ECLASS-VARIABLE: EGIT_NONSHALLOW |
|
|
87 |
# @DEFAULT_UNSET |
88 |
# @DESCRIPTION: |
89 |
# Disable performing shallow fetches/clones. Shallow clones have |
90 |
# a fair number of limitations. Therefore, if you'd like the eclass to |
91 |
# perform complete clones instead, set this to a non-null value. |
92 |
# |
93 |
# This variable can be set in make.conf and ebuilds. The make.conf |
94 |
# value specifies user-specific default, while ebuilds may use it |
95 |
# to force deep clones when the server does not support shallow clones |
96 |
# (e.g. Google Code). |
97 |
|
98 |
# @FUNCTION: _git-r3_env_setup |
85 |
# @FUNCTION: _git-r3_env_setup |
99 |
# @INTERNAL |
86 |
# @INTERNAL |
100 |
# @DESCRIPTION: |
87 |
# @DESCRIPTION: |
Lines 217-230
_git-r3_set_gitdir() {
Link Here
|
217 |
fi |
204 |
fi |
218 |
|
205 |
|
219 |
addwrite "${EGIT3_STORE_DIR}" |
206 |
addwrite "${EGIT3_STORE_DIR}" |
|
|
207 |
if [[ -e ${GIT_DIR}/shallow ]]; then |
208 |
einfo "${GIT_DIR} was a shallow clone, recreating..." |
209 |
rm -r "${GIT_DIR}" || die |
210 |
fi |
220 |
if [[ ! -d ${GIT_DIR} ]]; then |
211 |
if [[ ! -d ${GIT_DIR} ]]; then |
221 |
mkdir "${GIT_DIR}" || die |
212 |
mkdir "${GIT_DIR}" || die |
222 |
git init --bare || die |
213 |
git init --bare || die |
223 |
|
|
|
224 |
if [[ ! ${EGIT_NONSHALLOW} ]]; then |
225 |
# avoid auto-unshallow :) |
226 |
touch "${GIT_DIR}"/shallow || die |
227 |
fi |
228 |
fi |
214 |
fi |
229 |
} |
215 |
} |
230 |
|
216 |
|
Lines 267-359
_git-r3_set_submodules() {
Link Here
|
267 |
done < <(echo "${data}" | git config -f /dev/fd/0 -l || die) |
253 |
done < <(echo "${data}" | git config -f /dev/fd/0 -l || die) |
268 |
} |
254 |
} |
269 |
|
255 |
|
270 |
# @FUNCTION: _git-r3_smart_fetch |
|
|
271 |
# @USAGE: <git-fetch-args>... |
272 |
# @DESCRIPTION: |
273 |
# Try fetching without '--depth' and switch to '--depth 1' if that |
274 |
# will involve less objects fetched. |
275 |
_git-r3_smart_fetch() { |
276 |
debug-print-function ${FUNCNAME} "$@" |
277 |
|
278 |
local sed_regexp='.*Counting objects: \([0-9]*\), done\..*' |
279 |
|
280 |
# start the main fetch |
281 |
local cmd=( git fetch --progress "${@}" ) |
282 |
echo "${cmd[@]}" >&2 |
283 |
|
284 |
# we copy the output to the 'sed' pipe for parsing. whenever sed finds |
285 |
# the process count, it quits quickly to avoid delays in writing it. |
286 |
# then, we start a dummy 'cat' to keep the pipe alive |
287 |
|
288 |
"${cmd[@]}" 2>&1 \ |
289 |
| tee >( |
290 |
sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}" \ |
291 |
> "${T}"/git-r3_main.count |
292 |
exec cat >/dev/null |
293 |
) & |
294 |
local main_pid=${!} |
295 |
|
296 |
# start the helper process |
297 |
_git-r3_sub_fetch() { |
298 |
# wait for main fetch to get object count; if the server doesn't |
299 |
# output it, we won't even launch the parallel process |
300 |
while [[ ! -s ${T}/git-r3_main.count ]]; do |
301 |
sleep 0.25 |
302 |
done |
303 |
|
304 |
# ok, let's see if parallel fetch gives us smaller count |
305 |
# --dry-run will prevent it from writing to the local clone |
306 |
# and sed should terminate git with SIGPIPE |
307 |
local sub_count=$(git fetch --progress --dry-run --depth 1 "${@}" 2>&1 \ |
308 |
| sed -n -e "/${sed_regexp}/{s/${sed_regexp}/\1/p;q}") |
309 |
local main_count=$(<"${T}"/git-r3_main.count) |
310 |
|
311 |
# let's be real sure that '--depth 1' will be good for us. |
312 |
# note that we have purely objects counts, and '--depth 1' |
313 |
# may involve much bigger objects |
314 |
if [[ ${main_count} && ${main_count} -ge $(( sub_count * 3/2 )) ]] |
315 |
then |
316 |
# signal that we want shallow fetch instead, |
317 |
# and terminate the non-shallow fetch process |
318 |
touch "${T}"/git-r3_want_shallow || die |
319 |
kill ${main_pid} &>/dev/null |
320 |
exit 0 |
321 |
fi |
322 |
|
323 |
exit 1 |
324 |
} |
325 |
_git-r3_sub_fetch "${@}" & |
326 |
local sub_pid=${!} |
327 |
|
328 |
# wait for main process to terminate, either of its own |
329 |
# or by signal from subprocess |
330 |
wait ${main_pid} |
331 |
local main_ret=${?} |
332 |
|
333 |
# wait for subprocess to terminate, killing it if necessary. |
334 |
# if main fetch finished before it, there's no point in keeping |
335 |
# it alive. if main fetch was killed by it, it's done anyway |
336 |
kill ${sub_pid} &>/dev/null |
337 |
wait ${sub_pid} |
338 |
|
339 |
# now see if subprocess wanted to tell us something... |
340 |
if [[ -f ${T}/git-r3_want_shallow ]]; then |
341 |
rm "${T}"/git-r3_want_shallow || die |
342 |
|
343 |
# if fetch finished already (wasn't killed), ignore it |
344 |
[[ ${main_ret} -eq 0 ]] && return 0 |
345 |
|
346 |
# otherwise, restart as shallow fetch |
347 |
einfo "Restarting fetch using --depth 1 to save bandwidth ..." |
348 |
local cmd=( git fetch --progress --depth 1 "${@}" ) |
349 |
echo "${cmd[@]}" >&2 |
350 |
"${cmd[@]}" |
351 |
main_ret=${?} |
352 |
fi |
353 |
|
354 |
return ${main_ret} |
355 |
} |
356 |
|
357 |
# @FUNCTION: _git-r3_is_local_repo |
256 |
# @FUNCTION: _git-r3_is_local_repo |
358 |
# @USAGE: <repo-uri> |
257 |
# @USAGE: <repo-uri> |
359 |
# @INTERNAL |
258 |
# @INTERNAL |
Lines 425-431
git-r3_fetch() {
Link Here
|
425 |
for r in "${repos[@]}"; do |
324 |
for r in "${repos[@]}"; do |
426 |
einfo "Fetching ${remote_ref} from ${r} ..." |
325 |
einfo "Fetching ${remote_ref} from ${r} ..." |
427 |
|
326 |
|
428 |
local is_branch lookup_ref |
327 |
local lookup_ref |
429 |
if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]] |
328 |
if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]] |
430 |
then |
329 |
then |
431 |
is_branch=1 |
330 |
is_branch=1 |
Lines 436-515
git-r3_fetch() {
Link Here
|
436 |
lookup_ref=refs/tags/${remote_ref} |
335 |
lookup_ref=refs/tags/${remote_ref} |
437 |
fi |
336 |
fi |
438 |
|
337 |
|
439 |
# first, try ls-remote to see if ${remote_ref} is a real ref |
338 |
local fetch_command=( |
440 |
# and not a commit id. if it succeeds, we can pass ${remote_ref} |
339 |
git fetch --prune "${r}" |
441 |
# to 'fetch'. otherwise, we will just fetch everything |
340 |
# mirror the remote branches as local branches |
442 |
|
341 |
"refs/heads/*:refs/heads/*" |
443 |
# split on whitespace |
342 |
# pull tags explicitly in order to prune them properly |
444 |
local ref=( |
343 |
"refs/tags/*:refs/tags/*" |
445 |
$(git ls-remote "${r}" "${lookup_ref}" || echo __FAIL__) |
|
|
446 |
) |
344 |
) |
447 |
|
345 |
|
448 |
# normally, ref[0] is a hash, so we can do magic strings here |
346 |
set -- "${fetch_command[@]}" |
449 |
[[ ${ref[0]} == __FAIL__ ]] && continue |
|
|
450 |
|
451 |
local nonshallow=${EGIT_NONSHALLOW} |
452 |
local ref_param=() |
453 |
if [[ ! ${ref[0]} ]]; then |
454 |
nonshallow=1 |
455 |
fi |
456 |
|
457 |
# trying to do a shallow clone of a local repo makes git try to |
458 |
# write to the repo. we don't want that to happen. |
459 |
_git-r3_is_local_repo "${r}" && nonshallow=1 |
460 |
|
461 |
# 1. if we need a non-shallow clone and we have a shallow one, |
462 |
# we need to unshallow it explicitly. |
463 |
# 2. if we want a shallow clone, we just pass '--depth 1' |
464 |
# to the first fetch in the repo. passing '--depth' |
465 |
# to further requests usually results in more data being |
466 |
# downloaded than without it. |
467 |
# 3. if we update a shallow clone, we try without '--depth' |
468 |
# first since that usually transfers less data. however, |
469 |
# we use git-r3_smart_fetch that can switch into '--depth 1' |
470 |
# if that looks beneficial. |
471 |
|
472 |
local fetch_command=( git fetch ) |
473 |
if [[ ${nonshallow} ]]; then |
474 |
if [[ -f ${GIT_DIR}/shallow ]]; then |
475 |
ref_param+=( --unshallow ) |
476 |
fi |
477 |
# fetch all branches |
478 |
ref_param+=( "refs/heads/*:refs/remotes/origin/*" ) |
479 |
else |
480 |
# 'git show-ref --heads' returns 1 when there are no branches |
481 |
if ! git show-ref --heads -q; then |
482 |
ref_param+=( --depth 1 ) |
483 |
else |
484 |
fetch_command=( _git-r3_smart_fetch ) |
485 |
fi |
486 |
fi |
487 |
|
488 |
# now, another important thing. we may only fetch a remote |
489 |
# branch directly to a local branch. Otherwise, we need to fetch |
490 |
# the commit and re-create the branch on top of it. |
491 |
|
492 |
if [[ ${ref[0]} ]]; then |
493 |
if [[ ${is_branch} ]]; then |
494 |
ref_param+=( -f "${remote_ref}:${local_id}/__main__" ) |
495 |
else |
496 |
ref_param+=( "refs/tags/${remote_ref}" ) |
497 |
fi |
498 |
fi |
499 |
|
500 |
# if ${remote_ref} is branch or tag, ${ref[@]} will contain |
501 |
# the respective commit id. otherwise, it will be an empty |
502 |
# array, so the following won't evaluate to a parameter. |
503 |
set -- "${fetch_command[@]}" --no-tags "${r}" "${ref_param[@]}" |
504 |
echo "${@}" >&2 |
347 |
echo "${@}" >&2 |
505 |
if "${@}"; then |
348 |
if "${@}"; then |
506 |
if [[ ! ${is_branch} ]]; then |
349 |
set -- git branch -f "${local_id}/__main__" \ |
507 |
set -- git branch -f "${local_id}/__main__" \ |
350 |
"${ref[0]:-${remote_ref}}" |
508 |
"${ref[0]:-${remote_ref}}" |
351 |
echo "${@}" >&2 |
509 |
echo "${@}" >&2 |
352 |
if ! "${@}"; then |
510 |
if ! "${@}"; then |
353 |
die "Creating branch for ${remote_ref} failed (wrong ref?)." |
511 |
die "Creating branch for ${remote_ref} failed (wrong ref?)." |
|
|
512 |
fi |
513 |
fi |
354 |
fi |
514 |
|
355 |
|
515 |
success=1 |
356 |
success=1 |
516 |
- |
|
|