diff --git a/asv/plugins/git.py b/asv/plugins/git.py index eae450515..891aaaa13 100644 --- a/asv/plugins/git.py +++ b/asv/plugins/git.py @@ -64,7 +64,13 @@ def _run_git(self, args, cwd=True, **kwargs): if cwd is True: cwd = self._path kwargs['cwd'] = cwd - return util.check_output([self._git] + args, **kwargs) + env = dict(kwargs.pop('env', os.environ)) + if cwd is not None: + prev = env.get('GIT_CEILING_DIRECTORIES') + env['GIT_CEILING_DIRECTORIES'] = os.pathsep.join( + [os.path.join(os.path.abspath(cwd), os.pardir)] + + ([prev] if prev is not None else [])) + return util.check_output([self._git] + args, env=env, **kwargs) def get_new_range_spec(self, latest_result, branch=None): return '{0}..{1}'.format(latest_result, self.get_branch_name(branch)) diff --git a/asv/util.py b/asv/util.py index 0108a591c..e1c147a2f 100644 --- a/asv/util.py +++ b/asv/util.py @@ -422,6 +422,12 @@ def get_content(header=None): log.debug("Running '{0}'".format(' '.join(args))) + if env and WIN and sys.version_info < (3,): + # Environment keys and values cannot be unicode + def _fix_env(s): + return s.encode('mbcs') if isinstance(s, unicode) else s + env = {_fix_env(k): _fix_env(v) for k, v in env.items()} + kwargs = dict(shell=shell, env=env, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if WIN: diff --git a/test/test_repo.py b/test/test_repo.py index 974d63282..88a498c20 100644 --- a/test/test_repo.py +++ b/test/test_repo.py @@ -397,3 +397,40 @@ def test_git_submodule(tmpdir): r.checkout(checkout_dir, commit_hash_5) assert os.path.isfile(join(checkout_dir, 'README')) assert not os.path.isdir(join(checkout_dir, 'sub1')) + + +@pytest.mark.parametrize('dvcs_type', [ + "git", + pytest.mark.skipif(hglib is None, reason="needs hglib")("hg") +]) +def test_root_ceiling(dvcs_type, tmpdir): + # Check that git/hg does not try to look for repository in parent + # directories. + tmpdir = six.text_type(tmpdir) + dvcs1 = tools.generate_repo_from_ops(tmpdir, dvcs_type, [("commit", 1)]) + dvcs2 = tools.generate_repo_from_ops(tmpdir, dvcs_type, [("commit", 2)]) + commit1 = dvcs1.get_branch_hashes()[0] + commit2 = dvcs2.get_branch_hashes()[0] + + conf = config.Config() + conf.branches = [] + conf.dvcs = dvcs_type + conf.project = join(tmpdir, "repo") + conf.repo = dvcs1.path + + r = repo.get_repo(conf) + + # Checkout into a subdir inside another repository + workcopy_dir = join(dvcs2.path, "workcopy") + r.checkout(workcopy_dir, commit1) + + # Corrupt the checkout + for pth in ['.hg', '.git']: + pth = os.path.join(workcopy_dir, pth) + if os.path.isdir(pth): + shutil.rmtree(pth) + + # Operation must fail (commit2 is not in dvcs1), not use the + # parent repository + with pytest.raises(Exception): + r.checkout(workcopy_dir, commit2) diff --git a/test/test_subprocess.py b/test/test_subprocess.py index 857dcc7fd..70971b74d 100644 --- a/test/test_subprocess.py +++ b/test/test_subprocess.py @@ -4,6 +4,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) +import os import sys import time @@ -104,6 +105,20 @@ def test_output_timeout(): assert False, "Expected exception" +def test_env(): + code = r""" +import os +print(os.environ['TEST_ASV_FOO']) +print(os.environ['TEST_ASV_BAR']) +""" + env = os.environ.copy() + env['TEST_ASV_FOO'] = 'foo' + # Force unicode string on Python 2 + env['TEST_ASV_BAR'] = u'bar' + output = util.check_output([sys.executable, "-c", code], env=env) + assert output.splitlines() == ['foo', 'bar'] + + # This *does* seem to work, only seems untestable somehow... # def test_dots(capsys): # code = r"""