packages: clone_pkgbuilds() and friends: add discard_changes arg, use in integration_tests

This commit is contained in:
InsanePrawn 2022-11-05 05:56:15 +01:00
parent 12554ebf18
commit 185894842f
3 changed files with 61 additions and 10 deletions

View file

@ -41,7 +41,7 @@ def test_packages_update(ctx: click.Context):
for branch, may_fail in branches.items(): for branch, may_fail in branches.items():
config.file.pkgbuilds.git_branch = branch config.file.pkgbuilds.git_branch = branch
try: try:
ctx.invoke(cmd_update, non_interactive=True, switch_branch=True) ctx.invoke(cmd_update, non_interactive=True, switch_branch=True, discard_changes=True)
except Exception as ex: except Exception as ex:
print(f'may_fail: {may_fail}; Exception: {ex}') print(f'may_fail: {may_fail}; Exception: {ex}')
if not may_fail: if not may_fail:

View file

@ -56,9 +56,10 @@ non_interactive_flag = click.option('--non-interactive', is_flag=True)
@cmd_packages.command(name='update') @cmd_packages.command(name='update')
@non_interactive_flag @non_interactive_flag
@click.option('--switch-branch', is_flag=True, help="Force the branch to be corrected even in non-interactive mode") @click.option('--switch-branch', is_flag=True, help="Force the branch to be corrected even in non-interactive mode")
def cmd_update(non_interactive: bool = False, switch_branch: bool = False): @click.option('--discard-changes', is_flag=True, help="When switching branches, discard any locally changed conflicting files")
def cmd_update(non_interactive: bool = False, switch_branch: bool = False, discard_changes: bool = False):
"""Update PKGBUILDs git repo""" """Update PKGBUILDs git repo"""
init_pkgbuilds(interactive=not non_interactive, lazy=False, update=True, switch_branch=switch_branch) init_pkgbuilds(interactive=not non_interactive, lazy=False, update=True, switch_branch=switch_branch, discard_changes=discard_changes)
logging.info("Refreshing SRCINFO caches") logging.info("Refreshing SRCINFO caches")
discover_pkgbuilds(lazy=False) discover_pkgbuilds(lazy=False)

View file

@ -12,6 +12,7 @@ from config.state import config, ConfigStateHolder
from constants import REPOSITORIES from constants import REPOSITORIES
from constants import Arch from constants import Arch
from distro.package import PackageInfo from distro.package import PackageInfo
from exec.file import remove_file
from logger import setup_logging from logger import setup_logging
from utils import git, git_get_branch from utils import git, git_get_branch
from wrapper import check_programs_wrap from wrapper import check_programs_wrap
@ -19,7 +20,15 @@ from wrapper import check_programs_wrap
from .srcinfo_cache import SrcinfoMetaFile from .srcinfo_cache import SrcinfoMetaFile
def clone_pkgbuilds(pkgbuilds_dir: str, repo_url: str, branch: str, interactive=False, update=True, switch_branch: bool = False): def clone_pkgbuilds(
pkgbuilds_dir: str,
repo_url: str,
branch: str,
interactive=False,
update=True,
switch_branch: bool = False,
discard_changes: bool = False,
):
check_programs_wrap(['git']) check_programs_wrap(['git'])
git_dir = os.path.join(pkgbuilds_dir, '.git') git_dir = os.path.join(pkgbuilds_dir, '.git')
if not os.path.exists(git_dir): if not os.path.exists(git_dir):
@ -35,31 +44,72 @@ def clone_pkgbuilds(pkgbuilds_dir: str, repo_url: str, branch: str, interactive=
result = git(['remote', 'update'], dir=pkgbuilds_dir) result = git(['remote', 'update'], dir=pkgbuilds_dir)
if result.returncode != 0: if result.returncode != 0:
raise Exception('failed updating PKGBUILDs branches') raise Exception('failed updating PKGBUILDs branches')
result = git(['switch', branch], dir=pkgbuilds_dir) result = git(['switch', *(['-f'] if discard_changes else []), branch], dir=pkgbuilds_dir)
if result.returncode != 0: if result.returncode != 0:
raise Exception('failed switching PKGBUILDs branches') raise Exception('failed switching PKGBUILDs branches')
logging.warning('Hint: you can use `kupferbootstrap packages update` to switch branches') logging.warning('Hint: you can use `kupferbootstrap packages update` to switch branches')
if update: if update:
if interactive: if interactive:
if not click.confirm('Would you like to try updating the PKGBUILDs repo?'): if not click.confirm('Would you like to try updating the PKGBUILDs repo?', default=True):
return return
result = git(['pull'], dir=pkgbuilds_dir) result = git(['fetch'], dir=pkgbuilds_dir)
if result.returncode != 0: if result.returncode != 0:
raise Exception('failed to update pkgbuilds') raise Exception("Failed to fetch updates with git")
pull_cmd = ['pull', '--ff-only']
result = git(pull_cmd, dir=pkgbuilds_dir)
if result.returncode != 0:
if discard_changes:
logging.info("git pull failed, detecting conflicting changes")
# '@{u}' is a git placeholder for the latest upstream commit
result = git(['diff', '--name-only', '--diff-filter=UD', '@{u}'], capture_output=True, dir=pkgbuilds_dir)
result.check_returncode()
if result.stdout:
logging.info("Discarding conflicting changes")
for f in result.stdout.decode().split('\n'):
path = os.path.join(pkgbuilds_dir, f)
if not os.path.exists(path):
continue
result = git(['checkout', '--', f], dir=pkgbuilds_dir, capture_output=True)
if result.returncode != 0:
logging.debug(f'git checkout of file "{f}" failed; removing.')
remove_file(path)
logging.info("Retrying git pull")
result = git(pull_cmd, dir=pkgbuilds_dir)
if result.returncode != 0:
logging.info("Last resort: git reset --hard")
result = git(['reset', '--hard', '@{u}'], capture_output=True, dir=pkgbuilds_dir)
if result.returncode == 0:
return
raise Exception('`git pull` failed to update pkgbuilds')
_pkgbuilds_initialised: bool = False _pkgbuilds_initialised: bool = False
def init_pkgbuilds(interactive=False, lazy: bool = True, update: bool = False, switch_branch: bool = False): def init_pkgbuilds(
interactive=False,
lazy: bool = True,
update: bool = False,
switch_branch: bool = False,
discard_changes: bool = False,
):
global _pkgbuilds_initialised global _pkgbuilds_initialised
if lazy and _pkgbuilds_initialised: if lazy and _pkgbuilds_initialised:
return return
pkgbuilds_dir = config.get_path('pkgbuilds') pkgbuilds_dir = config.get_path('pkgbuilds')
repo_url = config.file.pkgbuilds.git_repo repo_url = config.file.pkgbuilds.git_repo
branch = config.file.pkgbuilds.git_branch branch = config.file.pkgbuilds.git_branch
clone_pkgbuilds(pkgbuilds_dir, repo_url, branch, interactive=interactive, update=update, switch_branch=switch_branch) clone_pkgbuilds(
pkgbuilds_dir,
repo_url,
branch,
interactive=interactive,
update=update,
switch_branch=switch_branch,
discard_changes=discard_changes,
)
_pkgbuilds_initialised = True _pkgbuilds_initialised = True