summaryrefslogtreecommitdiffstats
path: root/project.py
diff options
context:
space:
mode:
Diffstat (limited to 'project.py')
-rw-r--r--project.py145
1 files changed, 134 insertions, 11 deletions
diff --git a/project.py b/project.py
index 3efc4452..5adfe82e 100644
--- a/project.py
+++ b/project.py
@@ -24,9 +24,11 @@ import urllib2
24 24
25from color import Coloring 25from color import Coloring
26from git_command import GitCommand 26from git_command import GitCommand
27from git_config import GitConfig, IsId 27from git_config import GitConfig, IsId, GetSchemeFromUrl
28from error import DownloadError
28from error import GitError, HookError, ImportError, UploadError 29from error import GitError, HookError, ImportError, UploadError
29from error import ManifestInvalidRevisionError 30from error import ManifestInvalidRevisionError
31from progress import Progress
30 32
31from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M 33from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M
32 34
@@ -884,15 +886,13 @@ class Project(object):
884 886
885## Sync ## 887## Sync ##
886 888
887 def Sync_NetworkHalf(self, quiet=False): 889 def Sync_NetworkHalf(self, quiet=False, is_new=None):
888 """Perform only the network IO portion of the sync process. 890 """Perform only the network IO portion of the sync process.
889 Local working directory/branch state is not affected. 891 Local working directory/branch state is not affected.
890 """ 892 """
891 is_new = not self.Exists 893 if is_new is None:
894 is_new = not self.Exists
892 if is_new: 895 if is_new:
893 if not quiet:
894 print >>sys.stderr
895 print >>sys.stderr, 'Initializing project %s ...' % self.name
896 self._InitGitDir() 896 self._InitGitDir()
897 897
898 self._InitRemote() 898 self._InitRemote()
@@ -1312,9 +1312,16 @@ class Project(object):
1312 name = self.remote.name 1312 name = self.remote.name
1313 1313
1314 ssh_proxy = False 1314 ssh_proxy = False
1315 if self.GetRemote(name).PreConnectFetch(): 1315 remote = self.GetRemote(name)
1316 if remote.PreConnectFetch():
1316 ssh_proxy = True 1317 ssh_proxy = True
1317 1318
1319 bundle_dst = os.path.join(self.gitdir, 'clone.bundle')
1320 bundle_tmp = os.path.join(self.gitdir, 'clone.bundle.tmp')
1321 use_bundle = False
1322 if os.path.exists(bundle_dst) or os.path.exists(bundle_tmp):
1323 use_bundle = True
1324
1318 if initial: 1325 if initial:
1319 alt = os.path.join(self.gitdir, 'objects/info/alternates') 1326 alt = os.path.join(self.gitdir, 'objects/info/alternates')
1320 try: 1327 try:
@@ -1329,6 +1336,8 @@ class Project(object):
1329 ref_dir = None 1336 ref_dir = None
1330 1337
1331 if ref_dir and 'objects' == os.path.basename(ref_dir): 1338 if ref_dir and 'objects' == os.path.basename(ref_dir):
1339 if use_bundle:
1340 use_bundle = False
1332 ref_dir = os.path.dirname(ref_dir) 1341 ref_dir = os.path.dirname(ref_dir)
1333 packed_refs = os.path.join(self.gitdir, 'packed-refs') 1342 packed_refs = os.path.join(self.gitdir, 'packed-refs')
1334 remote = self.GetRemote(name) 1343 remote = self.GetRemote(name)
@@ -1368,6 +1377,7 @@ class Project(object):
1368 1377
1369 else: 1378 else:
1370 ref_dir = None 1379 ref_dir = None
1380 use_bundle = True
1371 1381
1372 cmd = ['fetch'] 1382 cmd = ['fetch']
1373 1383
@@ -1376,15 +1386,37 @@ class Project(object):
1376 depth = self.manifest.manifestProject.config.GetString('repo.depth') 1386 depth = self.manifest.manifestProject.config.GetString('repo.depth')
1377 if depth and initial: 1387 if depth and initial:
1378 cmd.append('--depth=%s' % depth) 1388 cmd.append('--depth=%s' % depth)
1389 use_bundle = False
1379 1390
1380 if quiet: 1391 if quiet:
1381 cmd.append('--quiet') 1392 cmd.append('--quiet')
1382 if not self.worktree: 1393 if not self.worktree:
1383 cmd.append('--update-head-ok') 1394 cmd.append('--update-head-ok')
1384 cmd.append(name) 1395
1385 if tag is not None: 1396 if use_bundle and not os.path.exists(bundle_dst):
1386 cmd.append('tag') 1397 bundle_url = remote.url + '/clone.bundle'
1387 cmd.append(tag) 1398 bundle_url = GitConfig.ForUser().UrlInsteadOf(bundle_url)
1399 if GetSchemeFromUrl(bundle_url) in ('http', 'https'):
1400 use_bundle = self._FetchBundle(
1401 bundle_url,
1402 bundle_tmp,
1403 bundle_dst,
1404 quiet=quiet)
1405 else:
1406 use_bundle = False
1407
1408 if use_bundle:
1409 if not quiet:
1410 cmd.append('--quiet')
1411 cmd.append(bundle_dst)
1412 for f in remote.fetch:
1413 cmd.append(str(f))
1414 cmd.append('refs/tags/*:refs/tags/*')
1415 else:
1416 cmd.append(name)
1417 if tag is not None:
1418 cmd.append('tag')
1419 cmd.append(tag)
1388 1420
1389 ok = GitCommand(self, 1421 ok = GitCommand(self,
1390 cmd, 1422 cmd,
@@ -1399,8 +1431,99 @@ class Project(object):
1399 os.remove(packed_refs) 1431 os.remove(packed_refs)
1400 self.bare_git.pack_refs('--all', '--prune') 1432 self.bare_git.pack_refs('--all', '--prune')
1401 1433
1434 if os.path.exists(bundle_dst):
1435 os.remove(bundle_dst)
1436 if os.path.exists(bundle_tmp):
1437 os.remove(bundle_tmp)
1438
1402 return ok 1439 return ok
1403 1440
1441 def _FetchBundle(self, srcUrl, tmpPath, dstPath, quiet=False):
1442 keep = True
1443 done = False
1444 dest = open(tmpPath, 'a+b')
1445 try:
1446 dest.seek(0, os.SEEK_END)
1447 pos = dest.tell()
1448
1449 req = urllib2.Request(srcUrl)
1450 if pos > 0:
1451 req.add_header('Range', 'bytes=%d-' % pos)
1452
1453 try:
1454 r = urllib2.urlopen(req)
1455 except urllib2.HTTPError, e:
1456 if e.code == 404:
1457 keep = False
1458 return False
1459 elif e.info()['content-type'] == 'text/plain':
1460 try:
1461 msg = e.read()
1462 if len(msg) > 0 and msg[-1] == '\n':
1463 msg = msg[0:-1]
1464 msg = ' (%s)' % msg
1465 except:
1466 msg = ''
1467 else:
1468 try:
1469 from BaseHTTPServer import BaseHTTPRequestHandler
1470 res = BaseHTTPRequestHandler.responses[e.code]
1471 msg = ' (%s: %s)' % (res[0], res[1])
1472 except:
1473 msg = ''
1474 raise DownloadError('HTTP %s%s' % (e.code, msg))
1475 except urllib2.URLError, e:
1476 raise DownloadError('%s (%s)' % (e.reason, req.get_host()))
1477
1478 p = None
1479 try:
1480 size = r.headers['content-length']
1481 unit = 1 << 10
1482
1483 if size and not quiet:
1484 if size > 1024 * 1.3:
1485 unit = 1 << 20
1486 desc = 'MB'
1487 else:
1488 desc = 'KB'
1489 p = Progress(
1490 'Downloading %s' % self.relpath,
1491 int(size) / unit,
1492 units=desc)
1493 if pos > 0:
1494 p.update(pos / unit)
1495
1496 s = 0
1497 while True:
1498 d = r.read(8192)
1499 if d == '':
1500 done = True
1501 return True
1502 dest.write(d)
1503 if p:
1504 s += len(d)
1505 if s >= unit:
1506 p.update(s / unit)
1507 s = s % unit
1508 if p:
1509 if s >= unit:
1510 p.update(s / unit)
1511 else:
1512 p.update(1)
1513 finally:
1514 r.close()
1515 if p:
1516 p.end()
1517 finally:
1518 dest.close()
1519
1520 if os.path.exists(dstPath):
1521 os.remove(dstPath)
1522 if done:
1523 os.rename(tmpPath, dstPath)
1524 elif not keep:
1525 os.remove(tmpPath)
1526
1404 def _Checkout(self, rev, quiet=False): 1527 def _Checkout(self, rev, quiet=False):
1405 cmd = ['checkout'] 1528 cmd = ['checkout']
1406 if quiet: 1529 if quiet: