add support for optional dependencies
update docs to explain how optional dependencies are handled
This commit is contained in:
parent
8bc31c0745
commit
38bb3aa21a
@ -1,3 +1,8 @@
|
||||
* 10.03.2023 John McQuah
|
||||
- make it possible to consider optional dependencies when updating
|
||||
- bump version of the cache file format, to warn users about the
|
||||
'Packager' field being replaced by 'Optional'
|
||||
|
||||
* 5.16 26.06.2008 Johannes Winkelmann
|
||||
- don't loop forever when version= contains unsupported $() tokens
|
||||
- gcc 4.3 fixes (thanks Fredrik)
|
||||
|
15
README
15
README
@ -11,8 +11,8 @@ process.
|
||||
|
||||
Installing:
|
||||
-----------
|
||||
Just install the crux port from
|
||||
- http://www.hta-bi.bfh.ch/~winkj/files/crux/prt-get.prt.gz
|
||||
Download an iso of the latest CRUX release for a precompiled package.
|
||||
Otherwise, build from the sources in this repository.
|
||||
|
||||
prt-get has to know where to look for ports. You can specify those in
|
||||
/etc/prt-get.conf, one directory per line. Note that the order
|
||||
@ -20,15 +20,16 @@ matters, when the same port is in multiple direcories
|
||||
(e.g. /usr/ports/contrib/mutt and /usr/ports/local/mutt), the one
|
||||
found _first_ will be used.
|
||||
|
||||
Feel free to contact me in case of problems (jw@tks6.net)
|
||||
|
||||
Feel free to file a bug report on the Gitea issue tracker:
|
||||
https://git.crux.nu:82/farkuhar/prt-get/issues/
|
||||
|
||||
more information
|
||||
----------------
|
||||
See the man pages for prt-get(8), prt-get.conf(5) and prt-cache for more
|
||||
information. There is also a user manual in the doc directory (as a
|
||||
tex file). This document should also be available as PDF from
|
||||
http://www.hta-bi.bfh.ch/~winkj/files/crux/manual.pdf
|
||||
information. The CRUX homepage also offers a (somewhat dated) User Manual
|
||||
and Quick Start guide:
|
||||
https://crux.nu/doc/prt-get%20-%20User%20Manual.html
|
||||
https://crux.nu/doc/prt-get%20-%20Quick%20start.html
|
||||
|
||||
"it must be user error" (thinkgeek)
|
||||
-----------------------------------
|
||||
|
2
TODO
2
TODO
@ -10,7 +10,7 @@
|
||||
CONSIDER:
|
||||
|
||||
- default formats for printf and dup
|
||||
- add update-footprint, update-md5sum commands (patch in trac)
|
||||
- add update-footprint, update-signature commands
|
||||
- sysup
|
||||
- allow injecting of new (uninstalled) dependencies
|
||||
- allow to prohibit recompilation of packages when a dependency failed
|
||||
|
@ -48,6 +48,9 @@ preferhigher yes
|
||||
|
||||
# use regexps for searching (default no)
|
||||
useregex yes
|
||||
|
||||
# consider soft dependencies when sorting the update/sysup targets
|
||||
softdeps no
|
||||
.fi
|
||||
|
||||
.LP
|
||||
@ -90,6 +93,17 @@ if set to yes, prt-get will interpret search and filter patterns in
|
||||
list, listinst, printf, search, dsearch and fsearch as regular
|
||||
expressions. This will be the default in prt-get 0.6.
|
||||
|
||||
.B softdeps
|
||||
if set to yes, during an update operation prt-get will perform a greedy search
|
||||
of the dependency graph, visiting any \fBinstalled\fP optional dependency of
|
||||
the ports specified on the command line and recursing until either a leaf node is
|
||||
found (port that doesn't depend on anything else) or a cycle is created. If a
|
||||
cycle is \fBnot\fP created by following a soft dependency, then this dependency
|
||||
relationship is added to the list of edges, and topological sort of the
|
||||
resulting graph can proceed as usual. The default is \fBsoftdeps no\fP, which
|
||||
means prt-get will only consider hard dependencies when walking the directed
|
||||
graph.
|
||||
|
||||
.LP
|
||||
.B makecommand
|
||||
.B addcommand
|
||||
@ -155,6 +169,6 @@ problem :-)
|
||||
|
||||
|
||||
.SH "AUTHORS"
|
||||
Johannes Winkelmann <jw@tks6.net>
|
||||
Johannes Winkelmann <jw@tks6.net>, John McQuah <jmcquah at disroot dot org>
|
||||
.SH "SEE ALSO"
|
||||
prt-get(8), pkgmk(8) pkgadd(8), ports(8)
|
||||
|
@ -41,3 +41,6 @@ logfile /var/log/pkgbuild/%n.log
|
||||
|
||||
### use regexp search
|
||||
# useregex no # (yes|no)
|
||||
|
||||
### consider optional dependencies when sorting the update/sysup targets
|
||||
# softdeps no # (yes|no)
|
||||
|
@ -29,6 +29,7 @@ ArgParser::ArgParser( int argc, char** argv )
|
||||
m_noStdConfig( false ),
|
||||
m_writeLog( false ),
|
||||
m_nodeps( false ),
|
||||
m_softdeps( false ),
|
||||
m_all( false ),
|
||||
m_printPath( false ),
|
||||
m_execPreInstall( false ),
|
||||
@ -182,6 +183,8 @@ bool ArgParser::parse()
|
||||
m_useCache = true;
|
||||
} else if ( s == "--nodeps" ) {
|
||||
m_nodeps = true;
|
||||
} else if ( s == "--softdeps" ) {
|
||||
m_softdeps = true;
|
||||
} else if ( s == "--all" ) {
|
||||
m_all = true;
|
||||
} else if ( s == "--path" ) {
|
||||
@ -388,6 +391,14 @@ bool ArgParser::nodeps() const
|
||||
return m_nodeps;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return whether there was a --softdeps argument
|
||||
*/
|
||||
bool ArgParser::followSoftdeps() const
|
||||
{
|
||||
return m_softdeps;
|
||||
}
|
||||
|
||||
/*!
|
||||
\return whether there was a --all argument
|
||||
*/
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
bool recursive() const;
|
||||
bool printTree() const;
|
||||
bool depSort() const;
|
||||
bool followSoftdeps() const;
|
||||
|
||||
const string& alternateConfigFile() const;
|
||||
const string& pkgmkArgs() const;
|
||||
@ -99,6 +100,7 @@ private:
|
||||
bool m_writeLog;
|
||||
|
||||
bool m_nodeps;
|
||||
bool m_softdeps;
|
||||
|
||||
bool m_all;
|
||||
bool m_printPath;
|
||||
|
@ -34,6 +34,7 @@ Configuration::Configuration( const std::string& configFile,
|
||||
m_runScripts( false ),
|
||||
m_preferHigher( false ),
|
||||
m_useRegex( false ),
|
||||
m_followSoftdeps( false ),
|
||||
m_makeCommand( "" ), m_addCommand( "" ),
|
||||
m_removeCommand( "" ), m_runscriptCommand( "" )
|
||||
{
|
||||
@ -188,6 +189,14 @@ void Configuration::parseLine(const string& line, bool prepend)
|
||||
if ( s == "yes" ) {
|
||||
m_useRegex = true;
|
||||
}
|
||||
} else if ( startsWithNoCase( s, "softdeps" ) ) {
|
||||
s = stripWhiteSpace( s.replace( 0, 8, "" ) );
|
||||
if ( s == "yes" ) {
|
||||
m_followSoftdeps = true;
|
||||
}
|
||||
if ( s == "no" ) {
|
||||
m_followSoftdeps = false;
|
||||
}
|
||||
} else if ( startsWithNoCase( s, "makecommand" ) ) {
|
||||
m_makeCommand = stripWhiteSpace( s.replace( 0, 11, "" ) );
|
||||
} else if ( startsWithNoCase( s, "addcommand" ) ) {
|
||||
@ -234,4 +243,8 @@ bool Configuration::useRegex() const
|
||||
return m_useRegex;
|
||||
}
|
||||
|
||||
bool Configuration::followSoftdeps() const
|
||||
{
|
||||
return m_followSoftdeps;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
bool runScripts() const;
|
||||
bool preferHigher() const;
|
||||
bool useRegex() const;
|
||||
bool followSoftdeps() const;
|
||||
|
||||
void addConfig(const std::string& line,
|
||||
bool configSet,
|
||||
@ -72,6 +73,7 @@ private:
|
||||
bool m_runScripts;
|
||||
bool m_preferHigher;
|
||||
bool m_useRegex;
|
||||
bool m_followSoftdeps;
|
||||
|
||||
std::string m_makeCommand;
|
||||
std::string m_addCommand;
|
||||
|
@ -467,12 +467,13 @@ bool InstallTransaction::calculateDependencies()
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<string> treeWalk;
|
||||
list< pair<string, const Package*> >::const_iterator it =
|
||||
m_packages.begin();
|
||||
for ( ; it != m_packages.end(); ++it ) {
|
||||
const Package* package = it->second;
|
||||
if ( package ) {
|
||||
checkDependecies( package );
|
||||
checkDependencies( false, package );
|
||||
}
|
||||
}
|
||||
list<int> indexList;
|
||||
@ -491,14 +492,17 @@ bool InstallTransaction::calculateDependencies()
|
||||
|
||||
/*!
|
||||
recursive method to calculate dependencies
|
||||
\param package package for which we want to calculate dependencies
|
||||
\param depends index if the package \a package depends on (-1 for none)
|
||||
\param greedy (=true if any soft dependencies took us to the current node)
|
||||
\param package, package for which we want to calculate dependencies
|
||||
\param depends, index of the package \a package depends on (-1 for none)
|
||||
*/
|
||||
void InstallTransaction::checkDependecies( const Package* package,
|
||||
void InstallTransaction::checkDependencies( bool greedy,
|
||||
const Package* package,
|
||||
int depends )
|
||||
{
|
||||
int index = -1;
|
||||
bool newPackage = true;
|
||||
|
||||
for ( unsigned int i = 0; i < m_depList.size(); ++i ){
|
||||
if ( m_depList[i] == package->name() ) {
|
||||
index = i;
|
||||
@ -507,17 +511,28 @@ void InstallTransaction::checkDependecies( const Package* package,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( index == -1 ) {
|
||||
index = m_depList.size();
|
||||
if (( not greedy ) or ( m_pkgDB->isInstalled(package->name(),false) )) {
|
||||
m_depList.push_back( package->name() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( depends != -1 ) {
|
||||
m_resolver.addDependency( index, depends );
|
||||
} else {
|
||||
// did we already visit the current node when walking the tree?
|
||||
// return to the caller if such a cycle is detected
|
||||
for ( unsigned int i = 0; i < treeWalk.size(); ++i) {
|
||||
if ( treeWalk[i] == package->name() ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
treeWalk.push_back(package->name());
|
||||
|
||||
if ( depends == -1 ) {
|
||||
// this just adds index to the dependency resolver
|
||||
m_resolver.addDependency( index, index );
|
||||
} else {
|
||||
m_resolver.addDependency( index, depends );
|
||||
}
|
||||
|
||||
if ( newPackage ) {
|
||||
@ -534,15 +549,41 @@ void InstallTransaction::checkDependecies( const Package* package,
|
||||
}
|
||||
const Package* p = m_repo->getPackage( dep );
|
||||
if ( p ) {
|
||||
checkDependecies( p, index );
|
||||
checkDependencies( greedy, p, index );
|
||||
} else {
|
||||
m_missingPackages.
|
||||
push_back( make_pair( dep, package->name() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( (m_config->followSoftdeps()) and (!package->optionals().empty()) ) {
|
||||
list<string> softDeps;
|
||||
split( package->optionals(), ',', softDeps );
|
||||
list<string>::iterator it = softDeps.begin();
|
||||
for ( ; it != softDeps.end(); ++it ) {
|
||||
string softdep = *it;
|
||||
if ( !softdep.empty() ) {
|
||||
string::size_type pos = softdep.find_last_of( '/' );
|
||||
if ( pos != string::npos && (pos+1) < softdep.length() ) {
|
||||
softdep = softdep.substr( pos + 1 );
|
||||
}
|
||||
if ( m_pkgDB->isInstalled(softdep, true) ) {
|
||||
const Package* p = m_repo->getPackage( softdep );
|
||||
if ( p ) {
|
||||
checkDependencies( true, p, index );
|
||||
} else {
|
||||
m_missingPackages.
|
||||
push_back( make_pair( softdep, package->name() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset the tree traversal history
|
||||
treeWalk.pop_back();
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,7 +103,7 @@ public:
|
||||
|
||||
private:
|
||||
bool calculateDependencies();
|
||||
void checkDependecies( const Package* package, int depends=-1 );
|
||||
void checkDependencies( bool greedy, const Package* package, int depends=-1 );
|
||||
|
||||
InstallResult installPackage( const Package* package,
|
||||
const ArgParser* parser,
|
||||
@ -136,6 +136,7 @@ private:
|
||||
|
||||
list<string> m_depNameList;
|
||||
vector<string> m_depList;
|
||||
vector<string> treeWalk;
|
||||
|
||||
// packages requested to be installed not found in the ports tree
|
||||
list< pair<string, string> > m_missingPackages;
|
||||
|
@ -44,7 +44,7 @@ Package::Package( const string& name,
|
||||
const string& description,
|
||||
const string& dependencies,
|
||||
const string& url,
|
||||
const string& packager,
|
||||
const string& optionals,
|
||||
const string& maintainer,
|
||||
const string& hasReadme,
|
||||
const string& hasPreInstall,
|
||||
@ -53,7 +53,7 @@ Package::Package( const string& name,
|
||||
{
|
||||
m_data = new PackageData( name, path, version, release,
|
||||
description, dependencies, url,
|
||||
packager, maintainer, hasReadme,
|
||||
optionals, maintainer, hasReadme,
|
||||
hasPreInstall, hasPostInstall );
|
||||
|
||||
}
|
||||
@ -110,11 +110,11 @@ const string& Package::url() const
|
||||
return m_data->url;
|
||||
}
|
||||
|
||||
/*! \return the packager of this package */
|
||||
const string& Package::packager() const
|
||||
/*! \return the optional dependencies of this package */
|
||||
const string& Package::optionals() const
|
||||
{
|
||||
load();
|
||||
return m_data->packager;
|
||||
return m_data->optionals;
|
||||
}
|
||||
/*! \return the maintainer of this package */
|
||||
const string& Package::maintainer() const
|
||||
@ -202,15 +202,36 @@ void Package::load() const
|
||||
if ( startsWithNoCase( line, "desc" ) ) {
|
||||
m_data->description =
|
||||
stripWhiteSpace( getValue( line, ':' ) );
|
||||
|
||||
} else if ( startsWithNoCase( line, "pack" ) ) {
|
||||
m_data->packager =
|
||||
stripWhiteSpace( getValue( line, ':' ) );
|
||||
} else if ( startsWithNoCase( line, "maint" ) ) {
|
||||
m_data->maintainer =
|
||||
stripWhiteSpace( getValue( line, ':' ) );
|
||||
} else if ( startsWithNoCase( line, "url" ) ) {
|
||||
m_data->url = stripWhiteSpace( getValue( line, ':' ) );
|
||||
} else if ( startsWithNoCase( line, "optional" ) or
|
||||
startsWithNoCase( line, "nice to have" ) ) {
|
||||
string softdeps = stripWhiteSpace( getValue( line, ':' ) );
|
||||
|
||||
StringHelper::replaceAll( softdeps, " ", "," );
|
||||
StringHelper::replaceAll( softdeps, ",,", "," );
|
||||
|
||||
// TODO: decide which one to use
|
||||
#if 0
|
||||
// remove commented out packages
|
||||
list<string> softDepList = StringHelper::split( softdeps, ',' );
|
||||
list<string>::iterator it = deps.begin();
|
||||
for ( ; it != softDepList.end(); ++it ) {
|
||||
if ( (*it)[0] == '#' ) {
|
||||
cerr << "Commented dep: " << *it << endl;
|
||||
} else {
|
||||
if ( it != softDepsList.begin() ) {
|
||||
m_data->optionals += ",";
|
||||
}
|
||||
m_data->optionals += *it;
|
||||
}
|
||||
}
|
||||
#else
|
||||
m_data->optionals = softdeps;
|
||||
#endif
|
||||
} else if ( startsWithNoCase( line, "dep" ) ) {
|
||||
string depends = stripWhiteSpace( getValue( line, ':' ) );
|
||||
|
||||
@ -265,6 +286,11 @@ void Package::setDependencies( const std::string& dependencies )
|
||||
m_data->depends = dependencies;
|
||||
}
|
||||
|
||||
void Package::setOptionals( const std::string& optionals )
|
||||
{
|
||||
m_data->optionals = optionals;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PackageData::PackageData( const string& name_,
|
||||
@ -274,7 +300,7 @@ PackageData::PackageData( const string& name_,
|
||||
const string& description_,
|
||||
const string& dependencies_,
|
||||
const string& url_,
|
||||
const string& packager_,
|
||||
const string& optionals_,
|
||||
const string& maintainer_,
|
||||
const string& hasReadme_,
|
||||
const string& hasPreInstall_,
|
||||
@ -286,7 +312,7 @@ PackageData::PackageData( const string& name_,
|
||||
description( description_ ),
|
||||
depends( dependencies_ ),
|
||||
url( url_ ),
|
||||
packager( packager_ ),
|
||||
optionals( optionals_ ),
|
||||
maintainer( maintainer_ )
|
||||
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
const std::string& description,
|
||||
const std::string& dependencies,
|
||||
const std::string& url,
|
||||
const std::string& packager,
|
||||
const std::string& optionals,
|
||||
const std::string& maintainer,
|
||||
const std::string& hasReadme,
|
||||
const std::string& hasPreInstall,
|
||||
@ -50,7 +50,7 @@ public:
|
||||
const std::string& description() const;
|
||||
const std::string& dependencies() const;
|
||||
const std::string& url() const;
|
||||
const std::string& packager() const;
|
||||
const std::string& optionals() const;
|
||||
const std::string& maintainer() const;
|
||||
const bool hasReadme() const;
|
||||
const bool hasPreInstall() const;
|
||||
@ -59,6 +59,7 @@ public:
|
||||
std::string versionReleaseString() const;
|
||||
|
||||
void setDependencies( const std::string& dependencies );
|
||||
void setOptionals( const std::string& optionals );
|
||||
|
||||
|
||||
private:
|
||||
@ -82,7 +83,7 @@ struct PackageData
|
||||
const std::string& description_="",
|
||||
const std::string& dependencies_="",
|
||||
const std::string& url_="",
|
||||
const std::string& packager="",
|
||||
const std::string& optionals_="",
|
||||
const std::string& maintainer="",
|
||||
const std::string& hasReadme_="",
|
||||
const std::string& hasPreInstall_="",
|
||||
@ -95,7 +96,7 @@ struct PackageData
|
||||
std::string description;
|
||||
std::string depends;
|
||||
std::string url;
|
||||
std::string packager;
|
||||
std::string optionals;
|
||||
std::string maintainer;
|
||||
|
||||
std::string versionReleaseString;
|
||||
|
175
src/prtget.cpp
175
src/prtget.cpp
@ -73,6 +73,7 @@ PrtGet::PrtGet( const ArgParser* parser )
|
||||
readConfig();
|
||||
|
||||
m_useRegex = m_config->useRegex() || m_parser->useRegex();
|
||||
m_followSoftdeps = m_config->followSoftdeps() || m_parser->followSoftdeps();
|
||||
}
|
||||
|
||||
/*! destruct PrtGet object */
|
||||
@ -152,6 +153,8 @@ void PrtGet::printUsage()
|
||||
<< "depend on 'port'"
|
||||
<< endl;
|
||||
cout << " where opt can be:" << endl;
|
||||
cout << " --softdeps consider optional dependencies too"
|
||||
<< endl;
|
||||
cout << " --all list all dependent packages, not "
|
||||
<< "only installed" << endl;
|
||||
cout << " --recursive print recursive listing" << endl;
|
||||
@ -205,16 +208,12 @@ void PrtGet::printUsage()
|
||||
cout << " sysup [opt] update all outdated ports"
|
||||
<< endl;
|
||||
cout << " where opt can be:" << endl;
|
||||
cout << " --nodeps don't sort by dependencies"
|
||||
cout << " --nodeps don't sort by dependencies"
|
||||
<< endl;
|
||||
cout << " --test test mode" << endl;
|
||||
cout << " --log write log file"<< endl;
|
||||
cout << " --prefer-higher prefer higher installed "
|
||||
<< "versions over lower ones in ports tree"
|
||||
<< endl;
|
||||
cout << " --strict-diff override prefer higher "
|
||||
<< "configuration setting"
|
||||
cout << " --softdeps consider optional dependencies when sorting"
|
||||
<< endl;
|
||||
cout << " --test test mode" << endl;
|
||||
cout << " --log write log file"<< endl;
|
||||
|
||||
cout << " lock <port1 port2...> lock current version "
|
||||
<< "of packages"
|
||||
@ -395,16 +394,15 @@ void PrtGet::printInfo()
|
||||
if ( !p->url().empty() ) {
|
||||
cout << "URL: " << p->url() << endl;
|
||||
}
|
||||
if ( !p->packager().empty() ) {
|
||||
cout << "Packager: " << p->packager() << endl;
|
||||
}
|
||||
if ( !p->maintainer().empty() ) {
|
||||
cout << "Maintainer: " << p->maintainer() << endl;
|
||||
}
|
||||
|
||||
if ( !p->dependencies().empty() ) {
|
||||
cout << "Dependencies: " << p->dependencies() << endl;
|
||||
}
|
||||
if ( !p->optionals().empty() ) {
|
||||
cout << "Optional: " << p->optionals() << endl;
|
||||
}
|
||||
|
||||
// TODO: don't hardcode file names
|
||||
string filesString = "";
|
||||
@ -765,7 +763,11 @@ void PrtGet::printDepends( bool simpleListing )
|
||||
}
|
||||
} else {
|
||||
if ( deps.size() > 0 ) {
|
||||
cout << "-- dependencies ([i] = installed)" << endl;
|
||||
cout << "-- dependencies (";
|
||||
if ( m_followSoftdeps ) {
|
||||
cout << "including optionals, ";
|
||||
}
|
||||
cout << "[i] = installed)" << endl;
|
||||
list<string>::const_iterator it = deps.begin();
|
||||
|
||||
bool isAlias;
|
||||
@ -1268,7 +1270,7 @@ void PrtGet::printf()
|
||||
StringHelper::replaceAll( output, "%r", p->release() );
|
||||
StringHelper::replaceAll( output, "%d", p->description() );
|
||||
StringHelper::replaceAll( output, "%e", p->dependencies() );
|
||||
StringHelper::replaceAll( output, "%P", p->packager() );
|
||||
StringHelper::replaceAll( output, "%P", p->optionals() );
|
||||
StringHelper::replaceAll( output, "%M", p->maintainer() );
|
||||
|
||||
StringHelper::replaceAll( output, "\\t", "\t" );
|
||||
@ -1281,7 +1283,7 @@ void PrtGet::printf()
|
||||
StringHelper::replaceAll( sortkey, "%r", p->release() );
|
||||
StringHelper::replaceAll( sortkey, "%d", p->description() );
|
||||
StringHelper::replaceAll( sortkey, "%e", p->dependencies() );
|
||||
StringHelper::replaceAll( sortkey, "%P", p->packager() );
|
||||
StringHelper::replaceAll( sortkey, "%P", p->optionals() );
|
||||
StringHelper::replaceAll( sortkey, "%M", p->maintainer() );
|
||||
|
||||
string isInst = "no";
|
||||
@ -1371,6 +1373,7 @@ void PrtGet::printDependent()
|
||||
|
||||
initRepo();
|
||||
string arg = *(m_parser->otherArgs().begin());
|
||||
vector<string> treeWalk;
|
||||
|
||||
if (m_parser->printTree()) {
|
||||
cout << arg << endl;
|
||||
@ -1385,6 +1388,14 @@ void PrtGet::printDependent(const string& dep, int level)
|
||||
map<string, Package*>::const_iterator it = m_repo->packages().begin();
|
||||
static map<string, bool> shownMap;
|
||||
|
||||
/* cycle detection --- code duplicated from checkDependencies */
|
||||
for ( unsigned int i=0; i != treeWalk.size() ; ++i ) {
|
||||
if ( treeWalk[i] == dep ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
treeWalk.push_back(dep);
|
||||
|
||||
set<const Package*> dependent;
|
||||
for ( ; it != m_repo->packages().end(); ++it ) {
|
||||
|
||||
@ -1400,6 +1411,17 @@ void PrtGet::printDependent(const string& dep, int level)
|
||||
dependent.insert( p );
|
||||
}
|
||||
}
|
||||
if ( p && m_pkgDB->isInstalled(p->name(),false) && m_followSoftdeps
|
||||
&& p->optionals().find( dep ) != string::npos ) {
|
||||
list<string> tokens;
|
||||
StringHelper::split( p->optionals(), ',', tokens );
|
||||
list<string>::iterator it = find( tokens.begin(),
|
||||
tokens.end(),
|
||||
dep );
|
||||
if ( it != tokens.end() ) {
|
||||
dependent.insert( p );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - there are two modes, tree and non-tree recursive mode; in
|
||||
@ -1446,6 +1468,8 @@ void PrtGet::printDependent(const string& dep, int level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
treeWalk.pop_back();
|
||||
}
|
||||
|
||||
void PrtGet::listOrphans()
|
||||
@ -1464,6 +1488,15 @@ void PrtGet::listOrphans()
|
||||
for (; lit != tokens.end(); ++lit) {
|
||||
required[*lit] = true;
|
||||
}
|
||||
if (m_followSoftdeps) {
|
||||
StringHelper::split( p->optionals(), ',', tokens );
|
||||
lit = tokens.begin();
|
||||
for (; lit != tokens.end(); ++lit) {
|
||||
if ( m_pkgDB->isInstalled(*lit,false) ) {
|
||||
required[*lit] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1990,67 +2023,95 @@ void PrtGet::printDependTree()
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->dependencies().length() > 0) {
|
||||
|
||||
cout << "-- dependencies ([i] = installed";
|
||||
if ( (p->dependencies().length() > 0) or
|
||||
(m_followSoftdeps && p->optionals().length() > 0) ) {
|
||||
cout << "-- dependencies (";
|
||||
if ( m_followSoftdeps ) {
|
||||
cout << "[s] soft, ";
|
||||
}
|
||||
cout << "[i] hard, [ ] not installed";
|
||||
if (!m_parser->all()) {
|
||||
cout << ", '-->' = seen before";
|
||||
cout << ", '-->' already shown";
|
||||
}
|
||||
cout << ")" << endl;
|
||||
if ( m_pkgDB->isInstalled( *it ) ) {
|
||||
cout << "[i] ";
|
||||
} else {
|
||||
cout << "[ ] ";
|
||||
}
|
||||
cout << p->name() << endl;
|
||||
printDepsLevel(2, p);
|
||||
printDepsLevel(2, p, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PrtGet::printDepsLevel(int indent, const Package* package)
|
||||
void PrtGet::printDepsLevel(int indent, const Package* package, bool greedy)
|
||||
{
|
||||
static map<string, bool> shownMap;
|
||||
string installStatus;
|
||||
bool isAlias = false;
|
||||
string aliasName = "";
|
||||
|
||||
/* cycle detection -- code duplicated from checkDependencies */
|
||||
for (unsigned int i=0; i<treeWalk.size(); ++i) {
|
||||
if (treeWalk[i] == package->name()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
treeWalk.push_back(package->name());
|
||||
|
||||
if ( m_pkgDB->isInstalled( package->name(), true, &isAlias, &aliasName ) ) {
|
||||
installStatus = ( greedy ) ? "[s] " : "[i] ";
|
||||
cout << installStatus;
|
||||
} else {
|
||||
cout << "[ ] ";
|
||||
}
|
||||
for (int i = 0; i < indent; ++i) {
|
||||
cout << " ";
|
||||
}
|
||||
cout << package->name();
|
||||
if (isAlias) {
|
||||
cout << " (provided by " << aliasName << ")";
|
||||
}
|
||||
map<string, bool>::iterator shownIt = shownMap.find(package->name());
|
||||
if (shownIt != shownMap.end()) {
|
||||
cout << " -->" << endl;
|
||||
treeWalk.pop_back();
|
||||
return;
|
||||
} else {
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
list<string> deps;
|
||||
StringHelper::split(package->dependencies(), ',', deps);
|
||||
list<string>::iterator it = deps.begin();
|
||||
bool isAlias = false;
|
||||
string aliasName = "";
|
||||
|
||||
for (; it != deps.end(); ++it) {
|
||||
if ( m_pkgDB->isInstalled( *it, true, &isAlias, &aliasName ) ) {
|
||||
cout << "[i] ";
|
||||
} else {
|
||||
cout << "[ ] ";
|
||||
}
|
||||
for (int i = 0; i < indent; ++i) {
|
||||
cout << " ";
|
||||
}
|
||||
cout << *it;
|
||||
if (isAlias) {
|
||||
cout << " (provided by " << aliasName << ")";
|
||||
}
|
||||
const Package* p = m_repo->getPackage( *it );
|
||||
if (p) {
|
||||
if (p->dependencies().length() > 0) {
|
||||
map<string, bool>::iterator shownIt = shownMap.find(*it);
|
||||
if (shownIt != shownMap.end()) {
|
||||
cout << " -->" << endl;;
|
||||
} else {
|
||||
cout << endl;
|
||||
printDepsLevel(indent+2, p);
|
||||
if (!m_parser->all()) {
|
||||
shownMap[*it] = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cout << endl;
|
||||
}
|
||||
printDepsLevel(indent+2, p, greedy);
|
||||
if (!m_parser->all()) {
|
||||
shownMap[*it] = true;
|
||||
}
|
||||
} else {
|
||||
cout << " (not found in ports tree)" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_followSoftdeps ) {
|
||||
list<string> softDeps;
|
||||
StringHelper::split(package->optionals(), ',', softDeps);
|
||||
list<string>::iterator it = softDeps.begin();
|
||||
for (; it != softDeps.end(); ++it) {
|
||||
if ( m_pkgDB->isInstalled(*it, true) ) {
|
||||
const Package* p = m_repo->getPackage( *it );
|
||||
if (p) {
|
||||
printDepsLevel(indent+2,p,true);
|
||||
if (!m_parser->all()) {
|
||||
shownMap[*it] = true;
|
||||
}
|
||||
} else {
|
||||
cout << " (not found in ports tree)" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset the tree traversal history
|
||||
treeWalk.pop_back();
|
||||
}
|
||||
|
||||
void PrtGet::dumpConfig()
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
void printDepsLevel(int indent, const Package* package);
|
||||
void printDepsLevel(int indent, const Package* package, bool greedy);
|
||||
|
||||
void printDependent(const std::string& dep, int level);
|
||||
|
||||
@ -138,6 +138,8 @@ protected:
|
||||
int m_returnValue;
|
||||
|
||||
bool m_useRegex;
|
||||
bool m_followSoftdeps;
|
||||
vector<string> treeWalk;
|
||||
|
||||
/*! Name of default configuration file */
|
||||
static const string CONF_FILE;
|
||||
|
@ -264,7 +264,7 @@ Repository::initFromCache( const string& cacheFile )
|
||||
// FIELDS:
|
||||
// name, path, version, release,
|
||||
// description, dependencies, url,
|
||||
// packager, maintainer, hasReadme;
|
||||
// optionals, maintainer, hasReadme;
|
||||
// hasPreInstall, hasPostInstall
|
||||
const int fieldCount = 12;
|
||||
string fields[fieldCount];
|
||||
@ -351,7 +351,7 @@ Repository::WriteResult Repository::writeCache( const string& cacheFile )
|
||||
p->description().c_str(),
|
||||
p->dependencies().c_str(),
|
||||
p->url().c_str(),
|
||||
p->packager().c_str(),
|
||||
p->optionals().c_str(),
|
||||
p->maintainer().c_str(),
|
||||
hasReadme, hasPreInstall, hasPostInstall );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user