blob: d10f44187503053b8086ea6d2570bbd343b1c587 [file] [log] [blame]
Andrew Geisslerd159c7f2021-09-02 21:05:58 -05001# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementation for crates.io
5"""
6
7# Copyright (C) 2016 Doug Goldstein
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21#
22# Based on functions from the base bb module, Copyright 2003 Holger Schurig
23
24import hashlib
25import json
26import os
27import shutil
28import subprocess
29import bb
30from bb.fetch2 import logger, subprocess_setup, UnpackError
31from bb.fetch2.wget import Wget
32
33
34class Crate(Wget):
35
36 """Class to fetch crates via wget"""
37
38 def _cargo_bitbake_path(self, rootdir):
39 return os.path.join(rootdir, "cargo_home", "bitbake")
40
41 def supports(self, ud, d):
42 """
43 Check to see if a given url is for this fetcher
44 """
45 return ud.type in ['crate']
46
47 def recommends_checksum(self, urldata):
48 return False
49
50 def urldata_init(self, ud, d):
51 """
52 Sets up to download the respective crate from crates.io
53 """
54
55 if ud.type == 'crate':
56 self._crate_urldata_init(ud, d)
57
58 super(Crate, self).urldata_init(ud, d)
59
60 def _crate_urldata_init(self, ud, d):
61 """
62 Sets up the download for a crate
63 """
64
65 # URL syntax is: crate://NAME/VERSION
66 # break the URL apart by /
67 parts = ud.url.split('/')
68 if len(parts) < 5:
69 raise bb.fetch2.ParameterError("Invalid URL: Must be crate://HOST/NAME/VERSION", ud.url)
70
71 # last field is version
72 version = parts[len(parts) - 1]
73 # second to last field is name
74 name = parts[len(parts) - 2]
75 # host (this is to allow custom crate registries to be specified
76 host = '/'.join(parts[2:len(parts) - 2])
77
78 # if using upstream just fix it up nicely
79 if host == 'crates.io':
80 host = 'crates.io/api/v1/crates'
81
82 ud.url = "https://%s/%s/%s/download" % (host, name, version)
83 ud.parm['downloadfilename'] = "%s-%s.crate" % (name, version)
84 ud.parm['name'] = name
85
86 logger.debug(2, "Fetching %s to %s" % (ud.url, ud.parm['downloadfilename']))
87
88 def unpack(self, ud, rootdir, d):
89 """
90 Uses the crate to build the necessary paths for cargo to utilize it
91 """
92 if ud.type == 'crate':
93 return self._crate_unpack(ud, rootdir, d)
94 else:
95 super(Crate, self).unpack(ud, rootdir, d)
96
97 def _crate_unpack(self, ud, rootdir, d):
98 """
99 Unpacks a crate
100 """
101 thefile = ud.localpath
102
103 # possible metadata we need to write out
104 metadata = {}
105
106 # change to the rootdir to unpack but save the old working dir
107 save_cwd = os.getcwd()
108 os.chdir(rootdir)
109
110 pn = d.getVar('BPN')
111 if pn == ud.parm.get('name'):
112 cmd = "tar -xz --no-same-owner -f %s" % thefile
113 else:
114 cargo_bitbake = self._cargo_bitbake_path(rootdir)
115
116 cmd = "tar -xz --no-same-owner -f %s -C %s" % (thefile, cargo_bitbake)
117
118 # ensure we've got these paths made
119 bb.utils.mkdirhier(cargo_bitbake)
120
121 # generate metadata necessary
122 with open(thefile, 'rb') as f:
123 # get the SHA256 of the original tarball
124 tarhash = hashlib.sha256(f.read()).hexdigest()
125
126 metadata['files'] = {}
127 metadata['package'] = tarhash
128
129 # path it
130 path = d.getVar('PATH')
131 if path:
132 cmd = "PATH=\"%s\" %s" % (path, cmd)
133 bb.note("Unpacking %s to %s/" % (thefile, os.getcwd()))
134
135 ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True)
136
137 os.chdir(save_cwd)
138
139 if ret != 0:
140 raise UnpackError("Unpack command %s failed with return value %s" % (cmd, ret), ud.url)
141
142 # if we have metadata to write out..
143 if len(metadata) > 0:
144 cratepath = os.path.splitext(os.path.basename(thefile))[0]
145 bbpath = self._cargo_bitbake_path(rootdir)
146 mdfile = '.cargo-checksum.json'
147 mdpath = os.path.join(bbpath, cratepath, mdfile)
148 with open(mdpath, "w") as f:
149 json.dump(metadata, f)