blob: ba83e7cb60876ca5aa860e2fd34207e94d8e1606 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' clearcase implementation
5
6The clearcase fetcher is used to retrieve files from a ClearCase repository.
7
8Usage in the recipe:
9
10 SRC_URI = "ccrc://cc.example.org/ccrc;vob=/example_vob;module=/example_module"
11 SRCREV = "EXAMPLE_CLEARCASE_TAG"
12 PV = "${@d.getVar("SRCREV", False).replace("/", "+")}"
13
14The fetcher uses the rcleartool or cleartool remote client, depending on which one is available.
15
16Supported SRC_URI options are:
17
18- vob
19 (required) The name of the clearcase VOB (with prepending "/")
20
21- module
22 The module in the selected VOB (with prepending "/")
23
24 The module and vob parameters are combined to create
25 the following load rule in the view config spec:
26 load <vob><module>
27
28- proto
29 http or https
30
31Related variables:
32
33 CCASE_CUSTOM_CONFIG_SPEC
34 Write a config spec to this variable in your recipe to use it instead
35 of the default config spec generated by this fetcher.
36 Please note that the SRCREV loses its functionality if you specify
37 this variable. SRCREV is still used to label the archive after a fetch,
38 but it doesn't define what's fetched.
39
40User credentials:
41 cleartool:
42 The login of cleartool is handled by the system. No special steps needed.
43
44 rcleartool:
45 In order to use rcleartool with authenticated users an `rcleartool login` is
46 necessary before using the fetcher.
47"""
48# Copyright (C) 2014 Siemens AG
49#
50# This program is free software; you can redistribute it and/or modify
51# it under the terms of the GNU General Public License version 2 as
52# published by the Free Software Foundation.
53#
54# This program is distributed in the hope that it will be useful,
55# but WITHOUT ANY WARRANTY; without even the implied warranty of
56# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57# GNU General Public License for more details.
58#
59# You should have received a copy of the GNU General Public License along
60# with this program; if not, write to the Free Software Foundation, Inc.,
61# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
62#
63
64import os
65import sys
66import shutil
67import bb
68from bb import data
69from bb.fetch2 import FetchMethod
70from bb.fetch2 import FetchError
71from bb.fetch2 import runfetchcmd
72from bb.fetch2 import logger
73from distutils import spawn
74
75class ClearCase(FetchMethod):
76 """Class to fetch urls via 'clearcase'"""
77 def init(self, d):
78 pass
79
80 def supports(self, ud, d):
81 """
82 Check to see if a given url can be fetched with Clearcase.
83 """
84 return ud.type in ['ccrc']
85
86 def debug(self, msg):
87 logger.debug(1, "ClearCase: %s", msg)
88
89 def urldata_init(self, ud, d):
90 """
91 init ClearCase specific variable within url data
92 """
93 ud.proto = "https"
94 if 'protocol' in ud.parm:
95 ud.proto = ud.parm['protocol']
96 if not ud.proto in ('http', 'https'):
97 raise fetch2.ParameterError("Invalid protocol type", ud.url)
98
99 ud.vob = ''
100 if 'vob' in ud.parm:
101 ud.vob = ud.parm['vob']
102 else:
103 msg = ud.url+": vob must be defined so the fetcher knows what to get."
104 raise MissingParameterError('vob', msg)
105
106 if 'module' in ud.parm:
107 ud.module = ud.parm['module']
108 else:
109 ud.module = ""
110
111 ud.basecmd = d.getVar("FETCHCMD_ccrc", True) or spawn.find_executable("cleartool") or spawn.find_executable("rcleartool")
112
113 if data.getVar("SRCREV", d, True) == "INVALID":
114 raise FetchError("Set a valid SRCREV for the clearcase fetcher in your recipe, e.g. SRCREV = \"/main/LATEST\" or any other label of your choice.")
115
116 ud.label = d.getVar("SRCREV", False)
117 ud.customspec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC", True)
118
119 ud.server = "%s://%s%s" % (ud.proto, ud.host, ud.path)
120
121 ud.identifier = "clearcase-%s%s-%s" % ( ud.vob.replace("/", ""),
122 ud.module.replace("/", "."),
123 ud.label.replace("/", "."))
124
125 ud.viewname = "%s-view%s" % (ud.identifier, d.getVar("DATETIME", d, True))
126 ud.csname = "%s-config-spec" % (ud.identifier)
127 ud.ccasedir = os.path.join(data.getVar("DL_DIR", d, True), ud.type)
128 ud.viewdir = os.path.join(ud.ccasedir, ud.viewname)
129 ud.configspecfile = os.path.join(ud.ccasedir, ud.csname)
130 ud.localfile = "%s.tar.gz" % (ud.identifier)
131
132 self.debug("host = %s" % ud.host)
133 self.debug("path = %s" % ud.path)
134 self.debug("server = %s" % ud.server)
135 self.debug("proto = %s" % ud.proto)
136 self.debug("type = %s" % ud.type)
137 self.debug("vob = %s" % ud.vob)
138 self.debug("module = %s" % ud.module)
139 self.debug("basecmd = %s" % ud.basecmd)
140 self.debug("label = %s" % ud.label)
141 self.debug("ccasedir = %s" % ud.ccasedir)
142 self.debug("viewdir = %s" % ud.viewdir)
143 self.debug("viewname = %s" % ud.viewname)
144 self.debug("configspecfile = %s" % ud.configspecfile)
145 self.debug("localfile = %s" % ud.localfile)
146
147 ud.localfile = os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
148
149 def _build_ccase_command(self, ud, command):
150 """
151 Build up a commandline based on ud
152 command is: mkview, setcs, rmview
153 """
154 options = []
155
156 if "rcleartool" in ud.basecmd:
157 options.append("-server %s" % ud.server)
158
159 basecmd = "%s %s" % (ud.basecmd, command)
160
161 if command is 'mkview':
162 if not "rcleartool" in ud.basecmd:
163 # Cleartool needs a -snapshot view
164 options.append("-snapshot")
165 options.append("-tag %s" % ud.viewname)
166 options.append(ud.viewdir)
167
168 elif command is 'rmview':
169 options.append("-force")
170 options.append("%s" % ud.viewdir)
171
172 elif command is 'setcs':
173 options.append("-overwrite")
174 options.append(ud.configspecfile)
175
176 else:
177 raise FetchError("Invalid ccase command %s" % command)
178
179 ccasecmd = "%s %s" % (basecmd, " ".join(options))
180 self.debug("ccasecmd = %s" % ccasecmd)
181 return ccasecmd
182
183 def _write_configspec(self, ud, d):
184 """
185 Create config spec file (ud.configspecfile) for ccase view
186 """
187 config_spec = ""
188 custom_config_spec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC", d)
189 if custom_config_spec is not None:
190 for line in custom_config_spec.split("\\n"):
191 config_spec += line+"\n"
192 bb.warn("A custom config spec has been set, SRCREV is only relevant for the tarball name.")
193 else:
194 config_spec += "element * CHECKEDOUT\n"
195 config_spec += "element * %s\n" % ud.label
196 config_spec += "load %s%s\n" % (ud.vob, ud.module)
197
198 logger.info("Using config spec: \n%s" % config_spec)
199
200 with open(ud.configspecfile, 'w') as f:
201 f.write(config_spec)
202
203 def _remove_view(self, ud, d):
204 if os.path.exists(ud.viewdir):
205 os.chdir(ud.ccasedir)
206 cmd = self._build_ccase_command(ud, 'rmview');
207 logger.info("cleaning up [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
208 bb.fetch2.check_network_access(d, cmd, ud.url)
209 output = runfetchcmd(cmd, d)
210 logger.info("rmview output: %s", output)
211
212 def need_update(self, ud, d):
213 if ("LATEST" in ud.label) or (ud.customspec and "LATEST" in ud.customspec):
214 ud.identifier += "-%s" % d.getVar("DATETIME",d, True)
215 return True
216 if os.path.exists(ud.localpath):
217 return False
218 return True
219
220 def supports_srcrev(self):
221 return True
222
223 def sortable_revision(self, ud, d, name):
224 return False, ud.identifier
225
226 def download(self, ud, d):
227 """Fetch url"""
228
229 # Make a fresh view
230 bb.utils.mkdirhier(ud.ccasedir)
231 self._write_configspec(ud, d)
232 cmd = self._build_ccase_command(ud, 'mkview')
233 logger.info("creating view [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
234 bb.fetch2.check_network_access(d, cmd, ud.url)
235 try:
236 runfetchcmd(cmd, d)
237 except FetchError as e:
238 if "CRCLI2008E" in e.msg:
239 raise FetchError("%s\n%s\n" % (e.msg, "Call `rcleartool login` in your console to authenticate to the clearcase server before running bitbake."))
240 else:
241 raise e
242
243 # Set configspec: Setting the configspec effectively fetches the files as defined in the configspec
244 os.chdir(ud.viewdir)
245 cmd = self._build_ccase_command(ud, 'setcs');
246 logger.info("fetching data [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
247 bb.fetch2.check_network_access(d, cmd, ud.url)
248 output = runfetchcmd(cmd, d)
249 logger.info("%s", output)
250
251 # Copy the configspec to the viewdir so we have it in our source tarball later
252 shutil.copyfile(ud.configspecfile, os.path.join(ud.viewdir, ud.csname))
253
254 # Clean clearcase meta-data before tar
255
256 runfetchcmd('tar -czf "%s" .' % (ud.localpath), d, cleanup = [ud.localpath])
257
258 # Clean up so we can create a new view next time
259 self.clean(ud, d);
260
261 def clean(self, ud, d):
262 self._remove_view(ud, d)
263 bb.utils.remove(ud.configspecfile)