gerrit_util is aware of auth errors

gerrit_util raises GerritAuthenticationError with a nice message
suggesting to check the .netrc file.

R=szager@chromium.org, vadimsh@chromium.org
BUG=369512

Review URL: https://codereview.chromium.org/278203002

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@269865 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gerrit_util.py b/gerrit_util.py
index c8d838c..984fa10 100755
--- a/gerrit_util.py
+++ b/gerrit_util.py
@@ -14,6 +14,7 @@
 import logging
 import netrc
 import os
+import re
 import time
 import urllib
 from cStringIO import StringIO
@@ -38,6 +39,10 @@
     self.message = '(%d) %s' % (self.http_status, self.message)
 
 
+class GerritAuthenticationError(GerritError):
+  """Exception class for authentication errors during Gerrit communication."""
+
+
 def _QueryString(param_dict, first_param=None):
   """Encodes query parameters in the key:val[+key:val...] format specified here:
 
@@ -115,6 +120,17 @@
   sleep_time = 0.5
   for idx in range(TRY_LIMIT):
     response = conn.getresponse()
+
+    # Check if this is an authentication issue.
+    www_authenticate = response.getheader('www-authenticate')
+    if (response.status in (httplib.UNAUTHORIZED, httplib.FOUND) and
+        www_authenticate):
+      auth_match = re.search('realm="([^"]+)"', www_authenticate, re.I)
+      host = auth_match.group(1) if auth_match else conn.req_host
+      reason = ('Authentication failed. Please make sure your .netrc file '
+                'has credentials for %s' % host)
+      raise GerritAuthenticationError(response.status, reason)
+
     # If response.status < 500 then the result is final; break retry loop.
     if response.status < 500:
       break