Imported Upstream version 17.7.1 upstream/17.7.1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:17:22 +0000 (16:17 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Mon, 2 Sep 2019 07:17:22 +0000 (16:17 +0900)
21 files changed:
VERSION.cmake
package/libzypp.changes
po/ar.po
po/da.po
tests/zypp/CMakeLists.txt
tests/zypp/PoolQueryCC_test.cc [new file with mode: 0644]
tests/zypp/PoolQuery_test.cc
tests/zypp/StrMatcher_test.cc
tests/zypp/base/String_test.cc
tests/zypp/data/PoolQuery/savedqueries
tests/zypp/data/PoolQueryCC/rxnames.xml [new file with mode: 0644]
zypp/Locks.cc
zypp/Pathname.cc
zypp/PoolQuery.cc
zypp/PoolQuery.h
zypp/Product.cc
zypp/base/String.cc
zypp/base/String.h
zypp/media/MediaPlugin.cc
zypp/media/MediaPlugin.h
zypp/solver/detail/Testcase.cc

index 196dc73..0bd2ed4 100644 (file)
@@ -61,8 +61,8 @@
 SET(LIBZYPP_MAJOR "17")
 SET(LIBZYPP_COMPATMINOR "2")
 SET(LIBZYPP_MINOR "7")
-SET(LIBZYPP_PATCH "0")
+SET(LIBZYPP_PATCH "1")
 #
-# LAST RELEASED: 17.7.0 (2)
+# LAST RELEASED: 17.7.1 (2)
 # (The number in parenthesis is LIBZYPP_COMPATMINOR)
 #=======
index c5f9299..b2aad9d 100644 (file)
@@ -1,4 +1,11 @@
 -------------------------------------------------------------------
+Fri Sep 28 14:38:01 CEST 2018 - ma@suse.de
+
+- Fix conversion of string and glob to regex when compiling queries
+  (bsc#1099982, bsc#939392)
+- version 17.7.1 (2)
+
+-------------------------------------------------------------------
 Fri Sep  7 12:07:39 CEST 2018 - ma@suse.de
 
 - Drop type application due to poor metadata support (bsc#1100095,
index 678e9e4..776064a 100644 (file)
--- a/po/ar.po
+++ b/po/ar.po
@@ -13,10 +13,10 @@ msgstr ""
 "Project-Id-Version: YaST (@memory@)\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2018-08-03 11:09+0200\n"
-"PO-Revision-Date: 2018-04-18 14:13+0000\n"
-"Last-Translator: George Yacoub <george.yacoub@arabize.com>\n"
-"Language-Team: Arabic <https://l10n.opensuse.org/projects/libzypp/master/ar/"
-">\n"
+"PO-Revision-Date: 2018-09-10 20:46+0000\n"
+"Last-Translator: Mahmoud Khalil <kkhalil2535@gmail.com>\n"
+"Language-Team: Arabic <https://l10n.opensuse.org/projects/libzypp/master/ar/>"
+"\n"
 "Language: ar\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -3790,20 +3790,20 @@ msgstr[5] "(ستنتهي الصلاحية خلال %d من الأيام)"
 #: zypp/RepoInfo.cc:513
 #, boost-format
 msgid "Looking for gpg key ID %1% in cache %2%."
-msgstr ""
+msgstr "البحث عن مفتاح gpg للتشفير %1% في الذاكرة المؤقتة %2%."
 
 #. translator: %1% is a gpg key ID like 3DBDC284
 #. %2% is a repositories name
 #: zypp/RepoInfo.cc:541
 #, boost-format
 msgid "Looking for gpg key ID %1% in repository %2%."
-msgstr ""
+msgstr "يتم البحث عن معرف لمفتاح الـgpg رقم %1% في المستودع %2%."
 
 #. translator: %1% is a repositories name
 #: zypp/RepoInfo.cc:565
 #, boost-format
 msgid "Repository %1% does not define additional 'gpgkey=' URLs."
-msgstr ""
+msgstr "المستودع %1% لم يقم بتعريف مفتاح إضافي 'مفتاح gpg=' عناوين المواقع."
 
 #: zypp/RepoManager.cc:314
 #, boost-format
@@ -4215,7 +4215,7 @@ msgstr "تم تجاوز المهلة عند الوصول إلى '%s'."
 #: zypp/media/MediaException.cc:195
 #, c-format, boost-format
 msgid "Downloaded data exceeded the expected filesize '%s' of '%s'."
-msgstr ""
+msgstr "تجاوزت البيانات المحملة حجم الملف ,الحجم المتوقع للملف '%s' من '%s'."
 
 #: zypp/media/MediaException.cc:203
 #, c-format, boost-format
index abdaccf..38482ef 100644 (file)
--- a/po/da.po
+++ b/po/da.po
@@ -7,7 +7,7 @@ msgstr ""
 "Project-Id-Version: libzypp\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2018-08-03 11:09+0200\n"
-"PO-Revision-Date: 2018-08-15 11:59+0000\n"
+"PO-Revision-Date: 2018-09-17 08:56+0000\n"
 "Last-Translator: scootergrisen <scootergrisen@gmail.com>\n"
 "Language-Team: Danish <https://l10n.opensuse.org/projects/libzypp/master/da/>"
 "\n"
@@ -412,7 +412,7 @@ msgstr "Gabon"
 #. :GAB:266:
 #: zypp/CountryCode.cc:233
 msgid "United Kingdom"
-msgstr "Storbritanien"
+msgstr "Storbritannien"
 
 #. :GBR:826:
 #: zypp/CountryCode.cc:234
@@ -624,7 +624,7 @@ msgstr "Comorerne"
 #. :COM:174:
 #: zypp/CountryCode.cc:276
 msgid "Saint Kitts and Nevis"
-msgstr "Sankt Kitts og Nevis"
+msgstr "Saint Kitts og Nevis"
 
 #. :KNA:659:
 #: zypp/CountryCode.cc:277
@@ -664,7 +664,7 @@ msgstr "Libanon"
 #. :LBN:422:
 #: zypp/CountryCode.cc:284
 msgid "Saint Lucia"
-msgstr "Sankt Lucia"
+msgstr "Saint Lucia"
 
 #. :LCA:662:
 #: zypp/CountryCode.cc:285
@@ -719,7 +719,7 @@ msgstr "Monaco"
 #. :MCO:492:
 #: zypp/CountryCode.cc:295
 msgid "Moldova"
-msgstr "Moldavien"
+msgstr "Moldova"
 
 #. :MDA:498:
 #: zypp/CountryCode.cc:296
@@ -878,7 +878,7 @@ msgstr "Niue"
 #. :NIU:570:
 #: zypp/CountryCode.cc:327
 msgid "New Zealand"
-msgstr "New Zeeland"
+msgstr "New Zealand"
 
 #. :NZL:554:
 #: zypp/CountryCode.cc:328
@@ -923,7 +923,7 @@ msgstr "Polen"
 #. :POL:616:
 #: zypp/CountryCode.cc:336
 msgid "Saint Pierre and Miquelon"
-msgstr "Sankt Pierre og Miquelon"
+msgstr "Saint Pierre og Miquelon"
 
 #. :SPM:666:
 #: zypp/CountryCode.cc:337
@@ -1017,7 +1017,7 @@ msgstr "Singapore"
 #. :SGP:702:
 #: zypp/CountryCode.cc:355
 msgid "Saint Helena"
-msgstr "Sankt Helena"
+msgstr "Saint Helena"
 
 #. :SHN:654:
 #: zypp/CountryCode.cc:356
@@ -1239,7 +1239,7 @@ msgstr "Samoa"
 #. :WSM:882:
 #: zypp/CountryCode.cc:399
 msgid "Yemen"
-msgstr "Jemen"
+msgstr "Yemen"
 
 #. :YEM:887:
 #: zypp/CountryCode.cc:400
@@ -1359,7 +1359,7 @@ msgstr "Kunne ikke importere nøgle."
 
 #: zypp/KeyRing.cc:553 zypp/KeyRing.cc:557 zypp/KeyRing.cc:561
 msgid "Failed to delete key."
-msgstr "Sletning af nøgle fejlede."
+msgstr "Sletning af nøgle mislykkedes."
 
 #: zypp/KeyRing.cc:570
 #, c-format, boost-format
@@ -1993,7 +1993,7 @@ msgstr "Esperanto"
 #. language code: est et
 #: zypp/LanguageCode.cc:423
 msgid "Estonian"
-msgstr "Estonisk"
+msgstr "Estisk"
 
 #. language code: ewe ee
 #: zypp/LanguageCode.cc:425
@@ -2098,7 +2098,7 @@ msgstr "Germanske (andre)"
 #. language code: geo kat ka
 #: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469
 msgid "Georgian"
-msgstr "Georgiansk"
+msgstr "Georgisk"
 
 #. language code: ger deu de
 #: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473
@@ -2258,7 +2258,7 @@ msgstr "Øvre sorbiansk"
 #. language code: hun hu
 #: zypp/LanguageCode.cc:537
 msgid "Hungarian"
-msgstr "Ungarnsk"
+msgstr "Ungarsk"
 
 #. language code: hup
 #: zypp/LanguageCode.cc:539
@@ -2593,7 +2593,7 @@ msgstr "Lingala"
 #. language code: lit lt
 #: zypp/LanguageCode.cc:673
 msgid "Lithuanian"
-msgstr "Litausk"
+msgstr "Litauisk"
 
 #. language code: lol
 #: zypp/LanguageCode.cc:675
@@ -3238,7 +3238,7 @@ msgstr "Sidamo"
 #. language code: sin si
 #: zypp/LanguageCode.cc:947
 msgid "Sinhala"
-msgstr "Sinhala"
+msgstr "Singhalesisk"
 
 #. language code: sio
 #: zypp/LanguageCode.cc:949
@@ -3258,7 +3258,7 @@ msgstr "Slavisk (Andre)"
 #. language code: slo slk sk
 #: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957
 msgid "Slovak"
-msgstr "Slovakkisk"
+msgstr "Slovakisk"
 
 #. language code: slv sl
 #: zypp/LanguageCode.cc:959
@@ -3578,7 +3578,7 @@ msgstr "Umbundu"
 #. language code: und
 #: zypp/LanguageCode.cc:1091
 msgid "Undetermined"
-msgstr "Ubestemt"
+msgstr "Ikke fastsat"
 
 #. language code: urd ur
 #: zypp/LanguageCode.cc:1093
@@ -3648,7 +3648,7 @@ msgstr "Sorbianske sprog"
 #. language code: wln wa
 #: zypp/LanguageCode.cc:1121
 msgid "Walloon"
-msgstr "Walloon"
+msgstr "Vallonsk"
 
 #. language code: wol wo
 #: zypp/LanguageCode.cc:1123
@@ -3926,7 +3926,7 @@ msgstr "Ugyldig tom URL-objektreference"
 
 #: zypp/Url.cc:326 zypp/Url.cc:340
 msgid "Unable to parse Url components"
-msgstr "Kan ikke  fortolke URL-komponenter"
+msgstr "Kan ikke fortolke URL-komponenter"
 
 #: zypp/VendorSupportOptions.cc:14
 msgid "unknown"
@@ -4064,12 +4064,12 @@ msgstr ""
 #: zypp/media/MediaException.cc:31
 #, c-format, boost-format
 msgid "Failed to mount %s on %s"
-msgstr "Montering af %s fejlede på %s"
+msgstr "Montering af %s mislykkedes på %s"
 
 #: zypp/media/MediaException.cc:41
 #, c-format, boost-format
 msgid "Failed to unmount %s"
-msgstr "Afmontering af %s fejlede"
+msgstr "Afmontering af %s mislykkedes"
 
 #: zypp/media/MediaException.cc:46
 #, c-format, boost-format
@@ -4103,7 +4103,7 @@ msgstr "Dårligt tilknytningspunkt for medie"
 #: zypp/media/MediaException.cc:77
 #, c-format, boost-format
 msgid "Download (curl) initialization failed for '%s'"
-msgstr "Download (curl) initialisering fejlede for '%s'"
+msgstr "Download (curl) initialisering mislykkede for '%s'"
 
 #: zypp/media/MediaException.cc:82
 #, c-format, boost-format
@@ -4650,7 +4650,7 @@ msgstr " afviklet"
 
 #: zypp/target/TargetImpl.cc:333
 msgid " execution failed"
-msgstr " afvikling fejlede"
+msgstr " afvikling mislykkedes"
 
 #. translators: We may find the same script content in files with different names.
 #. Only the first occurence is executed, subsequent ones are skipped. It's a one-line
@@ -4699,7 +4699,7 @@ msgstr "HalVolume er ikke initialiseret"
 
 #: zypp/target/hal/HalContext.cc:229
 msgid "Unable to create dbus connection"
-msgstr "Kan ikke  oprette dbus-tilslutning"
+msgstr "Kan ikke oprette dbus-tilslutning"
 
 #: zypp/target/hal/HalContext.cc:242
 msgid "libhal_ctx_new: Can't create libhal context"
@@ -4711,7 +4711,7 @@ msgstr "libhal_set_dbus_connection: dbus-tilslutning kan ikke indstilles"
 
 #: zypp/target/hal/HalContext.cc:272
 msgid "Unable to initalize HAL context -- hald not running?"
-msgstr "Kan ikke initialisere HAL-kontekst -- kører hald  ikke?"
+msgstr "Kan ikke initialisere HAL-kontekst -- kører hald ikke?"
 
 #: zypp/target/hal/HalContext.cc:851
 msgid "Not a CDROM drive"
@@ -4722,19 +4722,19 @@ msgstr "Ikke et cd-rom-drev"
 #: zypp/target/rpm/RpmDb.cc:832 zypp/target/rpm/RpmDb.cc:2093
 #: zypp/target/rpm/RpmDb.cc:2239
 msgid "RPM failed: "
-msgstr "RPM fejlede: "
+msgstr "RPM mislykkedes: "
 
 #. Translator: %1% is a gpg public key
 #: zypp/target/rpm/RpmDb.cc:1148
 #, boost-format
 msgid "Failed to import public key %1%"
-msgstr "Import af offentlig nøgle %1% fejlede"
+msgstr "Import af offentlig nøgle %1% mislykkedes"
 
 #. Translator: %1% is a gpg public key
 #: zypp/target/rpm/RpmDb.cc:1218
 #, boost-format
 msgid "Failed to remove public key %1%"
-msgstr "Fjernelse af den offentlige nøgle %1% fejlede"
+msgstr "Fjernelse af den offentlige nøgle %1% mislykkedes"
 
 #: zypp/target/rpm/RpmDb.cc:1599
 msgid "Package is not signed!"
index 25a47bb..6649586 100644 (file)
@@ -29,6 +29,7 @@ ADD_TESTS(
   PathInfo
   Pathname
   PluginFrame
+  PoolQueryCC
   PoolQuery
   ProgressData
   PtrTypes
diff --git a/tests/zypp/PoolQueryCC_test.cc b/tests/zypp/PoolQueryCC_test.cc
new file mode 100644 (file)
index 0000000..6c50db4
--- /dev/null
@@ -0,0 +1,121 @@
+#include "TestSetup.h"
+#include <zypp/base/String.h>
+#include <zypp/base/LogTools.h>
+
+#include "zypp/PoolQuery.h"
+#include "zypp/PoolQueryUtil.tcc"
+
+#define BOOST_TEST_MODULE PoolQuery_CC
+
+using boost::unit_test::test_case;
+using std::cin;
+using std::cout;
+using std::cerr;
+using std::endl;
+using namespace zypp;
+
+static TestSetup test;
+
+/////////////////////////////////////////////////////////////////////////////
+template <class TCont>
+std::ostream & nlist( std::ostream & str, const TCont & set_r )
+{
+  str << "[" << set_r.size() << "]: ";
+  for ( const auto & solv : set_r )
+    str << " \"" << solv.name() << "\"";
+  return str << endl;
+}
+
+BOOST_AUTO_TEST_CASE(init)
+{
+  test.loadTargetHelix( TESTS_SRC_DIR "/zypp/data/PoolQueryCC/rxnames.xml" );
+  nlist( cout << "repo ", ResPool::instance() );
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Basic issue: Multiple match strings are compiled into a singe regex. The
+// semantic of the individual match strings must be preserved. I.e. a literal
+// "." must become "\.". Globbing patterns must match the whole string, so they
+// need to be anchored within the regex. Etc.
+/////////////////////////////////////////////////////////////////////////////
+static const unsigned qtestSIZEMISS    = unsigned(-1);
+static const unsigned qtestRXFAIL      = unsigned(-2);
+static const unsigned qtestRXFAILCOMB  = unsigned(-3);
+
+unsigned qtest( const std::string & pattern_r, Match::Mode mode_r, bool verbose_r = false )
+{
+  static constexpr const bool noMatchInvalidRegexException = false;
+
+  typedef std::set<sat::Solvable> Result;
+  PoolQuery q;
+  q.addAttribute(sat::SolvAttr::name);
+  switch ( mode_r )
+  {
+    case Match::STRING:                q.setMatchExact();      break;
+    case Match::SUBSTRING:     q.setMatchSubstring();  break;
+    case Match::OTHER:         q.setMatchWord();       break;  // OTHER missused for matchWord()
+    case Match::GLOB:          q.setMatchGlob();       break;
+    case Match::REGEX:         q.setMatchRegex();      break;
+    default:
+      throw( "unhandled match mode" );
+      break;
+  }
+  q.addString( pattern_r );
+  Result o;
+  try {
+    o = Result( q.begin(), q.end() );  // original query
+  }
+  catch ( const zypp::MatchInvalidRegexException & excpt )
+  {
+    cout << "Caught: " << excpt << endl;
+    return qtestRXFAIL;
+  }
+
+  q.addString( "more" );
+  try {
+    Result r( q.begin(), q.end() );    // compiles into RX (o|more)
+
+    BOOST_CHECK( o == r );
+    if ( o != r || verbose_r )
+    {
+      cout << '"' << pattern_r << "\"  " << mode_r << endl;
+      nlist( cout << "    o", o );
+      nlist( cout << "    r", r );
+      if ( ! verbose_r )
+       return qtestSIZEMISS;
+    }
+  }
+  catch ( const zypp::MatchInvalidRegexException & excpt )
+  {
+    BOOST_CHECK( noMatchInvalidRegexException );
+    cout << "Caught: " << excpt << endl;
+    return qtestRXFAILCOMB;
+  }
+
+  return o.size();
+}
+
+inline unsigned qtest( const std::string & pattern_r, bool verbose_r = false )
+{ return qtest( pattern_r, Match::SUBSTRING, verbose_r ); }
+
+/////////////////////////////////////////////////////////////////////////////
+BOOST_AUTO_TEST_CASE(pool_query_init)
+{
+  // NOTE: qtest( , Match::OTHER ) is missused for matchWord()
+  BOOST_CHECK_EQUAL( qtest( "?", Match::SUBSTRING ),   1 );
+  BOOST_CHECK_EQUAL( qtest( "?", Match::STRING ),      1 );
+  BOOST_CHECK_EQUAL( qtest( "?", Match::OTHER ),       0 );    // not word boundary
+  BOOST_CHECK_EQUAL( qtest( "?", Match::GLOB ),                15 );
+  BOOST_CHECK_EQUAL( qtest( "\\?", Match::GLOB ),      1 );
+  BOOST_CHECK_EQUAL( qtest( "?", Match::REGEX ),       qtestRXFAIL );
+  BOOST_CHECK_EQUAL( qtest( "\\?", Match::REGEX ),     1 );
+
+  BOOST_CHECK_EQUAL( qtest( "A", Match::SUBSTRING ),   4 );
+  BOOST_CHECK_EQUAL( qtest( "A", Match::OTHER ),       2 );
+  BOOST_CHECK_EQUAL( qtest( "A*", Match::OTHER ),      0 );
+  BOOST_CHECK_EQUAL( qtest( "*A", Match::OTHER ),      0 );
+  BOOST_CHECK_EQUAL( qtest( "A*", Match::GLOB ),       2 );
+  BOOST_CHECK_EQUAL( qtest( "*A", Match::GLOB ),       1 );
+}
+
+/////////////////////////////////////////////////////////////////////////////
index 2019580..94f53ef 100644 (file)
@@ -604,7 +604,6 @@ BOOST_AUTO_TEST_CASE(pool_query_recovery)
   q.addRepo("opensuse");
   q.addKind(ResKind::patch);
   q.setMatchRegex();
-  q.setRequireAll();
   q.setCaseSensitive();
   q.setUninstalledOnly();
   q.setEdition(Edition("0.8.3"),Rel::NE);
index ec2e157..3dddf0c 100644 (file)
@@ -103,6 +103,8 @@ BOOST_AUTO_TEST_CASE(StrMatcher_STRING)
   BOOST_CHECK( !m( "" ) );
   BOOST_CHECK( !m( "a" ) );
   BOOST_CHECK( m( "fau" ) );
+  BOOST_CHECK( !m( "fault" ) );
+  BOOST_CHECK( !m( "defau" ) );
   BOOST_CHECK( !m( "default" ) );
 }
 
@@ -113,6 +115,7 @@ BOOST_AUTO_TEST_CASE(StrMatcher_STRINGSTART)
   BOOST_CHECK( !m( "a" ) );
   BOOST_CHECK( m( "fau" ) );
   BOOST_CHECK( m( "fault" ) );
+  BOOST_CHECK( !m( "defau" ) );
   BOOST_CHECK( !m( "default" ) );
 }
 
@@ -122,12 +125,61 @@ BOOST_AUTO_TEST_CASE(StrMatcher_STRINGEND)
   BOOST_CHECK( !m( "" ) );
   BOOST_CHECK( !m( "a" ) );
   BOOST_CHECK( m( "fau" ) );
+  BOOST_CHECK( !m( "fault" ) );
   BOOST_CHECK( m( "defau" ) );
   BOOST_CHECK( !m( "default" ) );
 }
 
+BOOST_AUTO_TEST_CASE(StrMatcher_GLOB)
+{
+  // GLOB must match whole word
+  StrMatcher m( "f[a]u", Match::GLOB );
+  BOOST_CHECK( !m( "" ) );
+  BOOST_CHECK( !m( "a" ) );
+  BOOST_CHECK( m( "fau" ) );
+  BOOST_CHECK( !m( "fault" ) );
+  BOOST_CHECK( !m( "defau" ) );
+  BOOST_CHECK( !m( "default" ) );
+}
+
 BOOST_AUTO_TEST_CASE(StrMatcher_REGEX)
 {
+  // REGEX matches substring (unless anchored)
+  StrMatcher m( "f[a]u", Match::REGEX );
+  BOOST_CHECK( !m( "" ) );
+  BOOST_CHECK( !m( "a" ) );
+  BOOST_CHECK( m( "fau" ) );
+  BOOST_CHECK( m( "fault" ) );
+  BOOST_CHECK( m( "defau" ) );
+  BOOST_CHECK( m( "default" ) );
+
+  m.setSearchstring( "^f[a]u" );
+  BOOST_CHECK( !m( "" ) );
+  BOOST_CHECK( !m( "a" ) );
+  BOOST_CHECK( m( "fau" ) );
+  BOOST_CHECK( m( "fault" ) );
+  BOOST_CHECK( !m( "defau" ) );
+  BOOST_CHECK( !m( "default" ) );
+
+  m.setSearchstring( "f[a]u$" );
+  BOOST_CHECK( !m( "" ) );
+  BOOST_CHECK( !m( "a" ) );
+  BOOST_CHECK( m( "fau" ) );
+  BOOST_CHECK( !m( "fault" ) );
+  BOOST_CHECK( m( "defau" ) );
+  BOOST_CHECK( !m( "default" ) );
+
+  m.setSearchstring( "^f[a]u$" );
+  BOOST_CHECK( !m( "" ) );
+  BOOST_CHECK( !m( "a" ) );
+  BOOST_CHECK( m( "fau" ) );
+  BOOST_CHECK( !m( "fault" ) );
+  BOOST_CHECK( !m( "defau" ) );
+  BOOST_CHECK( !m( "default" ) );
+}
+
+BOOST_AUTO_TEST_CASE(StrMatcher_RX)
+{
   StrMatcher m( "fau" );
 
   BOOST_CHECK( !m.isCompiled() );
index 152a229..2e82ab8 100644 (file)
@@ -11,6 +11,56 @@ using namespace std;
 using namespace zypp;
 using namespace zypp::str;
 
+#define RXspecial "\\^.[$()|*+?{"
+
+BOOST_AUTO_TEST_CASE(str2rx)
+{
+  char s[] = "c";
+  char x[] = "\\c";
+  for ( const char * ch = RXspecial; *ch; ++ch )
+  {
+    s[0] = x[1] = *ch;
+    BOOST_CHECK_EQUAL( str::rxEscapeStr( s ), x );
+  }
+}
+
+BOOST_AUTO_TEST_CASE(glob2rx)
+{
+  {
+    char s[] = "c";
+    char x[] = "\\c";
+    for ( const char * ch = RXspecial; *ch; ++ch )
+    {
+      s[0] = x[1] = *ch;
+      if ( *ch == '?' )
+       BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "." );
+      else if ( *ch == '*' )
+       BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), ".*" );
+      else if ( *ch == '[' )
+       BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\[" );     // no closing ] so it is literal
+       else if ( *ch == '\\' )
+         BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\" );    // actually an input error as "\" is not a valid GLOB
+         else
+         {
+           s[0] = x[1] = *ch;
+           BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), x );
+         }
+    }
+    std::string a( str::rxEscapeStr( RXspecial ) );    // all rx/glob special chars are literally (\-escaped)
+    BOOST_CHECK_EQUAL( str::rxEscapeGlob( a ), a );    // nothing more to escape.
+
+    // character class: contains "]["
+    BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[][]" ),    "[][]" );
+    BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^][]" ),   "[^][]" );
+    BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!][]" ),   "[^][]" );      // glob allows ! and ^ to negate a cclass
+
+    // no character class: no closing ']' so take it literally (the ] would be member of the cclass, not the closing ])
+    BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[]" ),      "\\[]" );
+    BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!]" ),     "\\[!]" );
+    BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^]" ),     "\\[\\^]" );
+  }
+}
+
 BOOST_AUTO_TEST_CASE(gsubTest)
 {
   string olds = "olds";
index 79c689b..26d56e6 100644 (file)
@@ -6,7 +6,6 @@ query_string: ma*
 repo: opensuse
 type: patch
 match_type: regex
-require_all: on
 case_sensitive: on
 install_status: not-installed
 version: != 0.8.3
diff --git a/tests/zypp/data/PoolQueryCC/rxnames.xml b/tests/zypp/data/PoolQueryCC/rxnames.xml
new file mode 100644 (file)
index 0000000..d3be84b
--- /dev/null
@@ -0,0 +1,21 @@
+<channel>
+  <subchannel>
+    <package><name>.</name></package>
+    <package><name>?</name></package>
+    <package><name>*</name></package>
+    <package><name>+</name></package>
+    <package><name>[</name></package>
+    <package><name>]</name></package>
+    <package><name>(</name></package>
+    <package><name>)</name></package>
+    <package><name>{</name></package>
+    <package><name>}</name></package>
+    <package><name>|</name></package>
+    <package><name>^</name></package>
+    <package><name>$</name></package>
+    <package><name>\</name></package>
+    <package><name>A</name></package>
+    <package><name>AB</name></package>
+    <package><name>BAB</name></package>
+    <package><name>.A.</name></package>
+</subchannel></channel>
index fef0658..c478be5 100644 (file)
@@ -257,7 +257,6 @@ void Locks::removeLock( const ResKind &kind_r, const IdString &name_r )
   q.addKind( kind_r );
   q.setMatchExact();
   q.setCaseSensitive(true);
-  q.requireAll();
   DBG << "remove lock by Selectable" << endl;
   removeLock(q);
 }
