fetchers: Cleanup more variables
[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 ParameterError(Exception):
42     """Exception raised when a url cannot be proccessed due to invalid parameters."""
43
44 class MD5SumError(Exception):
45     """Exception raised when a MD5SUM of a file does not match the expected one"""
46
47 def uri_replace(uri, uri_find, uri_replace, d):
48 #   bb.msg.note(1, bb.msg.domain.Fetcher, "uri_replace: operating on %s" % uri)
49     if not uri or not uri_find or not uri_replace:
50         bb.msg.debug(1, bb.msg.domain.Fetcher, "uri_replace: passed an undefined value, not replacing")
51     uri_decoded = list(bb.decodeurl(uri))
52     uri_find_decoded = list(bb.decodeurl(uri_find))
53     uri_replace_decoded = list(bb.decodeurl(uri_replace))
54     result_decoded = ['','','','','',{}]
55     for i in uri_find_decoded:
56         loc = uri_find_decoded.index(i)
57         result_decoded[loc] = uri_decoded[loc]
58         import types
59         if type(i) == types.StringType:
60             import re
61             if (re.match(i, uri_decoded[loc])):
62                 result_decoded[loc] = re.sub(i, uri_replace_decoded[loc], uri_decoded[loc])
63                 if uri_find_decoded.index(i) == 2:
64                     if d:
65                         localfn = bb.fetch.localpath(uri, d)
66                         if localfn:
67                             result_decoded[loc] = os.path.dirname(result_decoded[loc]) + "/" + os.path.basename(bb.fetch.localpath(uri, d))
68 #                       bb.msg.note(1, bb.msg.domain.Fetcher, "uri_replace: matching %s against %s and replacing with %s" % (i, uri_decoded[loc], uri_replace_decoded[loc]))
69             else:
70 #               bb.msg.note(1, bb.msg.domain.Fetcher, "uri_replace: no match")
71                 return uri
72 #           else:
73 #               for j in i.keys():
74 #                   FIXME: apply replacements against options
75     return bb.encodeurl(result_decoded)
76
77 methods = []
78 urldata = {}
79
80 def init(urls = [], d = None):
81     if d == None:
82         bb.msg.debug(2, bb.msg.domain.Fetcher, "BUG init called with None as data object!!!")
83         return
84
85     for m in methods:
86         m.urls = []
87
88     for u in urls:
89         ud = initdata(u, d)
90         if ud.method:
91             ud.method.urls.append(u)
92
93 def initdata(url, d):
94     if url not in urldata:
95         ud = FetchData()
96         (ud.type, ud.host, ud.path, ud.user, ud.pswd, ud.parm) = bb.decodeurl(data.expand(url, d))
97         ud.date = Fetch.getSRCDate(d)
98         for m in methods:
99             if m.supports(url, ud, d):
100                 ud.localpath = m.localpath(url, ud, d)
101                 # if user sets localpath for file, use it instead.
102                 if "localpath" in ud.parm:
103                     ud.localpath = ud.parm["localpath"]
104                 ud.method = m
105                 break
106         urldata[url] = ud
107     return urldata[url]
108
109 def go(d):
110     """Fetch all urls"""
111     for m in methods:
112         for u in m.urls:
113             # RP - is olddir needed?
114             olddir = os.path.abspath(os.getcwd())
115             m.go(u, urldata[u], d)
116             os.chdir(olddir)
117
118 def localpaths(d):
119     """Return a list of the local filenames, assuming successful fetch"""
120     local = []
121     for m in methods:
122         for u in m.urls:
123             local.append(urldata[u].localpath)
124     return local
125
126 def localpath(url, d):
127     ud = initdata(url, d)
128     if ud.method:
129         return ud.localpath
130     return url
131
132 class FetchData(object):
133     """Class for fetcher variable store"""
134
135 class Fetch(object):
136     """Base class for 'fetch'ing data"""
137
138     def __init__(self, urls = []):
139         self.urls = []
140
141     def supports(self, url, urldata, d):
142         """
143         Check to see if this fetch class supports a given url.
144         """
145         return 0
146
147     def localpath(self, url, urldata, d):
148         """
149         Return the local filename of a given url assuming a successful fetch.
150         Can also setup variables in urldata for use in go (saving code duplication 
151         and duplicate code execution)
152         """
153         return url
154
155     def setUrls(self, urls):
156         self.__urls = urls
157
158     def getUrls(self):
159         return self.__urls
160
161     urls = property(getUrls, setUrls, None, "Urls property")
162
163     def go(self, url, urldata, d):
164         """
165         Fetch urls
166         Assumes localpath was called first
167         """
168         raise NoMethodError("Missing implementation for url")
169
170     def getSRCDate(d):
171         """
172         Return the SRC Date for the component
173
174         d the bb.data module
175         """
176         return data.getVar("SRCDATE", d, 1) or data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1 )
177     getSRCDate = staticmethod(getSRCDate)
178
179     def try_mirror(d, tarfn):
180         """
181         Try to use a mirrored version of the sources. We do this
182         to avoid massive loads on foreign cvs and svn servers.
183         This method will be used by the different fetcher
184         implementations.
185
186         d Is a bb.data instance
187         tarfn is the name of the tarball
188         """
189         tarpath = os.path.join(data.getVar("DL_DIR", d, 1), tarfn)
190         if os.access(tarpath, os.R_OK):
191             bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists, skipping checkout." % tarfn)
192             return True
193
194         pn = data.getVar('PN', d, True)
195         src_tarball_stash = None
196         if pn:
197             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) or "").split()
198
199         for stash in src_tarball_stash:
200             fetchcmd = data.getVar("FETCHCOMMAND_mirror", d, True) or data.getVar("FETCHCOMMAND_wget", d, True)
201             uri = stash + tarfn
202             bb.msg.note(1, bb.msg.domain.Fetcher, "fetch " + uri)
203             fetchcmd = fetchcmd.replace("${URI}", uri)
204             ret = os.system(fetchcmd)
205             if ret == 0:
206                 bb.msg.note(1, bb.msg.domain.Fetcher, "Fetched %s from tarball stash, skipping checkout" % tarfn)
207                 return True
208         return False
209     try_mirror = staticmethod(try_mirror)
210
211 import cvs
212 import git
213 import local
214 import svn
215 import wget
216 import svk
217 import ssh
218
219 methods.append(cvs.Cvs())
220 methods.append(git.Git())
221 methods.append(local.Local())
222 methods.append(svn.Svn())
223 methods.append(wget.Wget())
224 methods.append(svk.Svk())
225 methods.append(ssh.SSH())