From 01f7f05e7855a8ddde20b5d9c256727099a8ad89 Mon Sep 17 00:00:00 2001 From: Johannes Winkelmann Date: Sun, 3 Sep 2006 16:12:55 +0000 Subject: [PATCH] prt-get: warn about unclear version decisions when using "prefer higher" git-svn-id: https://crux.nu/svn/tools/prt-get/trunk@1806 0b5ae1c7-2405-0410-a7fc-ba219f786e1e --- ChangeLog | 5 ++ src/package.cpp | 35 +++++++--- src/package.h | 10 ++- src/prtget.cpp | 182 ++++++++++++++++++++++++++++++++---------------- src/prtget.h | 16 ++++- 5 files changed, 172 insertions(+), 76 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e37792..cdf65b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +* 0.5.13 00.09.2006 Johannes Winkelmann +- Show undecided versions in diff and sysup when using "prefer higher" +- fix display bug in "dependent" +- fix bug in version comparator + * 0.5.12 00.04.2006 Johannes Winkelmann - Add 'depinst' in 'help' (thanks Simone) - Fix compilation on OpenBSD diff --git a/src/package.cpp b/src/package.cpp index 454ff6e..4c2dd31 100644 --- a/src/package.cpp +++ b/src/package.cpp @@ -130,6 +130,13 @@ const bool Package::hasReadme() const return m_data->hasReadme; } +/*! \return a typically formatted version-release string */ +string Package::versionReleaseString() const +{ + load(); + return m_data->versionReleaseString; +} + const bool Package::hasPreInstall() const { return m_data->hasPreInstall; @@ -162,10 +169,10 @@ void Package::load() const const int length = BUFSIZ; char input[length]; string line; - + time_t timeNow; time(&timeNow); - + struct utsname unameBuf; if (uname(&unameBuf) != 0) { unameBuf.release[0] = '\0'; @@ -235,6 +242,7 @@ void Package::load() const } fclose( fp ); + m_data->generateVersionReleaseString(); string file = m_data->path + "/" + m_data->name + "/README"; struct stat buf; @@ -282,29 +290,36 @@ PackageData::PackageData( const string& name_, maintainer( maintainer_ ) { + generateVersionReleaseString(); + hasReadme = ( stripWhiteSpace( hasReadme_ ) == "yes" ); hasPreInstall = ( stripWhiteSpace( hasPreInstall_ ) == "yes" ); hasPostInstall = ( stripWhiteSpace( hasPostInstall_ ) == "yes" ); } +void PackageData::generateVersionReleaseString() +{ + versionReleaseString = version + "-" + release; +} -void Package::expandShellCommands(std::string& input, + +void Package::expandShellCommands(std::string& input, const time_t& timeNow, const struct utsname unameBuf) { // TODO: consider dropping either of the tagsets, depending on feedback - + static const int TAG_COUNT = 2; string startTag[TAG_COUNT] = { "`", "$(" }; string endTag[TAG_COUNT] = { "`", ")" }; - + for (int i = 0; i < TAG_COUNT; ++i) { string::size_type pos; while ((pos = input.find(startTag[i])) != string::npos) { if (unameBuf.release) { - input = replaceAll(input, - startTag[i] + "uname -r" + endTag[i], + input = replaceAll(input, + startTag[i] + "uname -r" + endTag[i], unameBuf.release); } @@ -314,9 +329,9 @@ void Package::expandShellCommands(std::string& input, string::size_type startpos, endpos; endpos = input.find(endTag[i], pos+1); startpos = input.find('+', pos+1); - + string format = input.substr(startpos+1, endpos-startpos-1); - + // support date '+...' and date "+..." int len = format.length(); if (format[len-1] == '\'' || format[len-1] == '"') { @@ -325,7 +340,7 @@ void Package::expandShellCommands(std::string& input, char timeBuf[32]; strftime(timeBuf, 32, format.c_str(), localtime(&timeNow)); - input = input.substr(0, pos) + timeBuf + + input = input.substr(0, pos) + timeBuf + input.substr(endpos+1); } } diff --git a/src/package.h b/src/package.h index 7af66dc..bc3e055 100644 --- a/src/package.h +++ b/src/package.h @@ -55,14 +55,16 @@ public: const bool hasReadme() const; const bool hasPreInstall() const; const bool hasPostInstall() const; + + std::string versionReleaseString() const; void setDependencies( const std::string& dependencies ); private: void load() const; - - static void expandShellCommands(std::string& input, + + static void expandShellCommands(std::string& input, const time_t& timeNow, const struct utsname unameBuf); @@ -96,9 +98,13 @@ struct PackageData std::string packager; std::string maintainer; + std::string versionReleaseString; + bool hasReadme; bool hasPreInstall; bool hasPostInstall; + + void generateVersionReleaseString(); }; #endif /* _PACKAGE_H_ */ diff --git a/src/prtget.cpp b/src/prtget.cpp index fef2afe..c4924b6 100644 --- a/src/prtget.cpp +++ b/src/prtget.cpp @@ -40,6 +40,12 @@ using namespace std; using namespace StringHelper; +using VersionComparator::COMP_RESULT; +using VersionComparator::GREATER; +using VersionComparator::LESS; +using VersionComparator::EQUAL; +using VersionComparator::UNDEFINED; + const string PrtGet::CONF_FILE = SYSCONFDIR"/prt-get.conf"; const string PrtGet::DEFAULT_CACHE_FILE = LOCALSTATEDIR"/lib/pkg/prt-get.cache"; @@ -148,7 +154,7 @@ void PrtGet::printUsage() cout << " --all list all dependent packages, not " << "only installed" << endl; cout << " --recursive print recursive listing" << endl; - cout << " --tree print recursive tree listing" + cout << " --tree print recursive tree listing" << endl; cout << "\nSEARCHING" << endl; @@ -792,14 +798,17 @@ void PrtGet::printQuickDiff() const map& installed = m_pkgDB->installedPackages(); map::const_iterator it = installed.begin(); const Package* p = 0; + COMP_RESULT result; for ( ; it != installed.end(); ++it ) { if ( !m_locker.isLocked( it->first ) ) { p = m_repo->getPackage( it->first ); if ( p ) { - if (greaterThan(p->version() + "-" + p->release(), - it->second)) { + result = compareVersions(p->versionReleaseString(), + it->second); + if (result == GREATER) { cout << it->first.c_str() << " "; } + // we don't care about undefined diffs here } } } @@ -807,6 +816,28 @@ void PrtGet::printQuickDiff() } +void PrtGet::printFormattedDiffLine(const string& name, + const string& version1, + const string& version2, + bool isLocked) +{ + cout.setf( ios::left, ios::adjustfield ); + cout.width( 20 ); + cout.fill( ' ' ); + cout << name; + + cout.width( 20 ); + cout.fill( ' ' ); + cout << version1; + + string locked = ""; + if ( isLocked ) { + locked = "locked"; + } + cout.width( 20 ); + cout.fill( ' ' ); + cout << version2 << locked << endl; +} /*! print an overview of port which are installed in a different version than they are in the repository @@ -843,6 +874,7 @@ void PrtGet::printDiff() map::const_iterator it = installed.begin(); const Package* p = 0; int count = 0; + COMP_RESULT result; for ( ; it != installed.end(); ++it ) { p = m_repo->getPackage( it->first ); @@ -851,8 +883,9 @@ void PrtGet::printDiff() continue; } - if ( greaterThan( p->version() + "-" + p->release(), - it->second ) ) { + result = compareVersions( p->versionReleaseString(), + it->second ); + if (result == GREATER ) { if ( !m_locker.isLocked( it->first ) || m_parser->otherArgs().size() > 0 || m_parser->all() ) { @@ -862,39 +895,46 @@ void PrtGet::printDiff() if ( count == 1 ) { cout << "Differences between installed packages " << "and ports tree:\n" << endl; - cout.setf( ios::left, ios::adjustfield ); - cout.width( 20 ); - cout.fill( ' ' ); - cout << "Ports"; - cout.width( 20 ); - cout.fill( ' ' ); - cout << "Installed"; - cout.width( 20 ); - cout.fill( ' ' ); - cout << "Available in the ports tree" << endl << endl; + printFormattedDiffLine("Port", + "Installed", + "Available in the ports tree", + false); + cout << endl; } - cout.setf( ios::left, ios::adjustfield ); - cout.width( 20 ); - cout.fill( ' ' ); - cout << it->first.c_str(); - cout.width( 20 ); - cout.fill( ' ' ); - cout << it->second.c_str(); - - string locked = ""; - if ( m_locker.isLocked( it->first ) ) { - locked = "locked"; - } - cout.width( 20 ); - cout.fill( ' ' ); - cout << (p->version()+"-"+p->release()).c_str() - << locked << endl; + printFormattedDiffLine(it->first, + it->second, + p->versionReleaseString(), + m_locker.isLocked( it->first )); } + } else if (result == UNDEFINED) { + m_undefinedVersionComp.push_back(make_pair(p, it->second)); } } } + if (m_undefinedVersionComp.size()) { + cout << "\n\n" << "Undecidable version differences (use --strict-diff)" + << endl << endl; + printFormattedDiffLine("Port", + "Installed", + "Available in the ports tree", + false); + cout << endl; + + list< pair< const Package*, string > >::iterator it = + m_undefinedVersionComp.begin(); + const Package* p; + for (; it != m_undefinedVersionComp.end(); ++it) { + p = it->first; + printFormattedDiffLine(p->name(), + p->versionReleaseString(), + it->second, + false); + } + } + + if ( count == 0 ) { cout << "No differences found" << endl; } @@ -920,8 +960,8 @@ void PrtGet::printPath() /*! helper method to print the result of an InstallTransaction */ void PrtGet::evaluateResult( InstallTransaction& transaction, - bool update, - bool interrupted ) + bool update, + bool interrupted ) { int errors = 0; @@ -942,7 +982,6 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, } } - const list< pair >& missing = transaction.missing(); if ( missing.size() ) { ++errors; @@ -1017,6 +1056,7 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, cout << endl; } + // readme's if ( atLeastOnePackageHasReadme ) { if ( m_config->readmeMode() == Configuration::VERBOSE_README ) { @@ -1031,9 +1071,25 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, } } } - - cout << endl; } + if ( m_undefinedVersionComp.size() ) { + cout << endl + << "-- Packages with undecidable version " + << "difference (use --strict-diff)" + << endl; + list< pair >::const_iterator uit = + m_undefinedVersionComp.begin(); + const Package * p; + for ( ; uit != m_undefinedVersionComp.end(); ++uit ) { + p = uit->first; + cout << p->name() << " (" + << p->versionReleaseString() + << " vs " + << uit->second << ")" << endl; + } + } + + cout << endl; if ( errors == 0 && !interrupted ) { cout << "prt-get: " << command[1] << " successfully" << endl; @@ -1093,23 +1149,23 @@ void PrtGet::createCache() /*! \return true if v1 is greater than v2 */ -bool PrtGet::greaterThan( const string& v1, const string& v2 ) +COMP_RESULT PrtGet::compareVersions( const string& v1, const string& v2 ) { - using namespace VersionComparator; - if (v1 == v2) { - return false; + return EQUAL; } if (m_parser->preferHigher() || (m_config->preferHigher() && !m_parser->strictDiff())) { - COMP_RESULT result = compareVersions(v1, v2); - return (result == GREATER); + COMP_RESULT result = VersionComparator::compareVersions(v1, v2); + return result; } - return v1 != v2; + if (v1 != v2) + return GREATER; + return LESS; } int PrtGet::returnValue() const @@ -1172,7 +1228,7 @@ void PrtGet::printf() if ( m_pkgDB->isInstalled( p->name() ) ) { string ip = p->name() + "-" + m_pkgDB->getPackageVersion( p->name() ); - if ( ip == p->name() + "-" + p->version() + "-" + p->release() ) { + if ( ip == p->name() + "-" + p->versionReleaseString() ) { isInst = "yes"; } else { isInst = "diff"; @@ -1255,15 +1311,15 @@ void PrtGet::printDependent() initRepo(); string arg = *(m_parser->otherArgs().begin()); - - if (m_parser) { + + if (m_parser->printTree()) { cout << arg << endl; printDependent(arg, 2); } else { printDependent(arg, 0); - } + } } - + void PrtGet::printDependent(const string& dep, int level) { map::const_iterator it = m_repo->packages().begin(); @@ -1294,7 +1350,7 @@ void PrtGet::printDependent(const string& dep, int level) // a -> b -> d // \ ^ // > c / - // + // // trying to rebuild 'd' before 'c' might possibly fail string indent = ""; if (m_parser->printTree()) { @@ -1305,26 +1361,26 @@ void PrtGet::printDependent(const string& dep, int level) set::iterator it2 = dependent.begin(); for ( ; it2 != dependent.end(); ++it2 ) { const Package* p = *it2; - + if (m_parser->recursive() && !m_parser->printTree()) { if (shownMap[p->name()]) { continue; } shownMap[p->name()] = true; } - + if ( m_parser->all() || m_pkgDB->isInstalled( p->name() ) ) { - + cout << indent << p->name(); if ( m_parser->verbose() > 0 ) { - cout << " " << p->version() << "-" << p->release(); + cout << " " << p->versionReleaseString(); } if ( m_parser->verbose() > 1 ) { cout << ": " << p->description(); } cout << endl; - + if (m_parser->recursive()) { printDependent( p->name(), level+2 ); } @@ -1338,7 +1394,7 @@ void PrtGet::listOrphans() map installed = m_pkgDB->installedPackages(); map required; map::iterator it = installed.begin(); - + for (; it != installed.end(); ++it) { list tokens; const Package* p = m_repo->getPackage(it->first); @@ -1349,12 +1405,12 @@ void PrtGet::listOrphans() required[*lit] = true; } } - } - + } + // - we could store the package pointer in another map to avoid // another getPackage lockup, but it seems better to optimized for // memory since it's only used when called with -vv - + it = installed.begin(); for (; it != installed.end(); ++it) { if (!required[it->first]) { @@ -1393,13 +1449,17 @@ void PrtGet::sysup() const map& installed = m_pkgDB->installedPackages(); map::const_iterator it = installed.begin(); const Package* p = 0; + COMP_RESULT result; for ( ; it != installed.end(); ++it ) { if ( !m_locker.isLocked( it->first ) ) { p = m_repo->getPackage( it->first ); if ( p ) { - if ( greaterThan( p->version() + "-" + p->release(), - it->second ) ) { + result = compareVersions( p->versionReleaseString(), + it->second ); + if (result == GREATER ) { packagesToUpdate.push_back( it->first ); + } else if (result == UNDEFINED ) { + m_undefinedVersionComp.push_back(make_pair(p, it->second)); } } } @@ -1906,7 +1966,7 @@ void PrtGet::printDepsLevel(int indent, const Package* package) } const Package* p = m_repo->getPackage( *it ); if (p) { - if (p->dependencies().length() > 0) { + if (p->dependencies().length() > 0) { map::iterator shownIt = shownMap.find(*it); if (shownIt != shownMap.end()) { cout << " -->" << endl;; diff --git a/src/prtget.h b/src/prtget.h index 1936b05..70f7445 100644 --- a/src/prtget.h +++ b/src/prtget.h @@ -25,6 +25,7 @@ using namespace std; #include "signaldispatcher.h" #include "locker.h" #include "installtransaction.h" +#include "versioncomparator.h" /*! \class PrtGet @@ -44,7 +45,7 @@ public: PG_INSTALL_ERROR, PG_PARTIAL_INSTALL_ERROR }; - + PrtGet( const ArgParser* parser ); ~PrtGet(); @@ -97,7 +98,7 @@ public: protected: void printDepsLevel(int indent, const Package* package); - + void printDependent(const std::string& dep, int level); void executeTransaction( InstallTransaction& transaction, @@ -116,6 +117,12 @@ protected: list& target ); void warnPackageNotFound(InstallTransaction& transaction); + + static void printFormattedDiffLine(const string& name, + const string& version1, + const string& version2, + bool locked); + Repository* m_repo; PkgDB* m_pkgDB; @@ -144,8 +151,11 @@ protected: void assertExactArgCount(int count); void argCountFailure(int count, const string& specifier); - bool greaterThan( const string& v1, const string& v2 ); + VersionComparator::COMP_RESULT + compareVersions( const string& v1, const string& v2 ); static bool printFile(const string& file); + + std::list< std::pair > m_undefinedVersionComp; }; #endif /* _PRTGET_H_ */