- zypper addrepo (alias service-add, sa) reimplemented
authorJan Kupec <jkupec@suse.cz>
Fri, 15 Jun 2007 12:29:59 +0000 (12:29 +0000)
committerJan Kupec <jkupec@suse.cz>
Fri, 15 Jun 2007 12:29:59 +0000 (12:29 +0000)
- some related code clean-up

src/zypper-sources.cc
src/zypper-sources.h
src/zypper.cc

index 58e5602..db723a6 100644 (file)
@@ -6,6 +6,7 @@
 #include <fstream>
 #include <boost/format.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/logic/tribool.hpp>
 
 #include <zypp/target/store/PersistentStorage.h>
 #include <zypp/base/IOStream.h>
@@ -185,49 +186,6 @@ void refresh_repos()
 
 // ----------------------------------------------------------------------------
 
-bool parse_repo_file (const string& file, string& url, string& alias)
-{
-  static const boost::regex
-    r_alias ("^\\[(.*)\\]$"),
-    r_type ("^type=(.*)"),
-    r_url ("^baseurl=(.*)");
-  boost::smatch match;
-
-  std::ifstream repo(file.c_str());
-  bool have_alias = false, have_url = false;
-  while (repo.good ()) {
-    string line = zypp::iostr::getline (repo);
-
-    if (regex_search (line, match, r_alias)) {
-      alias = match[1];
-      have_alias = true;
-    }
-    else if (regex_search (line, match, r_type)) {
-      string type = match[1];
-      if (type != "rpm-md" && type != "yast2") {
-       cerr << _("Unknown repository type ") << type << endl;
-       return false;
-      }
-    }
-    else if (regex_search (line, match, r_url)) {
-      url = match[1];
-      have_url = true;
-    }
-  }
-  repo.close ();
-
-  if (!have_alias) {
-    cerr << _("Name not found") << endl;
-  }  
-  if (!have_url) {
-    cerr << _("baseurl not found") << endl;
-  }  
-  cerr_vv << "Name: " << alias << endl;
-  cerr_vv << "URL: " << url << endl;
-
-  return have_alias && have_url;
-}
-
 static
 std::string timestamp ()
 {
@@ -245,58 +203,112 @@ std::string timestamp ()
   return outstr;
 }
 
