Align our cwd tracking with os

This commit is contained in:
Mike McLean 2024-02-13 13:32:48 -05:00 committed by Tomas Kopecek
parent 895d0cf8ec
commit e8ae18fcc8
2 changed files with 44 additions and 6 deletions

View file

@ -575,7 +575,6 @@ def _rmtree_nofork(path, logger=None):
if not stat.S_ISDIR(st.st_mode):
raise koji.GenericError("Not a directory: %s" % path)
dev = st.st_dev
new_cwd = os.path.abspath(path)
cwd = os.getcwd()
try:
@ -583,6 +582,11 @@ def _rmtree_nofork(path, logger=None):
while True:
try:
os.chdir(path)
new_cwd = os.getcwd()
# make sure we're where we think we are
if not os.path.samefile(new_cwd, path):
raise koji.GenericError('chdir to %s resulted in different cwd %s',
path, new_cwd)
except OSError as e:
if e.errno in (errno.ENOENT, errno.ESTALE):
# likely racing with another rmtree

View file

@ -1254,6 +1254,7 @@ class TestRmtree(unittest.TestCase):
self.listdir = mock.patch('os.listdir').start()
self.getcwd = mock.patch('os.getcwd').start()
self.isdir = mock.patch('stat.S_ISDIR').start()
self.samefile = mock.patch('os.path.samefile').start()
self._assert_cwd = mock.patch('koji.util._assert_cwd').start()
def tearDown(self):
@ -1285,17 +1286,18 @@ class TestRmtree(unittest.TestCase):
stat.st_dev = 'dev'
self.lstat.return_value = stat
self.isdir.return_value = True
self.getcwd.return_value = 'cwd'
path = self.dirname
self.getcwd.return_value = path
logger = mock.MagicMock()
self.assertEqual(koji.util._rmtree_nofork(path, logger), None)
self.chdir.assert_called_with('cwd')
result = koji.util._rmtree_nofork(path, logger)
self.assertEqual(result, None)
self.chdir.assert_called_with(path)
_rmtree.assert_called_once_with('dev', path, logger)
self.rmdir.assert_called_once_with(path)
@patch('koji.util._rmtree')
def test_rmtree_directory_scrub_failure(self, _rmtree):
@patch('koji.util._stripcwd')
def test_rmtree_directory_stripcwd_failure(self, stripcwd):
""" Tests that the koji.util._rmtree_nofork function returns a GeneralException
when the scrub of the files in the directory fails.
"""
@ -1304,12 +1306,44 @@ class TestRmtree(unittest.TestCase):
self.lstat.return_value = stat
self.isdir.return_value = True
self.getcwd.return_value = 'cwd'
stripcwd.side_effect = OSError('xyz')
logger = mock.MagicMock()
with self.assertRaises(OSError):
koji.util._rmtree('dev', 'cwd', logger)
@patch('koji.util._rmtree')
def test_rmtree_call_failure(self, _rmtree):
""" Tests that the koji.util._rmtree_nofork function returns a GeneralException
when the underlying _rmtree call fails
"""
stat = mock.MagicMock()
stat.st_dev = 'dev'
self.lstat.return_value = stat
self.isdir.return_value = True
self.getcwd.return_value = 'cwd'
path = self.dirname
_rmtree.side_effect = OSError('xyz')
with self.assertRaises(OSError):
koji.util._rmtree_nofork(path)
@patch('koji.util._rmtree')
def test_rmtree_getcwd_mismatch(self, _rmtree):
""" Tests that the koji.util._rmtree_nofork function returns a GeneralException
when getcwd disagrees with initial chdir
"""
stat = mock.MagicMock()
stat.st_dev = 'dev'
self.lstat.return_value = stat
self.isdir.return_value = True
self.getcwd.return_value = 'cwd'
path = self.dirname
self.samefile.return_value = False
with self.assertRaises(koji.GenericError):
koji.util._rmtree_nofork(path)
@patch('koji.util._stripcwd')
def test_rmtree_internal_empty(self, stripcwd):
dev = 'dev'