I'm creating this new issue. Suppose you have a spec file like this:
%global yyyymmdd %{lua: print(os.date("%Y%m%d"))} Name: foo Version: 13.0.0 Release: 1 Summary: Foo License: Foo Source0: https://github.com/kwk/llvm-project/releases/download/source-snapshot/llvm-release-%{yyyymmdd}.txt #%%if ! 0%{?in_spectool} %global llvm_version %{lua: print(io.lines(rpm.expand("%{SOURCE0}"))())} %{echo: llvm_version=%{llvm_version}} #%%endif %description My Description
And you process it with rpmdev-spectool, you'll get this error:
rpmdev-spectool
$ rm -vf ~/rpmbuild/SOURCES/llvm-release-2021*.txt && rpmdev-spectool -R -g test.spec [...] error: lua script failed: [string "<lua>"]:1: cannot open file '/home/kkleine/rpmbuild/SOURCES/llvm-release-20210419.txt' (No such file or directory) error: test.spec: line 10: Macro %llvm_version failed to expand [...]
In order to work around this error one can fence the expansion of the llvm_version variable with a check for a define:
llvm_version
define
%global yyyymmdd %{lua: print(os.date("%Y%m%d"))} Name: foo Version: 13.0.0 Release: 1 Summary: Foo License: Foo Source0: https://github.com/kwk/llvm-project/releases/download/source-snapshot/llvm-release-%{yyyymmdd}.txt %if !0%{?____in_spectool} %global llvm_version %{lua: print(io.lines(rpm.expand("%{SOURCE0}"))())} %{echo: llvm_version=%{llvm_version}} %endif %description My Description
Then you can download the source files using this invocation of rpmdev-spectool:
$ rm -vf ~/rpmbuild/SOURCES/llvm-release-2021*.txt && rpmdev-spectool -R -g --define "____in_spectool 1" test.spec Downloading: https://github.com/kwk/llvm-project/releases/download/source-snapshot/llvm-release-20210419.txt 100% of 7.0 B |######################################################################################################| Elapsed Time: 0:00:00 Time: 0:00:00 Downloaded: llvm-release-20210419.txt
I'm asking if rpmdev-spectool can provide such a define on it's own. Then an RPM spec file can protect itself from being misinterpreted by rpmdev-spectool. I would love to see this change in rpmdev-spectool and not in the invocation of rpmdev-spectool. I hope this makes sense.
spectool does not do any .spec file parsing itself, it delegates this completely to RPM. So if spectool cannot parse your .spec file, then RPM shouldn't be able to, either ... you can try with the rpmspec command.
rpmspec
RPM is able to parse my spec file.
It's clearly not, since we can't fetch the sources.
@ngompa sorry I I wanted to add a line break and accidentally hit "Comment". rpmbuild can parse my spec file but the source file needs to exist. And I thought that spectool is supposed to download the source file.
You can't rely on source files being there when the .spec file is being parsed. This introduces a chicken-and-egg-problem - spectool can't download sources because RPM can't parse the spec file because the sources aren't there.
In general, this is a very bad practice because it does not guarantee that a spec file is parseable. This kind of thing isn't even supported in the Fedora or openSUSE build systems, either.
I'm trying to find another way to guarantee parsability in all tools. Just so you know and maybe you have solution to this problem: I want to read the contents of a file (if it exists) and set a %global according the contents of the file.
%global
The only way that'll sanely work is if you have a fallback value defined first, then redefine it if and only if there's a file to parse.
Otherwise, you're just SOL, because you can't guarantee the availability of the file ahead of time.
If you're committed to this approach, though... You can tell rpmdev-spectool where your sources are (if they're not in the default directory) by passing --define "_sourcedir /path/to/sources".
--define "_sourcedir /path/to/sources"
I'm fine having defaults but I'm still trying to understand how to check for file existence. The if posix.access(“/bin/rpm”, “x”) then … end from https://rpm.org/user_doc/lua.html doesn't work.
if posix.access(“/bin/rpm”, “x”) then … end
First, what is the actual problem you're trying to solve by doing this? Because I'm not sure you really need to do it this way.
We have many spec files that build a particular version of LLVM. In order build a snapshot (e.g. with a %bcond_with snapshot_build) we want to consume externally available source tarballs that have been created for a particular day. This way the spec file only needs to know about the current date but the rest (e.g. like git revision or LLVM version) can be fetched from some URL.
%bcond_with snapshot_build
Given this context I want to dynamically set the Version: tag based on information that's not living in the spec file but in some file that is reachable using http.
Version:
This is where the source tarballs currently live in my private fork in a pre-release on github here: https://github.com/kwk/llvm-project/releases/tag/source-snapshot
The source files of the last three days are always kept and the rest is deleted. The files for the git revision and version are: llvm-release-<YYYYMMDD>.txt and llvm-git-revision-<YYYYMMDD>.txt.
llvm-release-<YYYYMMDD>.txt
llvm-git-revision-<YYYYMMDD>.txt
At this point, you're probably better served by using a proper templating language for generating your .spec file (jinja2, for example) rather than working around spectool and RPM limitations?
@decathorpe I value that we have one spec file for everything. Therefore I decided to prefix a spec file with generated information. No template needed.
Metadata Update from @kkleine: - Issue status updated to: Closed (was: Open)