From f2c0f370d475ccd506753fd71b92616b3dab4395 Mon Sep 17 00:00:00 2001 From: John McQuah Date: Sun, 19 Mar 2023 16:47:11 -0400 Subject: [PATCH] cut down on duplicate code; fix FS#1930; expand man-page examples --- ChangeLog | 11 +- doc/prt-get.8 | 170 +++--- src/argparser.cpp | 263 +++++---- src/argparser.h | 40 +- src/installtransaction.cpp | 282 +++++----- src/installtransaction.h | 15 +- src/main.cpp | 57 +- src/pkgdb.h | 1 + src/prtget.cpp | 1058 +++++++++++++----------------------- src/prtget.h | 40 +- src/repository.cpp | 60 +- src/repository.h | 6 + src/stringhelper.cpp | 1 - 13 files changed, 848 insertions(+), 1156 deletions(-) diff --git a/ChangeLog b/ChangeLog index d6567f7..166e412 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ +* 19.03.2023 John McQuah +- switch between install and update on a port-by-port basis, whichever is needed +- allow dependency injection during sysup (controllable via --nodeps) +- check whether a built package already exists before calling pkgmk +- consolidate printDependent and printDepTree +- consolidate sysup, printQuickDiff, and printDiff +- let the argParser recognize some synonyms for old commands +- assign meanings to --nodeps and --depsort for other subroutines + * 10.03.2023 John McQuah -- make it possible to consider optional dependencies when updating +- make it possible for the dependency resolver to consider optionals - bump version of the cache file format, to warn users about the 'Packager' field being replaced by 'Optional' diff --git a/doc/prt-get.8 b/doc/prt-get.8 index 8079279..6149da3 100644 --- a/doc/prt-get.8 +++ b/doc/prt-get.8 @@ -75,33 +75,26 @@ non-option argument passed. This is very similar to .TP -.B install [\-\-margs] [\-\-aargs] [\-\-log] [ ...] -install all packages in the listed order. Note that you can do this -from any directory. +.B install [\-\-margs] [\-\-aargs] [\-\-log] [\-\-nodeps] [\-\-softdeps] [ ...] +install or update the packages given on the command line. Note that you can do +this from any directory. Pass the --nodeps flag to prevent \fBprt\-get\fP from +resolving dependencies and injecting any needed ports into the list of targets. +Pass the --softdeps flag if you want the dependency resolver to also consider +the "Optional" relationships among the packages given on the command line. .TP .B depinst [\-\-margs] [\-\-aargs] [\-\-log] [\-\-softdeps] [ ...] -install all packages given on the command line, including their dependencies. -Passing the --softdeps flag tells \fBprt-get\fP to consider also the optional -dependencies when sorting. Note that already-installed packages will be left -at their current version, even if out of date. prt\-get depinst behaves this -way because all of its child pkgadd processes will \fBlack\fP the \-u flag, -which is needed when updating an already-installed package. +Basically a synonym for install (without the --nodeps flag). .TP -.B update [\-\-margs] [\-\-aargs] [\-\-log] [ ...] -update all packages listed in this order. Note: if the latest version of -a package has acquired dependencies that were not needed by the currently-installed -version and are not present on the system, the update command will not attempt to -resolve this omission. prt-get update behaves this way because pkgadd invocations -inherit the flag -u for every package in the transaction, causing an error if -the package is not already installed. You can follow the CRUX mailing list or the -IRC channels to stay informed of the situations where an update will require manual -intervention, or filter the output of -.B prt\-get quickdep $(prt\-get quickdiff) -through \fBprt\-get isinst\fP to get a list of packages suitable for an -\fBinstall\fP or \fBupdate\fP command. -See the \fBEXAMPLES\fP section below for details. +.B update [\-\-margs] [\-\-aargs] [\-\-log] [\-\-softdeps] [ ...] +Basically a synonym for install. Earlier versions of \fBprt\-get\fP did not adjust +the \fBpkgadd(8)\fP arguments on a package-by-package basis, but applied "install +mode" or "update mode" to the entire transaction. This latest \fBprt\-get\fP +interprets the install command less rigidly, and tries to sync your installed +ports with their repository versions unless instructed otherwise (using +\fBprt\-get lock\fP, the --prefer-higher option, or the \fIprt-get.aliases\fP +file). .TP .B remove [ ...] @@ -112,14 +105,13 @@ remove packages listed in this order Update all installed packages which are outdated. Sorts by hard dependencies by default. Passing the --softdeps switch tells \fBprt\-get\fP to also consider optional dependencies when sorting. Passing the --nodeps switch tells prt-get -not to sort by dependencies at all, for approximately the same effect as -.B prt\-get update $(prt\-get quickdiff). -As with an \fBupdate\fP command, the child \fBpkgadd\fP processes will -inherit the \-u flag, so if a port has acquired new dependencies since -its last successful build, those new dependencies will be omitted from -the transaction (unless they happen to be installed for some other reason and -are also in need of an update). See the \fBEXAMPLES\fP section for a way to -automate the resolution of such omissions. Also see the +not to sort by dependencies at all. +.B Breaking Change: +If a port has acquired new dependencies since its last successful build, +those new dependencies will be injected into the transaction. This feature +lingered many years on the TODO list, and its absence was the motivation for +many clever workarounds (documented in the \fBEXAMPLES\fP section below). +You can use the .B lock and .B unlock @@ -166,15 +158,9 @@ prints a simple list of packages which have a different version in the ports tree than what is installed. The output is sorted alphabetically, but you can generate a (larger) list sorted by dependencies using .B prt\-get quickdep $(prt\-get quickdiff). -Note that the resulting list is usually a mix of installed and -not-installed packages, so it must be filtered by -.B prt\-get isinst -before being passed as argument to prt\-get install or prt\-get update. See the -.B EXAMPLES -section below. -If you want to see only diffs which have a lower version installed than the one in -the ports tree, use the --prefer-higher option. +If you want to see only diffs which have a lower version installed than +the one in the ports tree, use the --prefer-higher option. .TP .B search [\-v|\-vv] [\-\-path] [\-\-regex] @@ -202,7 +188,6 @@ will change in prt-get 0.6, where full path search will be the default. Pattern can be a shell-like wildcard pattern (e.g. prt-get fsearch "*.h") or a regular expression (e.g. prt-get fsearch --regex 'liblz(o2|ma).*') - .TP .B info Print available info for a port @@ -231,7 +216,7 @@ if you don't want to filter out manually the ports that are invalid targets for installation. For example, instead of .B prt\-get depinst xorg-server you might micromanage the process as follows: -.B for i in $(prt\-get quickdep xorg-server); do if prt\-get isinst $i 2>/dev/null; then prt\-get update \-fr $i; else prt\-get install $i; fi; done +.B for i in $(prt\-get quickdep xorg-server); do prt\-get install \-fr \-\-nodeps $i; done which ensures that the latest version of each dependency is built. Note: It might be useful to run @@ -409,13 +394,9 @@ but does not print the version information. This command has a return value of greater than 0. .TP -.B current +.B current [ ...] Shows the currently-installed version of , or a message -that is not installed. Unlike -.B prt\-get isinst package1 package2, -this command does \fBnot\fP accept more than one package as argument. Use -.B pkginfo \-i| grep \-E '^(package1|package2|...)' -to work around this limitation. +that is not installed. .TP .B ls [\-\-path] @@ -423,7 +404,8 @@ Prints out a listing of the port's directory .TP .B cat [] -Prints out the file to stdout. If is not specified, 'Pkgfile' is used. If set, uses $PAGER. +Prints out the file to stdout. If is not specified, 'Pkgfile' is used. +If set, uses $PAGER. .TP .B edit [] @@ -465,14 +447,6 @@ Force install; Implies 'pkgadd -f'; same as --aargs=-f .B \-fr Force rebuild, Implies 'pkgmk -f'; same as --margs=-f -.TP -.B \-um -Update md5sum, implies 'pkgmk -um'; same as --margs=-um - -.TP -.B \-im -Ignore md5sum, implies 'pkgmk -im'; same as --margs=-im - .TP .B \-us Update signature, implies 'pkgmk -us'; same as --margs=-us @@ -515,6 +489,11 @@ future uses and consistency reasons .B \-\-ignore= Don't install these packages, even if they're listed as dependencies +.TP +.B \-\-nodeps +Leave the list of requested ports as-is, without sorting by dependencies +or injecting missing dependencies. + .TP .B \-\-softdeps Consider optional dependencies when determining the order in which to build @@ -623,29 +602,38 @@ See man prt\-get.conf(5) .SH "EXAMPLES" .TP .B prt\-get install irssi -Download, build and install irssi, with one simple command +Download, build and install irssi (and any of its missing dependencies), with +one simple command .TP -.B prt\-get install paper yasm -Install paper and yasm. Abort with an informative error message if either package is already -installed, allowing you to issue a revised command. +.B prt\-get install --nodeps jasper +Install jasper, without trying to resolve dependencies. .TP -.B prt\-get update bmake cmake -Update bmake and cmake. Abort with an informative error message if either package is not yet -installed, allowing you to issue a revised command. +.B prt\-get update --softdeps webkitgtk +Get the latest version of webkitgtk, rebuilding any of its outdated dependencies +(hard and soft) in the optimal order. .TP .B prt\-get update -fr openssh -Update your current version of openssh, forcing a rebuild even if no version difference is detected. -Useful if there was a major version change in one of its dependencies, and \fBrevdep openssh\fP -indicates a broken package. :\-) +Update your current version of openssh, forcing a rebuild even if no version +difference is detected. +Useful if there was a major soversion change in one of its dependencies, +and \fBrevdep openssh\fP indicates a broken package. :\-) .TP .B MISSLIBS=$(revdep -vvv mpv | awk -v FS=: '/(missing library)/ {print $3}'); [ -n \(dq${MISSLIBS[@]}\(dq ] && for i in ${MISSLIBS[@]}; do prt\-get fsearch $i; done (adapted from a script by ppetrov^) Check for the presence of the runtime libraries needed by mpv. If any are absent, search the footprints to determine which ports provide the missing libraries. +.TP +.B prt\-get printf '%i:%p:%n\en' | awk -v FS=: '/^diff:\e/usr\e/ports\e/core/ { print $3 }' | xargs prt\-get update +Basically a \fBsysup\fP operation, but restricted to the core collection. +Because core ports are often omitted from the dependency line if they aren't +dynamically linked in, the \fBsysup\fP sorting algorithm might not put them +at the front of the queue. Run this command before a regular \fBsysup\fP in +order to ensure that core ports are updated first. + .TP .B prt\-get isinst $(prt-get info ffmpeg | awk -v FS=: '/^Optional/ {gsub(/,/,\(dq \(dq,$2); print $2}') | awk -v FS=\(dq \(dq '/not installed/ {print $2}' Show all the optional dependencies of ffmpeg that are not currently installed. @@ -663,12 +651,13 @@ place. Extension of the above (addressing a use case envisioned by ivandi). The user can create the file /etc/prt-get.softdeps containing a line like .B ffmpeg: x264 x265 -and then the above command will perform a depinst --group operation to ensure that -at least x264 and x265 (but not necessarily any of the other optional -dependencies) are present before trying to build ffmpeg. In the absence of such -a .softdeps config, the operation reverts to the behaviour of the preceding -example (maximal feature set). Implementing Gentoo USE flags with such an -awkward one-liner might draw criticism from advocates of the KISS principle. +and then the above command will perform a depinst --group operation to +ensure that at least x264 and x265 (but not necessarily any of the other +optional dependencies) are present before trying to build ffmpeg. In the +absence of such a .softdeps config, the operation reverts to the behaviour +of the preceding example (maximal feature set). Implementing Gentoo USE +flags with such an awkward one-liner might draw criticism from advocates of +the KISS principle. .TP .B prt\-get search \-\-regex '^(m|n|p)c.*' @@ -686,46 +675,45 @@ shells (like bash) that support process substitution .TP .B comm -13 <(cat ~/.keepers <(ls /usr/ports/core) | sort) <(prt\-get listorphans) | xargs prt\-get remove (system-hosing extension of the above) A one-liner inspired by \fBpkg\-clean\fP -and \fBpkgfoster\fP, but without the safeguard of interactivity. \fBDo not try this on a -mission-critical system.\fP +and \fBpkgfoster\fP, but without the safeguard of interactivity. +\fBDo not try this on a mission-critical system.\fP .TP .B prt\-get isinst $(prt\-get quickdep $(prt\-get quickdiff)) | awk '/not installed/ {print $2}' -(adapted from a comment by Fun) After updating your ports tree, print out a list of dependencies -that were not needed the last time you built your currently-installed ports, but are needed now by -the newer versions of these ports. The output of this command is sorted by dependencies, therefore +(adapted from a comment by Fun) After updating your ports tree, print out a +list of dependencies that were not needed the last time you built your +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 prt\-get isinst $(prt\-get quickdep $(prt\-get quickdiff)) | awk '/is installed/ {print $2}' -Same as above, but only print the dependencies that are already installed. The output of this -command is suitable for piping to \fBxargs prt\-get update\fP. - .TP .B prt\-get printf \(dq%p\et%u\en\(dq | grep myrepo | cut -f 2 -Print the upstream URL for each port in the collection \(dqmyrepo\(dq, perhaps as the first step in -keeping your personal overlay up to date. +Print the upstream URL for each port in the collection \(dqmyrepo\(dq, +perhaps as the first step in keeping your personal overlay up to date. .TP .B prt\-get printf \(dq%M\et%n\en\(dq | grep ^Tim | wc -l -Count how many ports our most-overworked core team member claims responsibility for. +Count how many ports our most-overworked core team member claims +responsibility for. .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. +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 listinst \-\-depsort | xargs prt-get install \-\-install\-root=/mnt Sort the list of installed packages by dependencies, and then install all -those packages onto a backup filesystem (mounted at /mnt). If you have a customized -pkgadd.conf that you want applied to this operation, either copy it to -/mnt/etc where pkgadd will be looking for it, or pass the additional option \-\-aargs=\(dq\-c -/etc/pkgadd.conf\(dq to the install command. +those packages onto a backup filesystem (mounted at /mnt). If you have a +customized pkgadd.conf that you want applied to this operation, either copy +it to /mnt/etc where pkgadd will be looking for it, or pass the additional +option \-\-aargs=\(dq\-c /etc/pkgadd.conf\(dq to the install command. .TP .B prt-get list --path --regex '^xorg.*' | grep -v \(dq/usr/ports/xorg\(dq -Show the ports whose names begin with xorg, but which appear outside the xorg port collection. +Show the ports whose names begin with xorg, but which appear outside the +xorg port collection. (At the time of writing, this command returned at least two font ports.) .SH "AUTHORS" diff --git a/src/argparser.cpp b/src/argparser.cpp index 79ec5df..fe44946 100644 --- a/src/argparser.cpp +++ b/src/argparser.cpp @@ -27,26 +27,28 @@ ArgParser::ArgParser( int argc, char** argv ) m_hasFilter( false ), m_noStdConfig( false ), m_writeLog( false ), - m_nodeps( false ), + m_depSort( true ), m_softdeps( false ), + m_revdep(false), m_all( false ), m_printPath( false ), m_execPreInstall( false ), m_execPostInstall( false ), m_preferHigher( false ), m_strictDiff( false ), + m_sysup( false ), m_group( false ), m_useRegex(false), m_fullPath(false), + m_quick(false), m_recursive(false), m_printTree(false), - m_depSort(false), m_alternateConfigFile( "" ), m_pkgmkArgs( "" ), m_pkgaddArgs( "" ), m_pkgrmArgs( "" ), - m_sortArgs( "" ), m_filter( "" ), + m_sortArgs( "" ), m_commandName( "" ), m_unknownOption( "" ), m_installRoot( "" ), @@ -80,7 +82,7 @@ bool ArgParser::isCommandGiven() const /*! \return a list of arguments not processed by ArgParser */ -const list& ArgParser::otherArgs() const +const list& ArgParser::otherArgs() const { return m_otherArgs; } @@ -103,7 +105,6 @@ const string& ArgParser::pkgmkArgs() const return m_pkgmkArgs; } - /*! \return addtional arguments to pkgadd */ @@ -112,7 +113,6 @@ const string& ArgParser::pkgaddArgs() const return m_pkgaddArgs; } - /*! \return the name of the alternative configuration file */ @@ -121,36 +121,34 @@ const string& ArgParser::alternateConfigFile() const return m_alternateConfigFile; } - /*! parse the arguments \return true on success */ -bool ArgParser::parse() -{ - const int commandCount = 34; - string commands[commandCount] = { "list", "search", "dsearch", - "info", "version", "cache", - "depends", "install", "depinst", - "help", "isinst", "dup", "update", - "quickdep", "diff", "quickdiff", - "path", "listinst", "printf", "readme", - "dependent", "sysup", "current", - "fsearch", "lock", "unlock", - "listlocked", "cat", "ls", "edit", - "remove", "deptree", "dumpconfig", - "listorphans" }; +bool ArgParser::parse() { + const int commandCount = 28; + string commands[commandCount] = { "help", "info", "version", + "search", "dsearch", "fsearch", + "cache", "install", "remove", + "current", "isinst", "diff", + "path", "printf", "readme", + "list", "listinst", "listorphans", + "lock", "unlock", "listlocked", + "cat", "ls", "edit", "dumpconfig", + "dup", "depends", "deptree" + }; + + Type commandID[commandCount] = { HELP, INFO, SHOW_VERSION, + SEARCH, DSEARCH, FSEARCH, + CREATE_CACHE, INSTALL, REMOVE, + CURRENT, ISINST, DIFF, + PATH, PRINTF, README, + LIST, LISTINST, LISTORPHANS, + LOCK, UNLOCK, LISTLOCKED, + CAT, LS, EDIT, DUMPCONFIG, + DUP, DEPENDS, DEPTREE + }; - Type commandID[commandCount] = { LIST, SEARCH, DSEARCH, INFO, - SHOW_VERSION, CREATE_CACHE, - DEPENDS, INSTALL, DEPINST, - HELP, ISINST, DUP, UPDATE, - QUICKDEP, DIFF, QUICKDIFF, - PATH, LISTINST, PRINTF, README, - DEPENDENT, SYSUP, CURRENT, - FSEARCH, LOCK, UNLOCK, LISTLOCKED, - CAT, LS, EDIT, REMOVE, DEPTREE, - DUMPCONFIG, LISTORPHANS }; if ( m_argc < 2 ) { return false; } @@ -170,71 +168,42 @@ bool ArgParser::parse() for ( int i = 1; i < m_argc; ++i ) { if ( m_argv[i][0] == '-' ) { string s = m_argv[i]; - if ( s == "-v" ) { - m_verbose += 1; - } else if ( s == "-vv" ) { - m_verbose += 2; - } else if ( s == "--test" ) { - m_isTest = true; - } else if ( s == "--cache" ) { - 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" ) { - m_printPath = true; - } else if ( s == "--log" ) { - m_writeLog = true; - } else if ( s == "--pre-install" ) { - m_execPreInstall = true; - } else if ( s == "--post-install" ) { + if ( s == "-v" ) { m_verbose += 1; + } else if ( s == "-vv" ) { m_verbose += 2; + } else if ( s == "--test" ) { m_isTest = true; + } else if ( s == "--cache" ) { m_useCache = true; + } else if ( s == "--depsort" ) { m_depSort = true; + } else if ( s == "--nodeps" ) { m_depSort = false; + } else if ( s == "--softdeps" ) { m_softdeps = true; + } else if ( s == "--all" ) { m_all = true; + } else if ( s == "--path" ) { m_printPath = true; + } else if ( s == "--log" ) { m_writeLog = true; + } else if ( s == "--pre-install" ) { m_execPreInstall = true; + } else if ( s == "--post-install" ) { m_execPostInstall = true; + } else if ( s == "--install-scripts" ) { m_execPreInstall = true; m_execPostInstall = true; - } else if ( s == "--install-scripts" ) { - m_execPreInstall = true; - m_execPostInstall = true; - } else if ( s == "--no-std-config" ) { - m_noStdConfig = true; + } else if ( s == "--no-std-config" ) { m_noStdConfig = true; } else if ( s == "--prefer-higher" || s == "-ph" ) { m_preferHigher = true; } else if ( s == "--strict-diff" || s == "-sd" ) { m_strictDiff = true; - } else if ( s == "--group" || s == "-g" ) { - m_group = true; - } else if ( s == "--regex" ) { - m_useRegex = true; - } else if ( s == "--full" ) { - m_fullPath = true; - } else if ( s == "--recursive" ) { - m_recursive = true; - } else if ( s == "--tree" ) { - m_printTree = true; - } else if ( s == "--depsort" ) { - m_depSort = true; - } else if ( s == "-f" ) { - m_pkgaddArgs += " " + s; - } else if ( s == "-fr" ) { - m_pkgmkArgs += " -f"; - } else if ( s == "-if" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-uf" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-im" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-um" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-is" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-us" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-kw" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-ns" ) { - m_pkgmkArgs += " " + s; - } else if ( s == "-fi" ) { - m_pkgaddArgs += " -f"; + } else if ( s == "--group" || s == "-g" ) { m_group = true; + } else if ( s == "--quick" || s == "-Q" ) { m_quick = true; + } else if ( s == "--regex" ) { m_useRegex = true; + } else if ( s == "--full" ) { m_fullPath = true; + } else if ( s == "--recursive" || s == "-R" ) { m_recursive = true; + } else if ( s == "--tree" || s == "-T" ) { m_printTree = true; + } else if ( s == "-f" ) { m_pkgaddArgs += " " + s; + } else if ( s == "-fi" ) { m_pkgaddArgs += " -f"; + } else if ( s == "-fr" ) { m_pkgmkArgs += " -f"; + } else if ( s == "-if" ) { m_pkgmkArgs += " " + s; + } else if ( s == "-uf" ) { m_pkgmkArgs += " " + s; + } else if ( s == "-im" ) { m_pkgmkArgs += " " + s; + } else if ( s == "-um" ) { m_pkgmkArgs += " " + s; + } else if ( s == "-is" ) { m_pkgmkArgs += " " + s; + } else if ( s == "-us" ) { m_pkgmkArgs += " " + s; + } else if ( s == "-kw" ) { m_pkgmkArgs += " " + s; + } else if ( s == "-ns" ) { m_pkgmkArgs += " " + s; } // substrings @@ -244,11 +213,11 @@ bool ArgParser::parse() m_pkgaddArgs += " " + s.substr( 8 ); } else if ( s.substr( 0, 8 ) == "--rargs=" ) { m_pkgrmArgs = s.substr( 8 ); - } else if ( s.substr( 0, 7 ) == "--sort=" ) { - m_sortArgs = s.substr( 7 ); } else if ( s.substr( 0, 9 ) == "--filter=" ) { m_filter = s.substr( 9 ); m_hasFilter = true; + } else if ( s.substr( 0, 7 ) == "--sort=" ) { + m_sortArgs = s.substr( 7 ); } else if ( s.substr( 0, 9 ) == "--config=" ) { m_alternateConfigFile = s.substr( 9 ); m_isAlternateConfigGiven = true; @@ -271,22 +240,45 @@ bool ArgParser::parse() } else { if (!m_isCommandGiven) { string s = m_argv[i]; - m_commandName = s; - if ( s == "grpinst" ) { - m_isCommandGiven = true; - m_commandType = commandID[7]; - m_group = true; - cout << "Warning: grpinst is obsolescent"; - cout << "; using install --group" << endl; - } else { - for ( int i = 0; i < commandCount; ++i ) { - if ( s == commands[i] ) { - m_isCommandGiven = true; - m_commandType = commandID[i]; - break; - } - } - } + if ( s == "grpinst") { + m_isCommandGiven = true; + m_commandType = INSTALL; + m_group = true; + cout << "Warning: grpinst is obsolescent"; + cout << "; using install --group" << endl; + } else if (s == "depinst") { + m_isCommandGiven = true; + m_commandType = INSTALL; + m_depSort = true; + } else if (s == "update") { + m_isCommandGiven = true; + m_commandType = INSTALL; + } else if (s == "sysup") { + m_isCommandGiven = true; + m_commandType = DIFF; + m_sysup = true; + } else if (s == "quickdiff") { + m_isCommandGiven = true; + m_commandType = DIFF; + m_quick = true; + } else if (s == "quickdep") { + m_isCommandGiven = true; + m_commandType = DEPENDS; + m_quick = true; + } else if (s == "dependent") { + m_isCommandGiven = true; + m_commandType = DEPTREE; + m_revdep = true; + } else { + for ( int i = 0; i < commandCount; ++i ) { + if ( s == commands[i] ) { + m_isCommandGiven = true; + m_commandName = s; + m_commandType = commandID[i]; + break; + } + } + } // first argument must be command if ( !m_isCommandGiven ) { return false; @@ -297,12 +289,9 @@ bool ArgParser::parse() } } - - return m_isCommandGiven; } - /*! \return true whether --test has been specified */ @@ -311,7 +300,6 @@ bool ArgParser::isTest() const return m_isTest; } - /*! \return the level of verbose: -v -> 1, -vv -> 2 */ @@ -320,7 +308,6 @@ int ArgParser::verbose() const return m_verbose; } - /*! \return whether --cache has been specified */ @@ -329,7 +316,6 @@ bool ArgParser::useCache() const return m_useCache; } - /*! \return whether prt-get was called as 'prt-cache' or not */ @@ -346,14 +332,6 @@ bool ArgParser::writeLog() const return m_writeLog; } -/*! - \return the --sort="..." string -*/ -const string& ArgParser::sortArgs() const -{ - return m_sortArgs; -} - /*! \return whether there was a --filter argument */ @@ -362,7 +340,6 @@ bool ArgParser::hasFilter() const return m_hasFilter; } - /*! \return whether there was a --no-std-config argument */ @@ -371,7 +348,6 @@ bool ArgParser::noStdConfig() const return m_noStdConfig; } - /*! \return the --filter="..." string */ @@ -381,16 +357,18 @@ const string& ArgParser::filter() const } /*! - \return whether there was a --nodeps argument + \return the --sort="..." string */ -bool ArgParser::nodeps() const +const string& ArgParser::sortArgs() const { - return m_nodeps; + return m_sortArgs; +} + +bool ArgParser::depSort() const +{ + return m_depSort; } -/*! - \return whether there was a --softdeps argument -*/ bool ArgParser::followSoftdeps() const { return m_softdeps; @@ -409,6 +387,16 @@ bool ArgParser::printPath() const return m_printPath; } +bool ArgParser::revdep() const +{ + return m_revdep; +} + +bool ArgParser::quick() const +{ + return m_quick; +} + bool ArgParser::recursive() const { return m_recursive; @@ -416,12 +404,7 @@ bool ArgParser::recursive() const bool ArgParser::printTree() const { - return m_printTree; -} - -bool ArgParser::depSort() const -{ - return m_depSort; + return (m_printTree || m_commandName == "deptree"); } const string& ArgParser::commandName() const @@ -470,6 +453,11 @@ bool ArgParser::strictDiff() const return m_strictDiff; } +bool ArgParser::sysup() const +{ + return m_sysup; +} + bool ArgParser::group() const { return m_group; @@ -485,7 +473,6 @@ bool ArgParser::fullPath() const return m_fullPath; } - const string& ArgParser::ignore() const { return m_ignore; diff --git a/src/argparser.h b/src/argparser.h index 44bfe4a..0c02792 100644 --- a/src/argparser.h +++ b/src/argparser.h @@ -31,14 +31,15 @@ public: bool parse(); /*! Command type */ - enum Type { HELP, LIST, SEARCH, DSEARCH, INSTALL, DEPINST, - INFO, DEPENDS, ISINST, DUP, UPDATE, - QUICKDEP, DIFF, - QUICKDIFF, SHOW_VERSION, CREATE_CACHE, PATH, - LISTINST, PRINTF, README, DEPENDENT, SYSUP, - CURRENT, FSEARCH, LOCK, UNLOCK, LISTLOCKED, - CAT, LS, EDIT, REMOVE, - DEPTREE, DUMPCONFIG, LISTORPHANS }; + enum Type { HELP, INFO, SHOW_VERSION, + SEARCH, DSEARCH, FSEARCH, + CREATE_CACHE, INSTALL, REMOVE, + CURRENT, ISINST, DIFF, + PATH, PRINTF, README, + LIST, LISTINST, LISTORPHANS, + LOCK, UNLOCK, LISTLOCKED, + CAT, LS, EDIT, DUMPCONFIG, + DUP, DEPENDS, DEPTREE }; bool isCommandGiven() const; bool isTest() const; @@ -48,27 +49,29 @@ public: bool writeLog() const; bool hasFilter() const; bool noStdConfig() const; - bool nodeps() const; + bool depSort() const; + bool followSoftdeps() const; bool all() const; bool printPath() const; bool execPreInstall() const; bool execPostInstall() const; bool preferHigher() const; bool strictDiff() const; + bool sysup() const; bool group() const; bool useRegex() const; bool fullPath() const; + bool revdep() const; + bool quick() const; bool recursive() const; bool printTree() const; - bool depSort() const; - bool followSoftdeps() const; const string& alternateConfigFile() const; const string& pkgmkArgs() const; const string& pkgaddArgs() const; const string& pkgrmArgs() const; - const string& sortArgs() const; const string& filter() const; + const string& sortArgs() const; const string& installRoot() const; const string& ignore() const; @@ -78,7 +81,7 @@ public: const string& commandName() const; const string& unknownOption() const; - const list& otherArgs() const; + const list& otherArgs() const; int verbose() const; @@ -99,8 +102,9 @@ private: bool m_writeLog; - bool m_nodeps; + bool m_depSort; bool m_softdeps; + bool m_revdep; bool m_all; bool m_printPath; @@ -109,20 +113,19 @@ private: bool m_execPostInstall; bool m_preferHigher; bool m_strictDiff; + bool m_sysup; bool m_group; bool m_useRegex; bool m_fullPath; + bool m_quick; bool m_recursive; bool m_printTree; - bool m_depSort; - string m_alternateConfigFile; string m_pkgmkArgs; string m_pkgaddArgs; string m_pkgrmArgs; - string m_sortArgs; string m_filter; string m_commandName; string m_unknownOption; @@ -136,7 +139,8 @@ private: int m_verbose; - list m_otherArgs; + string m_sortArgs; + list m_otherArgs; list< pair > m_configData; }; diff --git a/src/installtransaction.cpp b/src/installtransaction.cpp index 009223f..21107e9 100644 --- a/src/installtransaction.cpp +++ b/src/installtransaction.cpp @@ -27,6 +27,7 @@ using namespace std; #include "pkgdb.h" #include "stringhelper.h" #include "argparser.h" +#include "versioncomparator.h" #include "process.h" #include "configuration.h" @@ -71,38 +72,6 @@ InstallTransaction::InstallTransaction( const list& names, } -/*! - Create a nice InstallTransaction - \param names a list of port names to be installed - \param repo the repository to look for packages - \param pkgDB the pkgDB with already installed packages -*/ -InstallTransaction::InstallTransaction( const list& names, - const Repository* repo, - PkgDB* pkgDB, - const Configuration* config ) - : m_pkgDB( pkgDB ), - m_resolver(), - m_repo( repo ), - m_depCalced( false ), - m_installedPackages(), - m_alreadyInstalledPackages(), - m_ignoredPackages(), - m_depNameList(), - m_depList(), - m_missingPackages(), - m_installErrors(), - m_config( config ) -{ - list::const_iterator it = names.begin(); - for ( ; it != names.end(); ++it ) { - m_packages.push_back( make_pair( *it, m_repo->getPackage( *it ) ) ); - } - -} - - - /*! Create a nice InstallTransaction \param names a list of port names to be installed @@ -142,18 +111,17 @@ InstallTransaction::installError() const /*! install (commit) a transaction \param parser the argument parser - \param update whether this is an update operation - \param group whether this is a group transaction (stops transaction on error) \return returns an InstallResult telling whether installation worked */ InstallTransaction::InstallResult -InstallTransaction::install( const ArgParser* parser, - bool update ) +InstallTransaction::install( const ArgParser* parser ) { if ( m_packages.empty() ) { return NO_PACKAGE_GIVEN; } + bool update; + const string forceRebuild = "-fr"; list ignoredPackages; StringHelper::split(parser->ignore(), ',', ignoredPackages); @@ -176,12 +144,28 @@ InstallTransaction::install( const ArgParser* parser, continue; } - // consider aliases here, but don't show them specifically - if ( !update && m_pkgDB->isInstalled( package->name(), true ) ) { - // ignore - m_alreadyInstalledPackages.push_back( package->name() ); - continue; - } + // Set the update flag if the package is installed and out of date, + // or if the user has forced a rebuild. + // Proceed to the next target if package is installed and up to date. + if ( m_pkgDB->isInstalled( package->name(), false ) ) { + VersionComparator::COMP_RESULT + rpDiff = VersionComparator::compareVersions( + m_repo->getPackageVersion( package->name() ), + m_pkgDB->getPackageVersion( package->name() ) ); + if ( rpDiff == VersionComparator::EQUAL && + parser->pkgmkArgs().find(forceRebuild) == string::npos ) { + m_alreadyInstalledPackages.push_back( package->name() ); + continue; + } else if ( (! m_config->preferHigher()) + || parser->strictDiff() + || rpDiff == VersionComparator::GREATER + || parser->pkgmkArgs().find(forceRebuild) != + string::npos ) { + update = true; + } else { + continue; + } + } InstallTransaction::InstallResult result; InstallInfo info( package->hasReadme() ); @@ -191,13 +175,12 @@ InstallTransaction::install( const ArgParser* parser, m_installedPackages.push_back( make_pair( package->name(), info)); } else { - // log failures are critical + // log failures and pkgdest errors are critical, + // don't proceed to the next install target if encountered if ( result == LOG_DIR_FAILURE || result == LOG_FILE_FAILURE || result == NO_LOG_FILE || result == CANT_LOCK_LOG_FILE || - - // or pkgdest result == PKGDEST_ERROR ) { return result; } @@ -224,8 +207,7 @@ InstallTransaction::installPackage( const Package* package, const ArgParser* parser, bool update, InstallTransaction::InstallInfo& info ) - const -{ +const { InstallTransaction::InstallResult result = SUCCESS; #ifdef USE_LOCKING @@ -241,7 +223,7 @@ InstallTransaction::installPackage( const Package* package, commandName = "prt-cache"; } - // - initial information about the package to be build + // - initial information about the package to be built string message; message = commandName + ": "; if (update) { @@ -299,8 +281,8 @@ InstallTransaction::installPackage( const Package* package, write( fdlog, timestamp.c_str(), timestamp.length()); } - string pkgdir = package->path() + "/" + package->name(); - chdir( pkgdir.c_str() ); + string portdir = package->path() + "/" + package->name(); + chdir( portdir.c_str() ); string runscriptCommand = "sh"; if (m_config->runscriptCommand() != "") { @@ -308,11 +290,11 @@ InstallTransaction::installPackage( const Package* package, } // -- pre-install - struct stat statData; + struct stat statData; struct stat fstatData; if ((parser->execPreInstall() || m_config->runScripts()) && - stat((pkgdir + "/" + "pre-install").c_str(), &statData) == 0) { + stat((portdir + "/pre-install").c_str(), &statData) == 0) { Process preProc( runscriptCommand, - pkgdir + "/" + "pre-install", + portdir + "/pre-install", fdlog ); if (preProc.executeShell()) { info.preState = FAILED; @@ -322,22 +304,32 @@ InstallTransaction::installPackage( const Package* package, } // -- build + string pkgdest = getPkgmkPackageDir(); + const string builtPkg = package->name() + "#" + package->version() + "-" + + package->release() + ".pkg.tar." + getPkgmkCompressionMode(); + string builtPkgPath = ( pkgdest != "" ) ? pkgdest + "/" + builtPkg : + portdir + "/" + builtPkg ; string cmd = PKGMK_DEFAULT_COMMAND; if (m_config->makeCommand() != "") { cmd = m_config->makeCommand(); } + // skip the build if a package exists newer than Pkgfile + // (e.g., created by running pkgmk manually) + if ( stat(builtPkgPath.c_str(), &statData) + + stat((portdir + "/Pkgfile").c_str(), &fstatData) == 0) { + time_t pkgMtime = statData.st_mtime; + time_t pfMtime = fstatData.st_mtime; + if ( difftime(pkgMtime,pfMtime) > 0 ) { cmd = "/bin/true"; } + } + string args = "-d " + parser->pkgmkArgs(); Process makeProc( cmd, args, fdlog ); if ( makeProc.executeShell() ) { result = PKGMK_FAILURE; } else { - // -- update - string pkgdest = getPkgmkPackageDir(); - if ( pkgdest != "" ) { - // TODO: don't manipulate pkgdir - pkgdir = pkgdest; - string message = "prt-get: Using PKGMK_PACKAGE_DIR: " + pkgdir; + string message = ( pkgdest == "" ) ? "" : + commandName + ": Using PKGMK_PACKAGE_DIR " + pkgdest; if (parser->verbose() > 0) { cout << message << endl; } @@ -345,94 +337,78 @@ InstallTransaction::installPackage( const Package* package, write( fdlog, message.c_str(), message.length() ); write( fdlog, "\n", 1 ); } - } + } - // the following chdir is a noop if usePkgDest() returns false - if ( chdir( pkgdir.c_str() ) != 0 ) { - result = PKGDEST_ERROR; + // no need to chdir if we provide absolute paths to pkgadd + cmd = PKGADD_DEFAULT_COMMAND; + if (m_config->addCommand() != "") { + cmd = m_config->addCommand(); + } + + args = ""; + if (parser->installRoot() != "") { + args = "-r " + parser->installRoot() + " "; + } + + if ( update ) { + args += "-u "; + } + if ( !parser->pkgaddArgs().empty() ) { + args += parser->pkgaddArgs() + " "; + } + args += builtPkgPath; + + // - inform the user about what's happening + string fullCommand = commandName + ": " + cmd + args; + string summary; + if (update) { + string from = m_pkgDB->getPackageVersion(package->name()); + string to = m_repo->getPackageVersion(package->name()); + if (from == to) { + summary = commandName + ": " + "reinstalling " + + package->name() + " " + to; } else { - cmd = PKGADD_DEFAULT_COMMAND; - if (m_config->addCommand() != "") { - cmd = m_config->addCommand(); - } + summary = commandName + ": " + "updating " + + package->name() + " from " + from + " to " + to; + } + } else { + summary = commandName + ": " + "installing " + package->name() + + " " + package->version() + "-" + package->release(); + } - args = ""; - if (parser->installRoot() != "") { - args = "-r " + parser->installRoot() + " "; - } + // - print and log + cout << summary << endl; + if (parser->verbose() > 0) { + cout << fullCommand << endl; + } + if ( m_config->writeLog() ) { + time_t endTime; + time(&endTime); + timestamp = ctime(&endTime); + timestamp = commandName + ": build done " + timestamp; + write( fdlog, summary.c_str(), summary.length() ); + write( fdlog, "\n", 1 ); + write( fdlog, fullCommand.c_str(), fullCommand.length() ); + write( fdlog, "\n", 1 ); + write( fdlog, timestamp.c_str(), timestamp.length()); + write( fdlog, "\n", 1 ); + } - if ( update ) { - args += "-u "; - } - if ( !parser->pkgaddArgs().empty() ) { - args += parser->pkgaddArgs() + " "; - } - args += - package->name() + "#" + - package->version() + "-" + - package->release() + ".pkg.tar." + getPkgmkCompressionMode(); - - - // - inform the user about what's happening - string fullCommand = commandName + ": " + cmd + " " + args; - string summary; - if (update) { - string from = m_pkgDB->getPackageVersion(package->name()); - string to = package->version() + "-" + package->release(); - if (from == to) { - summary = commandName + ": " + "reinstalling " + - package->name() + " " + to; + Process installProc( cmd, args, fdlog ); + if ( installProc.executeShell() ) { + result = PKGADD_FAILURE; + } else { + // exec post install + if ((parser->execPostInstall() || m_config->runScripts() ) && + stat((portdir + "/post-install").c_str(), &statData) == 0) { + Process postProc( runscriptCommand, + portdir + "/post-install", fdlog ); + if (postProc.executeShell()) { + info.postState = FAILED; } else { - summary = commandName + ": " + "updating " + - package->name() + " from " + from + " to " + to; + info.postState = EXEC_SUCCESS; } - } else { - summary = commandName + ": " + "installing " + - package->name() + " " + - package->version() + "-" + package->release(); - } - - // - print and log - cout << summary << endl; - if (parser->verbose() > 0) { - cout << fullCommand << endl; - } - if ( m_config->writeLog() ) { - time_t endTime; - time(&endTime); - timestamp = ctime(&endTime); - timestamp = commandName + ": build done " + timestamp; - - write( fdlog, summary.c_str(), summary.length() ); - write( fdlog, "\n", 1 ); - write( fdlog, fullCommand.c_str(), fullCommand.length() ); - write( fdlog, "\n", 1 ); - write( fdlog, timestamp.c_str(), timestamp.length()); - write( fdlog, "\n", 1 ); - } - - Process installProc( cmd, args, fdlog ); - if ( installProc.executeShell() ) { - result = PKGADD_FAILURE; - } else { - // exec post install - if ((parser->execPostInstall() || m_config->runScripts() ) && - stat((package->path() + "/" + package->name() + - "/" + "post-install").c_str(), &statData) - == 0) { - // Work around the pkgdir variable change - Process postProc( runscriptCommand, - package->path() + "/" + package->name()+ - "/" + "post-install", - fdlog ); - if (postProc.executeShell()) { - info.postState = FAILED; - } else { - info.postState = EXEC_SUCCESS; - } - } - } } } @@ -568,7 +544,7 @@ void InstallTransaction::checkDependencies( bool greedy, if ( pos != string::npos && (pos+1) < softdep.length() ) { softdep = softdep.substr( pos + 1 ); } - if ( m_pkgDB->isInstalled(softdep, true) ) { + if ( m_pkgDB->isInstalled(softdep, false) or isRequested(softdep) ) { const Package* p = m_repo->getPackage( softdep ); if ( p ) { checkDependencies( true, p, index ); @@ -586,6 +562,16 @@ void InstallTransaction::checkDependencies( bool greedy, treeWalk.pop_back(); } +/*! + Method to determine whether a package was passed on the command line +*/ +bool InstallTransaction::isRequested(const string pname) { + list< pair >::iterator it = m_packages.begin(); + for ( ; it != m_packages.end(); ++it ) { + if ( it->first == pname ) { return true; } + } + return false; +} /*! This method returns a list of packages which should be installed to @@ -638,11 +624,11 @@ InstallTransaction::installedPackages() const /*! calculate dependendencies for this package */ -InstallTransaction::InstallResult -InstallTransaction::calcDependencies( ) +bool InstallTransaction::calcDependencies( ) { if ( m_packages.empty() ) { - return NO_PACKAGE_GIVEN; + cout << "No packages given for this transaction" << endl; + return false; } bool validPackages = false; @@ -656,13 +642,15 @@ InstallTransaction::calcDependencies( ) } } if ( !validPackages ) { - return PACKAGE_NOT_FOUND; + cout << "No valid packages in this transaction" << endl; + return false; } if ( !calculateDependencies() ) { - return CYCLIC_DEPEND; + cout << "Could not resolve dependencies for this transaction" << endl; + return false; } - return SUCCESS; + return true; } diff --git a/src/installtransaction.h b/src/installtransaction.h index 53030ab..ebfc215 100644 --- a/src/installtransaction.h +++ b/src/installtransaction.h @@ -33,10 +33,6 @@ class Configuration; class InstallTransaction { public: - InstallTransaction( const list& names, - const Repository* repo, - PkgDB* pkgDB, - const Configuration* config ); InstallTransaction( const list& names, const Repository* repo, PkgDB* pkgDB, @@ -54,12 +50,12 @@ public: /*! Result of an installation */ enum InstallResult { SUCCESS, /*!< yeah, success */ - NO_PACKAGE_GIVEN, /*!< no package give to install */ + NO_PACKAGE_GIVEN, /*!< no package given to install */ PACKAGE_NOT_FOUND, /*!< package not found */ PKGMK_EXEC_ERROR, /*!< can't execute pkgmk */ PKGMK_FAILURE, /*!< error while pkgmk */ PKGADD_EXEC_ERROR, /*!< can't execute pkgadd */ - PKGDEST_ERROR, /*!< can't change to PKGDEST */ + PKGDEST_ERROR, /*!< can't change to PKGDEST */ PKGADD_FAILURE, /*!< error while pkgadd */ CYCLIC_DEPEND, /*!< cyclic dependencies found */ LOG_DIR_FAILURE, /*!< couldn't create log directory */ @@ -84,15 +80,13 @@ public: bool hasReadme; }; - InstallResult install( const ArgParser* parser, - bool update ); - InstallResult calcDependencies(); + InstallResult install( const ArgParser* parser ); + bool calcDependencies(); const list< pair >& installedPackages() const; const list& alreadyInstalledPackages() const; const list& ignoredPackages() const; - const list& dependencies() const; const list< pair >& missing() const; const list< pair >& installError() const; @@ -108,6 +102,7 @@ private: const ArgParser* parser, bool update, InstallInfo& info ) const; + bool isRequested(const string pname); static string getPkgmkSetting(const string& setting); static string getPkgmkSettingFromFile(const string& setting, diff --git a/src/main.cpp b/src/main.cpp index c1af3f1..5f2f98f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,17 +57,13 @@ int main( int argc, char** argv ) ArgParser::Type command = argParser.commandType(); - switch ( command ) - { + switch ( command ) { case ArgParser::HELP: prtGet.printUsage(); break; case ArgParser::SHOW_VERSION: prtGet.printVersion(); break; - case ArgParser::LIST: - prtGet.listPackages(); - break; case ArgParser::DUP: prtGet.listShadowed(); break; @@ -84,25 +80,16 @@ int main( int argc, char** argv ) prtGet.isInstalled(); break; case ArgParser::INSTALL: - prtGet.install(); + prtGet.install( argParser.depSort() ); break; - case ArgParser::DEPINST: - prtGet.install( false, true ); - break; case ArgParser::DEPENDS: - prtGet.printDepends(); - break; - case ArgParser::QUICKDEP: - prtGet.printDepends( true ); - break; - case ArgParser::UPDATE: - prtGet.install( true ); + prtGet.printDepends( argParser.quick() ); break; + case ArgParser::DEPTREE: + prtGet.printDepTree(); + break; case ArgParser::DIFF: - prtGet.printDiff(); - break; - case ArgParser::QUICKDIFF: - prtGet.printQuickDiff(); + prtGet.printDiff( argParser.quick() ); break; case ArgParser::CREATE_CACHE: prtGet.createCache(); @@ -110,36 +97,36 @@ int main( int argc, char** argv ) case ArgParser::PATH: prtGet.printPath(); break; - case ArgParser::LISTINST: - prtGet.listInstalled(); - break; case ArgParser::PRINTF: prtGet.printf(); break; case ArgParser::README: prtGet.readme(); break; - case ArgParser::DEPENDENT: - prtGet.printDependent(); - break; - case ArgParser::SYSUP: - prtGet.sysup(); - break; case ArgParser::CURRENT: prtGet.current(); break; case ArgParser::FSEARCH: prtGet.fsearch(); break; + case ArgParser::LIST: + prtGet.listPackages(); + break; + case ArgParser::LISTINST: + prtGet.listInstalled(); + break; + case ArgParser::LISTORPHANS: + prtGet.listOrphans(); + break; + case ArgParser::LISTLOCKED: + prtGet.listLocked(); + break; case ArgParser::LOCK: prtGet.setLock( true ); break; case ArgParser::UNLOCK: prtGet.setLock( false ); break; - case ArgParser::LISTLOCKED: - prtGet.listLocked(); - break; case ArgParser::CAT: prtGet.cat(); break; @@ -152,15 +139,9 @@ int main( int argc, char** argv ) case ArgParser::REMOVE: prtGet.remove(); break; - case ArgParser::DEPTREE: - prtGet.printDependTree(); - break; case ArgParser::DUMPCONFIG: prtGet.dumpConfig(); break; - case ArgParser::LISTORPHANS: - prtGet.listOrphans(); - break; default: cerr << "unknown command" << endl; break; diff --git a/src/pkgdb.h b/src/pkgdb.h index 930b8e1..e772ca3 100644 --- a/src/pkgdb.h +++ b/src/pkgdb.h @@ -32,6 +32,7 @@ public: bool useAlias = false, bool* isAlias = 0, string* aliasOrignalName = 0 ) const; + bool isOutdated( const std::string& name ) const; std::string getPackageVersion( const std::string& name ) const; diff --git a/src/prtget.cpp b/src/prtget.cpp index ddac10c..30d6038 100644 --- a/src/prtget.cpp +++ b/src/prtget.cpp @@ -39,7 +39,6 @@ using namespace std; #include "datafileparser.h" using namespace StringHelper; - using VersionComparator::COMP_RESULT; using VersionComparator::GREATER; using VersionComparator::LESS; @@ -60,15 +59,13 @@ PrtGet::PrtGet( const ArgParser* parser ) m_locker(), m_parser( parser ), m_cacheFile( DEFAULT_CACHE_FILE ), - m_returnValue( PG_OK ) -{ + m_returnValue( PG_OK ) { if ( m_parser->wasCalledAsPrtCached() ) { m_appName = "prt-cache"; } else { m_appName = "prt-get"; } - m_pkgDB = new PkgDB(m_parser->installRoot()); readConfig(); @@ -77,8 +74,7 @@ PrtGet::PrtGet( const ArgParser* parser ) } /*! destruct PrtGet object */ -PrtGet::~PrtGet() -{ +PrtGet::~PrtGet() { if ( m_config ) { delete m_config; } @@ -89,17 +85,14 @@ PrtGet::~PrtGet() delete m_pkgDB; } - /*! print version and exit */ -void PrtGet::printVersion() -{ +void PrtGet::printVersion() { cout << m_appName << " " << VERSION << " by Johannes Winkelmann, jw@tks6.net" << endl; } /*! print version, usage and exit */ -void PrtGet::printUsage() -{ +void PrtGet::printUsage() { printVersion(); cout << "Usage: " << m_appName << " [options]" << endl; @@ -128,37 +121,28 @@ void PrtGet::printUsage() << endl; cout << "\nDIFFERENCES / CHECK FOR UPDATES" << endl; - cout << " diff list outdated packages (or check " - << "args for change)" << endl; - cout << " quickdiff same as diff but simple format" - << endl; + cout << " diff [opt] list outdated packages" << endl; cout << " where opt can be:" << endl; - cout << " --all display locked ports too" - << endl; - cout << " --prefer-higher prefer higher installed " - << "versions over lower ports" - << endl; + cout << " --quick | -Q simple format" << endl; + cout << " --all display locked ports too" << endl; + cout << " --prefer-higher prefer higher " + << "versions over lower" << endl; cout << " --strict-diff override prefer higher " << "configuration setting" << endl; cout << "\nDEPENDENCIES" << endl; - cout << " depends calculate dependencies of the given ports" + cout << " depends [opt] calculate dependencies of the given ports" << endl; - cout << " quickdep same as 'depends' but simple format" - << endl; - cout << " deptree show dependencies tree for " - << endl; - cout << " dependent [opt] show installed packages which " - << "depend on 'port'" - << endl; - cout << " where opt can be:" << endl; - cout << " --softdeps consider optional dependencies too" - << endl; - cout << " --all list all dependent packages, not " + cout << " where opt can be:" << endl; + cout << " --reverse calculate packages that depend on " << endl; + cout << " --all list all dependent packages, not " << "only installed" << endl; - cout << " --recursive print recursive listing" << endl; - cout << " --tree print recursive tree listing" + cout << " --softdeps consider optional dependencies too" + << endl; + cout << " --quick | -Q simple listing, space-separated" << endl; + cout << " --recursive calculate recursively (default unless --reverse)" << endl; + cout << " --tree | -T print recursive tree listing" << endl; cout << "\nSEARCHING" << endl; @@ -169,33 +153,31 @@ void PrtGet::printUsage() << "'pattern'" << endl; cout << "\nINSTALL, UPDATE and REMOVAL" << endl; - cout << " install [opt] install ports" << endl; - cout << " update [opt] update ports" << endl; - cout << " depinst [opt] install ports and their dependencies" - << endl; + cout << " install [opt] install/update these ports" << endl; cout << " remove [opt] remove ports" << endl; cout << " where opt can be:" << endl; - cout << " -g, --group stop if one package fails" << endl; - cout << " -f, -fi force installation" << endl; - cout << " -fr force rebuild" << endl; - cout << " -uf update footprint" << endl; - cout << " -if ignore footprint" << endl; - cout << " -um update md5sum" << endl; - cout << " -im ignore md5sum" << endl; - cout << " -us update signature" << endl; - cout << " -is ignore signature" << endl; - cout << " --margs= pass 'string' to pkgmk" + cout << " -g, --group stop if one package fails" << endl; + cout << " --nodeps don't inject (or sort by) dependencies" << endl; + cout << " -f, -fi force installation" << endl; + cout << " -fr force rebuild" << endl; + cout << " -uf update footprint" << endl; + cout << " -if ignore footprint" << endl; + cout << " -um update md5sum" << endl; + cout << " -im ignore md5sum" << endl; + cout << " -us update signature" << endl; + cout << " -is ignore signature" << endl; + cout << " --margs= pass 'string' to pkgmk" << endl; - cout << " --aargs= pass 'string' to pkgadd" + cout << " --aargs= pass 'string' to pkgadd" << endl; - cout << " --rargs= pass 'string' to pkgrm" + cout << " --rargs= pass 'string' to pkgrm" << endl; - cout << " --test test mode" << endl; - cout << " --log write log file"<< endl; - cout << " --ignore=" << endl - << " Don't install/update those packages"<< endl; - cout << " --pre-install execute pre-install script" + cout << " --test test mode" << endl; + cout << " --log write log file"<< endl; + cout << " --ignore=" << endl + << " Don't install/update those packages"<< endl; + cout << " --pre-install execute pre-install script" << endl; cout << " --post-install execute post-install script" << endl; @@ -207,43 +189,38 @@ 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 inject (or sort by) dependencies" << endl; - cout << " --softdeps consider optional dependencies when sorting" + cout << " --softdeps consider optional dependencies when sorting" << endl; - cout << " --test test mode" << endl; - cout << " --log write log file"<< endl; + cout << " --test test mode" << endl; + cout << " --log write log file"<< endl; - cout << " lock lock current version " - << "of packages" + cout << " lock lock these ports at their current version" << endl; - cout << " unlock unlock packages" + cout << " unlock unlock these ports" << endl; - cout << " listlocked list locked packages" + cout << " listlocked list locked ports" << endl; cout << "\nFILE OPERATIONS " << endl; - cout << " ls print a listing of the port's" + cout << " ls print a listing of the port's" << " directory" << endl; - cout << " cat print out 'port/file'" + cout << " cat print out 'port/file'" << endl; - cout << " edit edit 'port/file'" << endl; + cout << " edit edit 'port/file'" << endl; cout << "\nGENERAL OPTIONS" << endl; - cout << " -v Show version in listing" + cout << " -v Show version in listing" << endl; - cout << " -vv Show version and decription " << "in listing\n" << endl; - cout << " --path Print path to port if appropriate (search, list, depends)\n" << endl; - cout << " --cache Use a cache file" << endl; - cout << " --config= Use alternative " + cout << " -vv Show version and decription " << "in listing\n" << endl; + cout << " --path Print path to port if appropriate (search, list, depends)\n" << endl; + cout << " --cache Use a cache file" << endl; + cout << " --config= Use alternative " << "configuration file" << endl; - cout << " --install-root=.. Use alternative " + cout << " --install-root=.. Use alternative " << "install root directory" << endl; - - - - cout << " --no-std-config Don't parse " << "default configuration file" << endl; cout << " --config-prepend=.. Prepend '..' to" @@ -257,10 +234,8 @@ void PrtGet::printUsage() } - /*! print list of duplicate packages in the repository */ -void PrtGet::listShadowed() -{ +void PrtGet::listShadowed() { if ( m_parser->useCache() ) { cout << m_appName << ": command 'dup' can't work on a cache" << endl; m_returnValue = PG_GENERAL_ERROR; @@ -302,8 +277,7 @@ void PrtGet::listShadowed() \sa Repository::getMatchingPackages() */ -void PrtGet::listPackages() -{ +void PrtGet::listPackages() { string arg = "*"; assertMaxArgCount(1); @@ -341,8 +315,7 @@ void PrtGet::listPackages() \sa Repository::searchMatchingPackages() */ -void PrtGet::searchPackages( bool searchDesc ) -{ +void PrtGet::searchPackages( bool searchDesc ) { assertExactArgCount(1); initRepo(); @@ -364,7 +337,6 @@ void PrtGet::searchPackages( bool searchDesc ) cout << ": " << (*it)->description(); } - cout << endl; } } else { @@ -374,8 +346,7 @@ void PrtGet::searchPackages( bool searchDesc ) } /*! print info for a package */ -void PrtGet::printInfo() -{ +void PrtGet::printInfo() { assertExactArgCount(1); initRepo(); @@ -433,14 +404,12 @@ void PrtGet::printInfo() } } - /*! initialize repository \sa Repository::initFromCache() \sa Repository::initFromFS() */ -void PrtGet::initRepo( bool listDuplicate ) -{ +void PrtGet::initRepo( bool listDuplicate ) { if ( !m_repo ) { m_repo = new Repository(m_useRegex); @@ -490,12 +459,11 @@ void PrtGet::initRepo( bool listDuplicate ) } /*! print whether a package is installed or not */ -void PrtGet::isInstalled() -{ +void PrtGet::isInstalled() { assertMinArgCount(1); - const list& l = m_parser->otherArgs(); - list::const_iterator it = l.begin(); + const list& l = m_parser->otherArgs(); + list::const_iterator it = l.begin(); for ( ; it != l.end(); ++it ) { bool isAlias = false; string aliasName; @@ -515,10 +483,8 @@ void PrtGet::isInstalled() } } - /*! list installed packages */ -void PrtGet::listInstalled() -{ +void PrtGet::listInstalled() { assertMaxArgCount(1); string arg = m_useRegex ? ".*" : "*"; @@ -551,26 +517,22 @@ void PrtGet::listInstalled() l.erase(mit); InstallTransaction trans( name, m_repo, m_pkgDB, m_config ); - InstallTransaction::InstallResult result __attribute__((unused)) = trans.calcDependencies(); - const list& depRef = trans.dependencies(); - list::const_iterator it = depRef.begin(); - - - for (; it != depRef.end(); ++it) { - if (l.find(*it) != l.end()) { - cout << *it << endl; - l.erase(*it); - } - } - cout << name << endl; + if ( trans.calcDependencies() ) { + const list& depRef = trans.dependencies(); + list::const_iterator it = depRef.begin(); + for (; it != depRef.end(); ++it) { + if (l.find(*it) != l.end()) { + cout << *it << endl; + l.erase(*it); + } + } + cout << name << endl; + } else { break; } } } else { + if ( m_parser->verbose() > 1 ) { initRepo(); } for ( ; it != l.end(); ++it ) { - if ( m_parser->verbose() > 1 ) { - // warning: will slow down the process... - initRepo(); - } cout << it->first.c_str(); if ( m_parser->verbose() > 0 ) { cout << " " << it->second.c_str(); @@ -589,49 +551,13 @@ void PrtGet::listInstalled() /*! install package - \param update, whether this is an update operation - \param dependencies, whether to consider dependencies - + param \a dependencies, whether to resolve dependencies */ -void PrtGet::install( bool update, bool dependencies ) -{ +void PrtGet::install( bool dependencies ) { assertMinArgCount(1); - // this can be done without initRepo() - const list& args = m_parser->otherArgs(); - list invalidArgs; - list::const_iterator it = args.begin(); - - if ( update ) { - for ( ; it != args.end(); ++it ) { - string s = *it; - if ( !m_pkgDB->isInstalled( s ) ) { - // can't upgrade what isn't installed - invalidArgs.push_back( s ); - } - } - } else { - for ( ; it != args.end(); ++it ) { - string s = *it; - if ( m_pkgDB->isInstalled( s ) ) { - // pkgadd will fail on these, since it won't be given the -u flag - invalidArgs.push_back( s ); - } - } - } - - if ( invalidArgs.size() > 0 ) { - string attemptedOp = ( update ) ? "update" : "install"; - attemptedOp += " the following packages "; - attemptedOp += ( update ) ? "(not yet installed)" : "(already installed)"; - cout << "cannot "<< attemptedOp <::const_iterator it = invalidArgs.begin(); - for ( ; it != invalidArgs.end(); ++it ) { - cout << *it << endl; - } - m_returnValue = PG_GENERAL_ERROR ; - return; - } + const list& args = m_parser->otherArgs(); + list::const_iterator it = args.begin(); initRepo(); @@ -639,101 +565,87 @@ void PrtGet::install( bool update, bool dependencies ) // calc dependencies InstallTransaction depTransaction( m_parser->otherArgs(), m_repo, m_pkgDB, m_config ); - InstallTransaction::InstallResult result = - depTransaction.calcDependencies(); + bool depck = depTransaction.calcDependencies(); - // TODO: code duplication with printDepends! - if ( result == InstallTransaction::CYCLIC_DEPEND ) { - cerr << "prt-get: cyclic dependencies found" << endl; - m_returnValue = PG_GENERAL_ERROR; - return; - } else if ( result == InstallTransaction::PACKAGE_NOT_FOUND ) { - warnPackageNotFound(depTransaction); - m_returnValue = PG_GENERAL_ERROR; - return; - } - const list& depRef = depTransaction.dependencies(); - list::const_iterator it = depRef.begin(); + // early exit when dependencies cannot be satisfied + if (!depck) { return; } - list deps; - for (; it != depRef.end(); ++it) { - if (!m_pkgDB->isInstalled(*it)) { - deps.push_back(*it); - } - } + const list& deps = depTransaction.dependencies(); InstallTransaction transaction( deps, m_repo, m_pkgDB, m_config ); - executeTransaction( transaction, update ); + executeTransaction( transaction ); } else { InstallTransaction transaction( m_parser->otherArgs(), m_repo, m_pkgDB, m_config ); - executeTransaction( transaction, update ); + executeTransaction( transaction ); } } -void PrtGet::executeTransaction( InstallTransaction& transaction, - bool update ) -{ +void PrtGet::executeTransaction( InstallTransaction& transaction ) { m_currentTransaction = &transaction; - string command[] = { "install", "installed" }; - if ( update ) { - command[0] = "update"; - command[1] = "updated"; - } - if ( m_parser->isTest() ) { cout << "*** " << m_appName << ": test mode" << endl; } InstallTransaction::InstallResult result = - transaction.install( m_parser, update ); + transaction.install( m_parser ); bool failed = false; - // TODO: use switch - if ( result == InstallTransaction::PACKAGE_NOT_FOUND ) { - cout << m_appName << ": package(s) not found" << endl; - } else if ( result == InstallTransaction::PKGMK_EXEC_ERROR ) { - cout << m_appName << " couldn't excecute pkgmk " - << "(or alternative command). " - << "Make sure it's installed properly" << endl; - } else if ( result == InstallTransaction::PKGMK_FAILURE ) { - cout << m_appName << ": error while " << command[0] << endl; - } else if ( result == InstallTransaction::NO_PACKAGE_GIVEN ) { - cout << m_appName << ": no package specified for " - << command[0] << endl; - } else if ( result == InstallTransaction::PKGADD_EXEC_ERROR ) { - cout << m_appName << " couldn't excecute pkgadd. " - << "Make sure it's installed properly" << endl; - } else if ( result == InstallTransaction::PKGDEST_ERROR ) { - cout << m_appName << ": error changing to PKGDEST directory " - << transaction.getPkgmkPackageDir() << endl; - failed = true; - } else if ( result == InstallTransaction::PKGADD_FAILURE ) { - cout << m_appName << ": error while pkgadding " << endl; - } else if ( result == InstallTransaction::LOG_DIR_FAILURE ) { - cout << m_appName << ": can't create log file directory " << endl; - } else if ( result == InstallTransaction::LOG_FILE_FAILURE ) { - cout << m_appName << ": can't create log file" << endl; - failed = true; - } else if ( result == InstallTransaction::NO_LOG_FILE ) { - cout << m_appName << ": no log file specified, but logging enabled" - << endl; - failed = true; - } else if ( result == InstallTransaction::CANT_LOCK_LOG_FILE ) { - cout << m_appName << ": can't create lock file for the log file. " - << "\nMaybe there's another instance of prt-get using the same " - << "file." - << "\nIf this is a stale not, please remove " - // TODO: file name of lock file - << endl; - failed = true; - } else if ( result != InstallTransaction::SUCCESS ) { - cout << m_appName << ": Unknown error " << result << endl; - failed = true; + switch (result) { + case InstallTransaction::SUCCESS: + break; + case InstallTransaction::PACKAGE_NOT_FOUND: + cout << m_appName << ": package(s) not found" << endl; + break; + case InstallTransaction::PKGMK_EXEC_ERROR: + cout << m_appName << " couldn't excecute pkgmk " + << "(or alternative command). " + << "Make sure it's installed properly" << endl; + break; + case InstallTransaction::PKGMK_FAILURE: + cout << m_appName << ": error while building " << endl; + break; + case InstallTransaction::NO_PACKAGE_GIVEN: + cout << m_appName << ": no package specified " << endl; + break; + case InstallTransaction::PKGADD_EXEC_ERROR: + cout << m_appName << " couldn't excecute pkgadd. " + << "Make sure it's installed properly" << endl; + break; + case InstallTransaction::PKGDEST_ERROR: + cout << m_appName << ": error changing to PKGDEST directory " + << transaction.getPkgmkPackageDir() << endl; + failed = true; + break; + case InstallTransaction::PKGADD_FAILURE: + cout << m_appName << ": error while pkgadding " << endl; + break; + case InstallTransaction::LOG_DIR_FAILURE: + cout << m_appName << ": can't create log file directory " << endl; + break; + case InstallTransaction::LOG_FILE_FAILURE: + cout << m_appName << ": can't create log file" << endl; + failed = true; + break; + case InstallTransaction::NO_LOG_FILE: + cout << m_appName << + ": no log file specified, but logging enabled" << endl; + failed = true; + break; + case InstallTransaction::CANT_LOCK_LOG_FILE: + cout << m_appName << + ": can't create lock file for the log file. " << + "\nMaybe there's another instance of prt-get using the same " << + "file." << "\nIf this is a stale not, please remove " << endl; + failed = true; + break; + default: + cout << m_appName << ": Unknown error " << result << endl; + failed = true; } if ( !failed ) { - evaluateResult( transaction, update ); + evaluateResult( transaction ); if ( m_parser->isTest() ) { cout << "\n*** " << m_appName << ": test mode end" << endl; } @@ -748,24 +660,16 @@ void PrtGet::executeTransaction( InstallTransaction& transaction, print dependency listing \param simpleListing Whether it should be in a simple format */ -void PrtGet::printDepends( bool simpleListing ) -{ +void PrtGet::printDepends( bool simpleListing ) { assertMinArgCount(1); initRepo(); InstallTransaction transaction( m_parser->otherArgs(), m_repo, m_pkgDB, m_config ); - InstallTransaction::InstallResult result = transaction.calcDependencies(); - if ( result == InstallTransaction::CYCLIC_DEPEND ) { - cerr << "prt-get: cyclic dependencies found" << endl; - m_returnValue = PG_GENERAL_ERROR; - return; - } else if ( result == InstallTransaction::PACKAGE_NOT_FOUND ) { - warnPackageNotFound(transaction); - m_returnValue = PG_GENERAL_ERROR; - return; - } + bool depck = transaction.calcDependencies(); + // early exit if dependencies could not be satisfied + if (! depck) { return; } const list& deps = transaction.dependencies(); if ( simpleListing ) { @@ -824,8 +728,7 @@ void PrtGet::printDepends( bool simpleListing ) } /*! read the config file */ -void PrtGet::readConfig() -{ +void PrtGet::readConfig() { string fName = CONF_FILE; if ( m_parser->isAlternateConfigGiven() ) { fName = m_parser->alternateConfigFile(); @@ -856,88 +759,38 @@ void PrtGet::readConfig() } } -/*! - print a simple list of port which are installed in a different version - than they are in the repository -*/ -void PrtGet::printQuickDiff() -{ - initRepo(); - - 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 ) { - result = compareVersions(p->versionReleaseString(), - it->second); - if (result == GREATER) { - cout << it->first.c_str() << " "; - } - // we don't care about undefined diffs here - } - } - } - cout << endl; -} - - void PrtGet::printFormattedDiffLine(const string& name, const string& versionInstalled, const string& versionPortsTree, - bool isLocked) -{ + bool isLocked) { + unsigned int minWidth = 20; cout.setf( ios::left, ios::adjustfield ); - cout.width( 20 ); + cout.width( minWidth ); cout.fill( ' ' ); - cout << name; + ( name.size() < minWidth ) ? cout << name : cout << name + " "; - cout.width( 20 ); + cout.width( minWidth ); cout.fill( ' ' ); - cout << versionInstalled; + ( versionInstalled.size() < minWidth ) ? cout << versionInstalled : + cout << versionInstalled + " "; - string locked = ""; - if ( isLocked ) { - locked = "locked"; - } - cout.width( 20 ); + string locked = ( isLocked ) ? "locked" : ""; + cout.width( minWidth ); cout.fill( ' ' ); - cout << versionPortsTree << locked << endl; + ( versionPortsTree.size() < minWidth ) ? cout << versionPortsTree : + cout << versionPortsTree + " "; + cout << locked << endl; } + /*! print an overview of port which are installed in a different version than they are in the repository + param \simpleListing, whether to format as a space-separated list, with no header */ -void PrtGet::printDiff() -{ +void PrtGet::printDiff( bool simpleListing ) { + bool sysup = m_parser->sysup(); initRepo(); - map< string, string > l; - if ( m_parser->otherArgs().size() > 0 ) { - expandWildcardsPkgDB( m_parser->otherArgs(), l ); - } - if ( l.size() < m_parser->otherArgs().size() ) { - cerr << "prt-get: no matching installed packages found" << endl; - m_returnValue = PG_GENERAL_ERROR; - return; - } - -#if 0 - // const list& l = m_parser->otherArgs(); - // list::const_iterator checkIt = l.begin(); - - // check whether ports to be checked are installed - list< string >::iterator checkIt = l.begin(); - for ( ; checkIt != l.end(); ++checkIt ) { - if ( ! m_pkgDB->isInstalled( *checkIt ) ) { - cerr << "Port not installed: " << *checkIt << endl; - m_returnValue = PG_GENERAL_ERROR; - return; - } - } -#endif + list packagesToUpdate; const map& installed = m_pkgDB->installedPackages(); map::const_iterator it = installed.begin(); @@ -948,20 +801,12 @@ void PrtGet::printDiff() p = m_repo->getPackage( it->first ); if ( p ) { - if ( l.size() && l.find( it->first ) == l.end() ) { - continue; - } - - result = compareVersions( p->versionReleaseString(), - 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() ) { - + if ( !m_locker.isLocked( it->first ) || m_parser->all() ) { ++count; - if ( count == 1 ) { + if (( count == 1 ) && (! simpleListing) && (! sysup)) { cout << "Differences between installed packages " << "and ports tree:\n" << endl; printFormattedDiffLine("Port", @@ -971,10 +816,16 @@ void PrtGet::printDiff() cout << endl; } - printFormattedDiffLine(it->first, + if ((! sysup) and (! simpleListing)) { + printFormattedDiffLine(it->first, it->second, p->versionReleaseString(), m_locker.isLocked( it->first )); + } else if ( ! sysup ) { + cout << it->first << " "; + } else { + packagesToUpdate.push_back( it->first ); + } } } else if (result == UNDEFINED) { m_undefinedVersionComp.push_back(make_pair(p, it->second)); @@ -982,7 +833,9 @@ void PrtGet::printDiff() } } - if (m_undefinedVersionComp.size()) { + if (simpleListing) { cout << endl; } + + if ((m_undefinedVersionComp.size()) and (! simpleListing) and (! sysup)) { cout << "\n\n" << "Undecidable version differences (use --strict-diff)" << endl << endl; printFormattedDiffLine("Port", @@ -1003,15 +856,47 @@ void PrtGet::printDiff() } } - if ( count == 0 ) { - cout << "No differences found" << endl; + if ( (! simpleListing) and (! sysup) ) { + cout << "No differences found" << endl; + } else if ( sysup ) { + cout << "System is up to date" << endl; + } else { + cout << endl; + } + } + + // don't proceed to update the ports unless sysup was requested + if (! sysup) { return; } + + if ( m_parser->depSort() ) { // sort by dependencies + InstallTransaction depTrans( packagesToUpdate, + m_repo, m_pkgDB, m_config ); + if (depTrans.calcDependencies()) { + list target; + const list& deps = depTrans.dependencies(); + list::const_iterator it = deps.begin(); + for (; it != deps.end(); ++it) { + if ( find( packagesToUpdate.begin(), + packagesToUpdate.end(), *it ) != packagesToUpdate.end() + || ! m_pkgDB->isInstalled( *it , true ) ) { + target.push_back( *it ); + } + } + InstallTransaction transaction( target, m_repo, m_pkgDB, m_config ); + executeTransaction( transaction ); + } else { // something went wrong in the dependency resolver + return; + } + } else { // process the list of targets as-is + InstallTransaction transaction( packagesToUpdate, + m_repo, m_pkgDB, m_config ); + executeTransaction( transaction ); } } /*! print path to a port */ -void PrtGet::printPath() -{ +void PrtGet::printPath() { assertExactArgCount(1); initRepo(); @@ -1026,21 +911,11 @@ void PrtGet::printPath() } } - /*! helper method to print the result of an InstallTransaction */ void PrtGet::evaluateResult( InstallTransaction& transaction, - bool update, - bool interrupted ) -{ + bool interrupted ) { int errors = 0; - // TODO: this is a duplicate, it's in install() as well - string command[] = { "install", "installed" }; - if ( update ) { - command[0] = "update"; - command[1] = "updated"; - } - const list& ignored = transaction.ignoredPackages(); if ( ignored.size() ) { cout << endl << "-- Packages ignored" << endl; @@ -1070,8 +945,7 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, transaction.installError(); if ( error.size() ) { ++errors; - cout << endl << "-- Packages where " - << command[0] << " failed" << endl; + cout << endl << "-- Packages where pkgmk/pkgadd failed" << endl; list< pair >::const_iterator eit = error.begin(); @@ -1083,7 +957,7 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, } const list& already = transaction.alreadyInstalledPackages(); - if ( already.size() ) { + if ( already.size() && ! m_parser->depSort() ) { cout << endl << "-- Packages installed before this run (ignored)" << endl; list::const_iterator ait = already.begin(); @@ -1102,11 +976,10 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, } } - const list< pair >& inst = transaction.installedPackages(); if ( inst.size() ) { - cout << endl << "-- Packages " << command[1] << endl; + cout << endl << "-- Successful packages "<< endl; list< pair >::const_iterator iit = inst.begin(); @@ -1133,12 +1006,11 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, cout << endl; } - // readme's if ( atLeastOnePackageHasReadme ) { if ( m_config->readmeMode() == Configuration::VERBOSE_README ) { - cout << endl << "-- " << command[1] - << " packages with README files:" << endl; + cout << endl << "-- " + << " Successful packages with README files:" << endl; iit = inst.begin(); for ( ; iit != inst.end(); ++iit ) { if ( iit->second.hasReadme ) { @@ -1169,7 +1041,7 @@ void PrtGet::evaluateResult( InstallTransaction& transaction, cout << endl; if ( errors == 0 && !interrupted ) { - cout << "prt-get: " << command[1] << " successfully" << endl; + cout << "prt-get: install successful." << endl; } else { m_returnValue = PG_PARTIAL_INSTALL_ERROR; } @@ -1190,12 +1062,10 @@ void PrtGet::reportPrePost(const InstallTransaction::InstallInfo& info) { } cout << " [post: " << postString << "]"; } - } /*! create a cache */ -void PrtGet::createCache() -{ +void PrtGet::createCache() { if ( m_parser->wasCalledAsPrtCached() ) { cerr << m_appName << ": Can't create cache from cache. " << "Use prt-get instead" << endl; @@ -1220,18 +1090,13 @@ void PrtGet::createCache() m_returnValue = PG_GENERAL_ERROR; return; } - } /*! \return true if v1 is greater than v2 */ -COMP_RESULT PrtGet::compareVersions( const string& v1, const string& v2 ) -{ - if (v1 == v2) { - return EQUAL; - } - +COMP_RESULT PrtGet::compareVersions( const string& v1, const string& v2 ) { + if (v1 == v2) { return EQUAL; } if (m_parser->preferHigher() || (m_config->preferHigher() && !m_parser->strictDiff())) { @@ -1240,20 +1105,18 @@ COMP_RESULT PrtGet::compareVersions( const string& v1, const string& v2 ) return result; } - if (v1 != v2) - return GREATER; + if (v1 != v2) { return GREATER; } + return LESS; } -int PrtGet::returnValue() const -{ +int PrtGet::returnValue() const { return m_returnValue; } /*! print a list of packages available in the repository */ -void PrtGet::printf() -{ +void PrtGet::printf() { map sortedOutput; assertExactArgCount(1); @@ -1305,11 +1168,8 @@ void PrtGet::printf() if ( m_pkgDB->isInstalled( p->name() ) ) { string ip = p->name() + "-" + m_pkgDB->getPackageVersion( p->name() ); - if ( ip == p->name() + "-" + p->versionReleaseString() ) { - isInst = "yes"; - } else { - isInst = "diff"; - } + isInst = ( ip == p->name() + "-" + p->versionReleaseString() ) ? + "yes" : "diff"; } StringHelper::replaceAll( output, "%i", isInst ); StringHelper::replaceAll( sortkey, "%i", isInst ); @@ -1341,8 +1201,7 @@ void PrtGet::printf() } } -void PrtGet::readme() -{ +void PrtGet::readme() { assertExactArgCount(1); initRepo(); @@ -1358,8 +1217,7 @@ void PrtGet::readme() } } -bool PrtGet::printFile(const string& file) -{ +bool PrtGet::printFile(const string& file) { if (!File::fileExists(file)) { return false; } @@ -1382,113 +1240,7 @@ bool PrtGet::printFile(const string& file) return true; } -void PrtGet::printDependent() -{ - assertExactArgCount(1); - - initRepo(); - string arg = *(m_parser->otherArgs().begin()); - vector treeWalk; - - 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(); - static map 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 dependent; - for ( ; it != m_repo->packages().end(); ++it ) { - - // TODO: is the following line needed? - const Package* p = it->second; - if ( p && p->dependencies().find( dep ) != string::npos ) { - list tokens; - StringHelper::split( p->dependencies(), ',', tokens ); - list::iterator it = find( tokens.begin(), - tokens.end(), - dep ); - if ( it != tokens.end() ) { - dependent.insert( p ); - } - } - if ( p && m_pkgDB->isInstalled(p->name(),false) && m_followSoftdeps - && p->optionals().find( dep ) != string::npos ) { - list tokens; - StringHelper::split( p->optionals(), ',', tokens ); - list::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 - // tree mode, packages are shown multiple times, in non tree - // recursive mode they're only printed the first time; this is not - // necessarily optimal for rebuilding: - // - // a -> b -> d - // \ ^ - // > c / - // - // trying to rebuild 'd' before 'c' might possibly fail - string indent = ""; - if (m_parser->printTree()) { - for (int i = 0; i < level; ++i) { - indent += " "; - } - } - 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->versionReleaseString(); - } - if ( m_parser->verbose() > 1 ) { - cout << ": " << p->description(); - } - - cout << endl; - - if (m_parser->recursive()) { - printDependent( p->name(), level+2 ); - } - } - } - - treeWalk.pop_back(); -} - -void PrtGet::listOrphans() -{ +void PrtGet::listOrphans() { initRepo(); map installed = m_pkgDB->installedPackages(); map required; @@ -1537,90 +1289,14 @@ void PrtGet::listOrphans() } } - -void PrtGet::warnPackageNotFound(InstallTransaction& transaction) -{ +void PrtGet::warnPackageNotFound(InstallTransaction& transaction) { cerr << "The package '"; cerr << transaction.missing().begin()->first; cerr << "' could not be found: " << endl; } -void PrtGet::sysup() -{ - // TODO: refactor getDifferentPackages from diff/quickdiff - initRepo(); - - list* target; - list packagesToUpdate; - list sortedList; - - 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 ) { - 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)); - } - } - } - } - - if ( packagesToUpdate.empty() ) { - cout << "System is up to date" << endl; - return; - } - - if ( m_parser->nodeps() ) { - target = &packagesToUpdate; - } else { - // sort by dependency - - // TODO: refactor code from printDepends - InstallTransaction depTrans( packagesToUpdate, - m_repo, m_pkgDB, m_config ); - InstallTransaction::InstallResult result = depTrans.calcDependencies(); - if ( result == InstallTransaction::CYCLIC_DEPEND ) { - cerr << "cyclic dependencies" << endl; - m_returnValue = PG_GENERAL_ERROR; - return; - } else if ( result == InstallTransaction::PACKAGE_NOT_FOUND ) { - warnPackageNotFound(depTrans); - m_returnValue = PG_GENERAL_ERROR; - return; - } - - const list& deps = depTrans.dependencies(); - if ( deps.size() > 0 ) { - list::const_iterator it = deps.begin(); - for ( ; it != deps.end(); ++it ) { - if ( find( packagesToUpdate.begin(), - packagesToUpdate.end(), *it ) != - packagesToUpdate.end() ) {; - sortedList.push_back( *it ); - } - } - } - - target = &sortedList; - } - - InstallTransaction transaction( *target, - m_repo, m_pkgDB, m_config ); - executeTransaction( transaction, true ); -} - - void PrtGet::expandWildcardsPkgDB( const list& in, - map& target ) -{ + map& target ) { list::const_iterator it = in.begin(); for ( ; it != in.end(); ++it ) { map l; @@ -1632,8 +1308,7 @@ void PrtGet::expandWildcardsPkgDB( const list& in, } } -void PrtGet::expandWildcardsRepo( const list& in, list& target ) -{ +void PrtGet::expandWildcardsRepo( const list& in, list& target ) { list::const_iterator it = in.begin(); for ( ; it != in.end(); ++it ) { @@ -1647,23 +1322,25 @@ void PrtGet::expandWildcardsRepo( const list& in, list& target ) } -void PrtGet::current() -{ - assertExactArgCount(1); +void PrtGet::current() { + map installed = m_pkgDB->installedPackages(); + list::const_iterator it = m_parser->otherArgs().begin(); + m_returnValue = 0; - const map& installed = m_pkgDB->installedPackages(); - map::const_iterator it = installed.begin(); - string search = *(m_parser->otherArgs().begin()); - - for ( ; it != installed.end(); ++it ) { - if ( it->first == search ) { - cout << it->second.c_str() << endl; - return; - } + for ( ; it != m_parser->otherArgs().end(); ++it ) { + if (m_pkgDB->isInstalled( *it , false )) { + map::const_iterator ii = installed.begin(); + for ( ; ii != installed.end(); ++ii ) { + if ( *it == ii->first ) { + cout << *it << ": version " << ii->second << endl; + break; + } + } + } else { + cout << "Package " << *it << " not installed" << endl; + m_returnValue += 1; + } } - - cout << "Package " << search << " not installed" << endl; - m_returnValue = 1; } SignalHandler::HandlerResult PrtGet::handleSignal( int signal ) @@ -1673,7 +1350,7 @@ SignalHandler::HandlerResult PrtGet::handleSignal( int signal ) cout << "prt-get: interrupted" << endl; if ( m_currentTransaction ) { - evaluateResult( *m_currentTransaction, false, true ); + evaluateResult( *m_currentTransaction, false ); } return EXIT; @@ -1684,8 +1361,7 @@ SignalHandler::HandlerResult PrtGet::handleSignal( int signal ) \sa Repository::getMatchingPackages() */ -void PrtGet::fsearch() -{ +void PrtGet::fsearch() { assertMinArgCount(1); string arg = "*"; @@ -1722,21 +1398,16 @@ void PrtGet::fsearch() } } - if ( first ) { - m_returnValue = PG_GENERAL_ERROR; - } + if ( first ) { m_returnValue = PG_GENERAL_ERROR; } } -void PrtGet::setLock( bool lock ) -{ +void PrtGet::setLock( bool lock ) { assertMinArgCount(1); - if ( lock ) { - initRepo(); - } + if ( lock ) { initRepo(); } - const list& args = m_parser->otherArgs(); - list::const_iterator it = args.begin(); + const list& args = m_parser->otherArgs(); + list::const_iterator it = args.begin(); for ( ; it != args.end(); ++it ) { if ( lock ) { if (m_pkgDB->isInstalled( *it )) { @@ -1765,8 +1436,7 @@ void PrtGet::setLock( bool lock ) } } -void PrtGet::listLocked() -{ +void PrtGet::listLocked() { // shares some code with listInstalled if ( m_locker.openFailed() ) { cerr << "Failed to open lock data file" << endl; @@ -1805,8 +1475,7 @@ void PrtGet::listLocked() } -void PrtGet::edit() -{ +void PrtGet::edit() { assertMinArgCount(1); assertMaxArgCount(2); @@ -1814,7 +1483,7 @@ void PrtGet::edit() if (editor) { initRepo(); - list::const_iterator it = m_parser->otherArgs().begin(); + list::const_iterator it = m_parser->otherArgs().begin(); string arg = *it; const Package* p = m_repo->getPackage( arg ); if ( p ) { @@ -1842,13 +1511,12 @@ void PrtGet::edit() } -void PrtGet::ls() -{ +void PrtGet::ls() { assertExactArgCount(1); initRepo(); - list::const_iterator it = m_parser->otherArgs().begin(); + list::const_iterator it = m_parser->otherArgs().begin(); string arg = *it; const Package* p = m_repo->getPackage( arg ); if ( p ) { @@ -1884,14 +1552,13 @@ void PrtGet::ls() } } -void PrtGet::cat() -{ +void PrtGet::cat() { assertMinArgCount(1); assertMaxArgCount(2); initRepo(); - list::const_iterator it = m_parser->otherArgs().begin(); + list::const_iterator it = m_parser->otherArgs().begin(); string arg = *it; const Package* p = m_repo->getPackage( arg ); if ( p ) { @@ -1912,8 +1579,7 @@ void PrtGet::cat() } } -void PrtGet::remove() -{ +void PrtGet::remove() { assertMinArgCount(1); list removed; @@ -1929,8 +1595,8 @@ void PrtGet::remove() command = m_config->removeCommand(); } - const list& args = m_parser->otherArgs(); - list::const_iterator it = args.begin(); + const list& args = m_parser->otherArgs(); + list::const_iterator it = args.begin(); for ( ; it != args.end(); ++it ) { if (m_pkgDB->isInstalled(*it)) { // TODO: prettify @@ -1988,150 +1654,187 @@ void PrtGet::remove() if ( m_parser->isTest() ) { cout << "*** " << m_appName << ": test mode end" << endl; } - - - } -void PrtGet::assertMaxArgCount(size_t count) -{ +void PrtGet::assertMaxArgCount(size_t count) { if ( m_parser->otherArgs().size() > count ) { argCountFailure(count, "at most"); } } -void PrtGet::assertExactArgCount(size_t count) -{ +void PrtGet::assertExactArgCount(size_t count) { if ( m_parser->otherArgs().size() != count ) { argCountFailure(count, "exactly"); } } -void PrtGet::assertMinArgCount(size_t count) -{ +void PrtGet::assertMinArgCount(size_t count) { if ( m_parser->otherArgs().size() < count ) { argCountFailure(count, "at least"); } } -void PrtGet::argCountFailure(size_t count, const string& specifier) -{ +void PrtGet::argCountFailure(size_t count, const string& specifier) { cerr << m_appName << " " << m_parser->commandName() << " takes " << specifier << " " << count << (count > 1 ? " arguments" : " argument") << endl; exit(PG_ARG_ERROR); } - -void PrtGet::printDependTree() -{ +/* print a nicely-formatted dependency graph */ +void PrtGet::printDepTree() { + bool reverse = m_parser->revdep(); + string depTreeHeader; assertExactArgCount(1); initRepo(); - list::const_iterator it = m_parser->otherArgs().begin(); - string arg = *it; - const Package* p = m_repo->getPackage( arg ); + list::const_iterator it = m_parser->otherArgs().begin(); + const Package* p = m_repo->getPackage( *it ); if (!p) { - cerr << "Package '" << arg << "' not found" << endl; + cerr << "Package '" << *it << "' not found" << endl; m_returnValue = PG_GENERAL_ERROR; return; - } - - if ( (p->dependencies().length() > 0) or - (m_followSoftdeps && p->optionals().length() > 0) ) { - cout << "-- dependencies ([i] installed"; - if ( m_followSoftdeps ) { - cout << ", [s] installed softdeps"; - } else { - cout << ", [ ] not installed"; - } - if (!m_parser->all()) { - cout << ", '-->' already shown"; - } - cout << ")" << endl; - printDepsLevel(2, p, false); + } else if (reverse) { + depTreeHeader = "Packages that need " + p->name(); } + + if ( !m_followSoftdeps ) { + depTreeHeader += " ([i] installed, [ ] not installed"; + } else if ( !reverse ) { + depTreeHeader += " ([i] installed dep, [s] installed softdep"; + } else { + depTreeHeader += " ([i] firmly dependent, [s] eagerly linked"; + } + + depTreeHeader += (m_parser->all()) ? ")" : ", '-->' already shown)"; + + if ( m_parser->printTree() || m_parser->all() ) { + cout << depTreeHeader << endl; + } + printDepsLevel(0, p, false); } -void PrtGet::printDepsLevel(int indent, const Package* package, bool greedy) -{ +void PrtGet::printDepsLevel(int level, const Package* package, + bool greedy) { static map shownMap; - string installStatus; bool isAlias = false; string aliasName = ""; + bool reverse = m_parser->revdep(); + bool indented = m_parser->printTree(); /* cycle detection -- code duplicated from checkDependencies */ for (unsigned int i=0; iname()) { + if (greedy) { return; + } else { cout << "Dependency cycle detected! "; + for (unsigned int j=i; j "; + } + cout << package->name() << endl; return; + } } } treeWalk.push_back(package->name()); - if ( m_pkgDB->isInstalled( package->name(), true, &isAlias, &aliasName ) ) { - installStatus = ( greedy ) ? "[s] " : "[i] "; - cout << installStatus; + string installStatus; string thisLine; + if ( greedy && m_pkgDB->isInstalled( package->name(), false) ) { + installStatus = "[s] "; + } else if ( (! reverse) && m_pkgDB->isInstalled( package->name(), true, + &isAlias, &aliasName ) ) { + installStatus = "[i] "; + } else if ( (reverse) && m_pkgDB->isInstalled( package->name(), false) ) { + installStatus = "[i] "; } else { - cout << "[ ] "; + installStatus = "[ ] "; } - for (int i = 0; i < indent; ++i) { - cout << " "; + + if ( m_parser->all() || ( indented && !reverse ) ) { + thisLine = installStatus; } - cout << package->name(); + + if (indented) { + for (int i = 0; i < level; ++i) { + thisLine += " "; + } + } + + thisLine += package->name(); if (isAlias) { - cout << " (provided by " << aliasName << ")"; + thisLine += " (provided by " + aliasName + ")"; } - map::iterator shownIt = shownMap.find(package->name()); - if (shownIt != shownMap.end()) { - cout << " -->" << endl; + if ( m_parser->verbose() > 0 ) { + thisLine += " " + package->versionReleaseString(); + } + if ( m_parser->verbose() > 1 ) { + thisLine += ": " + package->description(); + } + if ( shownMap[package->name()] && !m_parser->all() ) { + thisLine += " -->"; + if (indented) { cout << thisLine << endl; } treeWalk.pop_back(); return; } else { - cout << endl; + if ( (level > 0) || !reverse ) { cout << thisLine << endl; } + if (!m_parser->all()) { + shownMap[package->name()] = true; + } } - list deps; - StringHelper::split(package->dependencies(), ',', deps); - list::iterator it = deps.begin(); - - for (; it != deps.end(); ++it) { - const Package* p = m_repo->getPackage( *it ); - if (p) { - printDepsLevel(indent+2, p, greedy); - if (!m_parser->all()) { - shownMap[*it] = true; - } - } else { - cout << " (not found in ports tree)" << endl; + if ( ! reverse ) { + list curdeps; + StringHelper::split(package->dependencies(), ',', curdeps); + list::iterator it = curdeps.begin(); + for (; it != curdeps.end(); ++it) { + const Package* p = m_repo->getPackage( *it ); + if (p) { + printDepsLevel(level+2, p, greedy); + } } - } - - if ( m_followSoftdeps ) { - list softDeps; - StringHelper::split(package->optionals(), ',', softDeps); - list::iterator it = softDeps.begin(); - for (; it != softDeps.end(); ++it) { + if ( m_followSoftdeps ) { + list optionals; + StringHelper::split(package->optionals(), ',', optionals); + list::iterator it = optionals.begin(); + for (; it != optionals.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; + printDepsLevel(level+2,p,true); } } } + } + } else { + list dependent; + list eagerlyLinked; + m_repo->getDependentPackages(package->name(), dependent, false); + if ( m_followSoftdeps ) { + m_repo->getDependentPackages(package->name(), eagerlyLinked, true); + } + if ( level==0 || m_parser->recursive() ) { + list::iterator it = dependent.begin(); + for (; it != dependent.end(); ++it) { + if ( m_parser->all() + || m_pkgDB->isInstalled((*it)->name(), false) ) { + printDepsLevel( level+2, *it, greedy ); + } + } + list::iterator il = eagerlyLinked.begin(); + for (; il != eagerlyLinked.end(); ++il) { + if ( m_parser->all() + || m_pkgDB->isInstalled((*il)->name(), false) ) { + printDepsLevel( level+2, *il, true ); + } + } + } } // reset the tree traversal history treeWalk.pop_back(); } -void PrtGet::dumpConfig() -{ +void PrtGet::dumpConfig() { cout.setf( ios::left, ios::adjustfield ); cout.width( 20 ); @@ -2207,9 +1910,7 @@ void PrtGet::dumpConfig() cout << "off"; break; } - cout << endl; - - cout << endl; + cout << "\n" << endl; if (m_config->logFilePattern() != "") { cout.setf( ios::left, ios::adjustfield ); @@ -2243,7 +1944,6 @@ void PrtGet::dumpConfig() cout << " Compression mode: " << InstallTransaction::getPkgmkCompressionMode() << endl; - cout << endl; list< pair >::const_iterator it = m_config->rootList().begin(); diff --git a/src/prtget.h b/src/prtget.h index 1bba138..48f69b6 100644 --- a/src/prtget.h +++ b/src/prtget.h @@ -55,22 +55,25 @@ public: void listPackages(); void listShadowed(); void listInstalled(); + void listOrphans(); + void listLocked(); + void setLock( bool lock ); void searchPackages( bool searchDesc=false ); + void fsearch(); + void printInfo(); void isInstalled(); + bool isOutdated(); + void current(); void readme(); - void install( bool update=false, - bool dependencies=false ); - void sysup(); - void current(); + void install( bool dependencies=false ); + void remove(); + void printDepends( bool simpleListing=false ); - void printDependTree(); - void printDependent(); - void printDiff(); - void printQuickDiff(); - void listOrphans(); + void printDiff( bool simpleListing=false ); + void printDepTree(); void createCache(); @@ -80,14 +83,6 @@ public: void cat(); void ls(); void edit(); - - void remove(); - - void setLock( bool lock ); - void listLocked(); - - void fsearch(); - void dumpConfig(); int returnValue() const; @@ -96,14 +91,10 @@ public: protected: - void printDepsLevel(int indent, const Package* package, bool greedy); + void printDepsLevel(int level, const Package* package, bool greedy); - void printDependent(const std::string& dep, int level); - - void executeTransaction( InstallTransaction& transaction, - bool update ); - void evaluateResult( InstallTransaction& transaction, - bool update, + void executeTransaction( InstallTransaction& transaction ); + void evaluateResult( InstallTransaction& transaction, bool interrupted=false ); void reportPrePost(const InstallTransaction::InstallInfo& info); @@ -122,7 +113,6 @@ protected: const string& version2, bool locked); - Repository* m_repo; PkgDB* m_pkgDB; Configuration* m_config; diff --git a/src/repository.cpp b/src/repository.cpp index c966003..60b477d 100644 --- a/src/repository.cpp +++ b/src/repository.cpp @@ -86,12 +86,26 @@ const Package* Repository::getPackage( const string& name ) const return it->second; } +/*! + \param name the package name to be matched + \return the version-release in the repository +*/ +std::string Repository::getPackageVersion( const string& name ) const +{ + map::const_iterator it = m_packageMap.find( name ); + if ( it == m_packageMap.end() ) { + return "0"; + } + const Package* p = it->second; + string result = p->version()+"-"+p->release(); + return result; +} /*! - Search packages for a match of \a pattern in name, and description of + Search packages for a match of \a pattern in name, or in description if \a searchDesc is true. - \note Name searches can often done without opening the Pkgfiles, but not - description search. Therefore, the later is much slower + \note Name searches can often be done without opening the Pkgfiles, but not + description search. Therefore, the latter is much slower \param pattern the pattern to be found \param searchDesc whether descriptions should be searched as well @@ -188,11 +202,10 @@ void Repository::initFromFS( const list< pair >& rootList, - // TODO: think about whether it would be faster (more - // efficient) to put all packages into a map, and the iterate - // over the list of allowed packages and copy them - // over. depending in the efficiency of find(), this might be - // faster + // TODO: think about whether it would be faster (more efficient) + // to put all packages into a map, and then iterate + // over the list of allowed packages and copy them over. + // Depending on the efficiency of find(), this might be faster. d = opendir( path.c_str() ); while ( ( de = readdir( d ) ) != NULL ) { name = de->d_name; @@ -390,6 +403,37 @@ bool Repository::createOutputDir( const string& path ) return true; } +/* + look for any port mentioning \a pattern as a dependency or soft dependency. + searchOptionals=false (the default) only searches the "Depends on:" line. + The output will need to be trimmed afterward, because in this namespace we + can't check whether the matching ports are installed. +*/ +void Repository::getDependentPackages( const string& pattern, + list& target, + bool searchOptionals ) const { + + map::const_iterator im = m_packageMap.begin(); + for ( ; im != m_packageMap.end(); ++im ) { + Package* q = im->second; string s; + if (searchOptionals) { + s = toLowerCase(q->optionals()); + } else { + s = toLowerCase(q->dependencies()); + } + + if ( s.find( pattern ) != string::npos ) { + list tokens; + split( s, ',', tokens ); + list::iterator ik = find( tokens.begin(), + tokens.end(), pattern ); + if ( ik != tokens.end() ) { + target.push_back( q ); + } + } + } +} + /*! Search packages for a match of \a pattern in name. The name can diff --git a/src/repository.h b/src/repository.h index dbf35a1..f3ea512 100644 --- a/src/repository.h +++ b/src/repository.h @@ -19,6 +19,7 @@ using namespace std; #include "package.h" +#include "stringhelper.h" /*! \class Repository @@ -33,6 +34,7 @@ public: ~Repository(); const Package* getPackage( const string& name ) const; + std::string getPackageVersion( const string& name ) const; const map& packages() const; const list >& shadowedPackages() const; @@ -40,6 +42,10 @@ public: list& target, bool searchDesc ) const; + void getDependentPackages( const string& pattern, + list& target, + bool searchOptionals ) const; + void getMatchingPackages( const string& pattern, list& target ) const; diff --git a/src/stringhelper.cpp b/src/stringhelper.cpp index 2b4f783..1952afa 100644 --- a/src/stringhelper.cpp +++ b/src/stringhelper.cpp @@ -155,5 +155,4 @@ string replaceAll( string& in, return in; } - }; // Namespace