index 3237fbe..61b08af 100644 (file)
@@ -249,7 +249,7 @@ namespace zypp
        return "/";
       std::string rest( str::stripPrefix( path_r.asString(), root_r.asString() ) );
       if ( rest[0] == '/' )    // needs to be a dir prefix!
-       return std::move(rest);
+       return rest;
       return path_r;
     }
 
index 9ac9cd9..4c2e8e7 100644 (file)
@@ -418,7 +418,6 @@ namespace zypp
     Impl()
       : _flags( Match::SUBSTRING | Match::NOCASE | Match::SKIP_KIND )
       , _match_word(false)
-      , _require_all(false)
       , _status_flags(ALL)
     {}
 
@@ -441,7 +440,6 @@ namespace zypp
     /** Sat solver search flags */
     Match _flags;
     bool _match_word;
-    bool _require_all;
 
     /** Sat solver status flags */
     StatusFilter _status_flags;
@@ -468,7 +466,6 @@ namespace zypp
       OUTS( _uncompiledPredicated );
       OUTS( _flags.get() );
       OUTS( _match_word );
-      OUTS( _require_all );
       OUTS( _status_flags );
       OUTS( _edition );
       OUTS( _op.inSwitch() );
@@ -496,7 +493,6 @@ namespace zypp
              && _attrs == rhs._attrs
              && _uncompiledPredicated == rhs._uncompiledPredicated
              && _match_word == rhs._match_word
