bitbake/lib/bb/fetch/:
[bitbake.git] / lib / bb / fetch / __init__.py
1 #!/usr/bin/env python
2 # ex:ts=4:sw=4:sts=4:et
3 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4 """
5 BitBake 'Fetch' implementations
6
7 Classes for obtaining upstream sources for the
8 BitBake build tools.
9
10 Copyright (C) 2003, 2004  Chris Larson
11
12 This program is free software; you can redistribute it and/or modify it under
13 the terms of the GNU General Public License as published by the Free Software
14 Foundation; either version 2 of the License, or (at your option) any later
15 version.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23 Place, Suite 330, Boston, MA 02111-1307 USA. 
24
25 Based on functions from the base bb module, Copyright 2003 Holger Schurig
26 """
27
28 import os, re
29 import bb
30 from   bb import data
31
32 class FetchError(Exception):
33     """Exception raised when a download fails"""
34
35 class NoMethodError(Exception):
36     """Exception raised when there is no method to obtain a supplied url or set of urls"""
37
38 class MissingParameterError(Exception):
39     """Exception raised when a fetch method is missing a critical parameter in the url"""
40
41 class MD5SumError(Exception):
42     """Exception raised when a MD5SUM of a file does not match the expected one"""
43
44 def uri_replace(uri, uri_find, uri_replace, d):
45 #   bb.note("uri_replace: operating on %s" % uri)
46     if not uri or not uri_find or not uri_replace:
47         bb.debug(1, "uri_replace: passed an undefined value, not replacing")
48     uri_decoded = list(bb.decodeurl(uri))
49     uri_find_decoded = list(bb.decodeurl(uri_find))
50     uri_replace_decoded = list(bb.decodeurl(uri_replace))
51     result_decoded = ['','','','','',{}]
52     for i in uri_find_decoded:
53         loc = uri_find_decoded.index(i)
54         result_decoded[loc] = uri_decoded[loc]
55         import types
56         if type(i) == types.StringType:
57             import re
58             if (re.match(i, uri_decoded[loc])):
59                 result_decoded[loc] = re.sub(i, uri_replace_decoded[loc], uri_decoded[loc])
60                 if uri_find_decoded.index(i) == 2:
61                     if d:
62                         localfn = bb.fetch.localpath(uri, d)
63                         if localfn:
64                             result_decoded[loc] = os.path.dirname(result_decoded[loc]) + "/" + os.path.basename(bb.fetch.localpath(uri, d))
65 #                       bb.note("uri_replace: matching %s against %s and replacing with %s" % (i, uri_decoded[loc], uri_replace_decoded[loc]))
66             else:
67 #               bb.note("uri_replace: no match")
68                 return uri
69 #           else:
70 #               for j in i.keys():
71 #                   FIXME: apply replacements against options
72     return bb.encodeurl(result_decoded)
73
74 methods = []
75
76 def init(urls = [], d = None):
77     if d == None:
78         bb.debug(2,"BUG init called with None as data object!!!")
79         return
80
81     for m in methods:
82         m.urls = []
83
84     for u in urls:
85         for m in methods:
86             m.data = d
87             if m.supports(u, d):
88                 m.urls.append(u)
89
90 def go(d):
91     """Fetch all urls"""
92     for m in methods:
93         if m.urls:
94             m.go(d)
95
96 def localpaths(d):
97     """Return a list of the local filenames, assuming successful fetch"""
98     local = []
99     for m in methods:
100         for u in m.urls:
101             local.append(m.localpath(u, d))
102     return local
103
104 def localpath(url, d):
105     for m in methods:
106         if m.supports(url, d):
107             return m.localpath(url, d)
108     return url
109
110 class Fetch(object):
111     """Base class for 'fetch'ing data"""
112
113     def __init__(self, urls = []):
114         self.urls = []
115         for url in urls:
116             if self.supports(bb.decodeurl(url), d) is 1:
117                 self.urls.append(url)
118
119     def supports(url, d):
120         """Check to see if this fetch class supports a given url.
121            Expects supplied url in list form, as outputted by bb.decodeurl().
122         """
123         return 0
124     supports = staticmethod(supports)
125
126     def localpath(url, d):
127         """Return the local filename of a given url assuming a successful fetch.
128         """
129         return url
130     localpath = staticmethod(localpath)
131
132     def setUrls(self, urls):
133         self.__urls = urls
134
135     def getUrls(self):
136         return self.__urls
137
138     urls = property(getUrls, setUrls, None, "Urls property")
139
140     def setData(self, data):
141         self.__data = data
142
143     def getData(self):
144         return self.__data
145
146     data = property(getData, setData, None, "Data property")
147
148     def go(self, urls = []):
149         """Fetch urls"""
150         raise NoMethodError("Missing implementation for url")
151
152     def getSRCDate(d):
153         """
154         Return the SRC Date for the component
155
156         d the bb.data module
157         """
158         return data.getVar("SRCDATE", d, 1) or data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1 )
159     getSRCDate = staticmethod(getSRCDate)
160
161     def try_mirror(d, tarfn):
162         """
163         Try to use a mirrored version of the sources. We do this
164         to avoid massive loads on foreign cvs and svn servers.
165         This method will be used by the different fetcher
166         implementations.
167
168         d Is a bb.data instance
169         tarfn is the name of the tarball
170         """
171         pn = data.getVar('PN', d, True)
172         src_tarball_stash = None
173         if pn:
174             src_tarball_stash = data.getVar('SRC_TARBALL_STASH_%s' % pn, d, True) or data.getVar('CVS_TARBALL_STASH_%s' % pn, d, True) or data.getVar('SRC_TARBALL_STASH', d, True) or data.getVar('CVS_TARBALL_STASH', d, True)
175
176         if src_tarball_stash:
177             fetchcmd = data.getVar("FETCHCOMMAND_mirror", d, True) or data.getVar("FETCHCOMMAND_wget", d, True)
178             uri = src_tarball_stash + tarfn
179             bb.note("fetch " + uri)
180             fetchcmd = fetchcmd.replace("${URI}", uri)
181             ret = os.system(fetchcmd)
182             if ret == 0:
183                 bb.note("Fetched %s from tarball stash, skipping checkout" % tarfn)
184                 return True
185         return False
186     try_mirror = staticmethod(try_mirror)
187
188 import cvs
189 import git
190 import local
191 import svn
192 import wget
193 import svk
194
195 methods.append(cvs.Cvs())
196 methods.append(git.Git())
197 methods.append(local.Local())
198 methods.append(svn.Svn())
199 methods.append(wget.Wget())
200 methods.append(svk.Svk())