fetchers: Only call createCopy and update_data after checking if the download already...
[bitbake.git] / lib / bb / fetch / wget.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 from   bb.fetch import Fetch
32 from   bb.fetch import FetchError
33 from   bb.fetch import MD5SumError
34 from   bb.fetch import uri_replace
35
36 class Wget(Fetch):
37     """Class to fetch urls via 'wget'"""
38     def supports(self, url, ud, d):
39         """
40         Check to see if a given url can be fetched with cvs.
41         """
42         return ud.type in ['http','https','ftp']
43
44     def localpath(self, url, ud, d):
45
46         url = bb.encodeurl([ud.type, ud.host, ud.path, ud.user, ud.pswd, {}])
47
48         return data.expand(os.path.join(data.getVar("DL_DIR", d), os.path.basename(url)), d)
49
50     def go(self, uri, ud, d):
51         """Fetch urls"""
52
53         def md5_sum(parm, d):
54             """
55             Return the MD5SUM associated with the to be downloaded
56             file.
57             It can return None if no md5sum is associated
58             """
59             try:
60                 return parm['md5sum']
61             except:
62                 return None
63
64         def verify_md5sum(wanted_sum, got_sum):
65             """
66             Verify the md5sum we wanted with the one we got
67             """
68             if not wanted_sum:
69                 return True
70
71             return wanted_sum == got_sum
72
73         def fetch_uri(uri, ud, basename, d):
74             # the MD5 sum we want to verify
75             wanted_md5sum = md5_sum(ud.parm, d)
76             if os.path.exists(ud.localpath):
77                 # file exists, but we didnt complete it.. trying again..
78                 fetchcmd = data.getVar("RESUMECOMMAND", d, 1)
79             else:
80                 fetchcmd = data.getVar("FETCHCOMMAND", d, 1)
81
82             bb.msg.note(1, bb.msg.domain.Fetcher, "fetch " + uri)
83             fetchcmd = fetchcmd.replace("${URI}", uri)
84             fetchcmd = fetchcmd.replace("${FILE}", basename)
85             bb.msg.debug(2, bb.msg.domain.Fetcher, "executing " + fetchcmd)
86             ret = os.system(fetchcmd)
87             if ret != 0:
88                 return False
89
90             # check if sourceforge did send us to the mirror page
91             if not os.path.exists(ud.localpath):
92                 os.system("rm %s*" % ud.localpath) # FIXME shell quote it
93                 bb.msg.debug(2, bb.msg.domain.Fetcher, "sourceforge.net send us to the mirror on %s" % basename)
94                 return False
95
96             # supposedly complete.. write out md5sum
97             if bb.which(data.getVar('PATH', d), 'md5sum'):
98                 try:
99                     md5pipe = os.popen('md5sum ' + ud.localpath)
100                     md5data = (md5pipe.readline().split() or [ "" ])[0]
101                     md5pipe.close()
102                 except OSError:
103                     md5data = ""
104
105             # verify the md5sum
106             if not verify_md5sum(wanted_md5sum, md5data):
107                 raise MD5SumError(uri)
108
109             md5out = file(ud.md5, 'w')
110             md5out.write(md5data)
111             md5out.close()
112             return True
113
114         completed = 0
115         basename = os.path.basename(ud.path)
116
117         if os.path.exists(ud.md5):
118             #complete, nothing to see here..
119             #touch md5 file to show activity
120             os.utime(ud.md5, None)
121             return
122
123         localdata = data.createCopy(d)
124         data.setVar('OVERRIDES', "wget:" + data.getVar('OVERRIDES', localdata), localdata)
125         data.update_data(localdata)
126
127         premirrors = [ i.split() for i in (data.getVar('PREMIRRORS', localdata, 1) or "").split('\n') if i ]
128         for (find, replace) in premirrors:
129             newuri = uri_replace(uri, find, replace, d)
130             if newuri != uri:
131                 if fetch_uri(newuri, ud, basename, localdata):
132                     completed = 1
133                     break
134
135         if completed:
136             return
137
138         if fetch_uri(uri, ud, basename, localdata):
139             return
140
141         # try mirrors
142         mirrors = [ i.split() for i in (data.getVar('MIRRORS', localdata, 1) or "").split('\n') if i ]
143         for (find, replace) in mirrors:
144             newuri = uri_replace(uri, find, replace, d)
145             if newuri != uri:
146                 if fetch_uri(newuri, ud, basename, localdata):
147                     completed = 1
148                     break
149
150         if not completed:
151             raise FetchError(uri)