Enabled obs:// URI in addrepo (bnc #423098).
authorJán Kupec <jkupec@suse.cz>
Thu, 10 Jun 2010 10:28:52 +0000 (12:28 +0200)
committerJán Kupec <jkupec@suse.cz>
Thu, 10 Jun 2010 10:28:52 +0000 (12:28 +0200)
doc/zypper.8
src/Config.cc
src/Config.h
src/Zypper.cc
src/utils/misc.cc
src/utils/misc.h
zypper.conf

index 0cec55b..571d39a 100644 (file)
@@ -32,6 +32,15 @@ To specify locations of repositories or other resources (RPM files, .repo
 files) you can use any type of URIs supported by libzypp. See
 http://en.opensuse.org/Libzypp/URI for a complete list and usage examples.
 
+Zypper also accepts special URIs identifying an openSUSE Build Service (OBS)
+repositories in the \fBaddrepo\fR command. These URIs have the form of
+\fBobs://<project>/<platform>\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. For example: obs://server:http/openSUSE_11.3.
+
+If \fIplatform\fR is omitted, zypper.conf's \fIobs.platform\fR value is used.
+See also other options in the [obs] section of zypper.conf.
+
 In addition to these URIs you can use plain directory and file paths in which
 case zypper automatically treats them as dir:/path URIs.
 
@@ -703,7 +712,7 @@ openSUSE 11.1 and openSUSE 11.2.
 To avoid the above trouble, you can specify the repositories from
 which to do the upgrade using the --from or --repo options.
 The difference between these two is that when --repo is used, zypper
-acts as if it knew onle the specified repositories, while with --from
+acts as if it knew only the specified repositories, while with --from
 zypper can eventually use also the rest of enabled repositories to
 satisfy package dependencies.
 
@@ -741,7 +750,7 @@ Upgrade the system using 'factory' and 'packman' repository:
 .br
 .B $ zypper install zypper libzypp
 .br
-.B $ zypper dup -r factory -r packman
+.B $ zypper dup --from factory --from packman
 
 .SS Query Commands
 
index dfd3f19..f308c79 100644 (file)
@@ -46,6 +46,8 @@ const ConfigOption ConfigOption::COLOR_NEGATIVE(ConfigOption::COLOR_NEGATIVE_e);
 const ConfigOption ConfigOption::COLOR_HIGHLIGHT(ConfigOption::COLOR_HIGHLIGHT_e);
 const ConfigOption ConfigOption::COLOR_PROMPT_OPTION(ConfigOption::COLOR_PROMPT_OPTION_e);
 const ConfigOption ConfigOption::COLOR_PROMPT_SHORTHAND(ConfigOption::COLOR_PROMPT_SHORTHAND_e);
+const ConfigOption ConfigOption::OBS_BASE_URL(ConfigOption::OBS_BASE_URL_e);
+const ConfigOption ConfigOption::OBS_PLATFORM(ConfigOption::OBS_PLATFORM_e);
 
 ConfigOption::ConfigOption(const std::string & strval_r)
   : _value(parse(strval_r))
@@ -98,6 +100,8 @@ const string ConfigOption::asString() const
     _table_str[COLOR_NEGATIVE_e] = "color/negative";
     _table_str[COLOR_HIGHLIGHT_e] = "color/highlight";
     _table_str[COLOR_PROMPT_OPTION_e] = "color/promptOption";
+    _table_str[OBS_BASE_URL_e] = "obs/baseUrl";
+    _table_str[OBS_PLATFORM_e] = "obs/platform";
   }
   map<ConfigOption::Option, string>::const_iterator it = _table_str.find(_value);
   if (it != _table_str.end())
@@ -120,6 +124,8 @@ Config::Config()
   , color_negative   ("red")
   , color_highlight  ("cyan")
   , color_promptOption("grey")
+  , obs_baseUrl("http://download.opensuse.org/repositories/")
+  , obs_platform("openSUSE_Factory")
 {}
 
 void Config::read(const string & file)
@@ -252,6 +258,23 @@ void Config::read(const string & file)
     else
       color_promptOption = c;
 
+
+    // ---------------[ obs ]---------------------------------------------------
+
+    s = augeas.getOption(ConfigOption::OBS_BASE_URL.asString());
+    if (!s.empty())
+    {
+      try { obs_baseUrl = Url(s); }
+      catch (Exception & e)
+      {
+        ERR << "Invalid OBS base URL (" << e.msg() << "), will use the default." << endl;
+      }
+    }
+
+    s = augeas.getOption(ConfigOption::OBS_PLATFORM.asString());
+    if (!s.empty())
+      obs_platform = s;
+
     m.stop();
   }
   catch (Exception & e)
index 9d3a782..baa693d 100644 (file)
@@ -11,6 +11,7 @@
 #include <string>
 #include <set>
 
+#include "zypp/Url.h"
 #include "Command.h"
 #include "utils/colors.h"
 
@@ -34,6 +35,9 @@ public:
   static const ConfigOption COLOR_PROMPT_OPTION;
   static const ConfigOption COLOR_PROMPT_SHORTHAND;
 
+  static const ConfigOption OBS_BASE_URL;
+  static const ConfigOption OBS_PLATFORM;
+
   enum Option
   {
     MAIN_SHOW_ALIAS_e,
@@ -51,7 +55,10 @@ public:
     COLOR_NEGATIVE_e,
     COLOR_HIGHLIGHT_e,
     COLOR_PROMPT_OPTION_e,
-    COLOR_PROMPT_SHORTHAND_e
+    COLOR_PROMPT_SHORTHAND_e,
+
+    OBS_BASE_URL_e,
+    OBS_PLATFORM_e
   };
 
   ConfigOption(Option option) : _value(option) {}
