blob: e2934ef9fcf55f644d77cb275dfef759a41a0a73 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001"""
2BitBake 'Fetch' clearcase implementation
3
4The clearcase fetcher is used to retrieve files from a ClearCase repository.
5
6Usage in the recipe:
7
8 SRC_URI = "ccrc://cc.example.org/ccrc;vob=/example_vob;module=/example_module"
9 SRCREV = "EXAMPLE_CLEARCASE_TAG"
10 PV = "${@d.getVar("SRCREV", False).replace("/", "+")}"
11
12The fetcher uses the rcleartool or cleartool remote client, depending on which one is available.
13
14Supported SRC_URI options are:
15
16- vob
17 (required) The name of the clearcase VOB (with prepending "/")
18
19- module
20 The module in the selected VOB (with prepending "/")
21
22 The module and vob parameters are combined to create
23 the following load rule in the view config spec:
24 load <vob><module>
25
26- proto
27 http or https
28
29Related variables:
30
31 CCASE_CUSTOM_CONFIG_SPEC
32 Write a config spec to this variable in your recipe to use it instead
33 of the default config spec generated by this fetcher.
34 Please note that the SRCREV loses its functionality if you specify
35 this variable. SRCREV is still used to label the archive after a fetch,
36 but it doesn't define what's fetched.
37
38User credentials:
39 cleartool:
40 The login of cleartool is handled by the system. No special steps needed.
41
42 rcleartool:
43 In order to use rcleartool with authenticated users an `rcleartool login` is
44 necessary before using the fetcher.
45"""
46# Copyright (C) 2014 Siemens AG
47#
Brad Bishopc342db32019-05-15 21:57:59 -040048# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049#
50
51import os
52import sys
53import shutil
54import bb
Patrick Williamsc124f4f2015-09-15 14:41:29 -050055from bb.fetch2 import FetchMethod
56from bb.fetch2 import FetchError
Brad Bishop96ff1982019-08-19 13:50:42 -040057from bb.fetch2 import MissingParameterError
58from bb.fetch2 import ParameterError
Patrick Williamsc124f4f2015-09-15 14:41:29 -050059from bb.fetch2 import runfetchcmd
60from bb.fetch2 import logger
Patrick Williamsc124f4f2015-09-15 14:41:29 -050061
62class ClearCase(FetchMethod):
63 """Class to fetch urls via 'clearcase'"""
64 def init(self, d):
65 pass
66
67 def supports(self, ud, d):
68 """
69 Check to see if a given url can be fetched with Clearcase.
70 """
71 return ud.type in ['ccrc']
72
73 def debug(self, msg):
74 logger.debug(1, "ClearCase: %s", msg)
75
76 def urldata_init(self, ud, d):
77 """
78 init ClearCase specific variable within url data
79 """
80 ud.proto = "https"
81 if 'protocol' in ud.parm:
82 ud.proto = ud.parm['protocol']
83 if not ud.proto in ('http', 'https'):
Brad Bishop96ff1982019-08-19 13:50:42 -040084 raise ParameterError("Invalid protocol type", ud.url)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050085
86 ud.vob = ''
87 if 'vob' in ud.parm:
88 ud.vob = ud.parm['vob']
89 else:
90 msg = ud.url+": vob must be defined so the fetcher knows what to get."
91 raise MissingParameterError('vob', msg)
92
93 if 'module' in ud.parm:
94 ud.module = ud.parm['module']
95 else:
96 ud.module = ""
97
Brad Bishopd5ae7d92018-06-14 09:52:03 -070098 ud.basecmd = d.getVar("FETCHCMD_ccrc") or "/usr/bin/env cleartool || rcleartool"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050099
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500100 if d.getVar("SRCREV") == "INVALID":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101 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.")
102
103 ud.label = d.getVar("SRCREV", False)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500104 ud.customspec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500105
106 ud.server = "%s://%s%s" % (ud.proto, ud.host, ud.path)
107
108 ud.identifier = "clearcase-%s%s-%s" % ( ud.vob.replace("/", ""),
109 ud.module.replace("/", "."),
110 ud.label.replace("/", "."))
111
112 ud.viewname = "%s-view%s" % (ud.identifier, d.getVar("DATETIME", d, True))
113 ud.csname = "%s-config-spec" % (ud.identifier)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500114 ud.ccasedir = os.path.join(d.getVar("DL_DIR"), ud.type)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500115 ud.viewdir = os.path.join(ud.ccasedir, ud.viewname)
116 ud.configspecfile = os.path.join(ud.ccasedir, ud.csname)
117 ud.localfile = "%s.tar.gz" % (ud.identifier)
118
119 self.debug("host = %s" % ud.host)
120 self.debug("path = %s" % ud.path)
121 self.debug("server = %s" % ud.server)
122 self.debug("proto = %s" % ud.proto)
123 self.debug("type = %s" % ud.type)
124 self.debug("vob = %s" % ud.vob)
125 self.debug("module = %s" % ud.module)
126 self.debug("basecmd = %s" % ud.basecmd)
127 self.debug("label = %s" % ud.label)
128 self.debug("ccasedir = %s" % ud.ccasedir)
129 self.debug("viewdir = %s" % ud.viewdir)
130 self.debug("viewname = %s" % ud.viewname)
131 self.debug("configspecfile = %s" % ud.configspecfile)
132 self.debug("localfile = %s" % ud.localfile)
133
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500134 ud.localfile = os.path.join(d.getVar("DL_DIR"), ud.localfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135
136 def _build_ccase_command(self, ud, command):
137 """
138 Build up a commandline based on ud
139 command is: mkview, setcs, rmview
140 """
141 options = []
142
143 if "rcleartool" in ud.basecmd:
144 options.append("-server %s" % ud.server)
145
146 basecmd = "%s %s" % (ud.basecmd, command)
147
Brad Bishop6dbb3162019-11-25 09:41:34 -0500148 if command == 'mkview':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500149 if not "rcleartool" in ud.basecmd:
150 # Cleartool needs a -snapshot view
151 options.append("-snapshot")
152 options.append("-tag %s" % ud.viewname)
153 options.append(ud.viewdir)
154
Brad Bishop6dbb3162019-11-25 09:41:34 -0500155 elif command == 'rmview':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500156 options.append("-force")
157 options.append("%s" % ud.viewdir)
158
Brad Bishop6dbb3162019-11-25 09:41:34 -0500159 elif command == 'setcs':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500160 options.append("-overwrite")
161 options.append(ud.configspecfile)
162
163 else:
164 raise FetchError("Invalid ccase command %s" % command)
165
166 ccasecmd = "%s %s" % (basecmd, " ".join(options))
167 self.debug("ccasecmd = %s" % ccasecmd)
168 return ccasecmd
169
170 def _write_configspec(self, ud, d):
171 """
172 Create config spec file (ud.configspecfile) for ccase view
173 """
174 config_spec = ""
175 custom_config_spec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC", d)
176 if custom_config_spec is not None:
177 for line in custom_config_spec.split("\\n"):
178 config_spec += line+"\n"
179 bb.warn("A custom config spec has been set, SRCREV is only relevant for the tarball name.")
180 else:
181 config_spec += "element * CHECKEDOUT\n"
182 config_spec += "element * %s\n" % ud.label
183 config_spec += "load %s%s\n" % (ud.vob, ud.module)
184
185 logger.info("Using config spec: \n%s" % config_spec)
186
187 with open(ud.configspecfile, 'w') as f:
188 f.write(config_spec)
189
190 def _remove_view(self, ud, d):
191 if os.path.exists(ud.viewdir):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500192 cmd = self._build_ccase_command(ud, 'rmview');
193 logger.info("cleaning up [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
194 bb.fetch2.check_network_access(d, cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600195 output = runfetchcmd(cmd, d, workdir=ud.ccasedir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500196 logger.info("rmview output: %s", output)
197
198 def need_update(self, ud, d):
199 if ("LATEST" in ud.label) or (ud.customspec and "LATEST" in ud.customspec):
200 ud.identifier += "-%s" % d.getVar("DATETIME",d, True)
201 return True
202 if os.path.exists(ud.localpath):
203 return False
204 return True
205
206 def supports_srcrev(self):
207 return True
208
209 def sortable_revision(self, ud, d, name):
210 return False, ud.identifier
211
212 def download(self, ud, d):
213 """Fetch url"""
214
215 # Make a fresh view
216 bb.utils.mkdirhier(ud.ccasedir)
217 self._write_configspec(ud, d)
218 cmd = self._build_ccase_command(ud, 'mkview')
219 logger.info("creating view [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
220 bb.fetch2.check_network_access(d, cmd, ud.url)
221 try:
222 runfetchcmd(cmd, d)
223 except FetchError as e:
224 if "CRCLI2008E" in e.msg:
225 raise FetchError("%s\n%s\n" % (e.msg, "Call `rcleartool login` in your console to authenticate to the clearcase server before running bitbake."))
226 else:
227 raise e
228
229 # Set configspec: Setting the configspec effectively fetches the files as defined in the configspec
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230 cmd = self._build_ccase_command(ud, 'setcs');
231 logger.info("fetching data [VOB=%s label=%s view=%s]", ud.vob, ud.label, ud.viewname)
232 bb.fetch2.check_network_access(d, cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600233 output = runfetchcmd(cmd, d, workdir=ud.viewdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500234 logger.info("%s", output)
235
236 # Copy the configspec to the viewdir so we have it in our source tarball later
237 shutil.copyfile(ud.configspecfile, os.path.join(ud.viewdir, ud.csname))
238
239 # Clean clearcase meta-data before tar
240
241 runfetchcmd('tar -czf "%s" .' % (ud.localpath), d, cleanup = [ud.localpath])
242
243 # Clean up so we can create a new view next time
244 self.clean(ud, d);
245
246 def clean(self, ud, d):
247 self._remove_view(ud, d)
248 bb.utils.remove(ud.configspecfile)