]>
git.saurik.com Git - apt.git/blob - apt-pkg/edsp.cc
55bc0a0d9202584ee7025f60638632c9d904c9ac
1 // -*- mode: cpp; mode: fold -*-
3 /* ######################################################################
4 Set of methods to help writing and reading everything needed for EDSP
5 ##################################################################### */
7 // Include Files /*{{{*/
8 #include <apt-pkg/edsp.h>
9 #include <apt-pkg/error.h>
10 #include <apt-pkg/configuration.h>
11 #include <apt-pkg/version.h>
12 #include <apt-pkg/policy.h>
13 #include <apt-pkg/tagfile.h>
21 // EDSP::WriteScenario - to the given file descriptor /*{{{*/
22 bool EDSP::WriteScenario(pkgDepCache
&Cache
, FILE* output
)
24 // we could use pkgCache::DepType and ::Priority, but these would be lokalized strings…
25 const char * const PrioMap
[] = {0, "important", "required", "standard",
27 const char * const DepMap
[] = {"", "Depends", "PreDepends", "Suggests",
28 "Recommends" , "Conflicts", "Replaces",
29 "Obsoletes", "Breaks", "Enhances"};
31 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
)
33 for (pkgCache::VerIterator Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
)
35 fprintf(output
, "Package: %s\n", Pkg
.Name());
36 fprintf(output
, "Architecture: %s\n", Ver
.Arch());
37 fprintf(output
, "Version: %s\n", Ver
.VerStr());
38 if (Pkg
.CurrentVer() == Ver
)
39 fprintf(output
, "Installed: yes\n");
40 if (Pkg
->SelectedState
== pkgCache::State::Hold
)
41 fprintf(output
, "Hold: yes\n");
42 fprintf(output
, "APT-ID: %d\n", Ver
->ID
);
43 fprintf(output
, "Priority: %s\n", PrioMap
[Ver
->Priority
]);
44 if ((Pkg
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
45 fprintf(output
, "Essential: yes\n");
46 fprintf(output
, "Section: %s\n", Ver
.Section());
47 if (Ver
->MultiArch
== pkgCache::Version::Allowed
|| Ver
->MultiArch
== pkgCache::Version::AllAllowed
)
48 fprintf(output
, "Multi-Arch: allowed\n");
49 else if (Ver
->MultiArch
== pkgCache::Version::Foreign
|| Ver
->MultiArch
== pkgCache::Version::AllForeign
)
50 fprintf(output
, "Multi-Arch: foreign\n");
51 else if (Ver
->MultiArch
== pkgCache::Version::Same
)
52 fprintf(output
, "Multi-Arch: same\n");
53 signed short Pin
= std::numeric_limits
<signed short>::min();
54 for (pkgCache::VerFileIterator File
= Ver
.FileList(); File
.end() == false; ++File
) {
55 signed short const p
= Cache
.GetPolicy().GetPriority(File
.File());
59 fprintf(output
, "APT-Pin: %d\n", Pin
);
60 if (Cache
.GetCandidateVer(Pkg
) == Ver
)
61 fprintf(output
, "APT-Candidate: yes\n");
62 if ((Cache
[Pkg
].Flags
& pkgCache::Flag::Auto
) == pkgCache::Flag::Auto
)
63 fprintf(output
, "APT-Automatic: yes\n");
64 std::string dependencies
[pkgCache::Dep::Enhances
+ 1];
66 for (pkgCache::DepIterator Dep
= Ver
.DependsList(); Dep
.end() == false; ++Dep
)
68 // Ignore implicit dependencies for multiarch here
69 if (strcmp(Pkg
.Arch(), Dep
.TargetPkg().Arch()) != 0)
72 dependencies
[Dep
->Type
].append(", ");
73 dependencies
[Dep
->Type
].append(Dep
.TargetPkg().Name());
74 if (Dep
->Version
!= 0)
75 dependencies
[Dep
->Type
].append(" (").append(pkgCache::CompTypeDeb(Dep
->CompareOp
)).append(" ").append(Dep
.TargetVer()).append(")");
76 if ((Dep
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
78 dependencies
[Dep
->Type
].append(" | ");
84 for (int i
= 1; i
< pkgCache::Dep::Enhances
+ 1; ++i
)
85 if (dependencies
[i
].empty() == false)
86 fprintf(output
, "%s: %s\n", DepMap
[i
], dependencies
[i
].c_str()+2);
88 for (pkgCache::PrvIterator Prv
= Ver
.ProvidesList(); Prv
.end() == false; ++Prv
)
90 // Ignore implicit provides for multiarch here
91 if (strcmp(Pkg
.Arch(), Prv
.ParentPkg().Arch()) != 0 || strcmp(Pkg
.Name(),Prv
.Name()) == 0)
93 provides
.append(", ").append(Prv
.Name());
95 if (provides
.empty() == false)
96 fprintf(output
, "Provides: %s\n", provides
.c_str()+2);
99 fprintf(output
, "\n");
105 // EDSP::WriteRequest - to the given file descriptor /*{{{*/
106 bool EDSP::WriteRequest(pkgDepCache
&Cache
, FILE* output
, bool const Upgrade
,
107 bool const DistUpgrade
, bool const AutoRemove
)
110 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
)
113 if (Cache
[Pkg
].Delete() == true)
115 else if (Cache
[Pkg
].NewInstall() == true || Cache
[Pkg
].Upgrade() == true)
119 req
->append(" ").append(Pkg
.FullName());
121 fprintf(output
, "Request: EDSP 0.2\n");
122 if (del
.empty() == false)
123 fprintf(output
, "Remove: %s\n", del
.c_str()+1);
124 if (inst
.empty() == false)
125 fprintf(output
, "Install: %s\n", inst
.c_str()+1);
127 fprintf(output
, "Upgrade: yes\n");
128 if (DistUpgrade
== true)
129 fprintf(output
, "Dist-Upgrade: yes\n");
130 if (AutoRemove
== true)
131 fprintf(output
, "Autoremove: yes\n");
132 if (_config
->FindB("APT::Solver::Strict-Pinning", true) == false)
133 fprintf(output
, "Strict-Pinning: no\n");
134 string
solverpref("APT::Solver::");
135 solverpref
.append(_config
->Find("APT::Solver::Name", "internal")).append("::Preferences");
136 if (_config
->Exists(solverpref
) == true)
137 fprintf(output
, "Preferences: %s\n", _config
->Find(solverpref
,"").c_str());
138 fprintf(output
, "\n");
143 // EDSP::ReadResponse - from the given file descriptor /*{{{*/
144 bool EDSP::ReadResponse(int const input
, pkgDepCache
&Cache
) {
146 in
.OpenDescriptor(input
, FileFd::ReadOnly
);
147 pkgTagFile
response(&in
);
148 pkgTagSection section
;
150 /* We build an map id to mmap offset here
151 In theory we could use the offset as ID, but then VersionCount
152 couldn't be used to create other versionmappings anymore and it
153 would be too easy for a (buggy) solver to segfault APT… */
154 unsigned long long const VersionCount
= Cache
.Head().VersionCount
;
155 unsigned long VerIdx
[VersionCount
];
156 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; ++P
)
157 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
158 VerIdx
[V
->ID
] = V
.Index();
160 while (response
.Step(section
) == true) {
162 if (section
.Exists("Install") == true)
164 else if (section
.Exists("Remove") == true)
166 //FIXME: handle progress
170 size_t const id
= section
.FindULL(type
.c_str(), VersionCount
);
171 if (id
== VersionCount
) {
172 _error
->Warning("Unable to parse %s request with id value '%s'!", type
.c_str(), section
.FindS(type
.c_str()).c_str());
174 } else if (id
> Cache
.Head().VersionCount
) {
175 _error
->Warning("ID value '%s' in %s request stanza is to high to refer to a known version!", section
.FindS(type
.c_str()).c_str(), type
.c_str());
179 pkgCache::VerIterator
Ver(Cache
.GetCache(), Cache
.GetCache().VerP
+ VerIdx
[id
]);
180 Cache
.SetCandidateVersion(Ver
);
181 if (type
== "Install")
182 Cache
.MarkInstall(Ver
.ParentPkg(), false, false);
183 else if (type
== "Remove")
184 Cache
.MarkDelete(Ver
.ParentPkg(), false);
189 // EDSP::ReadLine - first line from the given file descriptor /*{{{*/
190 // ---------------------------------------------------------------------
191 /* Little helper method to read a complete line into a string. Similar to
192 fgets but we need to use the low-level read() here as otherwise the
193 listparser will be confused later on as mixing of fgets and read isn't
194 a supported action according to the manpages and results are undefined */
195 bool EDSP::ReadLine(int const input
, std::string
&line
) {
200 while ((data
= read(input
, &one
, sizeof(one
))) != -1) {
207 if (line
.empty() == true && isblank(one
) != 0)
214 // EDSP::StringToBool - convert yes/no to bool /*{{{*/
215 // ---------------------------------------------------------------------
216 /* we are not as lazy as we are in the global StringToBool as we really
217 only accept yes/no here - but we will ignore leading spaces */
218 bool EDSP::StringToBool(char const *answer
, bool const defValue
) {
219 for (; isspace(*answer
) != 0; ++answer
);
220 if (strncasecmp(answer
, "yes", 3) == 0)
222 else if (strncasecmp(answer
, "no", 2) == 0)
225 _error
->Warning("Value '%s' is not a boolean 'yes' or 'no'!", answer
);
229 // EDSP::ReadRequest - first stanza from the given file descriptor /*{{{*/
230 bool EDSP::ReadRequest(int const input
, std::list
<std::string
> &install
,
231 std::list
<std::string
> &remove
, bool &upgrade
,
232 bool &distUpgrade
, bool &autoRemove
)
240 while (ReadLine(input
, line
) == true)
242 // Skip empty lines before request
243 if (line
.empty() == true)
245 // The first Tag must be a request, so search for it
246 if (line
.compare(0, 8, "Request:") != 0)
249 while (ReadLine(input
, line
) == true)
251 // empty lines are the end of the request
252 if (line
.empty() == true)
255 std::list
<std::string
> *request
= NULL
;
256 if (line
.compare(0, 8, "Install:") == 0)
261 else if (line
.compare(0, 7, "Remove:") == 0)
266 else if (line
.compare(0, 8, "Upgrade:") == 0)
267 upgrade
= EDSP::StringToBool(line
.c_str() + 9, false);
268 else if (line
.compare(0, 13, "Dist-Upgrade:") == 0)
269 distUpgrade
= EDSP::StringToBool(line
.c_str() + 14, false);
270 else if (line
.compare(0, 11, "Autoremove:") == 0)
271 autoRemove
= EDSP::StringToBool(line
.c_str() + 12, false);
273 _error
->Warning("Unknown line in EDSP Request stanza: %s", line
.c_str());
277 size_t end
= line
.length();
279 size_t begin
= line
.rfind(' ');
280 if (begin
== std::string::npos
)
282 request
->push_back(line
.substr(0, end
));
285 else if (begin
< end
)
286 request
->push_back(line
.substr(begin
+ 1, end
));
288 end
= line
.find_last_not_of(' ');
289 } while (end
!= std::string::npos
);
295 // EDSP::ApplyRequest - first stanza from the given file descriptor /*{{{*/
296 bool EDSP::ApplyRequest(std::list
<std::string
> const &install
,
297 std::list
<std::string
> const &remove
,
300 for (std::list
<std::string
>::const_iterator i
= install
.begin();
301 i
!= install
.end(); ++i
)
302 Cache
.MarkInstall(Cache
.FindPkg(*i
), false);
304 for (std::list
<std::string
>::const_iterator i
= remove
.begin();
305 i
!= remove
.end(); ++i
)
306 Cache
.MarkDelete(Cache
.FindPkg(*i
));
310 // EDSP::WriteSolution - to the given file descriptor /*{{{*/
311 bool EDSP::WriteSolution(pkgDepCache
&Cache
, FILE* output
)
313 bool const Debug
= _config
->FindB("Debug::EDSP::WriteSolution", false);
314 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
)
316 if (Cache
[Pkg
].Delete() == true)
317 fprintf(output
, "Remove: %d\n", Cache
.GetCandidateVer(Pkg
)->ID
);
318 else if (Cache
[Pkg
].NewInstall() == true || Cache
[Pkg
].Upgrade() == true)
319 fprintf(output
, "Install: %d\n", Cache
.GetCandidateVer(Pkg
)->ID
);
323 fprintf(output
, "Package: %s\nVersion: %s\n", Pkg
.FullName().c_str(), Cache
.GetCandidateVer(Pkg
).VerStr());
324 fprintf(output
, "\n");
330 bool EDSP::WriteError(std::string
const &message
, FILE* output
) { return false; }