Skip to content

Commit

Permalink
test: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomas Peterka committed Feb 6, 2024
1 parent 98b7c1d commit e039862
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 39 deletions.
40 changes: 19 additions & 21 deletions gira/__main__.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
import argparse
import logging
import sys
from pathlib import Path

import click

from . import config as config_parser
from . import gira, logger


@click.command()
@click.option("-r", "--ref", "ref", type=str)
@click.option("-c", "--config", "config", type=str)
@click.option("-v", "--verbose", "verbose", type=bool, is_flag=True)
@click.option(
"-f",
"--format",
"format",
type=str,
default="commit",
help="Output format: commit, detail, markdown",
)
@click.argument("args", nargs=-1)
def main(config: str, ref: str, verbose: bool, format: str, args: list[str]) -> int:
logging.basicConfig(level=logging.DEBUG if verbose else logging.INFO, stream=sys.stderr)
def main() -> int:
"""Prepare gira to run with arguments from command line. Return exit code."""
parser = argparse.ArgumentParser(description="Gira - Git Dependencies Analyzer")
parser.add_argument("-r", "--ref", type=str)
parser.add_argument("-c", "--config", type=str)
parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument(
"-f", "--format", type=str, default="commit", help="Output format: commit, detail, markdown"
)
parser.add_argument("args", nargs=argparse.REMAINDER)
args = parser.parse_args(sys.argv[1:])

logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO, stream=sys.stderr)
logging.getLogger("urllib3").setLevel(logging.WARNING)

conf = config_parser.from_file(Path(config) if config else None)
logger.debug(f"Arguments: {args}")
conf = config_parser.from_file(Path(args.config) if args.config else None)
if not conf.observe and not conf.submodules:
logger.error("No observed dependencies found in gira configuration file")
return 1

stream = sys.stdout
precommit = len(args) > 0 and args[0] == ".git/COMMIT_EDITMSG"
precommit = len(args.args) > 0 and args.args[0] == ".git/COMMIT_EDITMSG"
if precommit:
commit_msg_file = args[0]
commit_msg_file = args.args[0]
logger.debug(f"Outputting to commit message file {commit_msg_file}")
stream = Path(commit_msg_file).open("at", newline="\n")

try:
gira.gira(conf, format=format, stream=stream, ref=ref)
gira.gira(conf, format=args.format, stream=stream, ref=args.ref)
return 0
except Exception as e:
logger.debug(e, stack_info=True)
Expand Down
23 changes: 14 additions & 9 deletions gira/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,36 @@
CACHE_DIR = Path(".gira_cache")


def cache(project: str, url: str) -> pygit2.Repository:
"""Return commit messages between two revisions a and b"""
repo_dir = CACHE_DIR / (project + ".git")
def cache(name: str, url: str) -> pygit2.Repository:
"""Cache a git repository by its url ane name and return a pygit2.Repository object to it"""
repo_dir = CACHE_DIR / (name + ".git")
if not CACHE_DIR.exists():
CACHE_DIR.mkdir()

if not url.startswith("http") and not url.startswith("git@"):
# add a protocol and .git suffix if missing
if "://" not in url and not url.startswith("git@"):
url = f"https://{url}"
if not url.endswith(".git"):
url = f"{url}.git"

# use the binary for remote url to avoid issues with ssh keys
if not repo_dir.exists():
logger.debug(f"Cloning {project} with url {url} to {repo_dir}")
subprocess.run(["git", "clone", "--bare", url, repo_dir], check=True, capture_output=True)
logger.debug(f"Cloning {name} with url {url} to {repo_dir}")
subprocess.run(
["git", "clone", "--bare", url, str(repo_dir)], check=True, capture_output=True
)
else:
logger.debug("Fetching from origin")
subprocess.run(["git", "fetch", "origin"], cwd=repo_dir, check=True, capture_output=True)
subprocess.run(
["git", "fetch", "origin"], cwd=str(repo_dir), check=True, capture_output=True
)
return repo.Repo(repo_dir, ref="HEAD", bare=True)


def messages(project: str, url: str, a: str, b: str) -> list[str]:
def messages(name: str, url: str, a: str, b: str) -> list[str]:
"""Return commit messages between two revisions a and b for cached git repository
@deprecated use cache() and repo.messages() instead.
"""
repo = cache(project, url)
repo = cache(name, url)
return repo.messages(a, b)
8 changes: 3 additions & 5 deletions gira/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import tomllib as toml
else:
import tomli as toml

from pathlib import Path

version_re = re.compile(r"""([0-9]+\.[0-9]+[^"',]*)""")
Expand Down Expand Up @@ -60,7 +59,7 @@ def parse_pytoml(content: str, observed: dict[str, str]) -> dict[str, str]:
dependencies[name] = "v" + version_match.group(1)

