Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

universal / apt-dbg   deb

Repository URL to install this package:

Version: 1.2.12-r0.0 

/ usr / src / debug / apt / 1.2.12-r0 / apt-1.2.12 / apt-private / private-source.cc

// Include Files							/*{{{*/
#include <config.h>

#include <apt-pkg/acquire-item.h>
#include <apt-pkg/acquire.h>
#include <apt-pkg/algorithms.h>
#include <apt-pkg/aptconfiguration.h>
#include <apt-pkg/cachefile.h>
#include <apt-pkg/cacheiterators.h>
#include <apt-pkg/cacheset.h>
#include <apt-pkg/cmndline.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/depcache.h>
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/hashes.h>
#include <apt-pkg/indexfile.h>
#include <apt-pkg/metaindex.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/srcrecords.h>
#include <apt-pkg/strutl.h>
#include <apt-pkg/version.h>
#include <apt-pkg/policy.h>

#include <apt-private/private-cachefile.h>
#include <apt-private/private-cacheset.h>
#include <apt-private/private-download.h>
#include <apt-private/private-install.h>
#include <apt-private/private-source.h>

#include <apt-pkg/debindexfile.h>

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#include <iostream>
#include <sstream>
#include <set>
#include <string>
#include <vector>

#include <apti18n.h>
									/*}}}*/

// GetReleaseFileForSourceRecord - Return Suite for the given srcrecord	/*{{{*/
static pkgCache::RlsFileIterator GetReleaseFileForSourceRecord(CacheFile &CacheFile,
      pkgSourceList const * const SrcList, pkgSrcRecords::Parser const * const Parse)
{
   // try to find release
   const pkgIndexFile& CurrentIndexFile = Parse->Index();

   for (pkgSourceList::const_iterator S = SrcList->begin(); 
	 S != SrcList->end(); ++S)
   {
      std::vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
      for (std::vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
	    IF != Indexes->end(); ++IF)
      {
	 if (&CurrentIndexFile == (*IF))
	    return (*S)->FindInCache(CacheFile, false);
      }
   }
   return pkgCache::RlsFileIterator(CacheFile);
}
									/*}}}*/
// FindSrc - Find a source record					/*{{{*/
static pkgSrcRecords::Parser *FindSrc(const char *Name,
			       pkgSrcRecords &SrcRecs,std::string &Src,
			       CacheFile &Cache)
{
   std::string VerTag, UserRequestedVerTag;
   std::string ArchTag = "";
   std::string RelTag = _config->Find("APT::Default-Release");
   std::string TmpSrc = Name;

   // extract release
   size_t found = TmpSrc.find_last_of("/");
   if (found != std::string::npos)
   {
      RelTag = TmpSrc.substr(found+1);
      TmpSrc = TmpSrc.substr(0,found);
   }
   // extract the version
   found = TmpSrc.find_last_of("=");
   if (found != std::string::npos)
   {
      VerTag = UserRequestedVerTag = TmpSrc.substr(found+1);
      TmpSrc = TmpSrc.substr(0,found);
   }
   // extract arch
   found = TmpSrc.find_last_of(":");
   if (found != std::string::npos)
   {
      ArchTag = TmpSrc.substr(found+1);
      TmpSrc = TmpSrc.substr(0,found);
   }

   /* Lookup the version of the package we would install if we were to
      install a version and determine the source package name, then look
      in the archive for a source package of the same name. */
   bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
   pkgCache::PkgIterator Pkg;
   if (ArchTag != "")
      Pkg = Cache.GetPkgCache()->FindPkg(TmpSrc, ArchTag);
   else
      Pkg = Cache.GetPkgCache()->FindPkg(TmpSrc);

   // if we can't find a package but the user qualified with a arch,
   // error out here
   if (Pkg.end() && ArchTag != "")
   {
      Src = Name;
      _error->Error(_("Can not find a package for architecture '%s'"),
	    ArchTag.c_str());
      return 0;
   }

   if (MatchSrcOnly == false && Pkg.end() == false)
   {
      if(VerTag != "" || RelTag != "" || ArchTag != "")
      {
	 bool fuzzy = false;
	 // we have a default release, try to locate the pkg. we do it like
	 // this because GetCandidateVer() will not "downgrade", that means
	 // "apt-get source -t stable apt" won't work on a unstable system
	 for (pkgCache::VerIterator Ver = Pkg.VersionList();; ++Ver)
	 {
	    // try first only exact matches, later fuzzy matches
	    if (Ver.end() == true)
	    {
	       if (fuzzy == true)
		  break;
	       fuzzy = true;
	       Ver = Pkg.VersionList();
	       // exit right away from the Pkg.VersionList() loop if we
	       // don't have any versions
	       if (Ver.end() == true)
		  break;
	    }

	    // ignore arches that are not for us
	    if (ArchTag != "" && Ver.Arch() != ArchTag)
	       continue;

	    // pick highest version for the arch unless the user wants
	    // something else
	    if (ArchTag != "" && VerTag == "" && RelTag == "")
	       if(Cache.GetPkgCache()->VS->CmpVersion(VerTag, Ver.VerStr()) < 0)
		  VerTag = Ver.VerStr();

	    // We match against a concrete version (or a part of this version)
	    if (VerTag.empty() == false &&
		  (fuzzy == true || Cache.GetPkgCache()->VS->CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match
		  (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match
	       continue;

	    for (pkgCache::VerFileIterator VF = Ver.FileList();
		  VF.end() == false; ++VF)
	    {
	       /* If this is the status file, and the current version is not the
		  version in the status file (ie it is not installed, or somesuch)
		  then it is not a candidate for installation, ever. This weeds
		  out bogus entries that may be due to config-file states, or
		  other. */
	       if ((VF.File()->Flags & pkgCache::Flag::NotSource) ==
		     pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
		  continue;

	       // or we match against a release
	       if(VerTag.empty() == false ||
		     (VF.File().Archive() != 0 && VF.File().Archive() == RelTag) ||
		     (VF.File().Codename() != 0 && VF.File().Codename() == RelTag))
	       {
		  // the Version we have is possibly fuzzy or includes binUploads,
		  // so we use the Version of the SourcePkg (empty if same as package)
		  Src = Ver.SourcePkgName();
		  VerTag = Ver.SourceVerStr();
		  break;
	       }
	    }
	    if (Src.empty() == false)
	       break;
	 }
      }

      if (Src.empty() == true && ArchTag.empty() == false)
      {
	 if (VerTag.empty() == false)
	    _error->Error(_("Can not find a package '%s' with version '%s'"),
		  Pkg.FullName().c_str(), VerTag.c_str());
	 if (RelTag.empty() == false)
	    _error->Error(_("Can not find a package '%s' with release '%s'"),
		  Pkg.FullName().c_str(), RelTag.c_str());
	 Src = Name;
	 return 0;
      }


      if (Src.empty() == true)
      {
	 // if we don't have found a fitting package yet so we will
	 // choose a good candidate and proceed with that.
	 // Maybe we will find a source later on with the right VerTag
	 // or RelTag
	 if (Cache.BuildPolicy() == false)
	    return nullptr;
	 pkgPolicy * Policy = dynamic_cast<pkgPolicy*>(Cache.GetPolicy());
	 if (Policy == nullptr)
	 {
	    _error->Fatal("Implementation error: dynamic up-casting policy engine failed in FindSrc!");
	    return nullptr;
	 }
	 pkgCache::VerIterator const Ver = Policy->GetCandidateVer(Pkg);
	 if (Ver.end() == false)
	 {
	    if (strcmp(Ver.SourcePkgName(),Ver.ParentPkg().Name()) != 0)
	       Src = Ver.SourcePkgName();
	    if (VerTag.empty() == true && strcmp(Ver.SourceVerStr(),Ver.VerStr()) != 0)
	       VerTag = Ver.SourceVerStr();
	 }
      }
   }

   if (Src.empty() == true)
   {
      Src = TmpSrc;
   }
   else 
   {
      /* if we have a source pkg name, make sure to only search
	 for srcpkg names, otherwise apt gets confused if there
	 is a binary package "pkg1" and a source package "pkg1"
	 with the same name but that comes from different packages */
      MatchSrcOnly = true;
      if (Src != TmpSrc) 
      {
	 ioprintf(c1out, _("Picking '%s' as source package instead of '%s'\n"), Src.c_str(), TmpSrc.c_str());
      }
   }

   // The best hit
   pkgSrcRecords::Parser *Last = 0;
   unsigned long Offset = 0;
   std::string Version;
   pkgSourceList const * const SrcList = Cache.GetSourceList();

   /* Iterate over all of the hits, which includes the resulting
      binary packages in the search */
	       pkgSrcRecords::Parser *Parse;
	       while (true)
	       {
		  SrcRecs.Restart();
		  while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0)
		  {
		     const std::string Ver = Parse->Version();

		     // See if we need to look for a specific release tag
		     if (RelTag.empty() == false && UserRequestedVerTag.empty() == true)
		     {
			pkgCache::RlsFileIterator const Rls = GetReleaseFileForSourceRecord(Cache, SrcList, Parse);
			if (Rls.end() == false)
			{
			   if ((Rls->Archive != 0 && RelTag != Rls.Archive()) &&
				 (Rls->Codename != 0 && RelTag != Rls.Codename()))
			      continue;
			}
		     }

		     // Ignore all versions which doesn't fit
		     if (VerTag.empty() == false &&
			   Cache.GetPkgCache()->VS->CmpVersion(VerTag, Ver) != 0) // exact match
			continue;

		     // Newer version or an exact match? Save the hit
		     if (Last == 0 || Cache.GetPkgCache()->VS->CmpVersion(Version,Ver) < 0) {
			Last = Parse;
			Offset = Parse->Offset();
			Version = Ver;
		     }

		     // was the version check above an exact match?
		     // If so, we don't need to look further
		     if (VerTag.empty() == false && (VerTag == Ver))
			break;
		  }
		  if (UserRequestedVerTag == "" && Version != "" && RelTag != "")
		     ioprintf(c1out, "Selected version '%s' (%s) for %s\n",
			   Version.c_str(), RelTag.c_str(), Src.c_str());

		  if (Last != 0 || VerTag.empty() == true)
		     break;
		  _error->Error(_("Can not find version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
		  return 0;
	       }

	       if (Last == 0 || Last->Jump(Offset) == false)
		  return 0;

	       return Last;
}
									/*}}}*/
// DoSource - Fetch a source archive					/*{{{*/
// ---------------------------------------------------------------------
/* Fetch souce packages */
struct DscFile
{
   std::string Package;
   std::string Version;
   std::string Dsc;
};
bool DoSource(CommandLine &CmdL)
{
   if (CmdL.FileSize() <= 1)
      return _error->Error(_("Must specify at least one package to fetch source for"));

   CacheFile Cache;
   if (Cache.BuildCaches(false) == false)
      return false;

   // Create the text record parsers
   pkgSourceList * const List = Cache.GetSourceList();
   pkgSrcRecords SrcRecs(*List);
   if (_error->PendingError() == true)
      return false;

   std::unique_ptr<DscFile[]> Dsc(new DscFile[CmdL.FileSize()]);

   // insert all downloaded uris into this set to avoid downloading them
   // twice
   std::set<std::string> queued;

   // Diff only mode only fetches .diff files
   bool const diffOnly = _config->FindB("APT::Get::Diff-Only", false);
   // Tar only mode only fetches .tar files
   bool const tarOnly = _config->FindB("APT::Get::Tar-Only", false);
   // Dsc only mode only fetches .dsc files
   bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false);

   // Load the requestd sources into the fetcher
   aptAcquireWithTextStatus Fetcher;
Loading ...