+ // Read the source list
+ pkgSourceList List;
+ if (List.ReadMainList() == false)
+ return _error->Error(_("The list of sources could not be read."));
+
+ // Create the text record parsers
+ pkgRecords Recs(Cache);
+ pkgSrcRecords SrcRecs(List);
+ if (_error->PendingError() == true)
+ return false;
+
+ // Create the download object
+ AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
+ pkgAcquire Fetcher(&Stat);
+
+ unsigned J = 0;
+ for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
+ {
+ string Src;
+ pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
+ if (Last == 0)
+ return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
+
+ // Process the build-dependencies
+ vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
+ if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
+ return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
+
+ // Also ensure that build-essential packages are present
+ Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
+ if (Opts)
+ Opts = Opts->Child;
+ for (; Opts; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+
+ pkgSrcRecords::Parser::BuildDepRec rec;
+ rec.Package = Opts->Value;
+ rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
+ rec.Op = 0;
+ BuildDeps.insert(BuildDeps.begin(), rec);
+ }
+
+ if (BuildDeps.size() == 0)
+ {
+ ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
+ continue;
+ }
+
+ // Install the requested packages
+ unsigned int ExpectedInst = 0;
+ vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
+ pkgProblemResolver Fix(Cache);
+ for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
+ {
+ if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
+ (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
+ {
+ pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
+ // Build-conflicts on unknown packages are silently ignored
+ if (Pkg.end() == true)
+ continue;
+
+ pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
+
+ /*
+ * Remove if we have an installed version that satisfies the
+ * version criteria
+ */
+ if (IV.end() == false &&
+ Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
+ TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
+ }
+ else // BuildDep || BuildDepIndep
+ {
+ pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
+ if (Pkg.end() == true)
+ {
+ // Check if there are any alternatives
+ if (((*D).Op & pkgCache::Dep::Or) != pkgCache::Dep::Or)
+ return _error->Error(_("%s dependency on %s cannot be satisfied "
+ "because the package %s cannot be found"),
+ Last->BuildDepType((*D).Type),Src.c_str(),
+ (*D).Package.c_str());
+ // Try the next alternative
+ continue;
+ }
+
+ /*
+ * if there are alternatives, we've already picked one, so skip
+ * the rest
+ *
+ * TODO: this means that if there's a build-dep on A|B and B is
+ * installed, we'll still try to install A; more importantly,
+ * if A is currently broken, we cannot go back and try B. To fix
+ * this would require we do a Resolve cycle for each package we
+ * add to the install list. Ugh
+ */
+ while (D != BuildDeps.end() &&
+ (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or))
+ D++;
+
+ // Get installed versions
+ pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
+
+ /*
+ * If this is a virtual package, we need to check the list of
+ * packages that provide it and see if any of those are
+ * installed
+ */
+ pkgCache::PrvIterator Prv = Pkg.ProvidesList();
+ for (; Prv.end() != true; Prv++)
+ if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
+ break;
+
+ /*
+ * TODO: if we depend on a version lower than what we already have
+ * installed it is not clear what should be done; in practice
+ * this case should be rare, and right now nothing is
+ * done about it :-(
+ */
+ if (Prv.end() == true && // Nothing provides it; and
+ (IV.end() == true || // It is not installed, or
+ Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == false))
+ // the version installed doesn't
+ // satisfy constraints
+ TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst);
+ }
+ }
+
+ Fix.InstallProtect();
+ if (Fix.Resolve(true) == false)
+ _error->Discard();
+
+ // Now we check the state of the packages,
+ if (Cache->BrokenCount() != 0)
+ return _error->Error(_("Some broken packages were found while trying to process build-dependencies.\n"
+ "You might want to run `apt-get -f install' to correct these."));
+ }
+
+ if (InstallPackages(Cache, false, true) == false)
+ return _error->Error(_("Failed to process build dependencies"));