summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2011-10-11 12:00:38 -0700
committerShawn O. Pearce <sop@google.com>2011-10-11 12:18:07 -0700
commitfab96c68e3acfb5403ffe65577563f3cb39e2530 (patch)
tree972a82f40c3e7de6b88f174f5f5b2a3418f92e40
parentbf1fbb20ab33cc479881a2b755e336872971dd78 (diff)
downloadgit-repo-fab96c68e3acfb5403ffe65577563f3cb39e2530.tar.gz
Work around Python 2.7 urllib2 bug
If the remote is using authenticated HTTP, but does not have $GIT_URL/clone.bundle files in each repository, an initial sync would fail around 8 projects in due to the library not resetting the number of failures after getting a 404. Work around this by updating the retry counter ourselves. The urllib2 library is also not thread-safe. Make it somewhat safer by wrapping the critical section with a lock. Change-Id: I886e2750ef4793cbe2150c3b5396eb9f10974f7f Signed-off-by: Shawn O. Pearce <sop@google.com>
-rwxr-xr-xmain.py11
-rw-r--r--project.py77
2 files changed, 54 insertions, 34 deletions
diff --git a/main.py b/main.py
index 8ffdfcce..22e6fa42 100755
--- a/main.py
+++ b/main.py
@@ -273,6 +273,15 @@ class _UserAgentHandler(urllib2.BaseHandler):
273 req.add_header('User-Agent', _UserAgent()) 273 req.add_header('User-Agent', _UserAgent())
274 return req 274 return req
275 275
276class _BasicAuthHandler(urllib2.HTTPBasicAuthHandler):
277 def http_error_auth_reqed(self, authreq, host, req, headers):
278 try:
279 return urllib2.AbstractBasicAuthHandler.http_error_auth_reqed(
280 self, authreq, host, req, headers)
281 except:
282 self.reset_retry_count()
283 raise
284
276def init_http(): 285def init_http():
277 handlers = [_UserAgentHandler()] 286 handlers = [_UserAgentHandler()]
278 287
@@ -287,7 +296,7 @@ def init_http():
287 pass 296 pass
288 except IOError: 297 except IOError:
289 pass 298 pass
290 handlers.append(urllib2.HTTPBasicAuthHandler(mgr)) 299 handlers.append(_BasicAuthHandler(mgr))
291 300
292 if 'http_proxy' in os.environ: 301 if 'http_proxy' in os.environ:
293 url = os.environ['http_proxy'] 302 url = os.environ['http_proxy']
diff --git a/project.py b/project.py
index 5f8369d5..4bc54de9 100644
--- a/project.py
+++ b/project.py
@@ -24,6 +24,11 @@ import sys
24import time 24import time
25import urllib2 25import urllib2
26 26
27try:
28 import threading as _threading
29except ImportError:
30 import dummy_threading as _threading
31
27from color import Coloring 32from color import Coloring
28from git_command import GitCommand 33from git_command import GitCommand
29from git_config import GitConfig, IsId, GetSchemeFromUrl 34from git_config import GitConfig, IsId, GetSchemeFromUrl
@@ -34,6 +39,8 @@ from progress import Progress
34 39
35from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M 40from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M
36 41
42_urllib_lock = _threading.Lock()
43
37def _lwrite(path, content): 44def _lwrite(path, content):
38 lock = '%s.lock' % path 45 lock = '%s.lock' % path
39 46
@@ -1458,40 +1465,44 @@ class Project(object):
1458 dest.seek(0, os.SEEK_END) 1465 dest.seek(0, os.SEEK_END)
1459 pos = dest.tell() 1466 pos = dest.tell()
1460 1467
1461 req = urllib2.Request(srcUrl) 1468 _urllib_lock.acquire()
1462 if pos > 0:
1463 req.add_header('Range', 'bytes=%d-' % pos)
1464
1465 try: 1469 try:
1466 r = urllib2.urlopen(req) 1470 req = urllib2.Request(srcUrl)
1467 except urllib2.HTTPError, e: 1471 if pos > 0:
1468 def _content_type(): 1472 req.add_header('Range', 'bytes=%d-' % pos)
1469 try: 1473
1470 return e.info()['content-type'] 1474 try:
1471 except: 1475 r = urllib2.urlopen(req)
1472 return None 1476 except urllib2.HTTPError, e:
1473 1477 def _content_type():
1474 if e.code == 404: 1478 try:
1475 keep = False 1479 return e.info()['content-type']
1476 return False 1480 except:
1477 elif _content_type() == 'text/plain': 1481 return None
1478 try: 1482
1479 msg = e.read() 1483 if e.code == 404:
1480 if len(msg) > 0 and msg[-1] == '\n': 1484 keep = False
1481 msg = msg[0:-1] 1485 return False
1482 msg = ' (%s)' % msg 1486 elif _content_type() == 'text/plain':
1483 except: 1487 try:
1484 msg = '' 1488 msg = e.read()
1485 else: 1489 if len(msg) > 0 and msg[-1] == '\n':
1486 try: 1490 msg = msg[0:-1]
1487 from BaseHTTPServer import BaseHTTPRequestHandler 1491 msg = ' (%s)' % msg
1488 res = BaseHTTPRequestHandler.responses[e.code] 1492 except:
1489 msg = ' (%s: %s)' % (res[0], res[1]) 1493 msg = ''
1490 except: 1494 else:
1491 msg = '' 1495 try:
1492 raise DownloadError('HTTP %s%s' % (e.code, msg)) 1496 from BaseHTTPServer import BaseHTTPRequestHandler
1493 except urllib2.URLError, e: 1497 res = BaseHTTPRequestHandler.responses[e.code]
1494 raise DownloadError('%s: %s ' % (req.get_host(), str(e))) 1498 msg = ' (%s: %s)' % (res[0], res[1])
1499 except:
1500 msg = ''
1501 raise DownloadError('HTTP %s%s' % (e.code, msg))
1502 except urllib2.URLError, e:
1503 raise DownloadError('%s: %s ' % (req.get_host(), str(e)))
1504 finally:
1505 _urllib_lock.release()
1495 1506
1496 p = None 1507 p = None
1497 try: 1508 try: