1 // Include Files /*{{{*/
4 #include <apt-pkg/acquire-item.h>
5 #include <apt-pkg/acquire.h>
6 #include <apt-pkg/algorithms.h>
7 #include <apt-pkg/aptconfiguration.h>
8 #include <apt-pkg/cachefile.h>
9 #include <apt-pkg/cacheiterators.h>
10 #include <apt-pkg/cacheset.h>
11 #include <apt-pkg/cmndline.h>
12 #include <apt-pkg/configuration.h>
13 #include <apt-pkg/depcache.h>
14 #include <apt-pkg/error.h>
15 #include <apt-pkg/fileutl.h>
16 #include <apt-pkg/hashes.h>
17 #include <apt-pkg/indexfile.h>
18 #include <apt-pkg/metaindex.h>
19 #include <apt-pkg/pkgcache.h>
20 #include <apt-pkg/sourcelist.h>
21 #include <apt-pkg/srcrecords.h>
22 #include <apt-pkg/strutl.h>
23 #include <apt-pkg/version.h>
24 #include <apt-pkg/policy.h>
26 #include <apt-private/private-cachefile.h>
27 #include <apt-private/private-cacheset.h>
28 #include <apt-private/private-download.h>
29 #include <apt-private/private-install.h>
30 #include <apt-private/private-source.h>
32 #include <apt-pkg/debindexfile.h>
50 // GetReleaseFileForSourceRecord - Return Suite for the given srcrecord /*{{{*/
51 static pkgCache::RlsFileIterator
GetReleaseFileForSourceRecord(CacheFile
&CacheFile
,
52 pkgSourceList
const * const SrcList
, pkgSrcRecords::Parser
const * const Parse
)
54 // try to find release
55 const pkgIndexFile
& CurrentIndexFile
= Parse
->Index();
57 for (pkgSourceList::const_iterator S
= SrcList
->begin();
58 S
!= SrcList
->end(); ++S
)
60 std::vector
<pkgIndexFile
*> *Indexes
= (*S
)->GetIndexFiles();
61 for (std::vector
<pkgIndexFile
*>::const_iterator IF
= Indexes
->begin();
62 IF
!= Indexes
->end(); ++IF
)
64 if (&CurrentIndexFile
== (*IF
))
65 return (*S
)->FindInCache(CacheFile
, false);
68 return pkgCache::RlsFileIterator(CacheFile
);
71 // FindSrc - Find a source record /*{{{*/
72 static pkgSrcRecords::Parser
*FindSrc(const char *Name
,
73 pkgSrcRecords
&SrcRecs
,std::string
&Src
,
76 std::string VerTag
, UserRequestedVerTag
;
77 std::string ArchTag
= "";
78 std::string RelTag
= _config
->Find("APT::Default-Release");
79 std::string TmpSrc
= Name
;
82 size_t found
= TmpSrc
.find_last_of("/");
83 if (found
!= std::string::npos
)
85 RelTag
= TmpSrc
.substr(found
+1);
86 TmpSrc
= TmpSrc
.substr(0,found
);
88 // extract the version
89 found
= TmpSrc
.find_last_of("=");
90 if (found
!= std::string::npos
)
92 VerTag
= UserRequestedVerTag
= TmpSrc
.substr(found
+1);
93 TmpSrc
= TmpSrc
.substr(0,found
);
96 found
= TmpSrc
.find_last_of(":");
97 if (found
!= std::string::npos
)
99 ArchTag
= TmpSrc
.substr(found
+1);
100 TmpSrc
= TmpSrc
.substr(0,found
);
103 /* Lookup the version of the package we would install if we were to
104 install a version and determine the source package name, then look
105 in the archive for a source package of the same name. */
106 bool MatchSrcOnly
= _config
->FindB("APT::Get::Only-Source");
107 pkgCache::PkgIterator Pkg
;
109 Pkg
= Cache
.GetPkgCache()->FindPkg(TmpSrc
, ArchTag
);
111 Pkg
= Cache
.GetPkgCache()->FindPkg(TmpSrc
);
113 // if we can't find a package but the user qualified with a arch,
115 if (Pkg
.end() && ArchTag
!= "")
118 _error
->Error(_("Can not find a package for architecture '%s'"),
123 if (MatchSrcOnly
== false && Pkg
.end() == false)
125 if(VerTag
!= "" || RelTag
!= "" || ArchTag
!= "")
128 // we have a default release, try to locate the pkg. we do it like
129 // this because GetCandidateVer() will not "downgrade", that means
130 // "apt-get source -t stable apt" won't work on a unstable system
131 for (pkgCache::VerIterator Ver
= Pkg
.VersionList();; ++Ver
)
133 // try first only exact matches, later fuzzy matches
134 if (Ver
.end() == true)
139 Ver
= Pkg
.VersionList();
140 // exit right away from the Pkg.VersionList() loop if we
141 // don't have any versions
142 if (Ver
.end() == true)
146 // ignore arches that are not for us
147 if (ArchTag
!= "" && Ver
.Arch() != ArchTag
)
150 // pick highest version for the arch unless the user wants
152 if (ArchTag
!= "" && VerTag
== "" && RelTag
== "")
153 if(Cache
.GetPkgCache()->VS
->CmpVersion(VerTag
, Ver
.VerStr()) < 0)
154 VerTag
= Ver
.VerStr();
156 // We match against a concrete version (or a part of this version)
157 if (VerTag
.empty() == false &&
158 (fuzzy
== true || Cache
.GetPkgCache()->VS
->CmpVersion(VerTag
, Ver
.VerStr()) != 0) && // exact match
159 (fuzzy
== false || strncmp(VerTag
.c_str(), Ver
.VerStr(), VerTag
.size()) != 0)) // fuzzy match
162 for (pkgCache::VerFileIterator VF
= Ver
.FileList();
163 VF
.end() == false; ++VF
)
165 /* If this is the status file, and the current version is not the
166 version in the status file (ie it is not installed, or somesuch)
167 then it is not a candidate for installation, ever. This weeds
168 out bogus entries that may be due to config-file states, or
170 if ((VF
.File()->Flags
& pkgCache::Flag::NotSource
) ==
171 pkgCache::Flag::NotSource
&& Pkg
.CurrentVer() != Ver
)
174 // or we match against a release
175 if(VerTag
.empty() == false ||
176 (VF
.File().Archive() != 0 && VF
.File().Archive() == RelTag
) ||
177 (VF
.File().Codename() != 0 && VF
.File().Codename() == RelTag
))
179 // the Version we have is possibly fuzzy or includes binUploads,
180 // so we use the Version of the SourcePkg (empty if same as package)
181 Src
= Ver
.SourcePkgName();
182 VerTag
= Ver
.SourceVerStr();
186 if (Src
.empty() == false)
191 if (Src
.empty() == true && ArchTag
.empty() == false)
193 if (VerTag
.empty() == false)
194 _error
->Error(_("Can not find a package '%s' with version '%s'"),
195 Pkg
.FullName().c_str(), VerTag
.c_str());
196 if (RelTag
.empty() == false)
197 _error
->Error(_("Can not find a package '%s' with release '%s'"),
198 Pkg
.FullName().c_str(), RelTag
.c_str());
204 if (Src
.empty() == true)
206 // if we don't have found a fitting package yet so we will
207 // choose a good candidate and proceed with that.
208 // Maybe we will find a source later on with the right VerTag
210 if (Cache
.BuildPolicy() == false)
212 pkgPolicy
* Policy
= dynamic_cast<pkgPolicy
*>(Cache
.GetPolicy());
213 if (Policy
== nullptr)
215 _error
->Fatal("Implementation error: dynamic up-casting policy engine failed in FindSrc!");
218 pkgCache::VerIterator
const Ver
= Policy
->GetCandidateVer(Pkg
);
219 if (Ver
.end() == false)
221 if (strcmp(Ver
.SourcePkgName(),Ver
.ParentPkg().Name()) != 0)
222 Src
= Ver
.SourcePkgName();
223 if (VerTag
.empty() == true && strcmp(Ver
.SourceVerStr(),Ver
.VerStr()) != 0)
224 VerTag
= Ver
.SourceVerStr();
229 if (Src
.empty() == true)
235 /* if we have a source pkg name, make sure to only search
236 for srcpkg names, otherwise apt gets confused if there
237 is a binary package "pkg1" and a source package "pkg1"
238 with the same name but that comes from different packages */
242 ioprintf(c1out
, _("Picking '%s' as source package instead of '%s'\n"), Src
.c_str(), TmpSrc
.c_str());
247 pkgSrcRecords::Parser
*Last
= 0;
248 unsigned long Offset
= 0;
250 pkgSourceList
const * const SrcList
= Cache
.GetSourceList();
252 /* Iterate over all of the hits, which includes the resulting
253 binary packages in the search */
254 pkgSrcRecords::Parser
*Parse
;
258 while ((Parse
= SrcRecs
.Find(Src
.c_str(), MatchSrcOnly
)) != 0)
260 const std::string Ver
= Parse
->Version();
262 // See if we need to look for a specific release tag
263 if (RelTag
.empty() == false && UserRequestedVerTag
.empty() == true)
265 pkgCache::RlsFileIterator
const Rls
= GetReleaseFileForSourceRecord(Cache
, SrcList
, Parse
);
266 if (Rls
.end() == false)
268 if ((Rls
->Archive
!= 0 && RelTag
!= Rls
.Archive()) &&
269 (Rls
->Codename
!= 0 && RelTag
!= Rls
.Codename()))
274 // Ignore all versions which doesn't fit
275 if (VerTag
.empty() == false &&
276 Cache
.GetPkgCache()->VS
->CmpVersion(VerTag
, Ver
) != 0) // exact match
279 // Newer version or an exact match? Save the hit
280 if (Last
== 0 || Cache
.GetPkgCache()->VS
->CmpVersion(Version
,Ver
) < 0) {
282 Offset
= Parse
->Offset();
286 // was the version check above an exact match?
287 // If so, we don't need to look further
288 if (VerTag
.empty() == false && (VerTag
== Ver
))
291 if (UserRequestedVerTag
== "" && Version
!= "" && RelTag
!= "")
292 ioprintf(c1out
, "Selected version '%s' (%s) for %s\n",
293 Version
.c_str(), RelTag
.c_str(), Src
.c_str());
295 if (Last
!= 0 || VerTag
.empty() == true)
297 _error
->Error(_("Can not find version '%s' of package '%s'"), VerTag
.c_str(), TmpSrc
.c_str());
301 if (Last
== 0 || Last
->Jump(Offset
) == false)
307 // DoSource - Fetch a source archive /*{{{*/
308 // ---------------------------------------------------------------------
309 /* Fetch souce packages */
316 bool DoSource(CommandLine
&CmdL
)
318 if (CmdL
.FileSize() <= 1)
319 return _error
->Error(_("Must specify at least one package to fetch source for"));
322 if (Cache
.BuildCaches(false) == false)
325 // Create the text record parsers
326 pkgSourceList
* const List
= Cache
.GetSourceList();
327 pkgSrcRecords
SrcRecs(*List
);
328 if (_error
->PendingError() == true)
331 std::unique_ptr
<DscFile
[]> Dsc(new DscFile
[CmdL
.FileSize()]);
333 // insert all downloaded uris into this set to avoid downloading them
335 std::set
<std::string
> queued
;
337 // Diff only mode only fetches .diff files
338 bool const diffOnly
= _config
->FindB("APT::Get::Diff-Only", false);
339 // Tar only mode only fetches .tar files
340 bool const tarOnly
= _config
->FindB("APT::Get::Tar-Only", false);
341 // Dsc only mode only fetches .dsc files
342 bool const dscOnly
= _config
->FindB("APT::Get::Dsc-Only", false);
344 // Load the requestd sources into the fetcher
345 aptAcquireWithTextStatus Fetcher
;
347 std::vector
<std::string
> UntrustedList
;
348 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++, J
++)
351 pkgSrcRecords::Parser
*Last
= FindSrc(*I
,SrcRecs
,Src
,Cache
);
353 return _error
->Error(_("Unable to find a source package for %s"),Src
.c_str());
356 if (Last
->Index().IsTrusted() == false)
357 UntrustedList
.push_back(Src
);
359 std::string srec
= Last
->AsStr();
360 std::string::size_type pos
= srec
.find("\nVcs-");
361 while (pos
!= std::string::npos
)
363 pos
+= strlen("\nVcs-");
364 std::string vcs
= srec
.substr(pos
,srec
.find(":",pos
)-pos
);
367 pos
= srec
.find("\nVcs-", pos
);
370 pos
+= vcs
.length()+2;
371 std::string::size_type epos
= srec
.find("\n", pos
);
372 std::string
const uri
= srec
.substr(pos
,epos
-pos
);
373 ioprintf(c1out
, _("NOTICE: '%s' packaging is maintained in "
374 "the '%s' version control system at:\n"
376 Src
.c_str(), vcs
.c_str(), uri
.c_str());
379 vcscmd
= "bzr branch " + uri
;
380 else if (vcs
== "Git")
381 vcscmd
= "git clone " + uri
;
383 if (vcscmd
.empty() == false)
384 ioprintf(c1out
,_("Please use:\n%s\n"
385 "to retrieve the latest (possibly unreleased) "
386 "updates to the package.\n"),
392 std::vector
<pkgSrcRecords::File2
> Lst
;
393 if (Last
->Files2(Lst
) == false) {
397 // Load them into the fetcher
398 for (std::vector
<pkgSrcRecords::File2
>::const_iterator I
= Lst
.begin();
401 // Try to guess what sort of file it is we are getting.
402 if (I
->Type
== "dsc")
404 Dsc
[J
].Package
= Last
->Package();
405 Dsc
[J
].Version
= Last
->Version();
406 Dsc
[J
].Dsc
= flNotDir(I
->Path
);
409 // Handle the only options so that multiple can be used at once
410 if (diffOnly
== true || tarOnly
== true || dscOnly
== true)
412 if ((diffOnly
== true && I
->Type
== "diff") ||
413 (tarOnly
== true && I
->Type
== "tar") ||
414 (dscOnly
== true && I
->Type
== "dsc"))
415 ; // Fine, we want this file downloaded
420 // don't download the same uri twice (should this be moved to
421 // the fetcher interface itself?)
422 if(queued
.find(Last
->Index().ArchiveURI(I
->Path
)) != queued
.end())
424 queued
.insert(Last
->Index().ArchiveURI(I
->Path
));
426 // check if we have a file with that md5 sum already localy
427 std::string localFile
= flNotDir(I
->Path
);
428 if (FileExists(localFile
) == true)
429 if(I
->Hashes
.VerifyFile(localFile
) == true)
431 ioprintf(c1out
,_("Skipping already downloaded file '%s'\n"),
436 // see if we have a hash (Acquire::ForceHash is the only way to have none)
437 if (I
->Hashes
.usable() == false && _config
->FindB("APT::Get::AllowUnauthenticated",false) == false)
439 ioprintf(c1out
, "Skipping download of file '%s' as requested hashsum is not available for authentication\n",
445 new pkgAcqFile(&Fetcher
,Last
->Index().ArchiveURI(I
->Path
),
446 I
->Hashes
, I
->FileSize
, Last
->Index().SourceInfo(*Last
,*I
), Src
);
450 // Display statistics
451 unsigned long long FetchBytes
= Fetcher
.FetchNeeded();
452 unsigned long long FetchPBytes
= Fetcher
.PartialPresent();
453 unsigned long long DebBytes
= Fetcher
.TotalNeeded();
455 if (CheckFreeSpaceBeforeDownload(".", (FetchBytes
- FetchPBytes
)) == false)
459 if (DebBytes
!= FetchBytes
)
460 //TRANSLATOR: The required space between number and unit is already included
461 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
462 ioprintf(c1out
,_("Need to get %sB/%sB of source archives.\n"),
463 SizeToStr(FetchBytes
).c_str(),SizeToStr(DebBytes
).c_str());
465 //TRANSLATOR: The required space between number and unit is already included
466 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
467 ioprintf(c1out
,_("Need to get %sB of source archives.\n"),
468 SizeToStr(DebBytes
).c_str());
470 if (_config
->FindB("APT::Get::Simulate",false) == true)
472 for (unsigned I
= 0; I
!= J
; I
++)
473 ioprintf(std::cout
,_("Fetch source %s\n"),Dsc
[I
].Package
.c_str());
477 // Just print out the uris an exit if the --print-uris flag was used
478 if (_config
->FindB("APT::Get::Print-URIs") == true)
480 pkgAcquire::UriIterator I
= Fetcher
.UriBegin();
481 for (; I
!= Fetcher
.UriEnd(); ++I
)
482 std::cout
<< '\'' << I
->URI
<< "' " << flNotDir(I
->Owner
->DestFile
) << ' ' <<
483 std::to_string(I
->Owner
->FileSize
) << ' ' << I
->Owner
->HashSum() << std::endl
;
487 // check authentication status of the source as well
488 if (UntrustedList
.empty() == false && AuthPrompt(UntrustedList
, false) == false)
493 if (AcquireRun(Fetcher
, 0, &Failed
, NULL
) == false || Failed
== true)
495 return _error
->Error(_("Failed to fetch some archives."));
498 if (_config
->FindB("APT::Get::Download-only",false) == true)
500 c1out
<< _("Download complete and in download only mode") << std::endl
;
504 // Unpack the sources
505 pid_t Process
= ExecFork();
509 bool const fixBroken
= _config
->FindB("APT::Get::Fix-Broken", false);
510 for (unsigned I
= 0; I
!= J
; ++I
)
512 std::string Dir
= Dsc
[I
].Package
+ '-' + Cache
.GetPkgCache()->VS
->UpstreamVersion(Dsc
[I
].Version
.c_str());
514 // Diff only mode only fetches .diff files
515 if (_config
->FindB("APT::Get::Diff-Only",false) == true ||
516 _config
->FindB("APT::Get::Tar-Only",false) == true ||
517 Dsc
[I
].Dsc
.empty() == true)
520 // See if the package is already unpacked
522 if (fixBroken
== false && stat(Dir
.c_str(),&Stat
) == 0 &&
523 S_ISDIR(Stat
.st_mode
) != 0)
525 ioprintf(c0out
,_("Skipping unpack of already unpacked source in %s\n"),
531 std::string
const sourceopts
= _config
->Find("DPkg::Source-Options", "-x");
533 strprintf(S
, "%s %s %s",
534 _config
->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
535 sourceopts
.c_str(), Dsc
[I
].Dsc
.c_str());
536 if (system(S
.c_str()) != 0)
538 fprintf(stderr
, _("Unpack command '%s' failed.\n"), S
.c_str());
539 fprintf(stderr
, _("Check if the 'dpkg-dev' package is installed.\n"));
544 // Try to compile it with dpkg-buildpackage
545 if (_config
->FindB("APT::Get::Compile",false) == true)
547 std::string buildopts
= _config
->Find("APT::Get::Host-Architecture");
548 if (buildopts
.empty() == false)
549 buildopts
= "-a" + buildopts
+ " ";
551 // get all active build profiles
552 std::string
const profiles
= APT::Configuration::getBuildProfilesString();
553 if (profiles
.empty() == false)
554 buildopts
.append(" -P").append(profiles
).append(" ");
556 buildopts
.append(_config
->Find("DPkg::Build-Options","-b -uc"));
558 // Call dpkg-buildpackage
560 strprintf(S
, "cd %s && %s %s",
562 _config
->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
565 if (system(S
.c_str()) != 0)
567 fprintf(stderr
, _("Build command '%s' failed.\n"), S
.c_str());
576 return ExecWait(Process
, "dpkg-source");
579 // DoBuildDep - Install/removes packages to satisfy build dependencies /*{{{*/
580 // ---------------------------------------------------------------------
581 /* This function will look at the build depends list of the given source
582 package and install the necessary packages to make it true, or fail. */
583 static std::vector
<pkgSrcRecords::Parser::BuildDepRec
> GetBuildDeps(pkgSrcRecords::Parser
* const Last
,
584 char const * const Src
, bool const StripMultiArch
, std::string
const &hostArch
)
586 std::vector
<pkgSrcRecords::Parser::BuildDepRec
> BuildDeps
;
587 // FIXME: Can't specify architecture to use for [wildcard] matching, so switch default arch temporary
588 if (hostArch
.empty() == false)
590 std::string nativeArch
= _config
->Find("APT::Architecture");
591 _config
->Set("APT::Architecture", hostArch
);
592 bool Success
= Last
->BuildDepends(BuildDeps
, _config
->FindB("APT::Get::Arch-Only", false), StripMultiArch
);
593 _config
->Set("APT::Architecture", nativeArch
);
594 if (Success
== false)
596 _error
->Error(_("Unable to get build-dependency information for %s"), Src
);
600 else if (Last
->BuildDepends(BuildDeps
, _config
->FindB("APT::Get::Arch-Only", false), StripMultiArch
) == false)
602 _error
->Error(_("Unable to get build-dependency information for %s"), Src
);
606 if (BuildDeps
.empty() == true)
607 ioprintf(c1out
,_("%s has no build depends.\n"), Src
);
611 static void WriteBuildDependencyPackage(std::ostringstream
&buildDepsPkgFile
,
612 std::string
const &PkgName
, std::string
const &Arch
,
613 std::vector
<pkgSrcRecords::Parser::BuildDepRec
> const &Dependencies
)
615 buildDepsPkgFile
<< "Package: " << PkgName
<< "\n"
616 << "Architecture: " << Arch
<< "\n"
619 std::string depends
, conflicts
;
620 for (auto const &dep
: Dependencies
)
623 if (dep
.Type
== pkgSrcRecords::Parser::BuildConflict
||
624 dep
.Type
== pkgSrcRecords::Parser::BuildConflictIndep
||
625 dep
.Type
== pkgSrcRecords::Parser::BuildConflictArch
)
630 type
->append(" ").append(dep
.Package
);
631 if (dep
.Version
.empty() == false)
632 type
->append(" (").append(pkgCache::CompTypeDeb(dep
.Op
)).append(" ").append(dep
.Version
).append(")");
633 if ((dep
.Op
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
635 type
->append("\n |");
640 if (depends
.empty() == false)
641 buildDepsPkgFile
<< "Depends:\n" << depends
;
642 if (conflicts
.empty() == false)
643 buildDepsPkgFile
<< "Conflicts:\n" << conflicts
;
644 buildDepsPkgFile
<< "\n";
646 bool DoBuildDep(CommandLine
&CmdL
)
649 std::vector
<std::string
> VolatileCmdL
;
650 Cache
.GetSourceList()->AddVolatileFiles(CmdL
, &VolatileCmdL
);
652 _config
->Set("APT::Install-Recommends", false);
654 if (CmdL
.FileSize() <= 1 && VolatileCmdL
.empty())
655 return _error
->Error(_("Must specify at least one package to check builddeps for"));
658 std::string hostArch
= _config
->Find("APT::Get::Host-Architecture");
659 if (hostArch
.empty() == false)
661 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
662 if (std::find(archs
.begin(), archs
.end(), hostArch
) == archs
.end())
663 return _error
->Error(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch
.c_str());
664 StripMultiArch
= false;
667 StripMultiArch
= true;
669 std::ostringstream buildDepsPkgFile
;
670 std::vector
<std::pair
<std::string
,std::string
>> pseudoPkgs
;
671 // deal with the build essentials first
673 std::vector
<pkgSrcRecords::Parser::BuildDepRec
> BuildDeps
;
674 Configuration::Item
const *Opts
= _config
->Tree("APT::Build-Essential");
677 for (; Opts
; Opts
= Opts
->Next
)
679 if (Opts
->Value
.empty() == true)
682 pkgSrcRecords::Parser::BuildDepRec rec
;
683 rec
.Package
= Opts
->Value
;
684 rec
.Type
= pkgSrcRecords::Parser::BuildDependIndep
;
686 BuildDeps
.push_back(rec
);
688 std::string
const pseudo
= "builddeps:essentials";
689 std::string
const nativeArch
= _config
->Find("APT::Architecture");
690 WriteBuildDependencyPackage(buildDepsPkgFile
, pseudo
, nativeArch
, BuildDeps
);
691 pseudoPkgs
.emplace_back(pseudo
, nativeArch
);
694 // Read the source list
695 if (Cache
.BuildSourceList() == false)
697 pkgSourceList
*List
= Cache
.GetSourceList();
698 std::string
const pseudoArch
= hostArch
.empty() ? _config
->Find("APT::Architecture") : hostArch
;
700 // FIXME: Avoid volatile sources == cmdline assumption
702 auto const VolatileSources
= List
->GetVolatileFiles();
703 if (VolatileSources
.size() == VolatileCmdL
.size())
705 for (size_t i
= 0; i
< VolatileSources
.size(); ++i
)
707 auto const Src
= VolatileCmdL
[i
];
708 if (DirectoryExists(Src
))
709 ioprintf(c1out
, _("Note, using directory '%s' to get the build dependencies\n"), Src
.c_str());
711 ioprintf(c1out
, _("Note, using file '%s' to get the build dependencies\n"), Src
.c_str());
712 std::unique_ptr
<pkgSrcRecords::Parser
> Last(VolatileSources
[i
]->CreateSrcParser());
714 return _error
->Error(_("Unable to find a source package for %s"), Src
.c_str());
716 std::string
const pseudo
= std::string("builddeps:") + Src
;
717 WriteBuildDependencyPackage(buildDepsPkgFile
, pseudo
, pseudoArch
,
718 GetBuildDeps(Last
.get(), Src
.c_str(), StripMultiArch
, hostArch
));
719 pseudoPkgs
.emplace_back(pseudo
, pseudoArch
);
723 return _error
->Error("Implementation error: Volatile sources (%lu) and"
724 "commandline elements (%lu) do not match!", VolatileSources
.size(),
725 VolatileCmdL
.size());
728 bool const WantLock
= _config
->FindB("APT::Get::Print-URIs", false) == false;
729 if (CmdL
.FileList
[1] != 0)
731 if (Cache
.BuildCaches(WantLock
) == false)
733 // Create the text record parsers
734 pkgSrcRecords
SrcRecs(*List
);
735 if (_error
->PendingError() == true)
737 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; ++I
)
740 pkgSrcRecords::Parser
* const Last
= FindSrc(*I
,SrcRecs
,Src
,Cache
);
742 return _error
->Error(_("Unable to find a source package for %s"), *I
);
744 std::string
const pseudo
= std::string("builddeps:") + Src
;
745 WriteBuildDependencyPackage(buildDepsPkgFile
, pseudo
, pseudoArch
,
746 GetBuildDeps(Last
, Src
.c_str(), StripMultiArch
, hostArch
));
747 pseudoPkgs
.emplace_back(pseudo
, pseudoArch
);
751 Cache
.AddIndexFile(new debStringPackageIndex(buildDepsPkgFile
.str()));
753 if (Cache
.Open(WantLock
) == false)
755 pkgProblemResolver
Fix(Cache
.GetDepCache());
757 APT::PackageVector removeAgain
;
759 pkgDepCache::ActionGroup
group(Cache
);
760 TryToInstall
InstallAction(Cache
, &Fix
, false);
761 for (auto const &pkg
: pseudoPkgs
)
763 pkgCache::PkgIterator
const Pkg
= Cache
->FindPkg(pkg
.first
, pkg
.second
);
766 Cache
->SetCandidateVersion(Pkg
.VersionList());
767 InstallAction(Cache
[Pkg
].CandidateVerIter(Cache
));
768 removeAgain
.push_back(Pkg
);
770 InstallAction
.doAutoInstall();
772 OpTextProgress
Progress(*_config
);
773 bool const resolver_fail
= Fix
.Resolve(true, &Progress
);
774 if (resolver_fail
== false && Cache
->BrokenCount() == 0)
776 if (CheckNothingBroken(Cache
) == false)
779 if (DoAutomaticRemove(Cache
) == false)
783 pkgDepCache::ActionGroup
group(Cache
);
784 if (_config
->FindB("APT::Get::Build-Dep-Automatic", false) == false)
786 for (auto const &pkg
: removeAgain
)
788 auto const instVer
= Cache
[pkg
].InstVerIter(Cache
);
789 if (unlikely(instVer
.end() == true))
791 for (auto D
= instVer
.DependsList(); D
.end() != true; ++D
)
793 if (D
->Type
!= pkgCache::Dep::Depends
|| D
.IsMultiArchImplicit())
795 APT::VersionList verlist
= APT::VersionList::FromDependency(Cache
, D
, APT::CacheSetHelper::CANDIDATE
);
796 for (auto const &V
: verlist
)
798 auto const P
= V
.ParentPkg();
799 if (Cache
[P
].InstallVer
!= V
)
801 Cache
->MarkAuto(P
, false);
806 for (auto const &pkg
: removeAgain
)
807 Cache
->MarkDelete(pkg
, false, 0, true);
811 if (_error
->PendingError() || InstallPackages(Cache
, false, true) == false)
812 return _error
->Error(_("Failed to process build dependencies"));