-             && _require_all == rhs._require_all
              && _status_flags == rhs._status_flags
              && _edition == rhs._edition
              && _op == rhs._op
@@ -520,8 +516,10 @@ namespace zypp
     mutable AttrMatchList _attrMatchList;
 
   private:
-    /** Pass flags from \ref compile, as they may have been changed. */
-    string createRegex( const StrContainer & container, const Match & flags ) const;
+    /** Join patterns in \a container_r according to \a flags_r into a single \ref StrMatcher.
+     * The \ref StrMatcher returned will be a REGEX if more than one pattern was passed.
+     */
+    StrMatcher joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const;
 
   private:
     friend Impl * rwcowClone<Impl>( const Impl * rhs );
@@ -558,13 +556,8 @@ namespace zypp
   {
     _attrMatchList.clear();
 
-    Match cflags( _flags );
-    if ( cflags.mode() == Match::OTHER ) // this will never succeed...
-      ZYPP_THROW( MatchUnknownModeException( cflags ) );
-
-    /** Compiled search strings. */
-    string rcstrings;
-
+    if ( _flags.mode() == Match::OTHER ) // this will never succeed...
+      ZYPP_THROW( MatchUnknownModeException( _flags ) );
 
     // 'different'         - will have to iterate through all and match by ourselves (slow)
     // 'same'              - will pass the compiled string to dataiterator_init
@@ -589,11 +582,8 @@ namespace zypp
       StrContainer joined;
       invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
       invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
-      rcstrings = createRegex(joined, cflags);
-      if (joined.size() > 1) // switch to regex for multiple strings
-        cflags.setModeRegex();
-      _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first,
-                                StrMatcher( rcstrings, cflags ) ) );
+
+      _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first, joinedStrMatcher( joined, _flags ) ) );
     }
 
     // // MULTIPLE ATTRIBUTES
@@ -601,16 +591,21 @@ namespace zypp
     {
       // check whether there are any per-attribute strings
       bool attrvals_empty = true;
-      for (AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai)
-        if (!ai->second.empty())
-          for(StrContainer::const_iterator it = ai->second.begin();
-              it != ai->second.end(); it++)
-            if (!it->empty())
-            {
-              attrvals_empty = false;
-              goto attremptycheckend;
-            }
-attremptycheckend:
+      for_( ai, _attrs.begin(), _attrs.end() )
+      {
+        if ( ai->second.empty() )
+         continue;
+       for_( it, ai->second.begin(), ai->second.end() )
+       {
+         if ( !it->empty() )
+         {
+           attrvals_empty = false;
+           break;
+         }
+       }
+        if ( ! attrvals_empty )
+         break;
+      }
 
       // chceck whether the per-attribute strings are all the same
       bool attrvals_thesame = true;
@@ -641,18 +636,15 @@ attremptycheckend:
         if (attrvals_empty)
         {
           invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
-          rcstrings = createRegex(joined, cflags);
         }
         else
         {
           invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
           invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined));
-          rcstrings = createRegex(joined, cflags);
         }
-        if (joined.size() > 1) // switch to regex for multiple strings
-          cflags.setModeRegex();
+
         // May use the same StrMatcher for all
