Skip to content

Commit 1bd0769

Browse files
Daniel Xufacebook-github-bot
authored andcommitted
Consider commit metadata changes as a change
Summary: This diff makes kpd treat the number of commits and the contents of said commits as significant. Before, kpd would treat the diff contents as significant, leading to series that only split changes out into separate commits to being un-updated. See https://github.com/facebookincubator/kernel-patches-daemon/blob/543eb6e78e79a112e8ba89bb6440b627fbe16468/kernel_patches_daemon/branch_worker.py#L972-L973 . Reviewed By: chantra, danielocfb Differential Revision: D63914823 fbshipit-source-id: 0f710a0076d454d94198f5495795d26695629129
1 parent 5a1be26 commit 1bd0769

File tree

2 files changed

+173
-4
lines changed

2 files changed

+173
-4
lines changed

kernel_patches_daemon/branch_worker.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,12 +448,29 @@ async def _series_already_applied(repo: git.Repo, series: Series) -> bool:
448448
return any(ps.lower() in summaries for ps in await series.patch_subjects())
449449

450450

451-
def _is_branch_changed(repo: git.Repo, old_branch: str, new_branch: str) -> bool:
451+
def _is_branch_changed(
452+
repo: git.Repo, base_branch: str, old_branch: str, new_branch: str
453+
) -> bool:
452454
"""
453455
Returns whether or not the new_branch (in local repo) is different from
454456
the old_branch (remote repo).
457+
458+
Note that care is taken to avoid detecting commit SHA differences. The
459+
SHA is unstable even if the contents are the same. So compare the contents
460+
we care about.
455461
"""
456-
return repo.git.diff(new_branch, old_branch)
462+
# Check if code changes are different
463+
if repo.git.diff(new_branch, old_branch):
464+
return True
465+
466+
# Check if change metadata is different (number of commits and
467+
# commit messages)
468+
old_metadata = repo.git.log('--format="%B"', f"{base_branch}..{old_branch}")
469+
new_metadata = repo.git.log('--format="%B"', f"{base_branch}..{new_branch}")
470+
if old_metadata != new_metadata:
471+
return True
472+
473+
return False
457474

458475

459476
def _is_outdated_pr(pr: PullRequest) -> bool:
@@ -932,12 +949,15 @@ async def apply_push_comment(
932949
has_merge_conflict=True,
933950
can_create=True,
934951
)
935-
# force push only if if's a new branch or there is code diffs between old and new branches
952+
# force push only if if's a new branch or there is code or metadata diffs between old and new branches
936953
# which could mean that we applied new set of patches or just rebased
937954
if branch_name in self.branches and (
938955
branch_name not in self.all_prs # NO PR yet
939956
or _is_branch_changed(
940-
self.repo_local, f"remotes/origin/{branch_name}", branch_name
957+
self.repo_local,
958+
f"remotes/origin/{self.repo_pr_base_branch}",
959+
f"remotes/origin/{branch_name}",
960+
branch_name,
941961
) # have code changes
942962
):
943963
# we have branch, but either NO PR or there is code changes, we must try to

tests/test_branch_worker.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
# pyre-unsafe
88

