This commit add basic support for crate vendoring in Rust. The user will
use something like `cargo vendor` to create a vendor directory (that can
later be deployed as a tgz) that contains all the dependencies.
This patch will analyze the output of `cargo manifest` to calculate the
closure of dependencies, and via the new parameter `--provides-vendor`,
print all the 'bundled(crate(NAME/FEATURE)) = 0.0.0' provided by the
binary.
The algorithm is not perfect, as today it will include all the features
resolved for the crate (not all the availables, tho), but basically is
something like:
1.- A dependency generator macro, cargo_bundled, will call
cargo-inspector like this:
# In STDIN we will provide the name of the binary
cargo-inspector --provides-vendor --path %{_builddir}
2.- cargo-inspector will search inside the 'path' tree a Cargo.toml that
generate the binary name send via STDIN.
3.- From this point, we go up to the tree to find the top-most
Cargo.toml, as this will be the directory where .cargo/config is living.
We make this directory our `cwd`.
4.- Using the metadata from `cargo manifest`, we generate the closure of
dependencies required by this binary. To simplify the problem, the
current code do not resolve the features, and accept the one resolved by
cargo as valid. Most of the time this will be OK, maybe will include
some extra features needed for other binaries.
5.- Print the 'bundled()' data.
This code will only be executed in the directory 'vendor' is present in
the top-most directory found on step 3.
We shouldn't crash when network communication fails, or when a subprocess fails.
The traceback is unsightly, and causes bug reports to be files. Let's just print
the error.
$ PYTHONPATH=$HOME/python/rust2rpm python -m rust2rpm ./asdfasdf.asdf
error: the manifest-path must be a path to a Cargo.toml file
Subcommand failed with code 101: cargo read-manifest --manifest-path=./asdfasdf.asdf
$ PYTHONPATH=$HOME/python/rust2rpm python -m rust2rpm asdfasdf
Failed to download metadata: 404 Client Error: Not Found for url: https://crates.io/api/v1/crates/asdfasdf/versionsFixes#145.
(This does the relatively easy thing of printing the original message. In
principle we could try to figure out what the exact error was and print uniform
error messages. But that'd be quite a lot of work, and fairly brittle, because
we'd need to cover all possible errors. So let's do this thing which should
be good enough in 95% of cases.)
The code was very hard to read because it was doing explicit lists
concatenations. Let's make the code more python by using 'yield' on
the interesting items, and hide the creation of the list in a decorator.
rpmautspec has some shortcomings (e.g. lack of support for multi-line
changelog entries), but those shortcomings are not very important for
rust packages. Let's just use rpmautospec by default for convenience.
Do not include subdirectories as %doc. Fix#136.
Sort license and doc files alphabetically. Fix#135.
Only include doc files from the root directory. Fix#134.
If a crate has a feature with `+` in it's name,
the `%__cargo_feature_from_name` macro fails to correctly parse it.
For example, the `cxxbridge-flags` crate declares (among others)
the `c++20` feature; that is currently parsed as follows:
```lua
> string.match("cxxbridge-flags+c++20-devel", "^.+%+(.+)-devel$")
20
```
The adjusted regex matches the *first* `+` as feature name separator:
```lua
> string.match("cxxbridge-flags+c++20-devel", "^[^+]+%+(.+)-devel$")
c++20
```
The SPDX license short identifier for "GNU Lesser General Public License
v2.1 or later" is LGPL-2.1-or-later [0]. Add a SPDX to Fedora mapping.
[0]: https://spdx.org/licenses/LGPL-2.1-or-later.html