-        StrMatcher matcher( rcstrings, cflags );
+        StrMatcher matcher( joinedStrMatcher( joined, _flags ) );
         for_( ai, _attrs.begin(), _attrs.end() )
         {
           _attrMatchList.push_back( AttrMatchData( ai->first, matcher ) );
@@ -670,11 +662,8 @@ attremptycheckend:
           StrContainer joined;
           invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined));
           invokeOnEach(ai->second.begin(), ai->second.end(), EmptyFilter(), MyInserter(joined));
-          string s = createRegex(joined, cflags);
-          if (joined.size() > 1) // switch to regex for multiple strings
-            cflags.setModeRegex();
-          _attrMatchList.push_back( AttrMatchData( ai->first,
-                                    StrMatcher( s, cflags ) ) );
+
+          _attrMatchList.push_back( AttrMatchData( ai->first, joinedStrMatcher( joined, _flags ) ) );
         }
       }
     }
@@ -694,14 +683,9 @@ attremptycheckend:
           if ( ! mstr.empty() )
             joined.insert( mstr );
 
-          cflags = _flags;
-          rcstrings = createRegex( joined, cflags );
-          if ( joined.size() > 1 ) // switch to regex for multiple strings
-            cflags.setModeRegex();
-
          // copy and exchange the StrMatcher
          AttrMatchData nattr( *it );
