public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/
@ 2014-07-17 20:12 André Erdmann
  2014-07-18 16:20 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
  0 siblings, 1 reply; 7+ messages in thread
From: André Erdmann @ 2014-07-17 20:12 UTC (permalink / raw
  To: gentoo-commits

commit:     3a7fd984632e964003802b81456eb51ecbb97b10
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Thu Jul 17 16:38:09 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Thu Jul 17 16:38:09 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=3a7fd984

remove SillyAdditionControlPackageRuleGenerator

replaced by AdditionControlPackageRuleGenerator

---
 .../packagerules/generators/addition_control.py    | 27 +---------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index 7f2cc95..0021817 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -333,37 +333,12 @@ class AdditionControlPackageRuleGenerator (
             return combined_acceptor
    # --- end of package_token_to_acceptor (...) ---
 
-
-class SillyAdditionControlPackageRuleGenerator (
-   roverlay.packagerules.generators.abstract.addition_control.\
-      AbstractAdditionControlPackageRuleGenerator
-):
-   """
-   An add-policy package rule generator that doesn't care about its tokens.
-
-   Not useful for productive usage - will be removed as soon as a proper
-   rule generator has been implemented.
-   """
-
-   def __init__ ( self ):
-      super ( SillyAdditionControlPackageRuleGenerator, self ).__init__()
-      self.namespace = roverlay.util.namespace.SimpleNamespace()
-
-   def _get_true_acceptor_from_namespace ( self, any_token, priority ):
-      return self.namespace.get_object_v (
-         roverlay.packagerules.acceptors.trivial.TrueAcceptor,
-         ( priority, ),
-         {}
-      )
-
-   category_token_to_acceptor = _get_true_acceptor_from_namespace
-   package_token_to_acceptor  = _get_true_acceptor_from_namespace
+# --- end of AdditionControlPackageRuleGenerator ---
 
 
 
 
 def temporary_demo_func():
-   #rule_generator             = SillyAdditionControlPackageRuleGenerator()
    ARES                       = AdditionControlResult
    rule_generator             = AdditionControlPackageRuleGenerator("sci-R")
    CTOKEN                     = rule_generator.create_category_token


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

* [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/
@ 2014-07-17 20:12 André Erdmann
  0 siblings, 0 replies; 7+ messages in thread
From: André Erdmann @ 2014-07-17 20:12 UTC (permalink / raw
  To: gentoo-commits

commit:     862594b151befc3ac3e1766df370890c8af88470
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Thu Jul 17 16:26:32 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Thu Jul 17 16:26:32 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=862594b1

add-policy rule-gen: implement token generatorion

---
 .../packagerules/generators/addition_control.py    | 883 +++++++--------------
 1 file changed, 279 insertions(+), 604 deletions(-)

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index 73040e0..7f2cc95 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -1,684 +1,342 @@
-# R overlay -- package rule generators, addition control
+# R overlay -- abstract package rule generators, addition control
 # -*- coding: utf-8 -*-
 # Copyright (C) 2014 André Erdmann <dywi@mailerd.de>
 # Distributed under the terms of the GNU General Public License;
 # either version 2 of the License, or (at your option) any later version.
 
 from __future__ import absolute_import
-# temporary_demo_func():
-from __future__ import print_function
 
 
 import abc
-# __metaclass__/metaclass= workaround
-_AbstractObject = abc.ABCMeta ( str("AbstractObject"), ( object, ), {} )
-
 import collections
+import fnmatch
+import re
+
+
+import roverlay.packagerules.generators.abstract.addition_control
 
-#~ import roverlay.util.fileio
-import roverlay.util.namespace
-#~
 import roverlay.packagerules.abstract.acceptors
-import roverlay.packagerules.abstract.rules
-#~ import roverlay.packagerules.acceptors.stringmatch
-#~ import roverlay.packagerules.acceptors.util
-import roverlay.packagerules.acceptors.trivial
-import roverlay.packagerules.actions.addition_control
-#~
-#~ from roverlay.packagerules.abstract.rules import (
-   #~ NestedPackageRule, PackageRule
-#~ )
-#~
-#~ from roverlay.packagerules.acceptors.stringmatch (
-   #~ NocaseStringAcceptor, StringAcceptor,
-   #~ RegexAcceptor, ExactRegexAcceptor
-#~ )
-#~
-#~ from roverlay.packagerules.acceptors.util import (
-   #~ get_package, get_package_name, get_ebuild_name, get_category,
-   #~ DEFAULT_CATEGORY_REPLACEMENT
-#~ )
-
-import roverlay.overlay.abccontrol
-from roverlay.overlay.abccontrol import AdditionControlResult
-
-
-# converting addition-control lists (cmdline, from file...) to rule objects,
-# hacky solution:
-#
-# ** step 1 ** -- collect category/package tokens, determine bitmask
-#
-#  create a dict (
-#     category_token|True => package_token|True => bitmask<policy>
-#     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^    ^~~~~~~~~~~~~~^
-#               "acceptor chain"                    "add-policy"
-#  )
-#
-#   "True" means "accept all".
-#
-#   make sure that the tokens get de-duped
-#    (normalize values, use tuples (or namespace))
-#
-#   Only the first and the last step need to know *what* category/package
-#   tokens are. All intermediate steps should not need to care about this.
-#
-
-
-
-class AbstractAdditionControlPackageRuleGenerator ( _AbstractObject ):
-   """(Abstract) object that takes cmdline/files as input and creates
-   add-policy package rules."""
-
-   # Note that tokens are not totally abstract,
-   #  the "match-all" (True) token is hardcoded
-
-   #CategoryToken = collections.namedtuple ( 'CategoryToken', '<attr>*' )
-   #PackageToken  = collections.namedtuple ( 'PackageToken',  '<attr>*' )
-
-   @abc.abstractmethod
-   def category_token_to_acceptor ( self, category_token, priority ):
-      """Creates a package rule acceptor for the given category token.
+import roverlay.packagerules.acceptors.stringmatch
+import roverlay.packagerules.acceptors.util
 
-      Returns: not-None acceptor (or nested acceptor)
 
-      Must not return None.
-      If a token is meaningless, then don't create it in the first place.
+from roverlay.packagerules.abstract.acceptors import Acceptor_AND
 
-      arguments:
-      * category_token -- a category token
-      * priority       -- priority of the acceptor (int)
-      """
-      raise NotImplementedError()
-   # --- end of category_token_to_acceptor (...) ---
+from roverlay.packagerules.acceptors.stringmatch import (
+   StringAcceptor, ExactRegexAcceptor,
+)
 
-   @abc.abstractmethod
-   def package_token_to_acceptor ( self, package_token, priority ):
-      """Creates a package rule acceptor for the given package token.
+from roverlay.packagerules.acceptors.util import (
+   get_category, get_ebuild_name, get_ebuild_version_tuple,
+)
 
-      Returns: not-None acceptor (or nested acceptor)
+#import roverlay.util.fileio
+import roverlay.util.namespace
 
-      arguments:
-      * package_token -- a package token
-      * priority      -- priority of the acceptor (int)
-      """
-      raise NotImplementedError()
-   # --- end of package_token_to_acceptor (...) ---
+import roverlay.util.portage_regex.default
+import roverlay.util.portage_regex.wildcard
+from roverlay.util.portage_regex.default  import RE_PACKAGE_EBUILD_FILE
+from roverlay.util.portage_regex.wildcard import (
+   RE_WILDCARD_PACKAGE, RE_WILDCARD_CATEGORY
+)
 
-   def create_package_rules ( self, reduced_bitmask_acceptor_chain_map ):
-      """Creates a nested add-policy package rule object.
-      The rule object's priority has to be set manually afterwards.
-
-      Returns: (nested) package rule or None
-      """
-      # create_package_rules() is defined/implemented below (step 5)
-      return create_package_rules (
-         reduced_bitmask_acceptor_chain_map,
-         convert_category_token_to_acceptor = self.category_token_to_acceptor,
-         convert_package_token_to_acceptor  = self.package_token_to_acceptor
-      )
-   # --- end of create_package_rules (...) ---
 
-   def prepare_bitmask_map ( self, acceptor_chain_bitmask_map ):
-      """Transforms the given "acceptor chain" -> "bitmask" map into the
-      reduced "effective bitmask" -> "acceptor chain" map.
 
-      Note: Involves in-place operations that modify
-            acceptor_chain_bitmask_map.
-            Pass a copy if the original map should remain unchanged.
 
-      Returns: reduced/optimized "effective bitmask" -> "acceptor chain"
 
-      arguments:
-      * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map
-      """
-      expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map )
 
-      bitmask_acceptor_chain_map = (
-         create_bitmask_acceptor_chain_map ( acceptor_chain_bitmask_map )
-      )
 
-      reduce_bitmask_acceptor_chain_map ( bitmask_acceptor_chain_map )
 
-      return bitmask_acceptor_chain_map
-   # --- end of prepare_bitmask_map (...) ---
 
-   def compile_bitmask_map ( self, acceptor_chain_bitmask_map ):
-      """Transforms the given "acceptor chain" -> "bitmask" map into a
-      (nested) package rule.
 
-      This is equal to calling
-         obj.create_package_rules (
-            obj.prepare_bitmask_map ( acceptor_chain_bitmask_map )
-         )
+class TokenValueError ( ValueError ):
+   pass
 
-      Returns: (nested) rule object or None
+class InvalidTokenInputString ( TokenValueError ):
+   pass
 
-      arguments:
-      * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map
-      """
-      return self.create_package_rules (
-         prepare_bitmask_map ( acceptor_chain_bitmask_map )
-      )
-   # --- end of compile_bitmask_map (...) ---
-
-
-# --- end of AbstractAdditionControlPackageRuleGenerator ---
-
-
-#
-# ** step 2 ** -- expand global and category-wide bitmasks,
-#                 set effective package bitmask
-#                 (FIXME: does it make sense to apply the global bitmask?)
-#
-#  for each category with at least one non-True package_token loop
-#    for each package in category loop
-#       category->package |= category->True  [bitwise-OR]
-#    end loop
-#    (do not modify category->True, as it applies to packages not matched
-#     by any package_token, too)
-#  end loop
-#
-#  for each category loop
-#     for each entry in category loop
-#        reduce policy bitmask (keep effective bits only)
-#     end loop
-#  end loop
-#
-#  (merge the two for-loops in code)
-#
-
-def expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map ):
-   """Expands a "acceptor chain" -> "bitmask" map.
-   (Sets the effective bitmask, propagates global bitmasks, ...)
-
-   In-place operation that modifies the acceptor_chain_bitmask_map arg.
-
-   Returns: None (implicit)
-
-   arguments:
-   * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map
-   """
-   # naming convention: >e<ffective bit>mask< => emask
-
-   get_emask = AdditionControlResult.get_effective_package_policy
-
-   def normalize_entry ( mapping, key, additional_emask=0 ):
-      """Determines and sets the effective bitmask of mapping->key.
-
-      Returns: None (implicit)
-
-      arguments:
-      * mapping          -- dict-like object
-      * key              -- dict key (has to exist)
-      * additional_emask -- effective bitmask that should be propagated to
-                            mapping->key (global/category-wide bitmask)
-      """
-      new_value     = get_emask ( mapping [key] | additional_emask )
-      mapping [key] = new_value
-      return new_value
-   # --- end of normalize_entry (...) ---
-
-   def normalize_entry_maybe_missing ( mapping, key, additional_emask=0 ):
-      """Like normalize_entry(), but does not require the existence of
-      mapping->key (the entry will be created if necessary).
-
-      arguments:
-      * mapping          --
-      * key              --
-      * additional_emask --
-      """
-      if key in mapping:
-         return normalize_entry ( mapping, key, additional_emask )
-      else:
-         mapping [key] = additional_emask
-         return additional_emask
-   # --- end of normalize_entry_maybe_missing (...) ---
+class TokenItemNotSupported ( TokenValueError ):
+   pass
 
-   # propagate global/category-wide emask to package_token entries
 
-   # acceptor_chain_bitmask_map->True->True is the global emask
-   if True in acceptor_chain_bitmask_map:
-      global_emask = normalize_entry_maybe_missing (
-         acceptor_chain_bitmask_map [True], True
-      )
-   else:
-      global_emask = 0
 
 
-   for category_token, package_token_map in acceptor_chain_bitmask_map.items():
-      # --- cannot modify acceptor_chain_bitmask_map in this block
 
-      category_emask = normalize_entry_maybe_missing (
-         package_token_map, True, global_emask
-      )
+class AdditionControlPackageRuleGenerator (
+   roverlay.packagerules.generators.abstract.addition_control.\
+      AbstractAdditionControlPackageRuleGenerator
+):
 
-      for package_token in package_token_map:
-         # --- cannot modify acceptor_chain_bitmask_map, package_token_map
-         if package_token is not True:
-            # else already processed (category_emask)
-            normalize_entry (
-               package_token_map, package_token, category_emask
-            )
-         # -- end if <package_token>
-      # -- end for <package_token>
-
-   # -- end for <category_token,package_token_map>
-
-# --- end of expand_acceptor_chain_bitmasks (...) ---
-
-
-#
-# ** step 3 -- create reversed map **
-#
-#  BITMASK_MAP: create a dict (
-#     effective_bitmask => category_token|True => set(package_token|True>)
-#     ^~~~~~~~~~~~~~~~^    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
-#     "add-policy atom"                 "acceptor chain"
-#  )
-#
-#
-#  **hacky**:
-#   It would be better to split effective_bitmask into its components
-#   (2**k for k in ...), but this requires path compaction.
-#   Not implemented. (graph/spanning-tree and/or logic minimization)
-#
-
-def create_bitmask_acceptor_chain_map ( acceptor_chain_bitmask_map ):
-   """Transforms a "acceptor chain" -> "[effective] bitmask" map
-   into a "[effective] bitmask" -> "acceptor chain" mask without applying
-   any optimization/reduction steps.
-
-   Returns: "[effective] bitmask" -> "acceptor chain" map
-
-   arguments:
-   * acceptor_chain_bitmask_map -- "acceptor chain" -> "bitmask" map
-                                   Should be in expanded form
-                                   (expand_acceptor_chain_bitmasks())
-   """
-   bitmask_acceptor_chain_map = {}
+   #TOKEN_ITEM_IS_SPECIAL = 0 ## implicit
+   TOKEN_ITEM_IS_STR      = 1
+   TOKEN_ITEM_IS_REGEX    = 2
 
-   for category_token, package_token_map in acceptor_chain_bitmask_map.items():
+   TokenItemTuple = collections.namedtuple (
+      "TokenItemTuple", "item_type value"
+   )
 
-      for package_token, emask in package_token_map.items():
-         try:
-            emask_entry = bitmask_acceptor_chain_map [emask]
-         except KeyError:
-            bitmask_acceptor_chain_map [emask] = {
-               category_token: set ({ package_token, })
-            }
-         else:
-            try:
-               category_entry = emask_entry [category_token]
-            except KeyError:
-               emask_entry [category_token] = set ({ package_token, })
-            else:
-               category_entry.add ( package_token )
-      # -- end for <package token map>
-
-   # -- end for <category token map>
-
-   return bitmask_acceptor_chain_map
-# --- end of create_bitmask_acceptor_chain_map (...) ---
-
-
-#
-# ** step 4 -- naive path compaction **
-#   (Keep in mind that acceptor tokens cannot be merged with match-all)
-#
-#   reduce acceptor chains (drop-superseeded):
-#   for each effective_bitmask b in BITMASK_MAP loop
-#      if BITMASK_MAP->b->True->True exists then
-#         drop all other entries from BITMASK_MAP->b
-#      else
-#         for each category in BITMASK_MAP->b loop
-#            if category->True exists then
-#               drop all other entries from category
-#            end if
-#         end loop
-#      end if
-#   end loop
-#
-#   (optional: drop overlapping acceptor chains, e.g. regex ".*" is equal
-#    to True and therefore all other entries in the regex' branch can be
-#    removed)
-#
-#
-#   merge-bitmask: (OPTIONAL / NOT IMPLEMENTED)
-#    (bitwise-OR effective_bitmasks with identical acceptor chains)
-#
-#    *could* create a large table
-#      <add-policy atom X category/package> => bool
-#       (where category, package can also be "accept-all")
-#
-#
-#    +-----------------+-------+-------+-----+-------+-------+-----+-------+
-#    | add-policy atom | c0/p0 | c0/p1 | ... | c0/pM | c1/p0 | ... | cN/pJ |
-#    +=================+=======+=======+=====+=======+=======+=====+=======+
-#    | 2**0            | 0|1   | 0|1   | ... | 0|1   | 0|1   | ... | 0|1   |
-#    +-----------------+-------+-------+-----+-------+-------+-----+-------+
-#    | ...             | ...   | ...   | ... | ...   | ...   | ... | ...   |
-#    +-----------------+-------+-------+-----+-------+-------+-----+-------+
-#    | 2**k            | 0|1   | 0|1   | ... | 0|1   | 0|1   | ... | 0|1   |
-#    +-----------------+-------+-------+-----+-------+-------+-----+-------+
-#
-#   ++ reduce table
-#
-
-def reduce_bitmask_acceptor_chain_map ( bitmask_acceptor_chain_map ):
-   """Reduces/Optimizes a "effective bitmask" -> "acceptor chain" map.
-
-   In-place operation, the bitmask_acceptor_chain_map will be modified.
-
-   Returns: None (implicit)
-
-   arguments:
-   * bitmask_acceptor_chain_map -- "effective bitmask" -> "acceptor chain" map
-
-   Implementation detail:
-   The reduced map uses empty sets/dicts for representing "match-all"
-   acceptors.
-   """
+   # PackageToken: tuple ( None|$PN, None|$PV, None|$PR )
+   #  (revision not implemented because it cannot be matched in package rules
+   #   -- always 0)
+   #  condition: not all ( item is None for item in <PackageToken> )
+   #              and all not-None items must evaluate to True
+   #             <=> any ( <PackageToken> )
+   #
+   PackageToken  = collections.namedtuple ( 'PackageToken', 'name version' )
 
-   # could be integrated in create_bitmask_acceptor_chain_map(),
-   #  but kept separate for better readability
+   # CategoryToken: tuple ( $CATEGORY )
+   #  same conditions as for PackageToken apply,
+   #   which effectively means that $CATEGORY must a non-empty str
    #
+   CategoryToken = collections.namedtuple ( 'CategoryToken', 'name' )
 
-   # emask==0 can be ignored
-   bitmask_acceptor_chain_map.pop ( 0, True )
-
-   for emask in bitmask_acceptor_chain_map:
-      emask_matches_all = False
-
-      for category_token, package_token_set in (
-         bitmask_acceptor_chain_map [emask].items()
-      ):
-         if True not in package_token_set:
-            # category~DONT_CARE, package!=True <=> keep entries
-            pass
-         elif category_token is True:
-            # category==True, package==True <=> match all, *** BREAK LOOP ***
-            emask_matches_all = True
-            break
-         else:
-            # category!=True, package==True <=> match entire category
-            package_token_set.clear()
-      # -- end for <category->package token map>
-
-      if emask_matches_all:
-         bitmask_acceptor_chain_map [emask].clear()
-   # -- end for <emask>
-# --- end of reduce_bitmask_acceptor_chain_map (...) ---
-
-
-#
-# ** step 5 -- convert the acceptor chains to objects **
-#
-#   the final BITMASK_MAP can be easily translated into rule objects:
-#
-#   * convert the the effective bitmask into one or more
-#      PackageAdditionControl*Actions
-#
-#   * an OR<category OR<packages>> match statement
-#      represents the acceptor chain
-#      (reduce properly, e.g. "accept-all" entries)
-#
-#
-# ** done **
-#
-
-def create_packagerule_action_map():
-   """Helper function that creates all add-policy package rule actions.
-
-   Returns: dict ( "bitmask atom" (2**k) -> "package rule action" )
-
-   arguments: None
-   """
-   return {
-      action_cls.CONTROL_RESULT: action_cls (
-         priority=action_cls.CONTROL_RESULT
-      )
-         for action_cls in (
-            getattr (
-               roverlay.packagerules.actions.addition_control,
-               action_cls_name
-            ) for action_cls_name in (
-               roverlay.packagerules.actions.addition_control.ACTIONS
-            )
-         ) if action_cls.CONTROL_RESULT
-   }
-# --- end of create_packagerule_action_map (...) ---
 
+   def create_token_item_from_str ( self, s ):
+      get_obj = self.namespace.get_object_v
 
-def create_package_rules (
-   reduced_bitmask_acceptor_chain_map,
-   convert_category_token_to_acceptor,
-   convert_package_token_to_acceptor
-):
-   """Converts the given "effective bitmask" -> "acceptor chain" map
-   into a nested package rule.
-
-   Returns: (nested) package rule or None
-
-   arguments:
-   * reduced_bitmask_acceptor_chain_map -- reduced/optimized
-                                           "bitmask" -> "acceptor chain" map
-   * convert_category_token_to_acceptor -- function(token,priority)
-                                             -> category acceptor
-   * convert_package_token_to_acceptor  -- function(token,priority)
-                                             -> package acceptor
-   """
-   packagerule_actions    = create_packagerule_action_map()
-   # true acceptor with priority -1
-   always_true_acceptor   = (
-      roverlay.packagerules.acceptors.trivial.TrueAcceptor ( priority=-1 )
-   )
+      if not s:
+         return None
 
+      elif any ( char in "?*" for char in s ):
+         s_stripped = s.strip("*")
+         if not s_stripped or (
+            s_stripped == "?" and s_stripped != s
+         ):
+            # "****", "?*", "*?", ... => match all
+            return True
 
-   def get_acceptor_recursive ( category_token_map, priority ):
-      """
-      Creates a (possibly nested) acceptor for the given category_token_map.
-
-      Returns: not-None acceptor
-
-      arguments:
-      * category_token_map -- "category token" -> "package token" map
-                               ("acceptor chain")
-      * priority           -- "recommended" priority of the acceptor
-                               Ignored when returning an always-true acceptor.
-      """
-
-      # Note: it's illegal to set an acceptor's priority after its creation
-      #       this would violate namespace->get_object()
-      #        ==> use 0 as priority for objects where it doesn't matter much
-      #             (at the cost of unstable-sorted output)
-      #
-      #        The acceptor gets wrapped with an Acceptor_AND object anyway(*),
-      #        no need to set any priority.
-      #        (*) "the top-level logic of a MATCH-block is AND by convention"
-      #            the acceptor returned by get_*acceptor*() can be of *any*
-      #            type, but its str representation (--print-package-rules)
-      #            would always be the same.
-      #
-      #        ["proper" prio-setting is already implemented at
-      #         package/category acceptor level, so the outmost AND acceptor
-      #         has exactly one member and the member's priority matches
-      #         the acceptor's]
-      #
-
-      def get_package_acceptor ( package_tokens, prio ):
-         """Creates a (nested) acceptor for the given non-empty iterable
-         of package tokens.
-
-         Returns: not-None acceptor
-
-         arguments:
-         * package_tokens -- iterable of package tokens (not empty)
-         * prio           -- advised priority of the top-most acceptor
-                              (the object being returned)
-         """
-         if not package_tokens:
-            raise ValueError ( "package token set must not be empty!" )
-
-         elif len(package_tokens) == 1:
-            # special case: bind prio to package_acceptor
-            return convert_package_token_to_acceptor (
-               next(iter(package_tokens)), prio
+         else:
+            return get_obj (
+               self.__class__.TokenItemTuple,
+               (
+                  self.__class__.TOKEN_ITEM_IS_REGEX,
+                  get_obj ( fnmatch.translate, ( s, ) )
+               )
             )
 
-         else:
-            package_acceptors = [
-               convert_package_token_to_acceptor ( package_token, 0 )
-                  for package_token in package_tokens
-            ]
+      else:
+         return get_obj (
+            self.__class__.TokenItemTuple,
+            ( self.__class__.TOKEN_ITEM_IS_STR, s )
+         )
+   # --- end of create_token_item_from_str (...) ---
+
+   def validate_token ( self, package_token ):
+      all_none       = True
+      any_nonspecial = False
+
+      for item in package_token:
+         if item:
+            all_none = False
+            if item is not True:
+               any_nonspecial = True
+      # -- end for
+
+      if all_none:
+         assert not any_nonspecial
+         return None
+      elif any_nonspecial:
+         return package_token
+      else:
+         # FIXME: remove assert
+         assert all ( item in ( True, None ) for item in package_token ), package_token
+         return True
+   # --- end of validate_token (...) ---
+
+   def _create_package_token ( self, name_str, version_str, revision_str ):
+      if revision_str:
+         raise TokenItemNotSupported (
+            "revision {!s}".format ( revision_str )
+         )
 
-            # package acceptors get ORed, no need to set a specific priority
-            combined_acceptor = (
-               roverlay.packagerules.abstract.acceptors.Acceptor_OR ( prio )
-            )
+      package_token = self.namespace.get_object_v (
+         self.__class__.PackageToken,
+         (
+            self.create_token_item_from_str ( name_str ),
+            self.create_token_item_from_str ( version_str ),
+##          self.create_token_item_from_str ( revision_str ),
+         )
+      )
 
-            for package_acceptor in package_acceptors:
-               combined_acceptor.add_acceptor ( package_acceptor )
+      return self.validate_token ( package_token )
+   # --- end of _create_package_token (...) ---
 
-            return combined_acceptor
+   def _create_category_token ( self, category_str ):
+      category_token = self.namespace.get_object_v (
+         self.__class__.CategoryToken,
+         (
+            self.create_token_item_from_str ( category_str ),
+         )
+      )
 
-      # --- end of get_package_acceptor (...) ---
+      return self.validate_token ( category_token )
+   # --- end of _create_category_token (...) ---
+
+   def create_category_token ( self, input_str ):
+      # input_str doesn't need much parsing,
+      #  not using RE_WILDCARD_CATEGORY for now
+##      re_match = RE_WILDCARD_CATEGORY.match ( input_str )
+##      if not re_match:
+##         raise InvalidTokenInputString ( input_str )
+##
+##      match_vars = re_match.groupdict()
+##
+##      if not match_vars ['CATEGORY']:
+##         raise InvalidTokenInputString ( input_str )
+
+      if not input_str:
+         raise InvalidTokenInputString ( input_str )
+      else:
+         return self._create_category_token ( input_str )
+   # --- end of create_category_token (...) ---
 
-      def get_category_acceptor ( category_token, package_tokens, prio ):
-         """Creates a nested acceptor for the given category token and its
-         package tokens.
 
-         Returns: not-None acceptor
+   def create_token (
+      self, input_str, with_category=True, package_regex=RE_WILDCARD_PACKAGE
+   ):
+      re_match = package_regex.match ( input_str )
 
-         arguments:
-         * category_token -- category token (True or non-empty)
-         * package_tokens -- iterable of package tokens (can be empty)
-         """
+      if not re_match:
+         raise InvalidTokenInputString (
+            "{!s}: not matched by regex".format ( input_str )
+         )
 
-         if category_token is True:
-            return get_package_acceptor ( package_tokens, prio )
+      match_vars = re_match.groupdict()
 
-         elif package_tokens:
-            acceptor = (
-               roverlay.packagerules.abstract.acceptors.Acceptor_AND ( prio )
-            )
 
-            # match category first and then packages
-            acceptor.add_acceptor (
-               convert_category_token_to_acceptor ( category_token, 0 )
-            )
-            acceptor.add_acceptor (
-               get_package_acceptor ( package_tokens, 1 )
-            )
+      package_token = self._create_package_token (
+         match_vars ['PN'], match_vars ['PV'], match_vars ['revision']
+      )
 
-            return acceptor
+      if not package_token:
+         raise InvalidTokenInputString ( input_str )
 
-         else:
-            return convert_category_token_to_acceptor ( category_token, prio )
-      # --- end of get_category_acceptor (...) ---
-
-      if not category_token_map:
-         # match-all
-         return always_true_acceptor
-
-      elif len(category_token_map) == 1:
-         # special case: bind priority to entry
-         category_acceptor = None
-         for category_token, package_tokens in category_token_map.items():
-            if category_acceptor is None:
-               category_acceptor = get_category_acceptor (
-                  category_token, package_tokens, priority
-               )
-            else:
-               raise AssertionError ( "must not loop more than once." )
-         # -- end for
 
-         return category_acceptor
+      if with_category:
+         category_token = self._create_category_token (
+            match_vars ['CATEGORY']
+         )
 
-      else:
-         acceptors = [
-            get_category_acceptor ( category_token, package_tokens, k )
-               for ( k, ( category_token, package_tokens ) ) in enumerate (
-                  category_token_map.items()
+         if not category_token:
+            if match_vars ['CATEGORY']:
+               raise InvalidTokenInputString (
+                  "{!s}: invalid category str {!s}".format (
+                     input_str, match_vars ['CATEGORY']
+                  )
                )
-         ]
+            # --
 
-         combined_acceptor = (
-            roverlay.packagerules.abstract.acceptors.Acceptor_OR ( priority )
+            # => match-all
+            category_token = True
+         # -- end if
+
+         return ( category_token, package_token )
+
+      elif match_vars ['CATEGORY']:
+         raise InvalidTokenInputString (
+            "{!s}: must not contain CATEGORY".format ( input_str )
          )
+      else:
+         return package_token
+   # --- end of create_token (...) ---
 
-         for acceptor in acceptors:
-            combined_acceptor.add_acceptor ( acceptor )
+   def create_token_for_ebuild_filepath ( self, efile ):
+      return self.create_token (
+         efile, with_category=True, package_regex=RE_PACKAGE_EBUILD_FILE
+      )
+   # --- end of create_token_for_ebuild_filepath (...) ---
 
-         return combined_acceptor
+   def create_package_token ( self, input_str ):
+      return self.create_token ( input_str, with_category=False )
+   # --- end of create_package_token (...) ---
 
-   # --- end of get_acceptor_recursive (...) ---
 
-   def create_rule ( category_token_map, emask ):
-      """Creates a package rule for the given acceptor chain
-      ("category token" -> "package tokens" map)
+   def __init__ ( self, default_category ):
+      super ( AdditionControlPackageRuleGenerator, self ).__init__()
+      self.namespace = roverlay.util.namespace.SimpleNamespace()
 
-      Returns: not-None not-nested package rule (with a nested match block)
+   def clear_object_cache ( self ):
+      if self.namespace:
+         self.namespace.zap(True)
+   # --- end of clear_object_cache (...) ---
 
-      arguments:
-      * category_token_map -- acceptor chain
-      * emask              -- effective bitmask that gets translated into
-                              its corresponding package rule actions
-      """
+   def __del__ ( self ):
+      try:
+         self.clear_object_cache()
+      except NotImplementedError:
+         pass
 
-      # wrap actual acceptor with Acceptor_AND, see above
-      actual_acceptor = get_acceptor_recursive ( category_token_map, 0 )
-      and_acceptor    = roverlay.packagerules.abstract.acceptors.Acceptor_AND (0)
-      and_acceptor.add_acceptor ( actual_acceptor )
+   def token_item_to_acceptor ( self, token_item, value_getter, priority ):
+      if token_item in ( True, None ):
+         # should be catched elsewhere
+         return None
 
-      rule = roverlay.packagerules.abstract.rules.PackageRule ( priority=emask )
+      elif token_item.item_type == self.__class__.TOKEN_ITEM_IS_STR:
+         acceptor_cls = StringAcceptor
 
-      rule.set_acceptor ( and_acceptor )
 
-      have_any_action = False
-      for k, action in packagerule_actions.items():
-         have_any_action = True
-         if ( k & emask ):
-            rule.add_action ( action )
+      elif token_item.item_type == self.__class__.TOKEN_ITEM_IS_REGEX:
+         acceptor_cls = ExactRegexAcceptor
 
-      if not have_any_action:
+      else:
          raise AssertionError (
-            "rule object has no actions - bad emask? {:#x}".format (
-               emask=emask
-            )
+            "invalid token item type: {!s}".format ( token_item.item_type )
          )
+      # -- end if
 
-      return rule
-   # --- end of create_rule (...) ---
-
-   rules = [
-      create_rule ( category_token_map, emask )
-         for emask, category_token_map in \
-            reduced_bitmask_acceptor_chain_map.items()
-   ]
+      return self.namespace.get_object_v (
+         acceptor_cls, ( priority, value_getter, token_item.value )
+      )
+   # --- end of token_item_to_acceptor (...) ---
 
-   if not rules:
-      return None
+   def category_token_to_acceptor ( self, category_token, priority ):
+      if category_token is True:
+         raise Exception ( "C-TRUE" )
 
-   elif len(rules) == 1:
-      rules [0].priority = -1
-      return rules [0]
 
-   else:
-      combined_rule = roverlay.packagerules.abstract.rules.NestedPackageRule (
-         priority = -1
+      return self.token_item_to_acceptor (
+         category_token.name, get_category, priority
       )
-      combined_rule.set_acceptor ( always_true_acceptor )
+   # --- end of category_token_to_acceptor (...) ---
 
-      for rule in rules:
-         combined_rule.add_rule ( rule )
+   def package_token_to_acceptor ( self, package_token, priority ):
+      if package_token is True:
+         raise Exception ( "P-TRUE" )
+      else:
+         relevant_items = [
+            item_and_getter for item_and_getter in zip (
+               package_token,
+               (
+                  get_ebuild_name,
+                  get_ebuild_version_tuple
+               )
+            ) if item_and_getter[0] and item_and_getter[0] is not True
+         ]
 
-      return combined_rule
-   # -- end if
+         if not relevant_items:
+            raise TokenValueError ( package_token )
+
+         elif len(relevant_items) == 1:
+            return self.token_item_to_acceptor (
+               relevant_items[0][0], relevant_items[0][1], priority
+            )
+         else:
+            sub_acceptors = [
+               self.token_item_to_acceptor ( item, getter, 0 )
+               for item, getter in relevant_items
+            ]
+
+            combined_acceptor = Acceptor_AND ( priority=priority )
+            for sub_acceptor in sub_acceptors:
+               combined_acceptor.add_acceptor ( sub_acceptor )
+
+            return combined_acceptor
+   # --- end of package_token_to_acceptor (...) ---
 
-# --- end of create_package_rules (...) ---
 
 class SillyAdditionControlPackageRuleGenerator (
-   AbstractAdditionControlPackageRuleGenerator
+   roverlay.packagerules.generators.abstract.addition_control.\
+      AbstractAdditionControlPackageRuleGenerator
 ):
    """
    An add-policy package rule generator that doesn't care about its tokens.
@@ -705,41 +363,53 @@ class SillyAdditionControlPackageRuleGenerator (
 
 
 def temporary_demo_func():
-   rule_generator             = SillyAdditionControlPackageRuleGenerator()
+   #rule_generator             = SillyAdditionControlPackageRuleGenerator()
+   ARES                       = AdditionControlResult
+   rule_generator             = AdditionControlPackageRuleGenerator("sci-R")
+   CTOKEN                     = rule_generator.create_category_token
+   PTOKEN                     = rule_generator.create_package_token
    add_control_rule           = None
    bitmask_acceptor_chain_map = None
    acceptor_chain_bitmask_map = {
-      True: {
-         True: AdditionControlResult.PKG_REVBUMP_ON_COLLISION,
-         'p0': 8|2,
+      CTOKEN ( "sys-*" ): {
+         PTOKEN ( "a*-2" ): ARES.PKG_FORCE_DENY,
+      },
+      CTOKEN ( "*" ): {
+         PTOKEN ( "?*" ): ARES.PKG_REVBUMP_ON_COLLISION,
+         PTOKEN ( 'p0' ): ARES.PKG_FORCE_DENY|ARES.PKG_FORCE_REPLACE,
       },
-      'c': {
-         True: 2,
+      CTOKEN ( 'c' ): {
+         PTOKEN ( "***?****" ): ARES.PKG_FORCE_DENY,
       },
-      'd': {
-         True: AdditionControlResult.PKG_REPLACE_ONLY,
+      CTOKEN ( 'd' ): {
+         PTOKEN ( "*" ): ARES.PKG_REPLACE_ONLY,
       },
-      'f': {
-         'p1': AdditionControlResult.PKG_REPLACE_ONLY,
+      CTOKEN ( 'f' ): {
+         PTOKEN ( 'p1' ): ARES.PKG_REPLACE_ONLY,
+         PTOKEN ( 'p1-5.0' ): ARES.PKG_REPLACE_ONLY,
       },
    }
 
+
    print ( "** initial acceptor_chain -> raw_bitmask map" )
    print ( acceptor_chain_bitmask_map )
    print()
 
+   roverlay.packagerules.generators.abstract.addition_control.\
    expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map )
    print ( "** expanded acceptor_chain -> effective_bitmask map" )
    print ( acceptor_chain_bitmask_map )
    print()
 
    bitmask_acceptor_chain_map = (
+      roverlay.packagerules.generators.abstract.addition_control.\
       create_bitmask_acceptor_chain_map ( acceptor_chain_bitmask_map )
    )
    print ( "** initial effective_bitmask -> acceptor_chain map" )
    print(bitmask_acceptor_chain_map)
    print()
 
+   roverlay.packagerules.generators.abstract.addition_control.\
    reduce_bitmask_acceptor_chain_map ( bitmask_acceptor_chain_map )
    print ( "** reduced effective_bitmask -> acceptor_chain map" )
    print(bitmask_acceptor_chain_map)
@@ -758,12 +428,17 @@ def temporary_demo_func():
    print ( "** content of the rule generator\'s namespace" )
    print ( rule_generator.namespace._objects )
 
+   print ( "** content of the rule generator\'s namespace after clear-cache" )
+   rule_generator.clear_object_cache()
+   print ( rule_generator.namespace._objects )
+
 # --- end of temporary_demo_func (...) ---
 
 
 if __name__ == '__main__':
    import sys
    import os
+   from roverlay.overlay.abccontrol import AdditionControlResult
 
    try:
       temporary_demo_func()


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

* [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/
@ 2014-07-17 20:12 André Erdmann
  0 siblings, 0 replies; 7+ messages in thread
From: André Erdmann @ 2014-07-17 20:12 UTC (permalink / raw
  To: gentoo-commits

commit:     12380781282c45e9bb6ed6d56af08b2382738841
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Thu Jul 17 20:06:48 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Thu Jul 17 20:06:48 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=12380781

add-policy rule gen: BitmaskMapCreator

creates a "bitmask" -> "acceptor chain" map, which means that the addition
control pkgrule generator is mostly done now, except for some cleanup.
All steps have been implemented, what remains to be done is integrating it
in the package rule system and roverlay.defaultscript (+argparser etc.).

---
 .../packagerules/generators/addition_control.py    | 289 ++++++++++++++++-----
 1 file changed, 225 insertions(+), 64 deletions(-)

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index 0021817..1591ecd 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -5,6 +5,7 @@
 # either version 2 of the License, or (at your option) any later version.
 
 from __future__ import absolute_import
+from __future__ import print_function
 
 
 import abc
@@ -13,12 +14,16 @@ import fnmatch
 import re
 
 
+
 import roverlay.packagerules.generators.abstract.addition_control
 
 import roverlay.packagerules.abstract.acceptors
 import roverlay.packagerules.acceptors.stringmatch
 import roverlay.packagerules.acceptors.util
 
+import roverlay.overlay.abccontrol
+from roverlay.overlay.abccontrol import AdditionControlResult
+
 
 from roverlay.packagerules.abstract.acceptors import Acceptor_AND
 
@@ -30,7 +35,7 @@ from roverlay.packagerules.acceptors.util import (
    get_category, get_ebuild_name, get_ebuild_version_tuple,
 )
 
-#import roverlay.util.fileio
+import roverlay.util.fileio
 import roverlay.util.namespace
 
 import roverlay.util.portage_regex.default
@@ -43,12 +48,6 @@ from roverlay.util.portage_regex.wildcard import (
 
 
 
-
-
-
-
-
-
 class TokenValueError ( ValueError ):
    pass
 
@@ -59,7 +58,18 @@ class TokenItemNotSupported ( TokenValueError ):
    pass
 
 
+def _read_list_file (
+   filepath,
+   _read_text_file=roverlay.util.fileio.read_text_file
+):
+   def strip_line ( s ):
+      return s.strip()
 
+   if filepath:
+      for line in _read_text_file ( filepath, preparse=strip_line ):
+         # skip line if <>
+         yield line
+# --- end of _read_list_file (...) ---
 
 
 class AdditionControlPackageRuleGenerator (
@@ -90,6 +100,13 @@ class AdditionControlPackageRuleGenerator (
    #
    CategoryToken = collections.namedtuple ( 'CategoryToken', 'name' )
 
+   DEFAULT_CATEGORY_TOKEN = CategoryToken (
+      TokenItemTuple (
+         TOKEN_ITEM_IS_STR,
+         roverlay.packagerules.acceptors.util.DEFAULT_CATEGORY_REPLACEMENT
+      )
+   )
+
 
    def create_token_item_from_str ( self, s ):
       get_obj = self.namespace.get_object_v
@@ -162,12 +179,16 @@ class AdditionControlPackageRuleGenerator (
    # --- end of _create_package_token (...) ---
 
    def _create_category_token ( self, category_str ):
-      category_token = self.namespace.get_object_v (
-         self.__class__.CategoryToken,
-         (
-            self.create_token_item_from_str ( category_str ),
+      if category_str == self.default_category:
+         # validate_token() not necessary (assumption)
+         return self.DEFAULT_CATEGORY_TOKEN
+      else:
+         category_token = self.namespace.get_object_v (
+            self.__class__.CategoryToken,
+            (
+               self.create_token_item_from_str ( category_str ),
+            )
          )
-      )
 
       return self.validate_token ( category_token )
    # --- end of _create_category_token (...) ---
@@ -253,7 +274,9 @@ class AdditionControlPackageRuleGenerator (
 
    def __init__ ( self, default_category ):
       super ( AdditionControlPackageRuleGenerator, self ).__init__()
-      self.namespace = roverlay.util.namespace.SimpleNamespace()
+      self.namespace        = roverlay.util.namespace.SimpleNamespace()
+      self.default_category = default_category
+   # --- end of __init__ (...) ---
 
    def clear_object_cache ( self ):
       if self.namespace:
@@ -290,9 +313,7 @@ class AdditionControlPackageRuleGenerator (
    # --- end of token_item_to_acceptor (...) ---
 
    def category_token_to_acceptor ( self, category_token, priority ):
-      if category_token is True:
-         raise Exception ( "C-TRUE" )
-
+      assert category_token and category_token is not True
 
       return self.token_item_to_acceptor (
          category_token.name, get_category, priority
@@ -300,40 +321,176 @@ class AdditionControlPackageRuleGenerator (
    # --- end of category_token_to_acceptor (...) ---
 
    def package_token_to_acceptor ( self, package_token, priority ):
-      if package_token is True:
-         raise Exception ( "P-TRUE" )
+      assert package_token and package_token is not True
+
+      relevant_items = [
+         item_and_getter for item_and_getter in zip (
+            package_token,
+            (
+               get_ebuild_name,
+               get_ebuild_version_tuple
+            )
+         ) if item_and_getter[0] and item_and_getter[0] is not True
+      ]
+
+      if not relevant_items:
+         raise TokenValueError ( package_token )
+
+      elif len(relevant_items) == 1:
+         return self.token_item_to_acceptor (
+            relevant_items[0][0], relevant_items[0][1], priority
+         )
       else:
-         relevant_items = [
-            item_and_getter for item_and_getter in zip (
-               package_token,
-               (
-                  get_ebuild_name,
-                  get_ebuild_version_tuple
-               )
-            ) if item_and_getter[0] and item_and_getter[0] is not True
+         sub_acceptors = [
+            self.token_item_to_acceptor ( item, getter, 0 )
+            for item, getter in relevant_items
          ]
 
-         if not relevant_items:
-            raise TokenValueError ( package_token )
+         combined_acceptor = Acceptor_AND ( priority=priority )
+         for sub_acceptor in sub_acceptors:
+            combined_acceptor.add_acceptor ( sub_acceptor )
 
-         elif len(relevant_items) == 1:
-            return self.token_item_to_acceptor (
-               relevant_items[0][0], relevant_items[0][1], priority
-            )
+         return combined_acceptor
+   # --- end of package_token_to_acceptor (...) ---
+
+# --- end of AdditionControlPackageRuleGenerator ---
+
+
+class BitmaskMapCreator ( object ):
+   """creates a "bitmask" => "acceptor chain" map"""
+
+   def __init__ ( self, rule_generator ):
+      super ( BitmaskMapCreator, self ).__init__()
+      self.rule_generator = rule_generator
+      self.data           = rule_generator.create_new_bitmask_map()
+
+   def get_bitmask ( self ):
+      return self.data
+
+   def get_bitmask_copy ( self ):
+      return self.data.copy()
+
+   def _insert_package ( self, bitmask_arg, package_str, package_regex ):
+      category_token, package_token = self.rule_generator.create_token (
+         package_str, with_category=True, package_regex=package_regex
+      )
+
+      if isinstance ( bitmask_arg, str ):
+         bitmask_int = AdditionControlResult.convert_str ( bitmask_arg )
+      else:
+         bitmask_int = int ( bitmask_arg )
+
+
+      try:
+         cat_entry = self.data [category_token]
+      except KeyError:
+         self.data [category_token] = { package_token: bitmask_int }
+      else:
+         try:
+            pkg_entry = cat_entry [package_token]
+         except KeyError:
+            cat_entry [package_token] = bitmask_int
          else:
-            sub_acceptors = [
-               self.token_item_to_acceptor ( item, getter, 0 )
-               for item, getter in relevant_items
-            ]
+            pkg_entry |= bitmask_int
+         # -- end try <package entry exists>
+      # -- end try <category entry exists>
+   # --- end of _insert_package (...) ---
 
-            combined_acceptor = Acceptor_AND ( priority=priority )
-            for sub_acceptor in sub_acceptors:
-               combined_acceptor.add_acceptor ( sub_acceptor )
+   def _split_bitmask_line ( self, line, default_bitmask ):
+      # str<[bitmask,]arg> => ( bitmask||default_bitmask, arg )
+      args = line.split ( None, 1 )
+
+      if len(args) == 2:
+         # convert bitmask str now
+         return ( AdditionControlResult.convert_str(args[0]), args[1] )
+
+      elif default_bitmask or (
+         default_bitmask == 0 and default_bitmask is not False
+         # ? or default_bitmask is 0
+      ):
+         return ( default_bitmask, args[0] )
+
+      else:
+         raise ValueError ( line )
+   # --- end of _split_bitmask_line (...) ---
+
+   def _insert_packages_v (
+      self, bitmask, arglist, package_regex, extended_format
+   ):
+      insert_package = self._insert_package
+
+      if extended_format:
+         split_bitmask_line = self._split_bitmask_line
+
+         for arg in arglist:
+            call_args = split_bitmask_line ( arg, bitmask )
+            insert_package ( call_args[0], call_args[1], package_regex )
+
+      else:
+         for arg in arglist:
+            insert_package ( bitmask, arg, package_regex )
+   # --- end of _insert_packages_v (...) ---
+
+   def insert_packages_v ( self, bitmask, packages, extended_format=False ):
+      self._insert_packages_v (
+         bitmask, packages, RE_WILDCARD_PACKAGE, extended_format
+      )
+   # --- end of insert_packages_v (...) ---
+
+   def insert_package ( self, bitmask, package, *args, **kwargs ):
+      self.insert_packages_v ( bitmask, ( package, ), *args, **kwargs )
+
+   def insert_packages ( self, bitmask, *packages, **kwargs ):
+      self.insert_packages_v ( bitmask, packages, **kwargs )
+
+   def insert_ebuild_files_v (
+      self, bitmask, ebuild_files, extended_format=False
+   ):
+      self._insert_packages_v (
+         bitmask, ebuild_files, RE_PACKAGE_EBUILD_FILE, extended_format
+      )
+   # --- end of insert_ebuild_files_v (...) ---
+
+   def insert_ebuild_file ( self, bitmask, ebuild_file, *args, **kwargs ):
+      self.insert_ebuild_files_v (
+         bitmask, ( ebuild_file, ), *args, **kwargs
+      )
+
+   def insert_ebuild_files ( self, bitmask, *ebuild_files, **kwargs ):
+      self.insert_ebuild_files_v ( bitmask, ebuild_files, **kwargs )
+
+
+   def feed ( self,
+      bitmask, package_list=None, ebuild_file_list=None,
+      extended_format=False
+   ):
+      if package_list:
+         self.insert_packages_v ( bitmask, package_list, extended_format )
+
+
+      if ebuild_file_list:
+         self.insert_ebuild_files_v (
+            bitmask, ebuild_file_list, extended_format
+         )
+
+   # --- end of feed (...) ---
+
+   def feed_from_file (
+      self, bitmask, package_list_file=None, ebuild_list_file=None, **kw
+   ):
+      # or ebuild_file_list_file
+
+      self.feed (
+         bitmask,
+         _read_list_file ( package_list_file ),
+         _read_list_file ( ebuild_list_file ),
+         **kw
+      )
+   # --- end of feed_from_file (...) ---
+
+# --- end of BitmaskMapCreator ---
 
-            return combined_acceptor
-   # --- end of package_token_to_acceptor (...) ---
 
-# --- end of AdditionControlPackageRuleGenerator ---
 
 
 
@@ -341,29 +498,27 @@ class AdditionControlPackageRuleGenerator (
 def temporary_demo_func():
    ARES                       = AdditionControlResult
    rule_generator             = AdditionControlPackageRuleGenerator("sci-R")
-   CTOKEN                     = rule_generator.create_category_token
-   PTOKEN                     = rule_generator.create_package_token
+   bmap_creator               = BitmaskMapCreator(rule_generator)
+   P                          = bmap_creator.insert_package
    add_control_rule           = None
    bitmask_acceptor_chain_map = None
-   acceptor_chain_bitmask_map = {
-      CTOKEN ( "sys-*" ): {
-         PTOKEN ( "a*-2" ): ARES.PKG_FORCE_DENY,
-      },
-      CTOKEN ( "*" ): {
-         PTOKEN ( "?*" ): ARES.PKG_REVBUMP_ON_COLLISION,
-         PTOKEN ( 'p0' ): ARES.PKG_FORCE_DENY|ARES.PKG_FORCE_REPLACE,
-      },
-      CTOKEN ( 'c' ): {
-         PTOKEN ( "***?****" ): ARES.PKG_FORCE_DENY,
-      },
-      CTOKEN ( 'd' ): {
-         PTOKEN ( "*" ): ARES.PKG_REPLACE_ONLY,
-      },
-      CTOKEN ( 'f' ): {
-         PTOKEN ( 'p1' ): ARES.PKG_REPLACE_ONLY,
-         PTOKEN ( 'p1-5.0' ): ARES.PKG_REPLACE_ONLY,
-      },
-   }
+   # ref
+   acceptor_chain_bitmask_map = bmap_creator.data
+
+   bmap_creator.feed_from_file (
+      "force-replace",
+      "/tmp/ML"
+   )
+
+
+   P  (  "force-deny",                    "sys-*/a*-2",     True      )
+   P  (  ARES.PKG_REVBUMP_ON_COLLISION,   "*/?*"            )
+   P  (  "force-deny,force-replace",      "*/p0"            )
+   P  (  ARES.PKG_FORCE_DENY,             "c/***?****"      )
+   P  (  "replace-only",                  "d/*"             )
+   P  (  "replace-only",                  "f/p1"            )
+   P  (  ARES.PKG_REPLACE_ONLY,           "f/p1-5.0"        )
+   P  (  ARES.PKG_FORCE_REPLACE,          "sci-R/*"         )
 
 
    print ( "** initial acceptor_chain -> raw_bitmask map" )
@@ -402,6 +557,13 @@ def temporary_demo_func():
 
    print ( "** content of the rule generator\'s namespace" )
    print ( rule_generator.namespace._objects )
+   for cls in rule_generator.namespace._objects:
+      if type(cls) != type(object):
+         continue
+
+
+      if issubclass ( cls, roverlay.packagerules.abstract.acceptors._AcceptorCompound ):
+         raise Exception(cls)
 
    print ( "** content of the rule generator\'s namespace after clear-cache" )
    rule_generator.clear_object_cache()
@@ -413,7 +575,6 @@ def temporary_demo_func():
 if __name__ == '__main__':
    import sys
    import os
-   from roverlay.overlay.abccontrol import AdditionControlResult
 
    try:
       temporary_demo_func()


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

* [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/
@ 2014-07-18  2:28 André Erdmann
  0 siblings, 0 replies; 7+ messages in thread
From: André Erdmann @ 2014-07-18  2:28 UTC (permalink / raw
  To: gentoo-commits

commit:     1efba0795cabdd2a60beab0a2e5b62296d461032
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jul 18 01:02:21 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jul 18 01:02:21 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=1efba079

create_addition_control_package_rule()

Accepts a _huge_ number of parameters, creates a bitmask map and "compiles" it.
The result is a single package rule (or None).

---
 .../packagerules/generators/addition_control.py    | 185 ++++++++++++++-------
 1 file changed, 121 insertions(+), 64 deletions(-)

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index 1591ecd..03e4b71 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -7,6 +7,11 @@
 from __future__ import absolute_import
 from __future__ import print_function
 
+# TODO: cleanup:
+#   BitmaskMapCreator / AdditionControlPackageRuleGenerator naming
+#   ...
+#
+
 
 import abc
 import collections
@@ -364,10 +369,10 @@ class BitmaskMapCreator ( object ):
       self.rule_generator = rule_generator
       self.data           = rule_generator.create_new_bitmask_map()
 
-   def get_bitmask ( self ):
+   def get_bitmask_map ( self ):
       return self.data
 
-   def get_bitmask_copy ( self ):
+   def get_bitmask_map_copy ( self ):
       return self.data.copy()
 
    def _insert_package ( self, bitmask_arg, package_str, package_regex ):
@@ -476,7 +481,8 @@ class BitmaskMapCreator ( object ):
    # --- end of feed (...) ---
 
    def feed_from_file (
-      self, bitmask, package_list_file=None, ebuild_list_file=None, **kw
+      self, bitmask, package_list_file=None, ebuild_list_file=None,
+      extended_format=False,
    ):
       # or ebuild_file_list_file
 
@@ -484,7 +490,7 @@ class BitmaskMapCreator ( object ):
          bitmask,
          _read_list_file ( package_list_file ),
          _read_list_file ( ebuild_list_file ),
-         **kw
+         extended_format = extended_format,
       )
    # --- end of feed_from_file (...) ---
 
@@ -492,83 +498,134 @@ class BitmaskMapCreator ( object ):
 
 
 
+def create_addition_control_package_rule (
+   default_category,
+
+   cmdline_package_default              = None,
+   cmdline_package_force_deny           = None,
+   cmdline_package_deny_replace         = None,
+   cmdline_package_force_replace        = None,
+   cmdline_package_replace_only         = None,
+   cmdline_package_revbump_on_collision = None,
+
+   cmdline_ebuild_default               = None,
+   cmdline_ebuild_force_deny            = None,
+   cmdline_ebuild_deny_replace          = None,
+   cmdline_ebuild_force_replace         = None,
+   cmdline_ebuild_replace_only          = None,
+   cmdline_ebuild_revbump_on_collision  = None,
+
+   file_package_default                 = None,
+   file_package_force_deny              = None,
+   file_package_deny_replace            = None,
+   file_package_force_replace           = None,
+   file_package_replace_only            = None,
+   file_package_revbump_on_collision    = None,
+
+   file_ebuild_default                  = None,
+   file_ebuild_force_deny               = None,
+   file_ebuild_deny_replace             = None,
+   file_ebuild_force_replace            = None,
+   file_ebuild_replace_only             = None,
+   file_ebuild_revbump_on_collision     = None,
+
+   file_package_extended                = None,
+   file_ebuild_extended                 = None,
+):
+   """All-in-one function that takes lists of packages, ebuild paths, list
+   files, ... as input, creates a "bitmask" -> "acceptor chain" map and
+   converts it into a single, nested package rule object or None.
+
+   *** SLOW ***
+
+   Returns: package rule or None
+
+   Note: the returned has to be prepared manually (rule.prepare()),
+         which is usually done by the PackagRules top-level rule
+
+   arguments:
+   * default_category         -- name of the default overlay category
+                                  Mandatory argument.
+   * cmdline_package_<policy> -- list of packages [None]
+   * cmdline_ebuild_<policy>  -- list of ebuilds  [None]
+   * file_package_<policy>    -- package list file[s] [None]
+   * file_ebuild_<policy>     -- ebuild  list file[s] [None]
+   * file_package_extended    -- package list file[s] in extended format [None]
+   * file_ebuild_extended     -- ebuild  list file[s] in extended format [None]
+
+   Note: file_* parameters support only a single input file, currently.
+   """
+   argv_locals = locals().copy()
+   get_args    = lambda pre, attr_name: (
+      argv_locals [pre + '_package_' + attr_name],
+      argv_locals [pre + '_ebuild_'  + attr_name]
+   )
+##   argv_locals = {
+##      k: v for locals().items()
+##         if ( k.startswith("cmdline_") or k.startswith("file_") )
+##   }
 
+   if not default_category:
+      raise ValueError ( "no default category given (or empty)." )
 
+   rule_generator    = AdditionControlPackageRuleGenerator ( default_category )
+   bitmask_mapgen    = BitmaskMapCreator ( rule_generator )
+   feed_bitmask      = bitmask_mapgen.feed
+   filefeed_bitmask  = bitmask_mapgen.feed_from_file
 
-def temporary_demo_func():
-   ARES                       = AdditionControlResult
-   rule_generator             = AdditionControlPackageRuleGenerator("sci-R")
-   bmap_creator               = BitmaskMapCreator(rule_generator)
-   P                          = bmap_creator.insert_package
-   add_control_rule           = None
-   bitmask_acceptor_chain_map = None
-   # ref
-   acceptor_chain_bitmask_map = bmap_creator.data
-
-   bmap_creator.feed_from_file (
-      "force-replace",
-      "/tmp/ML"
-   )
 
+   for bitmask, desc in AdditionControlResult.PKG_DESCRIPTION_MAP.items():
+      attr_name = desc.replace ( '-', '_' )
+      # any() not strictly necessary here
 
-   P  (  "force-deny",                    "sys-*/a*-2",     True      )
-   P  (  ARES.PKG_REVBUMP_ON_COLLISION,   "*/?*"            )
-   P  (  "force-deny,force-replace",      "*/p0"            )
-   P  (  ARES.PKG_FORCE_DENY,             "c/***?****"      )
-   P  (  "replace-only",                  "d/*"             )
-   P  (  "replace-only",                  "f/p1"            )
-   P  (  ARES.PKG_REPLACE_ONLY,           "f/p1-5.0"        )
-   P  (  ARES.PKG_FORCE_REPLACE,          "sci-R/*"         )
+      args = get_args ( "cmdline", attr_name )
 
+      if any ( args ):
+         feed_bitmask ( bitmask, args[0], args[1] )
 
-   print ( "** initial acceptor_chain -> raw_bitmask map" )
-   print ( acceptor_chain_bitmask_map )
-   print()
 
-   roverlay.packagerules.generators.abstract.addition_control.\
-   expand_acceptor_chain_bitmasks ( acceptor_chain_bitmask_map )
-   print ( "** expanded acceptor_chain -> effective_bitmask map" )
-   print ( acceptor_chain_bitmask_map )
-   print()
-
-   bitmask_acceptor_chain_map = (
-      roverlay.packagerules.generators.abstract.addition_control.\
-      create_bitmask_acceptor_chain_map ( acceptor_chain_bitmask_map )
-   )
-   print ( "** initial effective_bitmask -> acceptor_chain map" )
-   print(bitmask_acceptor_chain_map)
-   print()
+      args = get_args ( "file", attr_name )
 
-   roverlay.packagerules.generators.abstract.addition_control.\
-   reduce_bitmask_acceptor_chain_map ( bitmask_acceptor_chain_map )
-   print ( "** reduced effective_bitmask -> acceptor_chain map" )
-   print(bitmask_acceptor_chain_map)
-   print()
+      if any ( args ):
+         filefeed_bitmask ( bitmask, args[0], args[1] )
+   # --
 
-   add_control_rule = (
-      rule_generator.create_package_rules ( bitmask_acceptor_chain_map )
+   if file_package_extended or file_ebuild_extended:
+      filefeed_bitmask (
+         None, file_package_extended, file_ebuild_extended,
+         extended_format=True
+      )
+   # --
+
+   add_control_rule = rule_generator.compile_bitmask_map (
+      bitmask_mapgen.get_bitmask_map()
    )
-   add_control_rule.priority = -1
-   add_control_rule.prepare()
 
-   print ( "** created package rule (sorted)" )
-   print(add_control_rule)
-   print()
+   # not necessary (GC)
+   rule_generator.clear_object_cache()
+   bitmask_mapgen.data.clear()
+   del bitmask_mapgen
+   del rule_generator
 
-   print ( "** content of the rule generator\'s namespace" )
-   print ( rule_generator.namespace._objects )
-   for cls in rule_generator.namespace._objects:
-      if type(cls) != type(object):
-         continue
+   return add_control_rule
+# --- end of create_addition_control_package_rule (...) ---
 
 
-      if issubclass ( cls, roverlay.packagerules.abstract.acceptors._AcceptorCompound ):
-         raise Exception(cls)
 
-   print ( "** content of the rule generator\'s namespace after clear-cache" )
-   rule_generator.clear_object_cache()
-   print ( rule_generator.namespace._objects )
+def temporary_demo_func():
+   rule = create_addition_control_package_rule (
+      "sci-R",
+      cmdline_package_force_deny = [ "sys-*/a*-2", "c/***?****", "*/p0", ],
+      cmdline_package_revbump_on_collision = [ "*/?*", ],
+      cmdline_package_force_replace = [ "*/p0", "sci-R/*", ],
+      cmdline_package_replace_only = [ "d/*", "f/p1", "f/p1-5.0", ],
+   )
+
+   assert rule
+   rule.priority = -1
+   rule.prepare()
 
+   print(rule)
 # --- end of temporary_demo_func (...) ---
 
 


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

* [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/
  2014-07-18 16:20 André Erdmann
@ 2014-07-18  2:28 ` André Erdmann
  0 siblings, 0 replies; 7+ messages in thread
From: André Erdmann @ 2014-07-18  2:28 UTC (permalink / raw
  To: gentoo-commits

commit:     a24d0669bde2e4853117d6233863452b3e164a2d
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jul 18 02:22:39 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jul 18 02:22:39 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=a24d0669

create_addition_control_package_rule(): add params

cmdline_{package,ebuild}_extended

---
 roverlay/packagerules/generators/addition_control.py | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index 03e4b71..2fbf4a1 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -515,6 +515,10 @@ def create_addition_control_package_rule (
    cmdline_ebuild_replace_only          = None,
    cmdline_ebuild_revbump_on_collision  = None,
 
+   cmdline_package_extended             = None,
+   cmdline_ebuild_extended              = None,
+
+
    file_package_default                 = None,
    file_package_force_deny              = None,
    file_package_deny_replace            = None,
@@ -590,6 +594,13 @@ def create_addition_control_package_rule (
          filefeed_bitmask ( bitmask, args[0], args[1] )
    # --
 
+   if cmdline_package_extended or cmdline_ebuild_extended:
+      feed_bitmask (
+         None, cmdline_package_extended, cmdline_ebuild_extended,
+         extended_format=True
+      )
+   # --
+
    if file_package_extended or file_ebuild_extended:
       filefeed_bitmask (
          None, file_package_extended, file_ebuild_extended,


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

* [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/
@ 2014-07-18  2:50 André Erdmann
  0 siblings, 0 replies; 7+ messages in thread
From: André Erdmann @ 2014-07-18  2:50 UTC (permalink / raw
  To: gentoo-commits

commit:     a091a84da2e11d473f75b1bdf97e60890f5f1390
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Fri Jul 18 02:30:34 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Fri Jul 18 02:30:34 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=a091a84d

remove dev-testing code

---
 .../packagerules/generators/addition_control.py    | 33 ----------------------
 1 file changed, 33 deletions(-)

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index 2fbf4a1..db6f244 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -5,7 +5,6 @@
 # either version 2 of the License, or (at your option) any later version.
 
 from __future__ import absolute_import
-from __future__ import print_function
 
 # TODO: cleanup:
 #   BitmaskMapCreator / AdditionControlPackageRuleGenerator naming
@@ -620,35 +619,3 @@ def create_addition_control_package_rule (
 
    return add_control_rule
 # --- end of create_addition_control_package_rule (...) ---
-
-
-
-def temporary_demo_func():
-   rule = create_addition_control_package_rule (
-      "sci-R",
-      cmdline_package_force_deny = [ "sys-*/a*-2", "c/***?****", "*/p0", ],
-      cmdline_package_revbump_on_collision = [ "*/?*", ],
-      cmdline_package_force_replace = [ "*/p0", "sci-R/*", ],
-      cmdline_package_replace_only = [ "d/*", "f/p1", "f/p1-5.0", ],
-   )
-
-   assert rule
-   rule.priority = -1
-   rule.prepare()
-
-   print(rule)
-# --- end of temporary_demo_func (...) ---
-
-
-if __name__ == '__main__':
-   import sys
-   import os
-
-   try:
-      temporary_demo_func()
-   except KeyboardInterrupt:
-      excode = os.EX_OK ^ 130
-   else:
-      excode = os.EX_OK
-
-   sys.exit ( excode )


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

* [gentoo-commits] proj/R_overlay:master commit in: roverlay/packagerules/generators/
  2014-07-17 20:12 [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/ André Erdmann
@ 2014-07-18 16:20 ` André Erdmann
  0 siblings, 0 replies; 7+ messages in thread
From: André Erdmann @ 2014-07-18 16:20 UTC (permalink / raw
  To: gentoo-commits

commit:     3a7fd984632e964003802b81456eb51ecbb97b10
Author:     André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Thu Jul 17 16:38:09 2014 +0000
Commit:     André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Thu Jul 17 16:38:09 2014 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=3a7fd984

remove SillyAdditionControlPackageRuleGenerator

replaced by AdditionControlPackageRuleGenerator

---
 .../packagerules/generators/addition_control.py    | 27 +---------------------
 1 file changed, 1 insertion(+), 26 deletions(-)

diff --git a/roverlay/packagerules/generators/addition_control.py b/roverlay/packagerules/generators/addition_control.py
index 7f2cc95..0021817 100644
--- a/roverlay/packagerules/generators/addition_control.py
+++ b/roverlay/packagerules/generators/addition_control.py
@@ -333,37 +333,12 @@ class AdditionControlPackageRuleGenerator (
             return combined_acceptor
    # --- end of package_token_to_acceptor (...) ---
 
-
-class SillyAdditionControlPackageRuleGenerator (
-   roverlay.packagerules.generators.abstract.addition_control.\
-      AbstractAdditionControlPackageRuleGenerator
-):
-   """
-   An add-policy package rule generator that doesn't care about its tokens.
-
-   Not useful for productive usage - will be removed as soon as a proper
-   rule generator has been implemented.
-   """
-
-   def __init__ ( self ):
-      super ( SillyAdditionControlPackageRuleGenerator, self ).__init__()
-      self.namespace = roverlay.util.namespace.SimpleNamespace()
-
-   def _get_true_acceptor_from_namespace ( self, any_token, priority ):
-      return self.namespace.get_object_v (
-         roverlay.packagerules.acceptors.trivial.TrueAcceptor,
-         ( priority, ),
-         {}
-      )
-
-   category_token_to_acceptor = _get_true_acceptor_from_namespace
-   package_token_to_acceptor  = _get_true_acceptor_from_namespace
+# --- end of AdditionControlPackageRuleGenerator ---
 
 
 
 
 def temporary_demo_func():
-   #rule_generator             = SillyAdditionControlPackageRuleGenerator()
    ARES                       = AdditionControlResult
    rule_generator             = AdditionControlPackageRuleGenerator("sci-R")
    CTOKEN                     = rule_generator.create_category_token


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

end of thread, other threads:[~2014-07-18 16:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-17 20:12 [gentoo-commits] proj/R_overlay:wip/addition_control commit in: roverlay/packagerules/generators/ André Erdmann
2014-07-18 16:20 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
  -- strict thread matches above, loose matches on Subject: below --
2014-07-18 16:20 André Erdmann
2014-07-18  2:28 ` [gentoo-commits] proj/R_overlay:wip/addition_control " André Erdmann
2014-07-18  2:50 André Erdmann
2014-07-18  2:28 André Erdmann
2014-07-17 20:12 André Erdmann
2014-07-17 20:12 André Erdmann

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