diff --git a/build/tools/repopick.py b/build/tools/repopick.py index 409eaec1..c537e410 100755 --- a/build/tools/repopick.py +++ b/build/tools/repopick.py @@ -27,14 +27,11 @@ import re import subprocess import sys import textwrap +import urllib.parse +import urllib.request from functools import cmp_to_key from xml.etree import ElementTree -try: - import requests -except ImportError: - import urllib.request - # cmp() is not available in Python 3, define it manually # See https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons @@ -121,39 +118,49 @@ def fetch_query_via_ssh(remote_url, query): return reviews -def fetch_query_via_http(remote_url, query): - if "requests" in sys.modules: - auth = None - if os.path.isfile(os.getenv("HOME") + "/.gerritrc"): - f = open(os.getenv("HOME") + "/.gerritrc", "r") - for line in f: - parts = line.rstrip().split("|") - if parts[0] in remote_url: - auth = requests.auth.HTTPBasicAuth( - username=parts[1], password=parts[2] - ) - status_code = "-1" - if auth: - url = "{0}/a/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS&o=ALL_COMMITS".format( - remote_url, query - ) - data = requests.get(url, auth=auth) - status_code = str(data.status_code) - if status_code != "200": - # They didn't get good authorization or data, Let's try the old way - url = "{0}/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS&o=ALL_COMMITS".format( - remote_url, query - ) - data = requests.get(url) - reviews = json.loads(data.text[5:]) - else: - """Given a query, fetch the change numbers via http""" - url = "{0}/changes/?q={1}&o=CURRENT_REVISION&o=ALL_REVISIONS&o=ALL_COMMITS".format( - remote_url, query - ) - data = urllib.request.urlopen(url).read().decode("utf-8") - reviews = json.loads(data[5:]) +def build_query_url(remote_url, query, auth): + p = urllib.parse.urlparse(remote_url)._asdict() + p["path"] = ("/a" if auth else "") + "/changes" + p["query"] = urllib.parse.urlencode( + { + "q": query, + "o": ["CURRENT_REVISION", "ALL_REVISIONS", "ALL_COMMITS"], + }, + doseq=True, + ) + return urllib.parse.urlunparse(urllib.parse.ParseResult(**p)) + +def fetch_query_via_http(remote_url, query, auth=True): + """Given a query, fetch the change numbers via http""" + if auth: + gerritrc = os.path.expanduser("~/.gerritrc") + username = password = "" + if os.path.isfile(gerritrc): + with open(gerritrc, "r") as f: + for line in f: + parts = line.rstrip().split("|") + if parts[0] in remote_url: + username, password = parts[1], parts[2] + + if username and password: + url = build_query_url(remote_url, query, auth) + password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() + password_mgr.add_password(None, url, username, password) + auth_handler = urllib.request.HTTPBasicAuthHandler(password_mgr) + opener = urllib.request.build_opener(auth_handler) + response = opener.open(url) + if response.getcode() != 200: + # They didn't get good authorization or data, Let's try the old way + return fetch_query_via_http(remote_url, query, False) + else: + return fetch_query_via_http(remote_url, query, False) + else: + url = build_query_url(remote_url, query, auth) + response = urllib.request.urlopen(url) + + data = response.read().decode("utf-8") + reviews = json.loads(data[5:]) for review in reviews: review["number"] = review.pop("_number") @@ -165,7 +172,7 @@ def fetch_query(remote_url, query): if remote_url[0:3] == "ssh": return fetch_query_via_ssh(remote_url, query) elif remote_url[0:4] == "http": - return fetch_query_via_http(remote_url, query.replace(" ", "+")) + return fetch_query_via_http(remote_url, query) else: raise Exception( "Gerrit URL should be in the form http[s]://hostname/ or ssh://[user@]host[:port]"