-         nattr.strMatcher = StrMatcher( rcstrings, cflags ),
+         nattr.strMatcher = joinedStrMatcher( joined, _flags );
           _attrMatchList.push_back( std::move(nattr) );
         }
         else
@@ -715,12 +699,7 @@ attremptycheckend:
     // If no attributes defined at all, then add 'query all'
     if ( _attrMatchList.empty() )
     {
-      cflags = _flags;
-      rcstrings = createRegex( _strings, cflags );
-      if ( _strings.size() > 1 ) // switch to regex for multiple strings
-        cflags.setModeRegex();
-      _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr,
-                                StrMatcher( rcstrings, cflags ) ) );
+      _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr, joinedStrMatcher( _strings, _flags ) ) );
     }
 
     // Finally check here, whether all involved regex compile.
@@ -731,102 +710,64 @@ attremptycheckend:
     //DBG << asString() << endl;
   }
 
-
-  /**
-   * Converts '*' and '?' wildcards within str into their regex equivalents.
-   */
-  static string wildcards2regex(const string & str)
-  {
-    string regexed = str;
-
-    string r_all(".*"); // regex equivalent of '*'
-    string r_one(".");  // regex equivalent of '?'
-    string::size_type pos;
-
-    // replace all "*" in input with ".*"
-    for (pos = 0; (pos = regexed.find("*", pos)) != std::string::npos; pos+=2)
-      regexed = regexed.replace(pos, 1, r_all);
-
-    // replace all "?" in input with "."
-    for (pos = 0; (pos = regexed.find('?', pos)) != std::string::npos; ++pos)
-      regexed = regexed.replace(pos, 1, r_one);
-
-    return regexed;
-  }
-
-  string PoolQuery::Impl::createRegex( const StrContainer & container, const Match & flags ) const
+  ///////////////////////////////////////////////////////////////////
+  namespace
   {
-//! macro for word boundary tags for regexes
-#define WB (_match_word ? string("\\b") : string())
-    string rstr;
+    /** Escape \a str_r for use in a regex.
+     * \a flags_r determines whether the input string is interpreted
+     * as regex, glob or plain string.
+     */
+    std::string rxEscape( std::string str_r, const Match & flags_r )
+    {
+      if ( str_r.empty() || flags_r.isModeRegex() )
+       return str_r;
 
-    if (container.empty())
-      return rstr;
+      if ( flags_r.isModeGlob() )
+       return str::rxEscapeGlob( std::move(str_r) );
 
-    if (container.size() == 1)
-    {
-      return WB + *container.begin() + WB;
+      return str::rxEscapeStr( std::move(str_r) );
     }
+  } // namespace
+  ///////////////////////////////////////////////////////////////////
 
-    // multiple strings
+  StrMatcher PoolQuery::Impl::joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const
+  {
+    USR << flags_r << " - " << container_r << endl;
 
-    bool use_wildcards = flags.isModeGlob();
-    StrContainer::const_iterator it = container.begin();
-    string tmp;
+    if ( container_r.empty() )
+      return StrMatcher( std::string(), flags_r );
 
-    if (use_wildcards)
-      tmp = wildcards2regex(*it);
-    else
-      tmp = *it;
+    if ( container_r.size() == 1 && !_match_word )     // use RX to match words
+      return StrMatcher( *container_r.begin(), flags_r );
 
-    if (_require_all)
-    {
-      if ( ! flags.isModeString() ) // not match exact
-        tmp += ".*" + WB + tmp;
-      rstr = "(?=" + tmp + ")";
-    }
-    else
-    {
-      if ( flags.isModeString() || flags.isModeGlob() )
-        rstr = "^";
-      rstr += WB + "(" + tmp;
-    }
+    // Convert to a regex.
+    // Note: Modes STRING and GLOB match whole strings (anchored ^ $)
+    //       SUBSTRING and REGEX match substrings      (match_word anchores SUBSTRING \b)
+    Match retflags( flags_r );
+    retflags.setModeRegex();
+    str::Str ret;
 
-    ++it;
+    if ( flags_r.isModeString() || flags_r.isModeGlob() )
+      ret << "^";
+    else if ( _match_word )
+      ret << "\\b";
 
-    for (; it != container.end(); ++it)
+    // (..|..|..)
+    char sep = '(';
+    for ( const::std::string & s : container_r )
     {
-      if (use_wildcards)
-        tmp = wildcards2regex(*it);
-      else
-        tmp = *it;
-
-      if (_require_all)
-      {
-        if ( ! flags.isModeString() ) // not match exact
-          tmp += ".*" + WB + tmp;
-        rstr += "(?=" + tmp + ")";
-      }
-      else
-      {
-        rstr += "|" + tmp;
-      }
+      ret << sep << rxEscape( s, flags_r );
+      if ( sep == '(' )
+       sep = '|';
     }
+    ret << ')';
 
-    if (_require_all)
-    {
-      if ( ! flags.isModeString() ) // not match exact
-        rstr += WB + ".*";
-    }
-    else
-    {
-      rstr += ")" + WB;
-      if ( flags.isModeString() || flags.isModeGlob() )
-        rstr += "$";
-    }
+    if ( flags_r.isModeString() || flags_r.isModeGlob() )
+      ret << "$";
+    else if ( _match_word )
+      ret << "\\b";
 
-    return rstr;
-#undef WB
+    return StrMatcher( ret, retflags );
   }
 
   string PoolQuery::Impl::asString() const
@@ -1009,15 +950,11 @@ attremptycheckend:
     _pimpl->_op = op;
   }
 
