blob: 45783256c8885a529a81927d217a44b1370769f0 [file] [log] [blame]
Mandeep Singh Bainesfb0f6702010-06-21 14:47:32 -07001# Copyright 1999-2009 Gentoo Foundation
2# Distributed under the terms of the GNU General Public License v2
3# $Header: /var/cvsroot/gentoo-x86/eclass/subversion.eclass,v 1.67 2009/05/10 20:33:38 arfrever Exp $
4
5# @ECLASS: subversion.eclass
6# @MAINTAINER:
7# Akinori Hattori <hattya@gentoo.org>
8# Bo Ørsted Andresen <zlin@gentoo.org>
9# Arfrever Frehtes Taifersar Arahesis <arfrever@gentoo.org>
10#
11# Original Author: Akinori Hattori <hattya@gentoo.org>
12#
13# @BLURB: The subversion eclass is written to fetch software sources from subversion repositories
14# @DESCRIPTION:
15# The subversion eclass provides functions to fetch, patch and bootstrap
16# software sources from subversion repositories.
17
18inherit eutils
19
20ESVN="${ECLASS}"
21
22case "${EAPI:-0}" in
23 0|1)
24 EXPORT_FUNCTIONS src_unpack pkg_preinst
25 ;;
26 *)
27 EXPORT_FUNCTIONS src_unpack src_prepare pkg_preinst
28 ;;
29esac
30
31DESCRIPTION="Based on the ${ECLASS} eclass"
32
Mike Frysinger7880f272011-12-19 14:21:19 -050033SUBVERSION_DEPEND="dev-vcs/subversion[webdav-neon,webdav-serf]
Mandeep Singh Bainesfb0f6702010-06-21 14:47:32 -070034 net-misc/rsync"
35
36if [[ -z "${ESVN_DISABLE_DEPENDENCIES}" ]]; then
37 DEPEND="${SUBVERSION_DEPEND}"
38fi
39
40# @ECLASS-VARIABLE: ESVN_STORE_DIR
41# @DESCRIPTION:
42# subversion sources store directory. Users may override this in /etc/make.conf
Ken Mixterb7c7d172010-07-16 15:33:35 -070043if [[ -z ${ESVN_STORE_DIR} ]]; then
44 ESVN_STORE_DIR="${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}/svn-src"
45 # Pick a directory with the same permissions now and in the future. Note
46 # that we cannot just use USERNAME because the eventual effective user when
47 # doing the svn commands may change - PORTAGE_USERNAME has not taken effect
48 # yet. Further complicating things, if features userpriv is not set,
49 # PORTAGE_USERNAME is going to be ignored. We assume that if we enable
50 # userpriv in the future, we will also set PORTAGE_USERNAME to something
51 # other than "portage".
52 # TODO: remove this once we are using consistent users and userpriv settings
53 # for emerge and emerge-${BOARD}.
54 ESVN_STORE_DIR="${ESVN_STORE_DIR}/${PORTAGE_USERNAME:-portage}"
55fi
Mandeep Singh Bainesfb0f6702010-06-21 14:47:32 -070056
57# @ECLASS-VARIABLE: ESVN_FETCH_CMD
58# @DESCRIPTION:
59# subversion checkout command
60ESVN_FETCH_CMD="svn checkout"
61
62# @ECLASS-VARIABLE: ESVN_UPDATE_CMD
63# @DESCRIPTION:
64# subversion update command
65ESVN_UPDATE_CMD="svn update"
66
67# @ECLASS-VARIABLE: ESVN_SWITCH_CMD
68# @DESCRIPTION:
69# subversion switch command
70ESVN_SWITCH_CMD="svn switch"
71
72# @ECLASS-VARIABLE: ESVN_OPTIONS
73# @DESCRIPTION:
74# the options passed to checkout or update. If you want a specific revision see
75# ESVN_REPO_URI instead of using -rREV.
76ESVN_OPTIONS="${ESVN_OPTIONS:-}"
77
78# @ECLASS-VARIABLE: ESVN_REPO_URI
79# @DESCRIPTION:
80# repository uri
81#
82# e.g. http://foo/trunk, svn://bar/trunk, svn://bar/branch/foo@1234
83#
84# supported protocols:
85# http://
86# https://
87# svn://
88# svn+ssh://
89#
90# to peg to a specific revision, append @REV to the repo's uri
91ESVN_REPO_URI="${ESVN_REPO_URI:-}"
92
93# @ECLASS-VARIABLE: ESVN_REVISION
94# @DESCRIPTION:
95# User configurable revision checkout or update to from the repository
96#
97# Useful for live svn or trunk svn ebuilds allowing the user to peg
98# to a specific revision
99#
100# Note: This should never be set in an ebuild!
101ESVN_REVISION="${ESVN_REVISION:-}"
102
103# @ECLASS-VARIABLE: ESVN_USER
104# @DESCRIPTION:
105# User name
106ESVN_USER="${ESVN_USER:-}"
107
108# @ECLASS-VARIABLE: ESVN_PASSWORD
109# @DESCRIPTION:
110# Password
111ESVN_PASSWORD="${ESVN_PASSWORD:-}"
112
113# @ECLASS-VARIABLE: ESVN_PROJECT
114# @DESCRIPTION:
115# project name of your ebuild (= name space)
116#
117# subversion eclass will check out the subversion repository like:
118#
119# ${ESVN_STORE_DIR}/${ESVN_PROJECT}/${ESVN_REPO_URI##*/}
120#
121# so if you define ESVN_REPO_URI as http://svn.collab.net/repo/svn/trunk or
122# http://svn.collab.net/repo/svn/trunk/. and PN is subversion-svn.
123# it will check out like:
124#
125# ${ESVN_STORE_DIR}/subversion/trunk
126#
127# this is not used in order to declare the name of the upstream project.
128# so that you can declare this like:
129#
130# # jakarta commons-loggin
131# ESVN_PROJECT=commons/logging
132#
133# default: ${PN/-svn}.
134ESVN_PROJECT="${ESVN_PROJECT:-${PN/-svn}}"
135
136# @ECLASS-VARIABLE: ESVN_BOOTSTRAP
137# @DESCRIPTION:
138# bootstrap script or command like autogen.sh or etc..
139ESVN_BOOTSTRAP="${ESVN_BOOTSTRAP:-}"
140
141# @ECLASS-VARIABLE: ESVN_PATCHES
142# @DESCRIPTION:
143# subversion eclass can apply patches in subversion_bootstrap().
144# you can use regexp in this variable like *.diff or *.patch or etc.
145# NOTE: patches will be applied before ESVN_BOOTSTRAP is processed.
146#
147# Patches are searched both in ${PWD} and ${FILESDIR}, if not found in either
148# location, the installation dies.
149ESVN_PATCHES="${ESVN_PATCHES:-}"
150
151# @ECLASS-VARIABLE: ESVN_RESTRICT
152# @DESCRIPTION:
153# this should be a space delimited list of subversion eclass features to
154# restrict.
155# export)
156# don't export the working copy to S.
157ESVN_RESTRICT="${ESVN_RESTRICT:-}"
158
159# @ECLASS-VARIABLE: ESVN_DISABLE_DEPENDENCIES
160# @DESCRIPTION:
161# Set this variable to a non-empty value to disable the automatic inclusion of
162# Subversion in dependencies.
163ESVN_DISABLE_DEPENDENCIES="${ESVN_DISABLE_DEPENDENCIES:-}"
164
165# @ECLASS-VARIABLE: ESVN_OFFLINE
166# @DESCRIPTION:
167# Set this variable to a non-empty value to disable the automatic updating of
168# an svn source tree. This is intended to be set outside the subversion source
169# tree by users.
170ESVN_OFFLINE="${ESVN_OFFLINE:-${ESCM_OFFLINE}}"
171
172# @ECLASS-VARIABLE: ESVN_UP_FREQ
173# @DESCRIPTION:
174# Set the minimum number of hours between svn up'ing in any given svn module. This is particularly
175# useful for split KDE ebuilds where we want to ensure that all submodules are compiled for the same
176# revision. It should also be kept user overrideable.
177ESVN_UP_FREQ="${ESVN_UP_FREQ:=}"
178
179# @ECLASS-VARIABLE: ESCM_LOGDIR
180# @DESCRIPTION:
181# User configuration variable. If set to a path such as e.g. /var/log/scm any
182# package inheriting from subversion.eclass will record svn revision to
183# ${CATEGORY}/${PN}.log in that path in pkg_preinst. This is not supposed to be
184# set by ebuilds/eclasses. It defaults to empty so users need to opt in.
185ESCM_LOGDIR="${ESCM_LOGDIR:=}"
186
187# @FUNCTION: subversion_fetch
188# @USAGE: [repo_uri] [destination]
189# @DESCRIPTION:
190# Wrapper function to fetch sources from subversion via svn checkout or svn update,
191# depending on whether there is an existing working copy in ${ESVN_STORE_DIR}.
192#
193# Can take two optional parameters:
194# repo_uri - a repository URI. default is ESVN_REPO_URI.
195# destination - a check out path in S.
196subversion_fetch() {
197 local repo_uri="$(subversion__get_repository_uri "${1:-${ESVN_REPO_URI}}")"
198 local revision="$(subversion__get_peg_revision "${1:-${ESVN_REPO_URI}}")"
199 local S_dest="${2}"
200
201 if [[ -z ${repo_uri} ]]; then
202 die "${ESVN}: ESVN_REPO_URI (or specified URI) is empty."
203 fi
204
205 [[ -n "${ESVN_REVISION}" ]] && revision="${ESVN_REVISION}"
206
207 # check for the protocol
208 local protocol="${repo_uri%%:*}"
209
210 case "${protocol}" in
211 http|https)
Mandeep Singh Bainesfb0f6702010-06-21 14:47:32 -0700212 ;;
213 svn|svn+ssh)
214 ;;
215 *)
216 die "${ESVN}: fetch from '${protocol}' is not yet implemented."
217 ;;
218 esac
219
220 addread "/etc/subversion"
221 addwrite "${ESVN_STORE_DIR}"
Ken Mixterb7c7d172010-07-16 15:33:35 -0700222 # Also make the /var/lib/portage/distfiles/svn-src directory writeable in sandbox
223 # so we can create it if necessary.
224 addwrite "$(dirname ${ESVN_STORE_DIR})"
Mandeep Singh Bainesfb0f6702010-06-21 14:47:32 -0700225
226 if [[ ! -d ${ESVN_STORE_DIR} ]]; then
227 debug-print "${FUNCNAME}: initial checkout. creating subversion directory"
228 mkdir -p "${ESVN_STORE_DIR}" || die "${ESVN}: can't mkdir ${ESVN_STORE_DIR}."
229 fi
230
231 cd "${ESVN_STORE_DIR}" || die "${ESVN}: can't chdir to ${ESVN_STORE_DIR}"
232
233 local wc_path="$(subversion__get_wc_path "${repo_uri}")"
234 local options="${ESVN_OPTIONS} --config-dir ${ESVN_STORE_DIR}/.subversion"
235
236 [[ -n "${revision}" ]] && options="${options} -r ${revision}"
237
238 if [[ "${ESVN_OPTIONS}" = *-r* ]]; then
239 ewarn "\${ESVN_OPTIONS} contains -r, this usage is unsupported. Please"
240 ewarn "see \${ESVN_REPO_URI}"
241 fi
242
Mike Frysinger7880f272011-12-19 14:21:19 -0500243 if has_version ">=dev-vcs/subversion-1.6.0"; then
Mandeep Singh Bainesfb0f6702010-06-21 14:47:32 -0700244 options="${options} --config-option=config:auth:password-stores="
245 fi
246
247 debug-print "${FUNCNAME}: wc_path = \"${wc_path}\""
248 debug-print "${FUNCNAME}: ESVN_OPTIONS = \"${ESVN_OPTIONS}\""
249 debug-print "${FUNCNAME}: options = \"${options}\""
250
251 if [[ ! -d ${wc_path}/.svn ]]; then
252 if [[ -n ${ESVN_OFFLINE} ]]; then
253 ewarn "ESVN_OFFLINE cannot be used when there is no existing checkout."
254 fi
255 # first check out
256 einfo "subversion check out start -->"
257 einfo " repository: ${repo_uri}${revision:+@}${revision}"
258
259 debug-print "${FUNCNAME}: ${ESVN_FETCH_CMD} ${options} ${repo_uri}"
260
261 mkdir -p "${ESVN_PROJECT}" || die "${ESVN}: can't mkdir ${ESVN_PROJECT}."
262 cd "${ESVN_PROJECT}" || die "${ESVN}: can't chdir to ${ESVN_PROJECT}"
263 if [[ -n "${ESVN_USER}" ]]; then
264 ${ESVN_FETCH_CMD} ${options} --username "${ESVN_USER}" --password "${ESVN_PASSWORD}" "${repo_uri}" || die "${ESVN}: can't fetch to ${wc_path} from ${repo_uri}."
265 else
266 ${ESVN_FETCH_CMD} ${options} "${repo_uri}" || die "${ESVN}: can't fetch to ${wc_path} from ${repo_uri}."
267 fi
Mandeep Singh Bainesfb0f6702010-06-21 14:47:32 -0700268
269 elif [[ -n ${ESVN_OFFLINE} ]]; then
270 svn upgrade "${wc_path}" &>/dev/null
271 svn cleanup "${wc_path}" &>/dev/null
272 subversion_wc_info "${repo_uri}" || die "${ESVN}: unknown problem occurred while accessing working copy."
273 if [[ -n ${ESVN_REVISION} && ${ESVN_REVISION} != ${ESVN_WC_REVISION} ]]; then
274 die "${ESVN}: You requested off-line updating and revision ${ESVN_REVISION} but only revision ${ESVN_WC_REVISION} is available locally."
275 fi
276 einfo "Fetching disabled: Using existing repository copy at revision ${ESVN_WC_REVISION}."
277 else
278 svn upgrade "${wc_path}" &>/dev/null
279 svn cleanup "${wc_path}" &>/dev/null
280 subversion_wc_info "${repo_uri}" || die "${ESVN}: unknown problem occurred while accessing working copy."
281
282 local esvn_up_freq=
283 if [[ -n ${ESVN_UP_FREQ} ]]; then
284 if [[ -n ${ESVN_UP_FREQ//[[:digit:]]} ]]; then
285 die "${ESVN}: ESVN_UP_FREQ must be an integer value corresponding to the minimum number of hours between svn up."
286 elif [[ -z $(find "${wc_path}/.svn/entries" -mmin "+$((ESVN_UP_FREQ*60))") ]]; then
287 einfo "Fetching disabled since ${ESVN_UP_FREQ} hours has not passed since last update."
288 einfo "Using existing repository copy at revision ${ESVN_WC_REVISION}."
289 esvn_up_freq=no_update
290 fi
291 fi
292
293 if [[ -z ${esvn_up_freq} ]]; then
294 if [[ ${ESVN_WC_URL} != $(subversion__get_repository_uri "${repo_uri}") ]]; then
295 einfo "subversion switch start -->"
296 einfo " old repository: ${ESVN_WC_URL}@${ESVN_WC_REVISION}"
297 einfo " new repository: ${repo_uri}${revision:+@}${revision}"
298
299 debug-print "${FUNCNAME}: ${ESVN_SWITCH_CMD} ${options} ${repo_uri}"
300
301 cd "${wc_path}" || die "${ESVN}: can't chdir to ${wc_path}"
302 if [[ -n "${ESVN_USER}" ]]; then
303 ${ESVN_SWITCH_CMD} ${options} --username "${ESVN_USER}" --password "${ESVN_PASSWORD}" ${repo_uri} || die "${ESVN}: can't update ${wc_path} from ${repo_uri}."
304 else
305 ${ESVN_SWITCH_CMD} ${options} ${repo_uri} || die "${ESVN}: can't update ${wc_path} from ${repo_uri}."
306 fi
307 else
308 # update working copy
309 einfo "subversion update start -->"
310 einfo " repository: ${repo_uri}${revision:+@}${revision}"
311
312 debug-print "${FUNCNAME}: ${ESVN_UPDATE_CMD} ${options}"
313
314 cd "${wc_path}" || die "${ESVN}: can't chdir to ${wc_path}"
315 if [[ -n "${ESVN_USER}" ]]; then
316 ${ESVN_UPDATE_CMD} ${options} --username "${ESVN_USER}" --password "${ESVN_PASSWORD}" || die "${ESVN}: can't update ${wc_path} from ${repo_uri}."
317 else
318 ${ESVN_UPDATE_CMD} ${options} || die "${ESVN}: can't update ${wc_path} from ${repo_uri}."
319 fi
320 fi
321 fi
322 fi
323
324 einfo " working copy: ${wc_path}"
325
326 if ! has "export" ${ESVN_RESTRICT}; then
327 cd "${wc_path}" || die "${ESVN}: can't chdir to ${wc_path}"
328
329 local S="${S}/${S_dest}"
330 mkdir -p "${S}"
331
332 # export to the ${WORKDIR}
333 #* "svn export" has a bug. see http://bugs.gentoo.org/119236
334 #* svn export . "${S}" || die "${ESVN}: can't export to ${S}."
335 rsync -rlpgo --exclude=".svn/" . "${S}" || die "${ESVN}: can't export to ${S}."
336 fi
337
338 echo
339}
340
341# @FUNCTION: subversion_bootstrap
342# @DESCRIPTION:
343# Apply patches in ${ESVN_PATCHES} and run ${ESVN_BOOTSTRAP} if specified.
344subversion_bootstrap() {
345 if has "export" ${ESVN_RESTRICT}; then
346 return
347 fi
348
349 cd "${S}"
350
351 if [[ -n ${ESVN_PATCHES} ]]; then
352 einfo "apply patches -->"
353
354 local patch fpatch
355
356 for patch in ${ESVN_PATCHES}; do
357 if [[ -f ${patch} ]]; then
358 epatch "${patch}"
359
360 else
361 for fpatch in ${FILESDIR}/${patch}; do
362 if [[ -f ${fpatch} ]]; then
363 epatch "${fpatch}"
364
365 else
366 die "${ESVN}: ${patch} not found"
367
368 fi
369 done
370
371 fi
372 done
373
374 echo
375 fi
376
377 if [[ -n ${ESVN_BOOTSTRAP} ]]; then
378 einfo "begin bootstrap -->"
379
380 if [[ -f ${ESVN_BOOTSTRAP} && -x ${ESVN_BOOTSTRAP} ]]; then
381 einfo " bootstrap with a file: ${ESVN_BOOTSTRAP}"
382 eval "./${ESVN_BOOTSTRAP}" || die "${ESVN}: can't execute ESVN_BOOTSTRAP."
383
384 else
385 einfo " bootstrap with command: ${ESVN_BOOTSTRAP}"
386 eval "${ESVN_BOOTSTRAP}" || die "${ESVN}: can't eval ESVN_BOOTSTRAP."
387
388 fi
389 fi
390}
391
392# @FUNCTION: subversion_src_unpack
393# @DESCRIPTION:
394# Default src_unpack. Fetch and, in older EAPIs, bootstrap.
395subversion_src_unpack() {
396 subversion_fetch || die "${ESVN}: unknown problem occurred in subversion_fetch."
397 if has "${EAPI:-0}" 0 1; then
398 subversion_bootstrap || die "${ESVN}: unknown problem occurred in subversion_bootstrap."
399 fi
400}
401
402# @FUNCTION: subversion_src_prepare
403# @DESCRIPTION:
404# Default src_prepare. Bootstrap.
405subversion_src_prepare() {
406 subversion_bootstrap || die "${ESVN}: unknown problem occurred in subversion_bootstrap."
407}
408
409# @FUNCTION: subversion_wc_info
410# @USAGE: [repo_uri]
411# @RETURN: ESVN_WC_URL, ESVN_WC_ROOT, ESVN_WC_UUID, ESVN_WC_REVISION and ESVN_WC_PATH
412# @DESCRIPTION:
413# Get svn info for the specified repo_uri. The default repo_uri is ESVN_REPO_URI.
414#
415# The working copy information on the specified repository URI are set to
416# ESVN_WC_* variables.
417subversion_wc_info() {
418 local repo_uri="$(subversion__get_repository_uri "${1:-${ESVN_REPO_URI}}")"
419 local wc_path="$(subversion__get_wc_path "${repo_uri}")"
420
421 debug-print "${FUNCNAME}: repo_uri = ${repo_uri}"
422 debug-print "${FUNCNAME}: wc_path = ${wc_path}"
423
424 if [[ ! -d ${wc_path} ]]; then
425 return 1
426 fi
427
428 export ESVN_WC_URL="$(subversion__svn_info "${wc_path}" "URL")"
429 export ESVN_WC_ROOT="$(subversion__svn_info "${wc_path}" "Repository Root")"
430 export ESVN_WC_UUID="$(subversion__svn_info "${wc_path}" "Repository UUID")"
431 export ESVN_WC_REVISION="$(subversion__svn_info "${wc_path}" "Revision")"
432 export ESVN_WC_PATH="${wc_path}"
433}
434
435## -- Private Functions
436
437## -- subversion__svn_info() ------------------------------------------------- #
438#
439# param $1 - a target.
440# param $2 - a key name.
441#
442subversion__svn_info() {
443 local target="${1}"
444 local key="${2}"
445
446 env LC_ALL=C svn info "${target}" | grep -i "^${key}" | cut -d" " -f2-
447}
448
449## -- subversion__get_repository_uri() --------------------------------------- #
450#
451# param $1 - a repository URI.
452subversion__get_repository_uri() {
453 local repo_uri="${1}"
454
455 debug-print "${FUNCNAME}: repo_uri = ${repo_uri}"
456
457 if [[ -z ${repo_uri} ]]; then
458 die "${ESVN}: ESVN_REPO_URI (or specified URI) is empty."
459 fi
460
461 # delete trailing slash
462 if [[ -z ${repo_uri##*/} ]]; then
463 repo_uri="${repo_uri%/}"
464 fi
465
466 repo_uri="${repo_uri%@*}"
467
468 echo "${repo_uri}"
469}
470
471## -- subversion__get_wc_path() ---------------------------------------------- #
472#
473# param $1 - a repository URI.
474subversion__get_wc_path() {
475 local repo_uri="$(subversion__get_repository_uri "${1}")"
476
477 debug-print "${FUNCNAME}: repo_uri = ${repo_uri}"
478
479 echo "${ESVN_STORE_DIR}/${ESVN_PROJECT}/${repo_uri##*/}"
480}
481
482## -- subversion__get_peg_revision() ----------------------------------------- #
483#
484# param $1 - a repository URI.
485subversion__get_peg_revision() {
486 local repo_uri="${1}"
487
488 debug-print "${FUNCNAME}: repo_uri = ${repo_uri}"
489
490 # repo_uri has peg revision ?
491 if [[ ${repo_uri} != *@* ]]; then
492 debug-print "${FUNCNAME}: repo_uri does not have a peg revision."
493 fi
494
495 local peg_rev=
496 [[ ${repo_uri} = *@* ]] && peg_rev="${repo_uri##*@}"
497
498 debug-print "${FUNCNAME}: peg_rev = ${peg_rev}"
499
500 echo "${peg_rev}"
501}
502
503# @FUNCTION: subversion_pkg_preinst
504# @USAGE: [repo_uri]
505# @DESCRIPTION:
506# Log the svn revision of source code. Doing this in pkg_preinst because we
507# want the logs to stick around if packages are uninstalled without messing with
508# config protection.
509subversion_pkg_preinst() {
510 local pkgdate=$(date "+%Y%m%d %H:%M:%S")
511 subversion_wc_info "${1:-${ESVN_REPO_URI}}"
512 if [[ -n ${ESCM_LOGDIR} ]]; then
513 local dir="${ROOT}/${ESCM_LOGDIR}/${CATEGORY}"
514 if [[ ! -d ${dir} ]]; then
515 mkdir -p "${dir}" || \
516 eerror "Failed to create '${dir}' for logging svn revision to '${PORTDIR_SCM}'"
517 fi
518 local logmessage="svn: ${pkgdate} - ${PF}:${SLOT} was merged at revision ${ESVN_WC_REVISION}"
519 if [[ -d ${dir} ]]; then
520 echo "${logmessage}" >> "${dir}/${PN}.log"
521 else
522 eerror "Could not log the message '${logmessage}' to '${dir}/${PN}.log'"
523 fi
524 fi
525}