[Checkins] SVN: z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/ Fix empty-directoryname bug and add support for create-intermediate option.

Ulrich Fouquet cvs-admin at zope.org
Mon Jun 25 23:56:03 UTC 2012


Log message for revision 127074:
  Fix empty-directoryname bug and add support for create-intermediate option.

Changed:
  U   z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/README.txt
  U   z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/__init__.py
  U   z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/regression.txt

-=-
Modified: z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/README.txt
===================================================================
--- z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/README.txt	2012-06-25 23:10:53 UTC (rev 127073)
+++ z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/README.txt	2012-06-25 23:56:00 UTC (rev 127074)
@@ -60,7 +60,21 @@
 
      If you don't specify a mode, the system default will be used.
 
+* ``create-intermediate``
+     Default: ``yes``
 
+     If set to `no`, the parent directory of the path to create _must_
+     already exist when running the recipe (and an error occurs if not).
+
+     If set to `yes`, any missing intermediate directories will be
+     created. E.g. if creating a relative dir
+
+     ``a/b/c/``
+
+     with ``create-intermediate`` set to ``no``, the relative path
+     ``a/b/`` must exist already.
+
+
 Simple creation of directories via buildout
 ===========================================
 
@@ -335,7 +349,7 @@
 ===========================
 
 If we specify several levels of directories, the intermediate parts
-will be created for us as well:
+will be created for us as well by default:
 
   >>> write('buildout.cfg',
   ... '''
@@ -358,7 +372,67 @@
   >>> ls('myrootdir', 'other', 'dir')
   d  finaldir
 
+If we set the ``create-intermediate`` option to ``no`` (default is
+``yes``), the resulting dir will only be create if the parent
+directory exists already:
 
+  >>> write('buildout.cfg',
+  ... '''
+  ... [buildout]
+  ... parts = mydir
+  ... offline = true
+  ...
+  ... [mydir]
+  ... recipe = z3c.recipe.mkdir
+  ... paths = leaf/dir/without/existing/parent
+  ... create-intermediate = no
+  ... ''')
+
+  >>> print system(join('bin', 'buildout')),
+  Uninstalling mydir.
+  Installing mydir.
+  While:
+    Installing mydir.
+  Error: Cannot create: /sample-buildout/leaf/dir/without/existing/parent
+         Parent does not exist or not a directory.
+
+If you want to be explicit about the paths to be created (and which
+not), you can set ``create-intermediate`` to ``no`` and simply list
+each part of the path in ``paths`` option. This has the nice
+sideeffect of setting permissions correctly also for intermediate
+paths:
+
+  >>> write('buildout.cfg',
+  ... '''
+  ... [buildout]
+  ... parts = mydir
+  ... offline = true
+  ...
+  ... [mydir]
+  ... recipe = z3c.recipe.mkdir
+  ... paths = mydir
+  ...         mydir/with
+  ...         mydir/with/existing
+  ...         mydir/with/existing/parent
+  ... create-intermediate = no
+  ... mode = 750
+  ... ''')
+
+  >>> print system(join('bin', 'buildout')),
+  Installing mydir.
+  mydir: created path: /sample-buildout/mydir
+  mydir:   mode 0750
+  mydir: created path: /sample-buildout/mydir/with
+  mydir:   mode 0750
+  mydir: created path: /sample-buildout/mydir/with/existing
+  mydir:   mode 0750
+  mydir: created path: /sample-buildout/mydir/with/existing/parent
+  mydir:   mode 0750
+
+This is more to write down, but you can be sure that only explicitly
+named dirs are created and permissions set accordingly.
+
+
 Paths are normalized
 ====================
 

Modified: z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/__init__.py
===================================================================
--- z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/__init__.py	2012-06-25 23:10:53 UTC (rev 127073)
+++ z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/__init__.py	2012-06-25 23:56:00 UTC (rev 127074)
@@ -10,6 +10,8 @@
         self.logger=logging.getLogger(self.name)
         self.remove_on_update = string_to_bool(
             options.get('remove-on-update', 'no'))
+        self.create_intermediate = string_to_bool(
+            options.get('create-intermediate', 'yes'))
 
         if 'path' in options.keys():
             self.logger.warn(
@@ -18,8 +20,14 @@
         paths = options.get(
             'paths', options.get('path', os.path.join(
                 buildout['buildout']['parts-directory'], name)))
-        self.paths = [os.path.normpath(os.path.abspath(
-            x.strip())) for x in paths.split('\n')]
+        self.paths = []
+        for path in paths.split('\n'):
+            path = path.strip()
+            if not path:
+                # don't consider empty dirs
+                continue
+            self.paths.append(os.path.normpath(os.path.abspath(path)))
+        self.paths = sorted(self.paths)
 
         self.mode = options.get('mode', None)
         if self.mode is not None:
@@ -53,6 +61,8 @@
 
         # Update options to be referencable...
         options['path'] = options['paths'] = '\n'.join(self.paths)
+        options['create-intermediate'] = '%s' % self.create_intermediate
+        options['remove-on-update'] = '%s' % self.remove_on_update
         if self.mode:
             options['mode'] = oct(self.mode)
         if self.user:
@@ -70,6 +80,11 @@
 
     def createIntermediatePaths(self, path):
         parent = os.path.dirname(path)
+        if self.create_intermediate is False:
+            if path in self.paths and not os.path.isdir(parent):
+                raise zc.buildout.UserError(
+                    "Cannot create: %s\n"
+                    "       Parent does not exist or not a directory." % path)
         if os.path.exists(path) and not os.path.isdir(path):
             raise zc.buildout.UserError(
                 "Cannot create directory: %s. It's a file." % path)
@@ -78,7 +93,8 @@
                 self.logger.info('set permissions for %s' % path)
                 self.setPermissions(path)
             return
-        self.createIntermediatePaths(parent)
+        if not os.path.isdir(parent):
+            self.createIntermediatePaths(parent)
         os.mkdir(path)
         self.logger.info('created path: %s' % path)
         self.setPermissions(path)

Modified: z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/regression.txt
===================================================================
--- z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/regression.txt	2012-06-25 23:10:53 UTC (rev 127073)
+++ z3c.recipe.mkdir/trunk/z3c/recipe/mkdir/regression.txt	2012-06-25 23:56:00 UTC (rev 127074)
@@ -1,6 +1,9 @@
 Regression Tests
 ================
 
+Deprecated `path` option works correctly
+----------------------------------------
+
   >>> write('buildout.cfg',
   ... '''
   ... [buildout]
@@ -31,3 +34,34 @@
 
   >>> ls('my/nested')
   d  dir
+
+Empty path is not processed
+---------------------------
+
+Up to version 0.4 the empty path was considered to be the current
+directory and permissions set. This does not happen anymore.
+
+We create a `paths` definition with empty entries (first and middle):
+
+  >>> write('buildout.cfg',
+  ... '''
+  ... [buildout]
+  ... parts = mydir
+  ... offline = true
+  ...
+  ... [mydir]
+  ... recipe = z3c.recipe.mkdir
+  ... paths =
+  ...    mypath1
+  ...
+  ...    mypath2
+  ... mode = 0750
+  ... ''')
+
+  >>> print system(join('bin', 'buildout')),
+  Uninstalling mydir.
+  Installing mydir.
+  mydir: created path: /sample-buildout/mypath1
+  mydir:   mode 0750
+  mydir: created path: /sample-buildout/mypath2
+  mydir:   mode 0750



More information about the checkins mailing list