| 1 | // -*- mode: cpp; mode: fold -*- |
| 2 | /** Description \file edsp.h {{{ |
| 3 | ###################################################################### |
| 4 | Set of methods to help writing and reading everything needed for EDSP |
| 5 | with the notable exception of reading a scenario for conversion into |
| 6 | a Cache as this is handled by edsp interface for listparser and friends |
| 7 | ##################################################################### */ |
| 8 | /*}}}*/ |
| 9 | #ifndef PKGLIB_EDSP_H |
| 10 | #define PKGLIB_EDSP_H |
| 11 | |
| 12 | #include <apt-pkg/cacheset.h> |
| 13 | #include <apt-pkg/pkgcache.h> |
| 14 | #include <apt-pkg/cacheiterators.h> |
| 15 | #include <apt-pkg/macros.h> |
| 16 | |
| 17 | #include <stdio.h> |
| 18 | |
| 19 | #include <list> |
| 20 | #include <string> |
| 21 | #include <vector> |
| 22 | |
| 23 | #ifndef APT_8_CLEANER_HEADERS |
| 24 | #include <apt-pkg/depcache.h> |
| 25 | #include <apt-pkg/progress.h> |
| 26 | #endif |
| 27 | |
| 28 | class pkgDepCache; |
| 29 | class OpProgress; |
| 30 | |
| 31 | namespace EDSP /*{{{*/ |
| 32 | { |
| 33 | namespace Request |
| 34 | { |
| 35 | enum Flags |
| 36 | { |
| 37 | AUTOREMOVE = (1 << 0), /*!< removal of unneeded packages should be performed */ |
| 38 | UPGRADE_ALL = (1 << 1), /*!< upgrade all installed packages, like 'apt-get full-upgrade' without forbid flags */ |
| 39 | FORBID_NEW_INSTALL = (1 << 2), /*!< forbid the resolver to install new packages */ |
| 40 | FORBID_REMOVE = (1 << 3), /*!< forbid the resolver to remove packages */ |
| 41 | }; |
| 42 | } |
| 43 | /** \brief creates the EDSP request stanza |
| 44 | * |
| 45 | * In the EDSP protocol the first thing send to the resolver is a stanza |
| 46 | * encoding the request. This method will write this stanza by looking at |
| 47 | * the given Cache and requests the installation of all packages which were |
| 48 | * marked for installation in it (equally for remove). |
| 49 | * |
| 50 | * \param Cache in which the request is encoded |
| 51 | * \param output is written to this "file" |
| 52 | * \param flags effecting the request documented in #EDSP::Request::Flags |
| 53 | * \param Progress is an instance to report progress to |
| 54 | * |
| 55 | * \return true if request was composed successfully, otherwise false |
| 56 | */ |
| 57 | bool WriteRequest(pkgDepCache &Cache, FileFd &output, |
| 58 | unsigned int const flags = 0, |
| 59 | OpProgress *Progress = NULL); |
| 60 | bool WriteRequest(pkgDepCache &Cache, FILE* output, |
| 61 | bool const upgrade = false, |
| 62 | bool const distUpgrade = false, |
| 63 | bool const autoRemove = false, |
| 64 | OpProgress *Progress = NULL) APT_DEPRECATED_MSG("Use FileFd-based interface instead"); |
| 65 | |
| 66 | /** \brief creates the scenario representing the package universe |
| 67 | * |
| 68 | * After the request all known information about a package are send |
| 69 | * to the solver. The output looks similar to a Packages or status file |
| 70 | * |
| 71 | * All packages and version included in this Cache are send, even if |
| 72 | * it doesn't make sense from an APT resolver point of view like versions |
| 73 | * with a negative pin to enable the solver to propose even that as a |
| 74 | * solution or at least to be able to give a hint what can be done to |
| 75 | * statisfy a request. |
| 76 | * |
| 77 | * \param Cache is the known package universe |
| 78 | * \param output is written to this "file" |
| 79 | * \param Progress is an instance to report progress to |
| 80 | * |
| 81 | * \return true if universe was composed successfully, otherwise false |
| 82 | */ |
| 83 | bool WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress *Progress = NULL); |
| 84 | bool WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL) APT_DEPRECATED_MSG("Use FileFd-based interface instead"); |
| 85 | |
| 86 | /** \brief creates a limited scenario representing the package universe |
| 87 | * |
| 88 | * This method works similar to #WriteScenario as it works in the same |
| 89 | * way but doesn't send the complete universe to the solver but only |
| 90 | * packages included in the pkgset which will have only dependencies |
| 91 | * on packages which are in the given set. All other dependencies will |
| 92 | * be removed, so that this method can be used to create testcases |
| 93 | * |
| 94 | * \param Cache is the known package universe |
| 95 | * \param output is written to this "file" |
| 96 | * \param pkgset is a set of packages the universe should be limited to |
| 97 | * \param Progress is an instance to report progress to |
| 98 | * |
| 99 | * \return true if universe was composed successfully, otherwise false |
| 100 | */ |
| 101 | bool WriteLimitedScenario(pkgDepCache &Cache, FileFd &output, |
| 102 | std::vector<bool> const &pkgset, |
| 103 | OpProgress *Progress = NULL); |
| 104 | bool WriteLimitedScenario(pkgDepCache &Cache, FILE* output, |
| 105 | APT::PackageSet const &pkgset, |
| 106 | OpProgress *Progress = NULL) APT_DEPRECATED_MSG("Use FileFd-based interface instead"); |
| 107 | |
| 108 | /** \brief waits and acts on the information returned from the solver |
| 109 | * |
| 110 | * This method takes care of interpreting whatever the solver sends |
| 111 | * through the standard output like a solution, progress or an error. |
| 112 | * The main thread should hand his control over to this method to |
| 113 | * wait for the solver to finish the given task. The file descriptor |
| 114 | * used as input is completely consumed and closed by the method. |
| 115 | * |
| 116 | * \param input file descriptor with the response from the solver |
| 117 | * \param Cache the solution should be applied on if any |
| 118 | * \param Progress is an instance to report progress to |
| 119 | * |
| 120 | * \return true if a solution is found and applied correctly, otherwise false |
| 121 | */ |
| 122 | bool ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL); |
| 123 | |
| 124 | /** \brief search and read the request stanza for action later |
| 125 | * |
| 126 | * This method while ignore the input up to the point it finds the |
| 127 | * Request: line as an indicator for the Request stanza. |
| 128 | * The request is stored in the parameters install and remove then, |
| 129 | * as the cache isn't build yet as the scenario follows the request. |
| 130 | * |
| 131 | * \param input file descriptor with the edsp input for the solver |
| 132 | * \param[out] install is a list which gets populated with requested installs |
| 133 | * \param[out] remove is a list which gets populated with requested removals |
| 134 | * \param[out] upgrade is true if it is a request like apt-get upgrade |
| 135 | * \param[out] distUpgrade is true if it is a request like apt-get dist-upgrade |
| 136 | * \param[out] autoRemove is true if removal of uneeded packages should be performed |
| 137 | * |
| 138 | * \return true if the request could be found and worked on, otherwise false |
| 139 | */ |
| 140 | bool ReadRequest(int const input, std::list<std::string> &install, |
| 141 | std::list<std::string> &remove, unsigned int &flags); |
| 142 | APT_DEPRECATED_MSG("use the flag-based version instead") bool ReadRequest(int const input, std::list<std::string> &install, |
| 143 | std::list<std::string> &remove, bool &upgrade, |
| 144 | bool &distUpgrade, bool &autoRemove); |
| 145 | |
| 146 | /** \brief takes the request lists and applies it on the cache |
| 147 | * |
| 148 | * The lists as created by #ReadRequest will be used to find the |
| 149 | * packages in question and mark them for install/remove. |
| 150 | * No solving is done and no auto-install/-remove. |
| 151 | * |
| 152 | * \param install is a list of packages to mark for installation |
| 153 | * \param remove is a list of packages to mark for removal |
| 154 | * \param Cache is there the markers should be set |
| 155 | * |
| 156 | * \return false if the request couldn't be applied, true otherwise |
| 157 | */ |
| 158 | bool ApplyRequest(std::list<std::string> const &install, |
| 159 | std::list<std::string> const &remove, |
| 160 | pkgDepCache &Cache); |
| 161 | |
| 162 | /** \brief formats a solution stanza for the given version |
| 163 | * |
| 164 | * EDSP uses a simple format for reporting solutions: |
| 165 | * A single required field name with an ID as value. |
| 166 | * Additional fields might appear as debug aids. |
| 167 | * |
| 168 | * \param output to write the stanza forming the solution to |
| 169 | * \param Type of the stanza, used as field name |
| 170 | * \param Ver this stanza applies to |
| 171 | * |
| 172 | * \return true if stanza could be written, otherwise false |
| 173 | */ |
| 174 | bool WriteSolutionStanza(FileFd &output, char const * const Type, pkgCache::VerIterator const &Ver); |
| 175 | bool WriteSolution(pkgDepCache &Cache, FILE* output) APT_DEPRECATED_MSG("Use FileFd-based single-stanza interface instead"); |
| 176 | |
| 177 | /** \brief sends a progress report |
| 178 | * |
| 179 | * \param percent of the solving completed |
| 180 | * \param message the solver wants the user to see |
| 181 | * \param output the front-end listens for progress report |
| 182 | */ |
| 183 | bool WriteProgress(unsigned short const percent, const char* const message, FileFd &output); |
| 184 | bool WriteProgress(unsigned short const percent, const char* const message, FILE* output) APT_DEPRECATED_MSG("Use FileFd-based interface instead"); |
| 185 | |
| 186 | /** \brief sends an error report |
| 187 | * |
| 188 | * Solvers are expected to execute successfully even if |
| 189 | * they were unable to calculate a solution for a given task. |
| 190 | * Obviously they can't send a solution through, so this |
| 191 | * methods deals with formatting an error message correctly |
| 192 | * so that the front-ends can receive and display it. |
| 193 | * |
| 194 | * The first line of the message should be a short description |
| 195 | * of the error so it can be used for dialog titles or alike |
| 196 | * |
| 197 | * \param uuid of this error message |
| 198 | * \param message is free form text to describe the error |
| 199 | * \param output the front-end listens for error messages |
| 200 | */ |
| 201 | bool WriteError(char const * const uuid, std::string const &message, FileFd &output); |
| 202 | bool WriteError(char const * const uuid, std::string const &message, FILE* output) APT_DEPRECATED_MSG("Use FileFd-based interface instead"); |
| 203 | |
| 204 | |
| 205 | /** \brief executes the given solver and returns the pipe ends |
| 206 | * |
| 207 | * The given solver is executed if it can be found in one of the |
| 208 | * configured directories and setup for it is performed. |
| 209 | * |
| 210 | * \param solver to execute |
| 211 | * \param[out] solver_in will be the stdin of the solver |
| 212 | * \param[out] solver_out will be the stdout of the solver |
| 213 | * |
| 214 | * \return PID of the started solver or 0 if failure occurred |
| 215 | */ |
| 216 | pid_t ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/); |
| 217 | APT_DEPRECATED_MSG("add a dummy bool parameter to use the overload returning a pid_t") bool ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); |
| 218 | |
| 219 | /** \brief call an external resolver to handle the request |
| 220 | * |
| 221 | * This method wraps all the methods above to call an external solver |
| 222 | * |
| 223 | * \param solver to execute |
| 224 | * \param Cache with the problem and as universe to work in |
| 225 | * \param flags effecting the request documented in #EDSP::Request::Flags |
| 226 | * \param Progress is an instance to report progress to |
| 227 | * |
| 228 | * \return true if the solver has successfully solved the problem, |
| 229 | * otherwise false |
| 230 | */ |
| 231 | bool ResolveExternal(const char* const solver, pkgDepCache &Cache, |
| 232 | unsigned int const flags = 0, |
| 233 | OpProgress *Progress = NULL); |
| 234 | APT_DEPRECATED_MSG("use the flag-based version instead") bool ResolveExternal(const char* const solver, pkgDepCache &Cache, |
| 235 | bool const upgrade, bool const distUpgrade, |
| 236 | bool const autoRemove, OpProgress *Progress = NULL); |
| 237 | } |
| 238 | /*}}}*/ |
| 239 | class pkgPackageManager; |
| 240 | namespace EIPP /*{{{*/ |
| 241 | { |
| 242 | namespace Request |
| 243 | { |
| 244 | enum Flags |
| 245 | { |
| 246 | IMMEDIATE_CONFIGURATION_ALL = (1 << 0), /*!< try to keep the least amount of packages unconfigured as possible at all times */ |
| 247 | NO_IMMEDIATE_CONFIGURATION = (1 << 1), /*!< do not perform immediate configuration at all */ |
| 248 | ALLOW_TEMPORARY_REMOVE_OF_ESSENTIALS = (1 << 2), /*!< just as the name suggests, very special case and dangerous! */ |
| 249 | }; |
| 250 | } |
| 251 | |
| 252 | APT_HIDDEN bool WriteRequest(pkgDepCache &Cache, FileFd &output, |
| 253 | unsigned int const flags, OpProgress * const Progress); |
| 254 | APT_HIDDEN bool WriteScenario(pkgDepCache &Cache, FileFd &output, |
| 255 | OpProgress * const Progress); |
| 256 | |
| 257 | APT_HIDDEN bool OrderInstall(char const * const planner, pkgPackageManager * const PM, |
| 258 | unsigned int const version, OpProgress * const Progress); |
| 259 | APT_HIDDEN bool ReadResponse(int const input, pkgPackageManager * const PM, |
| 260 | OpProgress * const Progress); |
| 261 | |
| 262 | enum class PKG_ACTION |
| 263 | { |
| 264 | NOOP, |
| 265 | INSTALL, |
| 266 | REINSTALL, |
| 267 | REMOVE |
| 268 | }; |
| 269 | bool ReadRequest(int const input, |
| 270 | std::list<std::pair<std::string,PKG_ACTION>> &actions, |
| 271 | unsigned int &flags); |
| 272 | bool ApplyRequest(std::list<std::pair<std::string,PKG_ACTION>> &actions, |
| 273 | pkgDepCache &Cache); |
| 274 | } |
| 275 | /*}}}*/ |
| 276 | #endif |