Imported Upstream version 14.36.0 25/94625/1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 1 Nov 2016 01:32:25 +0000 (10:32 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 1 Nov 2016 01:32:26 +0000 (10:32 +0900)
Change-Id: Icb6874870214a5dd9871a97ad40d74099f613fd8
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
20 files changed:
TODO [deleted file]
VERSION.cmake
package/libzypp.changes
po/createPot
po/zypp-po.tar.bz2
tests/repo/RepoVariables_test.cc
zypp/CMakeLists.txt
zypp/KeyRing.cc
zypp/PublicKey.cc
zypp/RepoInfo.h
zypp/RepoManager.h
zypp/ServiceInfo.h
zypp/base/Regex.cc
zypp/base/Regex.h
zypp/base/TypeTraits.h [new file with mode: 0644]
zypp/base/ValueTransform.h [new file with mode: 0644]
zypp/repo/RepoInfoBase.h
zypp/repo/RepoVariables.cc
zypp/repo/RepoVariables.h
zypp/target/RpmPostTransCollector.cc

diff --git a/TODO b/TODO
deleted file mode 100644 (file)
index c4378d6..0000000
--- a/TODO
+++ /dev/null
@@ -1,9 +0,0 @@
-
-API Cleanups:
-=============
-
-Source.h
-- remove const from return types:
-  ie: const Pathname providePackage( Package::constPtr package );
-- pass by reference
-  resolvables(zypp::Resolvable::Kind kind) const;
index 3820e38..336f9b5 100644 (file)
@@ -60,9 +60,9 @@
 #
 SET(LIBZYPP_MAJOR "14")
 SET(LIBZYPP_COMPATMINOR "30")
-SET(LIBZYPP_MINOR "35")
+SET(LIBZYPP_MINOR "36")
 SET(LIBZYPP_PATCH "0")
 #
-# LAST RELEASED: 14.35.0 (30)
+# LAST RELEASED: 14.36.0 (30)
 # (The number in parenthesis is LIBZYPP_COMPATMINOR)
 #=======
index cd3824e..b8ab72c 100644 (file)
@@ -1,4 +1,39 @@
 -------------------------------------------------------------------
+Mon Feb  9 16:05:38 CET 2015 - ma@suse.de
+
+- Don't execute scripts in /tmp or /var/tmp, as they could be 
+  mounted noexec for security reasons (bnc#915928)
+- zypp/PublicKey.cc: Use GPG_BINARY from KeyRing
+- Support $releasever_major/$releasever_minor repo variables 
+  (FATE#318354)
+- version 14.36.0 (30)
+
+-------------------------------------------------------------------
+Sun Feb  8 01:13:14 CET 2015 - ma@suse.de
+
+- Update zypp-po.tar.bz2
+
+-------------------------------------------------------------------
+Thu Feb  5 01:13:27 CET 2015 - ma@suse.de
+
+- Update zypp-po.tar.bz2
+
+-------------------------------------------------------------------
+Sun Feb  1 01:13:10 CET 2015 - ma@suse.de
+
+- Update zypp-po.tar.bz2
+
+-------------------------------------------------------------------
+Thu Jan 29 01:13:12 CET 2015 - ma@suse.de
+
+- Update zypp-po.tar.bz2
+
+-------------------------------------------------------------------
+Thu Jan 22 01:13:36 CET 2015 - ma@suse.de
+
+- Update zypp-po.tar.bz2
+
+-------------------------------------------------------------------
 Wed Jan 21 10:28:49 CET 2015 - ma@suse.de
 
 - PathInfo: Deprecate major/minor in favor of new devMajor/devMinor.
index 4629c23..f8ef2a9 100755 (executable)
@@ -10,4 +10,4 @@ SRCFILES=`find examples tools zypp \
                                 -o -name "*.cc"  \
                                 -o -name "*.cpp"`
 #calling xgettext with the sourcefiles
-xgettext -L C++ --boost -s --no-wrap --add-comments --add-location --keyword=_ --keyword=_:1,2 --keyword=__ --keyword=N_ --foreign-user --copyright-holder="SuSE Linux Products GmbH, Nuernberg" --default-domain=libzypp --output="$POTFILE" $SRCFILES
+xgettext -L C++ --boost -s --no-wrap --add-comments --add-location --keyword=_ --keyword=_:1,2 --keyword=__ --keyword=N_ --foreign-user --copyright-holder="SuSE Linux GmbH, Nuernberg" --package-name=libzypp --default-domain=libzypp --output="$POTFILE" $SRCFILES
index 07c62ea..d1eff8e 100644 (file)
Binary files a/po/zypp-po.tar.bz2 and b/po/zypp-po.tar.bz2 differ
index 0eb0c78..9ca2400 100644 (file)
@@ -10,6 +10,7 @@
 #include "zypp/PathInfo.h"
 #include "zypp/TmpPath.h"
 #include "zypp/ZConfig.h"
+#include "zypp/base/ValueTransform.h"
 #include "zypp/repo/RepoVariables.h"
 
 using std::cout;
@@ -21,14 +22,92 @@ using namespace zypp::repo;
 
 #define DATADIR (Pathname(TESTS_SRC_DIR) +  "/repo/yum/data")
 
+typedef std::list<std::string> ListType;
+
+namespace std {
+  std::ostream & operator<<( std::ostream & str, const ListType & obj )
+  {
+    str << "[";
+    for ( const auto & el : obj )
+      str << " " << el;
+    return str << " ]";
+  }
+}
+
+// plain functor
+struct PlainTransformator
+{
+  std::string operator()( const std::string & value_r ) const
+  { return "{"+value_r+"}"; }
+};
+
+// plain functor + std::unary_function typedefs
+struct FncTransformator : public PlainTransformator, public std::unary_function<const std::string &, std::string>
+{};
+
+
+BOOST_AUTO_TEST_CASE(value_transform)
+{
+  using zypp::base::ValueTransform;
+  using zypp::base::ContainerTransform;
+
+  typedef ValueTransform<std::string, FncTransformator> ReplacedString;
+  typedef ContainerTransform<ListType, FncTransformator> ReplacedStringList;
+
+  ReplacedString r( "val" );
+  BOOST_CHECK_EQUAL( r.raw(), "val" );
+  BOOST_CHECK_EQUAL( r.transformed(),  "{val}" );
+
+  r.raw() = "new";
+  BOOST_CHECK_EQUAL( r.raw(), "new" );
+  BOOST_CHECK_EQUAL( r.transformed(),  "{new}" );
+
+  ReplacedStringList rl;
+  BOOST_CHECK_EQUAL( rl.empty(), true );
+  BOOST_CHECK_EQUAL( rl.size(), 0 );
+  BOOST_CHECK_EQUAL( rl.raw(), ListType() );
+  BOOST_CHECK_EQUAL( rl.transformed(), ListType() );
+
+  rl.raw().push_back("a");
+  rl.raw().push_back("b");
+  rl.raw().push_back("c");
+
+  BOOST_CHECK_EQUAL( rl.empty(), false );
+  BOOST_CHECK_EQUAL( rl.size(), 3 );
+  BOOST_CHECK_EQUAL( rl.raw(), ListType({ "a","b","c" }) );
+  BOOST_CHECK_EQUAL( rl.transformed(), ListType({ "{a}", "{b}", "{c}" }) );
+
+  BOOST_CHECK_EQUAL( rl.transformed( rl.rawBegin() ), "{a}" );
+}
+
 BOOST_AUTO_TEST_CASE(replace_text)
 {
   /* check RepoVariablesStringReplacer */
   ZConfig::instance().setSystemArchitecture(Arch("i686"));
+  ::setenv( "ZYPP_REPO_RELEASEVER", "13.2", 1 );
 
   RepoVariablesStringReplacer replacer1;
-  BOOST_CHECK_EQUAL(replacer1("http://foo/$arch/bar"),
-                    "http://foo/i686/bar");
+  BOOST_CHECK_EQUAL( replacer1(""),            "" );
+  BOOST_CHECK_EQUAL( replacer1("$"),           "$" );
+  BOOST_CHECK_EQUAL( replacer1("$arc"),                "$arc" );
+  BOOST_CHECK_EQUAL( replacer1("$arch"),       "i686" );
+
+  BOOST_CHECK_EQUAL( replacer1("$archit"),     "$archit" );
+  BOOST_CHECK_EQUAL( replacer1("${rc}it"),     "${rc}it" );
+  BOOST_CHECK_EQUAL( replacer1("$arch_it"),    "$arch_it" );
+
+  BOOST_CHECK_EQUAL( replacer1("$arch-it"),    "i686-it" );
+  BOOST_CHECK_EQUAL( replacer1("$arch it"),    "i686 it" );
+  BOOST_CHECK_EQUAL( replacer1("${arch}it"),   "i686it" );
+
+  BOOST_CHECK_EQUAL( replacer1("${arch}it$archit $arch"),      "i686it$archit i686" );
+  BOOST_CHECK_EQUAL( replacer1("X${arch}it$archit $arch-it"),  "Xi686it$archit i686-it" );
+
+  BOOST_CHECK_EQUAL( replacer1("${releasever}"),       "13.2" );
+  BOOST_CHECK_EQUAL( replacer1("${releasever_major}"), "13" );
+  BOOST_CHECK_EQUAL( replacer1("${releasever_minor}"), "2" );
+
+  BOOST_CHECK_EQUAL(replacer1("http://foo/$arch/bar"), "http://foo/i686/bar");
 
   /* check RepoVariablesUrlReplacer */
   RepoVariablesUrlReplacer replacer2;
@@ -42,23 +121,8 @@ BOOST_AUTO_TEST_CASE(replace_text)
   BOOST_CHECK_EQUAL(replacer2(Url("http://site.org/update/?arch=$arch")).asCompleteString(),
                    "http://site.org/update/?arch=i686");
 
-  // now we initialize the target
-  filesystem::TmpDir tmp;
-
-  ZYpp::Ptr z = getZYpp();
-
-  // create the products.d directory
-  assert_dir(tmp.path() / "/etc/products.d" );
-  BOOST_CHECK( copy( Pathname(TESTS_SRC_DIR) / "/zypp/data/Target/product.prod",  tmp.path() / "/etc/products.d/product.prod") == 0 );
-  // make it the base product
-  BOOST_CHECK( symlink(tmp.path() / "/etc/products.d/product.prod", tmp.path() / "/etc/products.d/baseproduct" ) == 0 );
-
-  z->initializeTarget( tmp.path() );
-  // target activated, there should be replacement of
-  // $distver
   BOOST_CHECK_EQUAL(replacer2(Url("http://site.org/update/$releasever/?arch=$arch")).asCompleteString(),
-                   "http://site.org/update/10/?arch=i686");
-
+                   "http://site.org/update/13.2/?arch=i686");
 }
 
 // vim: set ts=2 sts=2 sw=2 ai et:
index 9bd803d..76e119a 100644 (file)
@@ -264,7 +264,9 @@ SET( zypp_base_HEADERS
   base/Regex.h
   base/Sysconfig.h
   base/Tr1hash.h
+  base/TypeTraits.h
   base/Unit.h
+  base/ValueTransform.h
   base/WatchFile.h
   base/Xml.h
 )
index 13cae3d..3523b45 100644 (file)
@@ -37,6 +37,7 @@ using std::endl;
 #undef  ZYPP_BASE_LOGGER_LOGGROUP
 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing"
 
+/** \todo Fix duplicate define in PublicKey/KeyRing */
 #define GPG_BINARY "/usr/bin/gpg2"
 
 ///////////////////////////////////////////////////////////////////
index 4d3d773..fc7435b 100644 (file)
@@ -28,6 +28,9 @@
 
 #include <ctime>
 
+/** \todo Fix duplicate define in PublicKey/KeyRing */
+#define GPG_BINARY "/usr/bin/gpg2"
+
 using std::endl;
 
 ///////////////////////////////////////////////////////////////////
@@ -349,7 +352,7 @@ namespace zypp
         static filesystem::TmpDir dir;
         const char* argv[] =
         {
-          "gpg",
+          GPG_BINARY,
           "-v",
           "--no-default-keyring",
           "--fixed-list-mode",
index b757edb..4d69974 100644 (file)
@@ -400,9 +400,6 @@ namespace zypp
        */
       virtual std::ostream & dumpAsXmlOn( std::ostream & str, const std::string & content = "" ) const;
 
-      /** \deprecated Use camel cased dumpAsXmlOn */
-      ZYPP_DEPRECATED std::ostream & dumpAsXMLOn( std::ostream & str, const std::string & content = "" ) const { return dumpAsXmlOn( str, content ); }
-
       class Impl;
     private:
       /** Pointer to implementation */
index 8717b9f..5653939 100644 (file)
@@ -88,11 +88,7 @@ namespace zypp
      * Target distro ID to be used when refreshing repo index services.
      * Repositories not maching this ID will be skipped/removed.
      *
-     * The value is initialized upon construction to
-     * \ref Target::targetDistribution() if the Target is already initialized,
-     * otherwise the value is initially empty.
-     *
-     * If empty, no repositories contained in the index will be skipped.
+     * If empty, \ref Target::targetDistribution() will be used instead.
      */
     std::string servicesTargetDistro;
 
index d40ad8a..ac5cf44 100644 (file)
@@ -188,9 +188,6 @@ namespace zypp
      */
     virtual std::ostream & dumpAsXmlOn( std::ostream & str, const std::string & content = "" ) const;
 
-    /** \deprecated Use camel cased dumpAsXmlOn */
-    ZYPP_DEPRECATED std::ostream & dumpAsXMLOn( std::ostream & str, const std::string & content = "" ) const { return dumpAsXmlOn( str, content ); }
-
     class Impl;
 
   private:
index 13adc4f..3ce92cc 100644 (file)
@@ -83,6 +83,14 @@ std::string smatch::operator[](unsigned i) const
   return std::string();
 }
 
+std::string::size_type smatch::begin( unsigned i ) const
+{ return( i < sizeof(pmatch)/sizeof(*pmatch) && pmatch[i].rm_so != -1 ? pmatch[i].rm_so : std::string::npos ); }
+
+std::string::size_type smatch::end( unsigned i ) const
+{ return( i < sizeof(pmatch)/sizeof(*pmatch) && pmatch[i].rm_so != -1 ? pmatch[i].rm_eo : std::string::npos ); }
+
+std::string::size_type smatch::size( unsigned i ) const
+{ return( i < sizeof(pmatch)/sizeof(*pmatch) && pmatch[i].rm_so != -1 ? pmatch[i].rm_eo-pmatch[i].rm_so : std::string::npos ); }
 
 unsigned smatch::size() const
 {
index f66f07b..00b2ca2 100644 (file)
@@ -151,6 +151,15 @@ namespace zypp
 
       unsigned size() const;
 
+      /** Begin index of subexpression \c i in \a match_str (or std::string::npos) */
+      std::string::size_type begin( unsigned i ) const;
+
+      /** End index of subexpression \c i in \a match_str (or std::string::npos) */
+      std::string::size_type end( unsigned i ) const;
+
+      /** Size of subexpression \c i (or std::string::npos) */
+      std::string::size_type size( unsigned i ) const;
+
       std::string match_str;
       regmatch_t pmatch[12];
     };
diff --git a/zypp/base/TypeTraits.h b/zypp/base/TypeTraits.h
new file mode 100644 (file)
index 0000000..4360470
--- /dev/null
@@ -0,0 +1,74 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/base/TypeTraits.h
+ */
+#ifndef ZYPP_TYPETRAITS_H
+#define ZYPP_TYPETRAITS_H
+
+#include <type_traits>
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{
+  ///////////////////////////////////////////////////////////////////
+  namespace _detail
+  {
+    template<typename _Tp>
+    struct _has_type_const_iterator
+    {
+    private:
+      template<typename C> static std::true_type  test( typename C::const_iterator * );
+      template<typename C> static std::false_type test(...);
+    public:
+      static constexpr bool value = decltype(test<_Tp>(nullptr))::value;
+    };
+
+    template <typename _Tp>
+    struct _has_container_begin_end
+    {
+    private:
+      template <typename C>
+      using Signature = typename C::const_iterator(C::*)() const;
+
+      template<typename C> static std::true_type  testBeg( typename std::enable_if<std::is_same<decltype(static_cast<Signature<C>>(&C::begin)), Signature<C>>::value, void>::type* );
+      template<typename C> static std::false_type testBeg(...);
+
+      template<typename C> static std::true_type  testEnd( typename std::enable_if<std::is_same<decltype(static_cast<Signature<C>>(&C::end)), Signature<C>>::value,   void>::type* );
+      template<typename C> static std::false_type testEnd(...);
+
+    public:
+      static constexpr bool beg_value = decltype(testBeg<_Tp>(nullptr))::value;
+      static constexpr bool end_value = decltype(testEnd<_Tp>(nullptr))::value;
+      static constexpr bool value = beg_value && end_value;
+    };
+  } // namespace _detail
+  ///////////////////////////////////////////////////////////////////
+
+  /** Whether \a _Tp defines type \a _Tp::const_iterator */
+  template<typename _Tp>
+  struct has_type_const_iterator
+  : public std::integral_constant<bool, _detail::has_type_const_iterator<_Tp>::value>
+  {};
+
+  /** Whether \a _Tp defines methods <tt>_Tp::const_iterator begin/end() const</tt> */
+  template<typename _Tp>
+  struct has_container_begin_end
+  : public std::integral_constant<bool, _detail::_has_container_begin_end<_Tp>::value>
+  {};
+
+  /** Whether \a _Tp is a container (begin/end iterabel, but not plain std::string) */
+  template<typename _Tp>
+  struct is_container
+  : public std::integral_constant<bool, !std::is_same<_Tp, std::string>::value && has_container_begin_end<_Tp>::value>
+  {};
+
+
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_TYPETRAITS_H
diff --git a/zypp/base/ValueTransform.h b/zypp/base/ValueTransform.h
new file mode 100644 (file)
index 0000000..13543ba
--- /dev/null
@@ -0,0 +1,168 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/base/ValueTransform.h
+ */
+#ifndef ZYPP_BASE_VALUETRANSFORM_H
+#define ZYPP_BASE_VALUETRANSFORM_H
+
+#include <iosfwd>
+
+#include "zypp/base/Iterator.h"
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{
+  ///////////////////////////////////////////////////////////////////
+  namespace base
+  {
+    ///////////////////////////////////////////////////////////////////
+    /// \class ValueTransform<_Tp,_UnaryFunction>
+    /// \brief Helper managing raw values with transformed representation
+    ///
+    /// This helper enforces to explicitly state wheter you are using
+    /// the raw or the variable replaced value. Usually you set \c raw
+    /// and get \c transformed (uness writing \c raw to some config file).
+    ///
+    /// Used e.g. vor variable replaced config strings.
+    ///////////////////////////////////////////////////////////////////
+    template<class _Tp, class _UnaryFunction>
+    struct ValueTransform
+    {
+      typedef _Tp RawType;
+      typedef _UnaryFunction Transformator;
+      typedef typename Transformator::result_type TransformedType;
+
+    public:
+      ValueTransform()
+      {}
+
+      explicit ValueTransform( RawType raw_r )
+      : _raw( std::move(raw_r) )
+      {}
+
+      ValueTransform( RawType raw_r, Transformator transform_r )
+      : _raw( std::move(raw_r) ), _transform( std::move(transform_r) )
+      {}
+
+    public:
+      /** Get the raw value */
+      const RawType & raw() const
+      { return _raw; }
+
+      /** Set the raw value */
+      RawType & raw()
+      { return _raw; }
+
+    public:
+      /** Return a transformed copy of the raw value */
+      TransformedType transformed() const
+      { return _transform( _raw ); }
+
+      /** Return a transformed copy of an arbitrary \a RawType */
+      TransformedType transformed( const RawType & raw_r ) const
+      { return _transform( raw_r ); }
+
+      /** Return the transformator */
+      const Transformator & transformator() const
+      { return _transform; }
+
+    private:
+      RawType _raw;
+      Transformator _transform;
+    };
+
+    ///////////////////////////////////////////////////////////////////
+    /// \class ContainerTransform<_Container,_UnaryFunction>
+    /// \brief Helper managing a container of raw values with transformed representation
+    ///
+    /// This helper enforces to explicitly state wheter you are using
+    /// the raw or the variable replaced value. Usually you set \c raw
+    /// and get \c transformed (uness writing \c raw to some config file).
+    ///
+    /// Offers iterating over transformed strings in the list.
+    ///////////////////////////////////////////////////////////////////
+    template<class _Container, class _UnaryFunction>
+    struct ContainerTransform
+    {
+      typedef _Container Container;
+      typedef _UnaryFunction Transformator;
+      typedef typename Container::size_type size_type;
+      typedef typename Container::value_type RawType;
+      typedef typename Transformator::result_type TransformedType;
+
+    public:
+      ContainerTransform()
+      {}
+
+      explicit ContainerTransform( Container raw_r )
+      : _raw( std::move(raw_r) )
+      {}
+
+      ContainerTransform( Container raw_r, Transformator transform_r )
+      : _raw( std::move(raw_r) ), _transform( std::move(transform_r) )
+      {}
+
+    public:
+      bool empty() const
+      { return _raw.empty(); }
+
+      size_type size() const
+      { return _raw.size(); }
+
+      typedef typename Container::const_iterator RawConstIterator;
+
+      RawConstIterator rawBegin() const
+      { return _raw.begin(); }
+
+      RawConstIterator rawEnd() const
+      { return _raw.end(); }
+
+      /** Get the raw value */
+      const Container & raw() const
+      { return _raw; }
+
+      /** Set the raw value */
+      Container & raw()
+      { return _raw; }
+
+    public:
+      typedef transform_iterator<Transformator, typename Container::const_iterator> TransformedConstIterator;
+
+      TransformedConstIterator transformedBegin() const
+      { return make_transform_iterator( _raw.begin(), _transform ); }
+
+      TransformedConstIterator transformedEnd() const
+      { return make_transform_iterator( _raw.end(), _transform ); }
+
+      /** Return copy with transformed variables (expensive) */
+      Container transformed() const
+      { return Container( transformedBegin(), transformedEnd() ); }
+
+      /** Return a transformed copy of an arbitrary \a RawType */
+      TransformedType transformed( const RawType & raw_r ) const
+      { return _transform( raw_r ); }
+
+      /** Return a transformed copy of a \a RawConstIterator raw value */
+      TransformedType transformed( const RawConstIterator & rawIter_r ) const
+      { return _transform( *rawIter_r ); }
+
+      /** Return the transformator */
+      const Transformator & transformator() const
+      { return _transform; }
+
+    private:
+      Container _raw;
+      Transformator _transform;
+    };
+
+  } // namespace base
+  ///////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_BASE_VALUETRANSFORM_H
index a3dfd49..e31ff59 100644 (file)
@@ -157,9 +157,6 @@ namespace zypp
        */
       virtual std::ostream & dumpAsXmlOn( std::ostream & str, const std::string & content = "" ) const;
 
-      /** \deprecated Use camel cased dumpAsXmlOn */
-      ZYPP_DEPRECATED std::ostream & dumpAsXMLOn( std::ostream & str, const std::string & content = "" ) const { return dumpAsXmlOn( str, content ); }
-
       class Impl;
     private:
       /** Pointer to implementation */
index f4edc87..f70e3d6 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "zypp/base/LogTools.h"
 #include "zypp/base/String.h"
+#include "zypp/base/Regex.h"
 
 #include "zypp/ZConfig.h"
 #include "zypp/Target.h"
@@ -39,63 +40,137 @@ namespace zypp
        */
       struct ReplacerData : private zypp::base::NonCopyable
       {
-       const std::string & sysarch() const
+       typedef const std::string & (ReplacerData::*Getter)() const;
+
+       const std::string & arch() const
        {
-         if ( _sysarch.empty() )
-           initArchStr();
-         return _sysarch;
+         assertArchStr();
+         return _arch;
        }
 
        const std::string & basearch() const
        {
-         if ( _basearch.empty() )
-           initArchStr();
+         assertArchStr();
          return _basearch;
        }
 
        const std::string & releasever() const
        {
-         if( _releasever.empty() )
+         assertReleaseverStr();
+         return _releasever;
+       }
+
+       const std::string & releaseverMajor() const
+       {
+         assertReleaseverStr();
+         return _releaseverMajor;
+       }
+
+       const std::string & releaseverMinor() const
+       {
+         assertReleaseverStr();
+         return _releaseverMinor;
+       }
+
+      private:
+       void assertArchStr() const
+       {
+         if ( _arch.empty() )
+         {
+           Arch arch( ZConfig::instance().systemArchitecture() );
+           _arch = arch.asString();
+           _basearch = arch.baseArch().asString();
+         }
+       }
+       void assertReleaseverStr() const
+       {
+         if ( _releasever.empty() )
          {
            _releasever = env::ZYPP_REPO_RELEASEVER();
            if( _releasever.empty() )
              _releasever = Target::distributionVersion( Pathname()/*guess*/ );
            else
              WAR << "ENV overwrites $releasever=" << _releasever << endl;
-         }
-         return _releasever;
-       }
 
-      private:
-       void initArchStr() const
-       {
-         Arch arch( ZConfig::instance().systemArchitecture() );
-         _sysarch = arch.asString();
-         _basearch = arch.baseArch().asString();
+           // split major/minor for SLE
+           std::string::size_type pos = _releasever.find( "." );
+           if ( pos == std::string::npos )
+           {
+             _releaseverMajor = _releasever;
+             _releaseverMinor.clear();
+           }
+           else
+           {
+             _releaseverMajor = _releasever.substr( 0, pos );
+             _releaseverMinor = _releasever.substr( pos+1 ) ;
+           }
+         }
        }
       private:
-       mutable std::string _sysarch;
+       mutable std::string _arch;
        mutable std::string _basearch;
        mutable std::string _releasever;
+       mutable std::string _releaseverMajor;
+       mutable std::string _releaseverMinor;
       };
 
-      /** \brief Replace repo variables on demand
+     /** \brief Replace repo variables on demand
        *
        * Initialisation of repo variables is delayed until they actually occur in
        * a string.
        */
-      std::string replacer( const std::string & value_r )
+      std::string replacer( std::string value_r )
       {
-       static ReplacerData _data;
+       std::string ret;
+       if ( ! value_r.empty() )
+       {
+         static const str::regex rxVAR( "^([^$]*)\\$(\\{[[:alnum:]_]+\\}|[[:alnum:]_]+)([^$]*)" );
+         str::smatch what;
+         while ( str::regex_match( value_r, what, rxVAR ) )
+         {
+           ReplacerData::Getter getter = nullptr;
 
-       std::string ret( value_r );
-       // Don't need to capture static (non automatic) _data in lambda
-       ret = str::replaceAllFun( ret, "$arch",         []()-> std::string { return _data.sysarch(); } );
-       ret = str::replaceAllFun( ret, "$basearch",     []()-> std::string { return _data.basearch(); } );
-       ret = str::replaceAllFun( ret, "$releasever",   []()-> std::string { return _data.releasever(); } );
+           const char * varStart = value_r.c_str() + what.begin( 2 );
+           std::string::size_type varSize = what.size( 2 );
+           if ( *varStart == '{' )     // enclosed in {}
+           {
+             ++varStart;
+             varSize -= 2;
+           }
+
+           switch ( varSize )
+           {
+#define ASSIGN_IF(NAME,GETTER) if ( ::strncmp( varStart, NAME, varSize ) == 0 ) getter = GETTER
+
+             case  4:  ASSIGN_IF( "arch",              &ReplacerData::arch );                  break;
+             case  8:  ASSIGN_IF( "basearch",          &ReplacerData::basearch );              break;
+             case 10:  ASSIGN_IF( "releasever",        &ReplacerData::releasever );            break;
+             case 16:  ASSIGN_IF( "releasever_major",  &ReplacerData::releaseverMajor );
+                  else ASSIGN_IF( "releasever_minor",  &ReplacerData::releaseverMinor );       break;
+#undef ASSIGN_IF
+           }
+
+           if ( getter )       // known var?
+           {
+             static const ReplacerData _data;
+             if ( what.size( 1 ) > 0 ) ret += what[1]; // pre
+             ret += (_data.*getter)();                 // var
+             if ( what.size( 3 ) > 0 ) ret += what[3]; // post
+           }
+           else
+           {
+             ret += what[0];   // unchanged
+           }
+
+           value_r.erase( 0, what.size( 0 ) );
+           if ( value_r.empty() )
+             break;
+         }
+         if ( ! value_r.empty() )
+           ret += std::move(value_r);          // no match
+       }
        return ret;
       }
-
     } // namespace
     ///////////////////////////////////////////////////////////////////
 
index a5c7efa..895764a 100644 (file)
@@ -26,6 +26,10 @@ namespace zypp
      * Replaces '$arch', '$basearch' and $releasever in a string
      * with the global ZYpp values.
      *
+     * Additionally $releasever_major and $releasever_minor can be used
+     * to refer to $releasever major number (everything up to the 1st \c '.' )
+     * and minor number (everything after the 1st \c '.' ).
+     *
      * \note The $releasever value is overwritten by the environment
      * variable \c ZYPP_REPO_RELEASEVER. This might  be handy for
      * distribution upogrades like this:
@@ -35,6 +39,12 @@ namespace zypp
      *   $ zypper dup
      *   ....upgrades to 13.2...
      * \endcode
+     * The same can be achieved by using zyppers --releasever global option:
+     * \code
+     *   $ zypper --releasever 13.2 lr -u
+     *   $ zypper --releasever 13.2 dup
+     *   ....upgrades to 13.2...
+     * \endcode
      * (see \ref zypp-envars)
      *
      * \code
index 14ceab8..73f7e89 100644 (file)
@@ -63,7 +63,7 @@ namespace zypp
          script.autoCleanup( false );  // no autodelete; within a tmpdir
          {
            std::ofstream out( script.path().c_str() );
-           out << "# " << pkg->tag_posttransprog() << endl
+           out << "#! " << pkg->tag_posttransprog() << endl
                << pkg->tag_posttrans() << endl;
          }
          _scripts.push_back( script.path().basename() );
@@ -81,7 +81,7 @@ namespace zypp
 
          HistoryLog historylog;
 
-         Pathname noRootScriptDir( filesystem::TmpDir::defaultLocation() / tmpDir().basename() );
+         Pathname noRootScriptDir( ZConfig::instance().update_scriptsPath() / tmpDir().basename() );
 
          for ( auto && script : _scripts )
          {
@@ -149,7 +149,7 @@ namespace zypp
        /** Lazy create tmpdir on demand. */
        Pathname tmpDir()
        {
-         if ( !_ptrTmpdir ) _ptrTmpdir.reset( new filesystem::TmpDir( _root / filesystem::TmpDir::defaultLocation(), "posttrans" ) );
+         if ( !_ptrTmpdir ) _ptrTmpdir.reset( new filesystem::TmpDir( _root / ZConfig::instance().update_scriptsPath(), "posttrans" ) );
          DBG << _ptrTmpdir->path() << endl;
          return _ptrTmpdir->path();
        }