Fix #725 and #729. /tmp/pip-build issues #734

Merged
merged 16 commits into from Jan 26, 2013
Jump to file or symbol
Failed to load files and symbols.
+110 −2
Diff settings

Always

Just for now

View
@@ -5,7 +5,7 @@ News
Next Release
============
-Beta and final releases of 1.3 are planned for the end of 2012.
+Beta and final releases of 1.3 are planned for Feb 2013.
.. include:: ../CHANGES.txt
View
@@ -4,7 +4,9 @@
import site
import os
import tempfile
+import getpass
from pip.backwardcompat import get_python_lib
+import pip.exceptions
def running_under_virtualenv():
@@ -25,6 +27,31 @@ def virtualenv_no_global():
if running_under_virtualenv() and os.path.isfile(no_global_file):
return True
+def _get_build_prefix():
+ """ Returns a safe build_prefix """
+ path = os.path.join(tempfile.gettempdir(), 'pip-build-%s' % \
+ getpass.getuser())
+ if sys.platform == 'win32':
+ """ on windows(tested on 7) temp dirs are isolated """
+ return path
+ try:
+ os.mkdir(path)
+ except OSError:
+ file_uid = None
+ try:
+ fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW)
+ file_uid = os.fstat(fd).st_uid
+ os.close(fd)
+ except OSError:
+ file_uid = None
+ if file_uid != os.getuid():
+ msg = "The temporary folder for building (%s) is not owned by your user!" \
+ % path
+ print (msg)
+ print("pip will not work until the temporary folder is " + \
+ "either deleted or owned by your user account.")
+ raise pip.exceptions.InstallationError(msg)
+ return path
if running_under_virtualenv():
build_prefix = os.path.join(sys.prefix, 'build')
@@ -33,7 +60,7 @@ def virtualenv_no_global():
# Use tempfile to create a temporary folder for build
# Note: we are NOT using mkdtemp so we can have a consistent build dir
# Note: using realpath due to tmp dirs on OSX being symlinks
- build_prefix = os.path.realpath(os.path.join(tempfile.gettempdir(), 'pip-build'))
+ build_prefix = os.path.realpath(_get_build_prefix())
## FIXME: keep src in cwd for now (it is not a temporary folder)
try:
View
@@ -0,0 +1,81 @@
+"""
+locations.py tests
+
+"""
+import os
+import sys
+import shutil
+import tempfile
+import getpass
+from mock import Mock
+import pip
+
+class TestLocations:
+ def setup(self):
+ self.tempdir = tempfile.mkdtemp()
+ self.st_uid = 9999
+ self.username = "example"
+ self.patch()
+
+ def tearDown(self):
+ self.revert_patch()
+ shutil.rmtree(self.tempdir, ignore_errors=True)
+
+ def patch(self):
+ """ first store and then patch python methods pythons """
+ self.tempfile_gettempdir = tempfile.gettempdir
+ self.old_os_fstat = os.fstat
+ self.old_os_getuid = os.getuid
+ self.old_getpass_getuser = getpass.getuser
+
+ # now patch
+ tempfile.gettempdir = lambda : self.tempdir
+ getpass.getuser = lambda : self.username
+ os.getuid = lambda : self.st_uid
+ os.fstat = lambda fd : self.get_mock_fstat(fd)
+
+ def revert_patch(self):
+ """ revert the patches to python methods """
+ tempfile.gettempdir = self.tempfile_gettempdir
+ getpass.getuser = self.old_getpass_getuser
+ os.getuid = self.old_os_getuid
+ os.fstat = self.old_os_fstat
+
+ def get_mock_fstat(self, fd):
+ """ returns a basic mock fstat call result.
+ Currently only the st_uid attribute has been set.
+ """
+ result = Mock()
+ result.st_uid = self.st_uid
+ return result
+
+ def get_build_dir_location(self):
+ """ returns a string pointing to the
+ current build_prefix.
+ """
+ return os.path.join(self.tempdir, 'pip-build-%s' % self.username)
+
+ def test_dir_created(self):
+ """ test that the build_prefix directory is generated when
+ _get_build_prefix is called.
+ """
+
+ assert not os.path.exists(self.get_build_dir_location() ), \
+ "the build_prefix directory should not exist yet!"
+ from pip import locations
+ locations._get_build_prefix()
+ assert os.path.exists(self.get_build_dir_location() ), \
+ "the build_prefix directory should now exist!"
+
+ def test_error_raised_when_owned_by_another(self):
+ """ test calling _get_build_prefix when there is a temporary
+ directory owned by another user raises an InstallationError.
+ """
+ from pip import locations
+ os.getuid = lambda : 1111
+ os.mkdir(self.get_build_dir_location() )
+ try:
+ locations._get_build_prefix()
+ raise AssertionError("An InstallationError should have been raised!")
+ except pip.exceptions.InstallationError:
+ pass