Imported Upstream version 17.10.3 upstream/17.10.3
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:18:53 +0000 (16:18 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:18:53 +0000 (16:18 +0900)
VERSION.cmake
package/libzypp.changes
tests/zypp/PoolQuery_test.cc
zypp/PoolQuery.cc

index fb94ca5..c229567 100644 (file)
@@ -61,8 +61,8 @@
 SET(LIBZYPP_MAJOR "17")
 SET(LIBZYPP_COMPATMINOR "9")
 SET(LIBZYPP_MINOR "10")
-SET(LIBZYPP_PATCH "2")
+SET(LIBZYPP_PATCH "3")
 #
-# LAST RELEASED: 17.10.2 (9)
+# LAST RELEASED: 17.10.3 (9)
 # (The number in parenthesis is LIBZYPP_COMPATMINOR)
 #=======
index 24831b1..08af145 100644 (file)
@@ -1,4 +1,10 @@
 -------------------------------------------------------------------
+Tue Dec 18 14:01:19 CET 2018 - ma@suse.de
+
+- Simplify complex locks so zypper can display them (bsc#1112911)
+- version 17.10.3 (9)
+
+-------------------------------------------------------------------
 Mon Dec 10 16:57:34 CET 2018 - ma@suse.de
 
 - commit: set `SYSTEMD_OFFLINE=1` during chrooted commits (bsc#1118758)
index 94f53ef..b814e8d 100644 (file)
@@ -870,4 +870,116 @@ BOOST_AUTO_TEST_CASE(addDependency)
   }
 }
 
+namespace
+{
+  std::string q2str( const PoolQuery & q_r )
+  {
+    str::Str s;
+    q_r.serialize( s.stream() );
+    return s;
+  }
+
+  template <class OutputIterator>
+  void str2q( const std::string & s_r, OutputIterator out_r )
+  {
+    std::istringstream s( s_r );
+    do {
+      PoolQuery q;
+      if ( q.recover( s ) )
+       *out_r++ = std::move(q);
+      else
+       break;
+    } while ( true );
+  }
+
+  typedef std::set<PoolQuery> Pqs;
+
+  PoolQuery str2q( const std::string & s_r )
+  {
+    Pqs ret;
+    str2q( s_r, std::insert_iterator<Pqs>( ret, ret.end() ) );
+    return *ret.begin();
+  }
+
+
+  std::string serialized( const std::string & arg_r )
+  { return "\n" + arg_r + "\n\n"; }
+
+  template <typename... Args>
+  std::string serialized( const std::string & arg_r, Args... args_r )
+  { return "\n" + arg_r + serialized( args_r... ); }
+
+
+  void testSerializeAndBack( const PoolQuery & q_r, const PoolQuery & expect_r, bool equal_r = true )
+  {
+    static unsigned i = 0;
+
+    std::string s { q2str( q_r ) };
+    PoolQuery   q { str2q( s ) };
+    BOOST_CHECK_EQUAL( (q == expect_r), equal_r );
+
+    if ( ++i && (q == expect_r) != equal_r )
+    {
+      cout << "+++" << endl;
+      cout << q << endl;
+      cout << "=== " << i << " ^v SerializeAndBack == " << equal_r << endl;
+      cout << expect_r << endl;
+      cout << "---" << endl;
+    }
+  }
+}
+
+BOOST_AUTO_TEST_CASE(zypperLocksSerialize)
+{
+  // Fix/cleanup zypper locks (old style, new stule, complex) (bsc#1112911)
+  // As you may notice: locks (by now) ignore any arch component
+  cout << "****zypperLocksSerialize****"  << endl;
+  std::string n { "n*" };
+  Rel         o { Rel::EQ };
+  Edition     e { "v", "r", 1 };
+  Arch        a { "a" };
+
+  {
+    // old style
+    // solvable_name: n*
+    PoolQuery oldq;
+    oldq.addAttribute( sat::SolvAttr::name, n );
+    testSerializeAndBack( oldq, oldq );
+
+    { // new style
+      PoolQuery q;
+      q.addDependency( sat::SolvAttr::name, n, Rel::ANY, Edition(), Arch_empty );
+      testSerializeAndBack( q, oldq );
+    }
 
+    { // new style + arch rule however stays complex
+      PoolQuery q;
+      q.addDependency( sat::SolvAttr::name, n, Rel::ANY, Edition(), a );
+      testSerializeAndBack( q, oldq, false );
+      testSerializeAndBack( q, q );
+    }
+  }
+
+  {
+    // old style
+    // solvable_name: n*
+    // version: == 1:v-r
+    PoolQuery oldq;
+    oldq.addAttribute( sat::SolvAttr::name, n );
+    oldq.setEdition( e, o );
+    testSerializeAndBack( oldq, oldq );
+
+    { // new style
+      PoolQuery q;
+      q.addDependency( sat::SolvAttr::name, n, o, e, Arch_empty );
+      testSerializeAndBack( q, oldq );
+    }
+
+    { // new style + arch rule however stays complex
+      PoolQuery q;
+      q.addDependency( sat::SolvAttr::name, n, o, e, a );
+      testSerializeAndBack( q, oldq, false );
+      testSerializeAndBack( q, q );
+    }
+  }
+}
index 0ebb9fc..ca234b6 100644 (file)
@@ -1302,6 +1302,70 @@ namespace zypp
 
     } while ( true );
 
