First patch for elog integration in 2.0.x adding the basic elog
framework without the actual modules, config samples or other docs. The
code is mostly unchanged from the 2.1 branch and only lightly tested
on 2.0. Known issues with this patch:
- needs better integration of isolated-functions.sh, probably should be
a separate patch (Brian?)
- module loader should be improved somehow (low priority)
- logging currenty only occurs after successful merges
- probably more that I can't remember atm

Later patches will add the actual logging modules and make.*
enhancements, maybe also python logging (for einfo style messages) and
support tools.

Marius

-- 
Public Key at http://www.genone.de/info/gpg-key.pub

In the beginning, there was nothing. And God said, 'Let there be
Light.' And there was still nothing, but you could see a bit better.
Index: pym/portage.py
===================================================================
--- pym/portage.py	(revision 2155)
+++ pym/portage.py	(working copy)
@@ -454,6 +454,57 @@
 			mygraph.okeys=self.okeys[:]
 		return mygraph
 
+def elog_process(cpv, mysettings):
+	mylogfiles = listdir(mysettings["T"]+"/logging/")
+	# shortcut for packages without any messages
+	if len(mylogfiles) == 0:
+		return
+	# exploit listdir() file order so we process log entries in cronological order
+	mylogfiles.reverse()
+	mylogentries = {}
+	for f in mylogfiles:
+		msgfunction, msgtype = f.split(".")
+		if not msgtype.upper() in mysettings["PORTAGE_ELOG_CLASSES"].split() \
+				and not msgtype.lower() in mysettings["PORTAGE_ELOG_CLASSES"].split():
+			continue
+		if msgfunction not in portage_const.EBUILD_PHASES.split():
+			print "!!! can't process invalid log file: %s" % f
+			continue
+		if not msgfunction in mylogentries:
+			mylogentries[msgfunction] = []
+		msgcontent = open(mysettings["T"]+"/logging/"+f, "r").readlines()
+		mylogentries[msgfunction].append((msgtype, msgcontent))
+
+	# in case the filters matched all messages
+	if len(mylogentries) == 0:
+		return
+
+	# generate a single string with all log messages
+	fulllog = ""
+	for phase in portage_const.EBUILD_PHASES.split():
+		if not phase in mylogentries:
+			continue
+		for msgtype,msgcontent in mylogentries[phase]:
+			fulllog += "%s: %s\n" % (msgtype, phase)
+			for line in msgcontent:
+				fulllog += line
+			fulllog += "\n"
+
+	# pass the processing to the individual modules
+	logsystems = mysettings["PORTAGE_ELOG_SYSTEM"].split()
+	for s in logsystems:
+		try:
+			# FIXME: ugly ad.hoc import code
+			# TODO:  implement a common portage module loader
+			logmodule = __import__("elog_modules.mod_"+s)
+			m = getattr(logmodule, "mod_"+s)
+			m.process(mysettings, cpv, mylogentries, fulllog)
+		except (ImportError, AttributeError), e:
+			print "!!! Error while importing logging modules:"
+			print e
+		except portage_exception.PortageException, e:
+			print e
+
 # valid end of version components; integers specify offset from release version
 # pre=prerelease, p=patchlevel (should always be followed by an int), rc=release candidate
 # all but _p (where it is required) can be followed by an optional trailing integer
@@ -2505,6 +2556,12 @@
 			os.chown(mysettings["T"],portage_uid,portage_gid)
 			os.chmod(mysettings["T"],02770)
 
+		logdir = mysettings["T"]+"/logging"
+		if not os.path.exists(logdir):
+			os.makedirs(logdir)
+		os.chown(logdir, portage_uid, portage_gid)
+		os.chmod(logdir, 0770)
+
 		try: # XXX: negative RESTRICT
 			if not (("nouserpriv" in string.split(mysettings["PORTAGE_RESTRICT"])) or \
 			   ("userpriv" in string.split(mysettings["PORTAGE_RESTRICT"]))):
@@ -6679,6 +6736,10 @@
 		if dircache.has_key(self.dbcatdir):
 			del dircache[self.dbcatdir]
 		print ">>>",self.mycpv,"merged."
