unify mirror support and make it independant of the fetcher
[bitbake.git] / lib / bb / fetch / perforce.py
1 # ex:ts=4:sw=4:sts=4:et
2 # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3 """
4 BitBake 'Fetch' implementations
5
6 Classes for obtaining upstream sources for the
7 BitBake 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 import os
29 import bb
30 from   bb import data
31 from   bb.fetch import Fetch
32 from   bb.fetch import FetchError
33
34 class Perforce(Fetch):
35     def supports(self, url, ud, d):
36         return ud.type in ['p4']
37
38     def doparse(url,d):
39         parm = {}
40         path = url.split("://")[1]
41         delim = path.find("@");
42         if delim != -1:
43             (user,pswd,host,port) = path.split('@')[0].split(":")
44             path = path.split('@')[1]
45         else:
46             (host,port) = data.getVar('P4PORT', d).split(':')
47             user = ""
48             pswd = ""
49
50         if path.find(";") != -1:
51             keys=[]
52             values=[]
53             plist = path.split(';')
54             for item in plist:
55                 if item.count('='):
56                     (key,value) = item.split('=')
57                     keys.append(key)
58                     values.append(value)
59
60             parm = dict(zip(keys,values))
61         path = "//" + path.split(';')[0]
62         host += ":%s" % (port)
63         parm["cset"] = Perforce.getcset(d, path, host, user, pswd, parm)
64
65         return host,path,user,pswd,parm
66     doparse = staticmethod(doparse)
67
68     def getcset(d, depot,host,user,pswd,parm):
69         p4opt = ""
70         if "cset" in parm:
71             return parm["cset"];
72         if user:
73             p4opt += " -u %s" % (user)
74         if pswd:
75             p4opt += " -P %s" % (pswd)
76         if host:
77             p4opt += " -p %s" % (host)
78
79         p4date = data.getVar("P4DATE", d, 1)
80         if "revision" in parm:
81             depot += "#%s" % (parm["revision"])
82         elif "label" in parm:
83             depot += "@%s" % (parm["label"])
84         elif p4date:
85             depot += "@%s" % (p4date)
86
87         p4cmd = data.getVar('FETCHCOMMAND_p4', d, 1)
88         bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s%s changes -m 1 %s" % (p4cmd, p4opt, depot))
89         p4file = os.popen("%s%s changes -m 1 %s" % (p4cmd, p4opt, depot))
90         cset = p4file.readline().strip()
91         bb.msg.debug(1, bb.msg.domain.Fetcher, "READ %s" % (cset))
92         if not cset:
93             return -1
94
95         return cset.split(' ')[1]
96     getcset = staticmethod(getcset)
97
98     def localpath(self, url, ud, d):        
99
100         (host,path,user,pswd,parm) = Perforce.doparse(url,d)
101
102         # If a label is specified, we use that as our filename
103
104         if "label" in parm:
105             ud.localfile = "%s.tar.gz" % (parm["label"])
106             return os.path.join(data.getVar("DL_DIR", d, 1), ud.localfile)
107
108         base = path
109         which = path.find('/...')
110         if which != -1:
111             base = path[:which]
112
113         if base[0] == "/":
114             base = base[1:]
115
116         cset = Perforce.getcset(d, path, host, user, pswd, parm)
117
118         ud.localfile = data.expand('%s+%s+%s.tar.gz' % (host,base.replace('/', '.'), cset), d)
119
120         return os.path.join(data.getVar("DL_DIR", d, 1), ud.localfile)
121
122     def go(self, loc, ud, d):
123         """
124         Fetch urls
125         """
126
127         (host,depot,user,pswd,parm) = Perforce.doparse(loc, d)
128
129         if depot.find('/...') != -1:
130             path = depot[:depot.find('/...')]
131         else:
132             path = depot
133
134         if "module" in parm:
135             module = parm["module"]
136         else:
137             module = os.path.basename(path)
138
139         localdata = data.createCopy(d)
140         data.setVar('OVERRIDES', "p4:%s" % data.getVar('OVERRIDES', localdata), localdata)
141         data.update_data(localdata)
142
143         # Get the p4 command
144         p4opt = ""
145         if user:
146             p4opt += " -u %s" % (user)
147
148         if pswd:
149             p4opt += " -P %s" % (pswd)
150
151         if host:
152             p4opt += " -p %s" % (host)
153
154         p4cmd = data.getVar('FETCHCOMMAND', localdata, 1)
155
156         # create temp directory
157         bb.msg.debug(2, bb.msg.domain.Fetcher, "Fetch: creating temporary directory")
158         bb.mkdirhier(data.expand('${WORKDIR}', localdata))
159         data.setVar('TMPBASE', data.expand('${WORKDIR}/oep4.XXXXXX', localdata), localdata)
160         tmppipe = os.popen(data.getVar('MKTEMPDIRCMD', localdata, 1) or "false")
161         tmpfile = tmppipe.readline().strip()
162         if not tmpfile:
163             bb.error("Fetch: unable to create temporary directory.. make sure 'mktemp' is in the PATH.")
164             raise FetchError(module)
165
166         if "label" in parm:
167             depot = "%s@%s" % (depot,parm["label"])
168         else:
169             cset = Perforce.getcset(d, depot, host, user, pswd, parm)
170             depot = "%s@%s" % (depot,cset)
171
172         os.chdir(tmpfile)
173         bb.msg.note(1, bb.msg.domain.Fetcher, "Fetch " + loc)
174         bb.msg.note(1, bb.msg.domain.Fetcher, "%s%s files %s" % (p4cmd, p4opt, depot))
175         p4file = os.popen("%s%s files %s" % (p4cmd, p4opt, depot))
176
177         if not p4file:
178             bb.error("Fetch: unable to get the P4 files from %s" % (depot))
179             raise FetchError(module)
180
181         count = 0
182
183         for file in p4file: 
184             list = file.split()
185
186             if list[2] == "delete":
187                 continue
188
189             dest = list[0][len(path)+1:]
190             where = dest.find("#")
191
192             os.system("%s%s print -o %s/%s %s" % (p4cmd, p4opt, module,dest[:where],list[0]))
193             count = count + 1
194             
195         if count == 0:
196             bb.error("Fetch:  No files gathered from the P4 fetch")
197             raise FetchError(module)
198
199         myret = os.system("tar -czf %s %s" % (ud.localpath, module))
200         if myret != 0:
201             try:
202                 os.unlink(ud.localpath)
203             except OSError:
204                 pass
205             raise FetchError(module)
206         # cleanup
207         os.system('rm -rf %s' % tmpfile)
208
209