summaryrefslogtreecommitdiff
path: root/apt-pkg/edsp.h
blob: 2f18d76eb3d802a94613da315260c43d8bbd5197 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
// -*- mode: cpp; mode: fold -*-
/** Description \file edsp.h						{{{
   ######################################################################
   Set of methods to help writing and reading everything needed for EDSP
   with the notable exception of reading a scenario for conversion into
   a Cache as this is handled by edsp interface for listparser and friends
   ##################################################################### */
									/*}}}*/
#ifndef PKGLIB_EDSP_H
#define PKGLIB_EDSP_H

#include <apt-pkg/cacheset.h>
#include <apt-pkg/macros.h>
#include <apt-pkg/pkgcache.h>

#include <stdio.h>

#include <list>
#include <string>
#include <vector>

#ifndef APT_8_CLEANER_HEADERS
#include <apt-pkg/depcache.h>
#include <apt-pkg/progress.h>
#endif

class pkgDepCache;
class OpProgress;

namespace EDSP								/*{{{*/
{
	namespace Request
	{
	   enum Flags
	   {
	      AUTOREMOVE = (1 << 0), /*!< removal of unneeded packages should be performed */
	      UPGRADE_ALL = (1 << 1), /*!< upgrade all installed packages, like 'apt-get full-upgrade' without forbid flags */
	      FORBID_NEW_INSTALL = (1 << 2), /*!< forbid the resolver to install new packages */
	      FORBID_REMOVE = (1 << 3), /*!< forbid the resolver to remove packages */
	   };
	}
	/** \brief creates the EDSP request stanza
	 *
	 *  In the EDSP protocol the first thing send to the resolver is a stanza
	 *  encoding the request. This method will write this stanza by looking at
	 *  the given Cache and requests the installation of all packages which were
	 *  marked for installation in it (equally for remove).
	 *
	 *  \param Cache in which the request is encoded
	 *  \param output is written to this "file"
	 *  \param flags effecting the request documented in #EDSP::Request::Flags
	 *  \param Progress is an instance to report progress to
	 *
	 *  \return true if request was composed successfully, otherwise false
	 */
	bool WriteRequest(pkgDepCache &Cache, FileFd &output,
				 unsigned int const flags = 0,
				OpProgress *Progress = NULL);
	bool WriteRequest(pkgDepCache &Cache, FILE* output,
				 bool const upgrade = false,
				 bool const distUpgrade = false,
				 bool const autoRemove = false,
				OpProgress *Progress = NULL) APT_DEPRECATED_MSG("Use FileFd-based interface instead");

	/** \brief creates the scenario representing the package universe
	 *
	 *  After the request all known information about a package are send
	 *  to the solver. The output looks similar to a Packages or status file
	 *
	 *  All packages and version included in this Cache are send, even if
	 *  it doesn't make sense from an APT resolver point of view like versions
	 *  with a negative pin to enable the solver to propose even that as a
	 *  solution or at least to be able to give a hint what can be done to
	 *  satisfy a request.
	 *
	 *  \param Cache is the known package universe
	 *  \param output is written to this "file"
	 *  \param Progress is an instance to report progress to
	 *
	 *  \return true if universe was composed successfully, otherwise false
	 */
	bool WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress *Progress = NULL);
	bool WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL) APT_DEPRECATED_MSG("Use FileFd-based interface instead");

	/** \brief creates a limited scenario representing the package universe
	 *
	 *  This method works similar to #WriteScenario as it works in the same
	 *  way but doesn't send the complete universe to the solver but only
	 *  packages included in the pkgset which will have only dependencies
	 *  on packages which are in the given set. All other dependencies will
	 *  be removed, so that this method can be used to create testcases
	 *
	 *  \param Cache is the known package universe
	 *  \param output is written to this "file"
	 *  \param pkgset is a set of packages the universe should be limited to
	 *  \param Progress is an instance to report progress to
	 *
	 *  \return true if universe was composed successfully, otherwise false
	 */
	bool WriteLimitedScenario(pkgDepCache &Cache, FileFd &output,
					 std::vector<bool> const &pkgset,
					 OpProgress *Progress = NULL);
	bool WriteLimitedScenario(pkgDepCache &Cache, FILE* output,
					 APT::PackageSet const &pkgset,
					 OpProgress *Progress = NULL) APT_DEPRECATED_MSG("Use FileFd-based interface instead");

	/** \brief waits and acts on the information returned from the solver
	 *
	 *  This method takes care of interpreting whatever the solver sends
	 *  through the standard output like a solution, progress or an error.
	 *  The main thread should hand his control over to this method to
	 *  wait for the solver to finish the given task. The file descriptor
	 *  used as input is completely consumed and closed by the method.
	 *
	 *  \param input file descriptor with the response from the solver
	 *  \param Cache the solution should be applied on if any
	 *  \param Progress is an instance to report progress to
	 *
	 *  \return true if a solution is found and applied correctly, otherwise false
	 */
	bool ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL);

	/** \brief search and read the request stanza for action later
	 *
	 *  This method while ignore the input up to the point it finds the
	 *  Request: line as an indicator for the Request stanza.
	 *  The request is stored in the parameters install and remove then,
	 *  as the cache isn't build yet as the scenario follows the request.
	 *
	 *  \param input file descriptor with the edsp input for the solver
	 *  \param[out] install is a list which gets populated with requested installs
	 *  \param[out] remove is a list which gets populated with requested removals
	 *  \param[out] upgrade is true if it is a request like apt-get upgrade
	 *  \param[out] distUpgrade is true if it is a request like apt-get dist-upgrade
	 *  \param[out] autoRemove is true if removal of unneeded packages should be performed
	 *
	 *  \return true if the request could be found and worked on, otherwise false
	 */
	bool ReadRequest(int const input, std::list<std::string> &install,
			std::list<std::string> &remove, unsigned int &flags);
	APT_DEPRECATED_MSG("use the flag-based version instead") bool ReadRequest(int const input, std::list<std::string> &install,
			std::list<std::string> &remove, bool &upgrade,
			bool &distUpgrade, bool &autoRemove);

	/** \brief takes the request lists and applies it on the cache
	 *
	 *  The lists as created by #ReadRequest will be used to find the
	 *  packages in question and mark them for install/remove.
	 *  No solving is done and no auto-install/-remove.
	 *
	 *  \param install is a list of packages to mark for installation
	 *  \param remove is a list of packages to mark for removal
	 *  \param Cache is there the markers should be set
	 *
	 *  \return false if the request couldn't be applied, true otherwise
	 */
	bool ApplyRequest(std::list<std::string> const &install,
				 std::list<std::string> const &remove,
				 pkgDepCache &Cache);

	/** \brief formats a solution stanza for the given version
	 *
	 *  EDSP uses a simple format for reporting solutions:
	 *  A single required field name with an ID as value.
	 *  Additional fields might appear as debug aids.
	 *
	 *  \param output to write the stanza forming the solution to
	 *  \param Type of the stanza, used as field name
	 *  \param Ver this stanza applies to
	 *
	 *  \return true if stanza could be written, otherwise false
	 */
	bool WriteSolutionStanza(FileFd &output, char const * const Type, pkgCache::VerIterator const &Ver);
	bool WriteSolution(pkgDepCache &Cache, FILE* output) APT_DEPRECATED_MSG("Use FileFd-based single-stanza interface instead");

	/** \brief sends a progress report
	 *
	 *  \param percent of the solving completed
	 *  \param message the solver wants the user to see
	 *  \param output the front-end listens for progress report
	 */
	bool WriteProgress(unsigned short const percent, const char* const message, FileFd &output);
	bool WriteProgress(unsigned short const percent, const char* const message, FILE* output) APT_DEPRECATED_MSG("Use FileFd-based interface instead");

	/** \brief sends an error report
	 *
	 *  Solvers are expected to execute successfully even if
	 *  they were unable to calculate a solution for a given task.
	 *  Obviously they can't send a solution through, so this
	 *  methods deals with formatting an error message correctly
	 *  so that the front-ends can receive and display it.
	 *
	 *  The first line of the message should be a short description
	 *  of the error so it can be used for dialog titles or alike
	 *
	 *  \param uuid of this error message
	 *  \param message is free form text to describe the error
	 *  \param output the front-end listens for error messages
	 */
	bool WriteError(char const * const uuid, std::string const &message, FileFd &output);
	bool WriteError(char const * const uuid, std::string const &message, FILE* output) APT_DEPRECATED_MSG("Use FileFd-based interface instead");


	/** \brief executes the given solver and returns the pipe ends
	 *
	 *  The given solver is executed if it can be found in one of the
	 *  configured directories and setup for it is performed.
	 *
	 *  \param solver to execute
	 *  \param[out] solver_in will be the stdin of the solver
	 *  \param[out] solver_out will be the stdout of the solver
	 *
	 *  \return PID of the started solver or 0 if failure occurred
	 */
	pid_t ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/);
	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);

	/** \brief call an external resolver to handle the request
	 *
	 *  This method wraps all the methods above to call an external solver
	 *
	 *  \param solver to execute
	 *  \param Cache with the problem and as universe to work in
	 *  \param flags effecting the request documented in #EDSP::Request::Flags
	 *  \param Progress is an instance to report progress to
	 *
	 *  \return true if the solver has successfully solved the problem,
	 *  otherwise false
	 */
	bool ResolveExternal(const char* const solver, pkgDepCache &Cache,
				    unsigned int const flags = 0,
				    OpProgress *Progress = NULL);
	APT_DEPRECATED_MSG("use the flag-based version instead") bool ResolveExternal(const char* const solver, pkgDepCache &Cache,
				    bool const upgrade, bool const distUpgrade,
				    bool const autoRemove, OpProgress *Progress = NULL);
}
									/*}}}*/
class pkgPackageManager;
namespace EIPP								/*{{{*/
{
   namespace Request
   {
      enum Flags
      {
	 IMMEDIATE_CONFIGURATION_ALL = (1 << 0), /*!< try to keep the least amount of packages unconfigured as possible at all times */
	 NO_IMMEDIATE_CONFIGURATION = (1 << 1), /*!< do not perform immediate configuration at all */
	 ALLOW_TEMPORARY_REMOVE_OF_ESSENTIALS = (1 << 2), /*!< just as the name suggests, very special case and dangerous! */
      };
   }

   APT_HIDDEN bool WriteRequest(pkgDepCache &Cache, FileFd &output,
	 unsigned int const flags, OpProgress * const Progress);
   APT_HIDDEN bool WriteScenario(pkgDepCache &Cache, FileFd &output,
	 OpProgress * const Progress);

   APT_HIDDEN bool OrderInstall(char const * const planner, pkgPackageManager * const PM,
	 unsigned int const version, OpProgress * const Progress);
   APT_HIDDEN bool ReadResponse(int const input, pkgPackageManager * const PM,
	 OpProgress * const Progress);

   enum class PKG_ACTION
   {
      NOOP,
      INSTALL,
      REINSTALL,
      REMOVE
   };
   bool ReadRequest(int const input,
	 std::list<std::pair<std::string,PKG_ACTION>> &actions,
	 unsigned int &flags);
   bool ApplyRequest(std::list<std::pair<std::string,PKG_ACTION>> &actions,
	 pkgDepCache &Cache);
}
									/*}}}*/
#endif