-void add_source_by_url( const zypp::Url &url, const string &alias,
-                       const string &type, bool enabled, bool refresh  )
+// ----------------------------------------------------------------------------
+
+//! \todo handle zypp exceptions
+static
+int add_repo(const RepoInfo & repo)
 {
-  cerr_vv << "Constructing SourceManager" << endl;
-  SourceManager_Ptr manager = SourceManager::sourceManager();
-  cerr_vv << "Restoring SourceManager" << endl;
-  manager->restore (gSettings.root_dir, true /*use_cache*/);
+  RepoManager manager;
 
-  list<SourceManager::SourceId> sourceIds;
-
-  Pathname path;
-  Pathname cache;
-  bool is_base = false;
-  string myalias = alias.empty() ? timestamp() : alias;
-   
-  // more products?
-  // try
-  cerr_vv << "Creating source" << endl;
-  Source_Ref source;
-  if (type.empty()) {
-    source = SourceFactory().createFrom( url, path, myalias, cache, is_base );
-  }
-  else {
-    source = SourceFactory().createFrom( type,
-                                        url, path, myalias, cache, is_base,
-                                        refresh );
-  }
-  cerr_vv << "Adding source" << endl;
-  SourceManager::SourceId sourceId = manager->addSource( source );
+  cout_v << format(_("Adding repository '%s'.")) % repo.alias() << endl;
+  manager.addRepository(repo);
+
+  cout << format(_("Repository '%s' successfully added:")) % repo.alias() << endl;
+  cout << ( repo.enabled() ? "[x]" : "[ ]" );
+  cout << ( repo.autorefresh() ? "* " : "  " );
+  cout << repo.alias() << " (" << *repo.baseUrlsBegin() << ")" << endl;
+
+  return ZYPPER_EXIT_OK;
+}
+
+// ----------------------------------------------------------------------------
+
+int add_repo_by_url( const zypp::Url & url, const string & alias,
+                     const string & type, bool enabled, bool refresh )
+{
+  RepoManager manager;
 
-  if (enabled)
-    source.enable();
+  // determine repository type
+  RepoType repotype_probed = manager.probe(url);
+  RepoType repotype = RepoType::RPMMD;
+  if (type.empty())
+    repotype = repotype_probed;
   else
-    source.disable();
-  
-  source.setAutorefresh (refresh);
+  {
+    try
+    {
+      repotype = RepoType(type);
 
-    sourceIds.push_back( sourceId );
-      cout << "Added Installation Sources:" << endl;
-  
-    list<SourceManager::SourceId>::const_iterator it;
-    for( it = sourceIds.begin(); it != sourceIds.end(); ++it ) {
-      Source_Ref source = manager->findSource(*it);
-      cout << ( source.enabled() ? "[x]" : "[ ]" );
-      cout << ( source.autorefresh() ? "* " : "  " );
-      cout << source.alias() << " (" << source.url() << ")" << endl;
+      if (repotype == repotype_probed)
+      {
+        cout_v << _("Zypper happy! Detected repository type matches the one"
+                     " specified in the --type option.");
+      }
+      else
+      {
+        cerr << format(_(
+            "Warning! Overriding detected repository type '%s' with "
+            "manually specified '%s'.")) % repotype_probed % repotype
+          << endl;
+      }
     }
+    catch (Exception & e)
+    {
+      string message = _(
+        "Warning: Unknown repository type '%s'."
+        " Using detected type '%s' instead.");
+      cerr << format(message) % type % repotype_probed << endl;
+
+      repotype = repotype_probed;
+    }
+  }
+
+  RepoInfo repo;
+  repo.setAlias(alias.empty() ? timestamp() : alias);
+  repo.setType(repotype);
+  repo.addBaseUrl(url);
+  repo.setEnabled(enabled);
+  repo.setAutorefresh(refresh);
 
-    cerr_vv << "Storing source data" << endl;
-    manager->store( gSettings.root_dir, true /*metadata_cache*/ );
+  return add_repo(repo);
 }
 
+// ----------------------------------------------------------------------------
+
+//! \todo handle zypp exceptions
+int add_repo_from_file(const std::string & repo_file_url,
+                       const tribool enabled, const tribool autorefresh)
+{
+  //! \todo handle local .repo files, validate the URL
+  Url url(repo_file_url);
+  RepoManager manager;
+  list<RepoInfo> repos = manager.readRepoFile(url);
+
+  for (list<RepoInfo>::iterator it = repos.begin();
+       it !=  repos.end(); ++it)
+  {
+    RepoInfo repo = *it;
+
+    if (!indeterminate(enabled))
+      repo.setEnabled(enabled);
+    if (!indeterminate(autorefresh))
+      repo.setAutorefresh(autorefresh);
+
+    // by default set enabled and autorefresh to true
+    if (indeterminate(repo.enabled()))
+      repo.setEnabled(true);
+    if (indeterminate(repo.autorefresh()))
+      repo.setAutorefresh(true);
+
+    add_repo(repo);
+  }
+
+  return ZYPPER_EXIT_OK;
+}
+
+// ----------------------------------------------------------------------------
+
 template<typename T>
 ostream& operator << (ostream& s, const vector<T>& v) {
   std::copy (v.begin(), v.end(), ostream_iterator<T> (s, ", "));
@@ -471,36 +483,7 @@ void rename_source( const std::string& anystring, const std::string& newalias )
   manager->store( gSettings.root_dir, true /*metadata_cache*/ );
 }
 
-
-MediaWrapper::MediaWrapper (const string& filename_or_url) {
-  try {
-    // the interface cannot provide a "complete path" :-(
-    Url url (filename_or_url);
-    Pathname path (url.getPathName ());
-    url.setPathName ("/");
-
-    _id = _mm.open (url);
-    _mm.attach (_id);
-
-    _mm.provideFile (_id, path);
-    Pathname local = _mm.localPath (_id, path);
-    _local_path = local.asString ();
-  }
-  catch (const Exception & ex) {
-    ZYPP_CAUGHT (ex);
-    if (looks_like_url (filename_or_url)) {
-    cerr << _("Error while fetching ") << filename_or_url << " : "
-        << ex << endl;
-//      ex.dumpOn (cerr);              // this suxxz
-    }
-    _local_path = filename_or_url;
-  }
-}
-
-MediaWrapper::~MediaWrapper () {
-  if (_mm.isOpen (_id))
-    _mm.close (_id);
-}
+// ----------------------------------------------------------------------------
 
 // #217028
 void warn_if_zmd()
index 64bf486..d030681 100644 (file)
 void init_repos();
 
 /**
- * 
+ * List defined repositories.
  */
 void list_repos();
 
 /**
- * 
+ * Refresh all enabled repositories.
  */
 void refresh_repos();
 
 
+/**
+ * Add repository specified by \url to system repositories.
+ * 
+ * \param url Valid URL of the repository.
+ * \param alias
+ * \param type
+ * \param enabled
+ * \param autorefresh
+ * \return ZYPPER_EXIT_ERR_ZYPP on unexpected zypp exception,
+ *         ZYPPER_EXIT_OK otherwise
+ */
+int add_repo_by_url( const zypp::Url & url,
+                      const std::string & alias,
+                      const std::string & type = "",
+                      bool enabled = true, bool autorefresh = true );
 
-bool parse_repo_file (const std::string& file, std::string& url, std::string& alias);
-
-void add_source_by_url( const zypp::Url &url, const std::string &alias,
-                        const std::string &type = "",
-                        bool enabled = true, bool refresh = true );
+/**
+ * Add repository specified in given repo file on \a repo_file_url.
+ * 
+ * \param repo_file_url Valid URL of the repo file.
+ * \param enabled       If determined, overrides repo file's enabled setting.
+ * \param autorefresh   If determined, overrides repo file's autorefresh setting.
+ * \return ZYPPER_EXIT_ERR_ZYPP on unexpected zypp exception,
+ *         ZYPPER_EXIT_OK otherwise
+ */
+int add_repo_from_file(const std::string & repo_file_url,
+                        tribool enabled = true, tribool autorefresh = true);
 
 /**
  * If ZMD process found, notify user that ZMD is running and that changes
@@ -34,21 +55,6 @@ void add_source_by_url( const zypp::Url &url, const std::string &alias,
  */
 void warn_if_zmd();
 
-//! download a copy of a remote file or just return the argument
-// The file is deleted when this class is destroyed
-class MediaWrapper : private zypp::base::NonCopyable {
-public:
-  MediaWrapper (const std::string& filename_or_url);
-  ~MediaWrapper ();
-  std::string localPath () const {
-    return _local_path;
-  }
-
-private:
-  zypp::media::MediaManager _mm; // noncopyable
-  zypp::media::MediaId _id;  
-  std::string _local_path;
-};
 
 //! calls init_system_sources if not disabled by user (or non-root)
 void cond_init_system_sources(); // OLD
index c0d9661..df06440 100644 (file)
@@ -18,6 +18,8 @@
 #include <readline/readline.h>
 #include <readline/history.h>
 
+#include <boost/logic/tribool.hpp>
+
 #include <zypp/zypp_detail/ZYppReadOnlyHack.h>
 
 #include "zypper.h"
@@ -35,9 +37,9 @@
 #include "zypper-command.h"
 
 using namespace std;
-//using namespace boost;
 using namespace zypp;
 using namespace zypp::detail;
+using namespace boost;
 
 ZYpp::Ptr God = NULL;
 RuntimeData gData;
@@ -64,8 +66,10 @@ static struct option global_options[] = {
   {0, 0, 0, 0}
 };
 
-//! a constructor wrapper catching exceptions
-// returns an empty one on error
+/**
+ * Constructor wrapper catching exceptions,
+ * returning an empty one on error.
+ */
 Url make_url (const string & url_s) {
   Url u;
   try {
@@ -75,7 +79,6 @@ Url make_url (const string & url_s) {
     ZYPP_CAUGHT( excpt_r );
     cerr << _("URL is invalid.") << endl;
     cerr << excpt_r.asUserString() << endl;
-    
   }
   return u;
 }
@@ -580,56 +583,52 @@ int one_command(const string& command_str, int argc, char **argv)
   
   else if (command.toEnum() == ZypperCommand::ADD_REPO_e)
   {
-    // TODO: repect values in .repo, have these as overrides
-    bool enabled = ! copts.count("disabled");
-    bool refresh = ! copts.count("no-refresh");
+    tribool enabled(indeterminate);
+    tribool refresh(indeterminate);
 
-    string type = copts.count("type")?  copts["type"].front() : "";
-    if (type != "" && type != "YaST" && type != "YUM" && type != "Plaindir") {
-      cerr << _("Warning: Unknown metadata type ") << type << endl;
-    }
+    if (copts.count("disabled"))
+      enabled = false;
+    if (copts.count("no-refresh"))
+      refresh = false;
 
-    string repoalias, repourl;
-    if (copts.count("repo")) {
-      string filename = copts["repo"].front();
-      // it may be an URL; cache the file while MediaWrapper exists
-      MediaWrapper download (filename);
-      filename = download.localPath ();
-      cerr_vv << "Got: " << filename << endl;
-      parse_repo_file (filename, repourl, repoalias);
+    // add repository specified in .repo file
+    if (copts.count("repo"))
+    {
+      return add_repo_from_file(copts["repo"].front(), enabled, refresh);
     }
 
-    if (ghelp || (arguments.size() < 1 && repoalias.empty ())) {
+    // force specific repository type. Validation is done in add_repo_by_url()
+    string type = copts.count("type") ? copts["type"].front() : "";
+
+    // display help message if insufficient info was given
+    if (ghelp || arguments.size() < 1)
+    {
+      //! todo display_help()
       cerr << specific_help;
-      return !ghelp;
+      if (ghelp) return ZYPPER_EXIT_OK;
+      return ZYPPER_EXIT_ERR_INVALID_ARGS;
     }
 
-    if (repourl.empty())
-      repourl = arguments[0];
-
-    Url url = make_url (repourl);
-    if (!url.isValid())
+    Url url = make_url (arguments[0]);
+    if (!url.isValid()) //! \todo error message
       return ZYPPER_EXIT_ERR_INVALID_ARGS;
-    string alias = repoalias;
-    if (alias.empty ())
-      alias = url.asString();
+
+    string alias;
     if (arguments.size() > 1)
       alias = arguments[1];
+    //! \todo use timestamp as alias, if no alias was given
+    if (alias.empty ())
+      alias = url.asString();
 
-    warn_if_zmd ();
+    if (indeterminate(enabled)) enabled = true;
+    if (indeterminate(refresh)) refresh = true;
+
+    warn_if_zmd();
 
     // load gpg keys
     cond_init_target ();
 
-    try {
-      // also stores it
-      add_source_by_url(url, alias, type, enabled, refresh);
-    }
-    catch ( const Exception & excpt_r )
-    {
-      cerr << excpt_r.asUserString() << endl;
-      return ZYPPER_EXIT_ERR_ZYPP;
-    }
+    return add_repo_by_url(url, alias, type, enabled, refresh);
 
     return ZYPPER_EXIT_OK;
   }