if _section(parsed, "tool.poetry.dependencies"):
"""The developer chould decide not to version poetry.lock so we need to parse pyproject.toml
"""The developer could decide not to version poetry.lock so we need to parse pyproject.toml
Example:
[tool.poetry.dependencies]
Expand All @@ -69,7 +68,7 @@ def parse_pytoml(content: str, observed: dict[str, str]) -> dict[str, str]:
pymavlink = "^2.4.20"
ruff = {version="*", optional=true}
"""
for dependency, value in _section(parsed, "tool.poetry.dependencies"):
for dependency, value in _section(parsed, "tool.poetry.dependencies").items():
if dependency not in observed:
continue
version = ""
Expand Down Expand Up @@ -117,8 +116,7 @@ def parse_package_lock(content: str, Set: set[str]) -> dict[str, str]:
"@fontsource/roboto": "^4.2.3",
"@fontsource/titillium-web": "^4.5.8",
"""
# TODO: implement
return {}
raise NotImplementedError("Not implemented parsing dependencies from package.json")


def parse_pubspec_yaml(content: str, observed: dict[str, str]) -> dict[str, str]:
Expand Down
7 changes: 4 additions & 3 deletions gira/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ def __init__(self, path: Path, ref: Optional[str] = "", bare: bool = False):
self.path = path
self.repo = pygit2.Repository(str(path), pygit2.GIT_REPOSITORY_OPEN_BARE if bare else 0)
self.bare = bare
self.ref = self._check_ref(ref)
try:
self.ref = self._check_ref(ref)
except KeyError as e:
raise RuntimeError(f"Revision {e.args[0]} does not exist")
self._submodules = None

@property
Expand Down Expand Up @@ -92,10 +95,8 @@ def _check_ref(self, ref: Optional[str]):
return "refs/tags/" + ref
except KeyError:
return "refs/heads/" + ref

if self.repo and len(self.repo.diff("HEAD")) == 0:
return "HEAD^"

return "HEAD"

def messages(self, a: str, b: Optional[str] = None):
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ readme = "README.md"
license.text = "MIT"
authors = [{name = "Tomas Peterka", email = "[email protected]"},]
dependencies = [
"click",
"pygit2",
"tomli; python_version < '3.11'",
"pyyaml",
Expand Down
10 changes: 10 additions & 0 deletions run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
set -e

# make sure the binaries are available
which git
which envsubst
which gira

cd tests
. run.sh
19 changes: 19 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Tests

Here are tests that deal with git repositories. The "remote" is TARed in remote/
folder and extracted at the begging of the test. Since file:// remotes must be
specified with absolute path then we have the local-template repository where
$GIRA_TEST_ROOT is being replaced (with pretty much just value of $PWD).


## Modify remote

We kept conveniently whole dep1 repository so you can just unTAR it, make commits
and then TAR it again. All of this just to avoid having sub-repositories in gira
repository.


## Test workings

Tests do `git init` and then make commits/changes so the .git repository does not
need to be part of gira repository.
39 changes: 39 additions & 0 deletions tests/local-template/poetry/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions tests/local-template/poetry/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "gira-test"
version = "0.0.0"
repository = "https://github.com/dronetag/gira"
authors = [
"Tomas Peterka <[email protected]>",
]
description = "Dummy pytoml"
readme = "README.md"
license = "MIT"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]

[tool.poetry.dependencies]
python = "^3.8"
dep1 = "1.0.0"
wheel = "*"
pytest = {version="*", optional=true}

[tool.poetry.extras]
dev = ["wheel", "pytest"]

[tool.gira.observe]
dep1 = "file://${GIRA_TEST_ROOT}/remote/dep1/.git"
25 changes: 25 additions & 0 deletions tests/local-template/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: gira_test_app
description: >-
Test of pubspec.yaml changes
version: 0.0.0
homepage: https://www.dronetag.cz
repository: https://github.com/dronetag/gira

publish_to: none

environment:
sdk: ">=3.2.4 <4.0.0"
flutter: ">=3.16.7"

dependencies:
analyzer: ^5.13.0
dep1:
git:
url: file:///${GIRA_TEST_ROOT}/remote/dep1/.git
ref: v1.0.0
non-internal-dep2: ^0.9.3+5

gira:
observe:
dep1: "file:///${GIRA_TEST_ROOT}/remote/dep1/.git"
23 changes: 23 additions & 0 deletions tests/local-template/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[build-system]
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "gira-test"
version = "0.0.0"
requires-python = ">=3.8"
description = "GIRA places JIRA tickets from your dependencies into your commit message"
readme = "README.md"
license.text = "MIT"
authors = [{name = "Tomas Peterka", email = "[email protected]"},]
dependencies = [
"click",
"pygit2",
"tomli; python_version < '3.11'",
"pyyaml",
"jira",
"dep1==1.0.0",
]

[tool.gira.observe]
dep1 = "file://${GIRA_TEST_ROOT}/remote/dep1/.git"
19 changes: 19 additions & 0 deletions tests/local-template/west.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
manifest:
version: 0.7

remotes:
- name: local
url-base: file://${GIRA_TEST_ROOT}/remote

defaults:
remote: local

projects:
- name: dep1
repo-path: libs/dep1
revision: v1.0.0
import: true

gira:
observe:
dep1: "file://${GIRA_TEST_ROOT}/remote/dep1/.git"
Binary file added tests/remote/dep1.tar
Binary file not shown.
Loading

0 comments on commit e039862

Please sign in to comment.