checkupdates: only update app branches if metadata file changed

This commit is contained in:
Hans-Christoph Steiner 2024-11-19 09:49:45 +01:00
parent e3f724681a
commit 0ec9cd6921
2 changed files with 58 additions and 12 deletions

View file

@ -740,9 +740,22 @@ def checkout_appid_branch(appid):
return True return True
def push_commits(remote_name='origin', branch_name='checkupdates', verbose=False): def get_changes_versus_ref(git_repo, ref, f):
changes = []
for m in re.findall(
r"^[+-].*", git_repo.git.diff(f"{ref}", '--', f), flags=re.MULTILINE
):
if not re.match(r"^(\+\+\+|---) ", m):
changes.append(m)
return changes
def push_commits(branch_name='checkupdates', verbose=False):
"""Make git branch then push commits as merge request. """Make git branch then push commits as merge request.
The appid is parsed from the actual file that was changed so that
only the right branch is ever updated.
This uses the appid as the standard branch name so that there is This uses the appid as the standard branch name so that there is
only ever one open merge request per-app. If multiple apps are only ever one open merge request per-app. If multiple apps are
included in the branch, then 'checkupdates' is used as branch included in the branch, then 'checkupdates' is used as branch
@ -760,9 +773,7 @@ def push_commits(remote_name='origin', branch_name='checkupdates', verbose=False
git_repo = git.Repo.init('.') git_repo = git.Repo.init('.')
upstream_main = get_upstream_main_branch(git_repo) upstream_main = get_upstream_main_branch(git_repo)
files = set() files = set()
for commit in git_repo.iter_commits( for commit in git_repo.iter_commits(f'{upstream_main}...HEAD', right_only=True):
f'{upstream_main}...HEAD', right_only=True
):
files.update(commit.stats.files.keys()) files.update(commit.stats.files.keys())
files = list(files) files = list(files)
@ -773,6 +784,11 @@ def push_commits(remote_name='origin', branch_name='checkupdates', verbose=False
if not files: if not files:
return return
remote = git_repo.remotes.origin
if branch_name in remote.refs:
if not get_changes_versus_ref(git_repo, f'origin/{branch_name}', files[0]):
return
git_repo.create_head(branch_name, force=True) git_repo.create_head(branch_name, force=True)
push_options = [ push_options = [
'merge_request.create', 'merge_request.create',
@ -784,13 +800,7 @@ def push_commits(remote_name='origin', branch_name='checkupdates', verbose=False
# mark as draft if there are only changes to CurrentVersion: # mark as draft if there are only changes to CurrentVersion:
current_version_only = True current_version_only = True
for m in re.findall( for m in get_changes_versus_ref(git_repo, upstream_main, files[0]):
r"^[+-].*",
git_repo.git.diff(f"{upstream_main}...HEAD"),
flags=re.MULTILINE,
):
if re.match(r"^(\+\+\+|---) ", m):
continue
if not re.match(r"^[-+]CurrentVersion", m): if not re.match(r"^[-+]CurrentVersion", m):
current_version_only = False current_version_only = False
break break
@ -810,7 +820,6 @@ def push_commits(remote_name='origin', branch_name='checkupdates', verbose=False
progress = MyProgressPrinter() progress = MyProgressPrinter()
remote = git_repo.remotes[remote_name]
pushinfos = remote.push( pushinfos = remote.push(
branch_name, branch_name,
progress=progress, progress=progress,

View file

@ -324,6 +324,9 @@ class CheckupdatesTest(unittest.TestCase):
for f in (basedir / 'metadata').glob('*.yml'): for f in (basedir / 'metadata').glob('*.yml'):
shutil.copy(f, 'metadata') shutil.copy(f, 'metadata')
git_repo = git.Repo.init(testdir) git_repo = git.Repo.init(testdir)
with git_repo.config_writer() as cw:
cw.set_value('user', 'name', 'Foo Bar')
cw.set_value('user', 'email', 'foo@bar.com')
git_repo.git.add(all=True) git_repo.git.add(all=True)
git_repo.index.commit("all metadata files") git_repo.index.commit("all metadata files")
@ -341,6 +344,40 @@ class CheckupdatesTest(unittest.TestCase):
return git_repo, origin_repo, upstream_repo return git_repo, origin_repo, upstream_repo
def test_get_changes_versus_ref(self):
def _make_commit_new_app(git_repo, metadata_file):
app = fdroidserver.metadata.App()
fdroidserver.metadata.write_metadata(metadata_file, app)
git_repo.git.add(metadata_file)
git_repo.git.commit(metadata_file, message=f'changed {metadata_file}')
git_repo, origin_repo, upstream_repo = self._get_test_git_repos()
for remote in git_repo.remotes:
remote.push(git_repo.active_branch)
appid = 'com.testvalue'
metadata_file = f'metadata/{appid}.yml'
# set up remote branch with change to app
git_repo.git.checkout('-b', appid)
_make_commit_new_app(git_repo, metadata_file)
git_repo.remotes.origin.push(appid)
# reset local branch and there should be differences
upstream_main = fdroidserver.checkupdates.get_upstream_main_branch(git_repo)
git_repo.git.reset(upstream_main)
self.assertTrue(
fdroidserver.checkupdates.get_changes_versus_ref(
git_repo, f'origin/{appid}', metadata_file
)
)
# make new commit that matches the previous, different commit, no diff
_make_commit_new_app(git_repo, metadata_file)
self.assertFalse(
fdroidserver.checkupdates.get_changes_versus_ref(
git_repo, f'origin/{appid}', metadata_file
)
)
def test_push_commits(self): def test_push_commits(self):
git_repo, origin_repo, upstream_repo = self._get_test_git_repos() git_repo, origin_repo, upstream_repo = self._get_test_git_repos()
for remote in git_repo.remotes: for remote in git_repo.remotes: