Imported Upstream version 1.11.32 62/109362/1 upstream/1.11.32
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Jan 2017 05:25:47 +0000 (14:25 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 10 Jan 2017 05:25:48 +0000 (14:25 +0900)
Change-Id: I74aaeeed41a4ded49b0fbf46c1e4de764f73737f
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
18 files changed:
VERSION.cmake
doc/zypp-refresh.8
doc/zypp-refresh.8.txt
doc/zypper-log.8
doc/zypper-log.8.txt
doc/zypper.8
doc/zypper.8.txt
package/zypper.changes
src/Config.cc
src/callbacks/repo.h
src/download.cc
src/output/Out.h
src/repos.cc
src/utils/Augeas.cc
src/utils/misc.cc
src/utils/misc.h
zypper.conf
zypper.spec.cmake

index 6fa91a0..440c5b9 100644 (file)
@@ -34,7 +34,7 @@
 #
 SET(VERSION_MAJOR "1")
 SET(VERSION_MINOR "11")
-SET(VERSION_PATCH "31")
+SET(VERSION_PATCH "32")
 
-# LAST RELEASED: 1.11.31
+# LAST RELEASED: 1.11.32
 #=======
index 7e7f278..219b48e 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: zypp-refresh
 .\"    Author: [see the "AUTHORS" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 10/27/2014
+.\"      Date: 06/12/2015
 .\"    Manual: ZYPPER
-.\"    Source: zypp-refresh
+.\"    Source: SUSE Linux
 .\"  Language: English
 .\"
-.TH "ZYPP\-REFRESH" "8" "10/27/2014" "zypp\-refresh" "ZYPPER"
+.TH "ZYPP\-REFRESH" "8" "06/12/2015" "SUSE Linux" "ZYPPER"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
index 07e679d..80c97be 100644 (file)
@@ -1,7 +1,7 @@
-zypp-refresh(8)
+ZYPP-REFRESH(8)
 =============
 :man manual: ZYPPER
-:man source: zypp-refresh
+:man source: SUSE Linux
 
 
 NAME
index e62cb25..3493d2a 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: zypper-log
 .\"    Author: [see the "AUTHORS" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 12/15/2014
+.\"      Date: 06/12/2015
 .\"    Manual: ZYPPER
-.\"    Source: zypper-log
+.\"    Source: SUSE Linux
 .\"  Language: English
 .\"
-.TH "ZYPPER\-LOG" "8" "12/15/2014" "zypper\-log" "ZYPPER"
+.TH "ZYPPER\-LOG" "8" "06/12/2015" "SUSE Linux" "ZYPPER"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -34,7 +34,7 @@ zypper-log \- Zypper logfile reader
 \fBzypper\-log\fR [\fIOPTIONS\fR] [\fIPID\fR]
 .SH "DESCRIPTION"
 .sp
-\fBzypper\-log\fR can read zypper's logfiles\&. It can also handle rotated logfiles, and will open plain, xz, gz and bz2\-compressed files\&.
+\fBzypper\-log\fR can read zypper\(cqs logfiles\&. It can also handle rotated logfiles, and will open plain, xz, gz and bz2\-compressed files\&.
 .sp
 By default \fB/var/log/zypper\&.log\fR will be read and a list of all \fBzypper\fR invocations is shown:
 .sp
index 093913b..7164415 100644 (file)
@@ -1,7 +1,7 @@
-zypper-log(8)
+ZYPPER-LOG(8)
 =============
 :man manual: ZYPPER
-:man source: zypper-log
+:man source: SUSE Linux
 
 
 NAME
index 33a32fc..a50ef48 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: zypper
 .\"    Author: [see the "AUTHORS" section]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 05/06/2015
+.\"      Date: 06/12/2015
 .\"    Manual: ZYPPER
-.\"    Source: zypper
+.\"    Source: SUSE Linux
 .\"  Language: English
 .\"
-.TH "ZYPPER" "8" "05/06/2015" "zypper" "ZYPPER"
+.TH "ZYPPER" "8" "06/12/2015" "SUSE Linux" "ZYPPER"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -45,6 +45,13 @@ Most of the following concepts are common for all applications based on the libz
 Libzypp works with package metadata, that is information about packages and their relations extracted from RPM packages and other data like patch information, pattern definitions, etc\&. These data are stored together with the RPM files in folders called \fIrepositories\fR\&. Repositories can be placed on various media like an HTTP or FTP server, DVD, or a folder on a local disc\&.
 .sp
 There is a special set of commands in zypper intended to manipulate repositories\&. Also many commands and options take a repository as an argument\&. See section \fBCOMMANDS\fR, subsection \fBRepository Management\fR for more details\&.
+.SS "GPG checks"
+.sp
+Zypp verifies the authenticity of repository metadata by checking their GPG signature\&. If the repository metadata are signed with a trusted key and and successfully verified, packages from that repository are accepted for installation if they match the checksum provided in the metadata\&. If the repository metadata are not signed, the signature of each downloaded rpm package is checked before accepting it for installation\&.
+.sp
+This default behavior can be tuned by explicitly setting the variables \fBrepo_gpgcheck\fR and/or \fBpkg_gpgcheck\fR in the ZYpp configuration file (\fB/etc/zypp/zypp\&.conf\fR) to perform those checks always (if \fIon\fR) or never (if \fIoff\fR)\&.
+.sp
+\fBDisabling GPG checks is not recommended\&.\fR Signing data enables the recipient to verify that no modifications occurred after the data were signed\&. Accepting data with no, wrong or unknown signature can lead to a corrupted system and in extreme cases even to a system compromise\&.
 .SS "Resource Identifiers (URI)"
 .sp
 To specify locations of repositories or other resources (RPM files, \&.repo files) you can use any type of URIs supported by libzypp\&. See section \fBCOMMANDS\fR, subsection \fBRepository Management\fR for a complete list and usage examples\&.
@@ -1708,6 +1715,52 @@ T}
 .TE
 .sp 1
 .RE
+.PP
+OpenSUSE Build Build Service (OBS) repositories
+.RS 4
+Zypper also accepts special URIs identifying openSUSE Build Service (OBS) repositories in the
+\fBaddrepo\fR
+command\&. These URIs have the form of
+\fBobs://\fR\fIproject\fR\fB/\fR[\fIplatform\fR], where
+\fIproject\fR
+is the name of the OBS project and
+\fIplatform\fR
+is the target platform (OS) for which the repository is intended\&.
+
+If
+\fIplatform\fR
+is omitted,
+\fBopenSUSE_$releasever\fR
+is used unless a value for
+\fBobs\&.platform\fR
+is defined in zypper\&.conf\&. If you are following
+\fBopenSUSE_Factory\fR
+or
+\fBopenSUSE_Tumbleweed\fR
+you may need to set these as your default platform\&. But we can only guess, how the directory containing the repository that fits your distribution is named on the server\&. In case of doubt you need to look up the right URL in a browser\&.
+.TS
+tab(:);
+lt lt
+lt lt
+lt lt.
+T{
+
+T}:T{
+\fBobs://zypp:Head/\fR
+T}
+T{
+
+T}:T{
+\fBobs://zypp:Head/openSUSE_Factory\fR
+T}
+T{
+
+T}:T{
+\fBobs://zypp:Head/openSUSE_Factory_Staging_Gcc49_standard\fR
+T}
+.TE
+.sp 1
+.RE
 .RE
 .SS ""
 .PP
@@ -1849,11 +1902,13 @@ The following data can be printed for each repository found on the system:
 \fIName\fR,
 \fIEnabled\fR
 (whether the repository is enabled),
+\fIGPG Check\fR
+(whether GPG check for repository metadata (\fBr\fR) and/or downloaded rpm packages (\fBp\fR) is enabled),
 \fIRefresh\fR
 (whether auto\-refresh is enabled for the repository),
 \fIPriority\fR,
 \fIType\fR
-(repository meta\-data type: rpm\-md, yast2, plaindir)\&. Which of the data is shown is determined by command line options listed below and the main\&.repoListColumns setting from zypper\&.conf\&. By default, #, Alias, Name, Enabled, and Refresh is shown\&.
+(repository meta\-data type: rpm\-md, yast2, plaindir)\&. Which of the data is shown is determined by command line options listed below and the main\&.repoListColumns setting from zypper\&.conf\&. By default, #, Alias, Name, Enabled, GPG Check and Refresh is shown\&.
 
 Repository number is a unique identifier of the repository in current set of repositories\&. If you add, remove or change a repository, the numbers may change\&. Keep that in mind when using the numbers with the repository handling commands\&. On the other hand, using the alias instead of the number is always safe\&.
 
@@ -2720,7 +2775,8 @@ Repository Options:
 .PP
 \fB\-\-no\-gpg\-checks\fR
 .RS 4
-Ignore GPG check failures and continue\&. If a GPG issue occurs when using this option zypper prints and logs a warning and automatically continues without interrupting the operation\&. Use this option with caution, as you can easily overlook security problems by using it\&.
+Ignore GPG check failures and continue\&. If a GPG issue occurs when using this option zypper prints and logs a warning and automatically continues without interrupting the operation\&. Use this option with caution, as you can easily overlook security problems by using it\&. (see section
+\fBGPG checks\fR)
 .RE
 .PP
 \fB\-\-gpg\-auto\-import\-keys\fR
index 760bb50..69b54a0 100644 (file)
@@ -1,7 +1,7 @@
-zypper(8)
+ZYPPER(8)
 =========
 :man manual: ZYPPER
-:man source: zypper
+:man source: SUSE Linux
 :nop:
 
 
@@ -32,6 +32,14 @@ Libzypp works with package metadata, that is information about packages and thei
 
 There is a special set of commands in zypper intended to manipulate repositories. Also many commands and options take a repository as an argument. See section *COMMANDS*, subsection *Repository Management* for more details.
 
+GPG checks
+~~~~~~~~~~
+Zypp verifies the authenticity of repository metadata by checking their GPG signature. If the repository metadata are signed with a trusted key and and successfully verified, packages from that repository are accepted for installation if they match the checksum provided in the metadata. If the repository metadata  are not signed, the signature of each downloaded rpm package is checked before accepting it for installation.
+
+This default behavior can be tuned by explicitly setting the variables *repo_gpgcheck* and/or *pkg_gpgcheck* in the ZYpp configuration file (*/etc/zypp/zypp.conf*) to perform those checks always (if 'on') or never (if 'off').
+
+*Disabling GPG checks is not recommended.* Signing data enables the recipient to verify that no modifications occurred after the data were signed. Accepting data with no, wrong or unknown signature can lead to a corrupted system and in extreme cases even to a system compromise.
+
 Resource Identifiers (URI)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 To specify locations of repositories or other resources (RPM files, .repo files) you can use any type of URIs supported by libzypp. See section *COMMANDS*, subsection *Repository Management* for a complete list and usage examples.
@@ -877,6 +885,15 @@ Supported URI formats:
                ;; *cifs://usern:passw@servername/share/path/on/the/share*'?workgroup=mygroup'
                ;; *cifs://servername/share/path/on/the/share*'?user=usern&pass=passw'
 
+       OpenSUSE Build Build Service (OBS) repositories:::
+               Zypper also accepts special URIs identifying openSUSE Build Service (OBS) repositories in the *addrepo* command. These URIs have the form of *obs://*'project'*/*['platform'], where 'project' is the name of the OBS project and 'platform' is the target platform (OS) for which the repository is intended.
+               +
+               If 'platform' is omitted, *openSUSE_$releasever* is used unless a value for *obs.platform* is defined in zypper.conf. If you are following *openSUSE_Factory* or *openSUSE_Tumbleweed* you may need to set these as your default platform. But we can only guess, how the directory containing the repository that fits your distribution is named on the server. In case of doubt you need to look up the right URL in a browser.
+[horizontal]
+               ;; *obs://zypp:Head/*
+               ;; *obs://zypp:Head/openSUSE_Factory*
+               ;; *obs://zypp:Head/openSUSE_Factory_Staging_Gcc49_standard*
+
 {nop}
 ~~~~~
 
@@ -944,7 +961,7 @@ Supported URI formats:
 *repos* (*lr*) ['options'] ['repo']...::
        List all defined repositories or show detailed information about those specified as arguments
        +
-       The following data can be printed for each repository found on the system: '#' (repository number), 'Alias' (unique identifier), 'Name', 'Enabled' (whether the repository is enabled), 'Refresh' (whether auto-refresh is enabled for the repository), 'Priority', 'Type' (repository meta-data type: rpm-md, yast2, plaindir). Which of the data is shown is determined by command line options listed below and the main.repoListColumns setting from zypper.conf. By default, #, Alias, Name, Enabled, and Refresh is shown.
+       The following data can be printed for each repository found on the system: '#' (repository number), 'Alias' (unique identifier), 'Name', 'Enabled' (whether the repository is enabled), 'GPG Check' (whether GPG check for repository metadata (*r*) and/or downloaded rpm packages (*p*) is enabled), 'Refresh' (whether auto-refresh is enabled for the repository), 'Priority', 'Type' (repository meta-data type: rpm-md, yast2, plaindir). Which of the data is shown is determined by command line options listed below and the main.repoListColumns setting from zypper.conf. By default, #, Alias, Name, Enabled, GPG Check and Refresh is shown.
        +
        Repository number is a unique identifier of the repository in current set of repositories. If you add, remove or change a repository, the numbers may change. Keep that in mind when using the numbers with the repository handling commands. On the other hand, using the alias instead of the number is always safe.
        +
@@ -1418,7 +1435,7 @@ GLOBAL OPTIONS
 Repository Options: :: {nop}
 
 *--no-gpg-checks*::
-       Ignore GPG check failures and continue. If a GPG issue occurs when using this option zypper prints and logs a warning and automatically continues without interrupting the operation. Use this option with caution, as you can easily overlook security problems by using it.
+       Ignore GPG check failures and continue. If a GPG issue occurs when using this option zypper prints and logs a warning and automatically continues without interrupting the operation. Use this option with caution, as you can easily overlook security problems by using it. (see section *GPG checks*)
 
 *--gpg-auto-import-keys*::
        If new repository signing key is found, do not ask what to do; trust and import it automatically. This option causes that the new key is imported also in non-interactive mode, where it would otherwise got rejected.
index c2d5b5b..01eec5c 100644 (file)
@@ -1,4 +1,17 @@
 -------------------------------------------------------------------
+Fri Jun 12 14:49:55 CEST 2015 - ma@suse.de
+
+- man: add section about GPG checks
+- repos/services: Show GPG Check status
+- Handle pkgGpgCheck callback (fate#314603)
+- BuildRequires:  libzypp-devel >= 14.39.0
+- download: fix wrong total (=0) counter in download message
+- download: actually abort on user request.
+- Clarify comment in zypper.conf (bnc#820693)
+- Fix format of sizes in output (bnc#897301)
+- version 1.11.32
+
+-------------------------------------------------------------------
 Tue Jun  2 19:52:45 CEST 2015 - ma@suse.de
 
 - Adapt enterprise product detection (bnc#933277)
index dae2c16..43c0a65 100644 (file)
@@ -186,7 +186,7 @@ Config::Config()
   , color_pkglistHighlight(true)
   , color_pkglistHighlightAttribute(ansi::Color::nocolor())
   , obs_baseUrl("http://download.opensuse.org/repositories/")
-  , obs_platform("openSUSE_Factory")
+  , obs_platform("")   // guess 
 {}
 
 void Config::read( const std::string & file )
index b4cf7fa..37cc658 100644 (file)
@@ -15,6 +15,7 @@
 #include <zypp/ZYppCallbacks.h>
 #include <zypp/Pathname.h>
 #include <zypp/Url.h>
+#include <zypp/target/rpm/RpmDb.h>
 
 #include "Zypper.h"
 #include "utils/prompt.h"
@@ -98,9 +99,9 @@ struct DownloadResolvableReportReceiver : public zypp::callback::ReceiveReport<z
                 << "/" << zypper_r.runtimeData().commit_pkgs_total << ")";
     if ( pkg_r )
     {
-      outstr_r.rhs << ", " << pkg_r->downloadSize().asString( 5 ) << " "
+      outstr_r.rhs << ", " << pkg_r->downloadSize().asString( 5, 3 ) << " "
                   // TranslatorExplanation %s is package size like "5.6 M"
-                  << boost::format(_("(%s unpacked)")) % pkg_r->installSize().asString( 5 );
+                  << boost::format(_("(%s unpacked)")) % pkg_r->installSize().asString( 5, 3 );
     }
   }
 
@@ -155,6 +156,95 @@ struct DownloadResolvableReportReceiver : public zypp::callback::ReceiveReport<z
     return action;
   }
 
+  virtual void pkgGpgCheck( const UserData & userData_r )
+  {
+    Zypper & zypper = *Zypper::instance();
+    // "Package"               Package::constPtr of the package
+    // "Localpath"             Pathname to downloaded package on disk
+    // "CheckPackageResult"    RpmDb::CheckPackageResult of signature check
+    // "CheckPackageDetail"    RpmDb::CheckPackageDetail logmessages of rpm signature check
+    //
+    //   Userdata accepted:
+    // "Action"                        DownloadResolvableReport::Action user advice how to behave on error (ABORT).
+    using target::rpm::RpmDb;
+    RpmDb::CheckPackageResult result           ( userData_r.get<RpmDb::CheckPackageResult>( "CheckPackageResult" ) );
+
+
+    if ( result == RpmDb::CHK_OK )     // quiet about good sigcheck unless verbose.
+    {
+      if ( zypper.out().verbosity() >= Out::HIGH )
+      {
+       const RpmDb::CheckPackageDetail & details       ( userData_r.get<RpmDb::CheckPackageDetail>( "CheckPackageDetail" ) );
+       if ( ! details.empty() )
+       {
+         zypper.out().info( details.begin()->second, Out::HIGH );
+       }
+      }
+      return;
+    }
+
+
+    // report problems in individual checks...
+    const Pathname & localpath                 ( userData_r.get<Pathname>( "Localpath" ) );
+    const std::string & rpmname                        ( localpath.basename() );
+    const RpmDb::CheckPackageDetail & details  ( userData_r.get<RpmDb::CheckPackageDetail>( "CheckPackageDetail" ) );
+
+    str::Str msg;
+    msg << rpmname << ":" << "\n";
+    for ( const auto & el : details )
+    {
+      switch ( el.first )
+      {
+       case RpmDb::CHK_OK:
+         if ( zypper.out().verbosity() >= Out::HIGH )
+           msg << el.second << "\n";
+         break;
+       case RpmDb::CHK_NOKEY:          // can't check
+       case RpmDb::CHK_NOTFOUND:
+         msg << ( ColorContext::MSG_WARNING << el.second ) << "\n";
+         break;
+       case RpmDb::CHK_FAIL:           // failed check
+       case RpmDb::CHK_NOTTRUSTED:
+       case RpmDb::CHK_ERROR:
+         msg << ( ColorContext::MSG_ERROR << el.second ) << "\n";
+         break;
+      }
+    }
+    // determine action
+    if ( zypper.globalOpts().no_gpg_checks )
+    {
+      // report and continue
+      Package::constPtr pkg    ( userData_r.get<Package::constPtr>( "Package" ) );
+      std::string err( str::Str() << pkg->asUserString() << ": " << _("Signature verification failed") << " " << result );
+      switch ( result )
+      {
+       case RpmDb::CHK_OK:
+         // Can't happen; already handled above
+         break;
+
+       case RpmDb::CHK_NOKEY:          // can't check
+       case RpmDb::CHK_NOTFOUND:
+         msg << ( ColorContext::MSG_WARNING << err ) << "\n";
+         break;
+
+       case RpmDb::CHK_FAIL:           // failed check
+       case RpmDb::CHK_ERROR:
+       case RpmDb::CHK_NOTTRUSTED:
+       default:
+         msg << ( ColorContext::MSG_ERROR << err ) << "\n";
+         break;
+      }
+      msg << _("Accepting package despite the error.") << " (--no-gpg-checks)" << "\n";
+      userData_r.set( "Action", IGNORE );
+    }
+    else
+    {
+      // error -> requests the default problem report
+      userData_r.reset( "Action" );
+    }
+    zypper.out().info( msg );
+  }
+
   // implementation not needed prehaps - the media backend reports the download progress
   virtual void finish( zypp::Resolvable::constPtr /*resolvable_ptr**/, Error error, const std::string & reason )
   {
index f247cd2..647a4fb 100644 (file)
@@ -157,6 +157,7 @@ namespace
     //packageCache.setCommitList( steps.begin(), steps.end() );
 
     unsigned current = 0;
+    _zypper.runtimeData().commit_pkgs_total = total; // fix DownloadResolvableReport total counter
     for ( const auto & ent : collect )
     {
       for ( const auto & pi : ent.second )
@@ -181,6 +182,10 @@ namespace
            {
              error_r.report( _zypper );
            }
+           catch ( const AbortRequestException & exp )
+           {
+             ZYPP_RETHROW(exp);
+           }
            catch ( const Exception & exp )
            {
              // TODO: Need class Out::Error support for exceptions
index 9479506..0896f7d 100644 (file)
@@ -30,6 +30,9 @@ class Zypper;
 
 #define OSD ColorStream( std::cout, ColorContext::OSDEBUG )
 
+inline char * asYesNo( bool val_r )
+{ return val_r ? _("Yes") : _("No"); }
+
 ///////////////////////////////////////////////////////////////////
 namespace out
 {
index fe8a04d..ea12f9b 100644 (file)
@@ -70,6 +70,65 @@ void safe_lexical_cast (Source s, Target &tr) {
   }
 }
 
+// | Enabled | GPG Check |  Colored strings for enabled and GPG Check status
+// +---------+-----------+
+// | Yes     | (  ) No   |
+// | Yes     | (rp) Yes  |
+// | No      | ----      |
+struct RepoGpgCheckStrings
+{
+  RepoGpgCheckStrings()
+  : _tagColor( ColorContext::DEFAULT )
+  {}
+
+  RepoGpgCheckStrings( const ServiceInfo & service_r )
+  {
+    if ( service_r.enabled() )
+    {
+       _tagColor = ColorContext::DEFAULT;
+      _enabledYN = ColorString( _tagColor, _("Yes") );
+      _gpgCheckYN = ColorString( _tagColor, "----" );
+    }
+    else
+    {
+      _tagColor = ColorContext::LOWLIGHT;
+      _enabledYN = ColorString( _tagColor, _("No") );
+      _gpgCheckYN = ColorString( _tagColor, "----" );
+    }
+  }
+
+  RepoGpgCheckStrings( const RepoInfo & repo_r )
+  {
+    if ( repo_r.enabled() )
+    {
+      bool gpgOK = false;
+      std::string tagStr( "(  ) " );
+      if ( repo_r.validRepoSignature() )       // is TriBool!
+      {
+       gpgOK = true;
+       tagStr[1] = 'r';
+      }
+      if ( repo_r.pkgGpgCheck() )
+      {
+       gpgOK = true;
+       tagStr[2] = 'p';
+      }
+      _tagColor = gpgOK ? ColorContext::DEFAULT : ColorContext::NEGATIVE;
+      _enabledYN = ColorString( ColorContext::DEFAULT, _("Yes") );
+      _gpgCheckYN = ColorString( _tagColor, tagStr+asYesNo(gpgOK) );
+    }
+    else
+    {
+      _tagColor = ColorContext::LOWLIGHT;
+      _enabledYN = ColorString( _tagColor, _("No") );
+      _gpgCheckYN = ColorString( _tagColor, "----" );
+    }
+  }
+  ColorContext _tagColor;      ///< color according to enabled and GPG Check status
+  ColorString _enabledYN;      ///< colored enabled Yes/No
+  ColorString _gpgCheckYN;     ///< colored GPG Check status if enabled else "----"
+};
+
 // ----------------------------------------------------------------------------
 
 static bool refresh_raw_metadata(Zypper & zypper,
@@ -118,8 +177,12 @@ static bool refresh_raw_metadata(Zypper & zypper,
               switch (stat)
               {
               case RepoManager::REPO_UP_TO_DATE:
-                zypper.out().info(boost::str(format(
-                 _("Repository '%s' is up to date.")) % repo.asUserString()));
+             {
+               TermLine outstr( TermLine::SF_SPLIT | TermLine::SF_EXPAND );
+               outstr.lhs << boost::str(format(_("Repository '%s' is up to date.")) % repo.asUserString());
+               //outstr.rhs << repoGpgCheckStatus( repo );
+               zypper.out().infoLine( outstr );
+             }
               break;
               case RepoManager::REPO_CHECK_DELAYED:
                 zypper.out().info(boost::str(format(
@@ -163,6 +226,7 @@ static bool refresh_raw_metadata(Zypper & zypper,
               RepoManager::RefreshIfNeededIgnoreDelay :
               RepoManager::RefreshIfNeeded);
 
+      //plabel += repoGpgCheckStatus( repo );
       zypper.out().progressEnd("raw-refresh", plabel);
       plabel.clear();
     }
@@ -967,6 +1031,10 @@ static void print_repo_list(Zypper & zypper,
   th << _("Enabled");
   ++index;
 
+  // GPG Check
+  th << _("GPG Check");
+  ++index;
+
   // 'autorefresh' flag
   if (all || showrefresh)
   {
@@ -1027,17 +1095,20 @@ static void print_repo_list(Zypper & zypper,
       continue;
 
     TableRow tr(index);
+    RepoGpgCheckStrings repoGpgCheck( repo );  // color strings for tag/enabled/gpgcheck
 
     // number
-    tr << str::numstring (i, nindent);
+    tr << ColorString( repoGpgCheck._tagColor, str::numstring(i, nindent) ).str();
     // alias
     if (all || showalias) tr << repo.alias();
     // name
     if (all || showname) tr << repo.name();
     // enabled?
-    tr << (repo.enabled() ? _("Yes") : _("No"));
+    tr << repoGpgCheck._enabledYN.str();
+    // GPG Check
+    tr << repoGpgCheck._gpgCheckYN.str();
     // autorefresh?
-    if (all || showrefresh) tr << (repo.autorefresh() ? _("Yes") : _("No"));
+    if (all || showrefresh) tr << asYesNo(repo.autorefresh());
     // priority
     if (all || showprio)
       // output flush right; looks nicer and sorts correctly
@@ -1082,6 +1153,8 @@ static void print_repo_details(Zypper & zypper, list<RepoInfo> & repos)
       cout << endl;
 
     RepoInfo repo = *it;
+    RepoGpgCheckStrings repoGpgCheck( repo );
+
     Table t;
     t.lineStyle(::Colon);
     t.allowAbbrev(1);
@@ -1093,12 +1166,12 @@ static void print_repo_details(Zypper & zypper, list<RepoInfo> & repos)
                                                    : (repo.mirrorListUrl().asString().empty()
                                                       ? "n/a"
                                                       : repo.mirrorListUrl().asString())) )
-      << (  TableRow() << _("Enabled")         << (repo.enabled() ? _("Yes") : _("No")) )
+      << (  TableRow() << _("Enabled")         << repoGpgCheck._enabledYN.str() )
+      << (  TableRow() << _("GPG Check")       << repoGpgCheck._gpgCheckYN.str() )
       << (  TableRow() << _("Priority")                << str::form("%d", repo.priority()) )
       << (  TableRow() << _("Auto-refresh")    << (repo.autorefresh() ? _("On") : _("Off")) )
       << (  TableRow() << _("Keep Packages")   << (repo.keepPackages() ? _("On") : _("Off")) )
       << (  TableRow() << _("Type")            << repo.type().asString() )
-      << (  TableRow() << _("GPG Check")       << (repo.gpgCheck() ? _("On") : _("Off")) )
       << (  TableRow() << _("GPG Key URI")     << repo.gpgKeyUrl() )
       << (  TableRow() << _("Path Prefix")     << repo.path() )
       << (  TableRow() << _("Parent Service")  << repo.service() )
@@ -1721,7 +1794,7 @@ void add_repo(Zypper & zypper, RepoInfo & repo)
     // translators: property name; short; used like "Name: value"
     p.add( _("Autorefresh"),   repo.autorefresh() );
     // translators: property name; short; used like "Name: value"
-    p.add( _("GPG check"),     repo.gpgCheck() ).paint( ColorContext::MSG_WARNING, repo.gpgCheck() == false );
+    p.add( _("GPG Check"),     repo.gpgCheck() ).paint( ColorContext::MSG_WARNING, repo.gpgCheck() == false );
     // translators: property name; short; used like "Name: value"
     p.add( _("URI"),           repo.baseUrlsBegin(), repo.baseUrlsEnd() );
     s << p;
@@ -2449,30 +2522,34 @@ static void service_list_tr(
     unsigned int reponumber,
     const ServiceListFlags & flags)
 {
-  ServiceInfo_Ptr service;
+  ServiceInfo_Ptr service = dynamic_pointer_cast<ServiceInfo>(srv);
   RepoInfo_Ptr repo;
+  if ( ! service )
+    repo = dynamic_pointer_cast<RepoInfo>(srv);
+  RepoGpgCheckStrings repoGpgCheck( service ? RepoGpgCheckStrings(*service) : RepoGpgCheckStrings(*repo) );
 
   TableRow tr(8);
 
   // number
   if (flags & SF_SERVICE_REPO)
-    tr << "";
+    if ( repo && ! repo->enabled() )
+      tr << ColorString( repoGpgCheck._tagColor, "-" ).str();
+    else
+      tr << "";
   else
-    tr << str::numstring (reponumber);
+    tr << ColorString( repoGpgCheck._tagColor, str::numstring(reponumber) ).str();
 
   // alias
   tr << srv->alias();
   // name
   tr << srv->name();
   // enabled?
-  tr << (srv->enabled() ? _("Yes") : _("No"));
+  tr << repoGpgCheck._enabledYN.str();
+  // GPG Check
+  tr << repoGpgCheck._gpgCheckYN.str();
   // autorefresh?
   tr << (srv->autorefresh() ? _("Yes") : _("No"));
 
-  service = dynamic_pointer_cast<ServiceInfo>(srv);
-  if (!service)
-    repo = dynamic_pointer_cast<RepoInfo>(srv);
-
   // priority
   if (flags & SF_SHOW_PRIO)
   {
@@ -2534,6 +2611,7 @@ static void print_service_list(Zypper & zypper,
      << _("Alias")
      << _("Name")
      << _("Enabled")
+     << _("GPG Check")
      // translators: 'zypper repos' column - whether autorefresh is enabled for the repository
      << _("Refresh");
   // optional columns
index 4950b16..8695881 100644 (file)
@@ -144,10 +144,8 @@ string Augeas::get(const string & augpath) const
     DBG << "Got " << augpath << " = " << value[0] << endl;
     return value[0];
   }
-  else if (_last_get_result == 0)
-    DBG << "No match for " << augpath << endl;
-  else
-    DBG << "Multiple matches for " << augpath << endl;
+  else if (_last_get_result > 1)
+    WAR << "Multiple matches for " << augpath << endl;
 
   return string();
 }
index 86131e1..ba9ca8f 100644 (file)
@@ -16,6 +16,7 @@
 #include <zypp/media/MediaManager.h>
 #include <zypp/misc/CheckAccessDeleted.h>
 #include <zypp/ExternalProgram.h>
+#include "zypp/parser/ProductFileReader.h"
 
 #include <zypp/ZYpp.h>
 #include <zypp/Target.h>
@@ -25,6 +26,7 @@
 
 #include "main.h"
 #include "Zypper.h"
+#include "repos.h"
 #include "Table.h"             // for process list in suggest_restart_services
 
 #include "utils/misc.h"
@@ -226,6 +228,29 @@ Url make_url (const string & url_s)
 // http://gitorious.org/opensuse/build-service/blobs/master/src/webui/app/controllers/application_controller.rb
 #define OBS_PROJECT_NAME_RX "[" ALNUM "][-+" ALNUM "\\.:]+"
 
+///////////////////////////////////////////////////////////////////
+namespace {
+  parser::ProductFileData baseproductdata( const Pathname & root_r )
+  {
+    parser::ProductFileData ret;
+    PathInfo baseproduct( Pathname::assertprefix( root_r, "/etc/products.d/baseproduct" ) );
+
+    if ( baseproduct.isFile() )
+    {
+      try
+      {
+       ret = parser::ProductFileReader::scanFile( baseproduct.path() );
+      }
+      catch ( const Exception & excpt )
+      {
+       ZYPP_CAUGHT( excpt );
+      }
+    }
+    return ret;
+  }
+
+} // namespace
+///////////////////////////////////////////////////////////////////
 
 Url make_obs_url( const string & obsuri, const Url & base_url, const string & default_platform )
 {
@@ -264,7 +289,43 @@ Url make_obs_url( const string & obsuri, const Url & base_url, const string & de
 
     Pathname path( ret.getPathName() );
     path /= str::gsub( project, ":", ":/" );
-    path /= ( platform.empty() ? default_platform : platform );
+
+    if ( platform.empty() )
+    {
+      Zypper & zypper( *Zypper::instance() );
+
+      if ( default_platform.empty() )
+      {
+       // Try to guess platform from baseproduct....
+       const parser::ProductFileData & pdata( baseproductdata( zypper.globalOpts().root_dir ) );
+       if ( pdata.empty() )
+       {
+         // Guess failed:
+                            // translators: don't translate '<platform>'
+         zypper.out().error(_("Unable to guess a value for <platform>."),
+                            _("Please use obs://<project>/<platform>") );
+         zypper.out().info(str::form(_("Example: %s"), "obs://server:http/openSUSE_11.3"));
+         return Url(); // FAIL!
+       }
+
+       platform = pdata.name().asString();
+       if ( platform == "openSUSE" && str::containsCI( pdata.summary(), "Tumbleweed" ) )
+         platform += "_Tumbleweed";
+       else
+         platform += "_$releasever";
+
+       zypper.out().info( "Guessed: platform = " + platform );
+       path /= platform;
+      }
+      else
+      {
+       zypper.out().info( "zypper.conf: obs.platform = " + default_platform );
+       path /= default_platform;
+      }
+    }
+    else
+      path /= platform;
+
     ret.setPathName( path.asString() );
 
     return ret;
index 300b592..7c21bba 100644 (file)
@@ -65,7 +65,7 @@ zypp::Url make_url (const std::string & url_s);
 zypp::Url make_obs_url(
     const std::string & obsuri,
     const zypp::Url & base_url,
-    const std::string & default_platform = "openSUSE_Factory");
+    const std::string & default_platform);
 
 /**
  * Returns <code>true</code> if the string \a s contains a substring starting
index 237ec0f..50033ac 100644 (file)
@@ -67,7 +67,7 @@
 
 [solver]
 
-## Do not install soft dependencies (recommended packages)
+## Install soft dependencies (recommended packages)
 ##
 ## Valid values: boolean
 ## Default value: yes
 ## This will be used if none is given in the obs://obsrepo/platform URI
 ## when adding new repository with 'addrepo' command.
 ##
-# platform = openSUSE_11.3
+## NOTE: The 'platform' is actually a directory on the OBS server.
+## We can only guess, how the directory containing the repository that fits
+## your distribution is named. If you are following 'openSUSE_Factory' or
+## 'openSUSE_Tumbleweed' you may need to set this as your platform.
+## In case of doubt you need to look up the right URL in a browser.
+##
+# platform = openSUSE_$releasever
index 4709f48..f45b95c 100644 (file)
@@ -22,7 +22,7 @@ BuildRequires:  boost-devel >= 1.33.1
 BuildRequires:  cmake >= 2.4.6
 BuildRequires:  gcc-c++ >= 4.7
 BuildRequires:  gettext-devel >= 0.15
-BuildRequires:  libzypp-devel >= 14.38.0
+BuildRequires:  libzypp-devel >= 14.39.0
 BuildRequires:  readline-devel >= 5.1
 Requires:       procps
 %if 0%{?suse_version}