def post_rollout_patch(self, svn_revision, rollout_reason): # Ensure that svn_revision is a number (and not an option to # create-rollout). try: svn_revision = int(svn_revision) except: raise ScriptError(message="Invalid svn revision number \"%s\"." % svn_revision) if rollout_reason.startswith("-"): raise ScriptError(message="The rollout reason may not begin " "with - (\"%s\")." % rollout_reason) output = self._sheriffbot.run_webkit_patch([ "create-rollout", "--force-clean", # In principle, we should pass --non-interactive here, but it # turns out that create-rollout doesn't need it yet. We can't # pass it prophylactically because we reject unrecognized command # line switches. "--parent-command=sheriff-bot", svn_revision, rollout_reason, ]) return parse_bug_id(output)
def execute(self, options, args, tool): commit_ids = tool.scm().commit_ids_from_commitish_arguments(args) if len( commit_ids ) > 10: # We could lower this limit, 10 is too many for one bug as-is. error( "webkit-patch does not support attaching %s at once. Are you sure you passed the right commit range?" % (pluralize("patch", len(commit_ids)))) have_obsoleted_patches = set() for commit_id in commit_ids: commit_message = tool.scm().commit_message_for_local_commit( commit_id) # Prefer --bug-id=, then a bug url in the commit message, then a bug url in the entire commit diff (i.e. ChangeLogs). bug_id = options.bug_id or parse_bug_id( commit_message.message()) or parse_bug_id( tool.scm().create_patch(git_commit=commit_id)) if not bug_id: log("Skipping %s: No bug id found in commit or specified with --bug-id." % commit_id) continue if options.obsolete_patches and bug_id not in have_obsoleted_patches: state = {"bug_id": bug_id} steps.ObsoletePatches(tool, options).run(state) have_obsoleted_patches.add(bug_id) diff = tool.scm().create_patch(git_commit=commit_id) description = options.description or commit_message.description( lstrip=True, strip_url=True) comment_text = self._comment_text_for_commit( options, commit_message, tool, commit_id) tool.bugs.add_patch_to_bug( bug_id, diff, description, comment_text, mark_for_review=options.review, mark_for_commit_queue=options.request_commit)
def execute(self, options, args, tool): commit_ids = tool.scm().commit_ids_from_commitish_arguments(args) if len(commit_ids) > 10: # We could lower this limit, 10 is too many for one bug as-is. error( "webkit-patch does not support attaching %s at once. Are you sure you passed the right commit range?" % (pluralize("patch", len(commit_ids))) ) have_obsoleted_patches = set() for commit_id in commit_ids: commit_message = tool.scm().commit_message_for_local_commit(commit_id) # Prefer --bug-id=, then a bug url in the commit message, then a bug url in the entire commit diff (i.e. ChangeLogs). bug_id = ( options.bug_id or parse_bug_id(commit_message.message()) or parse_bug_id(tool.scm().create_patch(git_commit=commit_id)) ) if not bug_id: log("Skipping %s: No bug id found in commit or specified with --bug-id." % commit_id) continue if options.obsolete_patches and bug_id not in have_obsoleted_patches: state = {"bug_id": bug_id} steps.ObsoletePatches(tool, options).run(state) have_obsoleted_patches.add(bug_id) diff = tool.scm().create_patch(git_commit=commit_id) description = options.description or commit_message.description(lstrip=True, strip_url=True) comment_text = self._comment_text_for_commit(options, commit_message, tool, commit_id) tool.bugs.add_patch_to_bug( bug_id, diff, description, comment_text, mark_for_review=options.review, mark_for_commit_queue=options.request_commit, )
def test_parse_bug_id(self): # FIXME: These would be all better as doctests bugs = Bugzilla() self.assertEquals(12345, parse_bug_id("http://webkit.org/b/12345")) self.assertEquals(12345, parse_bug_id("http://bugs.webkit.org/show_bug.cgi?id=12345")) self.assertEquals(12345, parse_bug_id(bugs.short_bug_url_for_bug_id(12345))) self.assertEquals(12345, parse_bug_id(bugs.bug_url_for_bug_id(12345))) self.assertEquals(12345, parse_bug_id(bugs.bug_url_for_bug_id(12345, xml=True))) # Our bug parser is super-fragile, but at least we're testing it. self.assertEquals(None, parse_bug_id("http://www.webkit.org/b/12345")) self.assertEquals(None, parse_bug_id("http://bugs.webkit.org/show_bug.cgi?ctype=xml&id=12345"))
def commit_info_for_revision(self, revision): committer_email = self._scm.committer_email_for_revision(revision) changelog_entries = self.changelog_entries_for_revision(revision) # Assume for now that the first entry has everything we need: # FIXME: This will throw an exception if there were no ChangeLogs. changelog_entry = changelog_entries[0] changelog_data = { "bug_id": parse_bug_id(changelog_entry.contents()), "author_name": changelog_entry.author_name(), "author_email": changelog_entry.author_email(), "author": changelog_entry.author(), "reviewer_text": changelog_entry.reviewer_text(), "reviewer": changelog_entry.reviewer(), } # We could pass the changelog_entry instead of a dictionary here, but that makes # mocking slightly more involved, and would make aggregating data from multiple # entries more difficult to wire in if we need to do that in the future. return CommitInfo(revision, committer_email, changelog_data)
def execute(self, nick, args, tool, sheriff): if len(args) < 2: tool.irc().post("%s: Usage: SVN_REVISION REASON" % nick) return svn_revision = args[0].lstrip("r") rollout_reason = " ".join(args[1:]) tool.irc().post("Preparing rollout for r%s..." % svn_revision) try: complete_reason = "%s (Requested by %s on %s)." % ( rollout_reason, nick, config_irc.channel) bug_id = sheriff.post_rollout_patch(svn_revision, complete_reason) bug_url = tool.bugs.bug_url_for_bug_id(bug_id) tool.irc().post("%s: Created rollout: %s" % (nick, bug_url)) except ScriptError, e: tool.irc().post("%s: Failed to create rollout patch:" % nick) tool.irc().post("%s" % e) bug_id = parse_bug_id(e.output) if bug_id: tool.irc().post("Ugg... Might have created %s" % tool.bugs.bug_url_for_bug_id(bug_id))
def commit_info_for_revision(self, revision): committer_email = self._scm.committer_email_for_revision(revision) changelog_entries = self.changelog_entries_for_revision(revision) # Assume for now that the first entry has everything we need: # FIXME: This will throw an exception if there were no ChangeLogs. if not len(changelog_entries): return None changelog_entry = changelog_entries[0] changelog_data = { "bug_id": parse_bug_id(changelog_entry.contents()), "author_name": changelog_entry.author_name(), "author_email": changelog_entry.author_email(), "author": changelog_entry.author(), "reviewer_text": changelog_entry.reviewer_text(), "reviewer": changelog_entry.reviewer(), } # We could pass the changelog_entry instead of a dictionary here, but that makes # mocking slightly more involved, and would make aggregating data from multiple # entries more difficult to wire in if we need to do that in the future. return CommitInfo(revision, committer_email, changelog_data)
def execute(self, nick, args, tool, sheriff): if len(args) < 2: tool.irc().post("%s: Usage: SVN_REVISION REASON" % nick) return svn_revision = args[0] rollout_reason = " ".join(args[1:]) tool.irc().post("Preparing rollout for r%s..." % svn_revision) try: complete_reason = "%s (Requested by %s on %s)." % ( rollout_reason, nick, config_irc.channel) bug_id = sheriff.post_rollout_patch(svn_revision, complete_reason) bug_url = tool.bugs.bug_url_for_bug_id(bug_id) tool.irc().post("%s: Created rollout: %s" % (nick, bug_url)) except ScriptError, e: tool.irc().post("%s: Failed to create rollout patch:" % nick) tool.irc().post("%s" % e) bug_id = parse_bug_id(e.output) if bug_id: tool.irc().post("Ugg... Might have created %s" % tool.bugs.bug_url_for_bug_id(bug_id))
def _determine_bug_id_and_svn_revision(self, tool, bug_id, svn_revision): commit_log = self._fetch_commit_log(tool, svn_revision) if not bug_id: bug_id = parse_bug_id(commit_log) if not svn_revision: match = re.search("^r(?P<svn_revision>\d+) \|", commit_log, re.MULTILINE) if match: svn_revision = match.group('svn_revision') if not bug_id or not svn_revision: not_found = [] if not bug_id: not_found.append("bug id") if not svn_revision: not_found.append("svn revision") error("Could not find %s on command-line or in %s." % (" or ".join(not_found), "r%s" % svn_revision if svn_revision else "last commit")) return (bug_id, svn_revision)
def execute(self, nick, args, tool, sheriff): svn_revision_list, rollout_reason = self._parse_args(args) if (len(svn_revision_list) == 0) or (len(rollout_reason) == 0): tool.irc().post("%s: Usage: SVN_REVISION [SVN_REVISIONS] REASON" % nick) return rollout_reason = " ".join(rollout_reason) tool.irc().post("Preparing rollout for %s..." % join_with_separators(["r" + str(revision) for revision in svn_revision_list])) try: complete_reason = "%s (Requested by %s on %s)." % ( rollout_reason, nick, config_irc.channel) bug_id = sheriff.post_rollout_patch(svn_revision_list, complete_reason) bug_url = tool.bugs.bug_url_for_bug_id(bug_id) tool.irc().post("%s: Created rollout: %s" % (nick, bug_url)) except ScriptError, e: tool.irc().post("%s: Failed to create rollout patch:" % nick) tool.irc().post("%s" % e) bug_id = parse_bug_id(e.output) if bug_id: tool.irc().post("Ugg... Might have created %s" % tool.bugs.bug_url_for_bug_id(bug_id))
def bug_id_for_this_commit(self, git_commit): try: return parse_bug_id(self.commit_message_for_this_commit(git_commit).message()) except ScriptError, e: pass # We might not have ChangeLogs.
def bug_id(self): return parse_bug_id(self._contents)
def bug_id_for_this_commit(self, git_commit, squash): try: return parse_bug_id(self.commit_message_for_this_commit(git_commit, squash).message()) except ScriptError, e: pass # We might not have ChangeLogs.