in sync/landing.py [0:0]
def add_metadata(self, sync: DownstreamSync) -> None:
logger.info("Adding metadata from downstream sync")
if self.has_metadata_for_sync(sync):
logger.info("Metadata already applied for PR %s" % sync.pr)
return
if not sync.metadata_commit or sync.metadata_commit.is_empty():
logger.info("No metadata commit available for PR %s" % sync.pr)
return
worktree = self.gecko_worktree.get()
success = gitutils.cherry_pick(worktree, sync.metadata_commit.sha1)
if not success:
logger.info("Cherry-pick failed, trying again with only test-related changes")
# Try to reset all metadata files that aren't related to an affected test.
affected_metadata = {os.path.join(env.config["gecko"]["path"]["meta"], item) + ".ini"
for items in sync.affected_tests_readonly.values()
for item in items}
checkout = []
status = gitutils.status(worktree)
for head_path, data in status.items():
if data["code"] not in {"DD", "AU", "UD", "UA", "DU", "AA", "UU"}:
# Only try to reset merge conflicts
continue
path = data["rename"] if data["rename"] else head_path
if path not in affected_metadata:
logger.debug("Resetting changes to %s" % head_path)
if data["code"] == "DU":
# Files that were deleted in master should just be removed
worktree.git.rm(head_path)
else:
checkout.append(head_path)
logger.debug("Resetting changes to %s" % " ".join(checkout))
try:
worktree.git.checkout("HEAD", "--", *checkout)
# Now try to commit again
worktree.git.commit(c=sync.metadata_commit.sha1, no_edit=True)
success = True
except git.GitCommandError as e:
if gitutils.handle_empty_commit(worktree, e):
return
if sync.skip:
return
success = False
if not success:
try:
logger.info("Cherry-pick had merge conflicts trying to automatically resolve")
status = gitutils.status(worktree)
for head_path, data in status.items():
if data["code"] in {"DD", "UD", "DU"}:
# Deleted by remote or local
# Could do better here and have the mergetool handle this case
logger.info("Removing %s which was deleted somewhere" % head_path)
worktree.git.rm(head_path)
if data["code"] in {"UA", "AU"}:
logger.info("Adding %s which was added somewhere" % head_path)
worktree.git.add(head_path)
logger.info("Running mergetool")
worktree.git.mergetool(tool="metamerge",
env={"MOZBUILD_STATE_PATH":
repos.Gecko.get_state_path(env.config,
worktree.working_dir)})
worktree.git.commit(c=sync.metadata_commit.sha1, no_edit=True)
worktree.git.clean(f=True)
success = True
except git.GitCommandError as e:
if gitutils.handle_empty_commit(worktree, e):
return
if sync.skip:
return
logger.error("Failed trying to use mergetool to resolve conflicts")
raise
metadata_commit = sync_commit.GeckoCommit(worktree, worktree.head.commit)
if metadata_commit.msg.startswith(b"Bug None"):
# If the metadata commit didn't get a valid bug number for some reason,
# we want to replace the placeholder bug number with the
# either the sync or landing bug number, otherwise the push will be
# rejected
bug_number = sync.bug or self.bug
new_message = b"Bug %s%s" % (str(bug_number).encode("utf8"),
metadata_commit.msg[len(b"Bug None"):])
sync_commit.create_commit(worktree, new_message, amend=True)