Author: jkupec Date: Fri Jan 11 14:52:36 2008 New Revision: 8261 URL: http://svn.opensuse.org/viewcvs/zypp?rev=8261&view=rev Log: - ability to install RPM files added (FATE #302151) - todo: polish the behavior a bit more Modified: trunk/zypper/src/zypper-utils.cc trunk/zypper/src/zypper-utils.h trunk/zypper/src/zypper.cc Modified: trunk/zypper/src/zypper-utils.cc URL: http://svn.opensuse.org/viewcvs/zypp/trunk/zypper/src/zypper-utils.cc?rev=8261&r1=8260&r2=8261&view=diff ============================================================================== --- trunk/zypper/src/zypper-utils.cc (original) +++ trunk/zypper/src/zypper-utils.cc Fri Jan 11 14:52:36 2008 @@ -9,6 +9,7 @@ #include "zypper-main.h" #include "zypper-utils.h" +#include "zypper-callbacks.h" using namespace std; using namespace zypp; @@ -40,6 +41,8 @@ return "\004"; } +// ---------------------------------------------------------------------------- + /// tell the user to report a bug, and how // (multiline, with endls) ostream& report_a_bug (ostream& stm) @@ -50,6 +53,8 @@ << _("See http://en.opensuse.org/Zypper#Troubleshooting for instructions.") << endl; } +// ---------------------------------------------------------------------------- + bool is_changeable_media(const zypp::Url & url) { MIL << "Checking if this is a changeable medium" << endl; @@ -102,7 +107,6 @@ // ---------------------------------------------------------------------------- -static bool looks_like_url (const string& s) { /* @@ -167,3 +171,59 @@ } return u; } + +// ---------------------------------------------------------------------------- + +bool looks_like_rpm_file(const std::string & s) +{ + if (s.rfind(".rpm") == s.size() - 4 || + s.find("./") == 0 || + s.find("../") == 0 || + s.find("/") == 0) + return true; + + return false; +} + +// ---------------------------------------------------------------------------- + +Pathname cache_rpm(const string & rpm_uri_str) +{ + Url rpmurl = make_url(rpm_uri_str); + Pathname rpmpath(rpmurl.getPathName()); + rpmurl.setPathName(rpmpath.dirname().asString()); // directory + rpmpath = rpmpath.basename(); // rpm file name + + try + { + media::MediaManager mm; + media::MediaAccessId mid = mm.open(rpmurl); + mm.attachDesiredMedia(mid); + + mm.provideFile(mid, rpmpath.basename()); + Pathname localrpmpath = mm.localPath(mid, rpmpath.basename()); + Pathname cachedrpmpath = "/var/cache/zypp/RPMS/"; + filesystem::assert_dir(cachedrpmpath); + bool error = + filesystem::copy(localrpmpath, cachedrpmpath / localrpmpath.basename()); + + mm.release(mid); + mm.close(mid); + + if (error) + { + cerr << _("Problem copying the specified RPM file to the cache directory.") + << endl << _("Perhaps you are running out of disk space.") << endl; + return Pathname(); + } + return cachedrpmpath / localrpmpath.basename(); + } + catch (const Exception & e) + { + report_problem(e, + _("Problem downloading the specified RPM file."), + _("Please check whether the file is accessible.")); + } + + return Pathname(); +} Modified: trunk/zypper/src/zypper-utils.h URL: http://svn.opensuse.org/viewcvs/zypp/trunk/zypper/src/zypper-utils.h?rev=8261&r1=8260&r2=8261&view=diff ============================================================================== --- trunk/zypper/src/zypper-utils.h (original) +++ trunk/zypper/src/zypper-utils.h Fri Jan 11 14:52:36 2008 @@ -6,6 +6,7 @@ #include "zypp/Url.h" #include "zypp/Resolvable.h" +#include "zypp/Pathname.h" std::string readline_getline(); @@ -20,9 +21,33 @@ const zypp::Resolvable::Kind & kind, unsigned long count); /** - * Constructor wrapper catching exceptions, - * returning an empty one on error. + * Creates a Url out of \a urls_s. If the url_s looks looks_like_url() + * Url(url_s) is returned. Otherwise if \a url_s represends a valid path to + * a file or directory, a dir:// Url is returned. Otherwise an empty Url is + * returned. */ zypp::Url make_url (const std::string & url_s); +/** + * 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()). + */ +bool looks_like_url (const std::string& s); + +/** + * Returns <code>true</code> if \a s ends with ".rpm" or starts with "/", "./", + * or "../". + */ +bool looks_like_rpm_file(const std::string & s); + +/** + * Download the RPM file specified by \a rpm_uri_str and copy it into zypp + * cache dir. + * + * \return The local Pathname of the file in the cache on success, empty + * Pathname if a problem occurs. + */ +zypp::Pathname cache_rpm(const std::string & rpm_uri_str); + #endif /*ZYPPER_UTILS_H*/ Modified: trunk/zypper/src/zypper.cc URL: http://svn.opensuse.org/viewcvs/zypp/trunk/zypper/src/zypper.cc?rev=8261&r1=8260&r2=8261&view=diff ============================================================================== --- trunk/zypper/src/zypper.cc (original) +++ trunk/zypper/src/zypper.cc Fri Jan 11 14:52:36 2008 @@ -27,6 +27,8 @@ #include "zypp/repo/RepoException.h" #include "zypp/zypp_detail/ZYppReadOnlyHack.h" +#include "zypp/target/rpm/RpmHeader.h" // for install <.rpmURI> + #include "zypper-main.h" #include "zypper.h" #include "zypper-repos.h" @@ -1632,17 +1634,82 @@ return; } - init_repos(*this); - if (exitCode() != ZYPPER_EXIT_OK) - return; + bool install_not_remove = command() == ZypperCommand::INSTALL; + + // check for rpm files among the arguments + list<string> rpms_files_caps; + if (install_not_remove) + { + for (vector<string>::iterator it = _arguments.begin(); + it != _arguments.end(); ) + { + if (looks_like_rpm_file(*it)) + { + DBG << *it << " looks like rpm file" << endl; + // download the rpm into the cache + //! \todo do we want this or a tmp dir? What about the files cached before? + //! \todo optimize: don't mount the same media multiple times for each rpm + Pathname rpmpath = cache_rpm(*it); + + if (rpmpath.empty()) + { + cerr << format(_("Problem with the RPM file specified as %s, skipping.")) + % *it << endl; + } + else + { + using target::rpm::RpmHeader; + // rpm header (need name-version-release) + RpmHeader::constPtr header = + RpmHeader::readPackage(rpmpath, RpmHeader::NOSIGNATURE); + if (header) + { + string nvrcap = + header->tag_name() + "=" + + header->tag_version() + "-" + + header->tag_release(); + DBG << "rpm package capability: " << nvrcap << endl; + + // store the rpm file capability string (name=version-release) + rpms_files_caps.push_back(nvrcap); + } + else + { + cerr << format( + _("Problem reading the RPM header of %s. Is it an RPM file?")) + % *it << endl; + } + } + + // remove this rpm argument + it = _arguments.erase(it); + } + else + ++it; + } + } - //! \todo support temporary additional repos - /* - for ( std::list<Url>::const_iterator it = globalOpts().additional_sources.begin(); it != globalOpts().additional_sources.end(); ++it ) + // if there were some rpm files, add the rpm cache as a temporary plaindir repo + if (!rpms_files_caps.empty()) { - include_source_by_url( *it ); + // add a plaindir repo + RepoInfo repo; + repo.setType(repo::RepoType::RPMPLAINDIR); + repo.addBaseUrl(Url("dir:///var/cache/zypp/RPMS")); + repo.setEnabled(true); + repo.setAutorefresh(true); + repo.setAlias("_tmpRPMcache_"); + repo.setName(_("RPM files cache")); + + gData.additional_repos.push_back(repo); } - */ + + //! \todo quit here if the argument list remains empty after founding only invalid rpm args + + // prepare repositories + init_repos(*this); + if (exitCode() != ZYPPER_EXIT_OK) + return; if ( gData.repos.empty() ) { @@ -1651,21 +1718,31 @@ " Nothing can be installed.") << endl; } + // prepare target cond_init_target(*this); + // load metadata cond_load_resolvables(*this); - bool install_not_remove = command() == ZypperCommand::INSTALL; + // mark resolvables for installation/removal bool by_capability = false; // install by name by default + //! \todo install by capability by default in the future (need to improve its output) if (copts.count("capability")) by_capability = true; for ( vector<string>::const_iterator it = _arguments.begin(); - it != _arguments.end(); ++it ) { + it != _arguments.end(); ++it ) + { if (by_capability) mark_by_capability (*this, install_not_remove, kind, *it); else mark_by_name (install_not_remove, kind, *it); } + // rpm files + for ( list<string>::const_iterator it = rpms_files_caps.begin(); + it != rpms_files_caps.end(); ++it ) + mark_by_capability (*this, true, kind, *it); + + // solve dependencies if (copts.count("debug-solver")) { establish(); -- To unsubscribe, e-mail: zypp-commit+unsubscribe@opensuse.org For additional commands, e-mail: zypp-commit+help@opensuse.org