-  void PoolQuery::setMatchSubstring()  { _pimpl->_flags.setModeSubstring(); }
-  void PoolQuery::setMatchExact()      { _pimpl->_flags.setModeString(); }
-  void PoolQuery::setMatchRegex()      { _pimpl->_flags.setModeRegex(); }
-  void PoolQuery::setMatchGlob()       { _pimpl->_flags.setModeGlob(); }
-  void PoolQuery::setMatchWord()
-  {
-    _pimpl->_match_word = true;
-    _pimpl->_flags.setModeRegex();
-  }
+  void PoolQuery::setMatchSubstring()  { _pimpl->_flags.setModeSubstring();    _pimpl->_match_word = false; }
+  void PoolQuery::setMatchExact()      { _pimpl->_flags.setModeString();       _pimpl->_match_word = false; }
+  void PoolQuery::setMatchRegex()      { _pimpl->_flags.setModeRegex();        _pimpl->_match_word = false; }
+  void PoolQuery::setMatchGlob()       { _pimpl->_flags.setModeGlob();         _pimpl->_match_word = false; }
+  void PoolQuery::setMatchWord()       { _pimpl->_flags.setModeSubstring();    _pimpl->_match_word = true; }
 
   Match PoolQuery::flags() const
   { return _pimpl->_flags; }
@@ -1033,10 +970,6 @@ attremptycheckend:
   { _pimpl->_status_flags = flags; }
 
 
-  void PoolQuery::setRequireAll(bool require_all)
-  { _pimpl->_require_all = require_all; }
-
-
   const PoolQuery::StrContainer &
   PoolQuery::strings() const
   { return _pimpl->_strings; }
@@ -1079,15 +1012,10 @@ attremptycheckend:
   { _pimpl->_flags.turn( Match::FILES, value ); }
 
   bool PoolQuery::matchExact() const           { return _pimpl->_flags.isModeString(); }
-  bool PoolQuery::matchSubstring() const       { return _pimpl->_flags.isModeSubstring(); }
+  bool PoolQuery::matchSubstring() const       { return _pimpl->_flags.isModeSubstring() && !_pimpl->_match_word; }
   bool PoolQuery::matchGlob() const            { return _pimpl->_flags.isModeGlob(); }
   bool PoolQuery::matchRegex() const           { return _pimpl->_flags.isModeRegex(); }
-
-  bool PoolQuery::matchWord() const
-  { return _pimpl->_match_word; }
-
-  bool PoolQuery::requireAll() const
-  { return _pimpl->_require_all; }
+  bool PoolQuery::matchWord() const            { return _pimpl->_flags.isModeSubstring() && _pimpl->_match_word; }
 
   PoolQuery::StatusFilter PoolQuery::statusFilterFlags() const
   { return _pimpl->_status_flags; }
@@ -1116,6 +1044,9 @@ attremptycheckend:
   { invokeOnEach( begin(), end(), fnc); }
 
 
+  /*DEPRECATED LEGACY:*/void PoolQuery::setRequireAll( bool ) {}
+  /*DEPRECATED LEGACY:*/bool PoolQuery::requireAll() const    { return false; }
+
   ///////////////////////////////////////////////////////////////////
   //
   //  CLASS NAME : PoolQuery::Attr
@@ -1150,7 +1081,7 @@ attremptycheckend:
     static const PoolQueryAttr kindAttr;
     static const PoolQueryAttr stringAttr;
     static const PoolQueryAttr stringTypeAttr;
-    static const PoolQueryAttr requireAllAttr;
+    static const PoolQueryAttr requireAllAttr; // LEAGACY: attribute was defined but never implemented.
     static const PoolQueryAttr caseSensitiveAttr;
     static const PoolQueryAttr installStatusAttr;
     static const PoolQueryAttr editionAttr;
@@ -1163,7 +1094,7 @@ attremptycheckend:
   const PoolQueryAttr PoolQueryAttr::kindAttr( "type" );
   const PoolQueryAttr PoolQueryAttr::stringAttr( "query_string" );
   const PoolQueryAttr PoolQueryAttr::stringTypeAttr("match_type");
-  const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all");
+  const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all");    // LEAGACY: attribute was defined but never implemented.
   const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive");
   const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status");
   const PoolQueryAttr PoolQueryAttr::editionAttr("version");
@@ -1287,18 +1218,8 @@ attremptycheckend:
       }
       else if ( attribute==PoolQueryAttr::requireAllAttr )
       {
-        if ( str::strToTrue(attrValue) )
-        {
-          setRequireAll(true);
-        }
-        else if ( !str::strToFalse(attrValue) )
-        {
-          setRequireAll(false);
-        }
-        else
-        {
-          WAR << "unknown boolean value " << attrValue << endl;
-        }
+       // LEAGACY: attribute was defined but never implemented.
+       // Actually it should not occur outside our testcases.
       }
       else if ( attribute==PoolQueryAttr::caseSensitiveAttr )
       {
@@ -1442,19 +1363,6 @@ attremptycheckend:
       }
     }
 
