feat: add ability to suppress git hints

It can be done by setting options in command. The commit author/email is
also now using this logic
This commit is contained in:
Evgenii Alekseev 2024-08-22 18:17:56 +03:00
parent 1eb4d8e47f
commit d1ad5ecc11
5 changed files with 117 additions and 80 deletions

View File

@ -82,6 +82,7 @@ limit-inference-results=100
# List of plugins (as comma separated values of python module names) to load, # List of plugins (as comma separated values of python module names) to load,
# usually to register additional checkers. # usually to register additional checkers.
load-plugins=pylint.extensions.docparams, load-plugins=pylint.extensions.docparams,
pylint.extensions.bad_builtin,
definition_order, definition_order,
import_order, import_order,
@ -131,6 +132,8 @@ attr-naming-style=snake_case
# style. # style.
#attr-rgx= #attr-rgx=
bad-functions=print,
# Bad variable names which should always be refused, separated by a comma. # Bad variable names which should always be refused, separated by a comma.
bad-names=foo, bad-names=foo,
bar, bar,

View File

@ -98,6 +98,7 @@ class Patch(Handler):
PkgbuildPatch: created patch for the PKGBUILD function PkgbuildPatch: created patch for the PKGBUILD function
""" """
if patch_path is None: if patch_path is None:
# pylint: disable=bad-builtin
print("Post new function or variable value below. Press Ctrl-D to finish:", file=sys.stderr) print("Post new function or variable value below. Press Ctrl-D to finish:", file=sys.stderr)
patch = "".join(list(sys.stdin)) patch = "".join(list(sys.stdin))
else: else:

View File

@ -77,5 +77,5 @@ class Update(Handler):
Callable[[str], None]: in case if dry_run is set it will return print, logger otherwise Callable[[str], None]: in case if dry_run is set it will return print, logger otherwise
""" """
def inner(line: str) -> None: def inner(line: str) -> None:
return print(line) if dry_run else application.logger.info(line) return print(line) if dry_run else application.logger.info(line) # pylint: disable=bad-builtin
return inner return inner

View File

