]>
git.saurik.com Git - apt.git/blob - apt-pkg/packagemanager.cc
ebf67b5ee9b184686726cff85be91cac89b523b9
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: packagemanager.cc,v 1.1 1998/07/07 04:17:01 jgg Exp $
4 /* ######################################################################
6 Package Manager - Abstacts the package manager
8 More work is needed in the area of transitioning provides, ie exim
9 replacing smail. This can cause interesing side effects.
11 Other cases involving conflicts+replaces should be tested.
13 ##################################################################### */
15 // Include Files /*{{{*/
17 #pragma implementation "pkglib/packagemanager.h"
19 #include <pkglib/packagemanager.h>
20 #include <pkglib/orderlist.h>
21 #include <pkglib/depcache.h>
22 #include <pkglib/sourcelist.h>
23 #include <pkglib/aquire.h>
24 #include <pkglib/controlcache.h>
25 #include <pkglib/error.h>
29 // PM::PackageManager - Constructor /*{{{*/
30 // ---------------------------------------------------------------------
32 pkgPackageManager::pkgPackageManager(pkgDepCache
&Cache
) : Cache(Cache
)
34 FileNames
= new string
[Cache
.Head().PackageCount
];
38 // PM::PackageManager - Destructor /*{{{*/
39 // ---------------------------------------------------------------------
41 pkgPackageManager::~pkgPackageManager()
47 // PM::GetArchives - Puts the install archives in the aquire list /*{{{*/
48 // ---------------------------------------------------------------------
49 /* The Source list is used to convert the packages to install into
50 URNs which are then passed to Aquire to convert to FileNames. */
51 bool pkgPackageManager::GetArchives(pkgSourceList
&List
,pkgAquire
&Engine
)
53 pkgControlCache
CCache(Cache
);
54 if (_error
->PendingError() == true)
57 Engine
.OutputDir(PKG_DEB_CA_ARCHIVES
);
58 pkgCache::PkgIterator I
= Cache
.PkgBegin();
59 for (;I
.end() != true; I
++)
62 if ((Cache
[I
].InstallVer
== (pkgCache::Version
*)I
.CurrentVer() &&
63 I
.State() != pkgCache::PkgIterator::NeedsUnpack
) ||
64 Cache
[I
].Delete() == true)
67 // Cross match with the source list.
68 pkgSourceList::const_iterator Dist
= List
.MatchPkgFile(Cache
[I
].InstVerIter(Cache
));
69 if (Dist
== List
.end())
71 _error
->Warning("Couldn't locate an archive source for package %s",I
.Name());
75 // Read in the info record
76 pkgSPkgCtrlInfo Inf
= CCache
[Cache
[I
].InstVerIter(Cache
)];
77 if (Inf
.isNull() == true)
79 _error
->Warning("Couldn't locate info for package %s",I
.Name());
83 // Isolate the filename
84 string File
= Inf
->Find("Filename")->Value();
85 if (File
.empty() == true)
87 _error
->Warning("Couldn't locate an archive for package %s",I
.Name());
91 // Generate the get request.
92 string URI
= Dist
->ArchiveURI(File
);
95 unsigned int Pos
= File
.rfind('/');
96 if (Pos
== File
.length())
97 return _error
->Error("Malformed file line in package %s",I
.Name());
99 // Null pos isnt used in present package files
100 if (Pos
== string::npos
)
105 if (Engine
.Get(URI
,string(File
,Pos
),
106 Dist
->ArchiveInfo(Cache
[I
].InstVerIter(Cache
)),
107 Cache
[I
].InstVerIter(Cache
)->Size
,
108 Inf
->Find("MD5sum")->Value(),
109 &FileNames
[I
->ID
]) == false)
116 // PM::FixMissing - Keep all missing packages /*{{{*/
117 // ---------------------------------------------------------------------
118 /* This is called to correct the installation when packages could not
120 bool pkgPackageManager::FixMissing()
122 unsigned char *Touch
= new unsigned char[Cache
.Head().PackageCount
];
123 for (PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
125 // Create the status list that ResolveConflicts needs
126 if ((Cache
[I
].DepState
& pkgDepCache::DepNowMin
) == pkgDepCache::DepNowMin
)
127 Touch
[I
->ID
] = (1 << 0) | (1 << 1);
129 Touch
[I
->ID
] = 1 << 1;
131 if (Cache
[I
].Keep() == true)
133 if (FileNames
[I
->ID
].empty() == false || Cache
[I
].Delete() == true)
138 // Now downgrade everything that is broken
139 Cache
.ResolveConflicts(Touch
);
142 return Cache
.BrokenCount() == 0;
146 // PM::DepAlwaysTrue - Returns true if this dep is irrelevent /*{{{*/
147 // ---------------------------------------------------------------------
148 /* The restriction on provides is to eliminate the case when provides
149 are transitioning between valid states [ie exim to smail] */
150 bool pkgPackageManager::DepAlwaysTrue(DepIterator D
)
152 if (D
.TargetPkg()->ProvidesList
!= 0)
155 if ((Cache
[D
] & pkgDepCache::DepInstall
) != 0 &&
156 (Cache
[D
] & pkgDepCache::DepNow
) != 0)
161 // PM::CheckRConflicts - Look for reverse conflicts /*{{{*/
162 // ---------------------------------------------------------------------
163 /* This looks over the reverses for a conflicts line that needs early
165 bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg
,DepIterator D
,
168 for (;D
.end() == false; D
++)
170 if (D
->Type
!= pkgDEP_Conflicts
)
173 if (D
.ParentPkg() == Pkg
)
176 if (pkgCheckDep(D
.TargetVer(),Ver
,D
->CompareOp
) == false)
179 if (List
->IsNow(Pkg
) == false)
182 if (EarlyRemove(D
.ParentPkg()) == false)
188 // PM::ConfigureAll - Run the all out configuration /*{{{*/
189 // ---------------------------------------------------------------------
190 /* This configures every package. It is assumed they are all unpacked and
191 that the final configuration is valid. */
192 bool pkgPackageManager::ConfigureAll()
194 pkgOrderList
OList(Cache
);
196 // Populate the order list
197 for (pkgOrderList::iterator I
= List
->begin(); I
!= List
->end(); I
++)
198 if (List
->IsFlag(pkgCache::PkgIterator(Cache
,*I
),
199 pkgOrderList::UnPacked
) == true)
202 if (OList
.OrderConfigure() == false)
205 // Perform the configuring
206 for (pkgOrderList::iterator I
= OList
.begin(); I
!= OList
.end(); I
++)
208 PkgIterator
Pkg(Cache
,*I
);
210 if (Configure(Pkg
) == false)
213 List
->Flag(Pkg
,pkgOrderList::Configured
,pkgOrderList::States
);
219 // PM::SmartConfigure - Perform immediate configuration of the pkg /*{{{*/
220 // ---------------------------------------------------------------------
221 /* This routine scheduals the configuration of the given package and all
222 of it's dependents. */
223 bool pkgPackageManager::SmartConfigure(PkgIterator Pkg
)
225 pkgOrderList
OList(Cache
);
227 if (DepAdd(OList
,Pkg
) == false)
230 if (OList
.OrderConfigure() == false)
233 // Perform the configuring
234 for (pkgOrderList::iterator I
= OList
.begin(); I
!= OList
.end(); I
++)
236 PkgIterator
Pkg(Cache
,*I
);
238 if (Configure(Pkg
) == false)
241 List
->Flag(Pkg
,pkgOrderList::Configured
,pkgOrderList::States
);
245 if (List
->IsFlag(Pkg
,pkgOrderList::Configured
) == false)
246 return _error
->Error("Internal error, could not immediate configure %s",Pkg
.Name());
251 // PM::DepAdd - Add all dependents to the oder list /*{{{*/
252 // ---------------------------------------------------------------------
253 /* This recursively adds all dependents to the order list */
254 bool pkgPackageManager::DepAdd(pkgOrderList
&OList
,PkgIterator Pkg
,int Depth
)
256 if (OList
.IsFlag(Pkg
,pkgOrderList::Added
) == true)
258 if (List
->IsFlag(Pkg
,pkgOrderList::Configured
) == true)
260 if (List
->IsFlag(Pkg
,pkgOrderList::UnPacked
) == false)
264 // Put the package on the list
265 OList
.push_back(Pkg
);
266 OList
.Flag(Pkg
,pkgOrderList::Added
);
269 // Check the dependencies to see if they are all satisfied.
271 for (DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList(); D
.end() == false;)
273 if (D
->Type
!= pkgDEP_Depends
&& D
->Type
!= pkgDEP_PreDepends
)
281 for (bool LastOR
= true; D
.end() == false && LastOR
== true; D
++)
283 LastOR
= (D
->CompareOp
& pkgOP_OR
) == pkgOP_OR
;
288 Version
**VList
= D
.AllTargets();
289 for (Version
**I
= VList
; *I
!= 0 && Bad
== true; I
++)
291 VerIterator
Ver(Cache
,*I
);
292 PkgIterator Pkg
= Ver
.ParentPkg();
294 // See if the current version is ok
295 if (Pkg
.CurrentVer() == Ver
&& List
->IsNow(Pkg
) == true &&
296 Pkg
.State() == PkgIterator::NeedsNothing
)
302 // Not the install version
303 if (Cache
[Pkg
].InstallVer
!= *I
||
304 (Cache
[Pkg
].Keep() == true && Pkg
.State() == PkgIterator::NeedsNothing
))
306 if (List
->IsFlag(Pkg
,pkgOrderList::UnPacked
) == true)
307 Bad
= !DepAdd(OList
,Pkg
,Depth
);
308 if (List
->IsFlag(Pkg
,pkgOrderList::Configured
) == true)
316 OList
.Flag(Pkg
,0,pkgOrderList::Added
);
327 // PM::EarlyRemove - Perform removal of packages before their time /*{{{*/
328 // ---------------------------------------------------------------------
329 /* This is called to deal with conflicts arising from unpacking */
330 bool pkgPackageManager::EarlyRemove(PkgIterator Pkg
)
332 if (List
->IsNow(Pkg
) == false)
335 // Already removed it
336 if (List
->IsFlag(Pkg
,pkgOrderList::Removed
) == true)
339 // Woops, it will not be re-installed!
340 if (List
->IsFlag(Pkg
,pkgOrderList::InList
) == false)
343 bool Res
= SmartRemove(Pkg
);
344 if (Cache
[Pkg
].Delete() == false)
345 List
->Flag(Pkg
,pkgOrderList::Removed
,pkgOrderList::States
);
350 // PM::SmartRemove - Removal Helper /*{{{*/
351 // ---------------------------------------------------------------------
353 bool pkgPackageManager::SmartRemove(PkgIterator Pkg
)
355 if (List
->IsNow(Pkg
) == false)
358 List
->Flag(Pkg
,pkgOrderList::Configured
,pkgOrderList::States
);
362 // PM::SmartUnPack - Install helper /*{{{*/
363 // ---------------------------------------------------------------------
364 /* This performs the task of handling pre-depends. */
365 bool pkgPackageManager::SmartUnPack(PkgIterator Pkg
)
367 // Check if it is already unpacked
368 if (Pkg
.State() == pkgCache::PkgIterator::NeedsConfigure
&&
369 Cache
[Pkg
].Keep() == true)
371 List
->Flag(Pkg
,pkgOrderList::UnPacked
,pkgOrderList::States
);
372 if (List
->IsFlag(Pkg
,pkgOrderList::Immediate
) == true)
373 if (SmartConfigure(Pkg
) == false)
374 return _error
->Error("Internal Error, Could not perform immediate configuraton");
378 /* See if this packages install version has any predependencies
379 that are not met by 'now' packages. */
380 for (DepIterator D
= Cache
[Pkg
].InstVerIter(Cache
).DependsList();
381 D
.end() == false; D
++)
383 if (D
->Type
== pkgDEP_PreDepends
)
385 // Look for possible ok targets.
386 Version
**VList
= D
.AllTargets();
388 for (Version
**I
= VList
; *I
!= 0 && Bad
== true; I
++)
390 VerIterator
Ver(Cache
,*I
);
391 PkgIterator Pkg
= Ver
.ParentPkg();
393 // See if the current version is ok
394 if (Pkg
.CurrentVer() == Ver
&& List
->IsNow(Pkg
) == true &&
395 Pkg
.State() == PkgIterator::NeedsNothing
)
402 // Look for something that could be configured.
403 for (Version
**I
= VList
; *I
!= 0 && Bad
== true; I
++)
405 VerIterator
Ver(Cache
,*I
);
406 PkgIterator Pkg
= Ver
.ParentPkg();
408 // Not the install version
409 if (Cache
[Pkg
].InstallVer
!= *I
||
410 (Cache
[Pkg
].Keep() == true && Pkg
.State() == PkgIterator::NeedsNothing
))
413 Bad
= !SmartConfigure(Pkg
);
419 return _error
->Error("Internal Error, Couldn't configure a pre-depend");
424 if (D
->Type
== pkgDEP_Conflicts
)
426 /* Look for conflicts. Two packages that are both in the install
427 state cannot conflict so we don't check.. */
428 Version
**VList
= D
.AllTargets();
429 for (Version
**I
= VList
; *I
!= 0; I
++)
431 VerIterator
Ver(Cache
,*I
);
432 PkgIterator Pkg
= Ver
.ParentPkg();
434 // See if the current version is conflicting
435 if (Pkg
.CurrentVer() == Ver
&& List
->IsNow(Pkg
) == true)
437 if (EarlyRemove(Pkg
) == false)
438 return _error
->Error("Internal Error, Could not early remove %s",Pkg
.Name());
445 // Check for reverse conflicts.
446 CheckRConflicts(Pkg
,Pkg
.RevDependsList(),
447 Cache
[Pkg
].InstVerIter(Cache
).VerStr());
448 for (PrvIterator P
= Cache
[Pkg
].InstVerIter(Cache
).ProvidesList();
449 P
.end() == false; P
++)
450 CheckRConflicts(Pkg
,P
.ParentPkg().RevDependsList(),P
.ProvideVersion());
452 if (Install(Pkg
,FileNames
[Pkg
->ID
]) == false)
455 List
->Flag(Pkg
,pkgOrderList::UnPacked
,pkgOrderList::States
);
457 // Perform immedate configuration of the package.
458 if (List
->IsFlag(Pkg
,pkgOrderList::Immediate
) == true)
459 if (SmartConfigure(Pkg
) == false)
460 return _error
->Error("Internal Error, Could not perform immediate configuraton");
465 // PM::OrderInstall - Installation ordering routine /*{{{*/
466 // ---------------------------------------------------------------------
468 bool pkgPackageManager::OrderInstall()
471 List
= new pkgOrderList(Cache
);
473 // Generate the list of affected packages and sort it
474 for (PkgIterator I
= Cache
.PkgBegin(); I
.end() == false; I
++)
476 // Consider all depends
477 if ((I
->Flags
& pkgFLAG_Essential
) == pkgFLAG_Essential
)
479 List
->Flag(I
,pkgOrderList::Immediate
);
480 if (Cache
[I
].InstallVer
!= 0)
481 for (DepIterator D
= Cache
[I
].InstVerIter(Cache
).DependsList();
482 D
.end() == false; D
++)
483 if (D
->Type
== pkgDEP_Depends
|| D
->Type
== pkgDEP_PreDepends
)
484 List
->Flag(D
.TargetPkg(),pkgOrderList::Immediate
);
485 if (I
->CurrentVer
!= 0)
486 for (DepIterator D
= I
.CurrentVer().DependsList();
487 D
.end() == false; D
++)
488 if (D
->Type
== pkgDEP_Depends
|| D
->Type
== pkgDEP_PreDepends
)
489 List
->Flag(D
.TargetPkg(),pkgOrderList::Immediate
);
493 if ((Cache
[I
].Keep() == true ||
494 Cache
[I
].InstVerIter(Cache
) == I
.CurrentVer()) &&
495 I
.State() == pkgCache::PkgIterator::NeedsNothing
)
498 // Append it to the list
501 if ((I
->Flags
& pkgFLAG_ImmediateConf
) == pkgFLAG_ImmediateConf
)
502 List
->Flag(I
,pkgOrderList::Immediate
);
505 if (List
->OrderUnpack() == false)
506 return _error
->Error("Internal ordering error");
508 for (pkgOrderList::iterator I
= List
->begin(); I
!= List
->end(); I
++)
510 PkgIterator
Pkg(Cache
,*I
);
513 if (Cache
[Pkg
].Keep() == true && Pkg
.State() == pkgCache::PkgIterator::NeedsNothing
)
514 return _error
->Error("Internal Error, trying to manipulate a kept package");
516 // Perform a delete or an install
517 if (Cache
[Pkg
].Delete() == true)
519 if (SmartRemove(Pkg
) == false)
523 if (SmartUnPack(Pkg
) == false)
527 // Final run through the configure phase
528 if (ConfigureAll() == false)
532 for (pkgOrderList::iterator I
= List
->begin(); I
!= List
->end(); I
++)
533 if (List
->IsFlag(*I
,pkgOrderList::Configured
) == false)
534 return _error
->Error("Internal error, packages left unconfigured. %s",
535 PkgIterator(Cache
,*I
).Name());
540 // PM::DoInstall - Does the installation /*{{{*/
541 // ---------------------------------------------------------------------
542 /* This uses the filenames in FileNames and the information in the
543 DepCache to perform the installation of packages.*/
544 bool pkgPackageManager::DoInstall()
546 return OrderInstall() && Go();