]> git.saurik.com Git - apt.git/blame - cmdline/apt-internal-planner.cc
eipp: let apt make a plan, not make stuff plane
[apt.git] / cmdline / apt-internal-planner.cc
CommitLineData
f74d99c6
DK
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3/* #####################################################################
4
5 cover around the internal solver to be able to run it like an external
6
7 ##################################################################### */
8 /*}}}*/
9// Include Files /*{{{*/
10#include <config.h>
11
12#include <apt-pkg/error.h>
13#include <apt-pkg/cmndline.h>
14#include <apt-pkg/init.h>
15#include <apt-pkg/cachefile.h>
16#include <apt-pkg/cacheset.h>
17#include <apt-pkg/strutl.h>
18#include <apt-pkg/edsp.h>
19#include <apt-pkg/fileutl.h>
20#include <apt-pkg/pkgsystem.h>
21#include <apt-pkg/configuration.h>
22#include <apt-pkg/packagemanager.h>
23#include <apt-pkg/prettyprinters.h>
24#include <apt-pkg/depcache.h>
25#include <apt-pkg/pkgcache.h>
26#include <apt-pkg/cacheiterators.h>
27
28#include <apt-private/private-output.h>
29#include <apt-private/private-cmndline.h>
30#include <apt-private/private-main.h>
31
32#include <string.h>
33#include <iostream>
34#include <sstream>
35#include <list>
36#include <string>
37#include <unistd.h>
38#include <cstdio>
39#include <stdlib.h>
40
41#include <apti18n.h>
42 /*}}}*/
43
44static bool ShowHelp(CommandLine &) /*{{{*/
45{
46 std::cout <<
8e99b22c 47 _("Usage: apt-internal-planner\n"
f74d99c6 48 "\n"
8e99b22c
DK
49 "apt-internal-planner is an interface to use the current internal\n"
50 "installation planner for the APT family like an external one,\n"
f74d99c6
DK
51 "for debugging or the like.\n");
52 return true;
53}
54 /*}}}*/
55APT_NORETURN static void DIE(std::string const &message) { /*{{{*/
56 std::cerr << "ERROR: " << message << std::endl;
57 _error->DumpErrors(std::cerr);
58 exit(EXIT_FAILURE);
59}
60 /*}}}*/
61static std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
62{
63 return {};
64}
65 /*}}}*/
66class PMOutput: public pkgPackageManager /*{{{*/
67{
68 FileFd &output;
69 bool const Debug;
70
71protected:
72 virtual bool Install(PkgIterator Pkg,std::string) APT_OVERRIDE
73 {
74 //std::cerr << "INSTALL: " << APT::PrettyPkg(&Cache, Pkg) << std::endl;
262fdd8b 75 return EDSP::WriteSolutionStanza(output, "Unpack", Cache[Pkg].InstVerIter(Cache));
f74d99c6
DK
76 }
77 virtual bool Configure(PkgIterator Pkg) APT_OVERRIDE
78 {
79 //std::cerr << "CONFIGURE: " << APT::PrettyPkg(&Cache, Pkg) << " " << std::endl;
80 return EDSP::WriteSolutionStanza(output, "Configure", Cache[Pkg].InstVerIter(Cache));
81 }
82 virtual bool Remove(PkgIterator Pkg,bool) APT_OVERRIDE
83 {
84 //std::cerr << "REMOVE: " << APT::PrettyPkg(&Cache, Pkg) << " " << std::endl;
85 return EDSP::WriteSolutionStanza(output, "Remove", Pkg.CurrentVer());
86 }
87public:
88 PMOutput(pkgDepCache *Cache, FileFd &file) : pkgPackageManager(Cache), output(file),
89 Debug(_config->FindB("Debug::EDSP::WriteSolution", false))
90 {}
91
92 bool ApplyRequest(std::list<std::pair<std::string,EIPP::PKG_ACTION>> const &actions)
93 {
94 for (auto && a: actions)
95 {
96 auto const Pkg = Cache.FindPkg(a.first);
97 if (unlikely(Pkg.end() == true))
98 continue;
99 switch (a.second)
100 {
101 case EIPP::PKG_ACTION::NOOP:
102 break;
103 case EIPP::PKG_ACTION::INSTALL:
104 case EIPP::PKG_ACTION::REINSTALL:
105 FileNames[Pkg->ID] = "EIPP";
106 break;
107 case EIPP::PKG_ACTION::REMOVE:
108 break;
109 }
110 }
111 return true;
112 }
113};
114 /*}}}*/
115int main(int argc,const char *argv[]) /*{{{*/
116{
117 // we really don't need anything
118 DropPrivileges();
119
120 CommandLine CmdL;
8e99b22c 121 ParseCommandLine(CmdL, APT_CMD::APT_INTERNAL_PLANNER, &_config, NULL, argc, argv, &ShowHelp, &GetCommands);
f74d99c6
DK
122
123 // Deal with stdout not being a tty
124 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
125 _config->Set("quiet","1");
126
127 if (_config->FindI("quiet", 0) < 1)
128 _config->Set("Debug::EIPP::WriteSolution", true);
129
8e99b22c
DK
130 _config->Set("APT::System", "Debian APT planner interface");
131 _config->Set("APT::Planner", "internal");
f74d99c6
DK
132 _config->Set("eipp::scenario", "/nonexistent/stdin");
133 FileFd output;
134 if (output.OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly | FileFd::BufferedWrite, true) == false)
135 DIE("stdout couldn't be opened");
136 int const input = STDIN_FILENO;
137 SetNonBlock(input, false);
138
8e99b22c 139 EDSP::WriteProgress(0, "Start up planner…", output);
f74d99c6
DK
140
141 if (pkgInitSystem(*_config,_system) == false)
142 DIE("System could not be initialized!");
143
144 EDSP::WriteProgress(1, "Read request…", output);
145
146 if (WaitFd(input, false, 5) == false)
8e99b22c 147 DIE("WAIT timed out in the planner");
f74d99c6
DK
148
149 std::list<std::pair<std::string,EIPP::PKG_ACTION>> actions;
150 unsigned int flags;
151 if (EIPP::ReadRequest(input, actions, flags) == false)
152 DIE("Parsing the request failed!");
a21aca10
DK
153 _config->Set("APT::Immediate-Configure", (flags & EIPP::Request::NO_IMMEDIATE_CONFIGURATION) == 0);
154 _config->Set("APT::Immediate-Configure-All", (flags & EIPP::Request::IMMEDIATE_CONFIGURATION_ALL) != 0);
8d1cb6da 155 _config->Set("APT::Force-LoopBreak", (flags & EIPP::Request::ALLOW_TEMPORARY_REMOVE_OF_ESSENTIALS) != 0);
f74d99c6
DK
156
157 EDSP::WriteProgress(5, "Read scenario…", output);
158
159 pkgCacheFile CacheFile;
160 if (CacheFile.Open(NULL, false) == false)
161 DIE("Failed to open CacheFile!");
162
163 EDSP::WriteProgress(50, "Apply request on scenario…", output);
164
165 if (EIPP::ApplyRequest(actions, CacheFile) == false)
166 DIE("Failed to apply request to depcache!");
167
168 EDSP::WriteProgress(60, "Call orderinstall on current scenario…", output);
169
170 //_config->Set("Debug::pkgOrderList", true);
171 //_config->Set("Debug::pkgPackageManager", true);
172 PMOutput PM(CacheFile, output);
173 if (PM.ApplyRequest(actions) == false)
174 DIE("Failed to apply request to packagemanager!");
175 pkgPackageManager::OrderResult const Res = PM.DoInstallPreFork();
91abb30f 176 std::ostringstream broken;
f74d99c6
DK
177 switch (Res)
178 {
179 case pkgPackageManager::Completed:
180 EDSP::WriteProgress(100, "Done", output);
181 break;
182 case pkgPackageManager::Incomplete:
8e99b22c 183 broken << "Planner could only incompletely plan an installation order!" << std::endl;
91abb30f
DK
184 _error->DumpErrors(broken, GlobalError::DEBUG);
185 EDSP::WriteError("pm-incomplete", broken.str(), output);
186 break;
f74d99c6 187 case pkgPackageManager::Failed:
8e99b22c 188 broken << "Planner failed to find an installation order!" << std::endl;
91abb30f
DK
189 _error->DumpErrors(broken, GlobalError::DEBUG);
190 EDSP::WriteError("pm-failed", broken.str(), output);
f74d99c6
DK
191 break;
192 }
193
194 return DispatchCommandLine(CmdL, {});
195}
196 /*}}}*/