-    if( requireAll() != q.requireAll() )
-    {
-      str << "require_all: ";
-      if (requireAll())
-      {
-        str << "on" << delim;
-      }
-      else
-      {
-        str << "off" << delim;
-      }
-    }
-
     if( statusFilterFlags() != q.statusFilterFlags() )
     {
       switch( statusFilterFlags() )
index 777138e..73582ac 100644 (file)
@@ -189,8 +189,7 @@ namespace zypp
      * This method can be used multiple times in which case the query strings
      * will be combined (together with strings added via addAttribute()) into
      * a regex. Searched attribute value will match this regex if <b>any</b>
-     * of these strings will match the value. This can be changed by
-     * (not yet implemented) \ref setRequireAll() method.
+     * of these strings will match the value.
      */
     void addString(const std::string & value);
 
@@ -202,8 +201,6 @@ namespace zypp
      * case the query strings will be combined (together with strings added
      * via addString()) into a regex. Searched attribute value will match
      * this regex if <b>any</b> of these strings will match the value.
-     * This can be changed by (not yet implemented) \ref setRequireAll()
-     * method.
      *
      * \note Though it is possible to use dependency attributes like
      * \ref Solv::Attr::provides here, note that the query string is
@@ -374,20 +371,11 @@ namespace zypp
     void setMatchGlob();
     /** Set to use the query strings as regexes */
     void setMatchRegex();
-    /** Set to match words (uses regex) */
+    /** Set substring to match words */
     void setMatchWord();
     //void setLocale(const Locale & locale);
     //@}
 
-    /**
-     * Require that all of the values set by addString or addAttribute
-     * match the values of respective attributes.
-     *
-     * \todo doesn't work yet, don't use this function
-     */
-    void setRequireAll( bool require_all = true );
-
-
     /** \name getters */
     //@{
 
@@ -430,12 +418,6 @@ namespace zypp
     Match::Mode matchMode() const
     { return flags().mode(); }
 
-    /**
-     * Whether all values added via addString() or addAttribute() are required
-     * to match the values of the respective attributes.
-     */
-    bool requireAll() const;
-
     StatusFilter statusFilterFlags() const;
     //@}
 
@@ -488,6 +470,12 @@ namespace zypp
     void setFlags( const Match & flags );
 
   public:
+    /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */
+    void setRequireAll( bool require_all = true ) ZYPP_DEPRECATED;
+    /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */
+    bool requireAll() const ZYPP_DEPRECATED;
+
+  public:
     class Impl;
   private:
     /** Pointer to implementation */
index 7e98447..ab3e07e 100644 (file)
@@ -31,20 +31,6 @@ namespace zypp
 
   namespace
   {
-    void fillList( std::list<Url> & ret_r, sat::Solvable solv_r, sat::SolvAttr attr_r )
-    {
-      sat::LookupAttr query( attr_r, solv_r );
-      for_( it, query.begin(), query.end() )
-      {
-        try // ignore malformed urls
-        {
-          ret_r.push_back( Url( it.asString() ) );
-        }
-        catch( const url::UrlException & )
-        {}
-      }
-    }
-
     void fillList( std::list<std::string> & ret_r, sat::Solvable solv_r, sat::SolvAttr attr_r )
     {
       sat::LookupAttr query( attr_r, solv_r );
index be0bb64..c5fa4b8 100644 (file)
@@ -388,6 +388,91 @@ namespace zypp
       return std::string( buf.begin(), buf.end() );
     }
 
+
+    std::string bEscape( std::string str_r, const C_Str & special_r )
+    {
+      if ( str_r.empty() )
+       return str_r;
+
+      if ( str_r.find_first_of( special_r ) == std::string::npos
+       && ( ::strchr( special_r.c_str(), '\\' ) ||  !::strchr( str_r.c_str(), '\\' ) ) )
+       return str_r;
+
+      Str buf;
+      for_( s, str_r.c_str(), s+str_r.size() )
+      {
+       if ( *s == '\\' || ::strchr( special_r.c_str(), *s ) )
+         buf << '\\';
+       buf << *s;
+      }
+      return buf;
+    }
+
+    #define RXSPECIALCHARS "\\.*+?^$[()|{"
+
+    std::string rxEscapeStr( std::string str_r )
+    {
+      return bEscape( std::move(str_r), RXSPECIALCHARS );
+    }
+
+    std::string rxEscapeGlob( std::string str_r )
+    {
+      if ( str_r.empty() )
+       return str_r;
+
+      if ( str_r.find_first_of( RXSPECIALCHARS ) == std::string::npos )
+       return str_r;
+
+      Str buf;
+      for_( s, str_r.c_str(), s+str_r.size() )
+      {
+       if ( *s == '\\' )       // + next char literally
+       {
+         buf << '\\';
+         if ( *(s+1) ) { ++s; buf << *s; }
+       }
+       else if ( *s == '?' )   // translate
+       {
+         buf << '.';
+       }
+       else if ( *s == '*' )   // translate
+       {
+         buf << ".*";
+       }
+       else if ( *s == '[' )   // character class if closing ] is found, else literally
+       {
+         const char * e = s+1;
+         if ( *e == '^' || *e == '!' ) // negated cclass
+           ++e;
+         if ( *e == ']' )              // ] in cclass
+           ++e;
+         while ( *e && *e != ']' )     // ...to ] or \0
+           ++e;
+         if ( *e ) // on closing ']'
+         {
+           ++s;  buf << '[' << (*s == '!' ? '^' : *s );
+           while ( ++s != e )
+             buf << *s;
+           buf << ']';
+         }
+         else
+         {
+           buf << "\\[";
+         }
+       }
+       else if ( ::strchr( RXSPECIALCHARS, *s ) )      // escape
+       {
+         buf << '\\' << *s;
+       }
+       else
+       {
+         buf << *s;
+       }
+      }
+      return buf;
+    }
+
+
     std::string getline( std::istream & str, const Trim trim_r )
     {
       return trim( receiveUpTo( str, '\n' ), trim_r );
index 5477fca..40b6413 100644 (file)
@@ -895,6 +895,15 @@ namespace zypp
           str_r += escape( next_r, sep_r );
       }
 
+      /** Return \a str_r with '\'-escaped chars occurring in \a special_r (and '\'). */
+      std::string bEscape( std::string str_r, const C_Str & special_r );
+
+      /** Escape plain STRING \a str_r for use in a regex (not anchored by "^" or "$"). */
+      std::string rxEscapeStr( std::string str_r );
+
+      /** Escape GLOB \a str_r for use in a regex (not anchored by "^" or "$"). */
+      std::string rxEscapeGlob( std::string str_r );
+
       //! \todo unsecape()
 
     //@}
index fcb9f09..171171e 100644 (file)
@@ -39,7 +39,7 @@ namespace zypp
     void MediaPlugin::releaseFrom( const std::string & ejectDev_r )
     {}
 
-    void MediaPlugin::getFile(const Pathname & filename_r , const ByteCount expectedFileSize_r) const
+    void MediaPlugin::getFile(const Pathname & filename_r , const ByteCount expectedFileSize_r) const
     {}
 
     void MediaPlugin::getDir( const Pathname & dirname_r, bool recurse_r ) const
index fd47dc9..c48ceb8 100644 (file)
@@ -36,7 +36,7 @@ namespace zypp
       protected:
        virtual void attachTo( bool next_r = false );
        virtual void releaseFrom( const std::string & ejectDev_r );
-       virtual void getFile( const Pathname & filename_r, const ByteCount expectedFileSize_r ) const;
+       virtual void getFile( const Pathname & filename_r, const ByteCount &expectedFileSize_r ) const;
        virtual void getDir( const Pathname & dirname_r, bool recurse_r ) const;
        virtual void getDirInfo( std::list<std::string> & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const;
        virtual void getDirInfo( filesystem::DirContent & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const;
index e42d88d..cf34ba1 100644 (file)
@@ -285,7 +285,6 @@ class  HelixControl {
                  const target::Modalias::ModaliasList & modaliasList,
                  const std::set<std::string> & multiversionSpec,
                  const std::string & systemPath);
-    HelixControl ();
     ~HelixControl ();
 
     void closeSetup()
@@ -394,12 +393,6 @@ HelixControl::HelixControl(const std::string & controlPath,
     // setup continued outside....
 }
 
-HelixControl::HelixControl()
-    :dumpFile ("/var/log/YaST2/solverTestcase/solver-test.xml")
-{
-    HelixControl (dumpFile);
-}
-
 HelixControl::~HelixControl()
 {
     closeSetup();      // in case it is still open