summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/fetch2
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/fetch2')
-rw-r--r--bitbake/lib/bb/fetch2/__init__.py824
-rw-r--r--bitbake/lib/bb/fetch2/bzr.py145
-rw-r--r--bitbake/lib/bb/fetch2/cvs.py172
-rw-r--r--bitbake/lib/bb/fetch2/git.py260
-rw-r--r--bitbake/lib/bb/fetch2/hg.py178
-rw-r--r--bitbake/lib/bb/fetch2/local.py73
-rw-r--r--bitbake/lib/bb/fetch2/osc.py143
-rw-r--r--bitbake/lib/bb/fetch2/perforce.py206
-rw-r--r--bitbake/lib/bb/fetch2/repo.py98
-rw-r--r--bitbake/lib/bb/fetch2/ssh.py118
-rw-r--r--bitbake/lib/bb/fetch2/svk.py104
-rw-r--r--bitbake/lib/bb/fetch2/svn.py202
-rw-r--r--bitbake/lib/bb/fetch2/wget.py93
13 files changed, 2616 insertions, 0 deletions
diff --git a/bitbake/lib/bb/fetch2/__init__.py b/bitbake/lib/bb/fetch2/__init__.py
new file mode 100644
index 0000000000..751e514121
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/__init__.py
@@ -0,0 +1,824 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementations
5
6Classes for obtaining upstream sources for the
7BitBake build tools.
8"""
9
10# Copyright (C) 2003, 2004 Chris Larson
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License version 2 as
14# published by the Free Software Foundation.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License along
22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24#
25# Based on functions from the base bb module, Copyright 2003 Holger Schurig
26
27from __future__ import absolute_import
28from __future__ import print_function
29import os, re
30import logging
31import bb
32from bb import data
33from bb import persist_data
34
35logger = logging.getLogger("BitBake.Fetch")
36
37class MalformedUrl(Exception):
38 """Exception raised when encountering an invalid url"""
39
40class FetchError(Exception):
41 """Exception raised when a download fails"""
42
43class NoMethodError(Exception):
44 """Exception raised when there is no method to obtain a supplied url or set of urls"""
45
46class MissingParameterError(Exception):
47 """Exception raised when a fetch method is missing a critical parameter in the url"""
48
49class ParameterError(Exception):
50 """Exception raised when a url cannot be proccessed due to invalid parameters."""
51
52class MD5SumError(Exception):
53 """Exception raised when a MD5SUM of a file does not match the expected one"""
54
55class InvalidSRCREV(Exception):
56 """Exception raised when an invalid SRCREV is encountered"""
57
58def decodeurl(url):
59 """Decodes an URL into the tokens (scheme, network location, path,
60 user, password, parameters).
61 """
62
63 m = re.compile('(?P<type>[^:]*)://((?P<user>.+)@)?(?P<location>[^;]+)(;(?P<parm>.*))?').match(url)
64 if not m:
65 raise MalformedUrl(url)
66
67 type = m.group('type')
68 location = m.group('location')
69 if not location:
70 raise MalformedUrl(url)
71 user = m.group('user')
72 parm = m.group('parm')
73
74 locidx = location.find('/')
75 if locidx != -1 and type.lower() != 'file':
76 host = location[:locidx]
77 path = location[locidx:]
78 else:
79 host = ""
80 path = location
81 if user:
82 m = re.compile('(?P<user>[^:]+)(:?(?P<pswd>.*))').match(user)
83 if m:
84 user = m.group('user')
85 pswd = m.group('pswd')
86 else:
87 user = ''
88 pswd = ''
89
90 p = {}
91 if parm:
92 for s in parm.split(';'):
93 s1, s2 = s.split('=')
94 p[s1] = s2
95
96 return (type, host, path, user, pswd, p)
97
98def encodeurl(decoded):
99 """Encodes a URL from tokens (scheme, network location, path,
100 user, password, parameters).
101 """
102
103 (type, host, path, user, pswd, p) = decoded
104
105 if not type or not path:
106 raise MissingParameterError("Type or path url components missing when encoding %s" % decoded)
107 url = '%s://' % type
108 if user:
109 url += "%s" % user
110 if pswd:
111 url += ":%s" % pswd
112 url += "@"
113 if host:
114 url += "%s" % host
115 url += "%s" % path
116 if p:
117 for parm in p:
118 url += ";%s=%s" % (parm, p[parm])
119
120 return url
121
122def uri_replace(uri, uri_find, uri_replace, d):
123 if not uri or not uri_find or not uri_replace:
124 logger.debug(1, "uri_replace: passed an undefined value, not replacing")
125 uri_decoded = list(decodeurl(uri))
126 uri_find_decoded = list(decodeurl(uri_find))
127 uri_replace_decoded = list(decodeurl(uri_replace))
128 result_decoded = ['', '', '', '', '', {}]
129 for i in uri_find_decoded:
130 loc = uri_find_decoded.index(i)
131 result_decoded[loc] = uri_decoded[loc]
132 if isinstance(i, basestring):
133 if (re.match(i, uri_decoded[loc])):
134 result_decoded[loc] = re.sub(i, uri_replace_decoded[loc], uri_decoded[loc])
135 if uri_find_decoded.index(i) == 2:
136 if d:
137 localfn = bb.fetch2.localpath(uri, d)
138 if localfn:
139 result_decoded[loc] = os.path.join(os.path.dirname(result_decoded[loc]), os.path.basename(bb.fetch2.localpath(uri, d)))
140 else:
141 return uri
142 return encodeurl(result_decoded)
143
144methods = []
145urldata_cache = {}
146saved_headrevs = {}
147
148def fetcher_init(d):
149 """
150 Called to initialize the fetchers once the configuration data is known.
151 Calls before this must not hit the cache.
152 """
153 pd = persist_data.persist(d)
154 # When to drop SCM head revisions controlled by user policy
155 srcrev_policy = bb.data.getVar('BB_SRCREV_POLICY', d, 1) or "clear"
156 if srcrev_policy == "cache":
157 logger.debug(1, "Keeping SRCREV cache due to cache policy of: %s", srcrev_policy)
158 elif srcrev_policy == "clear":
159 logger.debug(1, "Clearing SRCREV cache due to cache policy of: %s", srcrev_policy)
160 try:
161 bb.fetch2.saved_headrevs = pd['BB_URI_HEADREVS'].items()
162 except:
163 pass
164 del pd['BB_URI_HEADREVS']
165 else:
166 raise FetchError("Invalid SRCREV cache policy of: %s" % srcrev_policy)
167
168 for m in methods:
169 if hasattr(m, "init"):
170 m.init(d)
171
172def fetcher_compare_revisions(d):
173 """
174 Compare the revisions in the persistant cache with current values and
175 return true/false on whether they've changed.
176 """
177
178 pd = persist_data.persist(d)
179 data = pd['BB_URI_HEADREVS'].items()
180 data2 = bb.fetch2.saved_headrevs
181
182 changed = False
183 for key in data:
184 if key not in data2 or data2[key] != data[key]:
185 logger.debug(1, "%s changed", key)
186 changed = True
187 return True
188 else:
189 logger.debug(2, "%s did not change", key)
190 return False
191
192# Function call order is usually:
193# 1. init
194# 2. go
195# 3. localpaths
196# localpath can be called at any time
197
198def init(urls, d, setup = True):
199 urldata = {}
200
201 fn = bb.data.getVar('FILE', d, 1)
202 if fn in urldata_cache:
203 urldata = urldata_cache[fn]
204
205 for url in urls:
206 if url not in urldata:
207 urldata[url] = FetchData(url, d)
208
209 if setup:
210 for url in urldata:
211 if not urldata[url].setup:
212 urldata[url].setup_localpath(d)
213
214 urldata_cache[fn] = urldata
215 return urldata
216
217def mirror_from_string(data):
218 return [ i.split() for i in (data or "").replace('\\n','\n').split('\n') if i ]
219
220def removefile(f):
221 try:
222 os.remove(f)
223 except:
224 pass
225
226def verify_checksum(u, ud, d):
227 """
228 verify the MD5 and SHA256 checksum for downloaded src
229
230 return value:
231 - True: checksum matched
232 - False: checksum unmatched
233
234 if checksum is missing in recipes file, "BB_STRICT_CHECKSUM" decide the return value.
235 if BB_STRICT_CHECKSUM = "1" then return false as unmatched, otherwise return true as
236 matched
237 """
238
239 if not ud.type in ["http", "https", "ftp", "ftps"]:
240 return
241
242 md5data = bb.utils.md5_file(ud.localpath)
243 sha256data = bb.utils.sha256_file(ud.localpath)
244
245 if (ud.md5_expected == None or ud.sha256_expected == None):
246 logger.warn('Missing SRC_URI checksum for %s, consider adding to the recipe:\n'
247 'SRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"',
248 ud.localpath, ud.md5_name, md5data,
249 ud.sha256_name, sha256data)
250 if bb.data.getVar("BB_STRICT_CHECKSUM", d, True) == "1":
251 raise FetchError("No checksum specified for %s." % u)
252 return
253
254 if (ud.md5_expected != md5data or ud.sha256_expected != sha256data):
255 logger.error('The checksums for "%s" did not match.\n'
256 ' MD5: expected "%s", got "%s"\n'
257 ' SHA256: expected "%s", got "%s"\n',
258 ud.localpath, ud.md5_expected, md5data,
259 ud.sha256_expected, sha256data)
260 raise FetchError("%s checksum mismatch." % u)
261
262def go(d, urls = None):
263 """
264 Fetch all urls
265 init must have previously been called
266 """
267 if not urls:
268 urls = d.getVar("SRC_URI", 1).split()
269 urldata = init(urls, d, True)
270
271 for u in urls:
272 ud = urldata[u]
273 m = ud.method
274 localpath = ""
275
276 if not ud.localfile:
277 continue
278
279 lf = bb.utils.lockfile(ud.lockfile)
280
281 if m.try_premirror(u, ud, d):
282 # First try fetching uri, u, from PREMIRRORS
283 mirrors = mirror_from_string(bb.data.getVar('PREMIRRORS', d, True))
284 localpath = try_mirrors(d, u, mirrors, False, m.forcefetch(u, ud, d))
285 elif os.path.exists(ud.localfile):
286 localpath = ud.localfile
287
288 # Need to re-test forcefetch() which will return true if our copy is too old
289 if m.forcefetch(u, ud, d) or not localpath:
290 # Next try fetching from the original uri, u
291 try:
292 m.go(u, ud, d)
293 localpath = ud.localpath
294 except FetchError:
295 # Remove any incomplete file
296 removefile(ud.localpath)
297 # Finally, try fetching uri, u, from MIRRORS
298 mirrors = mirror_from_string(bb.data.getVar('MIRRORS', d, True))
299 localpath = try_mirrors (d, u, mirrors)
300 if not localpath or not os.path.exists(localpath):
301 raise FetchError("Unable to fetch URL %s from any source." % u)
302
303 ud.localpath = localpath
304
305 if os.path.exists(ud.md5):
306 # Touch the md5 file to show active use of the download
307 try:
308 os.utime(ud.md5, None)
309 except:
310 # Errors aren't fatal here
311 pass
312 else:
313 # Only check the checksums if we've not seen this item before
314 verify_checksum(u, ud, d)
315 Fetch.write_md5sum(u, ud, d)
316
317 bb.utils.unlockfile(lf)
318
319def checkstatus(d, urls = None):
320 """
321 Check all urls exist upstream
322 init must have previously been called
323 """
324 urldata = init([], d, True)
325
326 if not urls:
327 urls = urldata
328
329 for u in urls:
330 ud = urldata[u]
331 m = ud.method
332 logger.debug(1, "Testing URL %s", u)
333 # First try checking uri, u, from PREMIRRORS
334 mirrors = mirror_from_string(bb.data.getVar('PREMIRRORS', d, True))
335 ret = try_mirrors(d, u, mirrors, True)
336 if not ret:
337 # Next try checking from the original uri, u
338 try:
339 ret = m.checkstatus(u, ud, d)
340 except:
341 # Finally, try checking uri, u, from MIRRORS
342 mirrors = mirror_from_string(bb.data.getVar('MIRRORS', d, True))
343 ret = try_mirrors (d, u, mirrors, True)
344
345 if not ret:
346 raise FetchError("URL %s doesn't work" % u)
347
348def localpaths(d):
349 """
350 Return a list of the local filenames, assuming successful fetch
351 """
352 local = []
353 urldata = init([], d, True)
354
355 for u in urldata:
356 ud = urldata[u]
357 local.append(ud.localpath)
358
359 return local
360
361def get_autorev(d):
362 # only not cache src rev in autorev case
363 if bb.data.getVar('BB_SRCREV_POLICY', d, True) != "cache":
364 bb.data.setVar('__BB_DONT_CACHE', '1', d)
365 return "AUTOINC"
366
367def get_srcrev(d):
368 """
369 Return the version string for the current package
370 (usually to be used as PV)
371 Most packages usually only have one SCM so we just pass on the call.
372 In the multi SCM case, we build a value based on SRCREV_FORMAT which must
373 have been set.
374 """
375
376 scms = []
377
378 # Only call setup_localpath on URIs which supports_srcrev()
379 urldata = init(bb.data.getVar('SRC_URI', d, 1).split(), d, False)
380 for u in urldata:
381 ud = urldata[u]
382 if ud.method.supports_srcrev():
383 if not ud.setup:
384 ud.setup_localpath(d)
385 scms.append(u)
386
387 if len(scms) == 0:
388 logger.error("SRCREV was used yet no valid SCM was found in SRC_URI")
389 raise ParameterError
390
391 if len(scms) == 1:
392 return urldata[scms[0]].method.sortable_revision(scms[0], urldata[scms[0]], d)
393
394 #
395 # Mutiple SCMs are in SRC_URI so we resort to SRCREV_FORMAT
396 #
397 format = bb.data.getVar('SRCREV_FORMAT', d, 1)
398 if not format:
399 logger.error("The SRCREV_FORMAT variable must be set when multiple SCMs are used.")
400 raise ParameterError
401
402 for scm in scms:
403 if 'name' in urldata[scm].parm:
404 name = urldata[scm].parm["name"]
405 rev = urldata[scm].method.sortable_revision(scm, urldata[scm], d)
406 format = format.replace(name, rev)
407
408 return format
409
410def localpath(url, d, cache = True):
411 """
412 Called from the parser with cache=False since the cache isn't ready
413 at this point. Also called from classed in OE e.g. patch.bbclass
414 """
415 ud = init([url], d)
416 if ud[url].method:
417 return ud[url].localpath
418 return url
419
420def runfetchcmd(cmd, d, quiet = False):
421 """
422 Run cmd returning the command output
423 Raise an error if interrupted or cmd fails
424 Optionally echo command output to stdout
425 """
426
427 # Need to export PATH as binary could be in metadata paths
428 # rather than host provided
429 # Also include some other variables.
430 # FIXME: Should really include all export varaiables?
431 exportvars = ['PATH', 'GIT_PROXY_COMMAND', 'GIT_PROXY_HOST',
432 'GIT_PROXY_PORT', 'GIT_CONFIG', 'http_proxy', 'ftp_proxy',
433 'https_proxy', 'no_proxy', 'ALL_PROXY', 'all_proxy',
434 'SSH_AUTH_SOCK', 'SSH_AGENT_PID', 'HOME']
435
436 for var in exportvars:
437 val = data.getVar(var, d, True)
438 if val:
439 cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
440
441 logger.debug(1, "Running %s", cmd)
442
443 # redirect stderr to stdout
444 stdout_handle = os.popen(cmd + " 2>&1", "r")
445 output = ""
446
447 while True:
448 line = stdout_handle.readline()
449 if not line:
450 break
451 if not quiet:
452 print(line, end=' ')
453 output += line
454
455 status = stdout_handle.close() or 0
456 signal = status >> 8
457 exitstatus = status & 0xff
458
459 if signal:
460 raise FetchError("Fetch command %s failed with signal %s, output:\n%s" % (cmd, signal, output))
461 elif status != 0:
462 raise FetchError("Fetch command %s failed with exit code %s, output:\n%s" % (cmd, status, output))
463
464 return output
465
466def try_mirrors(d, uri, mirrors, check = False, force = False):
467 """
468 Try to use a mirrored version of the sources.
469 This method will be automatically called before the fetchers go.
470
471 d Is a bb.data instance
472 uri is the original uri we're trying to download
473 mirrors is the list of mirrors we're going to try
474 """
475 fpath = os.path.join(data.getVar("DL_DIR", d, 1), os.path.basename(uri))
476 if not check and os.access(fpath, os.R_OK) and not force:
477 logger.debug(1, "%s already exists, skipping checkout.", fpath)
478 return fpath
479
480 ld = d.createCopy()
481 for (find, replace) in mirrors:
482 newuri = uri_replace(uri, find, replace, ld)
483 if newuri != uri:
484 try:
485 ud = FetchData(newuri, ld)
486 except bb.fetch2.NoMethodError:
487 logger.debug(1, "No method for %s", uri)
488 continue
489
490 ud.setup_localpath(ld)
491
492 try:
493 if check:
494 found = ud.method.checkstatus(newuri, ud, ld)
495 if found:
496 return found
497 else:
498 ud.method.go(newuri, ud, ld)
499 return ud.localpath
500 except (bb.fetch2.MissingParameterError,
501 bb.fetch2.FetchError,
502 bb.fetch2.MD5SumError):
503 import sys
504 (type, value, traceback) = sys.exc_info()
505 logger.debug(2, "Mirror fetch failure: %s", value)
506 removefile(ud.localpath)
507 continue
508 return None
509
510
511class FetchData(object):
512 """
513 A class which represents the fetcher state for a given URI.
514 """
515 def __init__(self, url, d):
516 self.localfile = ""
517 (self.type, self.host, self.path, self.user, self.pswd, self.parm) = decodeurl(data.expand(url, d))
518 self.date = Fetch.getSRCDate(self, d)
519 self.url = url
520 if not self.user and "user" in self.parm:
521 self.user = self.parm["user"]
522 if not self.pswd and "pswd" in self.parm:
523 self.pswd = self.parm["pswd"]
524 self.setup = False
525
526 if "name" in self.parm:
527 self.md5_name = "%s.md5sum" % self.parm["name"]
528 self.sha256_name = "%s.sha256sum" % self.parm["name"]
529 else:
530 self.md5_name = "md5sum"
531 self.sha256_name = "sha256sum"
532 self.md5_expected = bb.data.getVarFlag("SRC_URI", self.md5_name, d)
533 self.sha256_expected = bb.data.getVarFlag("SRC_URI", self.sha256_name, d)
534
535 for m in methods:
536 if m.supports(url, self, d):
537 self.method = m
538 if hasattr(m,"urldata_init"):
539 m.urldata_init(self, d)
540 if m.supports_srcrev():
541 self.revision = Fetch.srcrev_internal_helper(self, d);
542 return
543 raise NoMethodError("Missing implementation for url %s" % url)
544
545 def setup_localpath(self, d):
546 self.setup = True
547 if "localpath" in self.parm:
548 # if user sets localpath for file, use it instead.
549 self.localpath = self.parm["localpath"]
550 self.basename = os.path.basename(self.localpath)
551 else:
552 premirrors = bb.data.getVar('PREMIRRORS', d, True)
553 local = ""
554 if premirrors and self.url:
555 aurl = self.url.split(";")[0]
556 mirrors = mirror_from_string(premirrors)
557 for (find, replace) in mirrors:
558 if replace.startswith("file://"):
559 path = aurl.split("://")[1]
560 path = path.split(";")[0]
561 local = replace.split("://")[1] + os.path.basename(path)
562 if local == aurl or not os.path.exists(local) or os.path.isdir(local):
563 local = ""
564 self.localpath = local
565 if not local:
566 self.localpath = self.method.localpath(self.url, self, d)
567 # We have to clear data's internal caches since the cached value of SRCREV is now wrong.
568 # Horrible...
569 bb.data.delVar("ISHOULDNEVEREXIST", d)
570
571 if self.localpath is not None:
572 # Note: These files should always be in DL_DIR whereas localpath may not be.
573 basepath = bb.data.expand("${DL_DIR}/%s" % os.path.basename(self.localpath), d)
574 self.md5 = basepath + '.md5'
575 self.lockfile = basepath + '.lock'
576
577
578class Fetch(object):
579 """Base class for 'fetch'ing data"""
580
581 def __init__(self, urls = []):
582 self.urls = []
583
584 def supports(self, url, urldata, d):
585 """
586 Check to see if this fetch class supports a given url.
587 """
588 return 0
589
590 def localpath(self, url, urldata, d):
591 """
592 Return the local filename of a given url assuming a successful fetch.
593 Can also setup variables in urldata for use in go (saving code duplication
594 and duplicate code execution)
595 """
596 return url
597 def _strip_leading_slashes(self, relpath):
598 """
599 Remove leading slash as os.path.join can't cope
600 """
601 while os.path.isabs(relpath):
602 relpath = relpath[1:]
603 return relpath
604
605 def setUrls(self, urls):
606 self.__urls = urls
607
608 def getUrls(self):
609 return self.__urls
610
611 urls = property(getUrls, setUrls, None, "Urls property")
612
613 def forcefetch(self, url, urldata, d):
614 """
615 Force a fetch, even if localpath exists?
616 """
617 return False
618
619 def supports_srcrev(self):
620 """
621 The fetcher supports auto source revisions (SRCREV)
622 """
623 return False
624
625 def go(self, url, urldata, d):
626 """
627 Fetch urls
628 Assumes localpath was called first
629 """
630 raise NoMethodError("Missing implementation for url")
631
632 def try_premirror(self, url, urldata, d):
633 """
634 Should premirrors be used?
635 """
636 if urldata.method.forcefetch(url, urldata, d):
637 return True
638 elif os.path.exists(urldata.md5) and os.path.exists(urldata.localfile):
639 return False
640 else:
641 return True
642
643 def checkstatus(self, url, urldata, d):
644 """
645 Check the status of a URL
646 Assumes localpath was called first
647 """
648 logger.info("URL %s could not be checked for status since no method exists.", url)
649 return True
650
651 def getSRCDate(urldata, d):
652 """
653 Return the SRC Date for the component
654
655 d the bb.data module
656 """
657 if "srcdate" in urldata.parm:
658 return urldata.parm['srcdate']
659
660 pn = data.getVar("PN", d, 1)
661
662 if pn:
663 return data.getVar("SRCDATE_%s" % pn, d, 1) or data.getVar("CVSDATE_%s" % pn, d, 1) or data.getVar("SRCDATE", d, 1) or data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1)
664
665 return data.getVar("SRCDATE", d, 1) or data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1)
666 getSRCDate = staticmethod(getSRCDate)
667
668 def srcrev_internal_helper(ud, d):
669 """
670 Return:
671 a) a source revision if specified
672 b) latest revision if SREREV="AUTOINC"
673 c) None if not specified
674 """
675
676 if 'rev' in ud.parm:
677 return ud.parm['rev']
678
679 if 'tag' in ud.parm:
680 return ud.parm['tag']
681
682 rev = None
683 if 'name' in ud.parm:
684 pn = data.getVar("PN", d, 1)
685 rev = data.getVar("SRCREV_%s_pn-%s" % (ud.parm['name'], pn), d, 1)
686 if not rev:
687 rev = data.getVar("SRCREV_pn-%s_%s" % (pn, ud.parm['name']), d, 1)
688 if not rev:
689 rev = data.getVar("SRCREV_%s" % (ud.parm['name']), d, 1)
690 if not rev:
691 rev = data.getVar("SRCREV", d, 1)
692 if rev == "INVALID":
693 raise InvalidSRCREV("Please set SRCREV to a valid value")
694 if rev == "AUTOINC":
695 rev = ud.method.latest_revision(ud.url, ud, d)
696
697 return rev
698
699 srcrev_internal_helper = staticmethod(srcrev_internal_helper)
700
701 def localcount_internal_helper(ud, d):
702 """
703 Return:
704 a) a locked localcount if specified
705 b) None otherwise
706 """
707
708 localcount = None
709 if 'name' in ud.parm:
710 pn = data.getVar("PN", d, 1)
711 localcount = data.getVar("LOCALCOUNT_" + ud.parm['name'], d, 1)
712 if not localcount:
713 localcount = data.getVar("LOCALCOUNT", d, 1)
714 return localcount
715
716 localcount_internal_helper = staticmethod(localcount_internal_helper)
717
718 def verify_md5sum(ud, got_sum):
719 """
720 Verify the md5sum we wanted with the one we got
721 """
722 wanted_sum = ud.parm.get('md5sum')
723 if not wanted_sum:
724 return True
725
726 return wanted_sum == got_sum
727 verify_md5sum = staticmethod(verify_md5sum)
728
729 def write_md5sum(url, ud, d):
730 md5data = bb.utils.md5_file(ud.localpath)
731 # verify the md5sum
732 if not Fetch.verify_md5sum(ud, md5data):
733 raise MD5SumError(url)
734
735 md5out = file(ud.md5, 'w')
736 md5out.write(md5data)
737 md5out.close()
738 write_md5sum = staticmethod(write_md5sum)
739
740 def latest_revision(self, url, ud, d):
741 """
742 Look in the cache for the latest revision, if not present ask the SCM.
743 """
744 if not hasattr(self, "_latest_revision"):
745 raise ParameterError
746
747 pd = persist_data.persist(d)
748 revs = pd['BB_URI_HEADREVS']
749 key = self.generate_revision_key(url, ud, d)
750 rev = revs[key]
751 if rev != None:
752 return str(rev)
753
754 revs[key] = rev = self._latest_revision(url, ud, d)
755 return rev
756
757 def sortable_revision(self, url, ud, d):
758 """
759
760 """
761 if hasattr(self, "_sortable_revision"):
762 return self._sortable_revision(url, ud, d)
763
764 pd = persist_data.persist(d)
765 localcounts = pd['BB_URI_LOCALCOUNT']
766 key = self.generate_revision_key(url, ud, d)
767
768 latest_rev = self._build_revision(url, ud, d)
769 last_rev = localcounts[key + '_rev']
770 uselocalcount = bb.data.getVar("BB_LOCALCOUNT_OVERRIDE", d, True) or False
771 count = None
772 if uselocalcount:
773 count = Fetch.localcount_internal_helper(ud, d)
774 if count is None:
775 count = localcounts[key + '_count']
776
777 if last_rev == latest_rev:
778 return str(count + "+" + latest_rev)
779
780 buildindex_provided = hasattr(self, "_sortable_buildindex")
781 if buildindex_provided:
782 count = self._sortable_buildindex(url, ud, d, latest_rev)
783
784 if count is None:
785 count = "0"
786 elif uselocalcount or buildindex_provided:
787 count = str(count)
788 else:
789 count = str(int(count) + 1)
790
791 localcounts[key + '_rev'] = latest_rev
792 localcounts[key + '_count'] = count
793
794 return str(count + "+" + latest_rev)
795
796 def generate_revision_key(self, url, ud, d):
797 key = self._revision_key(url, ud, d)
798 return "%s-%s" % (key, bb.data.getVar("PN", d, True) or "")
799
800from . import cvs
801from . import git
802from . import local
803from . import svn
804from . import wget
805from . import svk
806from . import ssh
807from . import perforce
808from . import bzr
809from . import hg
810from . import osc
811from . import repo
812
813methods.append(local.Local())
814methods.append(wget.Wget())
815methods.append(svn.Svn())
816methods.append(git.Git())
817methods.append(cvs.Cvs())
818methods.append(svk.Svk())
819methods.append(ssh.SSH())
820methods.append(perforce.Perforce())
821methods.append(bzr.Bzr())
822methods.append(hg.Hg())
823methods.append(osc.Osc())
824methods.append(repo.Repo())
diff --git a/bitbake/lib/bb/fetch2/bzr.py b/bitbake/lib/bb/fetch2/bzr.py
new file mode 100644
index 0000000000..97b042b2a5
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/bzr.py
@@ -0,0 +1,145 @@
1"""
2BitBake 'Fetch' implementation for bzr.
3
4"""
5
6# Copyright (C) 2007 Ross Burton
7# Copyright (C) 2007 Richard Purdie
8#
9# Classes for obtaining upstream sources for the
10# BitBake build tools.
11# Copyright (C) 2003, 2004 Chris Larson
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
26import os
27import sys
28import logging
29import bb
30from bb import data
31from bb.fetch2 import Fetch, FetchError, runfetchcmd, logger
32
33class Bzr(Fetch):
34 def supports(self, url, ud, d):
35 return ud.type in ['bzr']
36
37 def urldata_init(self, ud, d):
38 """
39 init bzr specific variable within url data
40 """
41 # Create paths to bzr checkouts
42 relpath = self._strip_leading_slashes(ud.path)
43 ud.pkgdir = os.path.join(data.expand('${BZRDIR}', d), ud.host, relpath)
44
45 def localpath (self, url, ud, d):
46 if not ud.revision:
47 ud.revision = self.latest_revision(url, ud, d)
48
49 ud.localfile = data.expand('bzr_%s_%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.revision), d)
50
51 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
52
53 def _buildbzrcommand(self, ud, d, command):
54 """
55 Build up an bzr commandline based on ud
56 command is "fetch", "update", "revno"
57 """
58
59 basecmd = data.expand('${FETCHCMD_bzr}', d)
60
61 proto = ud.parm.get('proto', 'http')
62
63 bzrroot = ud.host + ud.path
64
65 options = []
66
67 if command is "revno":
68 bzrcmd = "%s revno %s %s://%s" % (basecmd, " ".join(options), proto, bzrroot)
69 else:
70 if ud.revision:
71 options.append("-r %s" % ud.revision)
72
73 if command is "fetch":
74 bzrcmd = "%s co %s %s://%s" % (basecmd, " ".join(options), proto, bzrroot)
75 elif command is "update":
76 bzrcmd = "%s pull %s --overwrite" % (basecmd, " ".join(options))
77 else:
78 raise FetchError("Invalid bzr command %s" % command)
79
80 return bzrcmd
81
82 def go(self, loc, ud, d):
83 """Fetch url"""
84
85 if os.access(os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir), '.bzr'), os.R_OK):
86 bzrcmd = self._buildbzrcommand(ud, d, "update")
87 logger.debug(1, "BZR Update %s", loc)
88 os.chdir(os.path.join (ud.pkgdir, os.path.basename(ud.path)))
89 runfetchcmd(bzrcmd, d)
90 else:
91 bb.utils.remove(os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir)), True)
92 bzrcmd = self._buildbzrcommand(ud, d, "fetch")
93 logger.debug(1, "BZR Checkout %s", loc)
94 bb.mkdirhier(ud.pkgdir)
95 os.chdir(ud.pkgdir)
96 logger.debug(1, "Running %s", bzrcmd)
97 runfetchcmd(bzrcmd, d)
98
99 os.chdir(ud.pkgdir)
100
101 scmdata = ud.parm.get("scmdata", "")
102 if scmdata == "keep":
103 tar_flags = ""
104 else:
105 tar_flags = "--exclude '.bzr' --exclude '.bzrtags'"
106
107 # tar them up to a defined filename
108 try:
109 runfetchcmd("tar %s -czf %s %s" % (tar_flags, ud.localpath, os.path.basename(ud.pkgdir)), d)
110 except:
111 t, v, tb = sys.exc_info()
112 try:
113 os.unlink(ud.localpath)
114 except OSError:
115 pass
116 raise t, v, tb
117
118 def supports_srcrev(self):
119 return True
120
121 def _revision_key(self, url, ud, d):
122 """
123 Return a unique key for the url
124 """
125 return "bzr:" + ud.pkgdir
126
127 def _latest_revision(self, url, ud, d):
128 """
129 Return the latest upstream revision number
130 """
131 logger.debug(2, "BZR fetcher hitting network for %s", url)
132
133 output = runfetchcmd(self._buildbzrcommand(ud, d, "revno"), d, True)
134
135 return output.strip()
136
137 def _sortable_revision(self, url, ud, d):
138 """
139 Return a sortable revision number which in our case is the revision number
140 """
141
142 return self._build_revision(url, ud, d)
143
144 def _build_revision(self, url, ud, d):
145 return ud.revision
diff --git a/bitbake/lib/bb/fetch2/cvs.py b/bitbake/lib/bb/fetch2/cvs.py
new file mode 100644
index 0000000000..1570cab9c3
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/cvs.py
@@ -0,0 +1,172 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementations
5
6Classes for obtaining upstream sources for the
7BitBake build tools.
8
9"""
10
11# Copyright (C) 2003, 2004 Chris Larson
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25#
26#Based on functions from the base bb module, Copyright 2003 Holger Schurig
27#
28
29import os
30import logging
31import bb
32from bb import data
33from bb.fetch2 import Fetch, FetchError, MissingParameterError, logger
34
35class Cvs(Fetch):
36 """
37 Class to fetch a module or modules from cvs repositories
38 """
39 def supports(self, url, ud, d):
40 """
41 Check to see if a given url can be fetched with cvs.
42 """
43 return ud.type in ['cvs']
44
45 def localpath(self, url, ud, d):
46 if not "module" in ud.parm:
47 raise MissingParameterError("cvs method needs a 'module' parameter")
48 ud.module = ud.parm["module"]
49
50 ud.tag = ud.parm.get('tag', "")
51
52 # Override the default date in certain cases
53 if 'date' in ud.parm:
54 ud.date = ud.parm['date']
55 elif ud.tag:
56 ud.date = ""
57
58 norecurse = ''
59 if 'norecurse' in ud.parm:
60 norecurse = '_norecurse'
61
62 fullpath = ''
63 if 'fullpath' in ud.parm:
64 fullpath = '_fullpath'
65
66 ud.localfile = data.expand('%s_%s_%s_%s%s%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.tag, ud.date, norecurse, fullpath), d)
67
68 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
69
70 def forcefetch(self, url, ud, d):
71 if (ud.date == "now"):
72 return True
73 return False
74
75 def go(self, loc, ud, d):
76
77 method = ud.parm.get('method', 'pserver')
78 localdir = ud.parm.get('localdir', ud.module)
79 cvs_port = ud.parm.get('port', '')
80
81 cvs_rsh = None
82 if method == "ext":
83 if "rsh" in ud.parm:
84 cvs_rsh = ud.parm["rsh"]
85
86 if method == "dir":
87 cvsroot = ud.path
88 else:
89 cvsroot = ":" + method
90 cvsproxyhost = data.getVar('CVS_PROXY_HOST', d, True)
91 if cvsproxyhost:
92 cvsroot += ";proxy=" + cvsproxyhost
93 cvsproxyport = data.getVar('CVS_PROXY_PORT', d, True)
94 if cvsproxyport:
95 cvsroot += ";proxyport=" + cvsproxyport
96 cvsroot += ":" + ud.user
97 if ud.pswd:
98 cvsroot += ":" + ud.pswd
99 cvsroot += "@" + ud.host + ":" + cvs_port + ud.path
100
101 options = []
102 if 'norecurse' in ud.parm:
103 options.append("-l")
104 if ud.date:
105 # treat YYYYMMDDHHMM specially for CVS
106 if len(ud.date) == 12:
107 options.append("-D \"%s %s:%s UTC\"" % (ud.date[0:8], ud.date[8:10], ud.date[10:12]))
108 else:
109 options.append("-D \"%s UTC\"" % ud.date)
110 if ud.tag:
111 options.append("-r %s" % ud.tag)
112
113 localdata = data.createCopy(d)
114 data.setVar('OVERRIDES', "cvs:%s" % data.getVar('OVERRIDES', localdata), localdata)
115 data.update_data(localdata)
116
117 data.setVar('CVSROOT', cvsroot, localdata)
118 data.setVar('CVSCOOPTS', " ".join(options), localdata)
119 data.setVar('CVSMODULE', ud.module, localdata)
120 cvscmd = data.getVar('FETCHCOMMAND', localdata, 1)
121 cvsupdatecmd = data.getVar('UPDATECOMMAND', localdata, 1)
122
123 if cvs_rsh:
124 cvscmd = "CVS_RSH=\"%s\" %s" % (cvs_rsh, cvscmd)
125 cvsupdatecmd = "CVS_RSH=\"%s\" %s" % (cvs_rsh, cvsupdatecmd)
126
127 # create module directory
128 logger.debug(2, "Fetch: checking for module directory")
129 pkg = data.expand('${PN}', d)
130 pkgdir = os.path.join(data.expand('${CVSDIR}', localdata), pkg)
131 moddir = os.path.join(pkgdir, localdir)
132 if os.access(os.path.join(moddir, 'CVS'), os.R_OK):
133 logger.info("Update " + loc)
134 # update sources there
135 os.chdir(moddir)
136 myret = os.system(cvsupdatecmd)
137 else:
138 logger.info("Fetch " + loc)
139 # check out sources there
140 bb.mkdirhier(pkgdir)
141 os.chdir(pkgdir)
142 logger.debug(1, "Running %s", cvscmd)
143 myret = os.system(cvscmd)
144
145 if myret != 0 or not os.access(moddir, os.R_OK):
146 try:
147 os.rmdir(moddir)
148 except OSError:
149 pass
150 raise FetchError(ud.module)
151
152 scmdata = ud.parm.get("scmdata", "")
153 if scmdata == "keep":
154 tar_flags = ""
155 else:
156 tar_flags = "--exclude 'CVS'"
157
158 # tar them up to a defined filename
159 if 'fullpath' in ud.parm:
160 os.chdir(pkgdir)
161 myret = os.system("tar %s -czf %s %s" % (tar_flags, ud.localpath, localdir))
162 else:
163 os.chdir(moddir)
164 os.chdir('..')
165 myret = os.system("tar %s -czf %s %s" % (tar_flags, ud.localpath, os.path.basename(moddir)))
166
167 if myret != 0:
168 try:
169 os.unlink(ud.localpath)
170 except OSError:
171 pass
172 raise FetchError(ud.module)
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
new file mode 100644
index 0000000000..c62145770f
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -0,0 +1,260 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' git implementation
5
6"""
7
8#Copyright (C) 2005 Richard Purdie
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License version 2 as
12# published by the Free Software Foundation.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License along
20# with this program; if not, write to the Free Software Foundation, Inc.,
21# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23import os
24import bb
25from bb import data
26from bb.fetch2 import Fetch
27from bb.fetch2 import runfetchcmd
28from bb.fetch2 import logger
29
30class Git(Fetch):
31 """Class to fetch a module or modules from git repositories"""
32 def init(self, d):
33 #
34 # Only enable _sortable revision if the key is set
35 #
36 if bb.data.getVar("BB_GIT_CLONE_FOR_SRCREV", d, True):
37 self._sortable_buildindex = self._sortable_buildindex_disabled
38 def supports(self, url, ud, d):
39 """
40 Check to see if a given url can be fetched with git.
41 """
42 return ud.type in ['git']
43
44 def urldata_init(self, ud, d):
45 """
46 init git specific variable within url data
47 so that the git method like latest_revision() can work
48 """
49 if 'protocol' in ud.parm:
50 ud.proto = ud.parm['protocol']
51 elif not ud.host:
52 ud.proto = 'file'
53 else:
54 ud.proto = "rsync"
55
56 ud.branch = ud.parm.get("branch", "master")
57
58 gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
59 ud.mirrortarball = 'git_%s.tar.gz' % (gitsrcname)
60 ud.clonedir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
61
62 ud.basecmd = data.getVar("FETCHCMD_git", d, True) or "git"
63
64 def localpath(self, url, ud, d):
65 ud.tag = ud.revision
66 if not ud.tag or ud.tag == "master":
67 ud.tag = self.latest_revision(url, ud, d)
68
69 subdir = ud.parm.get("subpath", "")
70 if subdir != "":
71 if subdir.endswith("/"):
72 subdir = subdir[:-1]
73 subdirpath = os.path.join(ud.path, subdir);
74 else:
75 subdirpath = ud.path;
76
77 if 'fullclone' in ud.parm:
78 ud.localfile = ud.mirrortarball
79 else:
80 ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, subdirpath.replace('/', '.'), ud.tag), d)
81
82 if 'noclone' in ud.parm:
83 ud.localfile = None
84 return None
85
86 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
87
88 def forcefetch(self, url, ud, d):
89 if 'fullclone' in ud.parm:
90 return True
91 if 'noclone' in ud.parm:
92 return False
93 if os.path.exists(ud.localpath):
94 return False
95 if not self._contains_ref(ud.tag, d):
96 return True
97 return False
98
99 def try_premirror(self, u, ud, d):
100 if 'noclone' in ud.parm:
101 return False
102 if os.path.exists(ud.clonedir):
103 return False
104 if os.path.exists(ud.localpath):
105 return False
106
107 return True
108
109 def go(self, loc, ud, d):
110 """Fetch url"""
111
112 if ud.user:
113 username = ud.user + '@'
114 else:
115 username = ""
116
117 repofile = os.path.join(data.getVar("DL_DIR", d, 1), ud.mirrortarball)
118
119 coname = '%s' % (ud.tag)
120 codir = os.path.join(ud.clonedir, coname)
121
122 # If we have no existing clone and no mirror tarball, try and obtain one
123 if not os.path.exists(ud.clonedir) and not os.path.exists(repofile):
124 try:
125 Fetch.try_mirrors(ud.mirrortarball)
126 except:
127 pass
128
129 # If the checkout doesn't exist and the mirror tarball does, extract it
130 if not os.path.exists(ud.clonedir) and os.path.exists(repofile):
131 bb.mkdirhier(ud.clonedir)
132 os.chdir(ud.clonedir)
133 runfetchcmd("tar -xzf %s" % (repofile), d)
134
135 # If the repo still doesn't exist, fallback to cloning it
136 if not os.path.exists(ud.clonedir):
137 runfetchcmd("%s clone -n %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.clonedir), d)
138
139 os.chdir(ud.clonedir)
140 # Update the checkout if needed
141 if not self._contains_ref(ud.tag, d) or 'fullclone' in ud.parm:
142 # Remove all but the .git directory
143 runfetchcmd("rm * -Rf", d)
144 if 'fullclone' in ud.parm:
145 runfetchcmd("%s fetch --all" % (ud.basecmd), d)
146 else:
147 runfetchcmd("%s fetch %s://%s%s%s %s" % (ud.basecmd, ud.proto, username, ud.host, ud.path, ud.branch), d)
148 runfetchcmd("%s fetch --tags %s://%s%s%s" % (ud.basecmd, ud.proto, username, ud.host, ud.path), d)
149 runfetchcmd("%s prune-packed" % ud.basecmd, d)
150 runfetchcmd("%s pack-redundant --all | xargs -r rm" % ud.basecmd, d)
151
152 # Generate a mirror tarball if needed
153 os.chdir(ud.clonedir)
154 mirror_tarballs = data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True)
155 if mirror_tarballs != "0" or 'fullclone' in ud.parm:
156 logger.info("Creating tarball of git repository")
157 runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d)
158
159 if 'fullclone' in ud.parm:
160 return
161
162 if os.path.exists(codir):
163 bb.utils.prunedir(codir)
164
165 subdir = ud.parm.get("subpath", "")
166 if subdir != "":
167 if subdir.endswith("/"):
168 subdirbase = os.path.basename(subdir[:-1])
169 else:
170 subdirbase = os.path.basename(subdir)
171 else:
172 subdirbase = ""
173
174 if subdir != "":
175 readpathspec = ":%s" % (subdir)
176 codir = os.path.join(codir, "git")
177 coprefix = os.path.join(codir, subdirbase, "")
178 else:
179 readpathspec = ""
180 coprefix = os.path.join(codir, "git", "")
181
182 scmdata = ud.parm.get("scmdata", "")
183 if scmdata == "keep":
184 runfetchcmd("%s clone -n %s %s" % (ud.basecmd, ud.clonedir, coprefix), d)
185 os.chdir(coprefix)
186 runfetchcmd("%s checkout -q -f %s%s" % (ud.basecmd, ud.tag, readpathspec), d)
187 else:
188 bb.mkdirhier(codir)
189 os.chdir(ud.clonedir)
190 runfetchcmd("%s read-tree %s%s" % (ud.basecmd, ud.tag, readpathspec), d)
191 runfetchcmd("%s checkout-index -q -f --prefix=%s -a" % (ud.basecmd, coprefix), d)
192
193 os.chdir(codir)
194 logger.info("Creating tarball of git checkout")
195 runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d)
196
197 os.chdir(ud.clonedir)
198 bb.utils.prunedir(codir)
199
200 def supports_srcrev(self):
201 return True
202
203 def _contains_ref(self, tag, d):
204 basecmd = data.getVar("FETCHCMD_git", d, True) or "git"
205 output = runfetchcmd("%s log --pretty=oneline -n 1 %s -- 2> /dev/null | wc -l" % (basecmd, tag), d, quiet=True)
206 return output.split()[0] != "0"
207
208 def _revision_key(self, url, ud, d):
209 """
210 Return a unique key for the url
211 """
212 return "git:" + ud.host + ud.path.replace('/', '.') + ud.branch
213
214 def _latest_revision(self, url, ud, d):
215 """
216 Compute the HEAD revision for the url
217 """
218 if ud.user:
219 username = ud.user + '@'
220 else:
221 username = ""
222
223 basecmd = data.getVar("FETCHCMD_git", d, True) or "git"
224 cmd = "%s ls-remote %s://%s%s%s %s" % (basecmd, ud.proto, username, ud.host, ud.path, ud.branch)
225 output = runfetchcmd(cmd, d, True)
226 if not output:
227 raise bb.fetch2.FetchError("Fetch command %s gave empty output\n" % (cmd))
228 return output.split()[0]
229
230 def _build_revision(self, url, ud, d):
231 return ud.tag
232
233 def _sortable_buildindex_disabled(self, url, ud, d, rev):
234 """
235 Return a suitable buildindex for the revision specified. This is done by counting revisions
236 using "git rev-list" which may or may not work in different circumstances.
237 """
238
239 cwd = os.getcwd()
240
241 # Check if we have the rev already
242
243 if not os.path.exists(ud.clonedir):
244 print("no repo")
245 self.go(None, ud, d)
246 if not os.path.exists(ud.clonedir):
247 logger.error("GIT repository for %s doesn't exist in %s, cannot get sortable buildnumber, using old value", url, ud.clonedir)
248 return None
249
250
251 os.chdir(ud.clonedir)
252 if not self._contains_ref(rev, d):
253 self.go(None, ud, d)
254
255 output = runfetchcmd("%s rev-list %s -- 2> /dev/null | wc -l" % (ud.basecmd, rev), d, quiet=True)
256 os.chdir(cwd)
257
258 buildindex = "%s" % output.split()[0]
259 logger.debug(1, "GIT repository for %s in %s is returning %s revisions in rev-list before %s", url, ud.clonedir, buildindex, rev)
260 return buildindex
diff --git a/bitbake/lib/bb/fetch2/hg.py b/bitbake/lib/bb/fetch2/hg.py
new file mode 100644
index 0000000000..0ba84330a5
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/hg.py
@@ -0,0 +1,178 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementation for mercurial DRCS (hg).
5
6"""
7
8# Copyright (C) 2003, 2004 Chris Larson
9# Copyright (C) 2004 Marcin Juszkiewicz
10# Copyright (C) 2007 Robert Schuster
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License version 2 as
14# published by the Free Software Foundation.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License along
22# with this program; if not, write to the Free Software Foundation, Inc.,
23# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24#
25# Based on functions from the base bb module, Copyright 2003 Holger Schurig
26
27import os
28import sys
29import logging
30import bb
31from bb import data
32from bb.fetch2 import Fetch
33from bb.fetch2 import FetchError
34from bb.fetch2 import MissingParameterError
35from bb.fetch2 import runfetchcmd
36from bb.fetch2 import logger
37
38class Hg(Fetch):
39 """Class to fetch from mercurial repositories"""
40 def supports(self, url, ud, d):
41 """
42 Check to see if a given url can be fetched with mercurial.
43 """
44 return ud.type in ['hg']
45
46 def urldata_init(self, ud, d):
47 """
48 init hg specific variable within url data
49 """
50 if not "module" in ud.parm:
51 raise MissingParameterError("hg method needs a 'module' parameter")
52
53 ud.module = ud.parm["module"]
54
55 # Create paths to mercurial checkouts
56 relpath = self._strip_leading_slashes(ud.path)
57 ud.pkgdir = os.path.join(data.expand('${HGDIR}', d), ud.host, relpath)
58 ud.moddir = os.path.join(ud.pkgdir, ud.module)
59
60 def forcefetch(self, url, ud, d):
61 revTag = ud.parm.get('rev', 'tip')
62 return revTag == "tip"
63
64 def localpath(self, url, ud, d):
65 if 'rev' in ud.parm:
66 ud.revision = ud.parm['rev']
67 elif not ud.revision:
68 ud.revision = self.latest_revision(url, ud, d)
69
70 ud.localfile = data.expand('%s_%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision), d)
71
72 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
73
74 def _buildhgcommand(self, ud, d, command):
75 """
76 Build up an hg commandline based on ud
77 command is "fetch", "update", "info"
78 """
79
80 basecmd = data.expand('${FETCHCMD_hg}', d)
81
82 proto = ud.parm.get('proto', 'http')
83
84 host = ud.host
85 if proto == "file":
86 host = "/"
87 ud.host = "localhost"
88
89 if not ud.user:
90 hgroot = host + ud.path
91 else:
92 hgroot = ud.user + "@" + host + ud.path
93
94 if command is "info":
95 return "%s identify -i %s://%s/%s" % (basecmd, proto, hgroot, ud.module)
96
97 options = [];
98 if ud.revision:
99 options.append("-r %s" % ud.revision)
100
101 if command is "fetch":
102 cmd = "%s clone %s %s://%s/%s %s" % (basecmd, " ".join(options), proto, hgroot, ud.module, ud.module)
103 elif command is "pull":
104 # do not pass options list; limiting pull to rev causes the local
105 # repo not to contain it and immediately following "update" command
106 # will crash
107 cmd = "%s pull" % (basecmd)
108 elif command is "update":
109 cmd = "%s update -C %s" % (basecmd, " ".join(options))
110 else:
111 raise FetchError("Invalid hg command %s" % command)
112
113 return cmd
114
115 def go(self, loc, ud, d):
116 """Fetch url"""
117
118 logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
119
120 if os.access(os.path.join(ud.moddir, '.hg'), os.R_OK):
121 updatecmd = self._buildhgcommand(ud, d, "pull")
122 logger.info("Update " + loc)
123 # update sources there
124 os.chdir(ud.moddir)
125 logger.debug(1, "Running %s", updatecmd)
126 runfetchcmd(updatecmd, d)
127
128 else:
129 fetchcmd = self._buildhgcommand(ud, d, "fetch")
130 logger.info("Fetch " + loc)
131 # check out sources there
132 bb.mkdirhier(ud.pkgdir)
133 os.chdir(ud.pkgdir)
134 logger.debug(1, "Running %s", fetchcmd)
135 runfetchcmd(fetchcmd, d)
136
137 # Even when we clone (fetch), we still need to update as hg's clone
138 # won't checkout the specified revision if its on a branch
139 updatecmd = self._buildhgcommand(ud, d, "update")
140 os.chdir(ud.moddir)
141 logger.debug(1, "Running %s", updatecmd)
142 runfetchcmd(updatecmd, d)
143
144 scmdata = ud.parm.get("scmdata", "")
145 if scmdata == "keep":
146 tar_flags = ""
147 else:
148 tar_flags = "--exclude '.hg' --exclude '.hgrags'"
149
150 os.chdir(ud.pkgdir)
151 try:
152 runfetchcmd("tar %s -czf %s %s" % (tar_flags, ud.localpath, ud.module), d)
153 except:
154 t, v, tb = sys.exc_info()
155 try:
156 os.unlink(ud.localpath)
157 except OSError:
158 pass
159 raise t, v, tb
160
161 def supports_srcrev(self):
162 return True
163
164 def _latest_revision(self, url, ud, d):
165 """
166 Compute tip revision for the url
167 """
168 output = runfetchcmd(self._buildhgcommand(ud, d, "info"), d)
169 return output.strip()
170
171 def _build_revision(self, url, ud, d):
172 return ud.revision
173
174 def _revision_key(self, url, ud, d):
175 """
176 Return a unique key for the url
177 """
178 return "hg:" + ud.moddir
diff --git a/bitbake/lib/bb/fetch2/local.py b/bitbake/lib/bb/fetch2/local.py
new file mode 100644
index 0000000000..bcb30dfc95
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/local.py
@@ -0,0 +1,73 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementations
5
6Classes for obtaining upstream sources for the
7BitBake build tools.
8
9"""
10
11# Copyright (C) 2003, 2004 Chris Larson
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25#
26# Based on functions from the base bb module, Copyright 2003 Holger Schurig
27
28import os
29import bb
30import bb.utils
31from bb import data
32from bb.fetch2 import Fetch
33
34class Local(Fetch):
35 def supports(self, url, urldata, d):
36 """
37 Check to see if a given url represents a local fetch.
38 """
39 return urldata.type in ['file']
40
41 def localpath(self, url, urldata, d):
42 """
43 Return the local filename of a given url assuming a successful fetch.
44 """
45 path = url.split("://")[1]
46 path = path.split(";")[0]
47 newpath = path
48 if path[0] != "/":
49 filespath = data.getVar('FILESPATH', d, 1)
50 if filespath:
51 newpath = bb.utils.which(filespath, path)
52 if not newpath:
53 filesdir = data.getVar('FILESDIR', d, 1)
54 if filesdir:
55 newpath = os.path.join(filesdir, path)
56 # We don't set localfile as for this fetcher the file is already local!
57 return newpath
58
59 def go(self, url, urldata, d):
60 """Fetch urls (no-op for Local method)"""
61 # no need to fetch local files, we'll deal with them in place.
62 return 1
63
64 def checkstatus(self, url, urldata, d):
65 """
66 Check the status of the url
67 """
68 if urldata.localpath.find("*") != -1:
69 logger.info("URL %s looks like a glob and was therefore not checked.", url)
70 return True
71 if os.path.exists(urldata.localpath):
72 return True
73 return False
diff --git a/bitbake/lib/bb/fetch2/osc.py b/bitbake/lib/bb/fetch2/osc.py
new file mode 100644
index 0000000000..06ac5a9ce3
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/osc.py
@@ -0,0 +1,143 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4Bitbake "Fetch" implementation for osc (Opensuse build service client).
5Based on the svn "Fetch" implementation.
6
7"""
8
9import os
10import sys
11import logging
12import bb
13from bb import data
14from bb.fetch2 import Fetch
15from bb.fetch2 import FetchError
16from bb.fetch2 import MissingParameterError
17from bb.fetch2 import runfetchcmd
18
19class Osc(Fetch):
20 """Class to fetch a module or modules from Opensuse build server
21 repositories."""
22
23 def supports(self, url, ud, d):
24 """
25 Check to see if a given url can be fetched with osc.
26 """
27 return ud.type in ['osc']
28
29 def localpath(self, url, ud, d):
30 if not "module" in ud.parm:
31 raise MissingParameterError("osc method needs a 'module' parameter.")
32
33 ud.module = ud.parm["module"]
34
35 # Create paths to osc checkouts
36 relpath = self._strip_leading_slashes(ud.path)
37 ud.pkgdir = os.path.join(data.expand('${OSCDIR}', d), ud.host)
38 ud.moddir = os.path.join(ud.pkgdir, relpath, ud.module)
39
40 if 'rev' in ud.parm:
41 ud.revision = ud.parm['rev']
42 else:
43 pv = data.getVar("PV", d, 0)
44 rev = Fetch.srcrev_internal_helper(ud, d)
45 if rev and rev != True:
46 ud.revision = rev
47 else:
48 ud.revision = ""
49
50 ud.localfile = data.expand('%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.path.replace('/', '.'), ud.revision), d)
51
52 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
53
54 def _buildosccommand(self, ud, d, command):
55 """
56 Build up an ocs commandline based on ud
57 command is "fetch", "update", "info"
58 """
59
60 basecmd = data.expand('${FETCHCMD_osc}', d)
61
62 proto = ud.parm.get('proto', 'ocs')
63
64 options = []
65
66 config = "-c %s" % self.generate_config(ud, d)
67
68 if ud.revision:
69 options.append("-r %s" % ud.revision)
70
71 coroot = self._strip_leading_slashes(ud.path)
72
73 if command is "fetch":
74 osccmd = "%s %s co %s/%s %s" % (basecmd, config, coroot, ud.module, " ".join(options))
75 elif command is "update":
76 osccmd = "%s %s up %s" % (basecmd, config, " ".join(options))
77 else:
78 raise FetchError("Invalid osc command %s" % command)
79
80 return osccmd
81
82 def go(self, loc, ud, d):
83 """
84 Fetch url
85 """
86
87 logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
88
89 if os.access(os.path.join(data.expand('${OSCDIR}', d), ud.path, ud.module), os.R_OK):
90 oscupdatecmd = self._buildosccommand(ud, d, "update")
91 logger.info("Update "+ loc)
92 # update sources there
93 os.chdir(ud.moddir)
94 logger.debug(1, "Running %s", oscupdatecmd)
95 runfetchcmd(oscupdatecmd, d)
96 else:
97 oscfetchcmd = self._buildosccommand(ud, d, "fetch")
98 logger.info("Fetch " + loc)
99 # check out sources there
100 bb.mkdirhier(ud.pkgdir)
101 os.chdir(ud.pkgdir)
102 logger.debug(1, "Running %s", oscfetchcmd)
103 runfetchcmd(oscfetchcmd, d)
104
105 os.chdir(os.path.join(ud.pkgdir + ud.path))
106 # tar them up to a defined filename
107 try:
108 runfetchcmd("tar -czf %s %s" % (ud.localpath, ud.module), d)
109 except:
110 t, v, tb = sys.exc_info()
111 try:
112 os.unlink(ud.localpath)
113 except OSError:
114 pass
115 raise t, v, tb
116
117 def supports_srcrev(self):
118 return False
119
120 def generate_config(self, ud, d):
121 """
122 Generate a .oscrc to be used for this run.
123 """
124
125 config_path = os.path.join(data.expand('${OSCDIR}', d), "oscrc")
126 if (os.path.exists(config_path)):
127 os.remove(config_path)
128
129 f = open(config_path, 'w')
130 f.write("[general]\n")
131 f.write("apisrv = %s\n" % ud.host)
132 f.write("scheme = http\n")
133 f.write("su-wrapper = su -c\n")
134 f.write("build-root = %s\n" % data.expand('${WORKDIR}', d))
135 f.write("urllist = http://moblin-obs.jf.intel.com:8888/build/%(project)s/%(repository)s/%(buildarch)s/:full/%(name)s.rpm\n")
136 f.write("extra-pkgs = gzip\n")
137 f.write("\n")
138 f.write("[%s]\n" % ud.host)
139 f.write("user = %s\n" % ud.parm["user"])
140 f.write("pass = %s\n" % ud.parm["pswd"])
141 f.close()
142
143 return config_path
diff --git a/bitbake/lib/bb/fetch2/perforce.py b/bitbake/lib/bb/fetch2/perforce.py
new file mode 100644
index 0000000000..18b27812e0
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/perforce.py
@@ -0,0 +1,206 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementations
5
6Classes for obtaining upstream sources for the
7BitBake build tools.
8
9"""
10
11# Copyright (C) 2003, 2004 Chris Larson
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25#
26# Based on functions from the base bb module, Copyright 2003 Holger Schurig
27
28from future_builtins import zip
29import os
30import logging
31import bb
32from bb import data
33from bb.fetch2 import Fetch
34from bb.fetch2 import FetchError
35from bb.fetch2 import logger
36
37class Perforce(Fetch):
38 def supports(self, url, ud, d):
39 return ud.type in ['p4']
40
41 def doparse(url, d):
42 parm = {}
43 path = url.split("://")[1]
44 delim = path.find("@");
45 if delim != -1:
46 (user, pswd, host, port) = path.split('@')[0].split(":")
47 path = path.split('@')[1]
48 else:
49 (host, port) = data.getVar('P4PORT', d).split(':')
50 user = ""
51 pswd = ""
52
53 if path.find(";") != -1:
54 keys=[]
55 values=[]
56 plist = path.split(';')
57 for item in plist:
58 if item.count('='):
59 (key, value) = item.split('=')
60 keys.append(key)
61 values.append(value)
62
63 parm = dict(zip(keys, values))
64 path = "//" + path.split(';')[0]
65 host += ":%s" % (port)
66 parm["cset"] = Perforce.getcset(d, path, host, user, pswd, parm)
67
68 return host, path, user, pswd, parm
69 doparse = staticmethod(doparse)
70
71 def getcset(d, depot, host, user, pswd, parm):
72 p4opt = ""
73 if "cset" in parm:
74 return parm["cset"];
75 if user:
76 p4opt += " -u %s" % (user)
77 if pswd:
78 p4opt += " -P %s" % (pswd)
79 if host:
80 p4opt += " -p %s" % (host)
81
82 p4date = data.getVar("P4DATE", d, 1)
83 if "revision" in parm:
84 depot += "#%s" % (parm["revision"])
85 elif "label" in parm:
86 depot += "@%s" % (parm["label"])
87 elif p4date:
88 depot += "@%s" % (p4date)
89
90 p4cmd = data.getVar('FETCHCOMMAND_p4', d, 1)
91 logger.debug(1, "Running %s%s changes -m 1 %s", p4cmd, p4opt, depot)
92 p4file = os.popen("%s%s changes -m 1 %s" % (p4cmd, p4opt, depot))
93 cset = p4file.readline().strip()
94 logger.debug(1, "READ %s", cset)
95 if not cset:
96 return -1
97
98 return cset.split(' ')[1]
99 getcset = staticmethod(getcset)
100
101 def localpath(self, url, ud, d):
102
103 (host, path, user, pswd, parm) = Perforce.doparse(url, d)
104
105 # If a label is specified, we use that as our filename
106
107 if "label" in parm:
108 ud.localfile = "%s.tar.gz" % (parm["label"])
109 return os.path.join(data.getVar("DL_DIR", d, 1), ud.localfile)
110
111 base = path
112 which = path.find('/...')
113 if which != -1:
114 base = path[:which]
115
116 base = self._strip_leading_slashes(base)
117
118 cset = Perforce.getcset(d, path, host, user, pswd, parm)
119
120 ud.localfile = data.expand('%s+%s+%s.tar.gz' % (host, base.replace('/', '.'), cset), d)
121
122 return os.path.join(data.getVar("DL_DIR", d, 1), ud.localfile)
123
124 def go(self, loc, ud, d):
125 """
126 Fetch urls
127 """
128
129 (host, depot, user, pswd, parm) = Perforce.doparse(loc, d)
130
131 if depot.find('/...') != -1:
132 path = depot[:depot.find('/...')]
133 else:
134 path = depot
135
136 module = parm.get('module', os.path.basename(path))
137
138 localdata = data.createCopy(d)
139 data.setVar('OVERRIDES', "p4:%s" % data.getVar('OVERRIDES', localdata), localdata)
140 data.update_data(localdata)
141
142 # Get the p4 command
143 p4opt = ""
144 if user:
145 p4opt += " -u %s" % (user)
146
147 if pswd:
148 p4opt += " -P %s" % (pswd)
149
150 if host:
151 p4opt += " -p %s" % (host)
152
153 p4cmd = data.getVar('FETCHCOMMAND', localdata, 1)
154
155 # create temp directory
156 logger.debug(2, "Fetch: creating temporary directory")
157 bb.mkdirhier(data.expand('${WORKDIR}', localdata))
158 data.setVar('TMPBASE', data.expand('${WORKDIR}/oep4.XXXXXX', localdata), localdata)
159 tmppipe = os.popen(data.getVar('MKTEMPDIRCMD', localdata, 1) or "false")
160 tmpfile = tmppipe.readline().strip()
161 if not tmpfile:
162 logger.error("Fetch: unable to create temporary directory.. make sure 'mktemp' is in the PATH.")
163 raise FetchError(module)
164
165 if "label" in parm:
166 depot = "%s@%s" % (depot, parm["label"])
167 else:
168 cset = Perforce.getcset(d, depot, host, user, pswd, parm)
169 depot = "%s@%s" % (depot, cset)
170
171 os.chdir(tmpfile)
172 logger.info("Fetch " + loc)
173 logger.info("%s%s files %s", p4cmd, p4opt, depot)
174 p4file = os.popen("%s%s files %s" % (p4cmd, p4opt, depot))
175
176 if not p4file:
177 logger.error("Fetch: unable to get the P4 files from %s", depot)
178 raise FetchError(module)
179
180 count = 0
181
182 for file in p4file:
183 list = file.split()
184
185 if list[2] == "delete":
186 continue
187
188 dest = list[0][len(path)+1:]
189 where = dest.find("#")
190
191 os.system("%s%s print -o %s/%s %s" % (p4cmd, p4opt, module, dest[:where], list[0]))
192 count = count + 1
193
194 if count == 0:
195 logger.error("Fetch: No files gathered from the P4 fetch")
196 raise FetchError(module)
197
198 myret = os.system("tar -czf %s %s" % (ud.localpath, module))
199 if myret != 0:
200 try:
201 os.unlink(ud.localpath)
202 except OSError:
203 pass
204 raise FetchError(module)
205 # cleanup
206 bb.utils.prunedir(tmpfile)
diff --git a/bitbake/lib/bb/fetch2/repo.py b/bitbake/lib/bb/fetch2/repo.py
new file mode 100644
index 0000000000..3330957ce3
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/repo.py
@@ -0,0 +1,98 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake "Fetch" repo (git) implementation
5
6"""
7
8# Copyright (C) 2009 Tom Rini <trini@embeddedalley.com>
9#
10# Based on git.py which is:
11#Copyright (C) 2005 Richard Purdie
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
26import os
27import bb
28from bb import data
29from bb.fetch2 import Fetch
30from bb.fetch2 import runfetchcmd
31
32class Repo(Fetch):
33 """Class to fetch a module or modules from repo (git) repositories"""
34 def supports(self, url, ud, d):
35 """
36 Check to see if a given url can be fetched with repo.
37 """
38 return ud.type in ["repo"]
39
40 def localpath(self, url, ud, d):
41 """
42 We don"t care about the git rev of the manifests repository, but
43 we do care about the manifest to use. The default is "default".
44 We also care about the branch or tag to be used. The default is
45 "master".
46 """
47
48 ud.proto = ud.parm.get('protocol', 'git')
49 ud.branch = ud.parm.get('branch', 'master')
50 ud.manifest = ud.parm.get('manifest', 'default.xml')
51 if not ud.manifest.endswith('.xml'):
52 ud.manifest += '.xml'
53
54 ud.localfile = data.expand("repo_%s%s_%s_%s.tar.gz" % (ud.host, ud.path.replace("/", "."), ud.manifest, ud.branch), d)
55
56 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
57
58 def go(self, loc, ud, d):
59 """Fetch url"""
60
61 if os.access(os.path.join(data.getVar("DL_DIR", d, True), ud.localfile), os.R_OK):
62 logger.debug(1, "%s already exists (or was stashed). Skipping repo init / sync.", ud.localpath)
63 return
64
65 gitsrcname = "%s%s" % (ud.host, ud.path.replace("/", "."))
66 repodir = data.getVar("REPODIR", d, True) or os.path.join(data.getVar("DL_DIR", d, True), "repo")
67 codir = os.path.join(repodir, gitsrcname, ud.manifest)
68
69 if ud.user:
70 username = ud.user + "@"
71 else:
72 username = ""
73
74 bb.mkdirhier(os.path.join(codir, "repo"))
75 os.chdir(os.path.join(codir, "repo"))
76 if not os.path.exists(os.path.join(codir, "repo", ".repo")):
77 runfetchcmd("repo init -m %s -b %s -u %s://%s%s%s" % (ud.manifest, ud.branch, ud.proto, username, ud.host, ud.path), d)
78
79 runfetchcmd("repo sync", d)
80 os.chdir(codir)
81
82 scmdata = ud.parm.get("scmdata", "")
83 if scmdata == "keep":
84 tar_flags = ""
85 else:
86 tar_flags = "--exclude '.repo' --exclude '.git'"
87
88 # Create a cache
89 runfetchcmd("tar %s -czf %s %s" % (tar_flags, ud.localpath, os.path.join(".", "*") ), d)
90
91 def supports_srcrev(self):
92 return False
93
94 def _build_revision(self, url, ud, d):
95 return ud.manifest
96
97 def _want_sortable_revision(self, url, ud, d):
98 return False
diff --git a/bitbake/lib/bb/fetch2/ssh.py b/bitbake/lib/bb/fetch2/ssh.py
new file mode 100644
index 0000000000..8b283222bf
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/ssh.py
@@ -0,0 +1,118 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3'''
4BitBake 'Fetch' implementations
5
6This implementation is for Secure Shell (SSH), and attempts to comply with the
7IETF secsh internet draft:
8 http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/
9
10 Currently does not support the sftp parameters, as this uses scp
11 Also does not support the 'fingerprint' connection parameter.
12
13'''
14
15# Copyright (C) 2006 OpenedHand Ltd.
16#
17#
18# Based in part on svk.py:
19# Copyright (C) 2006 Holger Hans Peter Freyther
20# Based on svn.py:
21# Copyright (C) 2003, 2004 Chris Larson
22# Based on functions from the base bb module:
23# Copyright 2003 Holger Schurig
24#
25#
26# This program is free software; you can redistribute it and/or modify
27# it under the terms of the GNU General Public License version 2 as
28# published by the Free Software Foundation.
29#
30# This program is distributed in the hope that it will be useful,
31# but WITHOUT ANY WARRANTY; without even the implied warranty of
32# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33# GNU General Public License for more details.
34#
35# You should have received a copy of the GNU General Public License along
36# with this program; if not, write to the Free Software Foundation, Inc.,
37# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38
39import re, os
40from bb import data
41from bb.fetch2 import Fetch
42from bb.fetch2 import FetchError
43
44
45__pattern__ = re.compile(r'''
46 \s* # Skip leading whitespace
47 ssh:// # scheme
48 ( # Optional username/password block
49 (?P<user>\S+) # username
50 (:(?P<pass>\S+))? # colon followed by the password (optional)
51 )?
52 (?P<cparam>(;[^;]+)*)? # connection parameters block (optional)
53 @
54 (?P<host>\S+?) # non-greedy match of the host
55 (:(?P<port>[0-9]+))? # colon followed by the port (optional)
56 /
57 (?P<path>[^;]+) # path on the remote system, may be absolute or relative,
58 # and may include the use of '~' to reference the remote home
59 # directory
60 (?P<sparam>(;[^;]+)*)? # parameters block (optional)
61 $
62''', re.VERBOSE)
63
64class SSH(Fetch):
65 '''Class to fetch a module or modules via Secure Shell'''
66
67 def supports(self, url, urldata, d):
68 return __pattern__.match(url) != None
69
70 def localpath(self, url, urldata, d):
71 m = __pattern__.match(url)
72 path = m.group('path')
73 host = m.group('host')
74 lpath = os.path.join(data.getVar('DL_DIR', d, True), host, os.path.basename(path))
75 return lpath
76
77 def go(self, url, urldata, d):
78 dldir = data.getVar('DL_DIR', d, 1)
79
80 m = __pattern__.match(url)
81 path = m.group('path')
82 host = m.group('host')
83 port = m.group('port')
84 user = m.group('user')
85 password = m.group('pass')
86
87 ldir = os.path.join(dldir, host)
88 lpath = os.path.join(ldir, os.path.basename(path))
89
90 if not os.path.exists(ldir):
91 os.makedirs(ldir)
92
93 if port:
94 port = '-P %s' % port
95 else:
96 port = ''
97
98 if user:
99 fr = user
100 if password:
101 fr += ':%s' % password
102 fr += '@%s' % host
103 else:
104 fr = host
105 fr += ':%s' % path
106
107
108 import commands
109 cmd = 'scp -B -r %s %s %s/' % (
110 port,
111 commands.mkarg(fr),
112 commands.mkarg(ldir)
113 )
114
115 (exitstatus, output) = commands.getstatusoutput(cmd)
116 if exitstatus != 0:
117 print(output)
118 raise FetchError('Unable to fetch %s' % url)
diff --git a/bitbake/lib/bb/fetch2/svk.py b/bitbake/lib/bb/fetch2/svk.py
new file mode 100644
index 0000000000..7990ff21fa
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/svk.py
@@ -0,0 +1,104 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementations
5
6This implementation is for svk. It is based on the svn implementation
7
8"""
9
10# Copyright (C) 2006 Holger Hans Peter Freyther
11# Copyright (C) 2003, 2004 Chris Larson
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25#
26# Based on functions from the base bb module, Copyright 2003 Holger Schurig
27
28import os
29import logging
30import bb
31from bb import data
32from bb.fetch2 import Fetch
33from bb.fetch2 import FetchError
34from bb.fetch2 import MissingParameterError
35from bb.fetch2 import logger
36
37class Svk(Fetch):
38 """Class to fetch a module or modules from svk repositories"""
39 def supports(self, url, ud, d):
40 """
41 Check to see if a given url can be fetched with svk.
42 """
43 return ud.type in ['svk']
44
45 def localpath(self, url, ud, d):
46 if not "module" in ud.parm:
47 raise MissingParameterError("svk method needs a 'module' parameter")
48 else:
49 ud.module = ud.parm["module"]
50
51 ud.revision = ud.parm.get('rev', "")
52
53 ud.localfile = data.expand('%s_%s_%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision, ud.date), d)
54
55 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
56
57 def forcefetch(self, url, ud, d):
58 return ud.date == "now"
59
60 def go(self, loc, ud, d):
61 """Fetch urls"""
62
63 svkroot = ud.host + ud.path
64
65 svkcmd = "svk co -r {%s} %s/%s" % (ud.date, svkroot, ud.module)
66
67 if ud.revision:
68 svkcmd = "svk co -r %s %s/%s" % (ud.revision, svkroot, ud.module)
69
70 # create temp directory
71 localdata = data.createCopy(d)
72 data.update_data(localdata)
73 logger.debug(2, "Fetch: creating temporary directory")
74 bb.mkdirhier(data.expand('${WORKDIR}', localdata))
75 data.setVar('TMPBASE', data.expand('${WORKDIR}/oesvk.XXXXXX', localdata), localdata)
76 tmppipe = os.popen(data.getVar('MKTEMPDIRCMD', localdata, 1) or "false")
77 tmpfile = tmppipe.readline().strip()
78 if not tmpfile:
79 logger.error("Fetch: unable to create temporary directory.. make sure 'mktemp' is in the PATH.")
80 raise FetchError(ud.module)
81
82 # check out sources there
83 os.chdir(tmpfile)
84 logger.info("Fetch " + loc)
85 logger.debug(1, "Running %s", svkcmd)
86 myret = os.system(svkcmd)
87 if myret != 0:
88 try:
89 os.rmdir(tmpfile)
90 except OSError:
91 pass
92 raise FetchError(ud.module)
93
94 os.chdir(os.path.join(tmpfile, os.path.dirname(ud.module)))
95 # tar them up to a defined filename
96 myret = os.system("tar -czf %s %s" % (ud.localpath, os.path.basename(ud.module)))
97 if myret != 0:
98 try:
99 os.unlink(ud.localpath)
100 except OSError:
101 pass
102 raise FetchError(ud.module)
103 # cleanup
104 bb.utils.prunedir(tmpfile)
diff --git a/bitbake/lib/bb/fetch2/svn.py b/bitbake/lib/bb/fetch2/svn.py
new file mode 100644
index 0000000000..1116795e87
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/svn.py
@@ -0,0 +1,202 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementation for svn.
5
6"""
7
8# Copyright (C) 2003, 2004 Chris Larson
9# Copyright (C) 2004 Marcin Juszkiewicz
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License version 2 as
13# published by the Free Software Foundation.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License along
21# with this program; if not, write to the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23#
24# Based on functions from the base bb module, Copyright 2003 Holger Schurig
25
26import os
27import sys
28import logging
29import bb
30from bb import data
31from bb.fetch2 import Fetch
32from bb.fetch2 import FetchError
33from bb.fetch2 import MissingParameterError
34from bb.fetch2 import runfetchcmd
35from bb.fetch2 import logger
36
37class Svn(Fetch):
38 """Class to fetch a module or modules from svn repositories"""
39 def supports(self, url, ud, d):
40 """
41 Check to see if a given url can be fetched with svn.
42 """
43 return ud.type in ['svn']
44
45 def urldata_init(self, ud, d):
46 """
47 init svn specific variable within url data
48 """
49 if not "module" in ud.parm:
50 raise MissingParameterError("svn method needs a 'module' parameter")
51
52 ud.module = ud.parm["module"]
53
54 # Create paths to svn checkouts
55 relpath = self._strip_leading_slashes(ud.path)
56 ud.pkgdir = os.path.join(data.expand('${SVNDIR}', d), ud.host, relpath)
57 ud.moddir = os.path.join(ud.pkgdir, ud.module)
58
59 def localpath(self, url, ud, d):
60 if 'rev' in ud.parm:
61 ud.date = ""
62 ud.revision = ud.parm['rev']
63 elif 'date' in ud.date:
64 ud.date = ud.parm['date']
65 ud.revision = ""
66 else:
67 #
68 # ***Nasty hack***
69 # If DATE in unexpanded PV, use ud.date (which is set from SRCDATE)
70 # Should warn people to switch to SRCREV here
71 #
72 pv = data.getVar("PV", d, 0)
73 if "DATE" in pv:
74 ud.revision = ""
75 else:
76 # use the initizlied revision
77 if ud.revision:
78 ud.date = ""
79
80 ud.localfile = data.expand('%s_%s_%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision, ud.date), d)
81
82 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
83
84 def _buildsvncommand(self, ud, d, command):
85 """
86 Build up an svn commandline based on ud
87 command is "fetch", "update", "info"
88 """
89
90 basecmd = data.expand('${FETCHCMD_svn}', d)
91
92 proto = ud.parm.get('proto', 'svn')
93
94 svn_rsh = None
95 if proto == "svn+ssh" and "rsh" in ud.parm:
96 svn_rsh = ud.parm["rsh"]
97
98 svnroot = ud.host + ud.path
99
100 # either use the revision, or SRCDATE in braces,
101 options = []
102
103 if ud.user:
104 options.append("--username %s" % ud.user)
105
106 if ud.pswd:
107 options.append("--password %s" % ud.pswd)
108
109 if command is "info":
110 svncmd = "%s info %s %s://%s/%s/" % (basecmd, " ".join(options), proto, svnroot, ud.module)
111 else:
112 suffix = ""
113 if ud.revision:
114 options.append("-r %s" % ud.revision)
115 suffix = "@%s" % (ud.revision)
116 elif ud.date:
117 options.append("-r {%s}" % ud.date)
118
119 if command is "fetch":
120 svncmd = "%s co %s %s://%s/%s%s %s" % (basecmd, " ".join(options), proto, svnroot, ud.module, suffix, ud.module)
121 elif command is "update":
122 svncmd = "%s update %s" % (basecmd, " ".join(options))
123 else:
124 raise FetchError("Invalid svn command %s" % command)
125
126 if svn_rsh:
127 svncmd = "svn_RSH=\"%s\" %s" % (svn_rsh, svncmd)
128
129 return svncmd
130
131 def go(self, loc, ud, d):
132 """Fetch url"""
133
134 logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
135
136 if os.access(os.path.join(ud.moddir, '.svn'), os.R_OK):
137 svnupdatecmd = self._buildsvncommand(ud, d, "update")
138 logger.info("Update " + loc)
139 # update sources there
140 os.chdir(ud.moddir)
141 logger.debug(1, "Running %s", svnupdatecmd)
142 runfetchcmd(svnupdatecmd, d)
143 else:
144 svnfetchcmd = self._buildsvncommand(ud, d, "fetch")
145 logger.info("Fetch " + loc)
146 # check out sources there
147 bb.mkdirhier(ud.pkgdir)
148 os.chdir(ud.pkgdir)
149 logger.debug(1, "Running %s", svnfetchcmd)
150 runfetchcmd(svnfetchcmd, d)
151
152 scmdata = ud.parm.get("scmdata", "")
153 if scmdata == "keep":
154 tar_flags = ""
155 else:
156 tar_flags = "--exclude '.svn'"
157
158 os.chdir(ud.pkgdir)
159 # tar them up to a defined filename
160 try:
161 runfetchcmd("tar %s -czf %s %s" % (tar_flags, ud.localpath, ud.module), d)
162 except:
163 t, v, tb = sys.exc_info()
164 try:
165 os.unlink(ud.localpath)
166 except OSError:
167 pass
168 raise t, v, tb
169
170 def supports_srcrev(self):
171 return True
172
173 def _revision_key(self, url, ud, d):
174 """
175 Return a unique key for the url
176 """
177 return "svn:" + ud.moddir
178
179 def _latest_revision(self, url, ud, d):
180 """
181 Return the latest upstream revision number
182 """
183 logger.debug(2, "SVN fetcher hitting network for %s", url)
184
185 output = runfetchcmd("LANG=C LC_ALL=C " + self._buildsvncommand(ud, d, "info"), d, True)
186
187 revision = None
188 for line in output.splitlines():
189 if "Last Changed Rev" in line:
190 revision = line.split(":")[1].strip()
191
192 return revision
193
194 def _sortable_revision(self, url, ud, d):
195 """
196 Return a sortable revision number which in our case is the revision number
197 """
198
199 return self._build_revision(url, ud, d)
200
201 def _build_revision(self, url, ud, d):
202 return ud.revision
diff --git a/bitbake/lib/bb/fetch2/wget.py b/bitbake/lib/bb/fetch2/wget.py
new file mode 100644
index 0000000000..cf36ccad0a
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/wget.py
@@ -0,0 +1,93 @@
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementations
5
6Classes for obtaining upstream sources for the
7BitBake build tools.
8
9"""
10
11# Copyright (C) 2003, 2004 Chris Larson
12#
13# This program is free software; you can redistribute it and/or modify
14# it under the terms of the GNU General Public License version 2 as
15# published by the Free Software Foundation.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License along
23# with this program; if not, write to the Free Software Foundation, Inc.,
24# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25#
26# Based on functions from the base bb module, Copyright 2003 Holger Schurig
27
28import os
29import logging
30import bb
31import urllib
32from bb import data
33from bb.fetch2 import Fetch, FetchError, encodeurl, decodeurl, logger, runfetchcmd
34
35class Wget(Fetch):
36 """Class to fetch urls via 'wget'"""
37 def supports(self, url, ud, d):
38 """
39 Check to see if a given url can be fetched with wget.
40 """
41 return ud.type in ['http', 'https', 'ftp']
42
43 def localpath(self, url, ud, d):
44
45 url = encodeurl([ud.type, ud.host, ud.path, ud.user, ud.pswd, {}])
46 ud.basename = os.path.basename(ud.path)
47 ud.localfile = data.expand(urllib.unquote(ud.basename), d)
48
49 return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
50
51 def go(self, uri, ud, d, checkonly = False):
52 """Fetch urls"""
53
54 def fetch_uri(uri, ud, d):
55 if checkonly:
56 fetchcmd = data.getVar("CHECKCOMMAND", d, 1)
57 elif os.path.exists(ud.localpath):
58 # file exists, but we didnt complete it.. trying again..
59 fetchcmd = data.getVar("RESUMECOMMAND", d, 1)
60 else:
61 fetchcmd = data.getVar("FETCHCOMMAND", d, 1)
62
63 uri = uri.split(";")[0]
64 uri_decoded = list(decodeurl(uri))
65 uri_type = uri_decoded[0]
66 uri_host = uri_decoded[1]
67
68 fetchcmd = fetchcmd.replace("${URI}", uri.split(";")[0])
69 fetchcmd = fetchcmd.replace("${FILE}", ud.basename)
70 logger.info("fetch " + uri)
71 logger.debug(2, "executing " + fetchcmd)
72 runfetchcmd(fetchcmd, d)
73
74 # Sanity check since wget can pretend it succeed when it didn't
75 # Also, this used to happen if sourceforge sent us to the mirror page
76 if not os.path.exists(ud.localpath) and not checkonly:
77 logger.debug(2, "The fetch command for %s returned success but %s doesn't exist?...", uri, ud.localpath)
78 return False
79
80 return True
81
82 localdata = data.createCopy(d)
83 data.setVar('OVERRIDES', "wget:" + data.getVar('OVERRIDES', localdata), localdata)
84 data.update_data(localdata)
85
86 if fetch_uri(uri, ud, localdata):
87 return True
88
89 raise FetchError(uri)
90
91
92 def checkstatus(self, uri, ud, d):
93 return self.go(uri, ud, d, True)