public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/R_overlay:master commit in: roverlay/overlay/metadata/, roverlay/overlay/
@ 2012-07-30  8:52 André Erdmann
  0 siblings, 0 replies; 4+ messages in thread
From: André Erdmann @ 2012-07-30  8:52 UTC (permalink / raw
  To: gentoo-commits

commit:     548e6ceede8e8ba8d75492656656275f13b20613
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Thu Jul 19 16:53:08 2012 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Thu Jul 19 16:53:28 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=548e6cee

incremental overlay writing

prepare for OverlayCreator

	geändert:   roverlay/overlay/category.py
	geändert:   roverlay/overlay/creator.py
	geändert:   roverlay/overlay/metadata/__init__.py
	geändert:   roverlay/overlay/metadata/nodes.py
	geändert:   roverlay/overlay/package.py
	geändert:   roverlay/overlay/root.py

---
 roverlay/overlay/category.py          |   24 +-
 roverlay/overlay/creator.py           |   11 +-
 roverlay/overlay/metadata/__init__.py |   84 ++++--
 roverlay/overlay/metadata/nodes.py    |   40 +--
 roverlay/overlay/package.py           |  535 +++++++++++++++------------------
 roverlay/overlay/root.py              |   23 +-
 6 files changed, 354 insertions(+), 363 deletions(-)

diff --git a/roverlay/overlay/category.py b/roverlay/overlay/category.py
index afa2456..9cf8ad9 100644
--- a/roverlay/overlay/category.py
+++ b/roverlay/overlay/category.py
@@ -68,6 +68,13 @@ class Category ( object ):
 			not False in ( d.empty() for d in self._subdirs.values() )
 	# --- end of empty (...) ---
 
+	def finalize_write_incremental ( self ):
+		for subdir in self._subdirs.values():
+			if subdir.modified:
+				subdir.write_incremental()
+			subdir.finalize_write_incremental()
+	# --- end of finalize_write_incremental (...) ---
+
 	def _get_package_dir ( self, pkg_name ):
 		if not pkg_name in self._subdirs:
 			self._lock.acquire()
@@ -84,7 +91,7 @@ class Category ( object ):
 		return self._subdirs [pkg_name]
 	# --- end of _get_package_dir (...) ---
 
-	def add ( self, package_info, write_after_add=False, header=None ):
+	def add ( self, package_info, **pkg_add_kw ):
 		"""Adds a package to this category.
 
 		arguments:
@@ -93,13 +100,7 @@ class Category ( object ):
 		returns: success
 		"""
 		subdir = self._get_package_dir ( package_info ['name'] )
-		if subdir.add ( package_info ):
-			if write_after_add:
-				roverlay.util.dodir ( subdir.physical_location )
-				subdir.write_incremental ( default_header=header )
-			return True
-		else:
-			return False
+		return subdir.add ( package_info, **pkg_add_kw )
 	# --- end of add (...) ---
 
 	def generate_metadata ( self, **metadata_kw ):
@@ -164,9 +165,10 @@ class Category ( object ):
 				# so collect the list of package dirs before iterating over it
 				subdirs = tuple ( self._subdirs.values() )
 
-			for package in subdirs:
-				roverlay.util.dodir ( package.physical_location )
-				package.write_incremental ( **write_kw )
+			for subdir in subdirs:
+				if subdir.modified:
+					roverlay.util.dodir ( subdir.physical_location )
+					subdir.write_incremental ( **write_kw )
 		except Exception as e:
 			self.logger.exception ( e )
 	# --- end of write_incremental (...) ---

diff --git a/roverlay/overlay/creator.py b/roverlay/overlay/creator.py
index 3a6e0ed..dd7c11e 100644
--- a/roverlay/overlay/creator.py
+++ b/roverlay/overlay/creator.py
@@ -214,15 +214,17 @@ class OverlayCreator ( object ):
 
 	def add_package_file ( self, package_file ):
 		"""Adds a single R package."""
+		raise Exception ( "to be removed" )
 		self._pkg_queue.put ( PackageInfo ( filepath=package_file ) )
 		self.package_added.inc()
-	# --- end of add_package (...) ---
+	# --- end of add_package_file (...) ---
 
 	def add_package_files ( self, *package_files ):
 		"""Adds multiple R packages."""
+		raise Exception ( "to be removed" )
 		for p in package_files: self.add_package_file ( p )
 		self.package_added.inc()
-	# --- end of add_packages (...) ---
+	# --- end of add_package_files (...) ---
 
 	def write_overlay ( self, incremental=False ):
 		"""Writes the overlay.
@@ -232,7 +234,10 @@ class OverlayCreator ( object ):
 		"""
 		if self.can_write_overlay:
 			start = time.time()
-			self.overlay.write()
+			if incremental:
+				self.overlay.write_incremental()
+			else:
+				self.overlay.write()
 			self._timestamp ( "overlay written", start )
 		else:
 			self.logger.warning ( "Not allowed to write overlay!" )

diff --git a/roverlay/overlay/metadata/__init__.py b/roverlay/overlay/metadata/__init__.py
index e4938b5..58fc414 100644
--- a/roverlay/overlay/metadata/__init__.py
+++ b/roverlay/overlay/metadata/__init__.py
@@ -11,37 +11,53 @@ USE_FULL_DESCRIPTION = True
 class MetadataJob ( object ):
 	"""R package description data -> metadata.xml interface."""
 
-	def __init__ ( self, logger ):
+	def __init__ ( self, filepath, logger ):
 		"""Initializes a MetadataJob.
 
 		arguments:
-		* logger       -- parent logger to use
+		* filepath -- path where the metadata file will be written to
+		* logger   -- parent logger to use
 		"""
-		self.logger    = logger.getChild ( 'metadata' )
-		self._metadata = nodes.MetadataRoot()
-		# reserved for future usage ("dominant ebuilds": when ebuildjobs
-		# share one metadata instance etc.)
-		self.package_info = None
-		self.filename     = 'metadata.xml'
+		self.logger        = logger.getChild ( 'metadata' )
+		self._package_info = None
+		self.filepath      = filepath
+		# no longer storing self._metadata, which will only be created twice
+		# when running show() (expected 1x write per PackageInfo instance)
 	# --- end of __init__ (...) ---
 
-	def update ( self, package_info ):
-		"""Updates the metadata using the given description data.
+	def empty ( self ):
+		return self._package_info is None
+	# --- end of empty (...) ---
 
-		It's expected that this method is called when Ebuild creation is done.
+	def update ( self, package_info ):
+		"""Updates the metadata.
+		Actually, this won't create any metadata, it will only set the
+		PackageInfo object to be used for metadata creation.
 
 		arguments:
-		* desc_data -- description data read from R package
-		* package_info -- reserved for future usage
-
-		returns: None (implicit)
+		* package_info --
 		"""
-		data = package_info ['desc_data']
+		if package_info.has ( 'desc_data' ) and \
+			package_info.compare_version ( self._package_info ) > 0:
+				self._package_info = package_info
+	# --- end of update (...) ---
 
-		mref = self._metadata
+	def update_using_iterable ( self, package_info_iter ):
+		for package_info in package_info_iter:
+			self.update ( package_info )
+	# --- end of update_using_iterable (...) ---
 
-		max_textline_width = roverlay.config.get ( 'METADATA.linewidth', 65 )
+	def _create ( self ):
+		"""Creates metadata (MetadataRoot) using the stored PackageInfo.
+
+		It's expected that this method is called when Ebuild creation is done.
+
+		returns: created metadata
+		"""
+		mref = nodes.MetadataRoot()
+		data = self._package_info ['desc_data']
 
+		max_textline_width = roverlay.config.get ( 'METADATA.linewidth', 65 )
 
 		description = None
 
@@ -67,22 +83,38 @@ class MetadataJob ( object ):
 		#if package_info ['has_suggests']:
 		#	mref.add_useflag ( 'R_suggests', 'install optional dependencies' )
 
+		return mref
 	# --- end of update (...) ---
 
-	def write ( self, _file ):
+	def _write ( self, fh ):
 		"""Writes the metadata into a file.
 
 		arguments:
 		* _file -- file to write, either a file handle or string in which case
 		           a file object will be created
 
-	  returns: True if writing succeeds, else False
+		returns: True if writing succeeds, else False
 
-	  raises: Exception if no metadata to write
-	  """
-		if self._metadata.empty():
-			raise Exception ( "not enough metadata to write!" )
-			#return False
+		raises: Exception if no metadata to write
+		"""
+		if self._create().write_file ( fh ):
+			return True
 		else:
-			return self._metadata.write_file ( _file )
+			raise Exception ( "not enough metadata to write!" )
+	# --- end of _write (...) ---
+
+	show = _write
+
+	def write ( self ):
+		_success = False
+		try:
+			fh = open ( self.filepath, 'w' )
+			self._write ( fh )
+			_success = True
+		except any as e:
+			self.logger.exception ( e )
+		finally:
+			if 'fh' in locals() and fh: fh.close()
+
+		return _success
 	# --- end of write (...) ---

diff --git a/roverlay/overlay/metadata/nodes.py b/roverlay/overlay/metadata/nodes.py
index 6f27deb..02d5482 100644
--- a/roverlay/overlay/metadata/nodes.py
+++ b/roverlay/overlay/metadata/nodes.py
@@ -57,46 +57,24 @@ class MetadataRoot ( MetadataNodeNamedAccess ):
 		return use_node
 	# --- end of add_useflag (...) ---
 
-	def write_file ( self, _file ):
+	def write_file ( self, fh ):
 		"""Writes the metadata to a file.
 
 		arguments:
-		* _file -- either a File object or a string
+		* fh -- a File object
 
 		returns: success True/False
 
 		raises: *passes IOError
 		"""
-		to_write = util.ascii_filter ( self.to_str() )
-
-		own_fh  = False
-		fh      = None
-		success = False
-
-		newline = '\n'
-
-		try:
-			if isinstance ( _file, str ):
-				own_fh = True
-				fh     = open ( _file, 'w' )
-			else:
-				fh     = _file
-
-
+		if not self.empty():
 			fh.write ( MetadataRoot.HEADER )
-			fh.write ( newline )
-			fh.write ( to_write )
-			fh.write ( newline )
-
-			success = True
-
-		except IOError:
-			# log this TODO
-			pass
-		finally:
-			if own_fh and fh: fh.close()
-
-		return success
+			fh.write ( '\n' )
+			fh.write ( util.ascii_filter ( self.to_str() ) )
+			fh.write ( '\n' )
+			return True
+		else:
+			return False
 	# --- end of write_file (...) ---
 
 

diff --git a/roverlay/overlay/package.py b/roverlay/overlay/package.py
index c0b4294..71b7ea9 100644
--- a/roverlay/overlay/package.py
+++ b/roverlay/overlay/package.py
@@ -1,20 +1,18 @@
-# R Overlay -- overlay module, package dir (subdir of category)
-# Copyright 2006-2012 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
+# replacement for package.py
 
-import threading
 import os
 import sys
+import threading
 
 from roverlay                  import manifest
 from roverlay.packageinfo      import PackageInfo
 from roverlay.overlay.metadata import MetadataJob
 
 SUPPRESS_EXCEPTIONS = True
-EBUILD_SUFFIX = '.ebuild'
 
-class PackageDir ( object ):
 
+class PackageDir ( object ):
+	EBUILD_SUFFIX = '.ebuild'
 
 	def __init__ ( self, name, logger, directory ):
 		"""Initializes a PackageDir which contains ebuilds, metadata and
@@ -30,47 +28,131 @@ class PackageDir ( object ):
 		self._lock             = threading.RLock()
 		# { <version> : <PackageInfo> }
 		self._packages         = dict()
-		self._metadata         = None
 		self.physical_location = directory
 
-		self._package_for_manifest = None
+		self._metadata         = MetadataJob (
+			filepath = self.physical_location + os.sep + 'metadata.xml',
+			logger   = self.logger
+		)
+
+		# <dir>/<PN>-<PVR>.ebuild
+		self.ebuild_filepath_format = \
+			self.physical_location + os.sep + \
+			self.name + "-{PVR}" + self.__class__.EBUILD_SUFFIX
 
 		# used to track changes for this package dir
-		self.modified          = False
+		self.modified = False
+		self._manifest_package = None
+		self._need_manifest = False
+		self._need_metadata = False
 	# --- end of __init__ (...) ---
 
-	def list_versions ( self ):
-		return self._packages.keys()
-	# --- end of list_versions (...) ---
+	def new_ebuild ( self ):
+		"""Called when a new ebuild has been created for this PackageDir."""
+		self._need_manifest = True
+		self.modified       = True
+	# --- end of new_ebuild (...) ---
 
-	def has_manifest ( self ):
-		return os.path.isfile (
-			self.physical_location + os.sep + 'Manifest'
-		)
-	# --- end of has_manifest (...) ---
+	def add ( self, package_info, add_if_physical=False ):
+		"""Adds a package to this PackageDir.
 
-	def has_metadata ( self ):
-		return os.path.isfile (
-			self.physical_location + os.sep + 'metadata.xml'
-		)
-	# --- end of has_metadata (...) ---
+		arguments:
+		* package_info    --
+		* add_if_physical -- add package even if it exists as ebuild file
+		                      (-> overwrite old ebuilds)
+
+		returns: success as bool
+
+		raises: Exception when ebuild already exists.
+		"""
+		shortver = package_info ['ebuild_verstr']
+		_success = False
+		try:
+			self._lock.acquire()
+			if shortver in self._packages:
+				# package exists, check if it existed before script invocation
+				if self._packages [shortver] ['physical_only']:
+					if not skip_if_physical:
+						# ignore ebuilds that exist as file
+						self._packages [shortver] = package_info
+						_success = True
+					else:
+						self.logger.debug (
+							"'{PN}-{PVR}.ebuild' exists as file, skipping.".format (
+								PN=self.name, PVR=shortver
+							)
+						)
+				else:
+					# package has been added to this overlay before
+					self.logger.info (
+						"'{PN}-{PVR}.ebuild' already exists, cannot add it!".format (
+						PN=self.name, PVR=shortver
+						)
+					)
+			else:
+				self._packages [shortver] = package_info
+				_success = True
+
+		finally:
+			self._lock.release()
+
+		return _success
+	# --- end of add (...) ---
+
+	def empty ( self ):
+		"""Returns True if no ebuilds stored, else False.
+		Note that "not empty" does not mean "have ebuilds to write".
+		"""
+		return len ( self._packages ) == 0
+	# --- end of empty (...) ---
+
+	def finalize_write_incremental ( self ):
+		with self._lock:
+			if self._need_metadata:
+				self.write_metadata()
+			if self._need_manifest:
+				self.write_manifest()
+	# --- end of finalize_write_incremental (...) ---
+
+	def generate_metadata ( self, skip_if_existent, **ignored_kw ):
+		"""Creates metadata for this package.
+
+		arguments:
+		* skip_if_existent -- do not create if metadata already exist
+		"""
+		with self._lock:
+			if self._metadata.empty() or not skip_if_existent:
+				self._metadata.update_using_iterable ( self._packages.values() )
+	# --- end of generate_metadata (...) ---
 
-	def get_ebuilds ( self ):
-		for x in os.listdir ( self.physical_location ):
-			if x.endswith ( EBUILD_SUFFIX ):
-				yield self.physical_location + os.sep + x
-	# --- end of get_ebuilds (...) ---
+	def list_versions ( self ):
+		return self._packages.keys()
+	# --- end of list_versions (...) ---
 
-	def _scan_ebuilds ( self ):
-		"""Searches for ebuilds in self.physical_location."""
-		elen = len ( EBUILD_SUFFIX )
+	def scan ( self, **kw ):
+		"""Scans the filesystem location of this package for existing
+		ebuilds and adds them.
+		"""
+		def scan_ebuilds():
+			"""Searches for ebuilds in self.physical_location."""
+			elen = len ( self.__class__.EBUILD_SUFFIX )
+			def ebuild_split_pvr ( _file ):
+				if _file.endswith ( self.__class__.EBUILD_SUFFIX ):
+					return _file [ : - elen ].split ( '-', 1 )
+				else:
+					return ( None, None )
+			# --- end of is_ebuild (...) ---
 
-		for f in os.listdir ( self.physical_location ):
-			if f.endswith ( EBUILD_SUFFIX ):
+			# assuming that self.physical_location exists
+			#  (should be verified by category.py:Category)
+			for f in os.listdir ( self.physical_location ):
 				try:
 					# filename without suffix ~= ${PF} := ${PN}-${PVR}
-					pn, pvr = f [ : - elen ].split ( '-', 1 )
-					if pn == self.name:
+					pn, pvr = ebuild_split_pvr ( f )
+					if pn is None:
+						# not an ebuild
+						pass
+					elif pn == self.name:
 						yield pvr
 					else:
 						# $PN does not match directory name, warn about that
@@ -78,298 +160,161 @@ class PackageDir ( object ):
 							"$PN does not match directory name, ignoring {!r}.".\
 							format ( f )
 						)
-
 				except:
 					self.logger.warning (
 						"ebuild {!r} has an invalid file name!".format ( f )
 					)
+		# --- end of scan_ebuilds (...) ---
 
-	# --- end of _scan_ebuilds (...) ---
-
-	def scan ( self, **kw ):
-		"""Scans the filesystem location of this package for existing
-		ebuilds and adds them.
-		"""
-		for pvr in self._scan_ebuilds():
+		for pvr in scan_ebuilds():
 			if pvr not in self._packages:
 				p = PackageInfo ( physical_only=True, pvr=pvr )
 				self._packages [ p ['ebuild_verstr'] ] = p
 	# --- end of scan (...) ---
 
-	def empty ( self ):
-		"""Returns True if no ebuilds stored, else False."""
-		return len ( self._packages ) == 0
-	# --- end of empty (...) ---
-
-	def _get_ebuild_filepath ( self, pvr ):
-		"""Returns the path to the ebuild file.
-
-		arguments:
-		* pvr -- version number with the revision (${PVR} in ebuilds)
-		"""
-		return "{root}{sep}{PN}-{PVR}{EBUILD_SUFFIX}".format (
-			root=self.physical_location, sep=os.sep,
-			PN=self.name, PVR=pvr, EBUILD_SUFFIX=EBUILD_SUFFIX
-		)
-	# --- end of _get_ebuild_filepath (...) ---
-
-	def write_incremental ( self, default_header ):
-		self.write_ebuilds ( header=default_header, overwrite=False )
-	# --- end of write_incremental (...) ---
-
-	def write_metadata ( self, shared_fh=None ):
-		"""Writes metadata for this package."""
-		try:
-
-			self._regen_metadata()
-
-			if shared_fh is None:
-				fh = open (
-					self.physical_location + os.sep + self._metadata.filename, 'w'
-				)
-			else:
-				fh = shared_fh
-
-			self._metadata.write ( fh )
-
-		except IOError as e:
-
-			self.logger.error (
-				"Failed to write metadata file {}.".format ( mfile )
-			)
-			self.logger.exception ( e )
-
-		finally:
-			if shared_fh is None and 'fh' in locals() and fh:
-				fh.close()
-	# --- end of write_metadata (...) ---
-
-	def write_ebuild ( self, efile, ebuild, header, shared_fh=None ):
-		"""Writes an ebuild.
+	def show ( self, stream=sys.stderr, default_header=None ):
+		"""Prints this dir (the ebuilds and the metadata) into a stream.
 
 		arguments:
-		* efile     -- file to write
-		* ebuild    -- ebuild object to write (has to have a __str__ method)
-		* header    -- ebuild header to write (^)
-		* shared_fh -- optional, see write_ebuilds()
-		"""
-		_success = False
-		try:
-			fh = open ( efile, 'w' ) if shared_fh is None else shared_fh
-			if header is not None:
-				fh.write ( str ( header ) )
-				fh.write ( '\n\n' )
-			fh.write ( str ( ebuild ) )
-			fh.write ( '\n' )
-
-			# adjust owner/perm? TODO
-			#if shared_fh is None:
-			#	chmod 0644 or 0444
-			#	chown 250.250
-			_success = True
-		except IOError as e:
-			self.logger.exception ( e )
-		finally:
-			if shared_fh is None and 'fh' in locals() and fh:
-				fh.close()
-
-		return _success
-	# --- end of write_ebuild (...) ---
+		* stream -- stream to use, defaults to sys.stderr
 
-	def write_ebuilds ( self, header, shared_fh=None, overwrite=True ):
-		"""Writes all ebuilds.
+		returns: None (implicit)
 
-		arguments:
-		* header    -- ebuild header
-		* shared_fh -- if set and not None: don't use own file handles (i.e.
-		               write files), write everything into shared_fh
+		raises:
+		* IOError
 		"""
-		for ver, p_info in self._packages.items():
-			if not p_info ['physical_only'] and p_info ['ebuild']:
-				efile = self._get_ebuild_filepath ( ver )
-
-				if not overwrite and efile == p_info ['ebuild_file']:
-					print ( efile + " exists, skipping write()." )
-
-
-				elif self.write_ebuild (
-					efile, p_info ['ebuild'], header, shared_fh
-				):
-					if shared_fh is None:
-						# this marks the package as 'written to fs'
-						p_info.update_now (
-							ebuild_file=efile,
-							remove_auto='ebuild_written'
-						)
-
-						self._package_for_manifest = p_info
-
-						self.logger.info ( "Wrote ebuild {}.".format ( efile ) )
-				else:
-					self.logger.error (
-						"Couldn't write ebuild {}.".format ( efile )
-					)
-	# --- end of write_ebuilds (...) ---
+		return self.write ( default_header=default_header, shared_fh=stream )
+	# --- end of show (...) ---
 
 	def write ( self,
-		default_header=None, write_manifest=True, shared_fh=None
+		default_header=None, shared_fh=None,
+		write_ebuilds=True, write_manifest=True, write_metadata=True,
+		overwrite_ebuilds=True
 	):
 		"""Writes this directory to its (existent!) filesystem location.
 
 		arguments:
 		* default_header    -- ebuild header to write
-		* write_manifest -- if set and False: don't write the Manifest file
+		* shared_fh         -- if set and not None: write everyting into <fh>
+		* write_ebuilds     -- if set and False: don't write ebuilds
+		* write_manifest    -- if set and False: don't write the Manifest file
+		* write_metadata    -- if set and False: don't write the metadata file
+		* overwrite_ebuilds -- if set and False: don't overwrite ebuilds
 
 		returns: None (implicit)
 
 		raises:
-		* IOError
+		* IOError (?)
 		"""
-		self._lock.acquire()
-		try:
+		with self._lock:
 			# mkdir not required here, overlay.Category does this
 
 			# write ebuilds
-			self.write_ebuilds ( header=default_header, shared_fh=shared_fh )
+			if write_ebuilds:
+				self.write_ebuilds (
+					default_header=default_header, shared_fh=shared_fh,
+					overwrite=overwrite_ebuilds
+				)
 
 			# write metadata
-			self.write_metadata ( shared_fh=shared_fh )
+			if write_metadata:
+				self.write_metadata ( shared_fh=shared_fh )
 
-			if write_manifest and shared_fh is not None:
+			# write manifest (only if shared_fh is None)
+			if write_manifest and shared_fh is None:
 				self.write_manifest()
-
-		finally:
-			self._lock.release()
 	# --- end of write (...) ---
 
-	def show ( self, stream=sys.stderr, default_header=None ):
-		"""Prints this dir (the ebuilds and the metadata) into a stream.
-
-		arguments:
-		* stream -- stream to use, defaults to sys.stderr
-
-		returns: None (implicit)
-
-		raises:
-		* IOError
-		"""
-		self.write (
-			default_header=default_header, shared_fh=stream, write_manifest=False
-		)
-	# --- end of show (...) ---
-
-	def _latest_package ( self, pkg_filter=None, use_lock=False ):
-		"""Returns the package info with the highest version number.
-
-		arguments:
-		* pkg_filter -- either None or a callable,
-		                 None: do not filter packages
-		                 else: ignore package if it does not pass the filter
-		* use_lock   -- if True: hold lock while searching
-		"""
-		first  = True
-		retver = None
-		retpkg = None
-
-		if use_lock: self._lock.acquire()
-		try:
-			for p in self._packages.values():
-				if pkg_filter is None or pkg_filter ( p ):
-					newver = p ['version']
-					if first or newver > retver:
-						retver = newver
-						retpkg = p
-						first  = False
-		finally:
-			if use_lock: self._lock.release()
-		return retpkg
-	# --- end of _latest_package (...) ---
-
-	def add ( self, package_info ):
-		"""Adds a package to this PackageDir.
+	def write_ebuilds ( self, default_header, overwrite, shared_fh=None ):
+		"""Writes all ebuilds.
 
 		arguments:
-		* package_info --
-
-		returns: success as bool
-
-		raises: Exception when ebuild already exists.
+		* default_header -- ebuild header
+		* shared_fh      -- if set and not None: don't use own file handles
+		                     (i.e. write files), write everything into shared_fh
+		* overwrite      -- write ebuilds that have been written before,
+		                     defaults to True
 		"""
-		shortver = package_info ['ebuild_verstr']
-
-		def already_exists ():
-			if shortver in self._packages:
-				self.logger.info (
-					"'{PN}-{PVR}.ebuild' already exists, cannot add it!".format (
-						PN=self.name, PVR=shortver
-					)
-				)
-				return True
-			else:
-				return False
-		# --- end of already_exists (...) ---
-
-		_success = False
-
-		if not already_exists():
+		def write_ebuild ( efile, ebuild ):
+			"""Writes an ebuild.
+
+			arguments:
+			* efile  -- file to write
+			* ebuild -- ebuild object to write (has to have a __str__ method)
+			* (default_header from write_ebuilds())
+			* (shared_fh from write_ebuilds())
+			"""
+			_success = False
 			try:
-				self._lock.acquire()
-				if not already_exists():
-					self._packages [shortver] = package_info
-					self.modified = True
-					_success = True
+				fh = open ( efile, 'w' ) if shared_fh is None else shared_fh
+				if default_header is not None:
+					fh.write ( str ( default_header ) )
+					fh.write ( '\n\n' )
+				fh.write ( str ( ebuild ) )
+				fh.write ( '\n' )
+
+				# adjust owner/perm? TODO
+				#if shared_fh is None:
+				#	chmod 0644 or 0444
+				#	chown 250.250
+				_success = True
+			except IOError as e:
+				self.logger.exception ( e )
 			finally:
-				self._lock.release()
+				if shared_fh is None and 'fh' in locals() and fh:
+					fh.close()
 
-		return _success
-	# --- end of add (...) ---
+			return _success
+		# --- end of write_ebuild (...) ---
 
-	def _regen_metadata ( self ):
-		"""Regenerates the metadata."""
-		self.generate_metadata (
-			skip_if_existent=True,
-			use_all_packages=False,
-			use_old_metadata=False
-		)
-	# --- end of _regen_metadata (...) ---
+		def ebuilds_to_write():
+			"""Yields all ebuilds that are ready to be written."""
 
-	def generate_metadata (
-		self,
-		skip_if_existent=False, use_all_packages=False, use_old_metadata=False
-	):
-		"""Creates metadata for this package.
+			for ver, p_info in self._packages.items():
+				if p_info.has ( 'ebuild' ) and not p_info ['physical_only']:
+					efile = self.ebuild_filepath_format.format ( PVR=ver )
 
-		arguments:
-		* skip_if_existent -- do not create if metadata already exist
-		* use_all_packages -- TODO in metadata
-		* use_old_metadata -- TODO in metadata
-		"""
-		if use_old_metadata or use_all_packages:
-			raise Exception ( "using >1 package for metadata.xml is TODO!" )
+					if efile != p_info ['ebuild_file'] or overwrite:
+						yield ( efile, p_info )
+					# else efile exists
+		# --- end of ebuilds_to_write (...) ---
 
-		if skip_if_existent and not self._metadata is None: return
+		all_ebuilds_written = True
 
-		self._lock.acquire()
-		try:
+		for efile, p_info in ebuilds_to_write():
+			if write_ebuild ( efile, p_info ['ebuild'] ):
+				self._need_manifest = True
+
+				# update metadata for each successfully written ebuild
+				#  (self._metadata knows how to handle this request)
+				self._metadata.update ( p_info )
 
-			if self._metadata is None or not use_old_metadata:
-				del self._metadata
-				self._metadata = MetadataJob ( self.logger )
+				if shared_fh is None:
+					# this marks the package as 'written to fs'
+					p_info.update_now (
+						ebuild_file=efile,
+						remove_auto='ebuild_written'
+					)
 
-			if use_all_packages:
-				for p_info in self._packages:
-					self._metadata.update ( p_info )
+					self.logger.info ( "Wrote ebuild {}.".format ( efile ) )
 			else:
-				self._metadata.update ( self._latest_package() )
+				all_ebuilds_written = False
+				self.logger.error (
+					"Couldn't write ebuild {}.".format ( efile )
+				)
 
-		finally:
-			self._lock.release()
-	# --- end of generate_metadata (...) ---
+		self.modified = not all_ebuilds_written
+	# --- end of write_ebuilds (...) ---
+
+	def write_incremental ( self, default_header ):
+		with self._lock:
+			self.write_ebuilds ( default_header=default_header, overwrite=False )
+	# --- end of write_incremental (...) ---
 
 	def write_manifest ( self ):
 		"""Generates and writes the Manifest file for this package.
 
-		expects: called in self.write(), after writing metadata/ebuilds
+		expects: called after writing metadata/ebuilds
 
 		returns: None (implicit)
 
@@ -378,27 +323,47 @@ class PackageDir ( object ):
 		"""
 
 		# it should be sufficient to call create_manifest for one ebuild,
-		#  choosing the latest one here that exists in self.physical_location.
+		#  choosing the latest one that exists in self.physical_location and
+		#  has enough data (DISTDIR, EBUILD_FILE) for this task.
 		#
 		# metadata.xml's full path cannot be used for manifest creation here
 		#  'cause DISTDIR would be unknown
 		#
-#		pkg_info_for_manifest = self._latest_package (
-#			pkg_filter=lambda pkg : pkg ['ebuild_file'] is not None,
-#			use_lock=True
-#		)
 
-		if self._package_for_manifest is None:
-			# ? FIXME
+		if self._manifest_package is not None:
+			manifest.create_manifest ( self._manifest_package, nofail=False )
+			self._need_manifest = False
+		else:
 			raise Exception (
 				"No ebuild written so far! I really don't know what do to!"
 			)
-		else:
-			# TODO: manifest creation interface is single threaded,
-			#        may want to 'fix' this later
-			manifest.create_manifest (
-				self._package_for_manifest, nofail=False,
-				#ebuild_file=...
+	# --- end of write_manifest (...) ---
+
+	def write_metadata ( self, shared_fh=None ):
+		"""Writes metadata for this package."""
+		if self._manifest_package is None and not shared_fh:
+			self.logger.error (
+				'write_metadata() requested, but no ebuild written so far! '
+				'This will most likely result in a corrupt Manifest.'
 			)
 
-	# --- end of write_manifest (...) ---
+		try:
+			self.generate_metadata ( skip_if_existent=True )
+
+			if self._metadata.write() \
+				if shared_fh is None else self._metadata.show ( shared_fh ) \
+			:
+				self._need_metadata = False
+				self._need_manifest = True
+				return True
+			else:
+				self.logger.error (
+					"Failed to write metadata file {}.".format (
+						self._metadata.filepath
+					)
+				)
+				return False
+		except:
+			# already logged
+			return False
+	# --- end of write_metadata (...) ---

diff --git a/roverlay/overlay/root.py b/roverlay/overlay/root.py
index 26be02a..e0446df 100644
--- a/roverlay/overlay/root.py
+++ b/roverlay/overlay/root.py
@@ -74,6 +74,8 @@ class Overlay ( object ):
 		self.default_category  = default_category
 		self.eclass_files      = eclass_files
 
+		self.ignore_existing_ebuilds = False
+
 		self._profiles_dir     = self.physical_location + os.sep + 'profiles'
 		self._catlock          = threading.Lock()
 		self._categories       = dict()
@@ -143,7 +145,7 @@ class Overlay ( object ):
 		return self._categories [category]
 	# --- end of _get_category (...) ---
 
-	def add ( self, package_info, write_after_add=False, category=None ):
+	def add ( self, package_info, category=None ):
 		"""Adds a package to this overlay.
 
 		arguments:
@@ -158,12 +160,9 @@ class Overlay ( object ):
 		)
 
 		if write_after_add:
-			util.dodir ( cat.physical_location, mkdir_p=True )
-			return cat.add (
-				package_info, write_after_add=True, header = self._get_header()
-			)
-		else:
-			return cat.add ( package_info, write_after_add=False )
+			raise Exception ( "add~write_after_add: to be removed." )
+
+		return cat.add ( package_info, write_after_add=False )
 	# --- end of add (...) ---
 
 	def show ( self, **show_kw ):
@@ -228,6 +227,16 @@ class Overlay ( object ):
 			self._incremental_write_lock.release()
 	# --- end of write_incremental (...) ---
 
+	def finalize_write_incremental ( self ):
+		"""Writes metadata + Manifest for all packages."""
+		self._init_overlay ( reimport_eclass=True, make_profiles_dir=True )
+
+		for cat in self._categories.values():
+			cat.finalize_write_incremental()
+
+		self._write_categories ( only_active=True )
+	# --- end of finalize_incremental (...) ---
+
 	def generate_metadata ( self, **metadata_kw ):
 		"""Tells the overlay's categories to create metadata.
 		You don't have to call this before write()/show() unless you want to use


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [gentoo-commits] proj/R_overlay:master commit in: roverlay/overlay/metadata/, roverlay/overlay/
  2012-07-23 16:34 [gentoo-commits] proj/R_overlay:overlay_wip " André Erdmann
@ 2012-07-30  8:52 ` André Erdmann
  0 siblings, 0 replies; 4+ messages in thread
From: André Erdmann @ 2012-07-30  8:52 UTC (permalink / raw
  To: gentoo-commits

commit:     b60d7f137f1f99f4b4afe85d1f82ace045d6b211
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Mon Jul 23 16:31:50 2012 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Mon Jul 23 16:31:50 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=b60d7f13

incremental overlay writing: keep n ebuilds

Added keep_nth_latest(n) which keeps the n-th latest ebuilds
of a PackageDir and removes all others.
Also added fs_cleanup() that removes "empty" (no ebuilds) package dirs from
the filesystem.

	geändert:   roverlay/overlay/category.py
	geändert:   roverlay/overlay/creator.py
	geändert:   roverlay/overlay/metadata/abstractnodes.py
	geändert:   roverlay/overlay/metadata/nodes.py
	geändert:   roverlay/overlay/package.py
	geändert:   roverlay/overlay/root.py

---
 roverlay/overlay/category.py               |    7 +
 roverlay/overlay/creator.py                |    1 +
 roverlay/overlay/metadata/abstractnodes.py |    2 +-
 roverlay/overlay/metadata/nodes.py         |    3 +-
 roverlay/overlay/package.py                |  153 +++++++++-
 roverlay/overlay/root.py                   |  428 +++++++++++++---------------
 6 files changed, 352 insertions(+), 242 deletions(-)

diff --git a/roverlay/overlay/category.py b/roverlay/overlay/category.py
index 1d0bf97..33149c4 100644
--- a/roverlay/overlay/category.py
+++ b/roverlay/overlay/category.py
@@ -104,6 +104,13 @@ class Category ( object ):
 		return os.path.isdir ( self.physical_location + os.sep + _dir )
 	# --- end of has_category (...) ---
 
+	def keep_nth_latest ( self, *args, **kwargs ):
+		"""See package.py:PackageDir:keep_nth_latest."""
+		for subdir in self._subdirs.values():
+			subdir.keep_nth_latest ( *args, **kwargs )
+			subdir.fs_cleanup()
+	# --- end of keep_nth_latest (...) ---
+
 	def list_packages ( self, for_deprules=False ):
 		"""Lists all packages in this category.
 		Yields <category>/<package name> or a dict (see for_deprules below).

