diff --git a/doc/prt-get.8 b/doc/prt-get.8 index 8fbe257..83ff0ba 100644 --- a/doc/prt-get.8 +++ b/doc/prt-get.8 @@ -739,6 +739,12 @@ currently-installed ports, but are needed now by the newer versions of these ports. The output of this command is sorted by dependencies, therefore suitable for piping to \fBxargs prt\-get install\fP. +.TP +.B comm \-13 <(prt\-get depends firefox\-bin |tail \-n +2 |sort) <(prt\-get depends firefox |tail \-n +2 |sort) +Find the build-time dependencies of firefox. Runtime dependencies would +also appear in the list generated by the first process substitution, and +\fBcomm \-13\fP will suppress what the two lists have in common. + .TP .B prt\-get isinst $(prt\-get quickdep i3) | awk '/not installed/ { print $2 }' | xargs prt\-get depinst \-\-softdeps \-\-test (inspired by a troubleshooting session with hestia) Assemble a set of install @@ -760,11 +766,15 @@ Requires that your repositories are synchronized using the \fBgit(1)\fP driver. Subsequent sorting by date may be done using \fBsort(1)\fP with the flags -k, -M, and -n (the appropriate key defs will depend on your locale). -.TP -.B comm \-13 <(prt\-get depends firefox\-bin |tail \-n +2 |sort) <(prt\-get depends firefox |tail \-n +2 |sort) -Find the build-time dependencies of firefox. Runtime dependencies would -also appear in the list generated by the first process substitution, and -\fBcomm \-13\fP will suppress what the two lists have in common. +.TP +.B for L in /var/log/pkgbuild/*.log; do P=${L%__*}; P=${P##*/}; VR=${L##*__}; VR=${VR%.log}; if ! prt\-get isinst $P >/dev/null; then mv $L /var/log/uninstalled/; elif [ \(dq$(prt\-get current $P)\(dq != \(dq$VR\(dq ]; then mv $L /var/log/oldbuild/; fi; done +(based on a feature request by samsep10l) a command you can put into a script +called by root's crontab, in order to mimic Slackware's tidy directory listings +(the main logdir only contains build logs of the latest installed packages; +other logs are moved to a separate directory). This particular command relies +on declaring \(dqlogfile /var/log/pkgbuild/%n__%v-%r.log\(dq and \(dqwritelog +enabled\(dq in \fBprt\-get.conf(5)\fP. Logs saved with a different filename +pattern will require slight adjustments to the command. .TP .B prt\-get listinst \-\-depsort | xargs prt\-get install \-\-install\-root=/mnt diff --git a/doc/prt-get.conf.5 b/doc/prt-get.conf.5 index 9d41564..8cc87df 100644 --- a/doc/prt-get.conf.5 +++ b/doc/prt-get.conf.5 @@ -128,13 +128,36 @@ replaced with the port's path, e.g. for port gcc in core, %p would be and %n would be .B gcc. This allows you to have separate log files per port. +Separate log files for each version and release can be achieved using +the placeholders %v and %r, respectively. But if you want to enable +\fBrmlog_on_uninst\fP, it is best to avoid %p, %v, and %r when +specifying \fBlogfile\fP (as explained below). + +.B rmlog_on_uninst +can be set to 'yes' or 'no'; when set to yes, uninstalling a package +will also try to delete its build log. Replacements in the template +\fBlogfile\fP will be made using the \fIcurrent values\fP from the +database of installed packages, and from the active repositories. If +log files exist with different values of %p, %v, or %r than what the +database and repositories provide, then the pattern substitutions will +fail to match the names of those logs, and this feature will be a no-op. +For example, suppose you specify the logfile pattern +\(dq%p/.buildlogs/%n__%v-%r.log\(dq, and you have a package installed +on your system through many versions, or after it has been moved from +opt to contrib. Uninstalling that package would leave behind all the +build logs except the latest. This pattern is also fragile with respect +to repository purges; if one of your installed ports is dropped from +the official repos, then either \(dq%p\(dq will expand to the path of +your personal overlay (you did make a copy, right?), or it will not +expand at all! See the EXAMPLES section of \fBprt\-get(8)\fP for +alternative ways to tidy up your directory of build logs. .B readme can be set to 'disabled', to suppress the notification after installing a port with a README file; 'compact', to collect all the READMEs into one post-transaction output; or 'verbose', to print separate information about each port with a README file. See -.B prt-get(8) +.B prt\-get(8) and especially the readme command how to read those README files using prt-get. diff --git a/src/configuration.cpp b/src/configuration.cpp index 5a26185..a7d88d1 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -30,6 +30,7 @@ Configuration::Configuration( const std::string& configFile, m_writeLog( false ), m_appendLog( false ), m_removeLogOnSuccess( false ), + m_removeLogOnUninst( false ), m_readmeMode( VERBOSE_README ), m_runScripts( false ), m_preferHigher( false ), @@ -85,6 +86,11 @@ bool Configuration::removeLogOnSuccess() const return m_removeLogOnSuccess; } +bool Configuration::removeLogOnUninst() const +{ + return m_removeLogOnUninst; +} + string Configuration::logFilePattern() const { return m_logFilePattern; @@ -189,6 +195,13 @@ void Configuration::parseLine(const string& line, bool prepend) } else if ( s == "no" ) { m_removeLogOnSuccess = false; } + } else if ( startsWithNoCase( s, "rmlog_on_uninst" ) ) { + s = stripWhiteSpace( s.replace( 0, 15, "" ) ); + if ( s == "yes" ) { + m_removeLogOnUninst = true; + } else if ( s == "no" ) { + m_removeLogOnUninst = false; + } } else if ( startsWithNoCase( s, "readme" ) ) { s = stripWhiteSpace( s.replace( 0, 6, "" ) ); if ( s == "compact" ) { diff --git a/src/configuration.h b/src/configuration.h index 6325432..833073b 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -30,6 +30,7 @@ public: bool writeLog() const; bool appendLog() const; bool removeLogOnSuccess() const; + bool removeLogOnUninst() const; std::string logFilePattern() const; const std::list< std::pair >& rootList() const; @@ -72,6 +73,7 @@ private: bool m_writeLog; bool m_appendLog; bool m_removeLogOnSuccess; + bool m_removeLogOnUninst; ReadmeMode m_readmeMode; diff --git a/src/prtget.cpp b/src/prtget.cpp index 031671f..18152d9 100644 --- a/src/prtget.cpp +++ b/src/prtget.cpp @@ -1575,12 +1575,17 @@ void PrtGet::cat() { void PrtGet::remove() { assertMinArgCount(1); + bool needRepo = false; list removed; list failed; list notInstalled; if ( m_parser->isTest() ) { cout << "*** " << m_appName << ": test mode" << endl; + } else if ( m_config->removeLogOnUninst() + && m_config->logFilePattern().find("%p") != string::npos ) { + needRepo = true; + initRepo(); } string command = InstallTransaction::PKGRM_DEFAULT_COMMAND; @@ -1592,17 +1597,46 @@ void PrtGet::remove() { list::const_iterator it = args.begin(); for ( ; it != args.end(); ++it ) { if (m_pkgDB->isInstalled(*it)) { - string args = (m_parser->installRoot() == "") ? "" : + string rm_args = (m_parser->installRoot() == "") ? "" : "-r " + m_parser->installRoot() + " "; - args += (m_parser->pkgrmArgs() + " " + *it); + rm_args += (m_parser->pkgrmArgs() + " " + *it); - Process proc(command, args); + Process proc(command, rm_args); if (m_parser->isTest() || proc.executeShell() == 0) { removed.push_back(*it); if (m_locker.isLocked(*it)) { m_locker.unlock(*it); m_locker.store(); } + if (m_config->removeLogOnUninst() && !m_parser->isTest()) { + string rm_logFile = m_config->logFilePattern(); + bool doneSubs=false; + const string pkgname = *it; + StringHelper::replaceAll( rm_logFile, "%n", pkgname ); + const string rm_ver = m_pkgDB->getPackageVersion( pkgname ); + size_t pos = rm_ver.find_last_of('-'); + if (pos != string::npos) { + const string rm_v = rm_ver.substr(0,pos); + const string rm_r = rm_ver.substr(pos+1); + StringHelper::replaceAll( rm_logFile, "%v", rm_v ); + StringHelper::replaceAll( rm_logFile, "%r", rm_r ); + } + if (! needRepo) { + doneSubs=true; + } else if (m_repo->getPackage( pkgname )) { + StringHelper::replaceAll( rm_logFile, "%p", + m_repo->getPackage( pkgname )->path() ); + doneSubs=true; + } else { + cout << "Warning: unable to determine the logfile for " + + pkgname + "; log removal aborted." << endl; + } + struct stat slF; + if ( doneSubs && stat(rm_logFile.c_str(), &slF)==0 + && (slF.st_mode & S_IFMT)==S_IFREG ) { + unlink( rm_logFile.c_str() ); + } + } } else { failed.push_back(*it); }