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
|
* 5.16 26.06.2008 Johannes Winkelmann
|
||||||
- don't loop forever when version= contains unsupported $() tokens
|
- don't loop forever when version= contains unsupported $() tokens
|
||||||
- gcc 4.3 fixes (thanks Fredrik)
|
- gcc 4.3 fixes (thanks Fredrik)
|
||||||
|
|
15
README
15
README
|
@ -11,8 +11,8 @@ process.
|
||||||
|
|
||||||
Installing:
|
Installing:
|
||||||
-----------
|
-----------
|
||||||
Just install the crux port from
|
Download an iso of the latest CRUX release for a precompiled package.
|
||||||
- http://www.hta-bi.bfh.ch/~winkj/files/crux/prt-get.prt.gz
|
Otherwise, build from the sources in this repository.
|
||||||
|
|
||||||
prt-get has to know where to look for ports. You can specify those in
|
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
|
/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
|
(e.g. /usr/ports/contrib/mutt and /usr/ports/local/mutt), the one
|
||||||
found _first_ will be used.
|
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
|
more information
|
||||||
----------------
|
----------------
|
||||||
See the man pages for prt-get(8), prt-get.conf(5) and prt-cache for more
|
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
|
information. The CRUX homepage also offers a (somewhat dated) User Manual
|
||||||
tex file). This document should also be available as PDF from
|
and Quick Start guide:
|
||||||
http://www.hta-bi.bfh.ch/~winkj/files/crux/manual.pdf
|
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)
|
"it must be user error" (thinkgeek)
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
2
TODO
2
TODO
|
@ -10,7 +10,7 @@
|
||||||
CONSIDER:
|
CONSIDER:
|
||||||
|
|
||||||
- default formats for printf and dup
|
- default formats for printf and dup
|
||||||
- add update-footprint, update-md5sum commands (patch in trac)
|
- add update-footprint, update-signature commands
|
||||||
- sysup
|
- sysup
|
||||||
- allow injecting of new (uninstalled) dependencies
|
- allow injecting of new (uninstalled) dependencies
|
||||||
- allow to prohibit recompilation of packages when a dependency failed
|
- allow to prohibit recompilation of packages when a dependency failed
|
||||||
|
|
|
@ -48,6 +48,9 @@ preferhigher yes
|
||||||
|
|
||||||
# use regexps for searching (default no)
|
# use regexps for searching (default no)
|
||||||
useregex yes
|
useregex yes
|
||||||
|
|
||||||
|
# consider soft dependencies when sorting the update/sysup targets
|
||||||
|
softdeps no
|
||||||
.fi
|
.fi
|
||||||
|
|
||||||
.LP
|
.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
|
list, listinst, printf, search, dsearch and fsearch as regular
|
||||||
expressions. This will be the default in prt-get 0.6.
|
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
|
.LP
|
||||||
.B makecommand
|
.B makecommand
|
||||||
.B addcommand
|
.B addcommand
|
||||||
|
@ -155,6 +169,6 @@ problem :-)
|
||||||
|
|
||||||
|
|
||||||
.SH "AUTHORS"
|
.SH "AUTHORS"
|
||||||
Johannes Winkelmann <jw@tks6.net>
|
Johannes Winkelmann <jw@tks6.net>, John McQuah <jmcquah at disroot dot org>
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
prt-get(8), pkgmk(8) pkgadd(8), ports(8)
|
prt-get(8), pkgmk(8) pkgadd(8), ports(8)
|
||||||
|
|
|
@ -41,3 +41,6 @@ logfile /var/log/pkgbuild/%n.log
|
||||||
|
|
||||||
### use regexp search
|
### use regexp search
|
||||||
# useregex no # (yes|no)
|
# 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_noStdConfig( false ),
|
||||||
m_writeLog( false ),
|
m_writeLog( false ),
|
||||||
m_nodeps( false ),
|
m_nodeps( false ),
|
||||||
|
m_softdeps( false ),
|
||||||
m_all( false ),
|
m_all( false ),
|
||||||
m_printPath( false ),
|
m_printPath( false ),
|
||||||
m_execPreInstall( false ),
|
m_execPreInstall( false ),
|
||||||
|
@ -182,6 +183,8 @@ bool ArgParser::parse()
|
||||||
m_useCache = true;
|
m_useCache = true;
|
||||||
} else if ( s == "--nodeps" ) {
|
} else if ( s == "--nodeps" ) {
|
||||||
m_nodeps = true;
|
m_nodeps = true;
|
||||||
|
} else if ( s == "--softdeps" ) {
|
||||||
|
m_softdeps = true;
|
||||||
} else if ( s == "--all" ) {
|
} else if ( s == "--all" ) {
|
||||||
m_all = true;
|
m_all = true;
|
||||||
} else if ( s == "--path" ) {
|
} else if ( s == "--path" ) {
|
||||||
|
@ -388,6 +391,14 @@ bool ArgParser::nodeps() const
|
||||||
return m_nodeps;
|
return m_nodeps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\return whether there was a --softdeps argument
|
||||||
|
*/
|
||||||
|
bool ArgParser::followSoftdeps() const
|
||||||
|
{
|
||||||
|
return m_softdeps;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\return whether there was a --all argument
|
\return whether there was a --all argument
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
bool recursive() const;
|
bool recursive() const;
|
||||||
bool printTree() const;
|
bool printTree() const;
|
||||||
bool depSort() const;
|
bool depSort() const;
|
||||||
|
bool followSoftdeps() const;
|
||||||
|
|
||||||
const string& alternateConfigFile() const;
|
const string& alternateConfigFile() const;
|
||||||
const string& pkgmkArgs() const;
|
const string& pkgmkArgs() const;
|
||||||
|
@ -99,6 +100,7 @@ private:
|
||||||
bool m_writeLog;
|
bool m_writeLog;
|
||||||
|
|
||||||
bool m_nodeps;
|
bool m_nodeps;
|
||||||
|
bool m_softdeps;
|
||||||
|
|
||||||
bool m_all;
|
bool m_all;
|
||||||
bool m_printPath;
|
bool m_printPath;
|
||||||
|
|
|
@ -34,6 +34,7 @@ Configuration::Configuration( const std::string& configFile,
|
||||||
m_runScripts( false ),
|
m_runScripts( false ),
|
||||||
m_preferHigher( false ),
|
m_preferHigher( false ),
|
||||||
m_useRegex( false ),
|
m_useRegex( false ),
|
||||||
|
m_followSoftdeps( false ),
|
||||||
m_makeCommand( "" ), m_addCommand( "" ),
|
m_makeCommand( "" ), m_addCommand( "" ),
|
||||||
m_removeCommand( "" ), m_runscriptCommand( "" )
|
m_removeCommand( "" ), m_runscriptCommand( "" )
|
||||||
{
|
{
|
||||||
|
@ -188,6 +189,14 @@ void Configuration::parseLine(const string& line, bool prepend)
|
||||||
if ( s == "yes" ) {
|
if ( s == "yes" ) {
|
||||||
m_useRegex = true;
|
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" ) ) {
|
} else if ( startsWithNoCase( s, "makecommand" ) ) {
|
||||||
m_makeCommand = stripWhiteSpace( s.replace( 0, 11, "" ) );
|
m_makeCommand = stripWhiteSpace( s.replace( 0, 11, "" ) );
|
||||||
} else if ( startsWithNoCase( s, "addcommand" ) ) {
|
} else if ( startsWithNoCase( s, "addcommand" ) ) {
|
||||||
|
@ -234,4 +243,8 @@ bool Configuration::useRegex() const
|
||||||
return m_useRegex;
|
return m_useRegex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Configuration::followSoftdeps() const
|
||||||
|
{
|
||||||
|
return m_followSoftdeps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ public:
|
||||||
bool runScripts() const;
|
bool runScripts() const;
|
||||||
bool preferHigher() const;
|
bool preferHigher() const;
|
||||||
bool useRegex() const;
|
bool useRegex() const;
|
||||||
|
bool followSoftdeps() const;
|
||||||
|
|
||||||
void addConfig(const std::string& line,
|
void addConfig(const std::string& line,
|
||||||
bool configSet,
|
bool configSet,
|
||||||
|
@ -72,6 +73,7 @@ private:
|
||||||
bool m_runScripts;
|
bool m_runScripts;
|
||||||
bool m_preferHigher;
|
bool m_preferHigher;
|
||||||
bool m_useRegex;
|
bool m_useRegex;
|
||||||
|
bool m_followSoftdeps;
|
||||||
|
|
||||||
std::string m_makeCommand;
|
std::string m_makeCommand;
|
||||||
std::string m_addCommand;
|
std::string m_addCommand;
|
||||||
|
|
|
@ -467,12 +467,13 @@ bool InstallTransaction::calculateDependencies()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<string> treeWalk;
|
||||||
list< pair<string, const Package*> >::const_iterator it =
|
list< pair<string, const Package*> >::const_iterator it =
|
||||||
m_packages.begin();
|
m_packages.begin();
|
||||||
for ( ; it != m_packages.end(); ++it ) {
|
for ( ; it != m_packages.end(); ++it ) {
|
||||||
const Package* package = it->second;
|
const Package* package = it->second;
|
||||||
if ( package ) {
|
if ( package ) {
|
||||||
checkDependecies( package );
|
checkDependencies( false, package );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list<int> indexList;
|
list<int> indexList;
|
||||||
|
@ -491,14 +492,17 @@ bool InstallTransaction::calculateDependencies()
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
recursive method to calculate dependencies
|
recursive method to calculate dependencies
|
||||||
\param package package for which we want to calculate dependencies
|
\param greedy (=true if any soft dependencies took us to the current node)
|
||||||
\param depends index if the package \a package depends on (-1 for none)
|
\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 depends )
|
||||||
{
|
{
|
||||||
int index = -1;
|
int index = -1;
|
||||||
bool newPackage = true;
|
bool newPackage = true;
|
||||||
|
|
||||||
for ( unsigned int i = 0; i < m_depList.size(); ++i ){
|
for ( unsigned int i = 0; i < m_depList.size(); ++i ){
|
||||||
if ( m_depList[i] == package->name() ) {
|
if ( m_depList[i] == package->name() ) {
|
||||||
index = i;
|
index = i;
|
||||||
|
@ -507,17 +511,28 @@ void InstallTransaction::checkDependecies( const Package* package,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( index == -1 ) {
|
if ( index == -1 ) {
|
||||||
index = m_depList.size();
|
index = m_depList.size();
|
||||||
|
if (( not greedy ) or ( m_pkgDB->isInstalled(package->name(),false) )) {
|
||||||
m_depList.push_back( package->name() );
|
m_depList.push_back( package->name() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( depends != -1 ) {
|
// did we already visit the current node when walking the tree?
|
||||||
m_resolver.addDependency( index, depends );
|
// return to the caller if such a cycle is detected
|
||||||
} else {
|
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
|
// this just adds index to the dependency resolver
|
||||||
m_resolver.addDependency( index, index );
|
m_resolver.addDependency( index, index );
|
||||||
|
} else {
|
||||||
|
m_resolver.addDependency( index, depends );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( newPackage ) {
|
if ( newPackage ) {
|
||||||
|
@ -534,15 +549,41 @@ void InstallTransaction::checkDependecies( const Package* package,
|
||||||
}
|
}
|
||||||
const Package* p = m_repo->getPackage( dep );
|
const Package* p = m_repo->getPackage( dep );
|
||||||
if ( p ) {
|
if ( p ) {
|
||||||
checkDependecies( p, index );
|
checkDependencies( greedy, p, index );
|
||||||
} else {
|
} else {
|
||||||
m_missingPackages.
|
m_missingPackages.
|
||||||
push_back( make_pair( dep, package->name() ) );
|
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:
|
private:
|
||||||
bool calculateDependencies();
|
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,
|
InstallResult installPackage( const Package* package,
|
||||||
const ArgParser* parser,
|
const ArgParser* parser,
|
||||||
|
@ -136,6 +136,7 @@ private:
|
||||||
|
|
||||||
list<string> m_depNameList;
|
list<string> m_depNameList;
|
||||||
vector<string> m_depList;
|
vector<string> m_depList;
|
||||||
|
vector<string> treeWalk;
|
||||||
|
|
||||||
// packages requested to be installed not found in the ports tree
|
// packages requested to be installed not found in the ports tree
|
||||||
list< pair<string, string> > m_missingPackages;
|
list< pair<string, string> > m_missingPackages;
|
||||||
|
|
|
@ -44,7 +44,7 @@ Package::Package( const string& name,
|
||||||
const string& description,
|
const string& description,
|
||||||
const string& dependencies,
|
const string& dependencies,
|
||||||
const string& url,
|
const string& url,
|
||||||
const string& packager,
|
const string& optionals,
|
||||||
const string& maintainer,
|
const string& maintainer,
|
||||||
const string& hasReadme,
|
const string& hasReadme,
|
||||||
const string& hasPreInstall,
|
const string& hasPreInstall,
|
||||||
|
@ -53,7 +53,7 @@ Package::Package( const string& name,
|
||||||
{
|
{
|
||||||
m_data = new PackageData( name, path, version, release,
|
m_data = new PackageData( name, path, version, release,
|
||||||
description, dependencies, url,
|
description, dependencies, url,
|
||||||
packager, maintainer, hasReadme,
|
optionals, maintainer, hasReadme,
|
||||||
hasPreInstall, hasPostInstall );
|
hasPreInstall, hasPostInstall );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -110,11 +110,11 @@ const string& Package::url() const
|
||||||
return m_data->url;
|
return m_data->url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \return the packager of this package */
|
/*! \return the optional dependencies of this package */
|
||||||
const string& Package::packager() const
|
const string& Package::optionals() const
|
||||||
{
|
{
|
||||||
load();
|
load();
|
||||||
return m_data->packager;
|
return m_data->optionals;
|
||||||
}
|
}
|
||||||
/*! \return the maintainer of this package */
|
/*! \return the maintainer of this package */
|
||||||
const string& Package::maintainer() const
|
const string& Package::maintainer() const
|
||||||
|
@ -202,15 +202,36 @@ void Package::load() const
|
||||||
if ( startsWithNoCase( line, "desc" ) ) {
|
if ( startsWithNoCase( line, "desc" ) ) {
|
||||||
m_data->description =
|
m_data->description =
|
||||||
stripWhiteSpace( getValue( line, ':' ) );
|
stripWhiteSpace( getValue( line, ':' ) );
|
||||||
|
|
||||||
} else if ( startsWithNoCase( line, "pack" ) ) {
|
|
||||||
m_data->packager =
|
|
||||||
stripWhiteSpace( getValue( line, ':' ) );
|
|
||||||
} else if ( startsWithNoCase( line, "maint" ) ) {
|
} else if ( startsWithNoCase( line, "maint" ) ) {
|
||||||
m_data->maintainer =
|
m_data->maintainer =
|
||||||
stripWhiteSpace( getValue( line, ':' ) );
|
stripWhiteSpace( getValue( line, ':' ) );
|
||||||
} else if ( startsWithNoCase( line, "url" ) ) {
|
} else if ( startsWithNoCase( line, "url" ) ) {
|
||||||
m_data->url = stripWhiteSpace( getValue( line, ':' ) );
|
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" ) ) {
|
} else if ( startsWithNoCase( line, "dep" ) ) {
|
||||||
string depends = stripWhiteSpace( getValue( line, ':' ) );
|
string depends = stripWhiteSpace( getValue( line, ':' ) );
|
||||||
|
|
||||||
|
@ -265,6 +286,11 @@ void Package::setDependencies( const std::string& dependencies )
|
||||||
m_data->depends = dependencies;
|
m_data->depends = dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Package::setOptionals( const std::string& optionals )
|
||||||
|
{
|
||||||
|
m_data->optionals = optionals;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PackageData::PackageData( const string& name_,
|
PackageData::PackageData( const string& name_,
|
||||||
|
@ -274,7 +300,7 @@ PackageData::PackageData( const string& name_,
|
||||||
const string& description_,
|
const string& description_,
|
||||||
const string& dependencies_,
|
const string& dependencies_,
|
||||||
const string& url_,
|
const string& url_,
|
||||||
const string& packager_,
|
const string& optionals_,
|
||||||
const string& maintainer_,
|
const string& maintainer_,
|
||||||
const string& hasReadme_,
|
const string& hasReadme_,
|
||||||
const string& hasPreInstall_,
|
const string& hasPreInstall_,
|
||||||
|
@ -286,7 +312,7 @@ PackageData::PackageData( const string& name_,
|
||||||
description( description_ ),
|
description( description_ ),
|
||||||
depends( dependencies_ ),
|
depends( dependencies_ ),
|
||||||
url( url_ ),
|
url( url_ ),
|
||||||
packager( packager_ ),
|
optionals( optionals_ ),
|
||||||
maintainer( maintainer_ )
|
maintainer( maintainer_ )
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,7 +35,7 @@ public:
|
||||||
const std::string& description,
|
const std::string& description,
|
||||||
const std::string& dependencies,
|
const std::string& dependencies,
|
||||||
const std::string& url,
|
const std::string& url,
|
||||||
const std::string& packager,
|
const std::string& optionals,
|
||||||
const std::string& maintainer,
|
const std::string& maintainer,
|
||||||
const std::string& hasReadme,
|
const std::string& hasReadme,
|
||||||
const std::string& hasPreInstall,
|
const std::string& hasPreInstall,
|
||||||
|
@ -50,7 +50,7 @@ public:
|
||||||
const std::string& description() const;
|
const std::string& description() const;
|
||||||
const std::string& dependencies() const;
|
const std::string& dependencies() const;
|
||||||
const std::string& url() const;
|
const std::string& url() const;
|
||||||
const std::string& packager() const;
|
const std::string& optionals() const;
|
||||||
const std::string& maintainer() const;
|
const std::string& maintainer() const;
|
||||||
const bool hasReadme() const;
|
const bool hasReadme() const;
|
||||||
const bool hasPreInstall() const;
|
const bool hasPreInstall() const;
|
||||||
|
@ -59,6 +59,7 @@ public:
|
||||||
std::string versionReleaseString() const;
|
std::string versionReleaseString() const;
|
||||||
|
|
||||||
void setDependencies( const std::string& dependencies );
|
void setDependencies( const std::string& dependencies );
|
||||||
|
void setOptionals( const std::string& optionals );
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -82,7 +83,7 @@ struct PackageData
|
||||||
const std::string& description_="",
|
const std::string& description_="",
|
||||||
const std::string& dependencies_="",
|
const std::string& dependencies_="",
|
||||||
const std::string& url_="",
|
const std::string& url_="",
|
||||||
const std::string& packager="",
|
const std::string& optionals_="",
|
||||||
const std::string& maintainer="",
|
const std::string& maintainer="",
|
||||||
const std::string& hasReadme_="",
|
const std::string& hasReadme_="",
|
||||||
const std::string& hasPreInstall_="",
|
const std::string& hasPreInstall_="",
|
||||||
|
@ -95,7 +96,7 @@ struct PackageData
|
||||||
std::string description;
|
std::string description;
|
||||||
std::string depends;
|
std::string depends;
|
||||||
std::string url;
|
std::string url;
|
||||||
std::string packager;
|
std::string optionals;
|
||||||
std::string maintainer;
|
std::string maintainer;
|
||||||
|
|
||||||
std::string versionReleaseString;
|
std::string versionReleaseString;
|
||||||
|
|
175
src/prtget.cpp
175
src/prtget.cpp
|
@ -73,6 +73,7 @@ PrtGet::PrtGet( const ArgParser* parser )
|
||||||
readConfig();
|
readConfig();
|
||||||
|
|
||||||
m_useRegex = m_config->useRegex() || m_parser->useRegex();
|
m_useRegex = m_config->useRegex() || m_parser->useRegex();
|
||||||
|
m_followSoftdeps = m_config->followSoftdeps() || m_parser->followSoftdeps();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! destruct PrtGet object */
|
/*! destruct PrtGet object */
|
||||||
|
@ -152,6 +153,8 @@ void PrtGet::printUsage()
|
||||||
<< "depend on 'port'"
|
<< "depend on 'port'"
|
||||||
<< endl;
|
<< endl;
|
||||||
cout << " where opt can be:" << endl;
|
cout << " where opt can be:" << endl;
|
||||||
|
cout << " --softdeps consider optional dependencies too"
|
||||||
|
<< endl;
|
||||||
cout << " --all list all dependent packages, not "
|
cout << " --all list all dependent packages, not "
|
||||||
<< "only installed" << endl;
|
<< "only installed" << endl;
|
||||||
cout << " --recursive print recursive listing" << endl;
|
cout << " --recursive print recursive listing" << endl;
|
||||||
|
@ -205,16 +208,12 @@ void PrtGet::printUsage()
|
||||||
cout << " sysup [opt] update all outdated ports"
|
cout << " sysup [opt] update all outdated ports"
|
||||||
<< endl;
|
<< endl;
|
||||||
cout << " where opt can be:" << endl;
|
cout << " where opt can be:" << endl;
|
||||||
cout << " --nodeps don't sort by dependencies"
|
cout << " --nodeps don't sort by dependencies"
|
||||||
<< endl;
|
<< endl;
|
||||||
cout << " --test test mode" << endl;
|
cout << " --softdeps consider optional dependencies when sorting"
|
||||||
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"
|
|
||||||
<< endl;
|
<< endl;
|
||||||
|
cout << " --test test mode" << endl;
|
||||||
|
cout << " --log write log file"<< endl;
|
||||||
|
|
||||||
cout << " lock <port1 port2...> lock current version "
|
cout << " lock <port1 port2...> lock current version "
|
||||||
<< "of packages"
|
<< "of packages"
|
||||||
|
@ -395,16 +394,15 @@ void PrtGet::printInfo()
|
||||||
if ( !p->url().empty() ) {
|
if ( !p->url().empty() ) {
|
||||||
cout << "URL: " << p->url() << endl;
|
cout << "URL: " << p->url() << endl;
|
||||||
}
|
}
|
||||||
if ( !p->packager().empty() ) {
|
|
||||||
cout << "Packager: " << p->packager() << endl;
|
|
||||||
}
|
|
||||||
if ( !p->maintainer().empty() ) {
|
if ( !p->maintainer().empty() ) {
|
||||||
cout << "Maintainer: " << p->maintainer() << endl;
|
cout << "Maintainer: " << p->maintainer() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !p->dependencies().empty() ) {
|
if ( !p->dependencies().empty() ) {
|
||||||
cout << "Dependencies: " << p->dependencies() << endl;
|
cout << "Dependencies: " << p->dependencies() << endl;
|
||||||
}
|
}
|
||||||
|
if ( !p->optionals().empty() ) {
|
||||||
|
cout << "Optional: " << p->optionals() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: don't hardcode file names
|
// TODO: don't hardcode file names
|
||||||
string filesString = "";
|
string filesString = "";
|
||||||
|
@ -765,7 +763,11 @@ void PrtGet::printDepends( bool simpleListing )
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( deps.size() > 0 ) {
|
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();
|
list<string>::const_iterator it = deps.begin();
|
||||||
|
|
||||||
bool isAlias;
|
bool isAlias;
|
||||||
|
@ -1268,7 +1270,7 @@ void PrtGet::printf()
|
||||||
StringHelper::replaceAll( output, "%r", p->release() );
|
StringHelper::replaceAll( output, "%r", p->release() );
|
||||||
StringHelper::replaceAll( output, "%d", p->description() );
|
StringHelper::replaceAll( output, "%d", p->description() );
|
||||||
StringHelper::replaceAll( output, "%e", p->dependencies() );
|
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, "%M", p->maintainer() );
|
||||||
|
|
||||||
StringHelper::replaceAll( output, "\\t", "\t" );
|
StringHelper::replaceAll( output, "\\t", "\t" );
|
||||||
|
@ -1281,7 +1283,7 @@ void PrtGet::printf()
|
||||||
StringHelper::replaceAll( sortkey, "%r", p->release() );
|
StringHelper::replaceAll( sortkey, "%r", p->release() );
|
||||||
StringHelper::replaceAll( sortkey, "%d", p->description() );
|
StringHelper::replaceAll( sortkey, "%d", p->description() );
|
||||||
StringHelper::replaceAll( sortkey, "%e", p->dependencies() );
|
StringHelper::replaceAll( sortkey, "%e", p->dependencies() );
|
||||||
StringHelper::replaceAll( sortkey, "%P", p->packager() );
|
StringHelper::replaceAll( sortkey, "%P", p->optionals() );
|
||||||
StringHelper::replaceAll( sortkey, "%M", p->maintainer() );
|
StringHelper::replaceAll( sortkey, "%M", p->maintainer() );
|
||||||
|
|
||||||
string isInst = "no";
|
string isInst = "no";
|
||||||
|
@ -1371,6 +1373,7 @@ void PrtGet::printDependent()
|
||||||
|
|
||||||
initRepo();
|
initRepo();
|
||||||
string arg = *(m_parser->otherArgs().begin());
|
string arg = *(m_parser->otherArgs().begin());
|
||||||
|
vector<string> treeWalk;
|
||||||
|
|
||||||
if (m_parser->printTree()) {
|
if (m_parser->printTree()) {
|
||||||
cout << arg << endl;
|
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();
|
map<string, Package*>::const_iterator it = m_repo->packages().begin();
|
||||||
static map<string, bool> shownMap;
|
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;
|
set<const Package*> dependent;
|
||||||
for ( ; it != m_repo->packages().end(); ++it ) {
|
for ( ; it != m_repo->packages().end(); ++it ) {
|
||||||
|
|
||||||
|
@ -1400,6 +1411,17 @@ void PrtGet::printDependent(const string& dep, int level)
|
||||||
dependent.insert( p );
|
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
|
// - 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()
|
void PrtGet::listOrphans()
|
||||||
|
@ -1464,6 +1488,15 @@ void PrtGet::listOrphans()
|
||||||
for (; lit != tokens.end(); ++lit) {
|
for (; lit != tokens.end(); ++lit) {
|
||||||
required[*lit] = true;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->dependencies().length() > 0) {
|
if ( (p->dependencies().length() > 0) or
|
||||||
|
(m_followSoftdeps && p->optionals().length() > 0) ) {
|
||||||
cout << "-- dependencies ([i] = installed";
|
cout << "-- dependencies (";
|
||||||
|
if ( m_followSoftdeps ) {
|
||||||
|
cout << "[s] soft, ";
|
||||||
|
}
|
||||||
|
cout << "[i] hard, [ ] not installed";
|
||||||
if (!m_parser->all()) {
|
if (!m_parser->all()) {
|
||||||
cout << ", '-->' = seen before";
|
cout << ", '-->' already shown";
|
||||||
}
|
}
|
||||||
cout << ")" << endl;
|
cout << ")" << endl;
|
||||||
if ( m_pkgDB->isInstalled( *it ) ) {
|
printDepsLevel(2, p, false);
|
||||||
cout << "[i] ";
|
|
||||||
} else {
|
|
||||||
cout << "[ ] ";
|
|
||||||
}
|
|
||||||
cout << p->name() << endl;
|
|
||||||
printDepsLevel(2, p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrtGet::printDepsLevel(int indent, const Package* package)
|
void PrtGet::printDepsLevel(int indent, const Package* package, bool greedy)
|
||||||
{
|
{
|
||||||
static map<string, bool> shownMap;
|
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;
|
list<string> deps;
|
||||||
StringHelper::split(package->dependencies(), ',', deps);
|
StringHelper::split(package->dependencies(), ',', deps);
|
||||||
list<string>::iterator it = deps.begin();
|
list<string>::iterator it = deps.begin();
|
||||||
bool isAlias = false;
|
|
||||||
string aliasName = "";
|
|
||||||
|
|
||||||
for (; it != deps.end(); ++it) {
|
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 );
|
const Package* p = m_repo->getPackage( *it );
|
||||||
if (p) {
|
if (p) {
|
||||||
if (p->dependencies().length() > 0) {
|
printDepsLevel(indent+2, p, greedy);
|
||||||
map<string, bool>::iterator shownIt = shownMap.find(*it);
|
if (!m_parser->all()) {
|
||||||
if (shownIt != shownMap.end()) {
|
shownMap[*it] = true;
|
||||||
cout << " -->" << endl;;
|
}
|
||||||
} else {
|
|
||||||
cout << endl;
|
|
||||||
printDepsLevel(indent+2, p);
|
|
||||||
if (!m_parser->all()) {
|
|
||||||
shownMap[*it] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
cout << " (not found in ports tree)" << endl;
|
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()
|
void PrtGet::dumpConfig()
|
||||||
|
|
|
@ -97,7 +97,7 @@ public:
|
||||||
|
|
||||||
protected:
|
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);
|
void printDependent(const std::string& dep, int level);
|
||||||
|
|
||||||
|
@ -138,6 +138,8 @@ protected:
|
||||||
int m_returnValue;
|
int m_returnValue;
|
||||||
|
|
||||||
bool m_useRegex;
|
bool m_useRegex;
|
||||||
|
bool m_followSoftdeps;
|
||||||
|
vector<string> treeWalk;
|
||||||
|
|
||||||
/*! Name of default configuration file */
|
/*! Name of default configuration file */
|
||||||
static const string CONF_FILE;
|
static const string CONF_FILE;
|
||||||
|
|
|
@ -264,7 +264,7 @@ Repository::initFromCache( const string& cacheFile )
|
||||||
// FIELDS:
|
// FIELDS:
|
||||||
// name, path, version, release,
|
// name, path, version, release,
|
||||||
// description, dependencies, url,
|
// description, dependencies, url,
|
||||||
// packager, maintainer, hasReadme;
|
// optionals, maintainer, hasReadme;
|
||||||
// hasPreInstall, hasPostInstall
|
// hasPreInstall, hasPostInstall
|
||||||
const int fieldCount = 12;
|
const int fieldCount = 12;
|
||||||
string fields[fieldCount];
|
string fields[fieldCount];
|
||||||
|
@ -351,7 +351,7 @@ Repository::WriteResult Repository::writeCache( const string& cacheFile )
|
||||||
p->description().c_str(),
|
p->description().c_str(),
|
||||||
p->dependencies().c_str(),
|
p->dependencies().c_str(),
|
||||||
p->url().c_str(),
|
p->url().c_str(),
|
||||||
p->packager().c_str(),
|
p->optionals().c_str(),
|
||||||
p->maintainer().c_str(),
|
p->maintainer().c_str(),
|
||||||
hasReadme, hasPreInstall, hasPostInstall );
|
hasReadme, hasPreInstall, hasPostInstall );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue