r447 - in zope-common/trunk: . debian

Fabio Tranchitella kobold at alioth.debian.org
Sun Nov 5 08:46:03 CET 2006


Author: kobold
Date: 2006-11-05 08:46:03 +0100 (Sun, 05 Nov 2006)
New Revision: 447

Modified:
   zope-common/trunk/debian/README.Debian
   zope-common/trunk/debian/changelog
   zope-common/trunk/debian/postinst
   zope-common/trunk/debian/postrm
   zope-common/trunk/dzhandle
Log:
Changes for dzhandle: allow user and system local products.


Modified: zope-common/trunk/debian/README.Debian
===================================================================
--- zope-common/trunk/debian/README.Debian	2006-11-02 22:43:46 UTC (rev 446)
+++ zope-common/trunk/debian/README.Debian	2006-11-05 07:46:03 UTC (rev 447)
@@ -64,7 +64,7 @@
 
 You (or a package) can create a zope instance using:
 
-  dzhandle -z 2.9 make-instance <instance> --addon-mode [all|manual]
+  dzhandle -z 2.9 make-instance <instance> --addon-mode [manual|all]
 
 The script uses the `mkzopeinstance.py' script to create the instance
 and creates a file /etc/zope2.9/<instance>/debian_policy, which has
@@ -125,6 +125,24 @@
 the instances.
 
 
+Local third-party zope products
+-------------------------------
+
+The system administrator can install third-party custom products in
+/usr/local/share/zope/Products, and they will be read before the
+system-installed ones.
+
+To enable dzhandle usage for a manually installed product, the system
+administrator has to create a .dzproduct file inside the product with
+a content like:
+
+  Name: ProductName
+  Package: local
+  Version: 0.1
+
+At this point, dzhandle list-products will include the custom product.
+
+
 Using dzhandle with non-root users
 ----------------------------------
 
@@ -134,8 +152,8 @@
 
 The default paths for personal zope and zeo instances are:
 
-  $HOME/zope-instances
-  $HOME/zeo-instances
+  $HOME/zope/instance
+  $HOME/zope/zeo
 
 These paths can be overridden creating a file ~/.dzhandle.conf within the
 home directory of the user with the following syntax:
@@ -143,9 +161,10 @@
   # this is a comment
   instances: /home/user1/zope/instances
   zeoinstances: /home/user1/zope/zeo
+  products: /home/user1/zope/products
 
 dzhandle detects when it is used with a non-root user and reads the
-configuration file in the home directory (or use the defaults). This
+configuration file in the home directory (or uses the default). This
 is an example usage of this feature:
 
   $ whoami
@@ -158,3 +177,7 @@
   
   this instance will be created in:
       /home/user1/zope-instances/zope2.9/testing
+
+Users can enable dzhandle usage for custom products putting them under
+~/zope/products (or where specified by the configuration file) and following
+the instructions from the "Local third-party zope products" paragraph.

Modified: zope-common/trunk/debian/changelog
===================================================================
--- zope-common/trunk/debian/changelog	2006-11-02 22:43:46 UTC (rev 446)
+++ zope-common/trunk/debian/changelog	2006-11-05 07:46:03 UTC (rev 447)
@@ -1,20 +1,20 @@
-zope-common (0.5.26) unstable; urgency=low
+zope-common (0.5.26) unstable; urgency=medium
 
   * debian/README.Debian: updated to use zope2.9 instead of zope2.10
     in the examples, because that's the version we'll ship in etch.
   * debian/templates: fixed two typos. (Closes: #385882)
-  * debian/control: sb-release and po-debconf should be in Build-Depends.
+  * debian/control: lsb-release and po-debconf should be in Build-Depends.
     (Closes: #392653)
   * debian/po/cs.po: updated. (Closes: #396759)
   * dzhandle: restart only running instances on upgrades.
     (Closes: #388253, #378364)
-  * dzhandle: use the atechnique from instance if not specified on the
+  * dzhandle: use atechnique from the instance if not specified on the
     command-line. (Closes: #382773)
-  * dzhandle: implemented basic normal-user personal instances handling.
+  * dzhandle: implemented basic non-root usage for personal instances.
     (Closes: #359256)
   * debian/rules: mv dzhandle from /usr/sbin to /usr/bin. (Closes: #379169)
 
- -- Fabio Tranchitella <kobold at debian.org>  Thu,  2 Nov 2006 23:10:54 +0100
+ -- Fabio Tranchitella <kobold at debian.org>  Fri,  3 Nov 2006 20:35:19 +0100
 
 zope-common (0.5.25) unstable; urgency=low
 

Modified: zope-common/trunk/debian/postinst
===================================================================
--- zope-common/trunk/debian/postinst	2006-11-02 22:43:46 UTC (rev 446)
+++ zope-common/trunk/debian/postinst	2006-11-05 07:46:03 UTC (rev 447)
@@ -21,6 +21,16 @@
 		mkdir -p /var/lib/zope/dzhandle
 		chown $zopeuse:$zopegroup /var/lib/zope/dzhandle
 	fi
+
+    LOCALDIR=/usr/local/share/zope
+    if [ ! -d $LOCALDIR ]; then
+        if mkdir $LOCALDIR 2>/dev/null ; then
+            mkdir $LOCALDIR/Products
+            chmod 2775 $LOCALDIR -R
+            chown root:$zopegroup $LOCALDIR -R
+        fi
+    fi
+
 	;;
 
     abort-upgrade|abort-remove|abort-deconfigure)

Modified: zope-common/trunk/debian/postrm
===================================================================
--- zope-common/trunk/debian/postrm	2006-11-02 22:43:46 UTC (rev 446)
+++ zope-common/trunk/debian/postrm	2006-11-05 07:46:03 UTC (rev 447)
@@ -35,7 +35,11 @@
         #    # PCGI resuource file should have already been removed.
         #fi
 
-	rm -rf /var/lib/zope/dzhandle
+        rm -rf /var/lib/zope/dzhandle
+
+        LOCALDIR=/usr/local/share/zope
+        rmdir --ignore-fail-on-non-empty $LOCALDIR/Products || true
+        rmdir --ignore-fail-on-non-empty $LOCALDIR || true
         ;;
 
     remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)

Modified: zope-common/trunk/dzhandle
===================================================================
--- zope-common/trunk/dzhandle	2006-11-02 22:43:46 UTC (rev 446)
+++ zope-common/trunk/dzhandle	2006-11-05 07:46:03 UTC (rev 447)
@@ -1,6 +1,29 @@
 #! /usr/bin/python2.4
 
-import fnmatch, glob, os, re, sys, shutil
+# Copyright (C) 2005-2006 Matthias Klose <doko at ubuntu.com>
+#                         Fabio Tranchitella <kobold at debian.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+
+import os
+import sys
+import re
+import glob
+import fnmatch
+import shutil
 import pwd, grp
 import logging
 import subprocess
@@ -76,18 +99,16 @@
 def addon_technique_code(name):
     return addon_options.index(name)
 
-personal_conf = {}
-def is_root():
-    return os.getuid() == 0
-
 known_actions = {}
 def register_action(action_class):
     known_actions[action_class.name] = action_class
 
+personal_conf = {}
+
 # --------------------------------------------------------------------------- #
 
-class DZError(Exception):
-    pass
+def is_root():
+    return os.getuid() == 0
 
 def strlist(sequence):
     return ', '.join(["`%s'" % s for s in sequence])
@@ -95,10 +116,8 @@
 def available_zope_versions():
     return [z['version'] for z in zope_packages if os.path.isdir(z['prefix'])]
 
-def filter_zope_version(**kw):
-    key = kw.keys()[0]
-    value = kw[key]
-    return [z for z in zope_packages if z[key] == value][0]
+def filter_zope_version(version):
+    return [z for z in zope_packages if z['version'] == version][0]
 
 def read_config_file(fn, required=None):
     attrs = {}
@@ -201,6 +220,7 @@
             self.depends = None
             self.recommends = None
             self.suggests = None
+            self.is_global = False
             self.zopeversions = " ".join([z['version'] for z in zope_packages])
         else:
             self.read_dzfile()
@@ -229,6 +249,7 @@
         self.suggests = attrs.get('Suggests', None)
         self.zopeversions = attrs.get('ZopeVersions', \
                             " ".join([z['version'] for z in zope_packages]))
+        self.is_global = (attrs.get('Global', None) == 'yes')
     
     def write_dzfile(self, fn=None):
         fn = fn or os.path.join(self.path, self.dzname)
@@ -252,6 +273,10 @@
         """checks if the addon is available in the instance
         """
 
+        if self.is_global:
+            ipath = os.path.join(instance.home, self.subdir, self.name + '.installed')
+            return os.path.exists(ipath)
+
         ipath = os.path.join(instance.home, self.subdir, self.name)
         return os.path.isdir(ipath)
 
@@ -259,6 +284,10 @@
         """If the addon is available in the instance, return it, else return None.
         """
         
+        if self.is_global:
+            ipath = os.path.join(instance.home, self.subdir, self.name + '.installed')
+            return os.path.exists(ipath) and self or None
+
         ipath = os.path.join(instance.home, self.subdir, self.name)
         if not os.path.isdir(ipath):
             return None
