diff options
Diffstat (limited to 'project.py')
-rw-r--r-- | project.py | 145 |
1 files changed, 134 insertions, 11 deletions
@@ -24,9 +24,11 @@ import urllib2 | |||
24 | 24 | ||
25 | from color import Coloring | 25 | from color import Coloring |
26 | from git_command import GitCommand | 26 | from git_command import GitCommand |
27 | from git_config import GitConfig, IsId | 27 | from git_config import GitConfig, IsId, GetSchemeFromUrl |
28 | from error import DownloadError | ||
28 | from error import GitError, HookError, ImportError, UploadError | 29 | from error import GitError, HookError, ImportError, UploadError |
29 | from error import ManifestInvalidRevisionError | 30 | from error import ManifestInvalidRevisionError |
31 | from progress import Progress | ||
30 | 32 | ||
31 | from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M | 33 | from 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: |