xonsh/tests/prompt/test_vc.py
Andy Kipp 059fc301e7
Introduce new resolver for executables to replace commands_cache usages and speed up everything (#5544)
* remove commands_cache from pyghooks to avoid cc.update_cache on every key press

* create executables.py

* replace cc.locate_binary to locate_executable

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* vc: replace locate_binary

* pyghooks: remove commands_cache

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* remove unused func _yield_executables

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Move `executables_in` from tools to commands_cache to avoid circular imports.

* First steps to `procs.executables` that is based on `commands_cache` and `tools`.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* test_executables

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* add not recommended notes

* tests

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add `get_paths` with test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix source test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* vc: remove tests because commands cache is not used

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* specs: fix exception for recursive call

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* specs: fix exception for recursive call

* improve test_locate_executable

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix test

* beautify pathext

* tests

* docs

* tests

* update locators

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* locate_file

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* comments

* return environ locate bin test

* comments

* Update xonsh/procs/executables.py

Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>

* Update xonsh/procs/executables.py

Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>

* Update xonsh/procs/executables.py

Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* add itertools

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* moving is_executable

* doc

* optimization is_executable_in_windows

* micro improvements

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* news

* news

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* bump test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: a <1@1.1>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
2024-07-09 09:44:03 +02:00

150 lines
4.2 KiB
Python

import os
import subprocess as sp
import textwrap
from pathlib import Path
import pytest
from xonsh.prompt import vc
# Xonsh interaction with version control systems.
VC_BRANCH = {
"git": {"master", "main"},
"hg": {"default"},
"fossil": {"trunk"},
}
VC_INIT: dict[str, list[list[str]]] = {
# A sequence of commands required to initialize a repository
"git": [["init"]],
"hg": [["init"]],
# Fossil "init" creates a central repository file with the given name,
# "open" creates the working directory at another, arbitrary location.
"fossil": [["init", "test.fossil"], ["open", "test.fossil"]],
}
@pytest.fixture(params=VC_BRANCH.keys())
def repo(request, tmpdir_factory):
"""Return a dict with vc and a temporary dir
that is a repository for testing.
"""
vc = request.param
temp_dir = Path(tmpdir_factory.mktemp("dir"))
os.chdir(temp_dir)
try:
for init_command in VC_INIT[vc]:
sp.call([vc] + init_command)
except FileNotFoundError:
pytest.skip(f"cannot find {vc} executable")
if vc == "git":
_init_git_repository(temp_dir)
return {"vc": vc, "dir": temp_dir}
def _init_git_repository(temp_dir):
git_config = temp_dir / ".git/config"
git_config.write_text(
textwrap.dedent(
"""\
[user]
name = me
email = my@email.address
[init]
defaultBranch = main
"""
)
)
# git needs at least one commit
Path("test-file").touch()
sp.call(["git", "add", "test-file"])
sp.call(["git", "commit", "-m", "test commit"])
@pytest.fixture
def set_xenv(xession, monkeypatch):
def _wrapper(path):
xession.env.update(dict(VC_BRANCH_TIMEOUT=2, PWD=path))
return xession
return _wrapper
def test_test_repo(repo):
if repo["vc"] == "fossil":
# Fossil stores the check-out meta-data in a special file within the open check-out.
# At least one of these below must exist
metadata_file_names = {
".fslckout",
"_FOSSIL_",
} # .fslckout on Unix, _FOSSIL_ on Windows
existing_files = {file.name for file in repo["dir"].iterdir()}
assert existing_files.intersection(metadata_file_names)
else:
test_vc_dir = repo["dir"] / ".{}".format(repo["vc"])
assert test_vc_dir.is_dir()
if repo["vc"] == "git":
test_file = repo["dir"] / "test-file"
assert test_file.exists()
def test_no_repo(tmpdir, set_xenv):
set_xenv(tmpdir)
assert vc.get_hg_branch() is None
assert vc.get_git_branch() is None
def test_vc_get_branch(repo, set_xenv):
set_xenv(repo["dir"])
# get corresponding function from vc module
get_branch = "get_{}_branch".format(repo["vc"])
branch = getattr(vc, get_branch)()
assert branch in VC_BRANCH[repo["vc"]]
if repo["vc"] == "git":
git_config = repo["dir"] / ".git/config"
with git_config.open("a") as f:
f.write(
"""
[color]
branch = always
interactive = always
[color "branch"]
current = yellow reverse
"""
)
branch = getattr(vc, get_branch)()
assert branch in VC_BRANCH[repo["vc"]]
assert not branch.startswith("\u001b[")
def test_dirty_working_directory(repo, set_xenv):
get_dwd = "{}_dirty_working_directory".format(repo["vc"])
set_xenv(repo["dir"])
# By default, git / hg do not care about untracked files
Path("second-test-file").touch()
assert not getattr(vc, get_dwd)()
sp.call([repo["vc"], "add", "second-test-file"])
assert getattr(vc, get_dwd)()
@pytest.mark.parametrize("include_untracked", [True, False])
def test_git_dirty_working_directory_includes_untracked(
xession, fake_process, include_untracked
):
xession.env["VC_GIT_INCLUDE_UNTRACKED"] = include_untracked
if include_untracked:
fake_process.register_subprocess(
command="git status --porcelain --untracked-files=normal".split(),
stdout=b"?? untracked-test-file",
)
else:
fake_process.register_subprocess(
command="git status --porcelain --untracked-files=no".split(),
stdout=b"",
)
assert vc.git_dirty_working_directory() == include_untracked