@@ -276,9 +305,7 @@
         iaddons = []
         for instance in instances:
             iaddon = self.installed_in_instance(instance)
-            if iaddon \
-                   and not iaddon.type in exclude \
-                   and iaddon.installed_by(self):
+            if iaddon and not iaddon.type in exclude and iaddon.installed_by(self):
                 iaddons.append(iaddon)
         return iaddons
 
@@ -303,12 +330,14 @@
     def installed_by(self, master):
         """checks if the installed addon was installed by the `master' addon
         """
-        assert self.type != ADDON_MASTER and master.type == ADDON_MASTER
+        assert self.type != ADDON_MASTER and master.type == ADDON_MASTER or self.is_global
         
-        if self.name != master.name or self.package != master.package:
+        if self.is_global:
+            return True
+        elif self.name != master.name or self.package != master.package:
             # other addon, or same addon installed by other package
             return False
-        if self.type == ADDON_COPIED:
+        elif self.type == ADDON_COPIED:
             # copied from master to instance, version may mismatch
             return True
         
@@ -327,7 +356,8 @@
         return True
         
     def printit(self, stream=sys.stdout):
-        print >>stream, self.kind, self.name, self.directory, self.package, self.version, self.path, self.depends
+        print >>stream, self.kind, self.name, self.directory, \
+            self.package, self.version, self.path, self.depends
         
 class ProductAttributes:
     kind = 'product'
@@ -348,6 +378,8 @@
 ProductAttributes.addonClass = Product
 ExtensionAttributes.addonClass = Extension
 
+# --------------------------------------------------------------------------- #
+
 class DZAction:
     _option_parser = None
     name = None
@@ -706,7 +738,7 @@
         
 class DZPrermProduct(ProductAttributes, DZPrerm):
     name = 'prerm-%s' % ProductAttributes.kind
-    help = 'handle prerm of a packaged %s' % ExtensionAttributes.kind
+    help = 'handle prerm of a packaged %s' % ProductAttributes.kind
 
 class DZPrermExtension(ExtensionAttributes, DZPrerm):
     name = 'prerm-%s' % ExtensionAttributes.kind
@@ -744,7 +776,7 @@
         
 class DZPostrmProduct(ProductAttributes, DZPostrm):
     name = 'postrm-%s' % ProductAttributes.kind
-    help = 'handle postrm of a packaged %s' % ExtensionAttributes.kind
+    help = 'handle postrm of a packaged %s' % ProductAttributes.kind
 
 class DZPostrmExtension(ExtensionAttributes, DZPostrm):
     name = 'postrm-%s' % ExtensionAttributes.kind
@@ -1054,7 +1086,12 @@
             else:
                 addon_base, addon_suffix = arg, ''
             ipath = os.path.join(self.instance.home, self.subdir, addon_base)
