diff --git a/sync/upstream.py b/sync/upstream.py index 5be649532..b49f4765c 100644 --- a/sync/upstream.py +++ b/sync/upstream.py @@ -629,8 +629,9 @@ def remove_complete_backouts(commits: Iterable[Commit]) -> Sequence[Commit]: if commit.is_backout: backed_out_commits, _ = commit.wpt_commits_backed_out() backed_out = {item.sha1 for item in backed_out_commits} - if backed_out.issubset(commits_remaining): - commits_remaining -= backed_out + intersecion = backed_out.intersection(commits_remaining) + if len(intersecion) > 0: + commits_remaining -= intersecion continue commits_remaining.add(commit.sha1) @@ -686,9 +687,9 @@ def updates_for_backout(git_gecko: Repo, sync = syncs.pop() assert isinstance(sync, UpstreamSync) if commit in sync.gecko_commits: - # This commit was already processed - backed_out_commit_shas = set() - return {}, {} + # This commit was already processed for this sync + backed_out_commit_shas.remove(backed_out_commit.sha1) + continue if backed_out_commit in sync.upstreamed_gecko_commits: backed_out_commit_shas.remove(backed_out_commit.sha1) assert sync.bug is not None diff --git a/test/conftest.py b/test/conftest.py index 1867ad77b..f658b9968 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -173,7 +173,9 @@ def setup(self): self.init() with open(os.path.join(self.working_tree, ".hg", "hgrc"), "w") as f: f.write("""[ui] -username=test""") +username=test +[extensions] +shelve=""") def __getattr__(self, name): def call(self, *args): @@ -349,12 +351,23 @@ def inner(revs, bugs, message=None, bookmarks="mozilla/autoland"): if isinstance(bugs, int): bugs = [bugs] * len(revs) assert len(bugs) == len(revs) - msg = [b"Backed out %i changesets (bug %d) for test, r=backout" % (len(revs), bugs[0]), b""] + msg = [] + all_bugs_msgs = [] for rev, bug in zip(revs, bugs): hg_gecko_upstream.backout("--no-commit", rev) - msg.append(b"Backed out changeset %s (Bug %d)" % (rev[:12].encode("ascii"), bug)) + # Shelve the changes so we can perform the next backout. + hg_gecko_upstream.shelve() + bug_msg = b'bug %d' % bug + msg.append(b"Backed out changeset %s (%s)" % (rev[:12].encode("ascii"), bug_msg)) + all_bugs_msgs.append(bug_msg) + bugs_msg = b", ".join(all_bugs_msgs) + if len(bugs) > 1: + title = [b"Backed out %i changesets (%s) for test, r=backout" % (len(revs), bugs_msg)] + msg = title + msg if message is None: message = b"\n".join(msg) + for _ in revs: + hg_gecko_upstream.unshelve() return hg_commit(hg_gecko_upstream, message, bookmarks) return inner diff --git a/test/test_upstream.py b/test/test_upstream.py index 77ab33ee9..3a3274471 100644 --- a/test/test_upstream.py +++ b/test/test_upstream.py @@ -173,6 +173,57 @@ def test_create_partial_backout_reland(git_gecko, git_wpt, upstream_gecko_commit sync.wpt_commits[1].metadata["gecko-commit"] == relanding_rev +def test_create_backout_of_multiple_bugs(git_gecko, git_wpt, upstream_gecko_commit, + upstream_gecko_backout): + bug = 1234 + test_changes = {"README": b"Change README\n"} + rev = upstream_gecko_commit(test_changes=test_changes, bug=bug, + message=b"Change README") + + update_repositories(git_gecko, git_wpt, wait_gecko_commit=rev) + upstream.gecko_push(git_gecko, git_wpt, "autoland", rev, + raise_on_error=True) + + syncs = upstream.UpstreamSync.for_bug(git_gecko, git_wpt, bug) + + bug_2 = 5678 + test_changes_2 = {"OTHER": b"Add other file\n"} + rev_2 = upstream_gecko_commit(test_changes=test_changes_2, bug=bug_2, + message=b"Add other") + + update_repositories(git_gecko, git_wpt, wait_gecko_commit=rev_2) + upstream.gecko_push(git_gecko, git_wpt, "autoland", rev_2, + raise_on_error=True) + + syncs_2 = upstream.UpstreamSync.for_bug(git_gecko, git_wpt, bug_2) + + backout_rev = upstream_gecko_backout([rev_2, rev], [bug_2, bug]) + + update_repositories(git_gecko, git_wpt, wait_gecko_commit=backout_rev) + upstream.gecko_push(git_gecko, git_wpt, "autoland", backout_rev, raise_on_error=True) + + syncs = upstream.UpstreamSync.for_bug(git_gecko, git_wpt, bug) + syncs_2 = upstream.UpstreamSync.for_bug(git_gecko, git_wpt, bug_2) + + assert list(syncs.keys()) == ["incomplete"] + assert len(syncs["incomplete"]) == 1 + sync = syncs["incomplete"].pop() + assert sync.status == "incomplete" + assert sync.process_name.seq_id == 0 + assert len(sync.gecko_commits) == 0 + assert len(sync.upstreamed_gecko_commits) == 1 + assert len(sync.wpt_commits) == 1 + + assert list(syncs_2.keys()) == ["incomplete"] + assert len(syncs_2["incomplete"]) == 1 + sync_2 = syncs_2["incomplete"].pop() + assert sync_2.status == "incomplete" + assert sync_2.process_name.seq_id == 0 + assert len(sync_2.gecko_commits) == 0 + assert len(sync_2.upstreamed_gecko_commits) == 1 + assert len(sync_2.wpt_commits) == 1 + + def test_land_pr(env, git_gecko, git_wpt, hg_gecko_upstream, upstream_gecko_commit): bug = 1234 test_changes = {"README": b"Change README\n"}