Fix git-related commands not working in worktrees
If spack is checked out in a git worktree (see [1]), all git-related commands fail because the `spack_is_git_repo()`-check is not thorough enough. When developing in a feature-branch in a seperate worktree, this is annoying as all unittests regarding git-related spack commands fail, cluttering the test results with false-positives. [1]: https://git-scm.com/docs/git-worktree Change-Id: I94b573a2c0e058e9ccc169e7ee6561626fbb06fd
This commit is contained in:
parent
dea5d913db
commit
1cff717ca8
@ -9,6 +9,7 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
import ruamel.yaml as yaml
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@ -16,7 +17,7 @@
|
|||||||
from llnl.util.lang import attr_setdefault, index_by
|
from llnl.util.lang import attr_setdefault, index_by
|
||||||
from llnl.util.tty.colify import colify
|
from llnl.util.tty.colify import colify
|
||||||
from llnl.util.tty.color import colorize
|
from llnl.util.tty.color import colorize
|
||||||
from llnl.util.filesystem import working_dir
|
from llnl.util.filesystem import join_path
|
||||||
|
|
||||||
import spack.config
|
import spack.config
|
||||||
import spack.error
|
import spack.error
|
||||||
@ -26,6 +27,7 @@
|
|||||||
import spack.store
|
import spack.store
|
||||||
import spack.util.spack_json as sjson
|
import spack.util.spack_json as sjson
|
||||||
import spack.util.string
|
import spack.util.string
|
||||||
|
from ruamel.yaml.error import MarkedYAMLError
|
||||||
|
|
||||||
|
|
||||||
# cmd has a submodule called "list" so preserve the python list module
|
# cmd has a submodule called "list" so preserve the python list module
|
||||||
@ -433,8 +435,23 @@ def format_list(specs):
|
|||||||
|
|
||||||
def spack_is_git_repo():
|
def spack_is_git_repo():
|
||||||
"""Ensure that this instance of Spack is a git clone."""
|
"""Ensure that this instance of Spack is a git clone."""
|
||||||
with working_dir(spack.paths.prefix):
|
return is_git_repo(spack.paths.prefix)
|
||||||
return os.path.isdir('.git')
|
|
||||||
|
|
||||||
|
def is_git_repo(path):
|
||||||
|
dotgit_path = join_path(path, '.git')
|
||||||
|
if os.path.isdir(dotgit_path):
|
||||||
|
# we are in a regular git repo
|
||||||
|
return True
|
||||||
|
if os.path.isfile(dotgit_path):
|
||||||
|
# we might be in a git worktree
|
||||||
|
try:
|
||||||
|
with open(dotgit_path, "rb") as f:
|
||||||
|
dotgit_content = yaml.load(f)
|
||||||
|
return os.path.isdir(dotgit_content.get("gitdir", dotgit_path))
|
||||||
|
except MarkedYAMLError:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PythonNameError(spack.error.SpackError):
|
class PythonNameError(spack.error.SpackError):
|
||||||
|
67
lib/spack/spack/test/cmd/is_git_repo.py
Normal file
67
lib/spack/spack/test/cmd/is_git_repo.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import spack
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from llnl.util.filesystem import mkdirp
|
||||||
|
|
||||||
|
from spack.util.executable import which
|
||||||
|
from spack.version import ver
|
||||||
|
|
||||||
|
|
||||||
|
git = which("git")
|
||||||
|
git_required_version = '2.17.0'
|
||||||
|
|
||||||
|
|
||||||
|
def check_git_version():
|
||||||
|
"""Check if git version is new enough for worktree functionality.
|
||||||
|
Return True if requirements are met.
|
||||||
|
|
||||||
|
The latest required functionality is `worktree remove` which was only added
|
||||||
|
in 2.17.0.
|
||||||
|
|
||||||
|
Refer:
|
||||||
|
https://github.com/git/git/commit/cc73385cf6c5c229458775bc92e7dbbe24d11611
|
||||||
|
"""
|
||||||
|
git_version = ver(git('--version', output=str).lstrip('git version '))
|
||||||
|
return git_version >= ver(git_required_version)
|
||||||
|
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.skipif(
|
||||||
|
not git or not check_git_version(),
|
||||||
|
reason="we need git to test if we are in a git repo"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def git_tmp_worktree(tmpdir):
|
||||||
|
"""Create new worktree in a temporary folder and monkeypatch
|
||||||
|
spack.paths.prefix to point to it.
|
||||||
|
"""
|
||||||
|
worktree_root = str(tmpdir.join("tmp_worktree"))
|
||||||
|
mkdirp(worktree_root)
|
||||||
|
|
||||||
|
git("worktree", "add", "--detach", worktree_root, "HEAD")
|
||||||
|
|
||||||
|
yield worktree_root
|
||||||
|
|
||||||
|
git("worktree", "remove", "--force", worktree_root)
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_git_repo_in_worktree(git_tmp_worktree):
|
||||||
|
"""Verify that spack.cmd.spack_is_git_repo() can identify a git repository
|
||||||
|
in a worktree.
|
||||||
|
"""
|
||||||
|
assert spack.cmd.is_git_repo(git_tmp_worktree)
|
||||||
|
|
||||||
|
|
||||||
|
def test_spack_is_git_repo_nongit(tmpdir, monkeypatch):
|
||||||
|
"""Verify that spack.cmd.spack_is_git_repo() correctly returns False if we
|
||||||
|
are in a non-git directory.
|
||||||
|
"""
|
||||||
|
assert not spack.cmd.is_git_repo(str(tmpdir))
|
Loading…
Reference in New Issue
Block a user