|
26 | 26 | import stat
|
27 | 27 | import errno
|
28 | 28 | from itertools import chain, izip, repeat
|
| 29 | +from urlparse import urlparse |
29 | 30 | import urllib
|
30 | 31 | import zipfile
|
31 | 32 |
|
@@ -250,7 +251,7 @@ def init(path, url):
|
250 | 251 | with cd(path):
|
251 | 252 | Bld.seturl(url)
|
252 | 253 |
|
253 |
| - def clone(url, path=None, depth=None, protocol=None): |
| 254 | + def clone(url, path=None, depth=None, protocol=None, cache=None): |
254 | 255 | m = Bld.isurl(url)
|
255 | 256 | if not m:
|
256 | 257 | raise ProcessException(1, "Not an mbed library build URL")
|
@@ -355,16 +356,15 @@ class Hg(object):
|
355 | 356 |
|
356 | 357 | def isurl(url):
|
357 | 358 | m_url = re.match(regex_url_ref, url.strip().replace('\\', '/'))
|
358 |
| - if m_url: |
359 |
| - return ((re.match(regex_hg_url, m_url.group(1)) or re.match(regex_mbed_url, m_url.group(1))) |
360 |
| - and not re.match(regex_build_url, m_url.group(1))) |
| 359 | + if m_url and not re.match(regex_build_url, m_url.group(1)): |
| 360 | + return re.match(regex_hg_url, m_url.group(1)) or re.match(regex_mbed_url, m_url.group(1)) |
361 | 361 | else:
|
362 | 362 | return False
|
363 | 363 |
|
364 | 364 | def init(path=None):
|
365 | 365 | popen([hg_cmd, 'init'] + ([path] if path else []) + (['-v'] if verbose else ['-q']))
|
366 | 366 |
|
367 |
| - def clone(url, name=None, depth=None, protocol=None): |
| 367 | + def clone(url, name=None, depth=None, protocol=None, cache=None): |
368 | 368 | popen([hg_cmd, 'clone', formaturl(url, protocol), name] + (['-v'] if verbose else ['-q']))
|
369 | 369 |
|
370 | 370 | def add(dest):
|
@@ -523,18 +523,17 @@ class Git(object):
|
523 | 523 |
|
524 | 524 | def isurl(url):
|
525 | 525 | m_url = re.match(regex_url_ref, url.strip().replace('\\', '/'))
|
526 |
| - if m_url: |
527 |
| - return (re.match(regex_git_url, m_url.group(1)) |
528 |
| - and not re.match(regex_mbed_url, m_url.group(1)) |
529 |
| - and not re.match(regex_build_url, m_url.group(1))) |
| 526 | + if m_url and not re.match(regex_build_url, m_url.group(1)) and not re.match(regex_mbed_url, m_url.group(1)): |
| 527 | + return re.match(regex_git_url, m_url.group(1)) |
530 | 528 | else:
|
531 | 529 | return False
|
532 | 530 |
|
533 | 531 | def init(path=None):
|
534 | 532 | popen([git_cmd, 'init'] + ([path] if path else []) + ([] if verbose else ['-q']))
|
535 | 533 |
|
536 |
| - def clone(url, name=None, depth=None, protocol=None): |
537 |
| - popen([git_cmd, 'clone', formaturl(url, protocol), name] + (['--depth', depth] if depth else []) + (['-v'] if verbose else ['-q'])) |
| 534 | + def clone(url, name=None, depth=None, protocol=None, cache=None): |
| 535 | + popen([git_cmd, 'clone', formaturl(url, protocol), name] + (['--depth', depth] if depth else []) + |
| 536 | + (['--reference', cache, '--dissociate'] if cache else []) + (['-v'] if verbose else ['-q'])) |
538 | 537 |
|
539 | 538 | def add(dest):
|
540 | 539 | log("Adding reference "+dest)
|
@@ -591,7 +590,7 @@ def checkout(rev):
|
591 | 590 | refs = Git.getrefs(rev)
|
592 | 591 | for ref in refs: # re-associate with a local or remote branch (rev is the same)
|
593 | 592 | branch = re.sub(r'^(.*?)\/(.*?)$', r'\2', ref)
|
594 |
| - log("Revision \"%s\" matches a branch \"%s\"reference. Re-associating with branch" % (rev, branch)) |
| 593 | + log("Revision \"%s\" matches a branch \"%s\" reference. Re-associating with branch" % (rev, branch)) |
595 | 594 | popen([git_cmd, 'checkout', branch] + ([] if verbose else ['-q']))
|
596 | 595 | break
|
597 | 596 |
|
@@ -755,6 +754,7 @@ class Repo(object):
|
755 | 754 | rev = None
|
756 | 755 | scm = None
|
757 | 756 | libs = []
|
| 757 | + cache = '/tmp/repo_cache' |
758 | 758 |
|
759 | 759 | @classmethod
|
760 | 760 | def fromurl(cls, url, path=None):
|
@@ -945,16 +945,34 @@ def clone(self, url, path, depth=None, protocol=None, **kwargs):
|
945 | 945 | sorted_scms = sorted(sorted_scms, key=lambda (m, _): not m)
|
946 | 946 |
|
947 | 947 | for _, scm in sorted_scms:
|
948 |
| - try: |
949 |
| - scm.clone(url, path, depth=depth, protocol=protocol, **kwargs) |
| 948 | + if scm.isurl(formaturl(url, 'https')): |
| 949 | + main = True |
| 950 | + cache = self.get_cache(url) |
| 951 | + |
| 952 | + # Try to clone with cache ref first |
| 953 | + if cache: |
| 954 | + try: |
| 955 | + scm.clone(url, path, depth=depth, protocol=protocol, cache=cache, **kwargs) |
| 956 | + main = False |
| 957 | + except ProcessException, e: |
| 958 | + if os.path.isdir(path): |
| 959 | + rmtree_readonly(path) |
| 960 | + |
| 961 | + # Main clone routine if the clone with cache ref failed (might occur if cache ref is dirty) |
| 962 | + if main: |
| 963 | + try: |
| 964 | + scm.clone(url, path, depth=depth, protocol=protocol, **kwargs) |
| 965 | + except ProcessException: |
| 966 | + if os.path.isdir(path): |
| 967 | + rmtree_readonly(path) |
| 968 | + continue |
| 969 | + |
950 | 970 | self.scm = scm
|
951 | 971 | self.url = url
|
952 | 972 | self.path = os.path.abspath(path)
|
953 | 973 | self.ignores()
|
| 974 | + self.set_cache(url) |
954 | 975 | return True
|
955 |
| - except ProcessException: |
956 |
| - if os.path.isdir(path): |
957 |
| - rmtree_readonly(path) |
958 | 976 | else:
|
959 | 977 | return False
|
960 | 978 |
|
@@ -994,6 +1012,24 @@ def rm_untracked(self):
|
994 | 1012 | action("Remove untracked library reference \"%s\"" % f)
|
995 | 1013 | os.remove(f)
|
996 | 1014 |
|
| 1015 | + def get_cache(self, url): |
| 1016 | + up = urlparse(formaturl(url, 'https')) |
| 1017 | + if self.cache and up and os.path.isdir(os.path.join(self.cache, up.netloc, re.sub(r'^/', '', up.path))): |
| 1018 | + return os.path.join(self.cache, up.netloc, re.sub(r'^/', '', up.path)) |
| 1019 | + |
| 1020 | + def set_cache(self, url): |
| 1021 | + up = urlparse(formaturl(url, 'https')) |
| 1022 | + if self.cache and up and os.path.isdir(self.path): |
| 1023 | + cpath = os.path.join(self.cache, up.netloc, re.sub(r'^/', '', up.path)) |
| 1024 | + if not os.path.isdir(cpath): |
| 1025 | + os.makedirs(cpath) |
| 1026 | + |
| 1027 | + scm_dir = '.'+self.scm.name |
| 1028 | + if os.path.isdir(os.path.join(cpath, scm_dir)): |
| 1029 | + rmtree_readonly(os.path.join(cpath, scm_dir)) |
| 1030 | + shutil.copytree(os.path.join(self.path, scm_dir), os.path.join(cpath, scm_dir)) |
| 1031 | + return False |
| 1032 | + |
997 | 1033 | def can_update(self, clean, force):
|
998 | 1034 | err = None
|
999 | 1035 | if (self.is_local or self.url is None) and not force:
|
|
0 commit comments