diff --git a/roverlay/overlay/creator.py b/roverlay/overlay/creator.py
index 114f12d..9de063c 100644
--- a/roverlay/overlay/creator.py
+++ b/roverlay/overlay/creator.py
@@ -304,6 +304,7 @@ class OverlayCreator ( object ):
 
 		self._close_workers()
 		close_resolver()
+		self.overlay.keep_nth_latest ( n=1 )
 		self.closed = True
 	# --- end of close (...) ---
 

diff --git a/roverlay/overlay/metadata/abstractnodes.py b/roverlay/overlay/metadata/abstractnodes.py
index a344fc1..284ea20 100644
--- a/roverlay/overlay/metadata/abstractnodes.py
+++ b/roverlay/overlay/metadata/abstractnodes.py
@@ -242,7 +242,7 @@ class MetadataLeaf ( _MetadataBasicNode ):
 		self._do_verify()
 		if self.print_node_name:
 			return "{indent}<{name}{flags}>{value}</{name}>".format (
-				indent=self._indent,
+				indent=self.indent,
 				name=self.name,
 				flags=self._flagstr(),
 				value=self._value_str(),

diff --git a/roverlay/overlay/metadata/nodes.py b/roverlay/overlay/metadata/nodes.py
index 02d5482..0002267 100644
--- a/roverlay/overlay/metadata/nodes.py
+++ b/roverlay/overlay/metadata/nodes.py
@@ -22,7 +22,8 @@ class MetadataRoot ( MetadataNodeNamedAccess ):
 
 	def __init__ ( self ):
 		super ( MetadataRoot, self ) . __init__ ( 'pkgmetadata' )
-		self.priority = 0
+		self.priority    = 0
+		self.allow_empty = True
 	# --- end of __init__ (...) ---
 
 	def empty ( self ):

diff --git a/roverlay/overlay/package.py b/roverlay/overlay/package.py
index 2ea4cb2..a2e4d9b 100644
--- a/roverlay/overlay/package.py
+++ b/roverlay/overlay/package.py
@@ -1,14 +1,15 @@
 import os
 import sys
 import threading
+import shutil
 
+from roverlay                  import util
 from roverlay.overlay          import manifest
 from roverlay.packageinfo      import PackageInfo
 from roverlay.overlay.metadata import MetadataJob
 
 SUPPRESS_EXCEPTIONS = True
 
-
 class PackageDir ( object ):
 	EBUILD_SUFFIX = '.ebuild'
 
@@ -48,6 +49,22 @@ class PackageDir ( object ):
 		self._need_metadata    = False
 	# --- end of __init__ (...) ---
 
+	def _remove_ebuild_file ( self, pkg_info ):
+		"""Removes the ebuild file of a pkg_info object.
+		Returns True on success, else False.
+		"""
+		try:
+			efile = pkg_info ['ebuild_file']
+			if efile is not None:
+				os.unlink ( efile )
+				# Manifest file has to be updated
+				self._need_manifest = True
+			return True
+		except Exception as e:
+			self.logger.exception ( e )
+			return False
+	# --- end of remove_ebuild_file (...) ---
+
 	def add ( self, package_info, add_if_physical=False ):
 		"""Adds a package to this PackageDir.
 
@@ -105,19 +122,51 @@ class PackageDir ( object ):
 
 	def empty ( self ):
 		"""Returns True if no ebuilds stored, else False.
-		Note that "not empty" does not mean "have ebuilds to write".
+		Note that "not empty" doesn't mean "has ebuilds to write" or "has
+		ebuilds written", use the modified attribute for the former, and the
+		has_ebuilds() function for the latter one.
 		"""
 		return len ( self._packages ) == 0
 	# --- end of empty (...) ---
 
 	def finalize_write_incremental ( self ):
+		"""Method that finalizes incremental writing, i.e. write outstanding
+		ebuilds and write metadata.xml, Manifest.
+		"""
 		with self._lock:
-			if self._need_metadata:
-				self.write_metadata()
-			if self._need_manifest:
-				self.write_manifest()
+			if self.has_ebuilds():
+				if self.modified:
+					self.write_ebuilds ( overwrite=False )
+				if self._need_metadata:
+					self.write_metadata()
+				if self._need_manifest:
+					self.write_manifest()
+			else:
+				self.logger.critical (
+					"<<todo>>: please clean up this dir: {}.".format (
+						self.physical_location
+				) )
 	# --- end of finalize_write_incremental (...) ---
 
+	def fs_cleanup ( self ):
+		"""Cleans up the filesystem location of this package dir.
+		To be called after keep_nth_latest, calls finalize_write_incremental().
+		"""
+		def rmtree_error ( function, path, excinfo ):
+			"""rmtree onerror function that simply logs the exception"""
+			self.logger.exception ( excinfo )
+		# --- end of rmtree_error (...) ---
+
+		with self._lock:
+			if self.has_ebuilds():
+				# !!! FIXME this doesn't work if no ebuilds written, but
+				# old ones removed -> DISTDIR unknown during Manifest creation
+				self.finalize_write_incremental()
+			elif os.path.isdir ( self.physical_location ):
+				# destroy self.physical_location
+				shutil.rmtree ( self.physical_location, onerror=rmtree_error )
+	# --- end of fs_cleanup (...) ---
+
 	def generate_metadata ( self, skip_if_existent, **ignored_kw ):
 		"""Creates metadata for this package.
 
@@ -129,6 +178,70 @@ class PackageDir ( object ):
 				self._metadata.update_using_iterable ( self._packages.values() )
 	# --- end of generate_metadata (...) ---
 
+	def has_ebuilds ( self ):
+		"""Returns True if this PackageDir has any ebuild files (filesystem)."""
+		for p in self._packages.values():
+			if p ['physical_only'] or p.has ( 'ebuild' ):
+				return True
+		return False
+	# --- end of has_ebuilds (...) ---
+
+	def keep_nth_latest ( self, n, cautious=True ):
+		"""Keeps the n-th latest ebuild files, removing all other packages,
+		physically (filesystem) as well as from this PackageDir object.
+
+		arguments:
+		* n        -- # of packages/ebuilds to keep
+		* cautious -- if True: be extra careful, verify that ebuilds exist
+		"""
+
+		# create the list of packages to iterate over,
+		# * package has to have an ebuild_file
+		# * sort them by version in reverse order (latest package gets index 0)
+		packages = reversed ( sorted (
+			filter (
+				lambda p : p [1] ['ebuild_file'] is not None,
+				self._packages.items()
+			),
+			key=lambda p : p [1] ['version']
+		) )
+
+		kept   = 0
+		ecount = 0
+		if not cautious:
+			# could use a slice here, too
+			for pvr, pkg in packages:
+				ecount += 1
+				if kept < n:
+					printself.logger.debug ( "Keeping {pvr}.".format ( pvr=pvr ) )
+					kept += 1
+				else:
+					self.logger.debug ( "Removing {pvr}.".format ( pvr=pvr ) )
+					self.purge_package ( pvr )
+		else:
+			for pvr, pkg in packages:
+				ecount += 1
+				if os.path.isfile ( pkg ['ebuild_file'] ):
+					if kept < n:
+						self.logger.debug ( "Keeping {pvr}.".format ( pvr=pvr ) )
+						kept += 1
+					else:
+						self.logger.debug ( "Removing {pvr}.".format ( pvr=pvr ) )
+						self.purge_package ( pvr )
+				else:
+					self.logger.error (
+						"{efile} is assumed to exist as file but doesn't!".format (
+							efile=pkg ['ebuild_file']
+					) )
+
+		# FIXME/IGNORE: this doesn't count inexistent files as kept
+		self.logger.debug (
+			"Kept {kept}/{total} ebuilds.".format ( kept=kept, total=ecount )
+		)
+
+		# FIXME: Manifest is now invalid and dir could be "empty" (no ebuilds)
+	# --- end of keep_nth_latest (...) ---
+
 	def list_versions ( self ):
 		return self._packages.keys()
 	# --- end of list_versions (...) ---
@@ -144,6 +257,21 @@ class PackageDir ( object ):
 			return True
 	# --- end of new_ebuild (...) ---
 
+	def purge_package ( self, pvr ):
+		"""Removes the PackageInfo with key pvr entirely from this PackageDir,
+		including its ebuild file.
+		Returns: removed PackageInfo object or None.
+		"""
+		try:
+			p = self._packages [pvr]
+			del self._packages [pvr]
+			self._remove_ebuild_file ( p )
+			return p
+		except Exception as e:
+			self.logger.exception ( e )
+			return None
+	# --- end of purge_package (...) ---
+
 	def scan ( self, **kw ):
 		"""Scans the filesystem location of this package for existing
 		ebuilds and adds them.
@@ -168,7 +296,7 @@ class PackageDir ( object ):
 						# not an ebuild
 						pass
 					elif pn == self.name:
-						yield pvr
+						yield ( pvr, self.physical_location + os.sep + f )
 					else:
 						# $PN does not match directory name, warn about that
 						self.logger.warning (
@@ -183,9 +311,11 @@ class PackageDir ( object ):
 
 		# ignore directories without a Manifest file
 		if os.path.isfile ( self.physical_location + os.sep + 'Manifest' ):
-			for pvr in scan_ebuilds():
+			for pvr, efile in scan_ebuilds():
 				if pvr not in self._packages:
-					p = PackageInfo ( physical_only=True, pvr=pvr )
+					p = PackageInfo (
+						physical_only=True, pvr=pvr, ebuild_file=efile
+					)
 					self._packages [ p ['ebuild_verstr'] ] = p
 	# --- end of scan (...) ---
 
@@ -260,6 +390,7 @@ class PackageDir ( object ):
 			"""
 			_success = False
 			try:
+				util.dodir ( self.physical_location )
 				fh = open ( efile, 'w' ) if shared_fh is None else shared_fh
 				if ebuild_header is not None:
 					fh.write ( str ( ebuild_header ) )
@@ -380,7 +511,7 @@ class PackageDir ( object ):
 			else:
 				self._metadata.show ( shared_fh )
 				return True
-		except:
-			# already logged
+		except Exception as e:
+			self.logger.exception ( e )
 			return False
 	# --- end of write_metadata (...) ---

diff --git a/roverlay/overlay/root.py b/roverlay/overlay/root.py
index 51239e2..363bdb5 100644
--- a/roverlay/overlay/root.py
+++ b/roverlay/overlay/root.py
@@ -27,11 +27,6 @@ class Overlay ( object ):
 		ebuild_header,
 		incremental
 	):