@@ -109,6 +116,11 @@ struct Config
   Color color_negative;
   Color color_highlight;
   Color color_promptOption;
+
+  /** zypper.conf: obs.baseUrl */
+  zypp::Url obs_baseUrl;
+  /** zypper.conf: obs.platform */
+  std::string obs_platform;
 };
 
 #endif /* ZYPPER_CONFIG_H_ */
index 110a840..75316db 100644 (file)
@@ -2906,7 +2906,11 @@ void Zypper::doCommand()
           break;
         }
       case 2:
-       Url url = make_url (_arguments[0]);
+       Url url;
+       if (_arguments[0].find("obs") == 0)
+         url = make_obs_url(_arguments[0], config().obs_baseUrl, config().obs_platform);
+       else
+         url = make_url(_arguments[0]);
         if (!url.isValid())
         {
           setExitCode(ZYPPER_EXIT_ERR_INVALID_ARGS);
index 9996259..21d0670 100644 (file)
@@ -15,6 +15,7 @@
 #include "zypp/base/Logger.h"
 #include "zypp/base/String.h"
 #include "zypp/base/Easy.h"
+#include "zypp/base/Regex.h"
 #include "zypp/media/MediaManager.h"
 #include "zypp/parser/xml/XmlEscape.h"
 #include "zypp/misc/CheckAccessDeleted.h"
@@ -197,11 +198,11 @@ bool looks_like_url (const string& s)
   }
 */
   string::size_type pos = s.find (':');
-  if (pos != string::npos) {
+  if (pos != string::npos)
+  {
     string scheme (s, 0, pos);
-    if (Url::isRegisteredScheme (scheme)) {
+    if (Url::isRegisteredScheme(scheme) || scheme == "obs")
       return true;
-    }
   }
   return false;
 }
@@ -261,6 +262,63 @@ Url make_url (const string & url_s)
 
 // ----------------------------------------------------------------------------
 
+// in the Estonian locale, a-z excludes t, for example. #302525
+// http://en.wikipedia.org/wiki/Estonian_alphabet
+#define ALNUM "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0-9_"
+
+// valid OBS project name regex from OBS' ApplicationController.valid_project_name? method:
+// http://gitorious.org/opensuse/build-service/blobs/master/src/webui/app/controllers/application_controller.rb
+#define OBS_PROJECT_NAME_RX "[" ALNUM "][-+" ALNUM "\\.:]+"
+
+Url make_obs_url (
+    const string & obsuri,
+    const Url & base_url,
+    const string & default_platform)
+{
+  // zypper's 'obs' URI regex
+  static str::regex obs_uri_rx("^obs://(" OBS_PROJECT_NAME_RX ")/?(.*)$");
+  str::smatch what;
+  if (str::regex_match(obsuri, what, obs_uri_rx))
+  {
+    vector<string> obsrpath;
+    cout << what[1] << endl;
+    str::split(what[1], back_inserter(obsrpath), ":");
+    if (obsrpath.empty())
+    {
+      Zypper::instance()->out().error(_("Empty OBS project name."));
+      return Url();
+    }
+
+    ostringstream urlstr; urlstr << "/";
+    unsigned i = 0;
+    for (; i < obsrpath.size() - 1; ++i)
+      urlstr << obsrpath[i] << ":/";
+    urlstr << obsrpath[i] << "/";         // no colon at the end
+
+    if (what[2].empty())
+      urlstr << default_platform;
+    else
+      urlstr << what[2];
+    urlstr << "/";
+
+    Url url = Url(base_url);
+    Pathname newpath(url.getPathName());
+    newpath = newpath / Pathname(urlstr.str());
+    url.setPathName(newpath.asString());
+
+    return url;
+  }
+  else
+  {
+    Zypper::instance()->out().error(_("Invalid OBS URI."), _("Correct form is obs://<project>/[platform]"));
+    Zypper::instance()->out().info(str::form(_("Example: %s"), "obs://server:http/openSUSE_11.3"));
+  }
+
+  return Url();
+}
+
+// ----------------------------------------------------------------------------
+
 bool looks_like_rpm_file(const string & s)
 {
   // don't even bother to check strings shorter than 4 chars.
index 199a69d..c8c646d 100644 (file)
@@ -64,6 +64,15 @@ std::string string_patch_status(const zypp::PoolItem & pi);
 zypp::Url make_url (const std::string & url_s);
 
 /**
+ * Creates Url out of obs://project/platform URI with given base URL and default
+ * platform (used in case the platform is not specified in the URI).
+ */
+zypp::Url make_obs_url(
+    const std::string & obsuri,
+    const zypp::Url & base_url,
+    const std::string & default_platform = "");
+
+/**
  * Returns <code>true</code> if the string \a s contains a substring starting
  * at the beginning and ending before the first colon matches any of registered
  * schemes (Url::isRegisteredScheme()).
index ec2fd12..802a1cf 100644 (file)
 ##
 # promptOption = grey
 
+[obs]
+
+## openSUSE Build Service repository base URL.
+## This is used to construct real URL from obs://project/platform URI
+##
+# baseUrl = http://download.opensuse.org/repositories/
+
+## openSUSE Build Service repository target platform.
+## 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