+
+		# Process ebuild logfiles
+		elog_process(self.mycpv, self.settings)
+		
 		return 0
 
 	def mergeme(self,srcroot,destroot,outfile,secondhand,stufftomerge,cfgfiledict,thismtime):
Index: pym/portage_const.py
===================================================================
--- pym/portage_const.py	(revision 2155)
+++ pym/portage_const.py	(working copy)
@@ -40,6 +40,8 @@
 SANDBOX_PIDS_FILE       = "/tmp/sandboxpids.tmp"
 CONFIG_MEMORY_FILE      = PRIVATE_PATH + "/config"
 
+EBUILD_PHASES			= "setup unpack compile test install preinst postinst prerm postrm"
+
 INCREMENTALS=["USE","FEATURES","ACCEPT_KEYWORDS","ACCEPT_LICENSE","CONFIG_PROTECT_MASK","CONFIG_PROTECT","PRELINK_PATH","PRELINK_PATH_MASK"]
 STICKIES=["KEYWORDS_ACCEPT","USE","CFLAGS","CXXFLAGS","MAKEOPTS","EXTRA_ECONF","EXTRA_EINSTALL","EXTRA_EMAKE"]
 
Index: bin/isolated-functions.sh
===================================================================
--- bin/isolated-functions.sh	(revision 0)
+++ bin/isolated-functions.sh	(revision 0)
@@ -0,0 +1,204 @@
+# Copyright 1999-2004 Gentoo Technologies, Inc.
+# Distributed under the terms of the GNU General Public License v2
+# $Header$
+
+# Internal logging function, don't use this in ebuilds
+elog_base() {
+	local messagetype
+	[ -z "${1}" -o -z "${T}" -o ! -d "${T}/logging" ] && return 1
+	case "${1}" in
+		INFO|WARN|ERROR|LOG)
+			messagetype="${1}"
+			shift
+			;;
+		*)
+			echo -e " ${BAD}*${NORMAL} Invalid use of internal function elog_base(), next message will not be logged"
+			return 1
+			;;
+	esac
+	echo ${*} >> ${T}/logging/${EBUILD_PHASE}.${messagetype}
+	return 0
+}
+
+elog() {
+	elog_base LOG ${*}
+	echo -e " ${GOOD}*${NORMAL} ${*}"
+	return 0
+}
+
+esyslog() {
+	local pri=
+	local tag=
+	
+	if [ -x /usr/bin/logger ]
+	then
+		pri="$1"
+		tag="$2"
+		
+		shift 2
+		[ -z "$*" ] && return 0
+		
+		/usr/bin/logger -p "${pri}" -t "${tag}" -- "$*"
+	fi
+
+	return 0
+}
+
+einfo() {
+	einfon ${*}
+	echo
+	return 0
+}
+
+einfon() {
+	elog_base INFO ${*}
+	echo -ne " ${GOOD}*${NORMAL} ${*}"
+	return 0
+}
+
+ewarn() {
+	elog_base WARN ${*}
+	echo -e " ${WARN}*${NORMAL} ${*}"
+	return 0
+}
+
+eerror() {
+	elog_base ERROR ${*}
+	echo -e " ${BAD}*${NORMAL} ${*}"
+	return 0
+}
+
+ebegin() {
+	if [ -z "${NOCOLOR}" ]; then
+		echo -ne " ${GOOD}*${NORMAL} ${*}..."
+	else
+		echo -e " ${GOOD}*${NORMAL} ${*}..."
+	fi
+	return 0
+}
+
+eend() {
+	local retval=
+	if [ "$#" -eq 0 ] || [ "${1:-1}" -eq  0 ]; then
+		echo -e "${ENDCOL}  ${BRACKET}[ ${GOOD}ok${BRACKET} ]${NORMAL}"
+	else
+		retval="$1"
+		
+		if [ "$#" -ge 2 ]
+		then
+			shift
+			eerror "${*}"
+		fi
+		echo -e "${ENDCOL}  ${BRACKET}[ ${BAD}!!${BRACKET} ]${NORMAL}"
+		# extra spacing makes it easier to read
+		echo
+		return ${retval}
+	fi
+	return 0
+}
+
+KV_major() {
+	local KV=
+	
+	[ -z "$1" ] && return 1
+
+	KV="$(echo "$1" | \
+		awk '{ tmp = $0; gsub(/^[0-9\.]*/, "", tmp); sub(tmp, ""); print }')"
+	echo "${KV}" | awk -- 'BEGIN { FS = "." } { print $1 }'
+
+	return 0
+}
+
+KV_minor() {
+	local KV=
+	
+	[ -z "$1" ] && return 1
+
+	KV="$(echo "$1" | \
+		awk '{ tmp = $0; gsub(/^[0-9\.]*/, "", tmp); sub(tmp, ""); print }')"
+	echo "${KV}" | awk -- 'BEGIN { FS = "." } { print $2 }'
+
+	return 0
+}
+
+KV_micro() {
+	local KV=
+	
+	[ -z "$1" ] && return 1
+
+	KV="$(echo "$1" | \
+		awk '{ tmp = $0; gsub(/^[0-9\.]*/, "", tmp); sub(tmp, ""); print }')"
+	echo "${KV}" | awk -- 'BEGIN { FS = "." } { print $3 }'
+
+	return 0
+}
+
+KV_to_int() {
+	local KV_MAJOR=
+	local KV_MINOR=
+	local KV_MICRO=
+	local KV_int=
+	
+	[ -z "$1" ] && return 1
+    
+	KV_MAJOR="$(KV_major "$1")"
+	KV_MINOR="$(KV_minor "$1")"
+	KV_MICRO="$(KV_micro "$1")"
+	KV_int="$((KV_MAJOR * 65536 + KV_MINOR * 256 + KV_MICRO))"
+    
+	# We make version 2.2.0 the minimum version we will handle as
+	# a sanity check ... if its less, we fail ...
+	if [ "${KV_int}" -ge 131584 ]
+	then 
+		echo "${KV_int}"
+
+		return 0
+	fi
+
+	return 1
+}   
+
+get_KV() {
+	local KV="$(uname -r)"
+
+	echo "$(KV_to_int "${KV}")"
+
+	return $?
+}
+
+getcols() {
+	echo "$2"
+}
+
+unset_colors() {
+	COLS="25 80"
+	ENDCOL=
+	
+	GOOD=
+	WARN=
+	BAD=
+	NORMAL=
+	HILITE=
+	BRACKET=
+	
+	if [ -n "${EBUILD}" ] && [ "${*/depend}" = "$*" ]; then
+		stty cols 80 &>/dev/null
+		stty rows 25 &>/dev/null
+	fi
+}
+
+set_colors() {
+	COLS="`stty size 2> /dev/null`"
+	COLS="`getcols ${COLS}`"
+	COLS=$((${COLS} - 7))
+	ENDCOL=$'\e[A\e['${COLS}'G'    # Now, ${ENDCOL} will move us to the end of the
+	                               # column;  irregardless of character width
+	
+	GOOD=$'\e[32;01m'
+	WARN=$'\e[33;01m'
+	BAD=$'\e[31;01m'
+	NORMAL=$'\e[0m'
+	HILITE=$'\e[36;01m'
+	BRACKET=$'\e[34;01m'
+}
+true
Index: bin/ebuild.sh
===================================================================
--- bin/ebuild.sh	(revision 2155)
+++ bin/ebuild.sh	(working copy)
@@ -50,8 +50,9 @@
 export PATH="/sbin:/usr/sbin:/usr/lib/portage/bin:/bin:/usr/bin:${ROOTPATH}"
 [ ! -z "$PREROOTPATH" ] && export PATH="${PREROOTPATH%%:}:$PATH"
 
-if [ -e /etc/init.d/functions.sh ]; then
-	source /etc/init.d/functions.sh  &>/dev/null
+if [ -e /usr/lib/portage/bin/isolated-functions.sh ]; then
+	source /usr/lib/portage/bin/isolated-functions.sh  &>/dev/null
+	set_colors
 elif [ -e /etc/rc.d/config/functions ];	then
 	source /etc/rc.d/config/functions &>/dev/null
 else

Attachment: pgpqGPvHsVmNG.pgp
Description: PGP signature

Reply via email to