2

In my rpm I have a full directory that I want to tag with %config(noreplace). There is a file in that directory that I want to replace on every install with the latest from the rpm, using the semantics from %config.

Using the guide here: http://www-uxsup.csx.cam.ac.uk/~jw35/docs/rpm_config.html, I tried the following:

%files
%config(noreplace) /my/saved/dir/*
%config /my/saved/dir/file1

and

%files
%config /my/saved/dir/file1
%config(noreplace) /my/saved/dir/*

hoping that the specific command would override the glob, but it didn't work. Is there any RPM like command that I can use to force the %config behaviour on a file that's nested under a %config(noreplace) directory?

Kyle Fransham
  • 1,859
  • 1
  • 19
  • 22

2 Answers2

6

From: http://ftp.rpm.org/max-rpm/s1-rpm-inside-files-list-directives.html

There is a restriction to the %config directive, and that restriction is that no more than one filename may follow the %config. This means that the following example is the only allowable way to specify config files:

%config /etc/foonly

Note that the full path to the file, as it is installed at build time, is required.

However you can craft that list dynamically in %install section:

%install
echo '%dir /etc' >> list.txt
echo '%config(noreplace) /etc/foo' >> list.txt
# use for-loop or any other shell scripting technique

%files -f list.txt
Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
msuchy
  • 5,162
  • 1
  • 14
  • 26
2

The assumption is that every file in the package is listed in the %files section (list) of .spec file exactly once. I bet when you were running rpmbuild there was the following line in the output

warning: File listed twice: /my/saved/dir/file1

The solution is to list configuration file (which you want to be always overwritten) only once and with proper directive i.e. %config(noreplace). This is no matter if it is specified directly or indirectly through wildcard character.

The statement referenced in msuchy's answer

There is a restriction to the %config directive, and that restriction is that no more than one filename may follow the %config.

must be from distant past for there are examples of spec files using wildcard characters in %config directive as early as in year 2008.

The problem is not in using wildcard characters per se. The problem is that one and the same file is listed twice (once directly, and once indirectly as a result of usage of wildcard character) with different %config directives (once with plain %config and once with %config(noreplace)). Your test – changing order of these two declarations – and the result you observe suggests that rpm merges these two declarations into one %config(noreplace). This would explain why the order of declarations does not matter. However, as I wrote above, the assumption is that every file is listed exactly once and this could be the reason I couldn't find any information on what is supposed to happen when some file is listed more than once.

Please note, that the file specified with %config(noreplace) must have changed – in the package – between the version already installed and the newer version being installed for .rpmnew files to be written – see .rpmnew file not created on package upgrade?

Please be also aware that installation of newer version of some package is not treated like updating the package – see Unexpected RPM conflict on %config(noreplace) files

Below are spec files for those wanting to try themselves.

mypackage-old.spec:

Summary: old version
Name: mypackage
Version: 1
Release: 1
License: BSD

%description
https://stackoverflow.com/questions/32610487/

%prep

%build

%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/foo
echo 'replace' > %{buildroot}/foo/replace
echo 'noreplace' > %{buildroot}/foo/noreplace

%clean
rm -rf %{buildroot}


%files
%defattr(-,root,root,-)
%config /foo/replace
%config(noreplace) /foo/*

mypackage-new.spec:

Summary: new version
Name: mypackage
Version: 2
Release: 1
License: BSD

%description
https://stackoverflow.com/questions/32610487/

%prep

%build

%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/foo
echo 'new replace' > %{buildroot}/foo/replace
echo 'new noreplace' > %{buildroot}/foo/noreplace

%clean
rm -rf %{buildroot}

%files
%defattr(-,root,root,-)
# declaration A    
%config /foo/replace    
# declaration B
%config(noreplace) /foo/*

The result with RPM version 4.14.0 is the same no matter what order we place declarations A and B above:

% rpmbuild -ba ./mypackge-old.spec
% rpmbuild -ba ./mypackge-new.spec
% sudo rpm -i ~/rpmbuild/RPMS/x86_64/mypackage-1-1.x86_64.rpm
% echo modified >> /foo/replace
% echo modified >> /foo/noreplace
% sudo rpm -U ~/rpmbuild/RPMS/x86_64/mypackage-2-1.x86_64.rpm
warning: /foo/noreplace created as /foo/noreplace.rpmnew
warning: /foo/replace created as /foo/replace.rpmnew
Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366