#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>
// ----------------------------------------------------------------------------
-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 ()
{
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, ", "));
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()
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
*/
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
#include <readline/readline.h>
#include <readline/history.h>
+#include <boost/logic/tribool.hpp>
+
#include <zypp/zypp_detail/ZYppReadOnlyHack.h>
#include "zypper.h"
#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;
{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 {
ZYPP_CAUGHT( excpt_r );
cerr << _("URL is invalid.") << endl;
cerr << excpt_r.asUserString() << endl;
-
}
return u;
}
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;
}