9+
import os
910
import random
1011
import re
1112
import shutil
@@ -23,6 +24,7 @@
2324
from freezegun import freeze_time
2425
from git.exc import GitCommandError
2526
from kernel_patches_daemon.branch_worker import (
27+
_is_branch_changed,
2628
_series_already_applied,
2729
ALREADY_MERGED_LOOKBACK,
2830
BRANCH_TTL,
@@ -983,6 +985,153 @@ async def test_applied_all_case_insensitive(self, m: aioresponses):
983985
self.assertTrue(await _series_already_applied(self.repo, series))
984986

985987

988+
class TestBranchChanged(unittest.TestCase):
989+
SINGLE_COMMIT_CHANGE_MESSAGE = "single commit change\n"
990+
991+
def setUp(self):
992+
self.tmp_dir = tempfile.mkdtemp()
993+
self.repo = git.Repo.init(self.tmp_dir)
994+
995+
# So git-commit --amend doesn't error about missing configs in CI
996+
self.repo.git.config("user.name", "test")
997+
self.repo.git.config("user.email", "[email protected]")
998+
999+
# Create a file in the repository
1000+
with open(self.tmp_dir + "/file.txt", "w") as f:
1001+
f.write("Hello, world!\n")
1002+
1003+
# Create initial commit on master
1004+
self.repo.index.add(["file.txt"])
1005+
self.repo.index.commit("Initial commit\n")
1006+
1007+
# Create new branch for single commit change
1008+
self.repo.create_head("single_commit_change", commit="master").checkout()
1009+
with open(f"{self.tmp_dir}/file.txt", "a") as f:
1010+
f.write("line 1\n")
1011+
f.write("line 2\n")
1012+
self.repo.index.add(["file.txt"])
1013+
self.repo.index.commit(self.SINGLE_COMMIT_CHANGE_MESSAGE)
1014+
1015+
# Create branch for a different single commit change
1016+
self.repo.create_head(
1017+
"different_single_commit_change", commit="master"
1018+
).checkout()
1019+
with open(f"{self.tmp_dir}/file.txt", "a") as f:
1020+
f.write("built different\n")
1021+
self.repo.index.add(["file.txt"])
1022+
self.repo.index.commit("different single commit change\n")
1023+
1024+
# Create duplicate branch for single commit change but with different SHA
1025+
self.repo.create_head(
1026+
"single_commit_change_clone", commit="single_commit_change"
1027+
).checkout()
1028+
self.repo.git.commit("--amend", "--no-edit")
1029+
1030+
# Create branch to do same change but in two commits
1031+
self.repo.create_head("two_commit_change", commit="master").checkout()
1032+
for i in range(2):
1033+
with open(f"{self.tmp_dir}/file.txt", "a") as f:
1034+
f.write(f"line {i+1}\n")
1035+
self.repo.index.add(["file.txt"])
1036+
self.repo.index.commit("split change, part {i+1}\n")
1037+
1038+
# Create branch to do same change but in two commits with same duplicate
1039+
self.repo.create_head(
1040+
"two_commit_change_with_same_msg", commit="master"
1041+
).checkout()
1042+
for i in range(2):
1043+
with open(f"{self.tmp_dir}/file.txt", "a") as f:
1044+
f.write(f"line {i+1}\n")
1045+
self.repo.index.add(["file.txt"])
1046+
self.repo.index.commit(self.SINGLE_COMMIT_CHANGE_MESSAGE)
1047+
1048+
self.repo.heads.master.checkout()
1049+
1050+
def tearDown(self):
1051+
shutil.rmtree(self.tmp_dir)
1052+
1053+
def test_different_change(self):
1054+
self.assertTrue(
1055+
_is_branch_changed(
1056+
self.repo,
1057+
"master",
1058+
"single_commit_change",
1059+
"different_single_commit_change",
1060+
)
1061+
)
1062+
1063+
def test_duplicate_change(self):
1064+
self.assertFalse(
1065+
_is_branch_changed(
1066+
self.repo,
1067+
"master",
1068+
"single_commit_change",
1069+
"single_commit_change",
1070+
)
1071+
)
1072+
self.assertFalse(
1073+
_is_branch_changed(
1074+
self.repo,
1075+
"master",
1076+
"two_commit_change",
1077+
"two_commit_change",
1078+
)
1079+
)
1080+
self.assertFalse(
1081+
_is_branch_changed(
1082+
self.repo,
1083+
"master",
1084+
"two_commit_change_with_same_msg",
1085+
"two_commit_change_with_same_msg",
1086+
)
1087+
)
1088+
self.assertFalse(
1089+
_is_branch_changed(
1090+
self.repo,
1091+
"master",
1092+
"single_commit_change_clone",
1093+
"single_commit_change_clone",
1094+
)
1095+
)
1096+
self.assertFalse(
1097+
_is_branch_changed(
1098+
self.repo,
1099+
"master",
1100+
"single_commit_change",
1101+
"single_commit_change_clone",
1102+
)
1103+
)
1104+
1105+
def test_split_change(self):
1106+
# Double check that there are no source changes
1107+
self.repo.heads.single_commit_change.checkout()
1108+
self.assertFalse(self.repo.git.diff("two_commit_change"))
1109+
1110+
# But the varying number of commits triggers a change detection
1111+
self.assertTrue(
1112+
_is_branch_changed(
1113+
self.repo,
1114+
"master",
1115+
"single_commit_change",
1116+
"two_commit_change",
1117+
)
1118+
)
1119+
1120+
def test_split_duplicate_message_change(self):
1121+
# Double check that there are no source changes
1122+
self.repo.heads.single_commit_change.checkout()
1123+
self.assertFalse(self.repo.git.diff("two_commit_change_with_same_msg"))
1124+
1125+
self.assertTrue(
1126+
_is_branch_changed(
1127+
self.repo,
1128+
"master",
1129+
"single_commit_change",
1130+
"two_commit_change_with_same_msg",
1131+
)
1132+
)
1133+
1134+
9861135
class TestEmailNotificationBody(unittest.TestCase):
9871136
# Always show full diff on string match failures
9881137
maxDiff = None

0 commit comments

Comments
 (0)