diff --git a/src/pkgmt/fail_if_modified.py b/src/pkgmt/fail_if_modified.py new file mode 100644 index 0000000..c462b9a --- /dev/null +++ b/src/pkgmt/fail_if_modified.py @@ -0,0 +1,48 @@ +import subprocess +import argparse +import sys + + +def check_modified(base_branch, exclude_path, debug=False): + # https://stackoverflow.com/questions/4380945 + cmd = f"git diff --exit-code {base_branch}... -- ." + + for path in exclude_path: + cmd += f" ':^{path}'" + + if debug: + print(f"cmd: {cmd}") + try: + subprocess.check_output(cmd, shell=True) + return 0 + except subprocess.CalledProcessError as err: + if debug: + print( + f"Path has been modified with respect to '{base_branch}'\n" + f"Excluding paths: {exclude_path}" + ) + print(f"Return code: {err.returncode}") + print(f"Output: {err.output}") + return 1 + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Check if a branch has modified" "anything excluding some path/dir" + ) + parser.add_argument( + "-b", "--base-branch", default="main", help="Base branch to compare against" + ) + parser.add_argument( + "-e", + "--exclude-path", + default=["doc"], + nargs="+", + help="Path to exclude from git diff." + "Can be used multiple times eg: -e p1 -e p2", + ) + parser.add_argument("--debug", action="store_true", help="Print debug info") + + args = parser.parse_args() + returncode = check_modified(args.base_branch, args.exclude_path, debug=args.debug) + sys.exit(returncode) diff --git a/tests/conftest.py b/tests/conftest.py index 584ffd5..e2b5fe7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -57,3 +57,69 @@ def tmp_another_package(root, tmp_empty): yield tmp_empty os.chdir(old) + + +@pytest.fixture +def tmp_package_modi(root, tmp_empty): + old = Path.cwd() + path_to_templates = root / "tests" / "assets" / "package_name" + + shutil.copytree(str(path_to_templates), "copy") + os.chdir("copy") + + subprocess.run(["git", "init"]) + subprocess.check_call(["git", "config", "commit.gpgsign", "false"]) + subprocess.check_call(["git", "config", "user.email", "ci@ploomberio"]) + subprocess.check_call(["git", "config", "user.name", "Ploomber"]) + subprocess.run(["git", "checkout", "-b", "main"]) + subprocess.run(["git", "add", "--all"]) + subprocess.run(["git", "commit", "-m", "init-commit-message"]) + + subprocess.run(["git", "checkout", "-b", "test_modified_doc"]) + Path.cwd().joinpath("test_doc1").mkdir(parents=True, exist_ok=True) + Path.cwd().joinpath("test_doc1", "test_modified.txt").touch() + Path.cwd().joinpath("test_doc2").mkdir(parents=True, exist_ok=True) + Path.cwd().joinpath("test_doc2", "test_modified.txt").touch() + subprocess.run(["git", "add", "."]) + subprocess.run(["git", "commit", "-m", "test_modified"]) + + yield tmp_empty + + os.chdir(old) + + +@pytest.fixture +def tmp_package_modi_2(root, tmp_empty): + old = Path.cwd() + path_to_templates = root / "tests" / "assets" / "package_name" + shutil.copytree(str(path_to_templates), "copy") + os.chdir("copy") + + subprocess.run(["git", "init"]) + subprocess.check_call(["git", "config", "commit.gpgsign", "false"]) + subprocess.check_call(["git", "config", "user.email", "ci@ploomberio"]) + subprocess.check_call(["git", "config", "user.name", "Ploomber"]) + subprocess.run(["git", "checkout", "-b", "main"]) + subprocess.run(["git", "add", "--all"]) + subprocess.run(["git", "commit", "-m", "init-commit-message"]) + + Path.cwd().joinpath("doc").mkdir(parents=True, exist_ok=True) + Path.cwd().joinpath("doc", "file.txt").touch() + subprocess.run(["git", "add", "."]) + subprocess.run(["git", "commit", "-m", "added doc/file.txt"]) + + subprocess.run(["git", "checkout", "-b", "test_modified_doc"]) + Path.cwd().joinpath("doc").mkdir(parents=True, exist_ok=True) + Path.cwd().joinpath("doc", "another.txt").touch() + subprocess.run(["git", "add", "."]) + subprocess.run(["git", "commit", "-m", "add doc/another.txt"]) + + subprocess.run(["git", "checkout", "main"]) + Path.cwd().joinpath("something").mkdir(parents=True, exist_ok=True) + Path.cwd().joinpath("something", "file.txt").touch() + subprocess.run(["git", "add", "."]) + subprocess.run(["git", "commit", "-m", "added something/file.txt"]) + + yield tmp_empty + + os.chdir(old) diff --git a/tests/test_modified.py b/tests/test_modified.py new file mode 100644 index 0000000..aa2f14a --- /dev/null +++ b/tests/test_modified.py @@ -0,0 +1,28 @@ +import pytest +from pkgmt import fail_if_modified + + +@pytest.mark.parametrize( + "base_branch, exclude_path, returncode", + [ + [ + "main", + ["test_doc1"], + 1, + ], + [ + "main", + ["test_doc1", "test_doc2"], + 0, + ], + ], +) +def test_check_modified(tmp_package_modi, base_branch, exclude_path, returncode): + assert ( + fail_if_modified.check_modified(base_branch, exclude_path, debug=True) + == returncode + ) + + +def test_check_modified_2(tmp_package_modi_2): + assert fail_if_modified.check_modified("main", ["doc"], debug=True) == 0