repopick: Use the builtin urllib to handle HTTP basic authentication

Also do proper URL encode while at it.

Change-Id: I64c0913eed535b109af2adc830288b3dd17c0cbb
diff --git a/build/tools/repopick.py b/build/tools/repopick.py
index 341a95e..fc3383f 100755
--- a/build/tools/repopick.py
+++ b/build/tools/repopick.py
@@ -27,14 +27,11 @@
 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 @@
     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 @@
     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]"