# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, # You can obtain one at http://mozilla.org/MPL/2.0/.
import json import logging import os import re import subprocess import sys
import mozpack.path as mozpath from mach.decorators import Command, CommandArgument
@Command( "import-pr",
category="misc",
description="Import a pull request from Github to the local repo.",
)
@CommandArgument("-b", "--bug-number", help="Bug number to use in the commit messages.")
@CommandArgument( "-t", "--bugzilla-token",
help="Bugzilla API token used to file a new bug if no bug number is provided.",
)
@CommandArgument("-r", "--reviewer", help="Reviewer nick to apply to commit messages.")
@CommandArgument( "pull_request",
help="URL to the pull request to import (e.g. " "https://github.com/servo/webrender/pull/3665).",
) def import_pr(
command_context,
pull_request,
bug_number=None,
bugzilla_token=None,
reviewer=None,
): import requests
pr_number = None
repository = None for r in PR_REPOSITORIES.values(): if pull_request.startswith(GITHUB_ROOT + r["github"] + "/pull/"): # sanitize URL, dropping anything after the PR number
pr_number = int(re.search("/pull/([0-9]+)", pull_request).group(1))
pull_request = GITHUB_ROOT + r["github"] + "/pull/" + str(pr_number)
repository = r break
if repository isNone:
command_context.log(
logging.ERROR, "unrecognized_repo",
{}, "The pull request URL was not recognized; add it to the list of " "recognized repos in PR_REPOSITORIES in %s" % __file__,
)
sys.exit(1)
command_context.log(
logging.INFO, "import_pr",
{"pr_url": pull_request}, "Attempting to import {pr_url}",
)
dirty = [
f for f in command_context.repository.get_changed_files(mode="all") if f.startswith(repository["path"])
] if dirty:
command_context.log(
logging.ERROR, "dirty_tree",
repository, "Local {path} tree is dirty; aborting!",
)
sys.exit(1)
target_dir = mozpath.join(
command_context.topsrcdir, os.path.normpath(repository["path"])
)
if bug_number isNone: if bugzilla_token isNone:
command_context.log(
logging.WARNING, "no_token",
{}, "No bug number or bugzilla API token provided; bug number will not " "be added to commit messages.",
) else:
bug_number = _file_bug(
command_context, bugzilla_token, repository, pr_number
) elif bugzilla_token isnotNone:
command_context.log(
logging.WARNING, "too_much_bug",
{}, "Providing a bugzilla token is unnecessary when a bug number is provided. " "Using bug number; ignoring token.",
)
pr_patch = requests.get(pull_request + ".patch")
pr_patch.raise_for_status() for patch in _split_patches(pr_patch.content, bug_number, pull_request, reviewer):
command_context.log(
logging.INFO, "commit_msg",
patch, "Processing commit [{commit_summary}] by [{author}] at [{date}]",
)
patch_cmd = subprocess.Popen(
["patch", "-p1", "-s"], stdin=subprocess.PIPE, cwd=target_dir
)
patch_cmd.stdin.write(patch["diff"].encode("utf-8"))
patch_cmd.stdin.close()
patch_cmd.wait() if patch_cmd.returncode != 0:
command_context.log(
logging.ERROR, "commit_fail",
{}, 'Error applying diff from commit via "patch -p1 -s". Aborting...',
)
sys.exit(patch_cmd.returncode)
command_context.repository.commit(
patch["commit_msg"], patch["author"], patch["date"], [target_dir]
)
command_context.log(logging.INFO, "commit_pass", {}, "Committed successfully.")
patch = b""
state = INITIAL for line in patchfile.splitlines(): if state == INITIAL: if line.startswith(b"From "):
state = HEADERS elif state == HEADERS:
patch += line + b"\n" if line == b"---":
state = STAT_AND_DIFF elif state == STAT_AND_DIFF: if line.startswith(b"From "): yield _parse_patch(patch, bug_number, pull_request, reviewer)
patch = b""
state = HEADERS else:
patch += line + b"\n" if len(patch) > 0: yield _parse_patch(patch, bug_number, pull_request, reviewer) return
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.