diff --git a/pmb/helpers/status.py b/pmb/helpers/status.py index 7e86d7e2..6c8b4d80 100644 --- a/pmb/helpers/status.py +++ b/pmb/helpers/status.py @@ -41,6 +41,74 @@ def print_git_repos(args): logging.info("- {} ({})".format(repo, ref)) +def print_checks_git_repo(args, repo, details=True): + """ Perform various checks on one checked out git repo. + :param details: if True, print each passing check (this is True by + default for the testsuite) + :returns: status, todo_msg + - status: integer, 0 if all passed, < 0 on failure + - msg_todo: message to help the user resolve the failure """ + def log_ok(msg_ok): + if details: + logging.info("[OK ] {}: {}".format(repo, msg_ok)) + + def log_nok_ret(status, msg_nok, msg_todo): + logging.warning("[NOK] {}: {}".format(repo, msg_nok)) + return (status, msg_todo) + + # On official branch + path = pmb.helpers.git.get_path(args, repo) + branches = pmb.helpers.git.get_branches_official(args, repo) + ref = pmb.helpers.git.rev_parse(args, path, extra_args=["--abbrev-ref"]) + if ref not in branches: + return log_nok_ret(-1, "not on official channel branch", + "consider checking out: " + ", ".join(branches)) + log_ok("on official channel branch") + + # Workdir clean + if not pmb.helpers.git.clean_worktree(args, path): + return log_nok_ret(-2, "workdir is not clean", + "consider cleaning your workdir") + log_ok("workdir is clean") + + # Tracking proper remote + remote_upstream = pmb.helpers.git.get_upstream_remote(args, repo) + branch_upstream = remote_upstream + "/" + ref + remote_ref = pmb.helpers.git.rev_parse(args, path, ref + "@{u}", + ["--abbrev-ref"]) + if remote_ref != branch_upstream: + return log_nok_ret(-3, "tracking unexpected remote branch", + "consider tracking remote branch '{}' instead of" + " '{}'".format(branch_upstream, remote_ref)) + log_ok("tracking proper remote branch '{}'".format(branch_upstream)) + + # Up to date + ref_branch = pmb.helpers.git.rev_parse(args, path, ref) + ref_branch_upstream = pmb.helpers.git.rev_parse(args, path, + branch_upstream) + if ref_branch != ref_branch_upstream: + return log_nok_ret(-4, "not up to date with remote branch", + "update with 'pmbootstrap pull'") + log_ok("up to date with remote branch") + + return (0, "") + + +def print_checks_git_repos(args, details): + """ Perform various checks on the checked out git repos. + :param details: if True, print each passing check + :returns: list of unresolved checklist items """ + ret = [] + for repo in pmb.config.git_repos.keys(): + path = pmb.helpers.git.get_path(args, repo) + if not os.path.exists(path): + continue + status, todo_msg = print_checks_git_repo(args, repo, details) + if status: + ret += ["{}: {}".format(repo, todo_msg)] + return ret + + def print_checks_chroots_outdated(args, details): """ Check if chroots were zapped recently. :param details: if True, print each passing check instead of a summary @@ -59,6 +127,7 @@ def print_checks(args, details): logging.info("*** CHECKS ***") checklist = [] checklist += print_checks_chroots_outdated(args, details) + checklist += print_checks_git_repos(args, details) # All OK if not checklist: diff --git a/test/test_helpers_status.py b/test/test_helpers_status.py index 591fd79a..f92bec0a 100644 --- a/test/test_helpers_status.py +++ b/test/test_helpers_status.py @@ -1,10 +1,13 @@ # Copyright 2020 Oliver Smith # SPDX-License-Identifier: GPL-3.0-or-later """ Test pmb/helpers/status.py """ +import os import pytest +import shutil import sys -import pmb_test # noqa +import pmb_test +import pmb_test.git import pmb.config import pmb.config.workdir @@ -41,3 +44,42 @@ def test_pmbootstrap_status(args, tmpdir): ret = pmb.helpers.run.user(args, [pmbootstrap, "-w", work, "status"], check=False) assert ret == 1 + + +def test_print_checks_git_repo(args, monkeypatch, tmpdir): + """ Test pmb.helpers.status.print_checks_git_repo """ + path, run_git = pmb_test.git.prepare_tmpdir(args, monkeypatch, tmpdir) + + # Not on official branch + func = pmb.helpers.status.print_checks_git_repo + name_repo = "test" + run_git(["checkout", "-b", "inofficial-branch"]) + status, _ = func(args, name_repo) + assert status == -1 + + # Workdir is not clean + run_git(["checkout", "master"]) + shutil.copy(__file__, path + "/test.py") + status, _ = func(args, name_repo) + assert status == -2 + os.unlink(path + "/test.py") + + # Tracking different remote + status, _ = func(args, name_repo) + assert status == -3 + + # Let master track origin/master + run_git(["checkout", "-b", "temp"]) + run_git(["branch", "-D", "master"]) + run_git(["checkout", "-b", "master", "--track", "origin/master"]) + + # Not up to date + run_git(["commit", "--allow-empty", "-m", "new"], "remote") + run_git(["fetch"]) + status, _ = func(args, name_repo) + assert status == -4 + + # Up to date + run_git(["pull"]) + status, _ = func(args, name_repo) + assert status == 0