blob: f57c2a4f52fe22ad9de65670737e8a6e9b4ce121 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001"""
Patrick Williamsc0f7c042017-02-23 20:41:17 -06002BitBake 'Fetch' implementation for perforce
Patrick Williamsc124f4f2015-09-15 14:41:29 -05003
4"""
5
6# Copyright (C) 2003, 2004 Chris Larson
Patrick Williamsc0f7c042017-02-23 20:41:17 -06007# Copyright (C) 2016 Kodak Alaris, Inc.
Patrick Williamsc124f4f2015-09-15 14:41:29 -05008#
Brad Bishopc342db32019-05-15 21:57:59 -04009# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
11# Based on functions from the base bb module, Copyright 2003 Holger Schurig
12
Patrick Williamsc124f4f2015-09-15 14:41:29 -050013import os
Patrick Williamsc124f4f2015-09-15 14:41:29 -050014import bb
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015from bb.fetch2 import FetchMethod
16from bb.fetch2 import FetchError
17from bb.fetch2 import logger
18from bb.fetch2 import runfetchcmd
19
20class Perforce(FetchMethod):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060021 """ Class to fetch from perforce repositories """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050022 def supports(self, ud, d):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060023 """ Check to see if a given url can be fetched with perforce. """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050024 return ud.type in ['p4']
25
Patrick Williamsc124f4f2015-09-15 14:41:29 -050026 def urldata_init(self, ud, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050027 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -060028 Initialize perforce specific variables within url data. If P4CONFIG is
29 provided by the env, use it. If P4PORT is specified by the recipe, use
30 its values, which may override the settings in P4CONFIG.
Patrick Williamsc124f4f2015-09-15 14:41:29 -050031 """
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080032 ud.basecmd = d.getVar("FETCHCMD_p4") or "/usr/bin/env p4"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080034 ud.dldir = d.getVar("P4DIR") or (d.getVar("DL_DIR") + "/p4")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050035
Patrick Williamsc0f7c042017-02-23 20:41:17 -060036 path = ud.url.split('://')[1]
37 path = path.split(';')[0]
38 delim = path.find('@');
39 if delim != -1:
40 (ud.user, ud.pswd) = path.split('@')[0].split(':')
41 ud.path = path.split('@')[1]
Patrick Williamsc124f4f2015-09-15 14:41:29 -050042 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060043 ud.path = path
Patrick Williamsc124f4f2015-09-15 14:41:29 -050044
Patrick Williamsc0f7c042017-02-23 20:41:17 -060045 ud.usingp4config = False
Brad Bishop6e60e8b2018-02-01 10:27:11 -050046 p4port = d.getVar('P4PORT')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047
Patrick Williamsc0f7c042017-02-23 20:41:17 -060048 if p4port:
49 logger.debug(1, 'Using recipe provided P4PORT: %s' % p4port)
50 ud.host = p4port
51 else:
52 logger.debug(1, 'Trying to use P4CONFIG to automatically set P4PORT...')
53 ud.usingp4config = True
54 p4cmd = '%s info | grep "Server address"' % ud.basecmd
Brad Bishop6e60e8b2018-02-01 10:27:11 -050055 bb.fetch2.check_network_access(d, p4cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060056 ud.host = runfetchcmd(p4cmd, d, True)
57 ud.host = ud.host.split(': ')[1].strip()
58 logger.debug(1, 'Determined P4PORT to be: %s' % ud.host)
59 if not ud.host:
60 raise FetchError('Could not determine P4PORT from P4CONFIG')
61
62 if ud.path.find('/...') >= 0:
63 ud.pathisdir = True
64 else:
65 ud.pathisdir = False
66
67 cleanedpath = ud.path.replace('/...', '').replace('/', '.')
68 cleanedhost = ud.host.replace(':', '.')
69 ud.pkgdir = os.path.join(ud.dldir, cleanedhost, cleanedpath)
70
Brad Bishop6e60e8b2018-02-01 10:27:11 -050071 ud.setup_revisions(d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060072
Brad Bishop6e60e8b2018-02-01 10:27:11 -050073 ud.localfile = d.expand('%s_%s_%s.tar.gz' % (cleanedhost, cleanedpath, ud.revision))
Patrick Williamsc0f7c042017-02-23 20:41:17 -060074
75 def _buildp4command(self, ud, d, command, depot_filename=None):
76 """
77 Build a p4 commandline. Valid commands are "changes", "print", and
78 "files". depot_filename is the full path to the file in the depot
79 including the trailing '#rev' value.
80 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081 p4opt = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050082
Patrick Williamsc0f7c042017-02-23 20:41:17 -060083 if ud.user:
84 p4opt += ' -u "%s"' % (ud.user)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050085
Patrick Williamsc0f7c042017-02-23 20:41:17 -060086 if ud.pswd:
87 p4opt += ' -P "%s"' % (ud.pswd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088
Patrick Williamsc0f7c042017-02-23 20:41:17 -060089 if ud.host and not ud.usingp4config:
90 p4opt += ' -p %s' % (ud.host)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050091
Patrick Williamsc0f7c042017-02-23 20:41:17 -060092 if hasattr(ud, 'revision') and ud.revision:
93 pathnrev = '%s@%s' % (ud.path, ud.revision)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060095 pathnrev = '%s' % (ud.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050096
Patrick Williamsc0f7c042017-02-23 20:41:17 -060097 if depot_filename:
98 if ud.pathisdir: # Remove leading path to obtain filename
99 filename = depot_filename[len(ud.path)-1:]
100 else:
101 filename = depot_filename[depot_filename.rfind('/'):]
102 filename = filename[:filename.find('#')] # Remove trailing '#rev'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500103
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600104 if command == 'changes':
105 p4cmd = '%s%s changes -m 1 //%s' % (ud.basecmd, p4opt, pathnrev)
106 elif command == 'print':
Andrew Geissler82c905d2020-04-13 13:39:40 -0500107 if depot_filename is not None:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600108 p4cmd = '%s%s print -o "p4/%s" "%s"' % (ud.basecmd, p4opt, filename, depot_filename)
109 else:
110 raise FetchError('No depot file name provided to p4 %s' % command, ud.url)
111 elif command == 'files':
112 p4cmd = '%s%s files //%s' % (ud.basecmd, p4opt, pathnrev)
113 else:
114 raise FetchError('Invalid p4 command %s' % command, ud.url)
115
116 return p4cmd
117
118 def _p4listfiles(self, ud, d):
119 """
120 Return a list of the file names which are present in the depot using the
121 'p4 files' command, including trailing '#rev' file revision indicator
122 """
123 p4cmd = self._buildp4command(ud, d, 'files')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500124 bb.fetch2.check_network_access(d, p4cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600125 p4fileslist = runfetchcmd(p4cmd, d, True)
126 p4fileslist = [f.rstrip() for f in p4fileslist.splitlines()]
127
128 if not p4fileslist:
129 raise FetchError('Unable to fetch listing of p4 files from %s@%s' % (ud.host, ud.path))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500130
131 count = 0
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600132 filelist = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500133
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600134 for filename in p4fileslist:
135 item = filename.split(' - ')
136 lastaction = item[1].split()
137 logger.debug(1, 'File: %s Last Action: %s' % (item[0], lastaction[0]))
138 if lastaction[0] == 'delete':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600140 filelist.append(item[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600142 return filelist
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500143
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600144 def download(self, ud, d):
145 """ Get the list of files, fetch each one """
146 filelist = self._p4listfiles(ud, d)
147 if not filelist:
148 raise FetchError('No files found in depot %s@%s' % (ud.host, ud.path))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500149
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600150 bb.utils.remove(ud.pkgdir, True)
151 bb.utils.mkdirhier(ud.pkgdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600153 for afile in filelist:
154 p4fetchcmd = self._buildp4command(ud, d, 'print', afile)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500155 bb.fetch2.check_network_access(d, p4fetchcmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600156 runfetchcmd(p4fetchcmd, d, workdir=ud.pkgdir)
157
158 runfetchcmd('tar -czf %s p4' % (ud.localpath), d, cleanup=[ud.localpath], workdir=ud.pkgdir)
159
160 def clean(self, ud, d):
161 """ Cleanup p4 specific files and dirs"""
162 bb.utils.remove(ud.localpath)
163 bb.utils.remove(ud.pkgdir, True)
164
165 def supports_srcrev(self):
166 return True
167
168 def _revision_key(self, ud, d, name):
169 """ Return a unique key for the url """
170 return 'p4:%s' % ud.pkgdir
171
172 def _latest_revision(self, ud, d, name):
173 """ Return the latest upstream scm revision number """
174 p4cmd = self._buildp4command(ud, d, "changes")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500175 bb.fetch2.check_network_access(d, p4cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600176 tip = runfetchcmd(p4cmd, d, True)
177
178 if not tip:
179 raise FetchError('Could not determine the latest perforce changelist')
180
181 tipcset = tip.split(' ')[1]
182 logger.debug(1, 'p4 tip found to be changelist %s' % tipcset)
183 return tipcset
184
185 def sortable_revision(self, ud, d, name):
186 """ Return a sortable revision number """
187 return False, self._build_revision(ud, d)
188
189 def _build_revision(self, ud, d):
190 return ud.revision
191