-            if not os.path.isdir(ipath):
+            if os.path.exists(ipath + '.installed'):
+                path = open(ipath + '.installed', 'r').read()
+                addon = self.addonClass(path, dzfile_required=False)
+                addons.append((addon, addon))
+                continue
+            elif not os.path.isdir(ipath):
                 if not self.options.lazy:
                     self.error("%s `%s' not found in instance `%s' (%s)"
                                % (self.kind, addon_base, self.instance.name, self.instance.version),
@@ -1819,12 +1856,24 @@
             return
 
         addon_technique = addon_technique or self.addon_technique
+        if addon_technique == ADDON_MANUAL:
+            return
+        assert addon_technique in (ADDON_LINKED, ADDON_TREELINKED, ADDON_COPIED)
 
-        if addon_technique == ADDON_MANUAL: return
-        assert addon_technique in (ADDON_LINKED, ADDON_TREELINKED, ADDON_COPIED)
-        
+        if self.version.startswith("3"):
+            files = []
+            files.extend(glob.glob(os.path.join(addon.path, '*-configure.zcml')))
+            files.extend(glob.glob(os.path.join(addon.path, '*-meta.zcml')))
+            files.extend(glob.glob(os.path.join(addon.path, '*-ftesting.zcml')))
+            for f in files:
+                filename = os.path.split(f)[1]
+                os.symlink(f, os.path.join(self.home, "etc/package-includes/", filename))
+
         target_path = os.path.join(self.home, addon.subdir, addon.name)
-        if addon_technique == ADDON_LINKED:
+        if addon.is_global:
+            open(target_path + '.installed', 'w').write(addon.path)
+            target_path = addon.path
+        elif addon_technique == ADDON_LINKED:
             os.symlink(addon.path, target_path)
             if global_options.verbose:
                 print "linked: %s -> %s" % (target_path, addon.path)
@@ -1839,10 +1888,6 @@
             if global_options.verbose:
                 print "copied: %s -> %s" % (addon.path, target_path)
 
-        if self.version.startswith("3") and os.path.isfile(os.path.join(addon.path, ".dzconfigure")):
-            os.symlink(os.path.join(addon.path, ".dzconfigure"), \
-                       os.path.join(self.home, "etc/package-includes/", addon.name + "-configure.zcml"))
-
         added_addon = addon.addonClass(target_path, False)
         self._installed_addons.append(added_addon)
         logging.info("added %s `%s'", added_addon.kind, added_addon.path)
@@ -1851,11 +1896,24 @@
         installed = [a for a in self.installed_addons() if getattr(addon, 'name', None) == a.name]
         if len(installed) != 1:
             raise DZError, "%s `%s' not installed in instance `%s'" \
-                  % (a.kind, a.name, self.name)
+                  % (addon.kind, addon.name, self.name)
         installed = installed[0]
         assert addon.name == installed.name
 
-        if installed.type == ADDON_LINKED:
+        if self.version.startswith("3"):
+            files = []
+            files.extend(glob.glob(os.path.join(addon.path, '*-configure.zcml')))
+            files.extend(glob.glob(os.path.join(addon.path, '*-meta.zcml')))
+            files.extend(glob.glob(os.path.join(addon.path, '*-ftesting.zcml')))
+            for f in files:
+                filename = os.path.split(f)[1]
+                target = os.path.join(self.home, "etc/package-includes/", filename)
+                if os.path.exists(target):
+                    os.unlink(target)
+
+        if addon.is_global:
+            os.unlink(os.path.join(self.home, addon.subdir, addon.name) + '.installed')
+        elif installed.type == ADDON_LINKED:
             os.unlink(installed.path)
         elif installed.type in (ADDON_MANUAL, ADDON_COPIED) and not global_options.force:
             raise DZError, "not removing copied or manually installed %s `%s'" \
@@ -1876,11 +1934,6 @@
         else:
             return
 
-        if self.version.startswith("3"):
-            try:
-                os.unlink(os.path.join(self.home, "etc/package-includes/", addon.name + "-configure.zcml"))
-            except OSError: pass
-
         self._installed_addons.remove(installed)
         logging.info("removed %s `%s'", installed.kind, installed.path)
 
@@ -2108,21 +2161,27 @@
     elif arch == 'any':
         prefixes = ['/usr/lib/zope']
     elif arch == 'all':
-        prefixes = ['/usr/share/zope']
+        prefixes = ['/usr/share/zope', '/usr/local/share/zope']
     else:
-        prefixes = ['/usr/share/zope', '/usr/lib/zope']
+        prefixes = ['/usr/share/zope', '/usr/lib/zope', '/usr/local/share/zope']
     if addonClass == Product:
         subdirs = [Product.subdir]
     elif addonClass == Extension:
         subdirs = [Extension.subdir]
     else:
         subdirs = [Product.subdir, Extension.subdir]
+    locals = []
+    if not instance and not is_root():
+        locals.append(personal_conf['products'])
     addons = []
-    for d in [os.path.join(pf, sd) for pf in prefixes for sd in subdirs]:
+    for d in locals + [os.path.join(pf, sd) for pf in prefixes for sd in subdirs]:
         for path in glob.glob(os.path.join(d, '*')):
-            if not os.path.isdir(path):
+            if os.path.isfile(path) and path.endswith('.installed'):
+                path = open(path, 'r').read()
+                addonClass = Product
+            elif not os.path.isdir(path):
                 continue
-            if not addonClass:
+            elif not addonClass:
                 if os.path.basename(os.path.dirname(path)) == Product.subdir:
                     addonClass = Product
                 else:
@@ -2302,11 +2361,13 @@
     if not is_root():
         home_dir = pwd.getpwuid(uid)[5]
         conf = os.path.join(home_dir, '.dzhandle.conf')
+        personal_conf['instances'] = os.path.join(home_dir, 'zope/instance')
+        personal_conf['products'] = os.path.join(home_dir, 'zope/products')
+        personal_conf['zeoinstances'] = os.path.join(home_dir, 'zope/zeo')
         if os.path.exists(conf):
             personal_conf.update(read_config_file(conf))
         else:
-            personal_conf['instances'] = os.path.join(home_dir, 'zope-instances')
-            personal_conf['zeoinstances'] = os.path.join(home_dir, 'zeo-instances')
+            write_config_file(conf, personal_conf)
 
     # setup logging stuff
     setup_logging(config.get('logfile', None),




More information about the pkg-zope-commits mailing list