// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: apt-get.cc,v 1.80 1999/10/18 00:37:35 jgg Exp $
+// $Id: apt-get.cc,v 1.83 1999/10/22 05:58:54 jgg Exp $
/* ######################################################################
apt-get - Cover for dpkg
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <regex.h>
#include <sys/wait.h>
/*}}}*/
// Print out each package and the failed dependencies
out <<" " << I.Name() << ":";
- int Indent = strlen(I.Name()) + 3;
+ unsigned Indent = strlen(I.Name()) + 3;
bool First = true;
if (Cache[I].InstVerIter(Cache).end() == true)
{
if (Cache->IsImportantDep(End) == false ||
(Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
continue;
-
- if (First == false)
- for (int J = 0; J != Indent; J++)
- out << ' ';
- First = false;
- out << ' ' << End.DepType() << ": " << End.TargetPkg().Name();
-
- // Show a quick summary of the version requirements
- if (End.TargetVer() != 0)
- out << " (" << End.CompType() << " " << End.TargetVer() <<
- ")";
-
- /* Show a summary of the target package if possible. In the case
- of virtual packages we show nothing */
- pkgCache::PkgIterator Targ = End.TargetPkg();
- if (Targ->ProvidesList == 0)
+ bool FirstOr = true;
+ while (1)
{
- out << " but ";
- pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
- if (Ver.end() == false)
- out << Ver.VerStr() << (Now?" is installed":" is to be installed");
+ if (First == false)
+ for (unsigned J = 0; J != Indent; J++)
+ out << ' ';
+ First = false;
+
+ if (FirstOr == false)
+ {
+ for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
+ out << ' ';
+ }
else
+ out << ' ' << End.DepType() << ": ";
+ FirstOr = false;
+
+ out << Start.TargetPkg().Name();
+
+ // Show a quick summary of the version requirements
+ if (Start.TargetVer() != 0)
+ out << " (" << Start.CompType() << " " << Start.TargetVer() <<
+ ")";
+
+ /* Show a summary of the target package if possible. In the case
+ of virtual packages we show nothing */
+ pkgCache::PkgIterator Targ = Start.TargetPkg();
+ if (Targ->ProvidesList == 0)
{
- if (Cache[Targ].CandidateVerIter(Cache).end() == true)
+ out << " but ";
+ pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
+ if (Ver.end() == false)
+ out << Ver.VerStr() << (Now?" is installed":" is to be installed");
+ else
{
- if (Targ->ProvidesList == 0)
- out << "it is not installable";
+ if (Cache[Targ].CandidateVerIter(Cache).end() == true)
+ {
+ if (Targ->ProvidesList == 0)
+ out << "it is not installable";
+ else
+ out << "it is a virtual package";
+ }
else
- out << "it is a virtual package";
- }
- else
- out << (Now?"it is not installed":"it is not going to be installed");
- }
- }
-
- out << endl;
+ out << (Now?"it is not installed":"it is not going to be installed");
+ }
+ }
+
+ if (Start != End)
+ cout << " or";
+ out << endl;
+
+ if (Start == End)
+ break;
+ Start++;
+ }
}
}
}
{
unsigned long Upgrade = 0;
unsigned long Install = 0;
+ unsigned long ReInstall = 0;
for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
{
if (Dep[I].NewInstall() == true)
else
if (Dep[I].Upgrade() == true)
Upgrade++;
+ if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
+ ReInstall++;
}
out << Upgrade << " packages upgraded, " <<
- Install << " newly installed, " <<
- Dep.DelCount() << " to remove and " <<
+ Install << " newly installed, ";
+ if (ReInstall != 0)
+ out << ReInstall << " reinstalled, ";
+ out << Dep.DelCount() << " to remove and " <<
Dep.KeepCount() << " not upgraded." << endl;
if (Dep.BadCount() != 0)
return _error->Error("Internal Error, InstallPackages was called with broken packages!");
}
- if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+ if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
Cache->BadCount() == 0)
return true;
}
}
/*}}}*/
+// TryToInstall - Try to install a single package /*{{{*/
+// ---------------------------------------------------------------------
+/* This used to be inlined in DoInstall, but with the advent of regex package
+ name matching it was split out.. */
+bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
+ pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
+ unsigned int &ExpectedInst,bool AllowFail = true)
+{
+ /* This is a pure virtual package and there is a single available
+ provides */
+ if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
+ Pkg.ProvidesList()->NextProvides == 0)
+ {
+ pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
+ c1out << "Note, installing " << Tmp.Name() << " instead of " << Pkg.Name() << endl;
+ Pkg = Tmp;
+ }
+
+ // Handle the no-upgrade case
+ if (_config->FindB("APT::Get::no-upgrade",false) == true &&
+ Pkg->CurrentVer != 0)
+ {
+ if (AllowFail == true)
+ c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
+ return true;
+ }
+
+ // Check if there is something at all to install
+ pkgDepCache::StateCache &State = Cache[Pkg];
+ if (State.CandidateVer == 0)
+ {
+ if (AllowFail == false)
+ return false;
+
+ if (Pkg->ProvidesList != 0)
+ {
+ c1out << "Package " << Pkg.Name() << " is a virtual package provided by:" << endl;
+
+ pkgCache::PrvIterator I = Pkg.ProvidesList();
+ for (; I.end() == false; I++)
+ {
+ pkgCache::PkgIterator Pkg = I.OwnerPkg();
+
+ if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
+ {
+ if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
+ c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
+ " [Installed]"<< endl;
+ else
+ c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
+ }
+ }
+ c1out << "You should explicitly select one to install." << endl;
+ }
+ else
+ {
+ c1out << "Package " << Pkg.Name() << " has no available version, but exists in the database." << endl;
+ c1out << "This typically means that the package was mentioned in a dependency and " << endl;
+ c1out << "never uploaded, or that it is an obsolete package." << endl;
+
+ string List;
+ pkgCache::DepIterator Dep = Pkg.RevDependsList();
+ for (; Dep.end() == false; Dep++)
+ {
+ if (Dep->Type != pkgCache::Dep::Replaces)
+ continue;
+ List += string(Dep.ParentPkg().Name()) + " ";
+ }
+ ShowList(c1out,"However the following packages replace it:",List);
+ }
+
+ _error->Error("Package %s has no installation candidate",Pkg.Name());
+ return false;
+ }
+
+ Fix.Protect(Pkg);
+ if (Remove == true)
+ {
+ Fix.Remove(Pkg);
+ Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
+ return true;
+ }
+
+ // Install it
+ Cache.MarkInstall(Pkg,false);
+ if (State.Install() == false)
+ {
+ if (_config->FindB("APT::Get::ReInstall",false) == true)
+ {
+ if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
+ c1out << "Sorry, re-installation of " << Pkg.Name() << " is not possible, it cannot be downloaded" << endl;
+ else
+ Cache.SetReInstall(Pkg,true);
+ }
+ else
+ {
+ if (AllowFail == true)
+ c1out << "Sorry, " << Pkg.Name() << " is already the newest version" << endl;
+ }
+ }
+ else
+ ExpectedInst++;
+
+ // Install it with autoinstalling enabled.
+ if (State.InstBroken() == true && BrokenFix == false)
+ Cache.MarkInstall(Pkg,true);
+ return true;
+}
+ /*}}}*/
// DoUpdate - Update the package lists /*{{{*/
// ---------------------------------------------------------------------
pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
Packages++;
if (Pkg.end() == true)
- return _error->Error("Couldn't find package %s",S);
-
- // Handle the no-upgrade case
- if (_config->FindB("APT::Get::no-upgrade",false) == true &&
- Pkg->CurrentVer != 0)
- {
- c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
- continue;
- }
-
- // Check if there is something new to install
- pkgDepCache::StateCache &State = (*Cache)[Pkg];
- if (State.CandidateVer == 0)
{
- if (Pkg->ProvidesList != 0)
- {
- c1out << "Package " << S << " is a virtual package provided by:" << endl;
-
- pkgCache::PrvIterator I = Pkg.ProvidesList();
- for (; I.end() == false; I++)
- {
- pkgCache::PkgIterator Pkg = I.OwnerPkg();
-
- if ((*Cache)[Pkg].CandidateVerIter(*Cache) == I.OwnerVer())
- {
- if ((*Cache)[Pkg].Install() == true && (*Cache)[Pkg].NewInstall() == false)
- c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
- " [Installed]"<< endl;
- else
- c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
- }
- }
- c1out << "You should explicly select one to install." << endl;
- }
- else
+ // Check if the name is a regex
+ const char *I;
+ for (I = S; *I != 0; I++)
+ if (*I == '.' || *I == '?' || *I == '*')
+ break;
+ if (*I == 0)
+ return _error->Error("Couldn't find package %s",S);
+
+ // Regexs must always be confirmed
+ ExpectedInst += 1000;
+
+ // Compile the regex pattern
+ regex_t Pattern;
+ if (regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
+ REG_NOSUB) != 0)
+ return _error->Error("Regex compilation error");
+
+ // Run over the matches
+ bool Hit = false;
+ for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
{
- c1out << "Package " << S << " has no available version, but exists in the database." << endl;
- c1out << "This typically means that the package was mentioned in a dependency and " << endl;
- c1out << "never uploaded, or that it is an obsolete package." << endl;
+ if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
+ continue;
- string List;
- pkgCache::DepIterator Dep = Pkg.RevDependsList();
- for (; Dep.end() == false; Dep++)
- {
- if (Dep->Type != pkgCache::Dep::Replaces)
- continue;
- List += string(Dep.ParentPkg().Name()) + " ";
- }
- ShowList(c1out,"However the following packages replace it:",List);
+ Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
+ ExpectedInst,false);
}
+ regfree(&Pattern);
- return _error->Error("Package %s has no installation candidate",S);
- }
-
- Fix.Protect(Pkg);
- if (Remove == true)
- {
- Fix.Remove(Pkg);
- Cache->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
- continue;
+ if (Hit == false)
+ return _error->Error("Couldn't find package %s",S);
}
-
- // Install it
- Cache->MarkInstall(Pkg,false);
- if (State.Install() == false)
- c1out << "Sorry, " << S << " is already the newest version" << endl;
else
- ExpectedInst++;
-
- // Install it with autoinstalling enabled.
- if (State.InstBroken() == true && BrokenFix == false)
- Cache->MarkInstall(Pkg,true);
+ {
+ if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
+ return false;
+ }
}
/* If we are in the Broken fixing mode we do not attempt to fix the
{0,"tar-only","APT::Get::tar-Only",0},
{0,"purge","APT::Get::Purge",0},
{0,"list-cleanup","APT::Get::List-Cleanup",0},
+ {0,"reinstall","APT::Get::ReInstall",0},
{'c',"config-file",0,CommandLine::ConfigFile},
{'o',"option",0,CommandLine::ArbItem},
{0,0,0,0}};