@ -19,6 +19,7 @@
# #
import shutil import shutil
from collections.abc import Generator
from pathlib import Path from pathlib import Path
from ahriman.core.exceptions import CalledProcessError from ahriman.core.exceptions import CalledProcessError
@ -38,10 +39,14 @@ class Sources(LazyLogging):
DEFAULT_BRANCH(str): (class attribute) default branch to process git repositories. DEFAULT_BRANCH(str): (class attribute) default branch to process git repositories.
Must be used only for local stored repositories, use RemoteSource descriptor instead for real packages Must be used only for local stored repositories, use RemoteSource descriptor instead for real packages
DEFAULT_COMMIT_AUTHOR(tuple[str, str]): (class attribute) default commit author to be used if none set DEFAULT_COMMIT_AUTHOR(tuple[str, str]): (class attribute) default commit author to be used if none set
GITCONFIG(dict[str, str]): (class attribute) git config options to suppress annoying hints
""" """
DEFAULT_BRANCH = "master" # default fallback branch DEFAULT_BRANCH = "master" # default fallback branch
DEFAULT_COMMIT_AUTHOR = ("ahriman", "ahriman@localhost") DEFAULT_COMMIT_AUTHOR = ("ahriman", "ahriman@localhost")
GITCONFIG = {
"init.defaultBranch": DEFAULT_BRANCH,
}
@staticmethod @staticmethod
def changes(source_dir: Path, last_commit_sha: str | None) -> str | None: def changes(source_dir: Path, last_commit_sha: str | None) -> str | None:
@ -106,15 +111,15 @@ class Sources(LazyLogging):
instance.fetch_until(sources_dir, branch=branch) instance.fetch_until(sources_dir, branch=branch)
elif remote.git_url is not None: elif remote.git_url is not None:
instance.logger.info("clone remote %s to %s using branch %s", remote.git_url, sources_dir, branch) instance.logger.info("clone remote %s to %s using branch %s", remote.git_url, sources_dir, branch)
check_output("git", "clone", "--quiet", "--depth", "1", "--branch", branch, "--single-branch", check_output(*instance.git(), "clone", "--quiet", "--depth", "1", "--branch", branch, "--single-branch",
remote.git_url, str(sources_dir), cwd=sources_dir.parent, logger=instance.logger) remote.git_url, str(sources_dir), cwd=sources_dir.parent, logger=instance.logger)
else: else:
# it will cause an exception later # it will cause an exception later
instance.logger.error("%s is not initialized, but no remote provided", sources_dir) instance.logger.error("%s is not initialized, but no remote provided", sources_dir)
# and now force reset to our branch # and now force reset to our branch
check_output("git", "checkout", "--force", branch, cwd=sources_dir, logger=instance.logger) check_output(*instance.git(), "checkout", "--force", branch, cwd=sources_dir, logger=instance.logger)
check_output("git", "reset", "--quiet", "--hard", f"origin/{branch}", check_output(*instance.git(), "reset", "--quiet", "--hard", f"origin/{branch}",
cwd=sources_dir, logger=instance.logger) cwd=sources_dir, logger=instance.logger)
# move content if required # move content if required
@ -136,7 +141,7 @@ class Sources(LazyLogging):
bool: True in case if there is any remote and false otherwise bool: True in case if there is any remote and false otherwise
""" """
instance = Sources() instance = Sources()
remotes = check_output("git", "remote", cwd=sources_dir, logger=instance.logger) remotes = check_output(*instance.git(), "remote", cwd=sources_dir, logger=instance.logger)
return bool(remotes) return bool(remotes)
@staticmethod @staticmethod
@ -150,7 +155,7 @@ class Sources(LazyLogging):
instance = Sources() instance = Sources()
if not (sources_dir / ".git").is_dir(): if not (sources_dir / ".git").is_dir():
# skip initializing in case if it was already # skip initializing in case if it was already
check_output("git", "init", "--quiet", "--initial-branch", instance.DEFAULT_BRANCH, check_output(*instance.git(), "init", "--quiet", "--initial-branch", instance.DEFAULT_BRANCH,
cwd=sources_dir, logger=instance.logger) cwd=sources_dir, logger=instance.logger)
# extract local files... # extract local files...
@ -220,7 +225,7 @@ class Sources(LazyLogging):
return # no changes to push, just skip action return # no changes to push, just skip action
git_url, branch = remote.git_source() git_url, branch = remote.git_source()
check_output("git", "push", "--quiet", git_url, branch, cwd=sources_dir, logger=instance.logger) check_output(*instance.git(), "push", "--quiet", git_url, branch, cwd=sources_dir, logger=instance.logger)
def add(self, sources_dir: Path, *pattern: str, intent_to_add: bool = False) -> None: def add(self, sources_dir: Path, *pattern: str, intent_to_add: bool = False) -> None:
""" """
@ -241,7 +246,7 @@ class Sources(LazyLogging):
self.logger.info("found matching files %s", found_files) self.logger.info("found matching files %s", found_files)
# add them to index # add them to index
args = ["--intent-to-add"] if intent_to_add else [] args = ["--intent-to-add"] if intent_to_add else []
check_output("git", "add", *args, *[str(fn.relative_to(sources_dir)) for fn in found_files], check_output(*self.git(), "add", *args, *[str(fn.relative_to(sources_dir)) for fn in found_files],
cwd=sources_dir, logger=self.logger) cwd=sources_dir, logger=self.logger)
def commit(self, sources_dir: Path, message: str | None = None, def commit(self, sources_dir: Path, message: str | None = None,
@ -264,15 +269,16 @@ class Sources(LazyLogging):
if message is None: if message is None:
message = f"Autogenerated commit at {utcnow()}" message = f"Autogenerated commit at {utcnow()}"
args = ["--message", message] args = ["--message", message]
environment: dict[str, str] = {}
if commit_author is None: if commit_author is None:
commit_author = self.DEFAULT_COMMIT_AUTHOR commit_author = self.DEFAULT_COMMIT_AUTHOR
user, email = commit_author user, email = commit_author
environment["GIT_AUTHOR_NAME"] = environment["GIT_COMMITTER_NAME"] = user gitconfig = {
environment["GIT_AUTHOR_EMAIL"] = environment["GIT_COMMITTER_EMAIL"] = email "user.email": email,
"user.name": user,
}
check_output("git", "commit", "--quiet", *args, cwd=sources_dir, logger=self.logger, environment=environment) check_output(*self.git(gitconfig), "commit", "--quiet", *args, cwd=sources_dir, logger=self.logger)
return True return True
@ -290,7 +296,7 @@ class Sources(LazyLogging):
args = [] args = []
if sha is not None: if sha is not None:
args.append(sha) args.append(sha)
return check_output("git", "diff", *args, cwd=sources_dir, logger=self.logger) return check_output(*self.git(), "diff", *args, cwd=sources_dir, logger=self.logger)
def fetch_until(self, sources_dir: Path, *, branch: str | None = None, commit_sha: str | None = None) -> None: def fetch_until(self, sources_dir: Path, *, branch: str | None = None, commit_sha: str | None = None) -> None:
""" """
@ -306,18 +312,37 @@ class Sources(LazyLogging):
commits_count = 1 commits_count = 1
while commit_sha is not None: while commit_sha is not None:
command = ["git", "fetch", "--quiet", "--depth", str(commits_count)] command = self.git() + ["fetch", "--quiet", "--depth", str(commits_count)]
if branch is not None: if branch is not None:
command += ["origin", branch] command += ["origin", branch]
check_output(*command, cwd=sources_dir, logger=self.logger) # fetch one more level check_output(*command, cwd=sources_dir, logger=self.logger) # fetch one more level
try: try:
# check if there is an object in current git directory # check if there is an object in current git directory
check_output("git", "cat-file", "-e", commit_sha, cwd=sources_dir, logger=self.logger) check_output(*self.git(), "cat-file", "-e", commit_sha, cwd=sources_dir, logger=self.logger)
commit_sha = None # reset search commit_sha = None # reset search
except CalledProcessError: except CalledProcessError:
commits_count += 1 # increase depth commits_count += 1 # increase depth
def git(self, gitconfig: dict[str, str] | None = None) -> list[str]:
"""
git command prefix
Args:
gitconfig(dict[str, str] | None, optional): additional git config flags if any (Default value = None)
Returns:
list[str]: git command prefix with valid default flags
"""
gitconfig = gitconfig or {}
def configuration_flags() -> Generator[str, None, None]:
for option, value in (self.GITCONFIG | gitconfig).items():
yield "-c"
yield f"{option}=\"{value}\""
return ["git"] + list(configuration_flags())
def has_changes(self, sources_dir: Path) -> bool: def has_changes(self, sources_dir: Path) -> bool:
""" """
check if there are changes in current git tree check if there are changes in current git tree
@ -329,7 +354,7 @@ class Sources(LazyLogging):
bool: True if there are uncommitted changes and False otherwise bool: True if there are uncommitted changes and False otherwise
""" """
# there is --exit-code argument to diff, however, there might be other process errors # there is --exit-code argument to diff, however, there might be other process errors
changes = check_output("git", "diff", "--cached", "--name-only", cwd=sources_dir, logger=self.logger) changes = check_output(*self.git(), "diff", "--cached", "--name-only", cwd=sources_dir, logger=self.logger)
return bool(changes) return bool(changes)
def head(self, sources_dir: Path, ref_name: str = "HEAD") -> str: def head(self, sources_dir: Path, ref_name: str = "HEAD") -> str:
@ -344,7 +369,7 @@ class Sources(LazyLogging):
str: HEAD commit hash str: HEAD commit hash
""" """
# we might want to parse git files instead though # we might want to parse git files instead though
return check_output("git", "rev-parse", ref_name, cwd=sources_dir, logger=self.logger) return check_output(*self.git(), "rev-parse", ref_name, cwd=sources_dir, logger=self.logger)
def move(self, pkgbuild_dir: Path, sources_dir: Path) -> None: def move(self, pkgbuild_dir: Path, sources_dir: Path) -> None:
""" """
@ -372,7 +397,7 @@ class Sources(LazyLogging):
# create patch # create patch
self.logger.info("apply patch %s from database at %s", patch.key, sources_dir) self.logger.info("apply patch %s from database at %s", patch.key, sources_dir)
if patch.is_plain_diff: if patch.is_plain_diff:
check_output("git", "apply", "--ignore-space-change", "--ignore-whitespace", check_output(*self.git(), "apply", "--ignore-space-change", "--ignore-whitespace",
cwd=sources_dir, input_data=patch.serialize(), logger=self.logger) cwd=sources_dir, input_data=patch.serialize(), logger=self.logger)
else: else:
patch.write(sources_dir / "PKGBUILD") patch.write(sources_dir / "PKGBUILD")

View File

@ -74,7 +74,7 @@ def test_fetch_empty(remote_source: RemoteSource, mocker: MockerFixture) -> None
check_output_mock.assert_not_called() check_output_mock.assert_not_called()
def test_fetch_existing(remote_source: RemoteSource, mocker: MockerFixture) -> None: def test_fetch_existing(sources: Sources, remote_source: RemoteSource, mocker: MockerFixture) -> None:
""" """
must fetch new package via fetch command must fetch new package via fetch command
""" """
@ -86,18 +86,19 @@ def test_fetch_existing(remote_source: RemoteSource, mocker: MockerFixture) -> N
head_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.head", return_value="sha") head_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.head", return_value="sha")
local = Path("local") local = Path("local")
assert Sources.fetch(local, remote_source) == "sha" assert sources.fetch(local, remote_source) == "sha"
fetch_mock.assert_called_once_with(local, branch=remote_source.branch) fetch_mock.assert_called_once_with(local, branch=remote_source.branch)
check_output_mock.assert_has_calls([ check_output_mock.assert_has_calls([
MockCall("git", "checkout", "--force", remote_source.branch, cwd=local, logger=pytest.helpers.anyvar(int)), MockCall(*sources.git(), "checkout", "--force", remote_source.branch,
MockCall("git", "reset", "--quiet", "--hard", f"origin/{remote_source.branch}", cwd=local, logger=pytest.helpers.anyvar(int)),
MockCall(*sources.git(), "reset", "--quiet", "--hard", f"origin/{remote_source.branch}",
cwd=local, logger=pytest.helpers.anyvar(int)), cwd=local, logger=pytest.helpers.anyvar(int)),
]) ])
move_mock.assert_called_once_with(local.resolve(), local) move_mock.assert_called_once_with(local.resolve(), local)
head_mock.assert_called_once_with(local) head_mock.assert_called_once_with(local)
def test_fetch_new(remote_source: RemoteSource, mocker: MockerFixture) -> None: def test_fetch_new(sources: Sources, remote_source: RemoteSource, mocker: MockerFixture) -> None:
""" """
must fetch new package via clone command must fetch new package via clone command
""" """
@ -107,19 +108,21 @@ def test_fetch_new(remote_source: RemoteSource, mocker: MockerFixture) -> None:
head_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.head", return_value="sha") head_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.head", return_value="sha")
local = Path("local") local = Path("local")
assert Sources.fetch(local, remote_source) == "sha" assert sources.fetch(local, remote_source) == "sha"
check_output_mock.assert_has_calls([ check_output_mock.assert_has_calls([
MockCall("git", "clone", "--quiet", "--depth", "1", "--branch", remote_source.branch, "--single-branch", MockCall(*sources.git(), "clone", "--quiet", "--depth", "1", "--branch", remote_source.branch,
remote_source.git_url, str(local), cwd=local.parent, logger=pytest.helpers.anyvar(int)), "--single-branch", remote_source.git_url, str(local),
MockCall("git", "checkout", "--force", remote_source.branch, cwd=local, logger=pytest.helpers.anyvar(int)), cwd=local.parent, logger=pytest.helpers.anyvar(int)),
MockCall("git", "reset", "--quiet", "--hard", f"origin/{remote_source.branch}", MockCall(*sources.git(), "checkout", "--force", remote_source.branch,
cwd=local, logger=pytest.helpers.anyvar(int)),
MockCall(*sources.git(), "reset", "--quiet", "--hard", f"origin/{remote_source.branch}",
cwd=local, logger=pytest.helpers.anyvar(int)) cwd=local, logger=pytest.helpers.anyvar(int))
]) ])
move_mock.assert_called_once_with(local.resolve(), local) move_mock.assert_called_once_with(local.resolve(), local)
head_mock.assert_called_once_with(local) head_mock.assert_called_once_with(local)
def test_fetch_new_without_remote(mocker: MockerFixture) -> None: def test_fetch_new_without_remote(sources: Sources, mocker: MockerFixture) -> None:
""" """
must fetch nothing in case if no remote set must fetch nothing in case if no remote set
""" """
@ -129,10 +132,11 @@ def test_fetch_new_without_remote(mocker: MockerFixture) -> None:
head_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.head", return_value="sha") head_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.head", return_value="sha")
local = Path("local") local = Path("local")
assert Sources.fetch(local, RemoteSource(source=PackageSource.Archive)) == "sha" assert sources.fetch(local, RemoteSource(source=PackageSource.Archive)) == "sha"
check_output_mock.assert_has_calls([ check_output_mock.assert_has_calls([
MockCall("git", "checkout", "--force", Sources.DEFAULT_BRANCH, cwd=local, logger=pytest.helpers.anyvar(int)), MockCall(*sources.git(), "checkout", "--force", sources.DEFAULT_BRANCH,
MockCall("git", "reset", "--quiet", "--hard", f"origin/{Sources.DEFAULT_BRANCH}", cwd=local, logger=pytest.helpers.anyvar(int)),
MockCall(*sources.git(), "reset", "--quiet", "--hard", f"origin/{sources.DEFAULT_BRANCH}",
cwd=local, logger=pytest.helpers.anyvar(int)) cwd=local, logger=pytest.helpers.anyvar(int))
]) ])
move_mock.assert_called_once_with(local.resolve(), local) move_mock.assert_called_once_with(local.resolve(), local)
@ -153,15 +157,15 @@ def test_fetch_relative(remote_source: RemoteSource, mocker: MockerFixture) -> N
head_mock.assert_called_once_with(local) head_mock.assert_called_once_with(local)
def test_has_remotes(mocker: MockerFixture) -> None: def test_has_remotes(sources: Sources, mocker: MockerFixture) -> None:
""" """
must ask for remotes must ask for remotes
""" """
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output", return_value="origin") check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output", return_value="origin")
local = Path("local") local = Path("local")
assert Sources.has_remotes(local) assert sources.has_remotes(local)
check_output_mock.assert_called_once_with("git", "remote", cwd=local, logger=pytest.helpers.anyvar(int)) check_output_mock.assert_called_once_with(*sources.git(), "remote", cwd=local, logger=pytest.helpers.anyvar(int))
def test_has_remotes_empty(mocker: MockerFixture) -> None: def test_has_remotes_empty(mocker: MockerFixture) -> None:
@ -172,7 +176,7 @@ def test_has_remotes_empty(mocker: MockerFixture) -> None:
assert not Sources.has_remotes(Path("local")) assert not Sources.has_remotes(Path("local"))
def test_init(mocker: MockerFixture) -> None: def test_init(sources: Sources, mocker: MockerFixture) -> None:
""" """
must create empty repository at the specified path must create empty repository at the specified path
""" """
@ -183,9 +187,9 @@ def test_init(mocker: MockerFixture) -> None:
commit_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.commit") commit_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.commit")
local = Path("local") local = Path("local")
Sources.init(local) sources.init(local)
check_output_mock.assert_called_once_with("git", "init", "--quiet", "--initial-branch", Sources.DEFAULT_BRANCH, check_output_mock.assert_called_once_with(*sources.git(), "init", "--quiet", "--initial-branch",
cwd=local, logger=pytest.helpers.anyvar(int)) sources.DEFAULT_BRANCH, cwd=local, logger=pytest.helpers.anyvar(int))
add_mock.assert_called_once_with(local, "PKGBUILD", ".SRCINFO", "local") add_mock.assert_called_once_with(local, "PKGBUILD", ".SRCINFO", "local")
commit_mock.assert_called_once_with(local) commit_mock.assert_called_once_with(local)
@ -267,7 +271,7 @@ def test_patch_create_with_newline(mocker: MockerFixture) -> None:
assert Sources.patch_create(Path("local"), "glob").endswith("\n") assert Sources.patch_create(Path("local"), "glob").endswith("\n")
def test_push(package_ahriman: Package, mocker: MockerFixture) -> None: def test_push(package_ahriman: Package, sources: Sources, mocker: MockerFixture) -> None:
""" """
must correctly push files to remote repository must correctly push files to remote repository
""" """
@ -277,11 +281,11 @@ def test_push(package_ahriman: Package, mocker: MockerFixture) -> None:
commit_author = ("commit author", "user@host") commit_author = ("commit author", "user@host")
local = Path("local") local = Path("local")
Sources.push(local, package_ahriman.remote, "glob", commit_author=commit_author) sources.push(local, package_ahriman.remote, "glob", commit_author=commit_author)
add_mock.assert_called_once_with(local, "glob") add_mock.assert_called_once_with(local, "glob")
commit_mock.assert_called_once_with(local, commit_author=commit_author) commit_mock.assert_called_once_with(local, commit_author=commit_author)
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"git", "push", "--quiet", package_ahriman.remote.git_url, package_ahriman.remote.branch, *sources.git(), "push", "--quiet", package_ahriman.remote.git_url, package_ahriman.remote.branch,
cwd=local, logger=pytest.helpers.anyvar(int)) cwd=local, logger=pytest.helpers.anyvar(int))
@ -308,7 +312,7 @@ def test_add(sources: Sources, mocker: MockerFixture) -> None:
sources.add(local, "pattern1", "pattern2") sources.add(local, "pattern1", "pattern2")
glob_mock.assert_has_calls([MockCall("pattern1"), MockCall("pattern2")]) glob_mock.assert_has_calls([MockCall("pattern1"), MockCall("pattern2")])
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"git", "add", "1", "2", "1", "2", cwd=local, logger=sources.logger *sources.git(), "add", "1", "2", "1", "2", cwd=local, logger=sources.logger
) )
@ -323,7 +327,7 @@ def test_add_intent_to_add(sources: Sources, mocker: MockerFixture) -> None:
sources.add(local, "pattern1", "pattern2", intent_to_add=True) sources.add(local, "pattern1", "pattern2", intent_to_add=True)
glob_mock.assert_has_calls([MockCall("pattern1"), MockCall("pattern2")]) glob_mock.assert_has_calls([MockCall("pattern1"), MockCall("pattern2")])
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"git", "add", "--intent-to-add", "1", "2", "1", "2", cwd=local, logger=sources.logger *sources.git(), "add", "--intent-to-add", "1", "2", "1", "2", cwd=local, logger=sources.logger
) )
@ -350,13 +354,8 @@ def test_commit(sources: Sources, mocker: MockerFixture) -> None:
user, email = sources.DEFAULT_COMMIT_AUTHOR user, email = sources.DEFAULT_COMMIT_AUTHOR
assert sources.commit(local, message=message) assert sources.commit(local, message=message)
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"git", "commit", "--quiet", "--message", message, *sources.git(), "-c", f"user.email=\"{email}\"", "-c", f"user.name=\"{user}\"",
cwd=local, logger=sources.logger, environment={ "commit", "--quiet", "--message", message, cwd=local, logger=sources.logger
"GIT_AUTHOR_NAME": user,
"GIT_AUTHOR_EMAIL": email,
"GIT_COMMITTER_NAME": user,
"GIT_COMMITTER_EMAIL": email,
}
) )
@ -383,13 +382,8 @@ def test_commit_author(sources: Sources, mocker: MockerFixture) -> None:
user, email = author = ("commit author", "user@host") user, email = author = ("commit author", "user@host")
assert sources.commit(Path("local"), message=message, commit_author=author) assert sources.commit(Path("local"), message=message, commit_author=author)
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"git", "commit", "--quiet", "--message", message, *sources.git(), "-c", f"user.email=\"{email}\"", "-c", f"user.name=\"{user}\"",
cwd=local, logger=sources.logger, environment={ "commit", "--quiet", "--message", message, cwd=local, logger=sources.logger
"GIT_AUTHOR_NAME": user,
"GIT_AUTHOR_EMAIL": email,
"GIT_COMMITTER_NAME": user,
"GIT_COMMITTER_EMAIL": email,
}
) )
@ -404,13 +398,8 @@ def test_commit_autogenerated_message(sources: Sources, mocker: MockerFixture) -
assert sources.commit(Path("local")) assert sources.commit(Path("local"))
user, email = sources.DEFAULT_COMMIT_AUTHOR user, email = sources.DEFAULT_COMMIT_AUTHOR
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"git", "commit", "--quiet", "--message", pytest.helpers.anyvar(str, strict=True), *sources.git(), "-c", f"user.email=\"{email}\"", "-c", f"user.name=\"{user}\"",
cwd=local, logger=sources.logger, environment={ "commit", "--quiet", "--message", pytest.helpers.anyvar(str, strict=True), cwd=local, logger=sources.logger
"GIT_AUTHOR_NAME": user,
"GIT_AUTHOR_EMAIL": email,
"GIT_COMMITTER_NAME": user,
"GIT_COMMITTER_EMAIL": email,
}
) )
@ -422,7 +411,7 @@ def test_diff(sources: Sources, mocker: MockerFixture) -> None:
local = Path("local") local = Path("local")
assert sources.diff(local) assert sources.diff(local)
check_output_mock.assert_called_once_with("git", "diff", cwd=local, logger=sources.logger) check_output_mock.assert_called_once_with(*sources.git(), "diff", cwd=local, logger=sources.logger)
def test_diff_specific(sources: Sources, mocker: MockerFixture) -> None: def test_diff_specific(sources: Sources, mocker: MockerFixture) -> None:
@ -433,7 +422,7 @@ def test_diff_specific(sources: Sources, mocker: MockerFixture) -> None:
local = Path("local") local = Path("local")
assert sources.diff(local, "hash") assert sources.diff(local, "hash")
check_output_mock.assert_called_once_with("git", "diff", "hash", cwd=local, logger=sources.logger) check_output_mock.assert_called_once_with(*sources.git(), "diff", "hash", cwd=local, logger=sources.logger)
def test_fetch_until(sources: Sources, mocker: MockerFixture) -> None: def test_fetch_until(sources: Sources, mocker: MockerFixture) -> None:
@ -450,10 +439,12 @@ def test_fetch_until(sources: Sources, mocker: MockerFixture) -> None:
local = Path("local") local = Path("local")
sources.fetch_until(local, branch="master", commit_sha="sha") sources.fetch_until(local, branch="master", commit_sha="sha")
check_output_mock.assert_has_calls([ check_output_mock.assert_has_calls([
MockCall("git", "fetch", "--quiet", "--depth", "1", "origin", "master", cwd=local, logger=sources.logger), MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", "origin", "master",
MockCall("git", "cat-file", "-e", "sha", cwd=local, logger=sources.logger), cwd=local, logger=sources.logger),
MockCall("git", "fetch", "--quiet", "--depth", "2", "origin", "master", cwd=local, logger=sources.logger), MockCall(*sources.git(), "cat-file", "-e", "sha", cwd=local, logger=sources.logger),
MockCall("git", "cat-file", "-e", "sha", cwd=local, logger=sources.logger), MockCall(*sources.git(), "fetch", "--quiet", "--depth", "2", "origin", "master",
cwd=local, logger=sources.logger),
MockCall(*sources.git(), "cat-file", "-e", "sha", cwd=local, logger=sources.logger),
]) ])
@ -466,8 +457,9 @@ def test_fetch_until_first(sources: Sources, mocker: MockerFixture) -> None:
local = Path("local") local = Path("local")
sources.fetch_until(local, branch="master") sources.fetch_until(local, branch="master")
check_output_mock.assert_has_calls([ check_output_mock.assert_has_calls([
MockCall("git", "fetch", "--quiet", "--depth", "1", "origin", "master", cwd=local, logger=sources.logger), MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", "origin", "master",
MockCall("git", "cat-file", "-e", "HEAD", cwd=local, logger=sources.logger), cwd=local, logger=sources.logger),
MockCall(*sources.git(), "cat-file", "-e", "HEAD", cwd=local, logger=sources.logger),
]) ])
@ -480,11 +472,27 @@ def test_fetch_until_all_branches(sources: Sources, mocker: MockerFixture) -> No
local = Path("local") local = Path("local")
sources.fetch_until(local) sources.fetch_until(local)
check_output_mock.assert_has_calls([ check_output_mock.assert_has_calls([
MockCall("git", "fetch", "--quiet", "--depth", "1", cwd=local, logger=sources.logger), MockCall(*sources.git(), "fetch", "--quiet", "--depth", "1", cwd=local, logger=sources.logger),
MockCall("git", "cat-file", "-e", "HEAD", cwd=local, logger=sources.logger), MockCall(*sources.git(), "cat-file", "-e", "HEAD", cwd=local, logger=sources.logger),
]) ])
def test_git(sources: Sources) -> None:
"""
must correctly generate git command
"""
assert sources.git() == ["git", "-c", "init.defaultBranch=\"master\""]
def test_git_overrides(sources: Sources) -> None:
"""
must correctly generate git command with additional settings
"""
assert sources.git({"user.email": "ahriman@localhost"}) == [
"git", "-c", "init.defaultBranch=\"master\"", "-c", "user.email=\"ahriman@localhost\""
]
def test_has_changes(sources: Sources, mocker: MockerFixture) -> None: def test_has_changes(sources: Sources, mocker: MockerFixture) -> None:
""" """
must correctly identify if there are changes must correctly identify if there are changes
@ -493,12 +501,12 @@ def test_has_changes(sources: Sources, mocker: MockerFixture) -> None:
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output", return_value="M a.txt") check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output", return_value="M a.txt")
assert sources.has_changes(local) assert sources.has_changes(local)
check_output_mock.assert_called_once_with("git", "diff", "--cached", "--name-only", check_output_mock.assert_called_once_with(*sources.git(), "diff", "--cached", "--name-only",
cwd=local, logger=sources.logger) cwd=local, logger=sources.logger)
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output", return_value="") check_output_mock = mocker.patch("ahriman.core.build_tools.sources.check_output", return_value="")
assert not sources.has_changes(local) assert not sources.has_changes(local)
check_output_mock.assert_called_once_with("git", "diff", "--cached", "--name-only", check_output_mock.assert_called_once_with(*sources.git(), "diff", "--cached", "--name-only",
cwd=local, logger=sources.logger) cwd=local, logger=sources.logger)
@ -510,7 +518,7 @@ def test_head(sources: Sources, mocker: MockerFixture) -> None:
local = Path("local") local = Path("local")
assert sources.head(local) == "sha" assert sources.head(local) == "sha"
check_output_mock.assert_called_once_with("git", "rev-parse", "HEAD", cwd=local, logger=sources.logger) check_output_mock.assert_called_once_with(*sources.git(), "rev-parse", "HEAD", cwd=local, logger=sources.logger)
def test_head_specific(sources: Sources, mocker: MockerFixture) -> None: def test_head_specific(sources: Sources, mocker: MockerFixture) -> None:
@ -521,7 +529,7 @@ def test_head_specific(sources: Sources, mocker: MockerFixture) -> None:
local = Path("local") local = Path("local")
assert sources.head(local, "master") == "sha" assert sources.head(local, "master") == "sha"
check_output_mock.assert_called_once_with("git", "rev-parse", "master", cwd=local, logger=sources.logger) check_output_mock.assert_called_once_with(*sources.git(), "rev-parse", "master", cwd=local, logger=sources.logger)
def test_move(sources: Sources, mocker: MockerFixture) -> None: def test_move(sources: Sources, mocker: MockerFixture) -> None:
@ -554,7 +562,7 @@ def test_patch_apply(sources: Sources, mocker: MockerFixture) -> None:
local = Path("local") local = Path("local")
sources.patch_apply(local, patch) sources.patch_apply(local, patch)
check_output_mock.assert_called_once_with( check_output_mock.assert_called_once_with(
"git", "apply", "--ignore-space-change", "--ignore-whitespace", *sources.git(), "apply", "--ignore-space-change", "--ignore-whitespace",
cwd=local, input_data=patch.value, logger=sources.logger cwd=local, input_data=patch.value, logger=sources.logger
) )