-		if directory is None:
-			raise Exception (
-				"support for overlays without filesystem location has been dropped"
-			)
-
 		self.name              = name
 		self.logger            = logger.getChild ( 'overlay' )
 		self.physical_location = directory
@@ -47,7 +42,7 @@ class Overlay ( object ):
 
 		# fixme or ignore: calculating eclass names twice,
 		# once here and another time when calling _init_overlay
-		self._header.set_eclasses ( set (
+		self._header.set_eclasses ( frozenset (
 			self._get_eclass_import_info ( only_eclass_names=True )
 		) )
 
@@ -56,44 +51,10 @@ class Overlay ( object ):
 
 			self._incremental_write_lock = threading.Lock()
 			self.scan()
-			self._init_overlay ( reimport_eclass=True, make_profiles_dir=True )
+			self._init_overlay ( reimport_eclass=True )
 
 	# --- end of __init__ (...) ---
 
-	def scan ( self, **kw ):
-		if os.path.isdir ( self.physical_location ):
-			for cat in self._scan_categories():
-				try:
-					cat.scan ( **kw )
-				except Exception as e:
-					self.logger.exception ( e )
-#		for package in sorted ( self.list_packages() ):
-#			print ( package )
-	# --- end of scan (...) ---
-
-	def list_packages ( self, for_deprules=True ):
-		for cat in self._categories.values():
-			for package in cat.list_packages ( for_deprules=True ):
-				yield package
-	# --- end of list_packages (...) ---
-
-	def list_rule_kwargs ( self ):
-		for cat in self._categories.values():
-			for kwargs in cat.list_packages ( for_deprules=True ):
-				yield kwargs
-	# --- end of list_rule_kwargs (...) ---
-
-	def has_dir ( self, _dir ):
-		return os.path.isdir ( self.physical_location + os.sep + _dir )
-	# --- end of has_category (...) ---
-
-	def _scan_categories ( self ):
-		for x in os.listdir ( self.physical_location ):
-			# FIXME could use a better check here
-			if '-' in x and self.has_dir ( x ):
-				yield self._get_category ( x )
-	# --- end of _scan_categories (...) ---
-
 	def _get_category ( self, category ):
 		"""Returns a reference to the given category. Creates it if necessary.
 
@@ -120,191 +81,6 @@ class Overlay ( object ):
 		return self._categories [category]
 	# --- end of _get_category (...) ---
 
-	def add ( self, package_info, category=None ):
-		"""Adds a package to this overlay.
-
-		arguments:
-		* package_info -- PackageInfo of the package to add
-		* category     -- category where the pkg should be put in, defaults to
-		                   self.default_category
-
-		returns: True if successfully added else False
-		"""
-		cat = self._get_category (
-			self.default_category if category is None else category
-		)
-		return cat.add ( package_info )
-	# --- end of add (...) ---
-
-	def show ( self, **show_kw ):
-		"""Presents the ebuilds/metadata stored in this overlay.
-
-		arguments:
-		* **show_kw -- keywords for package.PackageDir.show(...)
-
-		returns: None (implicit)
-		"""
-		if not self._header.eclasses: self._header.set_eclasses (
-			tuple ( self._get_eclass_import_info ( only_eclass_names=True ) )
-		)
-		for cat in self._categories.values():
-			cat.show ( **show_kw )
-	# --- end of show (...) ---
-
-	def write ( self, **write_kw ):
-		"""Writes the overlay to its physical location (filesystem), including
-		metadata and Manifest files.
-
-		arguments:
-		* **write_kw -- keywords for package.PackageDir.write(...)
-
-		returns: None (implicit)
-
-		raises: IOError
-
-		! TODO/FIXME/DOC: This is not thread-safe, it's expected to be called
-		when ebuild creation is done.
-		"""
-		raise Exception ( "^,^" )
-		# writing profiles/ here, rewriting categories/ later
-		self._init_overlay ( reimport_eclass=True, make_profiles_dir=True )
-
-		for cat in self._categories.values():
-			if not cat.empty():
-				util.dodir ( cat.physical_location )
-				cat.write ( **write_kw )
-
-		self._write_categories ( only_active=True )
-	# --- end of write (...) ---
-
-	def write_incremental ( self, **write_kw ):
-		"""Writes all ebuilds that have been added since the last
-		write_incremental call.
-		TODO:
-		* This could be useful to save some mem by removing already written
-		package infos.
-		* This has to be thread safe
-		"""
-		if not self._incremental_write_lock.acquire():
-			# another incremental write is running, drop this request
-			return
-
-		try:
-			util.dodir ( self.physical_location )
-			cats = tuple ( self._categories.values() )
-			for cat in cats:
-				util.dodir ( cat.physical_location )
-				cat.write_incremental ( **write_kw )
-		finally:
-			self._incremental_write_lock.release()
-	# --- end of write_incremental (...) ---
-
-	def finalize_write_incremental ( self ):
-		"""Writes metadata + Manifest for all packages."""
-		self._write_categories ( only_active=True )
-		for cat in self._categories.values():
-			cat.finalize_write_incremental()
-	# --- end of finalize_incremental (...) ---
-
-	def generate_metadata ( self, **metadata_kw ):
-		"""Tells the overlay's categories to create metadata.
-		You don't have to call this before write()/show() unless you want to use
-		special metadata options.
-
-		arguments:
-		* **metadata_kw -- keywords for package.PackageDir.generate_metadata(...)
-
-		returns: None (implicit)
-		"""
-		for cat in self._categories.values():
-			cat.generate_metadata ( **metadata_kw )
-	# --- end of generate_metadata (...) ---
-
-	def generate_manifest ( self, **manifest_kw ):
-		"""Generates Manifest files for all ebuilds in this overlay that exist
-		physically/in filesystem.
-		Manifest files are automatically created when calling write().
-
-		arguments:
-		* **manifest_kw -- see PackageDir.generate_manifest(...)
-
-		returns: None (implicit)
-		"""
-		for cat in self._categories.values():
-			cat.generate_manifest ( **manifest_kw )
-	# --- end of generate_manifest (...) ---
-
-	def _write_profiles_dir ( self, only_active_categories=True ):
-		"""Creates and updates the profiles/ dir.
-
-		arguments:
-		* only_active_categories -- if True: do not list categories without
-		                                      ebuilds in profiles/categories
-		"""
-		# profiles/
-		util.dodir ( self._profiles_dir )
-		self._write_repo_name()
-		self._write_categories ( only_active=only_active_categories )
-		self._write_usedesc()
-	# --- end of _write_profiles_dir (...) ---
-
-	def _write_profiles_file ( self, filename, to_write ):
-		"""Writes a file in profiles/.
-
-		arguments:
-		* filename -- name of the file to write (including file extension)
-		* to_write -- string to write (don't forget newline at the end)
-		"""
-		fh = None
-		try:
-			fh = open ( self._profiles_dir + os.sep + filename, 'w' )
-			if to_write:
-				# else touch file
-				fh.write ( to_write )
-		except IOError as e:
-			self.logger.exception ( e )
-			raise
-		finally:
-			if fh: fh.close()
-	# --- end of _write_profiles_file (...) ---
-
-	def _write_repo_name ( self ):
-		"""Writes profiles/repo_name."""
-		self._write_profiles_file ( 'repo_name', self.name + '\n' )
-	# --- end of _write_repo_name (...) ---
-
-	def _write_categories ( self, only_active=True ):
-		"""Writes profiles/categories.
-
-		arguments:
-		* only_active -- exclude categories without ebuilds
-		"""
-		cats = None
-		if only_active:
-			cats = [
-				name for name, category
-					in self._categories.items() if not category.empty()
-			]
-		else:
-			cats = list ( self._categories.keys() )
-
-		if cats:
-			self._write_profiles_file (
-				'categories',
-				'\n'.join ( cats ) + '\n'
-			)
-	# --- end of _write_categories (...) ---
-
-	def _write_usedesc ( self ):
-		"""Writes profiles/use.desc."""
-		use_desc = config.get (
-			'OVERLAY.use_desc',
-			fallback_value=DEFAULT_USE_DESC
-		)
-		if use_desc:
-			self._write_profiles_file ( 'use.desc', use_desc + '\n' )
-	# --- end of _write_usedesc (...) ---
-
 	def _get_eclass_import_info ( self, only_eclass_names=False ):
 		"""Yields eclass import information (eclass names and files).
 
@@ -363,7 +139,7 @@ class Overlay ( object ):
 				raise
 	# --- end of _import_eclass (...) ---
 
-	def _init_overlay ( self, reimport_eclass, make_profiles_dir ):
+	def _init_overlay ( self, reimport_eclass ):
 		"""Initializes the overlay at its physical/filesystem location.
 
 		arguments:
@@ -374,14 +150,58 @@ class Overlay ( object ):
 		raises:
 		* IOError
 		"""
+		def write_profiles_dir():
+			"""Creates and updates the profiles/ dir."""
+			def write_profiles_file ( filename, to_write ):
+				"""Writes a file in profiles/.
+
+				arguments:
+				* filename -- name of the file to write (including file extension)
+				* to_write -- string to write (don't forget newline at the end)
+				"""
+				fh = None
+				try:
+					fh = open ( self._profiles_dir + os.sep + filename, 'w' )
+					if to_write:
+						# else touch file
+						fh.write ( to_write )
+				except IOError as e:
+					self.logger.exception ( e )
+					raise
+				finally:
+					if fh: fh.close()
+			# --- end of write_profiles_file (...) ---
+
+			# always use the default category (+write it into profiles/categories)
+			self._get_category ( self.default_category )
+
+			# profiles/
+			util.dodir ( self._profiles_dir )
+
+			# profiless/repo_name
+			write_profiles_file ( 'repo_name', self.name + '\n' )
+
+			# profiles/categories
+			cats = '\n'.join ( self._categories.keys() )
+			if cats:
+				write_profiles_file ( 'categories', cats + '\n' )
+
+			# profiles/use.desc
+			use_desc = config.get (
+				'OVERLAY.use_desc',
+				fallback_value=DEFAULT_USE_DESC
+			)
+			if use_desc:
+				write_profiles_file ( 'use.desc', use_desc + '\n' )
+		# --- end of write_profiles_dir (...) ---
+
 		try:
 			# mkdir overlay root
 			util.dodir ( self.physical_location, mkdir_p=True )
 
 			self._import_eclass ( reimport_eclass )
 
-			if make_profiles_dir:
-				self._write_profiles_dir ( only_active_categories=False )
+			write_profiles_dir()
 
 		except IOError as e:
 
@@ -389,3 +209,153 @@ class Overlay ( object ):
 			self.logger.critical ( "^failed to init overlay" )
 			raise
 	# --- end of _init_overlay (...) ---
+
+	def add ( self, package_info, category=None ):
+		"""Adds a package to this overlay.
+
+		arguments:
+		* package_info -- PackageInfo of the package to add
+		* category     -- category where the pkg should be put in, defaults to
+		                   self.default_category
+
+		returns: True if successfully added else False
+		"""
+		cat = self._get_category (
+			self.default_category if category is None else category
+		)
+		return cat.add ( package_info )
+	# --- end of add (...) ---
+
+	def finalize_write_incremental ( self ):
+		"""Writes metadata + Manifest for all packages."""
+		for cat in self._categories.values():
+			cat.finalize_write_incremental()
+	# --- end of finalize_incremental (...) ---
+
+	def generate_manifest ( self, **manifest_kw ):
+		"""Generates Manifest files for all ebuilds in this overlay that exist
+		physically/in filesystem.
+		Manifest files are automatically created when calling write().
+
+		arguments:
+		* **manifest_kw -- see PackageDir.generate_manifest(...)
+
+		returns: None (implicit)
+		"""
+		for cat in self._categories.values():
+			cat.generate_manifest ( **manifest_kw )
+	# --- end of generate_manifest (...) ---
+
+	def generate_metadata ( self, **metadata_kw ):
+		"""Tells the overlay's categories to create metadata.
+		You don't have to call this before write()/show() unless you want to use
+		special metadata options.
+
+		arguments:
+		* **metadata_kw -- keywords for package.PackageDir.generate_metadata(...)
+
+		returns: None (implicit)
+		"""
+		for cat in self._categories.values():
+			cat.generate_metadata ( **metadata_kw )
+	# --- end of generate_metadata (...) ---
+
+	def has_dir ( self, _dir ):
+		return os.path.isdir ( self.physical_location + os.sep + _dir )
+	# --- end of has_category (...) ---
+
+	def keep_nth_latest ( self, *args, **kwargs ):
+		"""See package.py:PackageDir:keep_nth_latest."""
+		for cat in self._categories.values():
+			cat.keep_nth_latest ( *args, **kwargs )
+	# --- end of keep_nth_latest (...) ---
+
+	def list_packages ( self, for_deprules=True ):
+		for cat in self._categories.values():
+			for package in cat.list_packages ( for_deprules=True ):
+				yield package
+	# --- end of list_packages (...) ---
+
+	def list_rule_kwargs ( self ):
+		for cat in self._categories.values():
+			for kwargs in cat.list_packages ( for_deprules=True ):
+				yield kwargs
+	# --- end of list_rule_kwargs (...) ---
+
+	def scan ( self, **kw ):
+		def scan_categories():
+			for x in os.listdir ( self.physical_location ):
+				# FIXME could use a better check here
+				if '-' in x and self.has_dir ( x ):
+					yield self._get_category ( x )
+		# --- end of scan_categories (...) ---
+
+		if os.path.isdir ( self.physical_location ):
+			for cat in scan_categories():
+				try:
+					cat.scan ( **kw )
+				except Exception as e:
+					self.logger.exception ( e )
+	# --- end of scan (...) ---
+
+	def show ( self, **show_kw ):
+		"""Presents the ebuilds/metadata stored in this overlay.
+
+		arguments:
+		* **show_kw -- keywords for package.PackageDir.show(...)
+
+		returns: None (implicit)
+		"""
+		if not self._header.eclasses: self._header.set_eclasses (
+			tuple ( self._get_eclass_import_info ( only_eclass_names=True ) )
+		)
+		for cat in self._categories.values():
+			cat.show ( **show_kw )
+	# --- end of show (...) ---
+
+	def write ( self, **write_kw ):
+		"""Writes the overlay to its physical location (filesystem), including
+		metadata and Manifest files.
+
+		arguments:
+		* **write_kw -- keywords for package.PackageDir.write(...)
+
+		returns: None (implicit)
+
+		raises: IOError
+
+		! TODO/FIXME/DOC: This is not thread-safe, it's expected to be called
+		when ebuild creation is done.
+		"""
+		raise Exception ( "to be removed/replaced" )
+		# writing profiles/ here, rewriting categories/ later
+		self._init_overlay ( reimport_eclass=True )
+
+		for cat in self._categories.values():
+			if not cat.empty():
+				util.dodir ( cat.physical_location )
+				cat.write ( **write_kw )
+	# --- end of write (...) ---
+
+	def write_incremental ( self, **write_kw ):
+		"""Writes all ebuilds that have been modified since the last write call.
+		Note that there are currently two modes of incremental writing:
+		(a) per-PackageDir incremental writing triggered by the new_ebuild()
+		event method and (b) "batched" incremental writing (this method) which
+		writes all modified PackageDirs.
+		"""
+		# FIXME merge with write(), making incremental writing the only option
+		# FIXME finalize_write_incremental?
+		if not self._incremental_write_lock.acquire():
+			# another incremental write is running, drop this request
+			return
+
+		try:
+			util.dodir ( self.physical_location )
+			cats = tuple ( self._categories.values() )
+			for cat in cats:
+				util.dodir ( cat.physical_location )
+				cat.write_incremental ( **write_kw )
+		finally:
+			self._incremental_write_lock.release()
+	# --- end of write_incremental (...) ---


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [gentoo-commits] proj/R_overlay:master commit in: roverlay/overlay/metadata/, roverlay/overlay/
@ 2012-07-31 17:51 André Erdmann
  0 siblings, 0 replies; 4+ messages in thread
From: André Erdmann @ 2012-07-31 17:51 UTC (permalink / raw
  To: gentoo-commits

commit:     3a7ca63ed7d8a57927835ce06b718354caa30b1a
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Tue Jul 31 14:02:27 2012 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Tue Jul 31 14:02:27 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=3a7ca63e

fix show_metadata

this fixes calling show_metadata with no metadata available

---
 roverlay/overlay/metadata/__init__.py |   44 +++++++++++++++++++-------------
 roverlay/overlay/package.py           |    1 +
 2 files changed, 27 insertions(+), 18 deletions(-)

diff --git a/roverlay/overlay/metadata/__init__.py b/roverlay/overlay/metadata/__init__.py
index c07f7a2..36e775c 100644
--- a/roverlay/overlay/metadata/__init__.py
+++ b/roverlay/overlay/metadata/__init__.py
@@ -42,7 +42,9 @@ class MetadataJob ( object ):
 				self._package_info = package_info
 	# --- end of update (...) ---
 
-	def update_using_iterable ( self, package_info_iter ):
+	def update_using_iterable ( self, package_info_iter, reset=True ):
+		if reset:
+			self._package_info = None
 		for package_info in package_info_iter:
 			self.update ( package_info )
 	# --- end of update_using_iterable (...) ---
@@ -101,24 +103,30 @@ class MetadataJob ( object ):
 	# --- end of _write (...) ---
 
 	def show ( self, stream ):
-		return self._create().write_file ( stream )
+		if self._package_info is not None:
+			return self._create().write_file ( stream )
+		else:
+			return False
 	# --- end of show (...) ---
 
 	def write ( self ):
-		_success = False
-		try:
-			# succeed if metadata empty or written
-			mref = self._create()
-			if mref.empty():
-				_success = True
-			else:
-				fh = open ( self.filepath, 'w' )
-				_success = self._write ( fh, mref )
-
-		except Exception as e:
-			self.logger.exception ( e )
-		finally:
-			if 'fh' in locals() and fh: fh.close()
-
-		return _success
+		if self._package_info is not None:
+			_success = False
+			try:
+				# succeed if metadata empty or written
+				mref = self._create()
+				if mref.empty():
+					_success = True
+				else:
+					fh = open ( self.filepath, 'w' )
+					_success = self._write ( fh, mref )
+
+			except Exception as e:
+				self.logger.exception ( e )
+			finally:
+				if 'fh' in locals() and fh: fh.close()
+
+			return _success
+		else:
+			return False
 	# --- end of write (...) ---

diff --git a/roverlay/overlay/package.py b/roverlay/overlay/package.py
index cb5cf72..434b1b1 100644
--- a/roverlay/overlay/package.py
+++ b/roverlay/overlay/package.py
@@ -158,6 +158,7 @@ class PackageDir ( object ):
 			# FIXME debug print
 			print ( "removing {PVR} from {PN}".format ( PVR=pvr, PN=self.name ) )
 			del self._packages [pvr]
+			self.generate_metadata ( skip_if_existent=False )
 		except KeyError:
 			pass
 		finally:


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [gentoo-commits] proj/R_overlay:master commit in: roverlay/overlay/metadata/, roverlay/overlay/
@ 2012-08-02 15:14 André Erdmann
  0 siblings, 0 replies; 4+ messages in thread
From: André Erdmann @ 2012-08-02 15:14 UTC (permalink / raw
  To: gentoo-commits

commit:     041f770675b288ef3f6a04670b9c4e399e4e26f0
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Thu Aug  2 15:10:56 2012 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Thu Aug  2 15:10:56 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=041f7706

overlay: comments, string formatting and strutil

also readded RERAISE to category.py's threaded overlay writing

---
 roverlay/overlay/category.py               |   10 +++++---
 roverlay/overlay/creator.py                |   13 +----------
 roverlay/overlay/metadata/abstractnodes.py |   30 +++++++++++++--------------
 roverlay/overlay/metadata/nodes.py         |    3 +-
 roverlay/overlay/package.py                |   28 +++++++++++--------------
 roverlay/overlay/root.py                   |   23 +++++++++++++--------
 6 files changed, 49 insertions(+), 58 deletions(-)

diff --git a/roverlay/overlay/category.py b/roverlay/overlay/category.py
index 3551b81..7bf93c8 100644
--- a/roverlay/overlay/category.py
+++ b/roverlay/overlay/category.py
@@ -158,10 +158,9 @@ class Category ( object ):
 					pkg.write ( write_manifest=False, **write_kw )
 				except queue.Empty:
 					break
-				#except ( Exception, KeyboardInterrupt ) as e:
 				except Exception as e:
-					# FIXME: reintroduce RERAISE
-					self.logger.exception ( e )
+					#self.logger.exception ( e )
+					self.RERAISE = e
 		# --- end of run_write_queue (...) ---
 
 		if len ( self._subdirs ) == 0: return
@@ -177,7 +176,7 @@ class Category ( object ):
 
 		max_jobs = self.__class__.WRITE_JOBCOUNT
 
-		# FIXME/TODO: what's an reasonable number of min package dirs to
+		# What's an reasonable number of min package dirs to
 		# start threaded writing?
 		# Ignoring it for now (and expecting enough pkg dirs)
 		if max_jobs > 1:
@@ -201,6 +200,9 @@ class Category ( object ):
 			for w in workers: w.start()
 			for w in workers: w.join()
 
+			if hasattr ( self, 'RERAISE' ) and self.RERAISE is not None:
+				raise self.RERAISE
+
 			self.remove_empty()
 
 			# write manifest files

diff --git a/roverlay/overlay/creator.py b/roverlay/overlay/creator.py
index 5f346fe..6b42867 100644
--- a/roverlay/overlay/creator.py
+++ b/roverlay/overlay/creator.py
@@ -196,7 +196,7 @@ class OverlayCreator ( object ):
 		delta = _stop - start
 
 		self.logger.debug (
-			"timestamp: %s (after %f seconds)" % ( description, delta )
+			"timestamp: {} (after {} seconds)".format ( description, delta )
 		)
 		return _stop
 	# --- end of _timestamp (...) ---
@@ -214,10 +214,7 @@ class OverlayCreator ( object ):
 	# --- end of add_package (...) ---
 
 	def write_overlay ( self ):
-		"""Writes the overlay.
-
-		arguments:
-		"""
+		"""Writes the overlay."""
 		if self.overlay.writeable():
 			start = time.time()
 			self.overlay.write()
@@ -306,7 +303,6 @@ class OverlayCreator ( object ):
 
 				if do_close:
 					self._err_queue.push ( context=-1, error=None )
-					# fixme: remove enabled?
 					for w in self._workers: w.enabled = False
 				else:
 					for w in self._workers: w.stop_when_empty()
@@ -373,11 +369,6 @@ class OverlayCreator ( object ):
 		arguments:
 		* package_info --
 		"""
-		# ... TODO
-		#  * increase the number of successful/failed packages,
-		#  * request an incremental write to save memory etc.
-
-		# if <>:
 		if package_info ['ebuild'] is not None:
 			self.create_success.inc()
 			if package_info.overlay_package_ref.new_ebuild():

diff --git a/roverlay/overlay/metadata/abstractnodes.py b/roverlay/overlay/metadata/abstractnodes.py
index 284ea20..060d369 100644
--- a/roverlay/overlay/metadata/abstractnodes.py
+++ b/roverlay/overlay/metadata/abstractnodes.py
@@ -2,6 +2,7 @@
 # Copyright 2006-2012 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
+from roverlay import strutil
 import re
 import textwrap
 
@@ -16,7 +17,6 @@ class _MetadataBasicNode ( object ):
 	"""
 
 	# these chars lead to metadata.bad: invalid token
-	# TODO/FIXME: look into repoman's / portage's source to get _all_ chars
 	INVALID_CHARS = "&<>"
 
 	def __init__ ( self, name, flags ):
@@ -92,7 +92,6 @@ class _MetadataBasicNode ( object ):
 		Does nothing if self._verify is not implemented, else dies on error.
 		"""
 		if hasattr ( self, '_verify' ) and not self._verify():
-			# todo, verify could return ( Status, ErrorMessages ) etc.
 			raise Exception ( "verification failed for a metadata node." )
 	# --- end of _do_verify (...) ---
 
@@ -197,10 +196,14 @@ class MetadataLeaf ( _MetadataBasicNode ):
 		if not self._text_wrapper is None:
 			self._text_wrapper.subsequent_indent = self.text_indent
 
-	def _value_str ( self ):
+	def _default_value_str ( self ):
 		"""Returns the value string. Derived classes may override this."""
 		#if self.value_format == ?: format value ~
-		return str ( self.value )
+		return re.sub (
+			"[" + self.__class__.INVALID_CHARS + "]",
+			'',
+			strutil.ascii_filter ( str ( self.value ) )
+		)
 	# --- end of _value_str (...) ---
 
 	def _pretty_value_str ( self ):
@@ -208,7 +211,6 @@ class MetadataLeaf ( _MetadataBasicNode ):
 		Not used here, but subclasses can use it by simply writing
 		'_value_str = MetadataLeaf._pretty_value_str' in the class body.
 		"""
-		# FIXME/TODO: could move this func to util
 		if not self.value: return ""
 
 		if self._text_wrapper is None:
@@ -218,13 +220,8 @@ class MetadataLeaf ( _MetadataBasicNode ):
 				width=self.linewidth if hasattr ( self, 'linewidth' ) else 50
 			)
 
-		val_lines = self._text_wrapper.wrap (
-			re.sub (
-				"[{}]".format ( self.__class__.INVALID_CHARS ),
-				'',
-				self.value
-			)
-		)
+		val_lines = self._text_wrapper.wrap ( self._default_value_str() )
+
 		if len ( val_lines ) < 1:
 			# why?
 			return ""
@@ -242,10 +239,11 @@ class MetadataLeaf ( _MetadataBasicNode ):
 		self._do_verify()
 		if self.print_node_name:
 			return "{indent}<{name}{flags}>{value}</{name}>".format (
-				indent=self.indent,
-				name=self.name,
-				flags=self._flagstr(),
-				value=self._value_str(),
+				indent = self.indent,
+				name   = self.name,
+				flags  = self._flagstr(),
+				value  = self._value_str() \
+					if hasattr ( self, '_value_str' ) else self._default_value_str()
 			)
 		else:
 			# not very useful, but allows to insert strings as nodes

diff --git a/roverlay/overlay/metadata/nodes.py b/roverlay/overlay/metadata/nodes.py
index 0002267..5f97181 100644
--- a/roverlay/overlay/metadata/nodes.py
+++ b/roverlay/overlay/metadata/nodes.py
@@ -2,7 +2,6 @@
 # Copyright 2006-2012 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
-from roverlay import util
 # import abstract nodes
 from roverlay.overlay.metadata.abstractnodes import \
 	MetadataNode, MetadataNodeNamedAccess, MetadataLeaf
@@ -71,7 +70,7 @@ class MetadataRoot ( MetadataNodeNamedAccess ):
 		if not self.empty():
 			fh.write ( MetadataRoot.HEADER )
 			fh.write ( '\n' )
-			fh.write ( util.ascii_filter ( self.to_str() ) )
+			fh.write ( self.to_str() )
 			fh.write ( '\n' )
 			return True
 		else:

diff --git a/roverlay/overlay/package.py b/roverlay/overlay/package.py
index 434b1b1..722be8b 100644
--- a/roverlay/overlay/package.py
+++ b/roverlay/overlay/package.py
@@ -122,8 +122,6 @@ class PackageDir ( object ):
 		if added:
 			# add a link to this PackageDir into the package info,
 			# !! package_info <-> self (double-linked)
-			# FIXME: remove physical_only flag from PackageInfo if
-			#         overlay_package_ref can be used for that
 			package_info.overlay_package_ref = self
 			return True
 		else:
@@ -267,8 +265,17 @@ class PackageDir ( object ):
 			"Kept {kept}/{total} ebuilds.".format ( kept=kept, total=ecount )
 		)
 
-		# FIXME: Manifest is now invalid and dir could be "empty" (no ebuilds)
-		# FIXME: force metadata regeneration
+		if self._need_metadata:
+			self.generate_metadata ( skip_if_existent=False )
+
+		# Manifest is now invalid,
+		#  need_manifest is set to True in purge_package()
+		#
+		# metadata will be re-written when calling write()
+		#
+		# dir could be "empty" (no ebuilds),
+		#  which is solved when calling fs_cleanup(),
+		#  implicitly called by write()
 	# --- end of keep_nth_latest (...) ---
 
 	def list_versions ( self ):
@@ -296,6 +303,7 @@ class PackageDir ( object ):
 			p = self._packages [pvr]
 			del self._packages [pvr]
 			self._remove_ebuild_file ( p )
+			self._need_metadata = True
 			return p
 		except Exception as e:
 			self.logger.exception ( e )
@@ -450,7 +458,6 @@ class PackageDir ( object ):
 				self.virtual_cleanup()
 				self.fs_cleanup()
 
-			# FIXME / TODO call fs_cleanup
 		# -- lock
 		return success
 	# --- end of write (...) ---
@@ -483,10 +490,6 @@ class PackageDir ( object ):
 				fh.write ( str ( ebuild ) )
 				fh.write ( '\n' )
 
-				# adjust owner/perm? TODO
-				#if shared_fh is None:
-				#	chmod 0644 or 0444
-				#	chown 250.250
 				_success = True
 			except IOError as e:
 				self.logger.exception ( e )
@@ -574,13 +577,6 @@ class PackageDir ( object ):
 		elif ignore_empty:
 			return True
 		else:
-			# FIXME: debug statements
-			# FIXME: remove excpetion, maybe delete Manifest in this case,..
-			for pvr, p in self._packages.items():
-				print ( "{} {} ebuild={} efile={} has={}".format (
-					pvr, p, p.has ('ebuild'), p ['ebuild_file'], self.has_ebuilds()
-				) )
-
 			raise Exception (
 				'In {mydir}: No ebuild written so far! '
 				'I really don\'t know what do to!'.format (

diff --git a/roverlay/overlay/root.py b/roverlay/overlay/root.py
index 3efdf66..5cbcef3 100644
--- a/roverlay/overlay/root.py
+++ b/roverlay/overlay/root.py
@@ -31,7 +31,7 @@ class Overlay ( object ):
 		write_allowed,
 		incremental,
 		skip_manifest,
-		runtime_incremental=True
+		runtime_incremental=False
 	):
 		"""Initializes an overlay.
 
@@ -52,7 +52,7 @@ class Overlay ( object ):
 		                         !!! The created overlay cannot be used with
 		                         emerge/portage
 		* runtime_incremental -- see package.py:PackageDir.__init__ (...),
-		                          Defaults to ?FIXME?
+		                          Defaults to False (saves memory but costs time)
 
 		"""
 		self.name                 = name
@@ -73,7 +73,7 @@ class Overlay ( object ):
 
 		self.skip_manifest        = skip_manifest
 
-		# fixme or ignore: calculating eclass names twice,
+		# calculating eclass names twice,
 		# once here and another time when calling _init_overlay
 		self._header.set_eclasses ( frozenset (
 			self._get_eclass_import_info ( only_eclass_names=True )
@@ -279,7 +279,6 @@ class Overlay ( object ):
 	def scan ( self, **kw ):
 		def scan_categories():
 			for x in os.listdir ( self.physical_location ):
-				# FIXME could use a better check here
 				if '-' in x and self.has_dir ( x ):
 					yield self._get_category ( x )
 		# --- end of scan_categories (...) ---
@@ -322,8 +321,8 @@ class Overlay ( object ):
 
 		raises: IOError
 
-		! TODO/FIXME/DOC: This is not thread-safe, it's expected to be called
-		when ebuild creation is done.
+		Note: This is not thread-safe, it's expected to be called when
+		ebuild creation is done.
 		"""
 		if self._writeable:
 			self._init_overlay ( reimport_eclass=True )
@@ -354,9 +353,15 @@ class Overlay ( object ):
 		returns: None (implicit)
 		"""
 		if self._writeable and not self.skip_manifest:
-			# FIXME: it would be good to ensure that profiles/categories exist
-			for cat in self._categories.values():
-				cat.write_manifest ( **manifest_kw )
+			# profiles/categories is required for successful Manifest
+			# creation
+			if os.path.isfile ( self._profiles_dir + os.sep + 'categories' ):
+				for cat in self._categories.values():
+					cat.write_manifest ( **manifest_kw )
+			else:
+				raise Exception (
+					'profiles/categories is missing - cannot write Manifest files!'
+				)
 		elif not self.skip_manifest:
 			# FIXME debug print
 			print (


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-08-02 15:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-07-31 17:51 [gentoo-commits] proj/R_overlay:master commit in: roverlay/overlay/metadata/, roverlay/overlay/ André Erdmann
  -- strict thread matches above, loose matches on Subject: below --
2012-08-02 15:14 André Erdmann
2012-07-30  8:52 André Erdmann
2012-07-23 16:34 [gentoo-commits] proj/R_overlay:overlay_wip " André Erdmann
2012-07-30  8:52 ` [gentoo-commits] proj/R_overlay:master " André Erdmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox