#
SET(LIBZYPP_MAJOR "17")
SET(LIBZYPP_COMPATMINOR "9")
-SET(LIBZYPP_MINOR "9")
+SET(LIBZYPP_MINOR "10")
SET(LIBZYPP_PATCH "0")
#
-# LAST RELEASED: 17.9.0 (9)
+# LAST RELEASED: 17.10.0 (9)
# (The number in parenthesis is LIBZYPP_COMPATMINOR)
#=======
Release: 0
License: GPL-2.0+
Url: https://github.com/openSUSE/libzypp
-Summary: Package, Patch, Pattern, and Product Management
+Summary: Library for package, patch, pattern and product management
Group: System/Packages
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Source: %{name}-%{version}.tar.bz2
BuildRequires: pkg-config
%endif
-BuildRequires: libsolv-devel >= 0.6.35
+BuildRequires: libsolv-devel >= 0.7.1
%if 0%{?suse_version} >= 1100
BuildRequires: libsolv-tools
%requires_eq libsolv-tools
%endif
%description
-Package, Patch, Pattern, and Product Management
+libzypp is the package management library that powers applications
+like YaST, zypper and the openSUSE/SLE implementation of PackageKit.
+
+libzypp provides functionality for a package manager:
+
+ * An API for package repository management, supporting most common
+ repository metadata formats and signed repositories.
+ * An API for solving packages, products, patterns and patches
+ (installation, removal, update and distribution upgrade
+ operations) dependencies, with additional features like locking.
+ * An API for commiting the transaction to the system over a rpm
+ target. Supporting deltarpm calculation, media changing and
+ installation order calculation.
+ * An API for browsing available and installed software, with some
+ facilities for programs with an user interface.
%package devel
-Summary: Package, Patch, Pattern, and Product Management - developers files
+Summary: Header files for libzypp, a library for package management
Group: Development/Libraries/C and C++
Provides: yast2-packagemanager-devel
Obsoletes: yast2-packagemanager-devel
%endif
%description devel
-Package, Patch, Pattern, and Product Management - developers files
+Development files for libzypp, a library for package, patch, pattern
+and product management.
%package devel-doc
-Summary: Package, Patch, Pattern, and Product Management - developers files
+Summary: Developer documentation for libzypp
Group: Documentation/HTML
%description devel-doc
-Package, Patch, Pattern, and Product Management - developers files
+Developer documentation for libzypp.
%prep
%setup -q
%build
mkdir build
cd build
-export CFLAGS="$RPM_OPT_FLAGS"
-export CXXFLAGS="$RPM_OPT_FLAGS"
+export CFLAGS="%{optflags}"
+export CXXFLAGS="%{optflags}"
unset EXTRA_CMAKE_OPTIONS
# No libproxy on SLE11
%if 0%{?suse_version} == 1110
make -C tests %{?_smp_mflags}
%install
-rm -rf "$RPM_BUILD_ROOT"
cd build
-make install DESTDIR=$RPM_BUILD_ROOT
-make -C doc/autodoc install DESTDIR=$RPM_BUILD_ROOT
+%make_install
+%make_install -C doc/autodoc
%if 0%{?fedora_version} || 0%{?rhel_version} >= 600 || 0%{?centos_version} >= 600
-ln -s %{_sysconfdir}/yum.repos.d $RPM_BUILD_ROOT%{_sysconfdir}/zypp/repos.d
+ln -s %{_sysconfdir}/yum.repos.d %{buildroot}/%{_sysconfdir}/zypp/repos.d
%else
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/repos.d
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/repos.d
%endif
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/services.d
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/systemCheck.d
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/vars.d
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/vendors.d
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/multiversion.d
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/needreboot.d
-mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/zypp/credentials.d
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/zypp
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/zypp/plugins
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/zypp/plugins/appdata
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/zypp/plugins/commit
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/zypp/plugins/services
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/zypp/plugins/system
-mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/zypp/plugins/urlresolver
-mkdir -p $RPM_BUILD_ROOT%{_var}/lib/zypp
-mkdir -p $RPM_BUILD_ROOT%{_var}/log/zypp
-mkdir -p $RPM_BUILD_ROOT%{_var}/cache/zypp
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/services.d
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/systemCheck.d
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/vars.d
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/vendors.d
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/multiversion.d
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/needreboot.d
+mkdir -p %{buildroot}/%{_sysconfdir}/zypp/credentials.d
+mkdir -p %{buildroot}/%{_prefix}/lib/zypp
+mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins
+mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/appdata
+mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/commit
+mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/services
+mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/system
+mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/urlresolver
+mkdir -p %{buildroot}/%{_var}/lib/zypp
+mkdir -p %{buildroot}/%{_var}/log/zypp
+mkdir -p %{buildroot}/%{_var}/cache/zypp
# Default to 'solver.dupAllowVendorChange = false' on TW and post SLE12
%if 0%{?suse_version} >= 1330 || "%{distribution}" == "openSUSE Tumbleweed"
sed -i "s|# solver.dupAllowVendorChange = true|solver.dupAllowVendorChange = false|g" %{buildroot}%{_sysconfdir}/zypp/zypp.conf
%endif
-make -C po install DESTDIR=$RPM_BUILD_ROOT
+%make_install -C po
# Create filelist with translations
cd ..
%{find_lang} zypp
%check
pushd build/tests
-LD_LIBRARY_PATH=$RPM_BUILD_ROOT%{_libdir}:${LD_LIBRARY_PATH} ctest .
+LD_LIBRARY_PATH="%{buildroot}/%{_libdir}:$LD_LIBRARY_PATH" ctest .
popd
%post
%postun -p /sbin/ldconfig
-%clean
-rm -rf "$RPM_BUILD_ROOT"
-
%files -f zypp.lang
%defattr(-,root,root)
%if 0%{?suse_version} >= 1500
-------------------------------------------------------------------
+Mon Nov 26 12:14:49 CET 2018 - ma@suse.de
+
+- str: recognize 'always' and 'never' as valid boolean strings
+- Fix needreboot code to use SolvableSpec parser (fate#326451)
+- SolvableSpec: Define a set of Solvables by ident and provides
+- version 17.10.0 (9)
+
+-------------------------------------------------------------------
Wed Nov 14 11:48:35 CET 2018 - ma@suse.de
- Provide needreboot config files in /etc/zypp (fate#326451, fixes #140)
--- /dev/null
+<channel><subchannel>
+<srcpackage>
+ <name>candidate</name>
+ <vendor>openSUSE</vendor>
+ <history><update>
+ <arch>noarch</arch>
+ <version>0</version>
+ <release>1</release>
+ </update></history>
+</srcpackage>
+<srcpackage>
+ <name>candidate</name>
+ <vendor>openSUSE</vendor>
+ <history><update>
+ <arch>noarch</arch>
+ <version>0</version>
+ <release>1</release>
+ </update></history>
+</srcpackage>
+
+<srcpackage>
+ <name>candidatenoarch</name>
+ <vendor>openSUSE</vendor>
+ <history><update>
+ <arch>noarch</arch>
+ <version>0</version>
+ <release>2</release>
+ </update></history>
+</srcpackage>
+<srcpackage>
+ <name>candidatenoarch</name>
+ <vendor>openSUSE</vendor>
+ <history><update>
+ <arch>noarch</arch>
+ <version>0</version>
+ <release>1</release>
+ </update></history>
+</srcpackage>
+<srcpackage>
+ <name>candidatenoarch</name>
+ <vendor>openSUSE</vendor>
+ <history><update>
+ <arch>noarch</arch>
+ <version>0</version>
+ <release>1</release>
+ </update></history>
+</srcpackage>
+<srcpackage>
+ <name>candidatenoarch</name>
+ <vendor>openSUSE</vendor>
+ <history><update>
+ <arch>noarch</arch>
+ <version>0</version>
+ <release>1</release>
+ </update></history>
+</srcpackage>
+</subchannel></channel>
- url : http://foo.org/distribution/LOW
-->
<channel file="RepoLOW.xml" name="RepoLOW" priority="99" />
+ <!--
+ - alias : RepoLOW
+ - url : http://foo.org/distribution/LOW
+ -->
+ <channel file="RepoSRC.xml" name="RepoSRC" priority="99" />
<locale name="en_US" />
<locale name="de" />
</setup>
Queue
Map
Solvable
+ SolvableSpec
SolvParsing
WhatObsoletes
WhatProvides
--- /dev/null
+#include <stdio.h>
+#include <iostream>
+#include <boost/test/auto_unit_test.hpp>
+
+#include "zypp/sat/SolvableSpec.h"
+#include "zypp/base/Logger.h"
+#include "TestSetup.h"
+
+#define BOOST_CHECK_MODULE SolvableSpec
+
+using std::cout;
+using std::endl;
+using std::string;
+using namespace zypp;
+using namespace boost::unit_test;
+
+
+BOOST_AUTO_TEST_CASE(parsing)
+{
+ {
+ sat::SolvableSpec specs;
+ // adds no empty values
+ specs.addIdent ( IdString() );
+ specs.addIdent ( IdString( "" ) );
+ specs.addProvides( Capability() );
+ specs.addProvides( Capability( "" ) );
+ BOOST_CHECK( ! specs.containsIdent( IdString() ) );
+ BOOST_CHECK( ! specs.containsProvides( Capability() ) );
+ BOOST_CHECK( ! specs.containsIdent( IdString( "" ) ) );
+ BOOST_CHECK( ! specs.containsProvides( Capability( "" ) ) );
+ }
+ {
+ sat::SolvableSpec specs;
+ specs.addIdent ( IdString( "idstr" ) );
+ specs.addProvides( Capability( "idcap" ) );
+ specs.addProvides( Capability( "idvcap=13" ) );
+ specs.addProvides( Capability( "idvwcap = 14" ) );
+ BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) );
+ }
+ {
+ sat::SolvableSpec specs;
+ specs.parse( "idstr" );
+ specs.parse( "provides:idcap" );
+ specs.parse( "provides:idvcap=13" );
+ specs.parse( "provides:idvwcap = 14" );
+ BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) );
+ }
+ {
+ sat::SolvableSpec specs;
+ std::stringstream str;
+ str << "# some comment" << endl;
+ str << " # maybe indented" << endl;
+ str << " \t " << endl; // white line
+ str << " idstr " << endl;
+ str << " provides:idcap " << endl;
+ str << " provides:idvcap=13 " << endl;
+ str << " provides:idvwcap = 14 " << endl;
+ str << "" << endl;
+ specs.parseFrom( str );
+ BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) );
+ }
+ {
+ sat::SolvableSpec specs;
+ specs.splitParseFrom( "idstr provides:idcap provides:idvcap=13 provides:idvwcap\\ =\\ 14 id\\ ws\\ str provides:id\\ ws\\ cap\\ =\\ 99" );
+ BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) );
+ BOOST_CHECK( specs.containsIdent ( IdString( "id ws str" ) ) );
+ BOOST_CHECK( specs.containsProvides( Capability( "", "id ws cap", "=", "99" ) ) );
+ }
+}
+
+BOOST_AUTO_TEST_CASE(eval)
+{
+ sat::SolvableSpec specs;
+ specs.parse( "candidate" );
+ BOOST_CHECK( !specs.dirty() ); // ident don't
+ specs.parse( "provides:available_only > 1-1" );
+ BOOST_CHECK( specs.dirty() ); // deps do
+
+ TestSetup test( Arch_x86_64 );
+ test.loadTestcaseRepos( TESTS_SRC_DIR "/data/TCSelectable" );
+ std::set<sat::Solvable::IdType> matches {2,3,8,9,14,15,16,17,28}; // matching Solvable IDs in TestcaseRepo (does not match srcpackage:!)
+ for ( const auto & solv : ResPool::instance() )
+ {
+ //cout << ( specs.contains( solv ) ? "* " : " " ) << solv << endl;
+ BOOST_CHECK_MESSAGE( specs.contains( solv ) == matches.count( solv.id() ), str::Str() << "Wrong: " << ( specs.contains( solv ) ? "* " : " " ) << solv );
+ }
+
+ BOOST_CHECK( !specs.dirty() ); // loop built the cache
+ specs.parse( "provides:available_only > 1-1" );
+ BOOST_CHECK( !specs.dirty() ); // already have this spec, no need to set dirty
+
+ specs.parse( "provides:available_only = 1-1" );
+ BOOST_CHECK( specs.dirty() ); // This is a new one, so got dirty
+ matches.insert( 13 );
+
+ for ( const auto & solv : ResPool::instance() )
+ {
+ BOOST_CHECK_MESSAGE( specs.contains( solv ) == matches.count( solv.id() ), str::Str() << "Wrong: " << ( specs.contains( solv ) ? "* " : " " ) << solv );
+ }
+}
--- /dev/null
+#define INCLUDE_TESTSETUP_WITHOUT_BOOST
+#include "zypp/../tests/lib/TestSetup.h"
+#undef INCLUDE_TESTSETUP_WITHOUT_BOOST
+#include "argparse.h"
+
+#include <iostream>
+#include <zypp/DiskUsageCounter.h>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+
+static std::string appname { "NO_NAME" };
+
+int errexit( const std::string & msg_r = std::string(), int exit_r = 100 )
+{
+ if ( ! msg_r.empty() )
+ cerr << endl << appname << ": ERR: " << msg_r << endl << endl;
+ return exit_r;
+}
+
+int usage( const argparse::Options & options_r, int return_r = 0 )
+{
+ cerr << "USAGE: " << appname << " [OPTION]... [ARGS]..." << endl;
+ cerr << " Print default mountpoint set for disk usage computation." << endl;
+ cerr << options_r << endl;
+ return return_r;
+}
+
+int main( int argc, char * argv[] )
+{
+ appname = Pathname::basename( argv[0] );
+
+ std::string sysRoot { "/" };
+
+ argparse::Options options;
+ options.add()
+ ( "help,h", "Print help and exit." )
+ ( "root", "Use the system located below ROOTDIR.", argparse::Option::Arg::required )
+ ;
+ auto result = options.parse( argc, argv );
+
+ if ( result.count( "help" ) )
+ return usage( options );
+
+ if ( result.count( "root" ) )
+ sysRoot = result["root"].arg();
+
+ // go...
+ cout << "DiskUsageCounter: relevant mount points detected below '" << sysRoot << "':" << endl;
+ cout << DiskUsageCounter::detectMountPoints( sysRoot ) << endl;
+
+ return 0;
+}
--- /dev/null
+#ifndef ZYPP_TOOLS_ARGPARSE_H
+#define ZYPP_TOOLS_ARGPARSE_H
+
+#include <iosfwd>
+#include <string>
+#include <exception>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+//#include <regex> seems to be bad with gcc < 4.9
+#include <zypp/base/Regex.h>
+
+///////////////////////////////////////////////////////////////////
+/// Simple arg parser for tools
+/// \code
+/// argparse::Options options;
+/// options.add()
+/// ( "help,h", "Print help and exit." )
+/// ( "root", "Use the system located below ROOTDIR.", argparse::Option::Arg::required )
+/// ;
+/// auto result = options.parse( argc, argv );
+///
+/// if ( result.count( "root" ) )
+/// sysRoot = result["root"].arg();
+/// \endcode
+namespace argparse
+{
+ using zypp::str::regex;
+ using zypp::str::smatch;
+ using zypp::str::regex_match;
+
+ ///////////////////////////////////////////////////////////////////
+ /// Exception thrown when defining Options or parsing.
+ class OptionException : public std::exception
+ {
+ public:
+ OptionException( std::string msg_r )
+ : _msg { std::move(msg_r) }
+ {}
+
+ OptionException( std::string msg_r, const std::string & msg2_r )
+ : _msg { std::move(msg_r) }
+ { if ( ! msg2_r.empty() ) _msg += msg2_r; }
+
+ const char* what() const noexcept override
+ { return _msg.c_str(); }
+
+ private:
+ std::string _msg;
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ /// Option description (TBD define arg consumer)
+ class Option
+ {
+ public:
+ enum class Arg { none, required, optional };
+
+ public:
+ Option( std::string descr_r, Arg hasarg_r )
+ : _descr { std::move(descr_r) }
+ , _hasarg { hasarg_r }
+ {
+ if ( hasarg_r == Arg::optional )
+ throw OptionException( "Not yet implemented: Option::Arg::optional" );
+ }
+
+ const std::string & descr() const
+ { return _descr; }
+
+ Arg hasarg() const
+ { return _hasarg; }
+
+ private:
+ std::string _descr;
+ Arg _hasarg;
+ };
+
+
+ class ParsedOptions;
+
+ ///////////////////////////////////////////////////////////////////
+ /// Map of option names -> option descriptions.
+ class Options
+ {
+ typedef std::unordered_map<std::string, std::shared_ptr<const Option>> OptionMap;
+ public:
+ Options()
+ {}
+
+ public:
+ class Injector
+ {
+ public:
+ Injector( OptionMap & optmap_r )
+ : _optmap { optmap_r }
+ {}
+
+ Injector & operator()( const std::string & names_r, std::string descr_r, Option::Arg hasarg_r = Option::Arg::none )
+ {
+ smatch result;
+ if ( regex_match( names_r, result, regex("([[:alnum:]][-_[:alnum:]]+)(,([[:alnum:]]))?") ) )
+ {
+ auto opt = std::make_shared<const Option>( std::move(descr_r), hasarg_r );
+ add( result[1], opt );
+ if ( ! result[3].empty() )
+ add( result[3], opt );
+ }
+ else
+ throw OptionException( "Illegal option names: ", names_r );
+
+ return *this;
+ }
+
+ private:
+ void add( std::string name_r, std::shared_ptr<const Option> opt_r )
+ {
+ if ( _optmap.count( name_r ) )
+ throw OptionException( "Duplicate option name: ", name_r );
+ _optmap[name_r] = opt_r;
+ }
+
+ private:
+ OptionMap & _optmap;
+ };
+
+ Injector add()
+ { return Injector( _optmap ); }
+
+ public:
+ ParsedOptions parse( int argc, char * argv[] ) const;
+
+ public:
+ std::ostream & dumpOn( std::ostream & str_r ) const
+ {
+ str_r << "OPTIONS:";
+ if ( ! _optmap.empty() )
+ {
+ std::unordered_map<std::shared_ptr<const Option>, std::string> unify;
+ for ( const auto & p : _optmap )
+ {
+ std::string & t { unify[p.second] };
+ if ( t.empty() )
+ t = (p.first.length()>1?"--":"-")+p.first;
+ else if ( p.first.length() > 1 )
+ t = "--"+p.first+", "+t;
+ else
+ t = t+", -"+p.first;
+ }
+
+ boost::format fmt( "\n %1% %|30t|%2%" );
+ for ( const auto & p : unify )
+ {
+ fmt % p.second % p.first->descr();
+ str_r << fmt.str();
+ }
+ }
+ else
+ {
+ str_r << " This command accepts no options.";
+ }
+ return str_r;
+ }
+
+ private:
+ OptionMap _optmap;
+ };
+
+ inline std::ostream & operator<<( std::ostream & str_r, const Options & obj_r )
+ { return obj_r.dumpOn( str_r ); }
+
+ ///////////////////////////////////////////////////////////////////
+ /// Parsed option incl. option args value (by now just stores the string)
+ class OptionValue
+ {
+ public:
+ OptionValue( std::shared_ptr<const Option> opt_r )
+ : _opt { opt_r }
+ {}
+
+ OptionValue( std::shared_ptr<const Option> opt_r, std::string arg_r )
+ : _opt { opt_r }
+ , _arg { std::make_shared<std::string>( std::move(arg_r) ) }
+ {}
+
+ const std::string & arg() const
+ {
+ if ( ! _arg )
+ throw std::domain_error( "No arg value" );
+
+ return *_arg;
+ }
+
+ private:
+ std::shared_ptr<const Option> _opt;
+ std::shared_ptr<std::string> _arg;
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ /// Parsed options and positional args
+ class ParsedOptions
+ {
+ typedef std::unordered_map<std::string, std::shared_ptr<const Option>> OptionMap;
+ typedef std::unordered_map<std::shared_ptr<const Option>, OptionValue> ResultMap;
+ public:
+ ParsedOptions( const OptionMap & optmap_r, int argc, char * argv[] )
+ : _optmap { optmap_r }
+ { parse( argc, argv ); }
+
+ public:
+ size_t count( const std::string & optname_r ) const
+ {
+ auto iter = _optmap.find( optname_r );
+ if ( iter == _optmap.end() )
+ return 0;
+
+ auto resiter = _options.find( iter->second );
+ return( resiter == _options.end() ? 0 : 1 );
+ }
+
+ const OptionValue & operator[]( const std::string & optname_r ) const
+ {
+ return requireOptValByName( optname_r );
+ }
+
+ const std::vector<std::string> & positionals() const
+ { return _positionals; }
+
+ private:
+ void parse( int argc, char * argv[] )
+ {
+ bool collectpositional = false;
+ for ( --argc,++argv; argc; --argc,++argv )
+ {
+ if ( (*argv)[0] == '-' && !collectpositional )
+ {
+ if ( (*argv)[1] == '-' )
+ {
+ if ( (*argv)[2] == '\0' )
+ {
+ // -- rest are positional...
+ collectpositional = true;
+ }
+ else
+ {
+ // --longopt
+ parseoptl( (*argv)+2, argc, argv );
+ }
+ }
+ else
+ {
+ // -s(hortopt)
+ parseopts( (*argv)+1, argc, argv );
+ }
+ }
+ else
+ {
+ // positional
+ _positionals.push_back( *argv );
+ }
+ }
+ }
+
+ private:
+ std::string dashed( std::string name_r ) const
+ { return name_r.insert( 0, name_r.size()>1?"--":"-" ); }
+
+ void parseoptl( const std::string & name_r, int & argc, char **& argv )
+ {
+ if ( name_r.length() < 2 )
+ throw OptionException( "Illegal long opt: --", name_r );
+
+ parseopt( name_r, argc, argv );
+ }
+
+ void parseopts( const std::string & name_r, int & argc, char **& argv )
+ {
+ if ( name_r.length() != 1 )
+ throw OptionException( "Illegal short opt: -", name_r );
+
+ parseopt( name_r, argc, argv );
+ }
+
+ void parseopt( const std::string & name_r, int & argc, char **& argv )
+ {
+ auto opt = requireOptByName( name_r );
+
+ auto iter = _options.find( opt );
+ if ( iter != _options.end() )
+ throw OptionException( "Multiple occurrences of option: ", dashed( name_r ) );
+
+ if ( opt->hasarg() != Option::Arg::none )
+ {
+ if ( opt->hasarg() == Option::Arg::optional )
+ throw OptionException( "Not yet implemented: Option::Arg::optional" ); // i.e. '--opt=arg'
+
+ if ( argc < 2 )
+ throw OptionException( "Missing argument for option: ", dashed( name_r ) );
+
+ --argc,++argv;
+ moveToResult( opt, OptionValue( opt, *argv ) );
+ }
+ else
+ moveToResult( opt, OptionValue( opt ) );
+ }
+
+ void moveToResult( std::shared_ptr<const Option> opt_r, OptionValue && value_r )
+ { _options.insert( std::make_pair( opt_r, std::move(value_r) ) ); }
+
+ std::shared_ptr<const Option> requireOptByName( const std::string & name_r ) const
+ {
+ auto iter = _optmap.find( name_r );
+ if ( iter == _optmap.end() )
+ throw OptionException( "Unknown option: ", dashed( name_r ) );
+ return iter->second;
+ }
+
+ const OptionValue & requireOptValByName( const std::string & name_r ) const
+ {
+ auto iter = _options.find( requireOptByName( name_r ) );
+ if ( iter == _options.end() )
+ throw OptionException( "Option not present: ", dashed( name_r ) );
+ return iter->second;
+ }
+
+ private:
+ const OptionMap & _optmap;
+ ResultMap _options;
+ std::vector<std::string> _positionals;
+ };
+
+ inline ParsedOptions Options::parse( int argc, char * argv[] ) const
+ { return ParsedOptions( _optmap, argc, argv ); }
+
+
+
+} // namespace argparse
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_TOOLS_ARGPARSE_H
sat/Pool.cc
sat/Solvable.cc
sat/SolvableSet.cc
+ sat/SolvableSpec.cc
sat/SolvIterMixin.cc
sat/Map.cc
sat/Queue.cc
sat/Solvable.h
sat/SolvableSet.h
sat/SolvableType.h
+ sat/SolvableSpec.h
sat/SolvIterMixin.h
sat/Map.h
sat/Queue.h
return( t == "1"
|| t == "yes"
|| t == "true"
+ || t == "always"
|| t == "on"
|| t == "+"
|| strtonum<long long>( str )
return ! ( t == "0"
|| t == "no"
|| t == "false"
+ || t == "never"
|| t == "off"
|| t == "-"
);
/** Parsing boolean from string.
*/
//@{
- /** Return \c true if str is <tt>1, true, yes, on</tt> (or a nonzero number). */
+ /** Return \c true if str is <tt>1, true, yes, on, always</tt> (or a nonzero number). */
bool strToTrue( const C_Str & str );
- /** Return \c false if str is <tt>0, false, no, off</tt>. */
+ /** Return \c false if str is <tt>0, false, no, off, never</tt>. */
bool strToFalse( const C_Str & str );
/** Parse \c str into a bool depending on the default value.
Queue Pool::autoInstalled() const { return myPool().autoInstalled(); }
void Pool::setAutoInstalled( const Queue & autoInstalled_r ){ myPool().setAutoInstalled( autoInstalled_r ); }
- Queue Pool::rebootNeededIdents() const { return myPool().rebootNeededIdents(); }
- void Pool::setRebootNeededIdents( const Queue & rebootNeeded_r ){ myPool().setRebootNeededIdents( rebootNeeded_r ); }
+ void Pool::setNeedrebootSpec( sat::SolvableSpec needrebootSpec_r ) { myPool().setNeedrebootSpec( std::move(needrebootSpec_r) ); }
/******************************************************************
**
namespace sat
{ /////////////////////////////////////////////////////////////////
+ class SolvableSpec;
+
///////////////////////////////////////////////////////////////////
//
// CLASS NAME : Pool
void setAutoInstalled( const Queue & autoInstalled_r );
//@}
- /** Get ident list of all solvables that trigger the "reboot needed" flag. */
- Queue rebootNeededIdents() const;
-
- /** Set ident list of all solvables that trigger the "reboot needed" flag. */
- void setRebootNeededIdents( const Queue & rebootNeeded_r );
+ public:
+ /** \name Needreboot */
+ //@{
+ /** Solvables which should trigger the reboot-needed hint if installed/updated. */
+ void setNeedrebootSpec( sat::SolvableSpec needrebootSpec_r );
+ //@}
public:
/** Expert backdoor. */
return myPool().isOnSystemByAuto( ident_r );
}
- bool Solvable::identTriggersRebootNeededHint ( const IdString &ident_r )
+ bool Solvable::isNeedreboot() const
{
- return myPool().triggersRebootNeededHint( ident_r );
+ NO_SOLVABLE_RETURN( false );
+ return myPool().isNeedreboot( *this );
}
bool Solvable::multiversionInstall() const
/** \overload static version */
static bool identIsAutoInstalled( const IdString & ident_r );
- /** Whether installing or upgrading a solvable with the same \ref ident will trigger the reboot needed hint. */
- bool identTriggersRebootNeededHint() const
- { return identTriggersRebootNeededHint( ident() ); }
- static bool identTriggersRebootNeededHint ( const IdString &ident_r );
+ /** Whether this solvable triggers the reboot-needed hint if installed/updated. */
+ bool isNeedreboot() const;
/** Whether different versions of this package can be installed at the same time.
* Per default \c false. \see also \ref ZConfig::multiversion.
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/sat/SolvableSpec.cc
+ */
+#include <iostream>
+
+#include "zypp/base/LogTools.h"
+#include "zypp/base/IOStream.h"
+
+#include "zypp/sat/SolvableSpec.h"
+#include "zypp/sat/WhatProvides.h"
+
+using std::endl;
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{
+ ///////////////////////////////////////////////////////////////////
+ namespace sat
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// \class SolvableSpec::Impl
+ /// \brief SolvableSpec implementation.
+ ///////////////////////////////////////////////////////////////////
+ class SolvableSpec::Impl
+ {
+ public:
+ void addIdent( IdString ident_r )
+ {
+ if ( ! ident_r.empty() )
+ _idents.insert( ident_r );
+ }
+
+ void addProvides( Capability provides_r )
+ {
+ if ( ! provides_r.empty() && _provides.insert( provides_r ).second )
+ setDirty();
+ }
+
+
+ void parse( const C_Str & spec_r )
+ {
+ if ( str::hasPrefix( spec_r, "provides:" ) )
+ addProvides( Capability(spec_r.c_str()+9) );
+ else
+ addIdent( IdString(spec_r) );
+ }
+
+
+ bool needed() const
+ { return !_provides.empty(); }
+
+ bool dirty() const
+ { return needed() && !_cache; }
+
+ void setDirty() const
+ { _cache.reset(); }
+
+ const WhatProvides & cache() const
+ {
+ if ( !_cache )
+ {
+ _cache.reset( new WhatProvides( _provides ) );
+ }
+ return *_cache;
+ }
+
+ bool contains( const sat::Solvable & solv_r ) const
+ { return( _idents.count( solv_r.ident() ) || ( needed() && cache().contains( solv_r ) ) ); }
+
+
+ const IdStringSet & idents() const
+ { return _idents; }
+
+ const CapabilitySet & provides() const
+ { return _provides; }
+
+ private:
+ IdStringSet _idents;
+ CapabilitySet _provides;
+
+ mutable shared_ptr<WhatProvides> _cache;
+
+ private:
+ friend Impl * rwcowClone<Impl>( const Impl * rhs );
+ /** clone for RWCOW_pointer */
+ Impl * clone() const
+ { return new Impl( *this ); }
+ };
+
+ /** \relates SolvableSpec::Impl Stream output */
+ inline std::ostream & operator<<( std::ostream & str, const SolvableSpec::Impl & obj )
+ {
+ str << "SolvableSpec {" << endl
+ << " Idents " << obj.idents() << endl
+ << " Provides " << obj.provides() << endl
+ << "}";
+ return str;
+ }
+
+ ///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : SolvableSpec
+ //
+ ///////////////////////////////////////////////////////////////////
+
+ SolvableSpec::SolvableSpec()
+ : _pimpl( new Impl )
+ {}
+
+ SolvableSpec::~SolvableSpec()
+ {}
+
+ void SolvableSpec::addIdent( IdString ident_r )
+ { _pimpl->addIdent( ident_r ); }
+
+ void SolvableSpec::addProvides( Capability provides_r )
+ { _pimpl->addProvides( provides_r ); }
+
+ void SolvableSpec::parse( const C_Str & spec_r )
+ { _pimpl->parse( spec_r ); }
+
+ void SolvableSpec::parseFrom( const InputStream & istr_r )
+ {
+ iostr::simpleParseFile( istr_r,
+ [this]( int num_r, const std::string & line_r )->bool
+ {
+ this->parse( line_r );
+ return true;
+ });
+ }
+
+ void SolvableSpec::splitParseFrom( const C_Str & multispec_r )
+ {
+ std::vector<std::string> v;
+ str::splitEscaped( multispec_r, std::back_inserter( v ), ", \t" );
+ parseFrom( v.begin(), v.end() );
+ }
+
+ bool SolvableSpec::contains( const sat::Solvable & solv_r ) const
+ { return _pimpl->contains( solv_r ) && !solv_r.isKind( ResKind::srcpackage ); }
+
+ bool SolvableSpec::dirty() const
+ { return _pimpl->dirty(); }
+
+ void SolvableSpec::setDirty() const
+ { _pimpl->setDirty(); }
+
+ bool SolvableSpec::containsIdent( const IdString & ident_r ) const
+ { return _pimpl->idents().count( ident_r ); }
+
+ bool SolvableSpec::containsProvides( const Capability & provides_r ) const
+ { return _pimpl->provides().count( provides_r ); }
+
+ std::ostream & operator<<( std::ostream & str, const SolvableSpec & obj )
+ { return str << *obj._pimpl; }
+
+ } // namespace sat
+ ///////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
--- /dev/null
+/*---------------------------------------------------------------------\
+| ____ _ __ __ ___ |
+| |__ / \ / / . \ . \ |
+| / / \ V /| _/ _/ |
+| / /__ | | | | | | |
+| /_____||_| |_| |_| |
+| |
+\---------------------------------------------------------------------*/
+/** \file zypp/sat/SolvableSpec.h
+ */
+#ifndef ZYPP_SAT_SOLVABLESPEC_H
+#define ZYPP_SAT_SOLVABLESPEC_H
+
+#include <iosfwd>
+
+#include "zypp/APIConfig.h"
+#include "zypp/base/PtrTypes.h"
+#include "zypp/base/InputStream.h"
+#include "zypp/base/String.h"
+
+#include "zypp/sat/SolvableType.h"
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{
+ ///////////////////////////////////////////////////////////////////
+ namespace sat
+ {
+ ///////////////////////////////////////////////////////////////////
+ /// \class SolvableSpec
+ /// \brief Define a set of \ref Solvables by ident and provides.
+ ///
+ /// Able to keep the definition of solvable sets like in 'needreboot'
+ /// or 'multiversion'. The associated file parser allows reading
+ /// stored definitions (one `IDENT` or provides:CAPABILITY` per line;
+ /// empty lines and lines starting with '#' are ignored).
+ ///
+ /// The use of provides requires re-computation of the solvable set,
+ /// whenever the solvable pool changes. This computation via \ref WhatProvides
+ /// is expensive, that's why a built in cache is also offered.
+ ///
+ /// \note \ref contains does not match srcpackage: per default.
+ ///////////////////////////////////////////////////////////////////
+ class SolvableSpec
+ {
+ public:
+ /** Default ctor */
+ SolvableSpec();
+
+ /** Dtor */
+ ~SolvableSpec();
+
+ public:
+ /** Add all \ref sat::Solvable with this \a ident_r */
+ void addIdent( IdString ident_r );
+
+ /** A all \ref sat::Solvable matching this \a provides_r. */
+ void addProvides( Capability provides_r );
+
+ public:
+ /** Parse and add spec from a string (`IDENT` or provides:CAPABILITY`). */
+ void parse( const C_Str & spec_r );
+
+ /** Parse file \a istr_r and add it's specs (one per line, #-comments). */
+ void parseFrom( const InputStream & istr_r );
+
+ /** Parse and add specs from iterator range. */
+ template <class TIterator>
+ void parseFrom( TIterator begin, TIterator end )
+ { for_( it, begin, end ) parse( *it ); }
+
+ /** Convenience using \ref str::splitEscaped(", \t") to parse multiple specs from one line. */
+ void splitParseFrom( const C_Str & multispec_r );
+
+ public:
+ /** Test whether \a solv_r matches the spec.
+ * (Re-)builds the \ref WhatProvides cache on demand.
+ *
+ * \note Does not match srcpackage: per default.
+ */
+ bool contains( const sat::Solvable & solv_r ) const;
+ /** \overload */
+ template <class Derived>
+ bool contains( const SolvableType<Derived> & solv_r ) const
+ { return contains( solv_r.satSolvable() ); }
+
+ /** Whether the cache is needed and dirty. */
+ bool dirty() const;
+
+ /** Explicitly flag the cache as dirty, so it will be rebuilt on the next request.
+ * To be called if the \ref ResPool content has changed. Intentionally `const` as
+ * this does not change the set of spects (though the set of matches might change).
+ * \note This has no effect if no cache is needed (i.e. no provides: are used).
+ */
+ void setDirty() const;
+
+ public:
+ /** Whether \a ident_r has been added to the specs (mainly for parser tests). */
+ bool containsIdent( const IdString & ident_r ) const;
+
+ /** Whether \a provides_r has been added to the sepcs (mainly for parser tests).*/
+ bool containsProvides( const Capability & provides_r ) const;
+
+ public:
+ class Impl; ///< Implementation class.
+ private:
+ RWCOW_pointer<Impl> _pimpl; ///< Pointer to implementation.
+ friend std::ostream & operator<<( std::ostream & str, const SolvableSpec & obj );
+ };
+
+ /** \relates SolvableSpec Stream output */
+ std::ostream & operator<<( std::ostream & str, const SolvableSpec & obj );
+
+ } // namespace sat
+ ///////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_SAT_SOLVABLESPEC_H
bool onSystemByAuto() const { return satSolvable().onSystemByAuto(); }
bool identIsAutoInstalled() const { return satSolvable().identIsAutoInstalled(); }
bool multiversionInstall() const { return satSolvable().multiversionInstall(); }
- bool identTriggersRebootNeededHint() const { return satSolvable().identTriggersRebootNeededHint(); }
+ bool isNeedreboot() const { return satSolvable().isNeedreboot(); }
Date buildtime() const { return satSolvable().buildtime(); }
Date installtime() const { return satSolvable().installtime(); }
_serial.setDirty(); // pool content change
_availableLocalesPtr.reset(); // available locales may change
_multiversionListPtr.reset(); // re-evaluate ZConfig::multiversionSpec.
+ _needrebootSpec.setDirty(); // re-evaluate needrebootSpec
depSetDirty(); // invaldate dependency/namespace related indices
}
#include "zypp/base/SerialNumber.h"
#include "zypp/base/SetTracker.h"
#include "zypp/sat/detail/PoolMember.h"
+#include "zypp/sat/SolvableSpec.h"
#include "zypp/sat/Queue.h"
#include "zypp/RepoInfo.h"
#include "zypp/Locale.h"
bool isOnSystemByAuto( IdString ident_r ) const
{ return _autoinstalled.contains( ident_r.id() ); }
+ //@}
- /** Get ident list of all solvables that trigger the "reboot needed" flag. */
- StringQueue rebootNeededIdents() const
- { return _rebootNeeded; }
-
- /** Set ident list of all solvables that trigger the "reboot needed" flag. */
- void setRebootNeededIdents( const StringQueue & rebootNeeded_r )
- { _rebootNeeded = rebootNeeded_r; }
-
- bool triggersRebootNeededHint( IdString ident_r ) const
- { return _rebootNeeded.contains( ident_r.id() ); }
+ public:
+ /** \name Solvables which should trigger the reboot-needed hint if installed/updated. */
+ //@{
+ /** Set new Solvable specs.*/
+ void setNeedrebootSpec( sat::SolvableSpec needrebootSpec_r )
+ {
+ _needrebootSpec = std::move(needrebootSpec_r);
+ _needrebootSpec.setDirty();
+ }
+ /** Whether \a solv_r matches the spec.*/
+ bool isNeedreboot( const Solvable & solv_r ) const
+ { return _needrebootSpec.contains( solv_r ); }
//@}
public:
/** */
sat::StringQueue _autoinstalled;
- /** database of all identifiers that will trigger the "reboot needed" flag */
- sat::StringQueue _rebootNeeded;
+ /** Solvables which should trigger the reboot-needed hint if installed/updated. */
+ sat::SolvableSpec _needrebootSpec;
/** filesystems mentioned in /etc/sysconfig/storage */
mutable scoped_ptr<std::set<std::string> > _requiredFilesystemsPtr;
#ifndef ZYPP_SAT_DETAIL_POOLMEMBER_H
#define ZYPP_SAT_DETAIL_POOLMEMBER_H
-#include <solv/solvversion.h>
-
#include "zypp/base/Hash.h"
#include "zypp/base/Iterator.h"
#include "zypp/base/String.h"
extern "C"
{
- // Those _Type names are exposed as sat::detail::CType below!
-#if ( LIBSOLV_VERSION >= 700 )
+ // Those s_Type names are exposed as sat::detail::CType below!
struct s_Dataiterator;
struct s_Datamatcher;
struct s_Map;
struct s_Solvable;
struct s_Solver;
struct s_Transaction;
-#else
- struct _Dataiterator;
- struct _Datamatcher;
- struct _Map;
- struct _Pool;
- struct _Queue;
- struct _Repo;
- struct _Solvable;
- struct _Solver;
- struct _Transaction;
-#endif
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
namespace detail
{
-#if ( LIBSOLV_VERSION >= 700 )
typedef ::s_Dataiterator CDataiterator; ///< Wrapped libsolv C data type exposed as backdoor
typedef ::s_Datamatcher CDatamatcher; ///< Wrapped libsolv C data type exposed as backdoor
typedef ::s_Map CMap; ///< Wrapped libsolv C data type exposed as backdoor
typedef ::s_Solvable CSolvable; ///< Wrapped libsolv C data type exposed as backdoor
typedef ::s_Solver CSolver; ///< Wrapped libsolv C data type exposed as backdoor
typedef ::s_Transaction CTransaction; ///< Wrapped libsolv C data type exposed as backdoor
-#else
- typedef ::_Dataiterator CDataiterator; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Datamatcher CDatamatcher; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Map CMap; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Pool CPool; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Queue CQueue; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Repo CRepo; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Solvable CSolvable; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Solver CSolver; ///< Wrapped libsolv C data type exposed as backdoor
- typedef ::_Transaction CTransaction; ///< Wrapped libsolv C data type exposed as backdoor
-#endif
} // namespace detail
///////////////////////////////////////////////////////////////////
#include "zypp/sat/Pool.h"
#include "zypp/sat/detail/PoolImpl.h"
+#include "zypp/sat/SolvableSpec.h"
#include "zypp/sat/Transaction.h"
#include "zypp/PluginExecutor.h"
satpool.setAutoInstalled( q );
}
- //load the packages that will trigger the update flag being set
+ // Load the needreboot package specs
{
- sat::StringQueue q;
- filesystem::Pathname needRebootFile { Pathname::assertprefix( root(), ZConfig::instance().needrebootFile() ) };
- if ( filesystem::PathInfo ( needRebootFile ).isExist() ) {
- SolvIdentFile file ( needRebootFile );
- for ( const auto & idstr : file.data() ) {
- q.push( idstr.id() );
- }
-#if 1
-#warning Hotfix: temp workaround missing SolvableSpec Parser
- // Also consider excluding .rpmnew/.rpmsave/.rpmorig files in needreboot.d
- q.push( IdString("kernel-azure").id() );
- q.push( IdString("kernel-azure-base").id() );
- q.push( IdString("kernel-debug").id() );
- q.push( IdString("kernel-debug-base").id() );
- q.push( IdString("kernel-default").id() );
- q.push( IdString("kernel-default-base").id() );
- q.push( IdString("kernel-kvmsmall").id() );
- q.push( IdString("kernel-kvmsmall-base").id() );
- q.push( IdString("kernel-rt").id() );
- q.push( IdString("kernel-rt-base").id() );
- q.push( IdString("kernel-rt_debug").id() );
- q.push( IdString("kernel-rt_debug-base").id() );
- q.push( IdString("kernel-vanilla").id() );
- q.push( IdString("kernel-vanilla-base").id() );
-#endif
- }
-
- filesystem::Pathname needRebootDir { Pathname::assertprefix( root(), ZConfig::instance().needrebootPath() ) };
- if ( filesystem::PathInfo ( needRebootDir ).isExist() ) {
- filesystem::DirContent ls;
- filesystem::readdir( ls, needRebootDir, false );
+ sat::SolvableSpec needrebootSpec;
- for ( const filesystem::DirEntry &entry : ls ) {
-
- if ( entry.type != filesystem::FT_FILE )
- continue;
+ Pathname needrebootFile { Pathname::assertprefix( root(), ZConfig::instance().needrebootFile() ) };
+ if ( PathInfo( needrebootFile ).isFile() )
+ needrebootSpec.parseFrom( needrebootFile );
- SolvIdentFile file ( needRebootDir / entry.name );
- for ( const auto & idstr : file.data() ) {
- q.push( idstr.id() );
- }
- }
- }
+ Pathname needrebootDir { Pathname::assertprefix( root(), ZConfig::instance().needrebootPath() ) };
+ if ( PathInfo( needrebootDir ).isDir() )
+ {
+ static const StrMatcher isRpmConfigBackup( "\\.rpm(new|save|orig)$", Match::REGEX );
+
+ filesystem::dirForEach( needrebootDir, filesystem::matchNoDots(),
+ [&]( const Pathname & dir_r, const char *const str_r )->bool
+ {
+ if ( ! isRpmConfigBackup( str_r ) )
+ {
+ Pathname needrebootFile { needrebootDir / str_r };
+ if ( PathInfo( needrebootFile ).isFile() )
+ needrebootSpec.parseFrom( needrebootFile );
+ }
+ return true;
+ });
+ }
- satpool.setRebootNeededIdents( q );
+ INT << "Needreboot " << needrebootSpec << endl;
+ satpool.setNeedrebootSpec( std::move(needrebootSpec) );
}
if ( ZConfig::instance().apply_locks_file() )
}
else
{
- if ( citem.identTriggersRebootNeededHint() ) {
+ if ( citem.isNeedreboot() ) {
auto rebootNeededFile = root() / "/var/run/reboot-needed";
if ( filesystem::assert_file( rebootNeededFile ) == EEXIST)
filesystem::touch( rebootNeededFile );