blob: 903a8e61aec5ad09edace2e7c233e77f06ea381c [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"""
Patrick Williamsc0f7c042017-02-23 20:41:17 -06004BitBake 'Fetch' implementation for perforce
Patrick Williamsc124f4f2015-09-15 14:41:29 -05005
6"""
7
8# Copyright (C) 2003, 2004 Chris Larson
Patrick Williamsc0f7c042017-02-23 20:41:17 -06009# Copyright (C) 2016 Kodak Alaris, Inc.
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License version 2 as
13# published by the Free Software Foundation.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License along
21# with this program; if not, write to the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23#
24# Based on functions from the base bb module, Copyright 2003 Holger Schurig
25
Patrick Williamsc124f4f2015-09-15 14:41:29 -050026import os
Patrick Williamsc124f4f2015-09-15 14:41:29 -050027import logging
28import bb
Patrick Williamsc124f4f2015-09-15 14:41:29 -050029from bb.fetch2 import FetchMethod
30from bb.fetch2 import FetchError
31from bb.fetch2 import logger
32from bb.fetch2 import runfetchcmd
33
34class Perforce(FetchMethod):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060035 """ Class to fetch from perforce repositories """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050036 def supports(self, ud, d):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060037 """ Check to see if a given url can be fetched with perforce. """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050038 return ud.type in ['p4']
39
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040 def urldata_init(self, ud, d):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050041 """
Patrick Williamsc0f7c042017-02-23 20:41:17 -060042 Initialize perforce specific variables within url data. If P4CONFIG is
43 provided by the env, use it. If P4PORT is specified by the recipe, use
44 its values, which may override the settings in P4CONFIG.
Patrick Williamsc124f4f2015-09-15 14:41:29 -050045 """
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080046 ud.basecmd = d.getVar("FETCHCMD_p4") or "/usr/bin/env p4"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080048 ud.dldir = d.getVar("P4DIR") or (d.getVar("DL_DIR") + "/p4")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050049
Patrick Williamsc0f7c042017-02-23 20:41:17 -060050 path = ud.url.split('://')[1]
51 path = path.split(';')[0]
52 delim = path.find('@');
53 if delim != -1:
54 (ud.user, ud.pswd) = path.split('@')[0].split(':')
55 ud.path = path.split('@')[1]
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060057 ud.path = path
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
Patrick Williamsc0f7c042017-02-23 20:41:17 -060059 ud.usingp4config = False
Brad Bishop6e60e8b2018-02-01 10:27:11 -050060 p4port = d.getVar('P4PORT')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050061
Patrick Williamsc0f7c042017-02-23 20:41:17 -060062 if p4port:
63 logger.debug(1, 'Using recipe provided P4PORT: %s' % p4port)
64 ud.host = p4port
65 else:
66 logger.debug(1, 'Trying to use P4CONFIG to automatically set P4PORT...')
67 ud.usingp4config = True
68 p4cmd = '%s info | grep "Server address"' % ud.basecmd
Brad Bishop6e60e8b2018-02-01 10:27:11 -050069 bb.fetch2.check_network_access(d, p4cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060070 ud.host = runfetchcmd(p4cmd, d, True)
71 ud.host = ud.host.split(': ')[1].strip()
72 logger.debug(1, 'Determined P4PORT to be: %s' % ud.host)
73 if not ud.host:
74 raise FetchError('Could not determine P4PORT from P4CONFIG')
75
76 if ud.path.find('/...') >= 0:
77 ud.pathisdir = True
78 else:
79 ud.pathisdir = False
80
81 cleanedpath = ud.path.replace('/...', '').replace('/', '.')
82 cleanedhost = ud.host.replace(':', '.')
83 ud.pkgdir = os.path.join(ud.dldir, cleanedhost, cleanedpath)
84
Brad Bishop6e60e8b2018-02-01 10:27:11 -050085 ud.setup_revisions(d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060086
Brad Bishop6e60e8b2018-02-01 10:27:11 -050087 ud.localfile = d.expand('%s_%s_%s.tar.gz' % (cleanedhost, cleanedpath, ud.revision))
Patrick Williamsc0f7c042017-02-23 20:41:17 -060088
89 def _buildp4command(self, ud, d, command, depot_filename=None):
90 """
91 Build a p4 commandline. Valid commands are "changes", "print", and
92 "files". depot_filename is the full path to the file in the depot
93 including the trailing '#rev' value.
94 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050095 p4opt = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -050096
Patrick Williamsc0f7c042017-02-23 20:41:17 -060097 if ud.user:
98 p4opt += ' -u "%s"' % (ud.user)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050099
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600100 if ud.pswd:
101 p4opt += ' -P "%s"' % (ud.pswd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500102
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600103 if ud.host and not ud.usingp4config:
104 p4opt += ' -p %s' % (ud.host)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500105
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600106 if hasattr(ud, 'revision') and ud.revision:
107 pathnrev = '%s@%s' % (ud.path, ud.revision)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500108 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600109 pathnrev = '%s' % (ud.path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500110
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600111 if depot_filename:
112 if ud.pathisdir: # Remove leading path to obtain filename
113 filename = depot_filename[len(ud.path)-1:]
114 else:
115 filename = depot_filename[depot_filename.rfind('/'):]
116 filename = filename[:filename.find('#')] # Remove trailing '#rev'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500117
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600118 if command == 'changes':
119 p4cmd = '%s%s changes -m 1 //%s' % (ud.basecmd, p4opt, pathnrev)
120 elif command == 'print':
121 if depot_filename != None:
122 p4cmd = '%s%s print -o "p4/%s" "%s"' % (ud.basecmd, p4opt, filename, depot_filename)
123 else:
124 raise FetchError('No depot file name provided to p4 %s' % command, ud.url)
125 elif command == 'files':
126 p4cmd = '%s%s files //%s' % (ud.basecmd, p4opt, pathnrev)
127 else:
128 raise FetchError('Invalid p4 command %s' % command, ud.url)
129
130 return p4cmd
131
132 def _p4listfiles(self, ud, d):
133 """
134 Return a list of the file names which are present in the depot using the
135 'p4 files' command, including trailing '#rev' file revision indicator
136 """
137 p4cmd = self._buildp4command(ud, d, 'files')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500138 bb.fetch2.check_network_access(d, p4cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600139 p4fileslist = runfetchcmd(p4cmd, d, True)
140 p4fileslist = [f.rstrip() for f in p4fileslist.splitlines()]
141
142 if not p4fileslist:
143 raise FetchError('Unable to fetch listing of p4 files from %s@%s' % (ud.host, ud.path))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144
145 count = 0
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600146 filelist = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500147
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600148 for filename in p4fileslist:
149 item = filename.split(' - ')
150 lastaction = item[1].split()
151 logger.debug(1, 'File: %s Last Action: %s' % (item[0], lastaction[0]))
152 if lastaction[0] == 'delete':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500153 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600154 filelist.append(item[0])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600156 return filelist
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500157
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600158 def download(self, ud, d):
159 """ Get the list of files, fetch each one """
160 filelist = self._p4listfiles(ud, d)
161 if not filelist:
162 raise FetchError('No files found in depot %s@%s' % (ud.host, ud.path))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500163
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600164 bb.utils.remove(ud.pkgdir, True)
165 bb.utils.mkdirhier(ud.pkgdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500166
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600167 for afile in filelist:
168 p4fetchcmd = self._buildp4command(ud, d, 'print', afile)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500169 bb.fetch2.check_network_access(d, p4fetchcmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600170 runfetchcmd(p4fetchcmd, d, workdir=ud.pkgdir)
171
172 runfetchcmd('tar -czf %s p4' % (ud.localpath), d, cleanup=[ud.localpath], workdir=ud.pkgdir)
173
174 def clean(self, ud, d):
175 """ Cleanup p4 specific files and dirs"""
176 bb.utils.remove(ud.localpath)
177 bb.utils.remove(ud.pkgdir, True)
178
179 def supports_srcrev(self):
180 return True
181
182 def _revision_key(self, ud, d, name):
183 """ Return a unique key for the url """
184 return 'p4:%s' % ud.pkgdir
185
186 def _latest_revision(self, ud, d, name):
187 """ Return the latest upstream scm revision number """
188 p4cmd = self._buildp4command(ud, d, "changes")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500189 bb.fetch2.check_network_access(d, p4cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600190 tip = runfetchcmd(p4cmd, d, True)
191
192 if not tip:
193 raise FetchError('Could not determine the latest perforce changelist')
194
195 tipcset = tip.split(' ')[1]
196 logger.debug(1, 'p4 tip found to be changelist %s' % tipcset)
197 return tipcset
198
199 def sortable_revision(self, ud, d, name):
200 """ Return a sortable revision number """
201 return False, self._build_revision(ud, d)
202
203 def _build_revision(self, ud, d):
204 return ud.revision
205