blob: 3a6573d0b23b2aa859416c6472574ccc0547e896 [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
Patrick Williamsc124f4f2015-09-15 14:41:29 -050068from bb.fetch2 import FetchMethod
69from bb.fetch2 import FetchError
70from bb.fetch2 import runfetchcmd
71from bb.fetch2 import logger
Patrick Williamsc124f4f2015-09-15 14:41:29 -050072
73class ClearCase(FetchMethod):
74 """Class to fetch urls via 'clearcase'"""
75 def init(self, d):
76 pass
77
78 def supports(self, ud, d):
79 """
80 Check to see if a given url can be fetched with Clearcase.
81 """
82 return ud.type in ['ccrc']
83
84 def debug(self, msg):
85 logger.debug(1, "ClearCase: %s", msg)
86
87 def urldata_init(self, ud, d):
88 """
89 init ClearCase specific variable within url data
90 """
91 ud.proto = "https"
92 if 'protocol' in ud.parm:
93 ud.proto = ud.parm['protocol']
94 if not ud.proto in ('http', 'https'):
95 raise fetch2.ParameterError("Invalid protocol type", ud.url)
96
97 ud.vob = ''
98 if 'vob' in ud.parm:
99 ud.vob = ud.parm['vob']
100 else:
101 msg = ud.url+": vob must be defined so the fetcher knows what to get."
102 raise MissingParameterError('vob', msg)
103
104 if 'module' in ud.parm:
105 ud.module = ud.parm['module']
106 else:
107 ud.module = ""
108
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700109 ud.basecmd = d.getVar("FETCHCMD_ccrc") or "/usr/bin/env cleartool || rcleartool"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500110
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500111 if d.getVar("SRCREV") == "INVALID":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500112 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.")
113
114 ud.label = d.getVar("SRCREV", False)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500115 ud.customspec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500116
117 ud.server = "%s://%s%s" % (ud.proto, ud.host, ud.path)
118
119 ud.identifier = "clearcase-%s%s-%s" % ( ud.vob.replace("/", ""),
120 ud.module.replace("/", "."),
121 ud.label.replace("/", "."))
122
123 ud.viewname = "%s-view%s" % (ud.identifier, d.getVar("DATETIME", d, True))
124 ud.csname = "%s-config-spec" % (ud.identifier)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500125 ud.ccasedir = os.path.join(d.getVar("DL_DIR"), ud.type)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500126 ud.viewdir = os.path.join(ud.ccasedir, ud.viewname)
127 ud.configspecfile = os.path.join(ud.ccasedir, ud.csname)
128 ud.localfile = "%s.tar.gz" % (ud.identifier)
129
130 self.debug("host = %s" % ud.host)
131 self.debug("path = %s" % ud.path)
132 self.debug("server = %s" % ud.server)
133 self.debug("proto = %s" % ud.proto)
134 self.debug("type = %s" % ud.type)
135 self.debug("vob = %s" % ud.vob)
136 self.debug("module = %s" % ud.module)
137 self.debug("basecmd = %s" % ud.basecmd)
138 self.debug("label = %s" % ud.label)
139 self.debug("ccasedir = %s" % ud.ccasedir)
140 self.debug("viewdir = %s" % ud.viewdir)
141 self.debug("viewname = %s" % ud.viewname)
142 self.debug("configspecfile = %s" % ud.configspecfile)
143 self.debug("localfile = %s" % ud.localfile)
144
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500145 ud.localfile = os.path.join(d.getVar("DL_DIR"), ud.localfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500146
147 def _build_ccase_command(self, ud, command):
148 """
149 Build up a commandline based on ud
150 command is: mkview, setcs, rmview
151 """
152 options = []
153
154 if "rcleartool" in ud.basecmd:
155 options.append("-server %s" % ud.server)
156
157 basecmd = "%s %s" % (ud.basecmd, command)
158
159 if command is 'mkview':
160 if not "rcleartool" in ud.basecmd:
161 # Cleartool needs a -snapshot view
162 options.append("-snapshot")
163 options.append("-tag %s" % ud.viewname)
164 options.append(ud.viewdir)
165
166 elif command is 'rmview':
167 options.append("-force")
168 options.append("%s" % ud.viewdir)
169
170 elif command is 'setcs':
171 options.append("-overwrite")
172 options.append(ud.configspecfile)
173
174 else:
175 raise FetchError("Invalid ccase command %s" % command)
176
177 ccasecmd = "%s %s" % (basecmd, " ".join(options))
178 self.debug("ccasecmd = %s" % ccasecmd)
179 return ccasecmd
180
181 def _write_configspec(self, ud, d):
182 """
183 Create config spec file (ud.configspecfile) for ccase view
184 """
185 config_spec = ""
186 custom_config_spec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC", d)
187 if custom_config_spec is not None:
188 for line in custom_config_spec.split("\\n"):
189 config_spec += line+"\n"
190 bb.warn("A custom config spec has been set, SRCREV is only relevant for the tarball name.")
191 else:
192 config_spec += "element * CHECKEDOUT\n"
193 config_spec += "element * %s\n" % ud.label
194 config_spec += "load %s%s\n" % (ud.vob, ud.module)
195
196 logger.info("Using config spec: \n%s" % config_spec)
197
198 with open(ud.configspecfile, 'w') as f:
199 f.write(config_spec)
200
201 def _remove_view(self, ud, d):
202 if os.path.exists(ud.viewdir):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500203 cmd = self._build_ccase_command(ud, 'rmview');
204 logger.info("cleaning up [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
205 bb.fetch2.check_network_access(d, cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600206 output = runfetchcmd(cmd, d, workdir=ud.ccasedir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500207 logger.info("rmview output: %s", output)
208
209 def need_update(self, ud, d):
210 if ("LATEST" in ud.label) or (ud.customspec and "LATEST" in ud.customspec):
211 ud.identifier += "-%s" % d.getVar("DATETIME",d, True)
212 return True
213 if os.path.exists(ud.localpath):
214 return False
215 return True
216
217 def supports_srcrev(self):
218 return True
219
220 def sortable_revision(self, ud, d, name):
221 return False, ud.identifier
222
223 def download(self, ud, d):
224 """Fetch url"""
225
226 # Make a fresh view
227 bb.utils.mkdirhier(ud.ccasedir)
228 self._write_configspec(ud, d)
229 cmd = self._build_ccase_command(ud, 'mkview')
230 logger.info("creating view [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
231 bb.fetch2.check_network_access(d, cmd, ud.url)
232 try:
233 runfetchcmd(cmd, d)
234 except FetchError as e:
235 if "CRCLI2008E" in e.msg:
236 raise FetchError("%s\n%s\n" % (e.msg, "Call `rcleartool login` in your console to authenticate to the clearcase server before running bitbake."))
237 else:
238 raise e
239
240 # Set configspec: Setting the configspec effectively fetches the files as defined in the configspec
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500241 cmd = self._build_ccase_command(ud, 'setcs');
242 logger.info("fetching data [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
243 bb.fetch2.check_network_access(d, cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600244 output = runfetchcmd(cmd, d, workdir=ud.viewdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500245 logger.info("%s", output)
246
247 # Copy the configspec to the viewdir so we have it in our source tarball later
248 shutil.copyfile(ud.configspecfile, os.path.join(ud.viewdir, ud.csname))
249
250 # Clean clearcase meta-data before tar
251
252 runfetchcmd('tar -czf "%s" .' % (ud.localpath), d, cleanup = [ud.localpath])
253
254 # Clean up so we can create a new view next time
255 self.clean(ud, d);
256
257 def clean(self, ud, d):
258 self._remove_view(ud, d)
259 bb.utils.remove(ud.configspecfile)