===NOTE=== This was written _way_ the hell back in the past, it may not map to the current iteration of design/goals. Some goofy/interesting/good ideas in it, good for historical info. Rewrite this once the sucker is actually fleshed out. "In our next episode of hellsing, we finally bring peace and quiet to our fair london town, our final episode... Hellfire! do do doo da... Sweet, baby..." ===Harring was bored, continue about your business=== specification of subsystems/relevant classes. this isn't a concrete "it must be this way", this is a guideline of the various subsystems/import classes, and how they interact. The intention being that you can read this, see the important aspects of portage at a single glass, and be aware of where/which subsystems touch up, and how things fit together sync subsystem/class: #sync'ing method. #potentially limited to a specific tree type. detection/complaints regarding this should be #detected/bailed upon during tree initialization (?) boolean sync() cachedb subsystem/class: #metadata cache. non structure caching, just metadata caching (for instances where it's #ass slow getting the keys, eg bash based formats) #format agnostic, state the keys stored up front at initialization, and that's what stored. #this conflicts with portage_db_flat. course that format sucks, so neh. #note, not necessarily required, and is a property of the defined repository/overlay #additionally, note the cache is a db. it doesn't update itself, it just retrieves/stores #data. functions as a dict. __getitem__ __setitem__ __delitem__ get_matches(SearchRestrictions): #assuming the cache can be stated upto date, or never drifts from the tree #or, just using the cache to handle the bulk of the cpv's. class src_format: #abstract class representing a package to be acted upon. #this is not a cpv, which is just (really) some random string a tree/cache spits #this instance is basically a handler. #note these are high level definitions. individual formats are free to define #what ever phases they want w/in the high level format. get_src_uri #stuff to fetch for this to be used build #high level represenation of building a src based package. #note binpkgs just return merge #actual transferrance/installation to either the livefs to an externally #specified location unmerge #high level representation of any potential commands to execute prior to #removing this format's files. prerm/postrm fex. get_metadata (currently ebuild.py:ebuild_handler.get_keys) #get metadata. *all* available metadata. if the format allows for undefined values, #return None if the metadata is undefined. # #formerly ebuild.py:ebuild_handler.get_keys class Package: # this is an atomic package returned from a repository. JIT binding of metadata attributes, category/package/name/version # are attributes additionally presuming the underlying format supports it unique_id # each derivative *must* define a unique_id that represents that versioned pkg; this is used for caching of instances. pkg_id # each derivative *must* define a pkg_id representing the category/package, non versioned (if the repository supports # multiple package/versions/slots- dpkg, fex would define package-version as the key, due to their namespace # layout) # key must be an immutable instance, due to potential for hashing. version_cmp(other-instance) # each derivative *must* define this; it's for comparing instances when the key is the same (cpv is the same). # used by the depresolver to determine the 'highest' version package instance. # for dpkg (again, fex), version_cmp would be basically a key compare. # for ebuilds, it would compare slot, then version # returns either -1, 0, or 1 to indicate if the instance (instance.version_cmp) is lt/eq/gt the passed in version get_handler # this should be bound to the src repository, via that the src_format- the instance should be able to return # an instance of the src_format handler class, for doing building/installing/etc data #attribute, functions as a dict. don't care how it's implemented, whether via descriptors (going that route for JIT), #or a customized dict derivative. #fex, for ebuildPackageInstance, holds (currently) #category, package, version, SLOT, DESCRIPTION, DEPENDS, RDEPENDS, CDEPENDS, PDEPENDS, SRC_URI, KEYWORDS, RESTRICT, #HOMEPAGE, etc. auxdbkeys. #attributes *should* be access via lowercase. # #This is debatable. #mostly I just hate the uppercase for auxdbkeys. _get_metadata # access the handed in repository, and get metadata # immediate derivatives class ebuildPackageInstance(Package): this is a common derivative of PackageInstance that holds the key attribute setting, and version_cmp logic. get_handler being defined here, or required handled in derivates will be defined at the time of implementation the crystal ball is sometimes a bit foggy, additionally genbot's 8ball functionally seems not too random :/ class indexable sequence: #stating it here either can iterate over it ala list, or access it via a hashable object example, using catpkg as key, and versions values for x in instance: == cpv instance[catpkg] == versions of that cp class protoTree #base tree class. repository configuration file/specification is used in constructing this instance, #namely specification of cacheing backend (if any), and sync'ing method (if any) #cache isn't directly used by this class, although the update_cache method is a maintenance method #for syncing the cache up with the tree (just as the sync function is used to sync the local tree #to a remote tree) #note, not all repositories may have categories, or versions persay. #flat namespaces of packages fex, won't. Probably need a special case then # # yes, special cases suck, but what other approach is there? # we *have* to have a way for external code to inspect/walk the repository... custom attributes # for walking the repository will only make things messier (inspect the instance to figure out how to inspect the instance? # no thank you :) categories = indexable sequence. for x in categories == walk all categories. categories[cat] == get subcategory packages = indexable sequence. for x in packages == all cp. packages[category] == all packages in category versions = indexable sequence. for x in versions == all cpv. versions[cp] == cat/packages versions search(RestrictionSet) = handed a RestrictionSet, returns PackageInstances that match the passed in Restrictions sync = sync this tree. the actual sync method is defined by the repository configuration, and is a sync class instance. update_cache = cache update method, for walking the tree and cleansing/updating the cache. if the repository config states update the cache on sync, this is called. seperated due to the fact that the cache backend is variable, may not even be used (eg no cache). #additionally, the instance itself functions as a indexable sequence for getting *all* packageInstances in this repository. #so... you can either do for x in instance == get *package-cpv* of all cpv, or instance[cpv] to get a specific package-cpv class gentoo_ebuild_repository # this is a derivative of protoTree that has the usual repository characteristics- categories, versions, packages, etc. __get_categories(self, *optional_base_category) = derivatives overload this to return categories, or if an optional positional arg is specified, the sub-categories- non recursive. returns a tuple of str __get_versions(str package) = derivatives overload this to return versions available for a package returns a tuple of str __get_packages(str category) = derivatives overload this to return packages avaiable for a category returns a tuple of str # note our current bintree, and ebuild tree should derive from this. # this is just an intermediate derivative holding common code. # remote binhost fex, would maintain a similar attribute layout, but wouldn't derive from this. # why? cause it's method of access is *far* different from the common approach, despite maintaining similar # notions of category/package/versions search subsystem/classes: # These are just the building blocks of other restrictions. class StrRestriction(object): # these aren't really Restrictions persay; they're the building blocks of actual Restrictions. match(str or instance that can be coerced to a str) class StrExactRestriction(StrRestriction): __init__(value, CaseSensitive=True) # class for seeing if two strings *are the exact same*, after accounting for case sensitivity. match(str or instance that can be coerced to a str) class StrSubStringRestriction(StrRestriction): __init__(value, CaseSensitive=True) # class representing matching a substring in the handed in value. match(str or instance that can be coerced to a str) class StrRegexRestriction(StrRestriction): __init__(regex, CaseSensitive=True): # take a guess. match(str or instance that can be coerced to a str) class BaseRestriction(object): # all derivatives *should* be __slots__ based to decrease mem overhead (potentially creating a lot of these # suckers) unless otherwise warranted. # it's minor, but most restrictions are write once- using a new style class w/ __slots__ makes the write once/ # error second write behaviour easily doable, and generalized in this base restriction. pmatch(PackageInstance) # general, high level non optimized match. # requires a package instance, derivatives will look in PackageInstance.data to do their matching. class AtomicRestriction(BaseRestriction): # has the usual pmatch method, plus a direct access method match(value) # direct access matching. This should hold the actual implementation of the matching check. # pmatch should just contain the code for getting at the actual value. # this method exists to allow for code that deals w/ restrictions, to directly hand values to the check # # **NOTE** RestrictionSets lack this method. This method *should* be defined only for atomic Restrictions, # eg, individual checks. # the first real, package specific restriction. class PackageDataRestriction(AtomicRestriction): __init__(data_name, StrRestriction instance) # data_name can be anything technically. # typically either category, package, version, or one of the auxdbkeys. # an initialized StrRestriction derivative is passed in, and used for matching. match(value): # again, the direct access method. all matching code should be here. pmatch(PackageInstance): # the non-specific route. handed a PackageInstance. class VersionRestriction(PackageDataRestriction): # implements version specific restriction rules class RestrictionSet(BaseRestriction): # abstraction over a set of individual restrictions. # builds a list of derivatives of Restriction class- note I said *derivatives* # RestrictionSet is a derivative of Restriction. # In other words, you can nest these buggers. __init__(*initialRestrictions) #initialRestrictions is optional. basically, all args are grouped into a list, and used as the initial #list of Restrictions (non-finalized) #basically is the equiv of getting the instance, then calling .addRestriction repeatedly #must be a list. a RestrictionSet is a Restriction derivative, so it would be added as is. addRestriction(self, Restriction-Instance): #append the passed in restriction to the current chain of restrictions. finalize(self): # optimize this chain (if viable/possible). # mostly just convert it from a list to a tuple, and do it recursively # across all held RestrictionSets in this instance. pmatch(self, PackageInstance): # run through the checks, returning true/false indicating if this set of restrictions matches, or doesn't. class AndRestrictionSet(RestrictionSet): # run through the list of restrictions, and'ing their returns together. class OrRestrictionSet(RestrictionSet): # run through the list of restrictions, or'ing their returns toegether. class PackageRestriction(AndRestrictionSet): # this is basically an atom. # for >=dev-util/diffball-0.6_pre4, holds # (PackageDataRestriction('category',StrExactRestriction('dev-util')), # PackageDataRestriction('name',StrExactRestriction('diffball')), # PackageDataRestriction('version',StrExactRestriction('dev-util'))) # # basically just a simple, mostly non modifying AndRestrictionSet. It is a special class # such that it can be easily identified by code via isintance checks, and will serve as the base # for potentially deriving a custom (per format) variation, that has an optimized version of .finalize class ConfigRestriction: # restrictions that apply to the systems configuration. eg, a package being built with a certain use flag enabled. class depresolver: #pluggable.