summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2012-08-02 14:57:37 -0700
committerShawn O. Pearce <sop@google.com>2012-08-02 15:18:10 -0700
commit5e7127d00baf5bdad3e52cf8784c8aaa736395e1 (patch)
treeb28b86ba1eb092483d0f5e02f73e6532a167e8c9
parent5d0efdb14a31d651a0f6061ffb73452a20b7ed77 (diff)
downloadgit-repo-5e7127d00baf5bdad3e52cf8784c8aaa736395e1.tar.gz
Use curl command line tool for clone.bundlev1.10.3
urllib2 is not thread safe and may be causing sync to lock up or not work correctly on various platforms. Instead use the command line curl program. Change-Id: I36eaf18bb4df089d26ea99d533cb015e7c616eb0
-rw-r--r--project.py132
1 files changed, 30 insertions, 102 deletions
diff --git a/project.py b/project.py
index 3f0fd80b..b7295790 100644
--- a/project.py
+++ b/project.py
@@ -20,19 +20,9 @@ import random
20import re 20import re
21import shutil 21import shutil
22import stat 22import stat
23import subprocess
23import sys 24import sys
24import time 25import time
25import urllib2
26
27try:
28 import threading as _threading
29except ImportError:
30 import dummy_threading as _threading
31
32try:
33 from os import SEEK_END
34except ImportError:
35 SEEK_END = 2
36 26
37from color import Coloring 27from color import Coloring
38from git_command import GitCommand 28from git_command import GitCommand
@@ -41,11 +31,10 @@ from error import DownloadError
41from error import GitError, HookError, ImportError, UploadError 31from error import GitError, HookError, ImportError, UploadError
42from error import ManifestInvalidRevisionError 32from error import ManifestInvalidRevisionError
43from progress import Progress 33from progress import Progress
34from trace import IsTrace, Trace
44 35
45from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M 36from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M
46 37
47_urllib_lock = _threading.Lock()
48
49def _lwrite(path, content): 38def _lwrite(path, content):
50 lock = '%s.lock' % path 39 lock = '%s.lock' % path
51 40
@@ -1553,100 +1542,39 @@ class Project(object):
1553 return ok 1542 return ok
1554 1543
1555 def _FetchBundle(self, srcUrl, tmpPath, dstPath, quiet): 1544 def _FetchBundle(self, srcUrl, tmpPath, dstPath, quiet):
1556 keep = True 1545 if os.path.exists(dstPath):
1557 done = False 1546 os.remove(dstPath)
1558 dest = open(tmpPath, 'a+b')
1559 try:
1560 dest.seek(0, SEEK_END)
1561 pos = dest.tell()
1562 1547
1563 _urllib_lock.acquire() 1548 cmd = ['curl', '--output', tmpPath, '--netrc', '--location']
1564 try: 1549 if quiet:
1565 req = urllib2.Request(srcUrl) 1550 cmd += ['--silent']
1566 if pos > 0: 1551 if os.path.exists(tmpPath):
1567 req.add_header('Range', 'bytes=%d-' % (pos,)) 1552 size = os.stat(tmpPath).st_size
1568 1553 if size >= 1024:
1569 try: 1554 cmd += ['--continue-at', '%d' % (size,)]
1570 r = urllib2.urlopen(req) 1555 else:
1571 except urllib2.HTTPError, e: 1556 os.remove(tmpPath)
1572 def _content_type(): 1557 if 'http_proxy' in os.environ and 'darwin' == sys.platform:
1573 try: 1558 cmd += ['--proxy', os.environ['http_proxy']]
1574 return e.info()['content-type'] 1559 cmd += [srcUrl]
1575 except:
1576 return None
1577
1578 if e.code in (401, 403, 404):
1579 keep = False
1580 return False
1581 elif _content_type() == 'text/plain':
1582 try:
1583 msg = e.read()
1584 if len(msg) > 0 and msg[-1] == '\n':
1585 msg = msg[0:-1]
1586 msg = ' (%s)' % (msg,)
1587 except:
1588 msg = ''
1589 else:
1590 try:
1591 from BaseHTTPServer import BaseHTTPRequestHandler
1592 res = BaseHTTPRequestHandler.responses[e.code]
1593 msg = ' (%s: %s)' % (res[0], res[1])
1594 except:
1595 msg = ''
1596 raise DownloadError('HTTP %s%s' % (e.code, msg))
1597 except urllib2.URLError, e:
1598 raise DownloadError('%s: %s ' % (req.get_host(), str(e)))
1599 finally:
1600 _urllib_lock.release()
1601
1602 p = None
1603 try:
1604 size = pos + int(r.headers.get('content-length', 0))
1605 unit = 1 << 10
1606 1560
1607 if size and not quiet: 1561 if IsTrace():
1608 if size > 1024 * 1.3: 1562 Trace('%s', ' '.join(cmd))
1609 unit = 1 << 20 1563 try:
1610 desc = 'MB' 1564 proc = subprocess.Popen(cmd)
1611 else: 1565 except OSError:
1612 desc = 'KB' 1566 return False
1613 p = Progress(
1614 'Downloading %s' % (self.relpath,),
1615 int(size) / unit,
1616 units=desc)
1617 if pos > 0:
1618 p.update(pos / unit)
1619
1620 s = 0
1621 while True:
1622 d = r.read(8192)
1623 if d == '':
1624 done = True
1625 return True
1626 dest.write(d)
1627 if p:
1628 s += len(d)
1629 if s >= unit:
1630 p.update(s / unit)
1631 s = s % unit
1632 if p:
1633 if s >= unit:
1634 p.update(s / unit)
1635 else:
1636 p.update(1)
1637 finally:
1638 r.close()
1639 if p:
1640 p.end()
1641 finally:
1642 dest.close()
1643 1567
1644 if os.path.exists(dstPath): 1568 ok = proc.wait() == 0
1645 os.remove(dstPath) 1569 if os.path.exists(tmpPath):
1646 if done: 1570 if ok and os.stat(tmpPath).st_size > 16:
1647 os.rename(tmpPath, dstPath) 1571 os.rename(tmpPath, dstPath)
1648 elif not keep: 1572 return True
1573 else:
1649 os.remove(tmpPath) 1574 os.remove(tmpPath)
1575 return False
1576 else:
1577 return False
1650 1578
1651 def _Checkout(self, rev, quiet=False): 1579 def _Checkout(self, rev, quiet=False):
1652 cmd = ['checkout'] 1580 cmd = ['checkout']