]>
git.saurik.com Git - apt.git/blob - apt-pkg/edsp.cc
1 // -*- mode: cpp; mode: fold -*-
3 /* ######################################################################
4 Set of methods to help writing and reading everything needed for EDSP
5 ##################################################################### */
7 // Include Files /*{{{*/
10 #include <apt-pkg/error.h>
11 #include <apt-pkg/cacheset.h>
12 #include <apt-pkg/depcache.h>
13 #include <apt-pkg/pkgcache.h>
14 #include <apt-pkg/cacheiterators.h>
15 #include <apt-pkg/progress.h>
16 #include <apt-pkg/fileutl.h>
17 #include <apt-pkg/edsp.h>
18 #include <apt-pkg/tagfile.h>
19 #include <apt-pkg/strutl.h>
36 // we could use pkgCache::DepType and ::Priority, but these would be localized stringsā¦
37 constexpr char const * const PrioMap
[] = {
38 nullptr , "important" , "required" , "standard" ,
41 constexpr char const * const DepMap
[] = {
42 nullptr , "Depends" , "Pre-Depends" , "Suggests" ,
43 "Recommends" , "Conflicts" , "Replaces" ,
44 "Obsoletes" , "Breaks" , "Enhances"
47 // WriteOkay - varaidic helper to easily Write to a FileFd /*{{{*/
48 static bool WriteOkay_fn ( FileFd
&) { return true ; }
49 template < typename
... Tail
> static bool WriteOkay_fn ( FileFd
& output
, APT :: StringView data
, Tail
... more_data
)
51 return likely ( output
. Write ( data
. data (), data
. length ()) && WriteOkay_fn ( output
, more_data
...));
53 template < typename
... Tail
> static bool WriteOkay_fn ( FileFd
& output
, unsigned int data
, Tail
... more_data
)
56 strprintf ( number
, " %d " , data
);
57 return likely ( output
. Write ( number
. data (), number
. length ()) && WriteOkay_fn ( output
, more_data
...));
59 template < typename
... Data
> static bool WriteOkay ( bool & Okay
, FileFd
& output
, Data
&&... data
)
61 Okay
= likely ( Okay
&& WriteOkay_fn ( output
, std :: forward
< Data
>( data
)...));
64 template < typename
... Data
> static bool WriteOkay ( FileFd
& output
, Data
&&... data
)
66 bool Okay
= likely ( output
. Failed () == false );
67 return WriteOkay ( Okay
, output
, std :: forward
< Data
>( data
)...);
70 // WriteScenarioVersion /*{{{*/
71 static void WriteScenarioVersion ( pkgDepCache
& Cache
, FILE * output
, pkgCache :: PkgIterator
const & Pkg
,
72 pkgCache :: VerIterator
const & Ver
)
74 fprintf ( output
, "Package: %s \n " , Pkg
. Name ());
75 fprintf ( output
, "Source: %s \n " , Ver
. SourcePkgName ());
76 fprintf ( output
, "Architecture: %s \n " , Ver
. Arch ());
77 fprintf ( output
, "Version: %s \n " , Ver
. VerStr ());
78 fprintf ( output
, "Source-Version: %s \n " , Ver
. SourceVerStr ());
79 if ( Pkg
. CurrentVer () == Ver
)
80 fprintf ( output
, "Installed: yes \n " );
81 if ( Pkg
-> SelectedState
== pkgCache :: State :: Hold
||
82 ( Cache
[ Pkg
]. Keep () == true && Cache
[ Pkg
]. Protect () == true ))
83 fprintf ( output
, "Hold: yes \n " );
84 fprintf ( output
, "APT-ID: %d \n " , Ver
-> ID
);
85 if ( PrioMap
[ Ver
-> Priority
] != nullptr )
86 fprintf ( output
, "Priority: %s \n " , PrioMap
[ Ver
-> Priority
]);
87 if (( Pkg
-> Flags
& pkgCache :: Flag :: Essential
) == pkgCache :: Flag :: Essential
)
88 fprintf ( output
, "Essential: yes \n " );
89 if ( Ver
-> Section
!= 0 )
90 fprintf ( output
, "Section: %s \n " , Ver
. Section ());
91 if (( Ver
-> MultiArch
& pkgCache :: Version :: Allowed
) == pkgCache :: Version :: Allowed
)
92 fprintf ( output
, "Multi-Arch: allowed \n " );
93 else if (( Ver
-> MultiArch
& pkgCache :: Version :: Foreign
) == pkgCache :: Version :: Foreign
)
94 fprintf ( output
, "Multi-Arch: foreign \n " );
95 else if (( Ver
-> MultiArch
& pkgCache :: Version :: Same
) == pkgCache :: Version :: Same
)
96 fprintf ( output
, "Multi-Arch: same \n " );
97 std :: set
< string
> Releases
;
98 for ( pkgCache :: VerFileIterator I
= Ver
. FileList (); I
. end () == false ; ++ I
) {
99 pkgCache :: PkgFileIterator File
= I
. File ();
100 if ( File
. Flagged ( pkgCache :: Flag :: NotSource
) == false ) {
101 string Release
= File
. RelStr ();
102 if (! Release
. empty ())
103 Releases
. insert ( Release
);
106 if (! Releases
. empty ()) {
107 fprintf ( output
, "APT-Release: \n " );
108 for ( std :: set
< string
>:: iterator R
= Releases
. begin (); R
!= Releases
. end (); ++ R
)
109 fprintf ( output
, " %s \n " , R
-> c_str ());
111 fprintf ( output
, "APT-Pin: %d \n " , Cache
. GetPolicy (). GetPriority ( Ver
));
112 if ( Cache
. GetCandidateVersion ( Pkg
) == Ver
)
113 fprintf ( output
, "APT-Candidate: yes \n " );
114 if (( Cache
[ Pkg
]. Flags
& pkgCache :: Flag :: Auto
) == pkgCache :: Flag :: Auto
)
115 fprintf ( output
, "APT-Automatic: yes \n " );
117 static bool WriteScenarioVersion ( FileFd
& output
, pkgCache :: PkgIterator
const & Pkg
,
118 pkgCache :: VerIterator
const & Ver
)
120 bool Okay
= WriteOkay ( output
, "Package: " , Pkg
. Name (),
121 " \n Architecture: " , Ver
. Arch (),
122 " \n Version: " , Ver
. VerStr ());
123 WriteOkay ( Okay
, output
, " \n APT-ID: " , Ver
-> ID
);
124 if (( Pkg
-> Flags
& pkgCache :: Flag :: Essential
) == pkgCache :: Flag :: Essential
)
125 WriteOkay ( Okay
, output
, " \n Essential: yes" );
126 if (( Ver
-> MultiArch
& pkgCache :: Version :: Allowed
) == pkgCache :: Version :: Allowed
)
127 WriteOkay ( Okay
, output
, " \n Multi-Arch: allowed" );
128 else if (( Ver
-> MultiArch
& pkgCache :: Version :: Foreign
) == pkgCache :: Version :: Foreign
)
129 WriteOkay ( Okay
, output
, " \n Multi-Arch: foreign" );
130 else if (( Ver
-> MultiArch
& pkgCache :: Version :: Same
) == pkgCache :: Version :: Same
)
131 WriteOkay ( Okay
, output
, " \n Multi-Arch: same" );
135 // WriteScenarioDependency /*{{{*/
136 static void WriteScenarioDependency ( FILE * output
, pkgCache :: VerIterator
const & Ver
)
138 std :: array
< std :: string
, _count ( DepMap
)> dependencies
;
139 bool orGroup
= false ;
140 for ( pkgCache :: DepIterator Dep
= Ver
. DependsList (); Dep
. end () == false ; ++ Dep
)
142 if ( Dep
. IsImplicit () == true )
144 if ( orGroup
== false )
145 dependencies
[ Dep
-> Type
]. append ( ", " );
146 dependencies
[ Dep
-> Type
]. append ( Dep
. TargetPkg (). Name ());
147 if ( Dep
-> Version
!= 0 )
148 dependencies
[ Dep
-> Type
]. append ( " (" ). append ( pkgCache :: CompTypeDeb ( Dep
-> CompareOp
)). append ( " " ). append ( Dep
. TargetVer ()). append ( ")" );
149 if (( Dep
-> CompareOp
& pkgCache :: Dep :: Or
) == pkgCache :: Dep :: Or
)
151 dependencies
[ Dep
-> Type
]. append ( " | " );
157 for ( size_t i
= 1 ; i
< dependencies
. size (); ++ i
)
158 if ( dependencies
[ i
]. empty () == false )
159 fprintf ( output
, " %s : %s \n " , DepMap
[ i
], dependencies
[ i
]. c_str ()+ 2 );
161 for ( pkgCache :: PrvIterator Prv
= Ver
. ProvidesList (); Prv
. end () == false ; ++ Prv
)
163 if ( Prv
. IsMultiArchImplicit () == true )
165 if ( provides
. empty () == false )
166 provides
. append ( ", " );
167 provides
. append ( Prv
. Name ());
168 if ( Prv
-> ProvideVersion
!= 0 )
169 provides
. append ( " (= " ). append ( Prv
. ProvideVersion ()). append ( ")" );
171 if ( provides
. empty () == false )
172 fprintf ( output
, "Provides: %s \n " , provides
. c_str ());
174 static bool WriteScenarioDependency ( FileFd
& output
, pkgCache :: VerIterator
const & Ver
, bool const OnlyCritical
)
176 std :: array
< std :: string
, _count ( DepMap
)> dependencies
;
177 bool orGroup
= false ;
178 for ( pkgCache :: DepIterator Dep
= Ver
. DependsList (); Dep
. end () == false ; ++ Dep
)
180 if ( Dep
. IsImplicit () == true )
182 if ( OnlyCritical
&& Dep
. IsCritical () == false )
184 if ( orGroup
== false && dependencies
[ Dep
-> Type
]. empty () == false )
185 dependencies
[ Dep
-> Type
]. append ( ", " );
186 dependencies
[ Dep
-> Type
]. append ( Dep
. TargetPkg (). Name ());
187 if ( Dep
-> Version
!= 0 )
188 dependencies
[ Dep
-> Type
]. append ( " (" ). append ( pkgCache :: CompTypeDeb ( Dep
-> CompareOp
)). append ( " " ). append ( Dep
. TargetVer ()). append ( ")" );
189 if (( Dep
-> CompareOp
& pkgCache :: Dep :: Or
) == pkgCache :: Dep :: Or
)
191 dependencies
[ Dep
-> Type
]. append ( " | " );
197 bool Okay
= output
. Failed () == false ;
198 for ( size_t i
= 1 ; i
< dependencies
. size (); ++ i
)
199 if ( dependencies
[ i
]. empty () == false )
200 WriteOkay ( Okay
, output
, " \n " , DepMap
[ i
], ": " , dependencies
[ i
]);
202 for ( pkgCache :: PrvIterator Prv
= Ver
. ProvidesList (); Prv
. end () == false ; ++ Prv
)
204 if ( Prv
. IsMultiArchImplicit () == true )
206 if ( provides
. empty () == false )
207 provides
. append ( ", " );
208 provides
. append ( Prv
. Name ());
209 if ( Prv
-> ProvideVersion
!= 0 )
210 provides
. append ( " (= " ). append ( Prv
. ProvideVersion ()). append ( ")" );
212 if ( provides
. empty () == false )
213 WriteOkay ( Okay
, output
, " \n Provides: " , provides
);
214 return WriteOkay ( Okay
, output
, " \n " );
217 // WriteScenarioLimitedDependency /*{{{*/
218 static void WriteScenarioLimitedDependency ( FILE * output
,
219 pkgCache :: VerIterator
const & Ver
,
220 APT :: PackageSet
const & pkgset
)
222 std :: array
< std :: string
, _count ( DepMap
)> dependencies
;
223 bool orGroup
= false ;
224 for ( pkgCache :: DepIterator Dep
= Ver
. DependsList (); Dep
. end () == false ; ++ Dep
)
226 if ( Dep
. IsImplicit () == true )
228 if ( orGroup
== false )
230 if ( pkgset
. find ( Dep
. TargetPkg ()) == pkgset
. end ())
232 if ( dependencies
[ Dep
-> Type
]. empty () == false )
233 dependencies
[ Dep
-> Type
]. append ( ", " );
235 else if ( pkgset
. find ( Dep
. TargetPkg ()) == pkgset
. end ())
237 if (( Dep
-> CompareOp
& pkgCache :: Dep :: Or
) == pkgCache :: Dep :: Or
)
239 dependencies
[ Dep
-> Type
]. erase ( dependencies
[ Dep
-> Type
]. end ()- 3 , dependencies
[ Dep
-> Type
]. end ());
243 dependencies
[ Dep
-> Type
]. append ( Dep
. TargetPkg (). Name ());
244 if ( Dep
-> Version
!= 0 )
245 dependencies
[ Dep
-> Type
]. append ( " (" ). append ( pkgCache :: CompTypeDeb ( Dep
-> CompareOp
)). append ( " " ). append ( Dep
. TargetVer ()). append ( ")" );
246 if (( Dep
-> CompareOp
& pkgCache :: Dep :: Or
) == pkgCache :: Dep :: Or
)
248 dependencies
[ Dep
-> Type
]. append ( " | " );
254 for ( size_t i
= 1 ; i
< dependencies
. size (); ++ i
)
255 if ( dependencies
[ i
]. empty () == false )
256 fprintf ( output
, " %s : %s \n " , DepMap
[ i
], dependencies
[ i
]. c_str ());
258 for ( pkgCache :: PrvIterator Prv
= Ver
. ProvidesList (); Prv
. end () == false ; ++ Prv
)
260 if ( Prv
. IsMultiArchImplicit () == true )
262 if ( pkgset
. find ( Prv
. ParentPkg ()) == pkgset
. end ())
264 if ( provides
. empty () == false )
265 provides
. append ( ", " );
266 provides
. append ( Prv
. Name ());
267 if ( Prv
-> ProvideVersion
!= 0 )
268 provides
. append ( " (= " ). append ( Prv
. ProvideVersion ()). append ( ")" );
270 if ( provides
. empty () == false )
271 fprintf ( output
, "Provides: %s \n " , provides
. c_str ());
273 static bool WriteScenarioLimitedDependency ( FileFd
& output
,
274 pkgCache :: VerIterator
const & Ver
,
275 std :: vector
< bool > const & pkgset
,
276 bool const OnlyCritical
)
278 std :: array
< std :: string
, _count ( DepMap
)> dependencies
;
279 bool orGroup
= false ;
280 for ( pkgCache :: DepIterator Dep
= Ver
. DependsList (); Dep
. end () == false ; ++ Dep
)
282 if ( Dep
. IsImplicit () == true )
284 if ( OnlyCritical
&& Dep
. IsCritical () == false )
286 if ( orGroup
== false )
288 if ( pkgset
[ Dep
. TargetPkg ()-> ID
] == false )
290 if ( dependencies
[ Dep
-> Type
]. empty () == false )
291 dependencies
[ Dep
-> Type
]. append ( ", " );
293 else if ( pkgset
[ Dep
. TargetPkg ()-> ID
] == false )
295 if (( Dep
-> CompareOp
& pkgCache :: Dep :: Or
) == pkgCache :: Dep :: Or
)
297 dependencies
[ Dep
-> Type
]. erase ( dependencies
[ Dep
-> Type
]. end ()- 3 , dependencies
[ Dep
-> Type
]. end ());
301 dependencies
[ Dep
-> Type
]. append ( Dep
. TargetPkg (). Name ());
302 if ( Dep
-> Version
!= 0 )
303 dependencies
[ Dep
-> Type
]. append ( " (" ). append ( pkgCache :: CompTypeDeb ( Dep
-> CompareOp
)). append ( " " ). append ( Dep
. TargetVer ()). append ( ")" );
304 if (( Dep
-> CompareOp
& pkgCache :: Dep :: Or
) == pkgCache :: Dep :: Or
)
306 dependencies
[ Dep
-> Type
]. append ( " | " );
312 bool Okay
= output
. Failed () == false ;
313 for ( size_t i
= 1 ; i
< dependencies
. size (); ++ i
)
314 if ( dependencies
[ i
]. empty () == false )
315 WriteOkay ( Okay
, output
, " \n " , DepMap
[ i
], ": " , dependencies
[ i
]);
317 for ( pkgCache :: PrvIterator Prv
= Ver
. ProvidesList (); Prv
. end () == false ; ++ Prv
)
319 if ( Prv
. IsMultiArchImplicit () == true )
321 if ( pkgset
[ Prv
. ParentPkg ()-> ID
] == false )
323 if ( provides
. empty () == false )
324 provides
. append ( ", " );
325 provides
. append ( Prv
. Name ());
326 if ( Prv
-> ProvideVersion
!= 0 )
327 provides
. append ( " (= " ). append ( Prv
. ProvideVersion ()). append ( ")" );
329 if ( provides
. empty () == false )
330 WriteOkay ( Okay
, output
, " \n Provides: " , provides
);
331 return WriteOkay ( Okay
, output
, " \n " );
334 static bool SkipUnavailableVersions ( pkgDepCache
& Cache
, pkgCache :: PkgIterator
const & Pkg
, pkgCache :: VerIterator
const & Ver
) /*{{{*/
336 /* versions which aren't current and aren't available in
337 any "online" source file are bad, expect if they are the choosen
338 candidate: The exception is for build-dep implementation as it creates
339 such pseudo (package) versions and removes them later on again.
340 We filter out versions at all so packages in 'rc' state only available
341 in dpkg/status aren't passed to solvers as they can't be installed. */
342 if ( Pkg
-> CurrentVer
!= 0 )
344 if ( Cache
. GetCandidateVersion ( Pkg
) == Ver
)
346 for ( pkgCache :: VerFileIterator I
= Ver
. FileList (); I
. end () == false ; ++ I
)
347 if ( I
. File (). Flagged ( pkgCache :: Flag :: NotSource
) == false )
352 static bool WriteScenarioEDSPVersion ( pkgDepCache
& Cache
, FileFd
& output
, pkgCache :: PkgIterator
const & Pkg
, /*{{{*/
353 pkgCache :: VerIterator
const & Ver
)
355 bool Okay
= WriteOkay ( output
, " \n Source: " , Ver
. SourcePkgName (),
356 " \n Source-Version: " , Ver
. SourceVerStr ());
357 if ( PrioMap
[ Ver
-> Priority
] != nullptr )
358 WriteOkay ( Okay
, output
, " \n Priority: " , PrioMap
[ Ver
-> Priority
]);
359 if ( Ver
-> Section
!= 0 )
360 WriteOkay ( Okay
, output
, " \n Section: " , Ver
. Section ());
361 if ( Pkg
. CurrentVer () == Ver
)
362 WriteOkay ( Okay
, output
, " \n Installed: yes" );
363 if ( Pkg
-> SelectedState
== pkgCache :: State :: Hold
||
364 ( Cache
[ Pkg
]. Keep () == true && Cache
[ Pkg
]. Protect () == true ))
365 WriteOkay ( Okay
, output
, " \n Hold: yes" );
366 std :: set
< string
> Releases
;
367 for ( pkgCache :: VerFileIterator I
= Ver
. FileList (); I
. end () == false ; ++ I
) {
368 pkgCache :: PkgFileIterator File
= I
. File ();
369 if ( File
. Flagged ( pkgCache :: Flag :: NotSource
) == false ) {
370 string Release
= File
. RelStr ();
371 if (! Release
. empty ())
372 Releases
. insert ( Release
);
375 if (! Releases
. empty ()) {
376 WriteOkay ( Okay
, output
, " \n APT-Release:" );
377 for ( std :: set
< string
>:: iterator R
= Releases
. begin (); R
!= Releases
. end (); ++ R
)
378 WriteOkay ( Okay
, output
, " \n " , * R
);
380 WriteOkay ( Okay
, output
, " \n APT-Pin: " , Cache
. GetPolicy (). GetPriority ( Ver
));
381 if ( Cache
. GetCandidateVersion ( Pkg
) == Ver
)
382 WriteOkay ( Okay
, output
, " \n APT-Candidate: yes" );
383 if (( Cache
[ Pkg
]. Flags
& pkgCache :: Flag :: Auto
) == pkgCache :: Flag :: Auto
)
384 WriteOkay ( Okay
, output
, " \n APT-Automatic: yes" );
388 // EDSP::WriteScenario - to the given file descriptor /*{{{*/
389 bool EDSP :: WriteScenario ( pkgDepCache
& Cache
, FILE * output
, OpProgress
* Progress
)
391 if ( Progress
!= NULL
)
392 Progress
-> SubProgress ( Cache
. Head (). VersionCount
, _ ( "Send scenario to solver" ));
394 std :: vector
< std :: string
> archs
= APT :: Configuration :: getArchitectures ();
395 for ( pkgCache :: PkgIterator Pkg
= Cache
. PkgBegin (); Pkg
. end () == false ; ++ Pkg
)
397 std :: string
const arch
= Pkg
. Arch ();
398 if ( std :: find ( archs
. begin (), archs
. end (), arch
) == archs
. end ())
400 for ( pkgCache :: VerIterator Ver
= Pkg
. VersionList (); Ver
. end () == false ; ++ Ver
, ++ p
)
402 if ( SkipUnavailableVersions ( Cache
, Pkg
, Ver
))
404 WriteScenarioVersion ( Cache
, output
, Pkg
, Ver
);
405 WriteScenarioDependency ( output
, Ver
);
406 fprintf ( output
, " \n " );
407 if ( Progress
!= NULL
&& p
% 100 == 0 )
408 Progress
-> Progress ( p
);
413 bool EDSP :: WriteScenario ( pkgDepCache
& Cache
, FileFd
& output
, OpProgress
* Progress
)
415 if ( Progress
!= NULL
)
416 Progress
-> SubProgress ( Cache
. Head (). VersionCount
, _ ( "Send scenario to solver" ));
418 bool Okay
= output
. Failed () == false ;
419 std :: vector
< std :: string
> archs
= APT :: Configuration :: getArchitectures ();
420 for ( pkgCache :: PkgIterator Pkg
= Cache
. PkgBegin (); Pkg
. end () == false && likely ( Okay
); ++ Pkg
)
422 std :: string
const arch
= Pkg
. Arch ();
423 if ( std :: find ( archs
. begin (), archs
. end (), arch
) == archs
. end ())
425 for ( pkgCache :: VerIterator Ver
= Pkg
. VersionList (); Ver
. end () == false && likely ( Okay
); ++ Ver
, ++ p
)
427 if ( SkipUnavailableVersions ( Cache
, Pkg
, Ver
))
429 Okay
&= WriteScenarioVersion ( output
, Pkg
, Ver
);
430 Okay
&= WriteScenarioEDSPVersion ( Cache
, output
, Pkg
, Ver
);
431 Okay
&= WriteScenarioDependency ( output
, Ver
, false );
432 WriteOkay ( Okay
, output
, " \n " );
433 if ( Progress
!= NULL
&& p
% 100 == 0 )
434 Progress
-> Progress ( p
);
440 // EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/
441 bool EDSP :: WriteLimitedScenario ( pkgDepCache
& Cache
, FILE * output
,
442 APT :: PackageSet
const & pkgset
,
443 OpProgress
* Progress
)
445 if ( Progress
!= NULL
)
446 Progress
-> SubProgress ( Cache
. Head (). VersionCount
, _ ( "Send scenario to solver" ));
448 for ( APT :: PackageSet :: const_iterator Pkg
= pkgset
. begin (); Pkg
!= pkgset
. end (); ++ Pkg
, ++ p
)
449 for ( pkgCache :: VerIterator Ver
= Pkg
. VersionList (); Ver
. end () == false ; ++ Ver
)
451 if ( SkipUnavailableVersions ( Cache
, Pkg
, Ver
))
453 WriteScenarioVersion ( Cache
, output
, Pkg
, Ver
);
454 WriteScenarioLimitedDependency ( output
, Ver
, pkgset
);
455 fprintf ( output
, " \n " );
456 if ( Progress
!= NULL
&& p
% 100 == 0 )
457 Progress
-> Progress ( p
);
459 if ( Progress
!= NULL
)
463 bool EDSP :: WriteLimitedScenario ( pkgDepCache
& Cache
, FileFd
& output
,
464 std :: vector
< bool > const & pkgset
,
465 OpProgress
* Progress
)
467 if ( Progress
!= NULL
)
468 Progress
-> SubProgress ( Cache
. Head (). VersionCount
, _ ( "Send scenario to solver" ));
470 bool Okay
= output
. Failed () == false ;
471 for ( auto Pkg
= Cache
. PkgBegin (); Pkg
. end () == false && likely ( Okay
); ++ Pkg
, ++ p
)
473 if ( pkgset
[ Pkg
-> ID
] == false )
475 for ( pkgCache :: VerIterator Ver
= Pkg
. VersionList (); Ver
. end () == false && likely ( Okay
); ++ Ver
)
477 if ( SkipUnavailableVersions ( Cache
, Pkg
, Ver
))
479 Okay
&= WriteScenarioVersion ( output
, Pkg
, Ver
);
480 Okay
&= WriteScenarioEDSPVersion ( Cache
, output
, Pkg
, Ver
);
481 Okay
&= WriteScenarioLimitedDependency ( output
, Ver
, pkgset
, false );
482 WriteOkay ( Okay
, output
, " \n " );
483 if ( Progress
!= NULL
&& p
% 100 == 0 )
484 Progress
-> Progress ( p
);
487 if ( Progress
!= NULL
)
492 // EDSP::WriteRequest - to the given file descriptor /*{{{*/
493 bool EDSP :: WriteRequest ( pkgDepCache
& Cache
, FILE * output
, bool const Upgrade
,
494 bool const DistUpgrade
, bool const AutoRemove
,
495 OpProgress
* Progress
)
497 if ( Progress
!= NULL
)
498 Progress
-> SubProgress ( Cache
. Head (). PackageCount
, _ ( "Send request to solver" ));
501 for ( pkgCache :: PkgIterator Pkg
= Cache
. PkgBegin (); Pkg
. end () == false ; ++ Pkg
, ++ p
)
503 if ( Progress
!= NULL
&& p
% 100 == 0 )
504 Progress
-> Progress ( p
);
506 pkgDepCache :: StateCache
& P
= Cache
[ Pkg
];
507 if ( P
. Delete () == true )
509 else if ( P
. NewInstall () == true || P
. Upgrade () == true || P
. ReInstall () == true ||
510 ( P
. Mode
== pkgDepCache :: ModeKeep
&& ( P
. iFlags
& pkgDepCache :: Protected
) == pkgDepCache :: Protected
))
514 req
-> append ( " " ). append ( Pkg
. FullName ());
516 fprintf ( output
, "Request: EDSP 0.5 \n " );
518 const char * arch
= _config
-> Find ( "APT::Architecture" ). c_str ();
519 std :: vector
< string
> archs
= APT :: Configuration :: getArchitectures ();
520 fprintf ( output
, "Architecture: %s \n " , arch
);
521 fprintf ( output
, "Architectures:" );
522 for ( std :: vector
< string
>:: const_iterator a
= archs
. begin (); a
!= archs
. end (); ++ a
)
523 fprintf ( output
, " %s " , a
-> c_str ());
524 fprintf ( output
, " \n " );
526 if ( del
. empty () == false )
527 fprintf ( output
, "Remove: %s \n " , del
. c_str ()+ 1 );
528 if ( inst
. empty () == false )
529 fprintf ( output
, "Install: %s \n " , inst
. c_str ()+ 1 );
531 fprintf ( output
, "Upgrade: yes \n " );
532 if ( DistUpgrade
== true )
533 fprintf ( output
, "Dist-Upgrade: yes \n " );
534 if ( AutoRemove
== true )
535 fprintf ( output
, "Autoremove: yes \n " );
536 auto const solver
= _config
-> Find ( "APT::Solver" , "internal" );
537 fprintf ( output
, "Solver: %s \n " , solver
. c_str ());
538 auto const solverconf
= std :: string ( "APT::Solver::" ) + solver
+ "::" ;
539 if ( _config
-> FindB ( solverconf
+ "Strict-Pinning" , _config
-> FindB ( "APT::Solver::Strict-Pinning" , true )) == false )
540 fprintf ( output
, "Strict-Pinning: no \n " );
541 auto const solverpref
= _config
-> Find ( solverconf
+ "Preferences" , _config
-> Find ( "APT::Solver::Preferences" , "" ));
542 if ( solverpref
. empty () == false )
543 fprintf ( output
, "Preferences: %s \n " , solverpref
. c_str ());
544 fprintf ( output
, " \n " );
547 bool EDSP :: WriteRequest ( pkgDepCache
& Cache
, FileFd
& output
,
548 unsigned int const flags
,
549 OpProgress
* Progress
)
551 if ( Progress
!= NULL
)
552 Progress
-> SubProgress ( Cache
. Head (). PackageCount
, _ ( "Send request to solver" ));
555 for ( pkgCache :: PkgIterator Pkg
= Cache
. PkgBegin (); Pkg
. end () == false ; ++ Pkg
, ++ p
)
557 if ( Progress
!= NULL
&& p
% 100 == 0 )
558 Progress
-> Progress ( p
);
560 pkgDepCache :: StateCache
& P
= Cache
[ Pkg
];
561 if ( P
. Delete () == true )
563 else if ( P
. NewInstall () == true || P
. Upgrade () == true || P
. ReInstall () == true ||
564 ( P
. Mode
== pkgDepCache :: ModeKeep
&& ( P
. iFlags
& pkgDepCache :: Protected
) == pkgDepCache :: Protected
))
568 req
-> append ( " " ). append ( Pkg
. FullName ());
570 bool Okay
= WriteOkay ( output
, "Request: EDSP 0.5 \n " );
572 const char * arch
= _config
-> Find ( "APT::Architecture" ). c_str ();
573 std :: vector
< string
> archs
= APT :: Configuration :: getArchitectures ();
574 WriteOkay ( Okay
, output
, "Architecture: " , arch
, " \n " ,
576 for ( std :: vector
< string
>:: const_iterator a
= archs
. begin (); a
!= archs
. end (); ++ a
)
577 WriteOkay ( Okay
, output
, " " , * a
);
578 WriteOkay ( Okay
, output
, " \n " );
580 if ( del
. empty () == false )
581 WriteOkay ( Okay
, output
, "Remove:" , del
, " \n " );
582 if ( inst
. empty () == false )
583 WriteOkay ( Okay
, output
, "Install:" , inst
, " \n " );
584 if ( flags
& Request :: AUTOREMOVE
)
585 WriteOkay ( Okay
, output
, "Autoremove: yes \n " );
586 if ( flags
& Request :: UPGRADE_ALL
)
588 WriteOkay ( Okay
, output
, "Upgrade-All: yes \n " );
589 if ( flags
& ( Request :: FORBID_NEW_INSTALL
| Request :: FORBID_REMOVE
))
590 WriteOkay ( Okay
, output
, "Upgrade: yes \n " );
592 WriteOkay ( Okay
, output
, "Dist-Upgrade: yes \n " );
594 if ( flags
& Request :: FORBID_NEW_INSTALL
)
595 WriteOkay ( Okay
, output
, "Forbid-New-Install: yes \n " );
596 if ( flags
& Request :: FORBID_REMOVE
)
597 WriteOkay ( Okay
, output
, "Forbid-Remove: yes \n " );
598 if ( _config
-> FindB ( "APT::Solver::Strict-Pinning" , true ) == false )
599 WriteOkay ( Okay
, output
, "Strict-Pinning: no \n " );
600 string
solverpref ( "APT::Solver::" );
601 solverpref
. append ( _config
-> Find ( "APT::Solver" , "internal" )). append ( "::Preferences" );
602 if ( _config
-> Exists ( solverpref
) == true )
603 WriteOkay ( Okay
, output
, "Preferences: " , _config
-> Find ( solverpref
, "" ), " \n " );
604 return WriteOkay ( Okay
, output
, " \n " );
607 // EDSP::ReadResponse - from the given file descriptor /*{{{*/
608 bool EDSP :: ReadResponse ( int const input
, pkgDepCache
& Cache
, OpProgress
* Progress
) {
609 /* We build an map id to mmap offset here
610 In theory we could use the offset as ID, but then VersionCount
611 couldn't be used to create other versionmappings anymore and it
612 would be too easy for a (buggy) solver to segfault APTā¦ */
613 unsigned long long const VersionCount
= Cache
. Head (). VersionCount
;
614 unsigned long VerIdx
[ VersionCount
];
615 for ( pkgCache :: PkgIterator P
= Cache
. PkgBegin (); P
. end () == false ; ++ P
) {
616 for ( pkgCache :: VerIterator V
= P
. VersionList (); V
. end () == false ; ++ V
)
617 VerIdx
[ V
-> ID
] = V
. Index ();
618 Cache
[ P
]. Marked
= true ;
619 Cache
[ P
]. Garbage
= false ;
623 in
. OpenDescriptor ( input
, FileFd :: ReadOnly
);
624 pkgTagFile
response (& in
, 100 );
625 pkgTagSection section
;
627 std :: set
< decltype ( Cache
. PkgBegin ()-> ID
)> seenOnce
;
628 while ( response
. Step ( section
) == true ) {
630 if ( section
. Exists ( "Install" ) == true )
632 else if ( section
. Exists ( "Remove" ) == true )
634 else if ( section
. Exists ( "Progress" ) == true ) {
635 if ( Progress
!= NULL
) {
636 string msg
= section
. FindS ( "Message" );
637 if ( msg
. empty () == true )
638 msg
= _ ( "Prepare for receiving solution" );
639 Progress
-> SubProgress ( 100 , msg
, section
. FindI ( "Percentage" , 0 ));
642 } else if ( section
. Exists ( "Error" ) == true ) {
643 std :: string msg
= SubstVar ( SubstVar ( section
. FindS ( "Message" ), " \n . \n " , " \n\n " ), " \n " , " \n " );
644 if ( msg
. empty () == true ) {
645 msg
= _ ( "External solver failed without a proper error message" );
646 _error
-> Error ( " %s " , msg
. c_str ());
648 _error
-> Error ( "External solver failed with: %s " , msg
. substr ( 0 , msg
. find ( ' \n ' )). c_str ());
649 if ( Progress
!= NULL
)
651 std :: cerr
<< "The solver encountered an error of type: " << section
. FindS ( "Error" ) << std :: endl
;
652 std :: cerr
<< "The following information might help you to understand what is wrong:" << std :: endl
;
653 std :: cerr
<< msg
<< std :: endl
<< std :: endl
;
655 } else if ( section
. Exists ( "Autoremove" ) == true )
660 size_t const id
= section
. FindULL ( type
. c_str (), VersionCount
);
661 if ( id
== VersionCount
) {
662 _error
-> Warning ( "Unable to parse %s request with id value ' %s '!" , type
. c_str (), section
. FindS ( type
. c_str ()). c_str ());
664 } else if ( id
> Cache
. Head (). VersionCount
) {
665 _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 ());
669 pkgCache :: VerIterator
Ver ( Cache
. GetCache (), Cache
. GetCache (). VerP
+ VerIdx
[ id
]);
670 auto const Pkg
= Ver
. ParentPkg ();
671 if ( type
== "Autoremove" ) {
672 Cache
[ Pkg
]. Marked
= false ;
673 Cache
[ Pkg
]. Garbage
= true ;
674 } else if ( seenOnce
. emplace ( Pkg
-> ID
). second
== false ) {
675 _error
-> Warning ( "Ignoring %s stanza received for package %s which already had a previous stanza effecting it!" , type
. c_str (), Pkg
. FullName ( false ). c_str ());
676 } else if ( type
== "Install" ) {
677 if ( Pkg
. CurrentVer () == Ver
) {
678 _error
-> Warning ( "Ignoring Install stanza received for version %s of package %s which is already installed!" ,
679 Ver
. VerStr (), Pkg
. FullName ( false ). c_str ());
681 Cache
. SetCandidateVersion ( Ver
);
682 Cache
. MarkInstall ( Pkg
, false , 0 , false );
684 } else if ( type
== "Remove" ) {
685 if ( Pkg
-> CurrentVer
== 0 )
686 _error
-> Warning ( "Ignoring Remove stanza received for version %s of package %s which isn't installed!" ,
687 Ver
. VerStr (), Pkg
. FullName ( false ). c_str ());
688 else if ( Pkg
. CurrentVer () != Ver
)
689 _error
-> Warning ( "Ignoring Remove stanza received for version %s of package %s which isn't the installed version %s !" ,
690 Ver
. VerStr (), Pkg
. FullName ( false ). c_str (), Pkg
. CurrentVer (). VerStr ());
692 Cache
. MarkDelete ( Ver
. ParentPkg (), false );
698 // ReadLine - first line from the given file descriptor /*{{{*/
699 // ---------------------------------------------------------------------
700 /* Little helper method to read a complete line into a string. Similar to
701 fgets but we need to use the low-level read() here as otherwise the
702 listparser will be confused later on as mixing of fgets and read isn't
703 a supported action according to the manpages and results are undefined */
704 static bool ReadLine ( int const input
, std :: string
& line
) {
709 while (( data
= read ( input
, & one
, sizeof ( one
))) != - 1 ) {
716 if ( line
. empty () == true && isblank ( one
) != 0 )
723 // StringToBool - convert yes/no to bool /*{{{*/
724 // ---------------------------------------------------------------------
725 /* we are not as lazy as we are in the global StringToBool as we really
726 only accept yes/no here - but we will ignore leading spaces */
727 static bool StringToBool ( char const * answer
, bool const defValue
) {
728 for (; isspace (* answer
) != 0 ; ++ answer
);
729 if ( strncasecmp ( answer
, "yes" , 3 ) == 0 )
731 else if ( strncasecmp ( answer
, "no" , 2 ) == 0 )
734 _error
-> Warning ( "Value ' %s ' is not a boolean 'yes' or 'no'!" , answer
);
738 static bool ReadFlag ( unsigned int & flags
, std :: string
const & line
, APT :: StringView
const name
, unsigned int const setflag
) /*{{{*/
740 if ( line
. compare ( 0 , name
. length (), name
. data ()) != 0 )
742 auto const l
= line
. c_str () + name
. length () + 1 ;
743 if ( StringToBool ( l
, false ))
750 // EDSP::ReadRequest - first stanza from the given file descriptor /*{{{*/
751 bool EDSP :: ReadRequest ( int const input
, std :: list
< std :: string
> & install
,
752 std :: list
< std :: string
> & remove
, unsigned int & flags
)
758 while ( ReadLine ( input
, line
) == true )
760 // Skip empty lines before request
761 if ( line
. empty () == true )
763 // The first Tag must be a request, so search for it
764 if ( line
. compare ( 0 , 8 , "Request:" ) != 0 )
767 while ( ReadLine ( input
, line
) == true )
769 // empty lines are the end of the request
770 if ( line
. empty () == true )
773 std :: list
< std :: string
> * request
= NULL
;
774 if ( line
. compare ( 0 , 8 , "Install:" ) == 0 )
779 else if ( line
. compare ( 0 , 7 , "Remove:" ) == 0 )
784 else if ( ReadFlag ( flags
, line
, "Upgrade:" , ( Request :: UPGRADE_ALL
| Request :: FORBID_REMOVE
| Request :: FORBID_NEW_INSTALL
)) ||
785 ReadFlag ( flags
, line
, "Dist-Upgrade:" , Request :: UPGRADE_ALL
) ||
786 ReadFlag ( flags
, line
, "Upgrade-All:" , Request :: UPGRADE_ALL
) ||
787 ReadFlag ( flags
, line
, "Forbid-New-Install:" , Request :: FORBID_NEW_INSTALL
) ||
788 ReadFlag ( flags
, line
, "Forbid-Remove:" , Request :: FORBID_REMOVE
) ||
789 ReadFlag ( flags
, line
, "Autoremove:" , Request :: AUTOREMOVE
))
791 else if ( line
. compare ( 0 , 13 , "Architecture:" ) == 0 )
792 _config
-> Set ( "APT::Architecture" , line
. c_str () + 14 );
793 else if ( line
. compare ( 0 , 14 , "Architectures:" ) == 0 )
795 std :: string
const archs
= line
. c_str () + 15 ;
796 _config
-> Set ( "APT::Architectures" , SubstVar ( archs
, " " , "," ));
798 else if ( line
. compare ( 0 , 7 , "Solver:" ) == 0 )
799 ; // purely informational line
801 _error
-> Warning ( "Unknown line in EDSP Request stanza: %s " , line
. c_str ());
805 size_t end
= line
. length ();
807 size_t begin
= line
. rfind ( ' ' );
808 if ( begin
== std :: string :: npos
)
810 request
-> push_back ( line
. substr ( 0 , end
));
813 else if ( begin
< end
)
814 request
-> push_back ( line
. substr ( begin
+ 1 , end
));
816 end
= line
. find_last_not_of ( ' ' );
817 } while ( end
!= std :: string :: npos
);
822 bool EDSP :: ReadRequest ( int const input
, std :: list
< std :: string
> & install
,
823 std :: list
< std :: string
> & remove
, bool & upgrade
,
824 bool & distUpgrade
, bool & autoRemove
)
827 auto const ret
= ReadRequest ( input
, install
, remove
, flags
);
828 autoRemove
= ( flags
& Request :: AUTOREMOVE
);
829 if ( flags
& Request :: UPGRADE_ALL
)
831 if ( flags
& ( Request :: FORBID_NEW_INSTALL
| Request :: FORBID_REMOVE
))
848 // EDSP::ApplyRequest - first stanza from the given file descriptor /*{{{*/
849 bool EDSP :: ApplyRequest ( std :: list
< std :: string
> const & install
,
850 std :: list
< std :: string
> const & remove
,
853 for ( std :: list
< std :: string
>:: const_iterator i
= install
. begin ();
854 i
!= install
. end (); ++ i
) {
855 pkgCache :: PkgIterator P
= Cache
. FindPkg (* i
);
857 _error
-> Warning ( "Package %s is not known, so can't be installed" , i
-> c_str ());
859 Cache
. MarkInstall ( P
, false );
862 for ( std :: list
< std :: string
>:: const_iterator i
= remove
. begin ();
863 i
!= remove
. end (); ++ i
) {
864 pkgCache :: PkgIterator P
= Cache
. FindPkg (* i
);
866 _error
-> Warning ( "Package %s is not known, so can't be installed" , i
-> c_str ());
873 // EDSP::WriteSolution - to the given file descriptor /*{{{*/
874 bool EDSP :: WriteSolution ( pkgDepCache
& Cache
, FILE * output
)
876 bool const Debug
= _config
-> FindB ( "Debug::EDSP::WriteSolution" , false );
877 for ( pkgCache :: PkgIterator Pkg
= Cache
. PkgBegin (); Pkg
. end () == false ; ++ Pkg
)
879 if ( Cache
[ Pkg
]. Delete () == true )
881 fprintf ( output
, "Remove: %d \n " , Pkg
. CurrentVer ()-> ID
);
883 fprintf ( output
, "Package: %s \n Version: %s \n " , Pkg
. FullName (). c_str (), Pkg
. CurrentVer (). VerStr ());
885 else if ( Cache
[ Pkg
]. NewInstall () == true || Cache
[ Pkg
]. Upgrade () == true )
887 pkgCache :: VerIterator
const CandVer
= Cache
. GetCandidateVersion ( Pkg
);
888 fprintf ( output
, "Install: %d \n " , CandVer
-> ID
);
890 fprintf ( output
, "Package: %s \n Version: %s \n " , Pkg
. FullName (). c_str (), CandVer
. VerStr ());
892 else if ( Cache
[ Pkg
]. Garbage
== true )
894 fprintf ( output
, "Autoremove: %d \n " , Pkg
. CurrentVer ()-> ID
);
896 fprintf ( output
, "Package: %s \n Version: %s \n " , Pkg
. FullName (). c_str (), Pkg
. CurrentVer (). VerStr ());
900 fprintf ( output
, " \n " );
905 bool EDSP :: WriteSolution ( pkgDepCache
& Cache
, FileFd
& output
)
907 bool const Debug
= _config
-> FindB ( "Debug::EDSP::WriteSolution" , false );
908 bool Okay
= output
. Failed () == false ;
909 for ( pkgCache :: PkgIterator Pkg
= Cache
. PkgBegin (); Pkg
. end () == false && likely ( Okay
); ++ Pkg
)
912 if ( Cache
[ Pkg
]. Delete () == true )
913 WriteOkay ( Okay
, output
, "Remove: " , Pkg
. CurrentVer ()-> ID
, " \n " );
914 else if ( Cache
[ Pkg
]. NewInstall () == true || Cache
[ Pkg
]. Upgrade () == true )
915 WriteOkay ( Okay
, output
, "Install: " , Cache
. GetCandidateVersion ( Pkg
)-> ID
, " \n " );
916 else if ( Cache
[ Pkg
]. Garbage
== true )
917 WriteOkay ( Okay
, output
, "Autoremove: " , Pkg
. CurrentVer ()-> ID
, " \n " );
923 WriteOkay ( Okay
, output
, "Package: " , Pkg
. FullName (), " \n Version: " );
924 if ( Cache
[ Pkg
]. Delete () == true || Cache
[ Pkg
]. Garbage
== true )
925 WriteOkay ( Okay
, output
, Pkg
. CurrentVer (). VerStr (), " \n\n " );
927 WriteOkay ( Okay
, output
, Cache
. GetCandidateVersion ( Pkg
). VerStr (), " \n\n " );
930 WriteOkay ( Okay
, output
, " \n " );
935 // EDSP::WriteProgess - pulse to the given file descriptor /*{{{*/
936 bool EDSP :: WriteProgress ( unsigned short const percent
, const char * const message
, FILE * output
) {
937 fprintf ( output
, "Progress: %s \n " , TimeRFC1123 ( time ( NULL
)). c_str ());
938 fprintf ( output
, "Percentage: %d \n " , percent
);
939 fprintf ( output
, "Message: %s \n\n " , message
);
943 bool EDSP :: WriteProgress ( unsigned short const percent
, const char * const message
, FileFd
& output
) {
944 return WriteOkay ( output
, "Progress: " , TimeRFC1123 ( time ( NULL
)), " \n " ,
945 "Percentage: " , percent
, " \n " ,
946 "Message: " , message
, " \n\n " ) && output
. Flush ();
949 // EDSP::WriteError - format an error message to be send to file descriptor /*{{{*/
950 bool EDSP :: WriteError ( char const * const uuid
, std :: string
const & message
, FILE * output
) {
951 fprintf ( output
, "Error: %s \n " , uuid
);
952 fprintf ( output
, "Message: %s \n\n " , SubstVar ( SubstVar ( message
, " \n\n " , " \n . \n " ), " \n " , " \n " ). c_str ());
955 bool EDSP :: WriteError ( char const * const uuid
, std :: string
const & message
, FileFd
& output
) {
956 return WriteOkay ( output
, "Error: " , uuid
, " \n " ,
957 "Message: " , SubstVar ( SubstVar ( message
, " \n\n " , " \n . \n " ), " \n " , " \n " ),
961 static pid_t
ExecuteExternal ( char const * const type
, char const * const binary
, char const * const configdir
, int * const solver_in
, int * const solver_out
) { /*{{{*/
962 std :: vector
< std :: string
> const solverDirs
= _config
-> FindVector ( configdir
);
964 for ( std :: vector
< std :: string
>:: const_iterator dir
= solverDirs
. begin ();
965 dir
!= solverDirs
. end (); ++ dir
) {
966 file
= flCombine (* dir
, binary
);
967 if ( RealFileExists ( file
. c_str ()) == true )
972 if ( file
. empty () == true )
974 _error
-> Error ( "Can't call external %s ' %s ' as it is not in a configured directory!" , type
, binary
);
977 int external
[ 4 ] = {- 1 , - 1 , - 1 , - 1 };
978 if ( pipe ( external
) != 0 || pipe ( external
+ 2 ) != 0 )
980 _error
-> Errno ( "Resolve" , "Can't create needed IPC pipes for EDSP" );
983 for ( int i
= 0 ; i
< 4 ; ++ i
)
984 SetCloseExec ( external
[ i
], true );
986 pid_t Solver
= ExecFork ();
988 dup2 ( external
[ 0 ], STDIN_FILENO
);
989 dup2 ( external
[ 3 ], STDOUT_FILENO
);
990 const char * calling
[ 2 ] = { file
. c_str (), 0 };
991 execv ( calling
[ 0 ], ( char **) calling
);
992 std :: cerr
<< "Failed to execute " << type
<< " '" << binary
<< "'!" << std :: endl
;
998 if ( WaitFd ( external
[ 1 ], true , 5 ) == false )
1000 _error
-> Errno ( "Resolve" , "Timed out while Waiting on availability of %s stdin" , type
);
1004 * solver_in
= external
[ 1 ];
1005 * solver_out
= external
[ 2 ];
1009 // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/
1010 pid_t
EDSP :: ExecuteSolver ( const char * const solver
, int * const solver_in
, int * const solver_out
, bool ) {
1011 return ExecuteExternal ( "solver" , solver
, "Dir::Bin::Solvers" , solver_in
, solver_out
);
1013 bool EDSP :: ExecuteSolver ( const char * const solver
, int * solver_in
, int * solver_out
) {
1014 if ( ExecuteSolver ( solver
, solver_in
, solver_out
, true ) == 0 )
1019 // EDSP::ResolveExternal - resolve problems by asking external for help {{{*/
1020 bool EDSP :: ResolveExternal ( const char * const solver
, pkgDepCache
& Cache
,
1021 unsigned int const flags
, OpProgress
* Progress
) {
1022 int solver_in
, solver_out
;
1023 pid_t
const solver_pid
= EDSP :: ExecuteSolver ( solver
, & solver_in
, & solver_out
, true );
1024 if ( solver_pid
== 0 )
1028 if ( output
. OpenDescriptor ( solver_in
, FileFd :: WriteOnly
| FileFd :: BufferedWrite
, true ) == false )
1029 return _error
-> Errno ( "ResolveExternal" , "Opening solver %s stdin on fd %d for writing failed" , solver
, solver_in
);
1031 bool Okay
= output
. Failed () == false ;
1032 if ( Progress
!= NULL
)
1033 Progress
-> OverallProgress ( 0 , 100 , 5 , _ ( "Execute external solver" ));
1034 Okay
&= EDSP :: WriteRequest ( Cache
, output
, flags
, Progress
);
1035 if ( Progress
!= NULL
)
1036 Progress
-> OverallProgress ( 5 , 100 , 20 , _ ( "Execute external solver" ));
1037 Okay
&= EDSP :: WriteScenario ( Cache
, output
, Progress
);
1040 if ( Progress
!= NULL
)
1041 Progress
-> OverallProgress ( 25 , 100 , 75 , _ ( "Execute external solver" ));
1042 if ( Okay
&& EDSP :: ReadResponse ( solver_out
, Cache
, Progress
) == false )
1045 return ExecWait ( solver_pid
, solver
);
1047 bool EDSP :: ResolveExternal ( const char * const solver
, pkgDepCache
& Cache
,
1048 bool const upgrade
, bool const distUpgrade
,
1049 bool const autoRemove
, OpProgress
* Progress
) {
1050 unsigned int flags
= 0 ;
1052 flags
|= Request :: AUTOREMOVE
;
1054 flags
|= Request :: UPGRADE_ALL
| Request :: FORBID_REMOVE
| Request :: FORBID_NEW_INSTALL
;
1056 flags
|= Request :: UPGRADE_ALL
;
1057 return ResolveExternal ( solver
, Cache
, flags
, Progress
);