+    // OLD STYLE VERSIONED LOCKS:
+    // solvable_name: kernel
+    // version: > 1
+    //
+    // NEW STYLE VERSIONED LOCKS:
+    // complex: AttrMatchData solvable:name kernel C SolvableRange\ >\ 1\ \"\"
+    //   or
+    // solvable_name: kernel > 1
+    //
+    // Semantically equivalent as locks, but due to the different syntax
+    // the complex lock is wrongly handled by zypper.
+    //
+    // bsc#1112911: Unfortunately all styles are found in real-life locks-files.
+    // libzypp will try to make sure, when parsing the locks-file, that complex
+    // locks are rewritten into to OLD STYLE queries zypper can handle.
+    if ( !_pimpl->_attrs.count(SolvAttr::name) && _pimpl->_uncompiledPredicated.size() == 1 )
+    {
+      // No OLD STYLE lock for SolvAttr::name and exactly one complex lock...
+      const AttrMatchData & attrmatch {  *_pimpl->_uncompiledPredicated.begin() };
+      if ( attrmatch.attr == SolvAttr::name && attrmatch.strMatcher.flags().mode() == Match::OTHER )
+      {
+       // ...for SolvAttr::name and following the global search flags.
+       // A candidate for a rewrite?
+
+       std::vector<std::string> words;
+       str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) );
+       if ( words.size() < 4 || words[3].empty() )
+       {
+         // We have _NO_ arch rule in the complex predicate, so we can simplify it.
+         //
+         // NOTE: AFAIK it's not possible to create (or have created) a complex lock
+         // with arch rule with zypper means. Nevertheless, in case such a rule made it
+         // into a locks file, it's better to have a strange looking 'zypper locks' list
+         // than to lock the wrong packages.
+         // (and remember that you can't use "addAttribute( SolvAttr::arch, ... )" because
+         // attributes are `OR`ed)
+
+         // kind
+         if ( attrmatch.kindPredicate )
+         {
+           _pimpl->_kinds.clear();     // an explicit kind overwrites any global one
+           addKind( attrmatch.kindPredicate );
+         }
+
+         // name
+         addAttribute( SolvAttr::name, attrmatch.strMatcher.searchstring() );
+
+         // edition
+         std::vector<std::string> words;
+         str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) );
+         if ( ! words.empty() )
+         {
+           if ( words[0] == "EditionRange" || words[0] == "SolvableRange" )
+           {
+             setEdition( Edition(words[2]), Rel(words[1]) );
+           }
+         }
+
+         // finally remove the complex lock
+         _pimpl->_uncompiledPredicated.clear();
+       }
+      }
+    }
+
     return finded_something;
   }