diff options
-rw-r--r-- | lib/bb/fetch/__init__.py | 123 | ||||
-rw-r--r-- | lib/bb/fetch/git.py | 56 |
2 files changed, 122 insertions, 57 deletions
diff --git a/lib/bb/fetch/__init__.py b/lib/bb/fetch/__init__.py index 7ba868c99..6fa0afaac 100644 --- a/lib/bb/fetch/__init__.py +++ b/lib/bb/fetch/__init__.py @@ -218,6 +218,15 @@ def init(urls, d, setup = True): urldata_cache[fn] = urldata return urldata +def mirror_from_string(data): + return [ i.split() for i in (data or "").replace('\\n','\n').split('\n') if i ] + +def removefile(f): + try: + os.remove(f) + except: + pass + def go(d, urls = None): """ Fetch all urls @@ -230,65 +239,64 @@ def go(d, urls = None): for u in urls: ud = urldata[u] m = ud.method - if ud.localfile: - if not m.forcefetch(u, ud, d) and os.path.exists(ud.md5) and os.path.exists(ud.localfile): - # File already present along with md5 stamp file - # Touch md5 file to show activity - try: - os.utime(ud.md5, None) - except: - # Errors aren't fatal here - pass - continue - lf = bb.utils.lockfile(ud.lockfile) - if not m.forcefetch(u, ud, d) and os.path.exists(ud.md5) and os.path.exists(ud.localfile): - # If someone else fetched this before we got the lock, - # notice and don't try again - try: - os.utime(ud.md5, None) - except: - # Errors aren't fatal here - pass - bb.utils.unlockfile(lf) - continue + localpath = "" - # First try fetching uri, u, from PREMIRRORS - mirrors = [ i.split() for i in (bb.data.getVar('PREMIRRORS', d, 1) or "").split('\n') if i ] - localpath = try_mirrors(d, u, mirrors) - if not localpath: + if not ud.localfile: + continue + + lf = bb.utils.lockfile(ud.lockfile) + + if m.try_premirror(u, ud, d): + # First try fetching uri, u, from PREMIRRORS + mirrors = mirror_from_string(bb.data.getVar('PREMIRRORS', d, True)) + localpath = try_mirrors(d, u, mirrors, False, m.forcefetch(u, ud, d)) + elif os.path.exists(ud.localfile): + localpath = ud.localfile + + # Need to re-test forcefetch() which will return true if our copy is too old + if m.forcefetch(u, ud, d) or not localpath: # Next try fetching from the original uri, u try: m.go(u, ud, d) localpath = ud.localpath except FetchError: + # Remove any incomplete file + removefile(ud.localpath) # Finally, try fetching uri, u, from MIRRORS - mirrors = [ i.split() for i in (bb.data.getVar('MIRRORS', d, 1) or "").split('\n') if i ] + mirrors = mirror_from_string(bb.data.getVar('MIRRORS', d, True)) localpath = try_mirrors (d, u, mirrors) if not localpath or not os.path.exists(localpath): raise FetchError("Unable to fetch URL %s from any source." % u) - if localpath: - ud.localpath = localpath - - if ud.localfile: - if not m.forcefetch(u, ud, d): - Fetch.write_md5sum(u, ud, d) - bb.utils.unlockfile(lf) + ud.localpath = localpath + if os.path.exists(ud.md5): + # Touch the md5 file to show active use of the download + try: + os.utime(ud.md5, None) + except: + # Errors aren't fatal here + pass + else: + Fetch.write_md5sum(u, ud, d) + bb.utils.unlockfile(lf) -def checkstatus(d): +def checkstatus(d, urls = None): """ Check all urls exist upstream init must have previously been called """ urldata = init([], d, True) - for u in urldata: + if not urls: + urls = urldata + + for u in urls: ud = urldata[u] m = ud.method - logger.info("Testing URL %s", u) + logger.debug("Testing URL %s", u) # First try checking uri, u, from PREMIRRORS - mirrors = [ i.split() for i in (bb.data.getVar('PREMIRRORS', d, 1) or "").split('\n') if i ] + mirrors = mirror_from_string(bb.data.getVar('PREMIRRORS', d, True)) ret = try_mirrors(d, u, mirrors, True) if not ret: # Next try checking from the original uri, u @@ -296,7 +304,7 @@ def checkstatus(d): ret = m.checkstatus(u, ud, d) except: # Finally, try checking uri, u, from MIRRORS - mirrors = [ i.split() for i in (bb.data.getVar('MIRRORS', d, 1) or "").split('\n') if i ] + mirrors = mirror_from_string(bb.data.getVar('MIRRORS', d, True)) ret = try_mirrors (d, u, mirrors, True) if not ret: @@ -396,7 +404,10 @@ def runfetchcmd(cmd, d, quiet = False): # rather than host provided # Also include some other variables. # FIXME: Should really include all export varaiables? - exportvars = ['PATH', 'GIT_PROXY_COMMAND', 'GIT_PROXY_HOST', 'GIT_PROXY_PORT', 'GIT_CONFIG', 'http_proxy', 'ftp_proxy', 'SSH_AUTH_SOCK', 'SSH_AGENT_PID', 'HOME'] + exportvars = ['PATH', 'GIT_PROXY_COMMAND', 'GIT_PROXY_HOST', + 'GIT_PROXY_PORT', 'GIT_CONFIG', 'http_proxy', 'ftp_proxy', + 'https_proxy', 'no_proxy', 'ALL_PROXY', 'all_proxy', + 'SSH_AUTH_SOCK', 'SSH_AGENT_PID', 'HOME'] for var in exportvars: val = data.getVar(var, d, True) @@ -428,7 +439,7 @@ def runfetchcmd(cmd, d, quiet = False): return output -def try_mirrors(d, uri, mirrors, check = False): +def try_mirrors(d, uri, mirrors, check = False, force = False): """ Try to use a mirrored version of the sources. This method will be automatically called before the fetchers go. @@ -438,7 +449,7 @@ def try_mirrors(d, uri, mirrors, check = False): mirrors is the list of mirrors we're going to try """ fpath = os.path.join(data.getVar("DL_DIR", d, 1), os.path.basename(uri)) - if not check and os.access(fpath, os.R_OK): + if not check and os.access(fpath, os.R_OK) and not force: logger.debug(1, "%s already exists, skipping checkout.", fpath) return fpath @@ -456,16 +467,19 @@ def try_mirrors(d, uri, mirrors, check = False): try: if check: - ud.method.checkstatus(newuri, ud, ld) + found = ud.method.checkstatus(newuri, ud, ld) + if found: + return found else: ud.method.go(newuri, ud, ld) - return ud.localpath + return ud.localpath except (bb.fetch.MissingParameterError, bb.fetch.FetchError, bb.fetch.MD5SumError): import sys (type, value, traceback) = sys.exc_info() logger.debug(2, "Mirror fetch failure: %s", value) + removefile(ud.localpath) continue return None @@ -495,12 +509,13 @@ class FetchData(object): if "localpath" in self.parm: # if user sets localpath for file, use it instead. self.localpath = self.parm["localpath"] + self.basename = os.path.basename(self.localpath) else: premirrors = bb.data.getVar('PREMIRRORS', d, True) local = "" if premirrors and self.url: aurl = self.url.split(";")[0] - mirrors = [ i.split() for i in (premirrors or "").split('\n') if i ] + mirrors = mirror_from_string(premirrors) for (find, replace) in mirrors: if replace.startswith("file://"): path = aurl.split("://")[1] @@ -519,10 +534,11 @@ class FetchData(object): # Horrible... bb.data.delVar("ISHOULDNEVEREXIST", d) - # Note: These files should always be in DL_DIR whereas localpath may not be. - basepath = bb.data.expand("${DL_DIR}/%s" % os.path.basename(self.localpath), d) - self.md5 = basepath + '.md5' - self.lockfile = basepath + '.lock' + if self.localpath is not None: + # Note: These files should always be in DL_DIR whereas localpath may not be. + basepath = bb.data.expand("${DL_DIR}/%s" % os.path.basename(self.localpath), d) + self.md5 = basepath + '.md5' + self.lockfile = basepath + '.lock' class Fetch(object): @@ -579,6 +595,17 @@ class Fetch(object): """ raise NoMethodError("Missing implementation for url") + def try_premirror(self, url, urldata, d): + """ + Should premirrors be used? + """ + if urldata.method.forcefetch(url, urldata, d): + return True + elif os.path.exists(urldata.md5) and os.path.exists(urldata.localfile): + return False + else: + return True + def checkstatus(self, url, urldata, d): """ Check the status of a URL diff --git a/lib/bb/fetch/git.py b/lib/bb/fetch/git.py index 2b252f388..a2fbd78cb 100644 --- a/lib/bb/fetch/git.py +++ b/lib/bb/fetch/git.py @@ -80,8 +80,33 @@ class Git(Fetch): ud.basecmd = data.getVar("FETCHCMD_git", d, True) or "git" + if 'noclone' in ud.parm: + ud.localfile = None + return None + return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile) + def forcefetch(self, url, ud, d): + if 'fullclone' in ud.parm: + return True + if 'noclone' in ud.parm: + return False + if os.path.exists(ud.localpath): + return False + if not self._contains_ref(ud.tag, d): + return True + return False + + def try_premirror(self, u, ud, d): + if 'noclone' in ud.parm: + return False + if os.path.exists(ud.clonedir): + return False + if os.path.exists(ud.localpath): + return False + + return True + def go(self, loc, ud, d): """Fetch url""" @@ -95,24 +120,37 @@ class Git(Fetch): coname = '%s' % (ud.tag) codir = os.path.join(ud.clonedir, coname) - if not os.path.exists(ud.clonedir): + # If we have no existing clone and no mirror tarball, try and obtain one + if not os.path.exists(ud.clonedir) and not os.path.exists(repofile): try: Fetch.try_mirrors(ud.mirrortarball) - bb.mkdirhier(ud.clonedir) - os.chdir(ud.clonedir) - runfetchcmd("tar -xzf %s" % (repofile), d) except: - runfetchcmd("%s clone -n %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.clonedir), d) + pass + + # If the checkout doesn't exist and the mirror tarball does, extract it + if not os.path.exists(ud.clonedir) and os.path.exists(repofile): + bb.mkdirhier(ud.clonedir) + os.chdir(ud.clonedir) + runfetchcmd("tar -xzf %s" % (repofile), d) + + # If the repo still doesn't exist, fallback to cloning it + if not os.path.exists(ud.clonedir): + runfetchcmd("%s clone -n %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.clonedir), d) os.chdir(ud.clonedir) - # Remove all but the .git directory - if not self._contains_ref(ud.tag, d): + # Update the checkout if needed + if not self._contains_ref(ud.tag, d) or 'fullclone' in ud.parm: + # Remove all but the .git directory runfetchcmd("rm * -Rf", d) - runfetchcmd("%s fetch %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.branch), d) + if 'fullclone' in ud.parm: + runfetchcmd("%s fetch --all" % (ud.basecmd), d) + else: + runfetchcmd("%s fetch %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.branch), d) runfetchcmd("%s fetch --tags %s://%s%s%s" % (ud.basecmd, ud.proto, username, ud.host, ud.path), d) runfetchcmd("%s prune-packed" % ud.basecmd, d) runfetchcmd("%s pack-redundant --all | xargs -r rm" % ud.basecmd, d) + # Generate a mirror tarball if needed os.chdir(ud.clonedir) mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) if mirror_tarballs != "0" or 'fullclone' in ud.parm: @@ -166,7 +204,7 @@ class Git(Fetch): """ Return a unique key for the url """ - return "git:" + ud.host + ud.path.replace('/', '.') + return "git:" + ud.host + ud.path.replace('/', '.') + ud.branch def _latest_revision(self, url, ud, d): """ |