Add Capability::guessPackageSpec parser also supporting "name-ver-rel.arch" formats.
authorMichael Andres <ma@suse.de>
Wed, 9 Sep 2009 13:23:08 +0000 (15:23 +0200)
committerMichael Andres <ma@suse.de>
Wed, 9 Sep 2009 13:23:08 +0000 (15:23 +0200)
tests/zypp/Capabilities_test.cc
zypp/Capability.cc
zypp/Capability.h

index 9f51606..989f4fe 100644 (file)
@@ -9,6 +9,7 @@
 #include <boost/test/floating_point_comparison.hpp>
 #include <boost/test/auto_unit_test.hpp>
 
+#include "TestSetup.h"
 #include "zypp/Arch.h"
 #include "zypp/Capability.h"
 #include "zypp/Capabilities.h"
@@ -20,6 +21,8 @@ using boost::test_tools::close_at_tolerance;
 using namespace std;
 using namespace zypp;
 
+static TestSetup test( Arch_x86_64 );
+
 BOOST_AUTO_TEST_CASE(capabilities_test)
 {
   //////////////////////////////////////////////////////////////////////
@@ -114,3 +117,32 @@ BOOST_AUTO_TEST_CASE(capabilities_test)
   BOOST_CHECK_EQUAL( Capability( Arch_i386, "na.me == 1" ), naoe );
 }
 
+BOOST_AUTO_TEST_CASE(guessPackageSpec)
+{
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "" ),
+                     Capability( "", "", "", "" ) );
+
+  // With no libzypp in the pool, no guess should succeed:
+  BOOST_REQUIRE( sat::WhatProvides(Capability("libzypp")).empty() );
+
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2" ),     Capability( "",     "libzypp-1-2",      "", "" ) );
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2.i586" ), Capability( "i586", "libzypp-1-2",      "", "" ) );
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp.i586-1-2" ), Capability( "",     "libzypp.i586-1-2", "", "" ) );
+
+  // now load some repo prividing libzypp and csee how the guessing
+  // changes:
+  test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
+
+  BOOST_REQUIRE( ! sat::WhatProvides(Capability("libzypp")).empty() );
+
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2" ),      Capability( "",     "libzypp", "=", "1-2" ) );
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2.i586" ), Capability( "i586", "libzypp", "=", "1-2" ) );
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp.i586-1-2" ), Capability( "i586", "libzypp", "=", "1-2" ) );
+
+  // Double arch spec: the trailing one succeeds, the other one gets part of the name.
+  // As "libzypp.i586' is not in the pool, guessing fails. Result is a named cap.
+  BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp.i586-1-2.ppc" ),
+                     Capability( "ppc",  "libzypp.i586-1-2", "", "" ) );
+}
+
+
index 0e4f6e3..b802ea6 100644 (file)
@@ -374,6 +374,46 @@ namespace zypp
     return str::regex_match( name_r, what, filenameRegex );
   }
 
+  Capability Capability::guessPackageSpec( const std::string & str_r )
+  {
+    Capability cap( str_r );
+    CapDetail detail( cap.detail() );
+
+    // str_r might be the form "libzypp-1.2.3-4.5(.arch)'
+    // correctly parsed as name capability by the ctor.
+    if ( detail.isNamed() && ::strrchr( detail.name().c_str(), '-' ) && sat::WhatProvides( cap ).empty() )
+    {
+      Arch origArch( detail.arch() ); // to support a trailing .arch
+
+      std::string guess( detail.name().asString() );
+      std::string::size_type pos( guess.rfind( '-' ) );
+      guess[pos] = '=';
+
+      Capability guesscap( origArch, guess );
+      detail = guesscap.detail();
+
+      if ( ! sat::WhatProvides( Capability(detail.name().id()) ).empty() )
+        return guesscap;
+
+      // try the one but last '-'
+      if ( pos )
+      {
+        guess[pos] = '-';
+        if ( (pos = guess.rfind( '-', pos-1 )) != std::string::npos )
+        {
+          guess[pos] = '=';
+
+          guesscap = Capability( origArch, guess );
+          detail = guesscap.detail();
+
+          if ( ! sat::WhatProvides( Capability(detail.name().id()) ).empty() )
+            return guesscap;
+        }
+      }
+    }
+    return cap;
+  }
+
   /******************************************************************
   **
   **   FUNCTION NAME : operator<<
index 77ff5b0..05697e8 100644 (file)
@@ -210,6 +210,32 @@ namespace zypp
       static bool isInterestingFileSpec( const std::string & name_r ) { return isInterestingFileSpec( name_r.c_str() ); }
       static bool isInterestingFileSpec( const char * name_r );
 
+      /** \ref Capability parser also guessing \c "libzypp-1.2.3-4.5.x86_64" formats.
+       *
+       * The argument might be in the form \c "libzypp-devel-1.2.3.x86_64".
+       * Passed to the Capability ctor, this would correctly be parsed as name
+       * capability, because actually the edition part had to be separated by a
+       * \c '=', and the architecture had to be appended to the name.
+       * So this is how it actually had to look like: \c "libzypp-devel.x86_64=1.2.3"
+       *
+       * Obviously we have to guess if, and where to split name and edition. In
+       * fact \c "devel" could also be the version and \c "1.2.3" would be the
+       * release then.
+       *
+       * Assuming this Capability should be provided by some package in
+       * the \ref ResPool, we check this. If unprovided, we substitute the last,
+       * (or one but last) \c '-' by a \c '='. If the name part
+       * (without version) of the resulting Capability is provided
+       * by the \ref ResPool, this Capability is returned.
+       *
+       * Otherwise we return the Capability originally created from
+       * \a str_r.
+       *
+       * \note: As this method will access the global pool, the returned
+       * result depends on the pools content.
+       */
+      static Capability guessPackageSpec( const std::string & str_r );
+
     public:
       /** Expert backdoor. */
       sat::detail::IdType id() const