Commit 6daada26 authored by Thomas Larrieu's avatar Thomas Larrieu

Modified cleanup feature : now it takes prefix into account to determine if a path is valid or not.

parent 10beede5
...@@ -228,36 +228,48 @@ class Recipe(object): ...@@ -228,36 +228,48 @@ class Recipe(object):
log.error('Command failed: %s: %s' % (e, cmd)) log.error('Command failed: %s: %s' % (e, cmd))
raise zc.buildout.UserError('System error') raise zc.buildout.UserError('System error')
def _return_if_exists_in_prefix(self, path, prefix):
relpath = os.path.relpath(path, prefix)
abspath = os.path.join(prefix, relpath)
if os.path.exists(abspath):
if relpath.startswith('..'):
raise IOError(prefix + " does not contain " + path)
else:
return path
else:
raise IOError(path + " does not exist")
def _is_pattern(self, pattern):
if pattern.find('*') > -1 or pattern.find('?') > -1 or pattern.find('[') > -1:
return True
return False
def _build_iterator(self, cleanup_list, prefix):
import glob
# First, expand eventual wildcards
for entry in [os.path.join(prefix, x) for x in cleanup_list]:
if self._is_pattern(entry):
paths = glob.glob(entry)
if paths:
for path in paths:
yield self._return_if_exists_in_prefix(path, prefix)
else:
raise IOError("Pattern " + entry + " did not match anything")
else:
yield self._return_if_exists_in_prefix(entry, prefix)
def clean(self, cleanup_list): def clean(self, cleanup_list):
""" """
Basically, this method does not do much, appart from removing Basically, this method does not do much, appart from removing
what it is told to, as a list passed in args what it is told to, as a list passed in args
""" """
import glob
def build_working_iterator(cleanup_list):
current_dir = os.getcwd()
for pattern in cleanup_list:
# if current pattern contains wildcards, we search for all matching
# files/directories
if pattern.find('*') > -1 or pattern.find('?') > -1 or pattern.find('[') > -1:
g = glob.glob(pattern)
if g:
for x in g:
yield x
else:
raise IOError("Pattern " + pattern + " did not match anything")
elif os.path.exists(pattern):
if os.path.relpath(pattern).startswith('..'):
raise IOError(current_dir + " does not contain " + pattern)
else:
yield pattern
else:
raise IOError(pattern + " does not exist")
# As build_working_iterator is a generator and since we want to first # As build_working_iterator is a generator and since we want to first
# check every file (raising exceptions when necessary) BEFORE removing # check every file (raising exceptions when necessary) BEFORE removing
# anything from the file system, we enforce full lookup by build a tuple # anything from the file system, we enforce full lookup by build a tuple
# out of it # out of it
for x in tuple(build_working_iterator(cleanup_list)): print self.options['prefix']
for x in tuple(self._build_iterator(cleanup_list, self.options['prefix'])):
# This first condition is mandatory as we might have removed an entire # This first condition is mandatory as we might have removed an entire
# tree during a previous iteration, possibly leading to a case where # tree during a previous iteration, possibly leading to a case where
# some items are still to be removed but do not exist anymore # some items are still to be removed but do not exist anymore
......
...@@ -7,6 +7,7 @@ import shutil ...@@ -7,6 +7,7 @@ import shutil
import stat import stat
import tarfile import tarfile
import tempfile import tempfile
import glob
from time import sleep from time import sleep
import zc.buildout import zc.buildout
import zc.buildout.testing import zc.buildout.testing
...@@ -317,7 +318,8 @@ class NonInformativeTests(unittest.TestCase): ...@@ -317,7 +318,8 @@ class NonInformativeTests(unittest.TestCase):
'cleanup': 'foo\nbar' 'cleanup': 'foo\nbar'
} }
) )
os.chdir(self.dir) os.mkdir(recipe.options.get('prefix'))
os.chdir(recipe.options.get('prefix'))
tmp = open('foo', 'a') tmp = open('foo', 'a')
tmp = open('bar', 'a') tmp = open('bar', 'a')
self.assertTrue(os.path.exists('foo')) self.assertTrue(os.path.exists('foo'))
...@@ -326,7 +328,28 @@ class NonInformativeTests(unittest.TestCase): ...@@ -326,7 +328,28 @@ class NonInformativeTests(unittest.TestCase):
self.assertFalse(os.path.exists('foo')) self.assertFalse(os.path.exists('foo'))
self.assertFalse(os.path.exists('bar')) self.assertFalse(os.path.exists('bar'))
def test_cleanup_succeeds_when_glob_is_valid(self):
recipe = self.make_recipe(
{},
'test',
{
'url': 'file://%s/testdata/package-0.0.0.tar.gz' % os.path.dirname(__file__),
'cleanup': 'foo/*'
}
)
os.mkdir(recipe.options.get('prefix'))
os.chdir(recipe.options.get('prefix'))
os.mkdir('foo')
tmp = open('foo/bar', 'a')
tmp = open('foo/barz', 'a')
self.assertTrue(os.path.exists('foo/bar'))
self.assertTrue(os.path.exists('foo/barz'))
recipe.install()
self.assertFalse(os.path.exists('foo/bar'))
self.assertFalse(os.path.exists('foo/barz'))
def test_cleanup_fails_when_file_does_not_exist(self): def test_cleanup_fails_when_file_does_not_exist(self):
os.chdir(self.dir)
recipe = self.make_recipe( recipe = self.make_recipe(
{}, {},
'test', 'test',
...@@ -335,12 +358,12 @@ class NonInformativeTests(unittest.TestCase): ...@@ -335,12 +358,12 @@ class NonInformativeTests(unittest.TestCase):
'cleanup': 'foo' 'cleanup': 'foo'
} }
) )
os.chdir(self.dir) self.assertFalse(os.path.exists(os.path.join(self.dir, 'foo')))
self.assertFalse(os.path.exists('foo'))
with self.assertRaises(IOError): with self.assertRaises(IOError):
recipe.install() recipe.install()
def test_cleanup_fails_when_file_is_out_of_reach(self): def test_cleanup_fails_when_file_is_out_of_reach(self):
os.chdir(self.dir)
recipe = self.make_recipe( recipe = self.make_recipe(
{}, {},
'test', 'test',
...@@ -349,12 +372,24 @@ class NonInformativeTests(unittest.TestCase): ...@@ -349,12 +372,24 @@ class NonInformativeTests(unittest.TestCase):
'cleanup': '/tmp/foo' 'cleanup': '/tmp/foo'
} }
) )
os.chdir(self.dir)
open('/tmp/foo', 'a') open('/tmp/foo', 'a')
self.assertTrue(os.path.exists('/tmp/foo')) self.assertTrue(os.path.exists('/tmp/foo'))
with self.assertRaises(IOError): with self.assertRaises(IOError):
recipe.install() recipe.install()
def test_cleanup_fails_when_unmatched_glob(self):
os.chdir(self.dir)
pattern = '/tmp/foo/trololol*'
recipe = self.make_recipe({}, 'test',
{
'url': 'file://%s/testdata/package-0.0.0.tar.gz' % os.path.dirname(__file__),
'cleanup': pattern
}
)
self.assertEqual(glob.glob(pattern), [])
with self.assertRaises(IOError):
recipe.install()
def test_suite(): def test_suite():
suite = unittest.TestSuite(( suite = unittest.TestSuite((
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment