Compare 15f32c4 ... +34 ... e5f9d66

Coverage Reach
apt-pkg/contrib/fileutl.cc apt-pkg/contrib/strutl.cc apt-pkg/contrib/configuration.cc apt-pkg/contrib/sha2_internal.cc apt-pkg/contrib/hashes.cc apt-pkg/contrib/mmap.cc apt-pkg/contrib/gpgv.cc apt-pkg/contrib/cmndline.cc apt-pkg/contrib/sha1.cc apt-pkg/contrib/md5.cc apt-pkg/contrib/cdromutl.cc apt-pkg/contrib/error.cc apt-pkg/contrib/netrc.cc apt-pkg/contrib/progress.cc apt-pkg/contrib/srvrec.cc apt-pkg/contrib/proxy.cc apt-pkg/contrib/hashsum.cc apt-pkg/contrib/crc-16.cc apt-pkg/contrib/srvrec.h apt-pkg/deb/dpkgpm.cc apt-pkg/deb/debmetaindex.cc apt-pkg/deb/deblistparser.cc apt-pkg/deb/debindexfile.cc apt-pkg/deb/debsystem.cc apt-pkg/deb/debsrcrecords.cc apt-pkg/deb/debversion.cc apt-pkg/deb/debrecords.cc apt-pkg/acquire-item.cc apt-pkg/pkgcachegen.cc apt-pkg/depcache.cc apt-pkg/edsp.cc apt-pkg/acquire.cc apt-pkg/algorithms.cc apt-pkg/packagemanager.cc apt-pkg/cdrom.cc apt-pkg/tagfile.cc apt-pkg/cacheset.cc apt-pkg/pkgcache.cc apt-pkg/orderlist.cc apt-pkg/acquire-worker.cc apt-pkg/indexcopy.cc apt-pkg/sourcelist.cc apt-pkg/aptconfiguration.cc apt-pkg/acquire-method.cc apt-pkg/indexfile.cc apt-pkg/policy.cc apt-pkg/edsp/edsplistparser.cc apt-pkg/edsp/edspsystem.cc apt-pkg/edsp/edspindexfile.cc apt-pkg/install-progress.cc apt-pkg/cachefile.cc apt-pkg/cacheiterators.h apt-pkg/cacheset.h apt-pkg/upgrade.cc apt-pkg/versionmatch.cc apt-pkg/cachefilter.cc apt-pkg/statechanges.cc apt-pkg/init.cc apt-pkg/prettyprinters.cc apt-pkg/srcrecords.cc apt-pkg/clean.cc apt-pkg/metaindex.cc apt-pkg/depcache.h apt-pkg/update.cc apt-pkg/pkgcache.h apt-pkg/pkgsystem.cc apt-pkg/acquire.h apt-pkg/pkgcachegen.h apt-pkg/pkgrecords.cc apt-pkg/tagfile-compat.cc apt-pkg/cachefile.h apt-pkg/pkgrecords.h apt-pkg/orderlist.h apt-pkg/acquire-item.h apt-pkg/install-progress.h apt-pkg/packagemanager.h apt-pkg/version.cc apt-pkg/indexfile.h apt-pkg/tagfile.h apt-pkg/algorithms.h apt-pkg/cachefilter.h apt-pkg/policy.h apt-pkg/srcrecords.h apt-pkg/acquire-method.h apt-pkg/version.h apt-pkg/indexcopy.h apt-pkg/pkgsystem.h apt-pkg/sourcelist.h apt-pkg/cdrom.h apt-pkg/aptconfiguration.h apt-pkg/prettyprinters.h apt-pkg/clean.h apt-pkg/metaindex.h apt-pkg/versionmatch.h apt-pkg/acquire-worker.h apt-pkg/statechanges.h test/libapt/hashsums_test.cc test/libapt/fileutl_test.cc test/libapt/tagsection_test.cc test/libapt/strutil_test.cc test/libapt/uri_test.cc test/libapt/getlanguages_test.cc test/libapt/parsedepends_test.cc test/libapt/tagfile_test.cc test/libapt/configuration_test.cc test/libapt/commandline_test.cc test/libapt/globalerror_test.cc test/libapt/acqprogress_test.cc test/libapt/cdromfindpackages_test.cc test/libapt/compareversion_test.cc test/libapt/getlistoffilesindir_test.cc test/libapt/cdrom_test.cc test/libapt/indexcopytosourcelist_test.cc test/libapt/getarchitectures_test.cc test/libapt/srvrecs_test.cc test/libapt/stringview_test.cc test/libapt/file-helpers.cc test/libapt/cachefilter_test.cc test/libapt/extracttar_test.cc test/libapt/install_progress_test.cc test/libapt/gtest_runner.cc test/libapt/sourcelist_test.cc test/libapt/priority_test.cc test/interactive-helper/aptwebserver.cc test/interactive-helper/test_fileutl.cc apt-private/private-install.cc apt-private/private-source.cc apt-private/private-output.cc apt-private/private-cmndline.cc apt-private/private-show.cc apt-private/private-cacheset.cc apt-private/private-download.cc apt-private/private-search.cc apt-private/acqprogress.cc apt-private/private-moo.cc apt-private/private-depends.cc apt-private/private-list.cc apt-private/private-unmet.cc apt-private/private-cachefile.cc apt-private/private-sources.cc apt-private/private-update.cc apt-private/private-utils.cc apt-private/private-main.cc apt-private/private-output.h apt-private/private-cacheset.h apt-private/private-cachefile.h apt-private/private-upgrade.cc apt-private/private-install.h apt-private/acqprogress.h apt-private/private-download.h methods/http.cc methods/rred.cc methods/server.cc methods/https.cc methods/gpgv.cc methods/connect.cc methods/cdrom.cc methods/aptmethod.h methods/store.cc methods/copy.cc methods/http.h methods/https.h methods/http_main.cc methods/server.h ftparchive/writer.cc ftparchive/apt-ftparchive.cc ftparchive/cachedb.cc ftparchive/multicompress.cc ftparchive/contents.cc ftparchive/override.cc ftparchive/cachedb.h ftparchive/sources.cc ftparchive/byhash.cc ftparchive/writer.h ftparchive/contents.h ftparchive/override.h ftparchive/sources.h ftparchive/multicompress.h cmdline/apt-cache.cc cmdline/apt-get.cc cmdline/apt-mark.cc cmdline/apt-extracttemplates.cc cmdline/apt-internal-solver.cc cmdline/apt-helper.cc cmdline/apt-cdrom.cc cmdline/apt-dump-solver.cc cmdline/apt-internal-planner.cc cmdline/apt-sortpkgs.cc cmdline/apt-config.cc cmdline/apt.cc apt-inst/filelist.cc apt-inst/extract.cc apt-inst/contrib/extracttar.cc apt-inst/contrib/arfile.cc apt-inst/deb/debfile.cc apt-inst/dirstream.cc

No flags found

Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.

e.g., #unittest #integration

#production #enterprise

#frontend #backend

Learn more about Codecov Flags here.

Showing 17 of 43 files from the diff.

@@ -1018,9 +1018,7 @@
Loading
1018 1018
   return false;
1019 1019
}
1020 1020
									/*}}}*/
1021 -
1022 -
																		/*}}}*/
1023 -
int pkgAcquire::Item::Priority() 				/*{{{*/
1021 +
int pkgAcquire::Item::Priority()					/*{{{*/
1024 1022
{
1025 1023
   // Stage 1: Meta indices and diff indices
1026 1024
   // - those need to be fetched first to have progress reporting working
@@ -1925,10 +1923,16 @@
Loading
1925 1923
   }
1926 1924
   else if(MetaIndex->CheckAuthDone(Message) == true)
1927 1925
   {
1928 -
      if (TransactionManager->IMSHit == false)
1926 +
      auto const Releasegpg = GetFinalFilename();
1927 +
      auto const Release = MetaIndex->GetFinalFilename();
1928 +
      // if this is an IMS-Hit on Release ensure we also have the the Release.gpg file stored
1929 +
      // (previously an unknown pubkey) – but only if the Release file exists locally (unlikely
1930 +
      // event of InRelease removed from the mirror causing fallback but still an IMS-Hit)
1931 +
      if (TransactionManager->IMSHit == false ||
1932 +
	    (FileExists(Releasegpg) == false && FileExists(Release) == true))
1929 1933
      {
1930 -
	 TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename());
1931 -
	 TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename());
1934 +
	 TransactionManager->TransactionStageCopy(this, DestFile, Releasegpg);
1935 +
	 TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, Release);
1932 1936
      }
1933 1937
   }
1934 1938
   else if (MetaIndex->Status != StatAuthError)
@@ -2051,7 +2055,7 @@
Loading
2051 2055
{
2052 2056
   // list cleanup needs to know that this file as well as the already
2053 2057
   // present index is ours, so we create an empty diff to save it for us
2054 -
   new pkgAcqIndexDiffs(Owner, TransactionManager, Target);
2058 +
   new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, Target.URI);
2055 2059
}
2056 2060
									/*}}}*/
2057 2061
static bool RemoveFileForBootstrapLinking(bool const Debug, std::string const &For, std::string const &Boot)/*{{{*/
@@ -2427,14 +2431,26 @@
Loading
2427 2431
      }
2428 2432
   }
2429 2433
2434 +
   std::string indexURI = Desc.URI;
2435 +
   auto const byhashidx = indexURI.find("/by-hash/");
2436 +
   if (byhashidx != std::string::npos)
2437 +
      indexURI = indexURI.substr(0, byhashidx - strlen(".diff"));
2438 +
   else
2439 +
   {
2440 +
      auto end = indexURI.length() - strlen(".diff/Index");
2441 +
      if (CurrentCompressionExtension != "uncompressed")
2442 +
	 end -= (1 + CurrentCompressionExtension.length());
2443 +
      indexURI = indexURI.substr(0, end);
2444 +
   }
2445 +
2430 2446
   if (pdiff_merge == false)
2431 -
      new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches);
2447 +
      new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, indexURI, available_patches);
2432 2448
   else
2433 2449
   {
2434 2450
      diffs = new std::vector<pkgAcqIndexMergeDiffs*>(available_patches.size());
2435 2451
      for(size_t i = 0; i < available_patches.size(); ++i)
2436 2452
	 (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, TransactionManager,
2437 -
               Target,
2453 +
               Target, UsedMirror, indexURI,
2438 2454
	       available_patches[i],
2439 2455
	       diffs);
2440 2456
   }
@@ -2504,8 +2520,9 @@
Loading
2504 2520
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner,
2505 2521
                                   pkgAcqMetaClearSig * const TransactionManager,
2506 2522
                                   IndexTarget const &Target,
2523 +
				   std::string const &indexUsedMirror, std::string const &indexURI,
2507 2524
				   vector<DiffInfo> const &diffs)
2508 -
   : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
2525 +
   : pkgAcqBaseIndex(Owner, TransactionManager, Target), indexURI(indexURI),
2509 2526
     available_patches(diffs)
2510 2527
{
2511 2528
   DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI), Target);
@@ -2516,6 +2533,12 @@
Loading
2516 2533
   Description = Target.Description;
2517 2534
   Desc.ShortDesc = Target.ShortDesc;
2518 2535
2536 +
   UsedMirror = indexUsedMirror;
2537 +
   if (UsedMirror == "DIRECT")
2538 +
      UsedMirror.clear();
2539 +
   else if (UsedMirror.empty() == false && Description.find(" ") != string::npos)
2540 +
      Description.replace(0, Description.find(" "), UsedMirror);
2541 +
2519 2542
   if(available_patches.empty() == true)
2520 2543
   {
2521 2544
      // we are done (yeah!), check hashes against the final file
@@ -2630,7 +2653,7 @@
Loading
2630 2653
   }
2631 2654
2632 2655
   // queue the right diff
2633 -
   Desc.URI = Target.URI + ".diff/" + available_patches[0].file + ".gz";
2656 +
   Desc.URI = indexURI + ".diff/" + available_patches[0].file + ".gz";
2634 2657
   Desc.Description = Description + " " + available_patches[0].file + string(".pdiff");
2635 2658
   DestFile = GetKeepCompressedFileName(GetPartialFileNameFromURI(Target.URI + ".diff/" + available_patches[0].file), Target);
2636 2659
@@ -2683,7 +2706,7 @@
Loading
2683 2706
	 // see if there is more to download
2684 2707
	 if(available_patches.empty() == false)
2685 2708
	 {
2686 -
	    new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches);
2709 +
	    new pkgAcqIndexDiffs(Owner, TransactionManager, Target, UsedMirror, indexURI, available_patches);
2687 2710
	    Finish();
2688 2711
	 } else {
2689 2712
	    DestFile = PatchedFile;
@@ -2712,19 +2735,26 @@
Loading
2712 2735
pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner,
2713 2736
                                             pkgAcqMetaClearSig * const TransactionManager,
2714 2737
                                             IndexTarget const &Target,
2738 +
					     std::string const &indexUsedMirror, std::string const &indexURI,
2715 2739
                                             DiffInfo const &patch,
2716 2740
                                             std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches)
2717 -
  : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL),
2718 -
     patch(patch), allPatches(allPatches), State(StateFetchDiff)
2741 +
  : pkgAcqBaseIndex(Owner, TransactionManager, Target), indexURI(indexURI),
2742 +
    patch(patch), allPatches(allPatches), State(StateFetchDiff)
2719 2743
{
2720 2744
   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
2721 2745
2722 -
   Desc.Owner = this;
2723 2746
   Description = Target.Description;
2747 +
   UsedMirror = indexUsedMirror;
2748 +
   if (UsedMirror == "DIRECT")
2749 +
      UsedMirror.clear();
2750 +
   else if (UsedMirror.empty() == false && Description.find(" ") != string::npos)
2751 +
      Description.replace(0, Description.find(" "), UsedMirror);
2752 +
2753 +
   Desc.Owner = this;
2724 2754
   Desc.ShortDesc = Target.ShortDesc;
2725 -
   Desc.URI = Target.URI + ".diff/" + patch.file + ".gz";
2755 +
   Desc.URI = indexURI + ".diff/" + patch.file + ".gz";
2726 2756
   Desc.Description = Description + " " + patch.file + ".pdiff";
2727 -
   DestFile = GetPartialFileNameFromURI(Desc.URI);
2757 +
   DestFile = GetPartialFileNameFromURI(Target.URI + ".diff/" + patch.file + ".gz");
2728 2758
2729 2759
   if(Debug)
2730 2760
      std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl;
@@ -2731 +2761 @@
Loading

@@ -143,6 +143,8 @@
Loading
143 143
  // of each array is the key, entry 1 is the value.
144 144
  const std::pair<const char *, const char *> PackageProcessingOps[] = {
145 145
    std::make_pair("install",   N_("Installing %s")),
146 +
    // we don't care for the difference
147 +
    std::make_pair("upgrade",   N_("Installing %s")),
146 148
    std::make_pair("configure", N_("Configuring %s")),
147 149
    std::make_pair("remove",    N_("Removing %s")),
148 150
    std::make_pair("purge",    N_("Completely removing %s")),
@@ -615,68 +617,154 @@
Loading
615 617
   {
616 618
      pkgname = APT::String::Strip(list[2]);
617 619
      action = APT::String::Strip(list[1]);
618 -
      // we don't care for the difference (as dpkg doesn't really either)
619 -
      if (action == "upgrade")
620 -
	 action = "install";
621 620
   }
622 621
   // "status" has the form: "status: pkg: state"
623 -
   // with state in ["half-installed", "unpacked", "half-configured", 
622 +
   // with state in ["half-installed", "unpacked", "half-configured",
624 623
   //                "installed", "config-files", "not-installed"]
625 624
   else if (prefix == "status")
626 625
   {
627 626
      pkgname = APT::String::Strip(list[1]);
628 627
      action = APT::String::Strip(list[2]);
629 -
   } else {
630 -
      if (Debug == true)
631 -
	 std::clog << "unknown prefix '" << prefix << "'" << std::endl;
632 -
      return;
633 -
   }
634 -
635 628
636 -
   /* handle the special cases first:
629 +
      /* handle the special cases first:
637 630
638 -
      errors look like this:
639 -
      'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data 
640 -
      and conffile-prompt like this
641 -
      'status:/etc/compiz.conf/compiz.conf :  conffile-prompt: 'current-conffile' 'new-conffile' useredited distedited
642 -
   */
643 -
   if (prefix == "status")
644 -
   {
631 +
	 errors look like this:
632 +
	 'status: /var/cache/apt/archives/krecipes_0.8.1-0ubuntu1_i386.deb : error : trying to overwrite `/usr/share/doc/kde/HTML/en/krecipes/krectip.png', which is also in package krecipes-data
633 +
	 and conffile-prompt like this
634 +
	 'status:/etc/compiz.conf/compiz.conf :  conffile-prompt: 'current-conffile' 'new-conffile' useredited distedited
635 +
	 */
645 636
      if(action == "error")
646 637
      {
647 -
         d->progress->Error(pkgname, PackagesDone, PackagesTotal,
648 -
                            list[3]);
649 -
         pkgFailures++;
638 +
         d->progress->Error(pkgname, PackagesDone, PackagesTotal, list[3]);
639 +
         ++pkgFailures;
650 640
         WriteApportReport(pkgname.c_str(), list[3].c_str());
651 641
         return;
652 642
      }
653 643
      else if(action == "conffile-prompt")
654 644
      {
655 -
         d->progress->ConffilePrompt(pkgname, PackagesDone, PackagesTotal,
656 -
                                     list[3]);
645 +
         d->progress->ConffilePrompt(pkgname, PackagesDone, PackagesTotal, list[3]);
657 646
         return;
658 647
      }
648 +
   } else {
649 +
      if (Debug == true)
650 +
	 std::clog << "unknown prefix '" << prefix << "'" << std::endl;
651 +
      return;
659 652
   }
660 653
661 -
   // at this point we know that we should have a valid pkgname, so build all 
662 -
   // the info from it
663 -
664 -
   // dpkg does not always send "pkgname:arch" so we add it here if needed
654 +
   // At this point we have a pkgname, but it might not be arch-qualified !
665 655
   if (pkgname.find(":") == std::string::npos)
666 656
   {
667 -
      // find the package in the group that is touched by dpkg
668 -
      // if there are multiple pkgs dpkg would send us a full pkgname:arch
669 657
      pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname);
670 -
      if (Grp.end() == false)
671 -
	 for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P))
672 -
	    if(Cache[P].Keep() == false || Cache[P].ReInstall() == true)
658 +
      /* No arch means that dpkg believes there can only be one package
659 +
         this can refer to so lets see what could be candidates here: */
660 +
      std::vector<pkgCache::PkgIterator> candset;
661 +
      for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P))
662 +
      {
663 +
	 if (PackageOps.find(P.FullName()) != PackageOps.end())
664 +
	    candset.push_back(P);
665 +
	 // packages can disappear without them having any interaction itself
666 +
	 // so we have to consider these as candidates, too
667 +
	 else if (P->CurrentVer != 0 && action == "disappear")
668 +
	    candset.push_back(P);
669 +
      }
670 +
      if (unlikely(candset.empty()))
671 +
      {
672 +
	 if (Debug == true)
673 +
	    std::clog << "unable to figure out which package is dpkg refering to with '" << pkgname << "'! (1)" << std::endl;
674 +
	 return;
675 +
      }
676 +
      else if (candset.size() == 1) // we are lucky
677 +
	 pkgname = candset.cbegin()->FullName();
678 +
      else
679 +
      {
680 +
	 /* here be dragons^Wassumptions about dpkg:
681 +
	    - an M-A:same version is always arch-qualified
682 +
	    - a package from a foreign arch is (in newer versions) */
683 +
	 size_t installedInstances = 0, wannabeInstances = 0;
684 +
	 for (auto const &P: candset)
685 +
	 {
686 +
	    if (P->CurrentVer != 0)
687 +
	    {
688 +
	       ++installedInstances;
689 +
	       if (Cache[P].Delete() == false)
690 +
		  ++wannabeInstances;
691 +
	    }
692 +
	    else if (Cache[P].Install())
693 +
	       ++wannabeInstances;
694 +
	 }
695 +
	 // the package becomes M-A:same, so we are still talking about current
696 +
	 if (installedInstances == 1 && wannabeInstances >= 2)
697 +
	 {
698 +
	    for (auto const &P: candset)
673 699
	    {
674 -
	       auto fullname = P.FullName();
675 -
	       if (Cache[P].Delete() && PackageOps[fullname].size() <= PackageOpsDone[fullname])
700 +
	       if (P->CurrentVer == 0)
676 701
		  continue;
677 -
	       pkgname = std::move(fullname);
702 +
	       pkgname = P.FullName();
703 +
	       break;
704 +
	    }
705 +
	 }
706 +
	 // the package was M-A:same, it isn't now, so we can only talk about that
707 +
	 else if (installedInstances >= 2 && wannabeInstances == 1)
708 +
	 {
709 +
	    for (auto const &P: candset)
710 +
	    {
711 +
	       auto const IV = Cache[P].InstVerIter(Cache);
712 +
	       if (IV.end())
713 +
		  continue;
714 +
	       pkgname = P.FullName();
678 715
	       break;
679 716
	    }
717 +
	 }
718 +
	 // that is a crossgrade
719 +
	 else if (installedInstances == 1 && wannabeInstances == 1 && candset.size() == 2)
720 +
	 {
721 +
	    auto const PkgHasCurrentVersion = [](pkgCache::PkgIterator const &P) { return P->CurrentVer != 0; };
722 +
	    auto const P = std::find_if(candset.begin(), candset.end(), PkgHasCurrentVersion);
723 +
	    if (unlikely(P == candset.end()))
724 +
	    {
725 +
	       if (Debug == true)
726 +
		  std::clog << "situation for '" << pkgname << "' looked like a crossgrade, but no current version?!" << std::endl;
727 +
	       return;
728 +
	    }
729 +
	    auto fullname = P->FullName();
730 +
	    if (PackageOps[fullname].size() != PackageOpsDone[fullname])
731 +
	       pkgname = std::move(fullname);
732 +
	    else
733 +
	       pkgname = std::find_if_not(candset.begin(), candset.end(), PkgHasCurrentVersion)->FullName();
734 +
	 }
735 +
	 // we are desperate: so "just" take the native one, but that might change mid-air,
736 +
	 // so we have to ask dpkg what it believes native is at the moment… all the time
737 +
	 else
738 +
	 {
739 +
	    std::vector<std::string> sArgs = debSystem::GetDpkgBaseCommand();
740 +
	    sArgs.push_back("--print-architecture");
741 +
	    int outputFd = -1;
742 +
	    pid_t const dpkgNativeArch = debSystem::ExecDpkg(sArgs, nullptr, &outputFd, true);
743 +
	    if (unlikely(dpkgNativeArch == -1))
744 +
	    {
745 +
	       if (Debug == true)
746 +
		  std::clog << "calling dpkg failed to ask it for its current native architecture to expand '" << pkgname << "'!" << std::endl;
747 +
	       return;
748 +
	    }
749 +
	    FILE *dpkg = fdopen(outputFd, "r");
750 +
	    if(dpkg != NULL)
751 +
	    {
752 +
	       char* buf = NULL;
753 +
	       size_t bufsize = 0;
754 +
	       if (getline(&buf, &bufsize, dpkg) != -1)
755 +
		  pkgname += ':' + bufsize;
756 +
	       free(buf);
757 +
	       fclose(dpkg);
758 +
	    }
759 +
	    ExecWait(dpkgNativeArch, "dpkg --print-architecture", true);
760 +
	    if (pkgname.find(':') != std::string::npos)
761 +
	    {
762 +
	       if (Debug == true)
763 +
		  std::clog << "unable to figure out which package is dpkg refering to with '" << pkgname << "'! (2)" << std::endl;
764 +
	       return;
765 +
	    }
766 +
	 }
767 +
      }
680 768
   }
681 769
682 770
   std::string arch = "";
@@ -690,10 +778,7 @@
Loading
690 778
   // 'processing: action: pkg'
691 779
   if(prefix == "processing")
692 780
   {
693 -
      const std::pair<const char *, const char *> * const iter =
694 -
	std::find_if(PackageProcessingOpsBegin,
695 -
		     PackageProcessingOpsEnd,
696 -
		     MatchProcessingOp(action.c_str()));
781 +
      auto const iter = std::find_if(PackageProcessingOpsBegin, PackageProcessingOpsEnd, MatchProcessingOp(action.c_str()));
697 782
      if(iter == PackageProcessingOpsEnd)
698 783
      {
699 784
	 if (Debug == true)
@@ -709,24 +794,15 @@
Loading
709 794
      //         short pkgnames?
710 795
      if (action == "disappear")
711 796
	 handleDisappearAction(pkgname);
797 +
      else if (action == "upgrade")
798 +
	 handleCrossUpgradeAction(pkgname);
712 799
      return;
713 800
   }
714 801
715 802
   if (prefix == "status")
716 803
   {
717 804
      std::vector<struct DpkgState> &states = PackageOps[pkgname];
718 -
      if (action == "triggers-pending")
719 -
      {
720 -
	 if (Debug == true)
721 -
	    std::clog << "(parsed from dpkg) pkg: " << pkgname
722 -
	       << " action: " << action << " (prefix 2 to "
723 -
	       << PackageOpsDone[pkgname] << " of " << states.size() << ")" << endl;
724 -
725 -
	 states.insert(states.begin(), {"installed", N_("Installed %s")});
726 -
	 states.insert(states.begin(), {"half-configured", N_("Configuring %s")});
727 -
	 PackagesTotal += 2;
728 -
      }
729 -
      else if(PackageOpsDone[pkgname] < states.size())
805 +
      if(PackageOpsDone[pkgname] < states.size())
730 806
      {
731 807
	 char const * next_action = states[PackageOpsDone[pkgname]].state;
732 808
	 if (next_action)
@@ -763,36 +839,19 @@
Loading
763 839
	       strprintf(msg, translation, i18n_pkgname.c_str());
764 840
	       d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
765 841
	    }
766 -
	    else if (action == "unpacked" && strcmp(next_action, "config-files") == 0)
767 -
	    {
768 -
	       // in a crossgrade what looked like a remove first is really an unpack over it
769 -
	       ++PackageOpsDone[pkgname];
770 -
	       ++PackagesDone;
771 -
772 -
	       auto const Pkg = Cache.FindPkg(pkgname);
773 -
	       if (likely(Pkg.end() == false))
774 -
	       {
775 -
		  auto const Grp = Pkg.Group();
776 -
		  if (likely(Grp.end() == false))
777 -
		  {
778 -
		     for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P))
779 -
			if(Cache[P].Install())
780 -
			{
781 -
			   auto && Ops = PackageOps[P.FullName()];
782 -
			   auto const unpackOp = std::find_if(Ops.cbegin(), Ops.cend(), [](DpkgState const &s) { return strcmp(s.state, "unpacked") == 0; });
783 -
			   if (unpackOp != Ops.cend())
784 -
			   {
785 -
			      auto const skipped = std::distance(Ops.cbegin(), unpackOp);
786 -
			      PackagesDone += skipped;
787 -
			      PackageOpsDone[P.FullName()] += skipped;
788 -
			      break;
789 -
			   }
790 -
			}
791 -
		  }
792 -
	       }
793 -
	    }
794 842
	 }
795 843
      }
844 +
      else if (action == "triggers-pending")
845 +
      {
846 +
	 if (Debug == true)
847 +
	    std::clog << "(parsed from dpkg) pkg: " << pkgname
848 +
	       << " action: " << action << " (prefix 2 to "
849 +
	       << PackageOpsDone[pkgname] << " of " << states.size() << ")" << endl;
850 +
851 +
	 states.insert(states.begin(), {"installed", N_("Installed %s")});
852 +
	 states.insert(states.begin(), {"half-configured", N_("Configuring %s")});
853 +
	 PackagesTotal += 2;
854 +
      }
796 855
   }
797 856
}
798 857
									/*}}}*/
@@ -803,6 +862,12 @@
Loading
803 862
   if (unlikely(Pkg.end() == true))
804 863
      return;
805 864
865 +
   // a disappeared package has no further actions
866 +
   auto const ROps = PackageOps[Pkg.FullName()].size();
867 +
   auto && ROpsDone = PackageOpsDone[Pkg.FullName()];
868 +
   PackagesDone += ROps - ROpsDone;
869 +
   ROpsDone = ROps;
870 +
806 871
   // record the package name for display and stuff later
807 872
   disappearedPkgs.insert(Pkg.FullName(true));
808 873
@@ -844,6 +909,38 @@
Loading
844 909
   }
845 910
}
846 911
									/*}}}*/
912 +
void pkgDPkgPM::handleCrossUpgradeAction(string const &pkgname)		/*{{{*/
913 +
{
914 +
   // in a crossgrade what looked like a remove first is really an unpack over it
915 +
   auto const Pkg = Cache.FindPkg(pkgname);
916 +
   if (likely(Pkg.end() == false) && Cache[Pkg].Delete())
917 +
   {
918 +
      auto const Grp = Pkg.Group();
919 +
      if (likely(Grp.end() == false))
920 +
      {
921 +
	 for (auto P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P))
922 +
	    if(Cache[P].Install())
923 +
	    {
924 +
	       auto && Ops = PackageOps[P.FullName()];
925 +
	       auto const unpackOp = std::find_if(Ops.cbegin(), Ops.cend(), [](DpkgState const &s) { return strcmp(s.state, "unpacked") == 0; });
926 +
	       if (unpackOp != Ops.cend())
927 +
	       {
928 +
		  // skip ahead in the crossgraded packages
929 +
		  auto const skipped = std::distance(Ops.cbegin(), unpackOp);
930 +
		  PackagesDone += skipped;
931 +
		  PackageOpsDone[P.FullName()] += skipped;
932 +
		  // finish the crossremoved package
933 +
		  auto const ROps = PackageOps[Pkg.FullName()].size();
934 +
		  auto && ROpsDone = PackageOpsDone[Pkg.FullName()];
935 +
		  PackagesDone += ROps - ROpsDone;
936 +
		  ROpsDone = ROps;
937 +
		  break;
938 +
	       }
939 +
	    }
940 +
      }
941 +
   }
942 +
}
943 +
									/*}}}*/
847 944
// DPkgPM::DoDpkgStatusFd						/*{{{*/
848 945
void pkgDPkgPM::DoDpkgStatusFd(int statusfd)
849 946
{
@@ -1087,6 +1184,18 @@
Loading
1087 1184
	 ++PackagesTotal;
1088 1185
	 return true;
1089 1186
      });
1187 +
      if ((I.Op == Item::Remove || I.Op == Item::Purge) && I.Pkg->CurrentVer != 0)
1188 +
      {
1189 +
	 if (I.Pkg->CurrentState == pkgCache::State::UnPacked ||
1190 +
	       I.Pkg->CurrentState == pkgCache::State::HalfInstalled)
1191 +
	 {
1192 +
	    if (likely(strcmp(PackageOps[name][0].state, "half-configured") == 0))
1193 +
	    {
1194 +
	       ++PackageOpsDone[name];
1195 +
	       --PackagesTotal;
1196 +
	    }
1197 +
	 }
1198 +
      }
1090 1199
   }
1091 1200
   /* one extra: We don't want the progress bar to reach 100%, especially not
1092 1201
      if we call dpkg --configure --pending and process a bunch of triggers
@@ -1327,7 +1436,8 @@
Loading
1327 1436
	 if (I.Op == Item::Install && alreadyConfigured.insert(I.Pkg->ID).second == true)
1328 1437
	    AppendList.emplace_back(Item::Configure, I.Pkg);
1329 1438
      for (auto Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
1330 -
	 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure && alreadyConfigured.insert(Pkg->ID).second == true)
1439 +
	 if (Pkg.State() == pkgCache::PkgIterator::NeedsConfigure &&
1440 +
	       Cache[Pkg].Delete() == false && alreadyConfigured.insert(Pkg->ID).second == true)
1331 1441
	    AppendList.emplace_back(Item::Configure, Pkg);
1332 1442
      std::move(AppendList.begin(), AppendList.end(), std::back_inserter(List));
1333 1443
   }
@@ -1397,7 +1507,7 @@
Loading
1397 1507
	 dpkg_recursive_install = Cache.VS().CmpVersion("1.18.5", dpkgpkg.CurrentVer().VerStr()) <= 0;
1398 1508
   }
1399 1509
   // no point in doing this dance for a handful of packages only
1400 -
   unsigned int const dpkg_recursive_install_min = _config->FindB("dpkg::install::recursive::minimum", 5);
1510 +
   unsigned int const dpkg_recursive_install_min = _config->FindI("dpkg::install::recursive::minimum", 5);
1401 1511
   // FIXME: workaround for dpkg bug, see our ./test-bug-740843-versioned-up-down-breaks test
1402 1512
   bool const dpkg_recursive_install_numbered = _config->FindB("dpkg::install::recursive::numbered", true);
1403 1513
@@ -1428,11 +1538,30 @@
Loading
1428 1538
	    continue;
1429 1539
1430 1540
	 auto const Grp = I->Pkg.Group();
1431 -
	 size_t installedInstances = 0;
1541 +
	 size_t installedInstances = 0, wannabeInstances = 0;
1542 +
	 bool multiArchInstances = false;
1432 1543
	 for (auto Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
1433 -
	    if (Pkg->CurrentVer != 0 || Cache[Pkg].Install())
1544 +
	 {
1545 +
	    if (Pkg->CurrentVer != 0)
1546 +
	    {
1434 1547
	       ++installedInstances;
1435 -
	 if (installedInstances == 2)
1548 +
	       if (Cache[Pkg].Delete() == false)
1549 +
		  ++wannabeInstances;
1550 +
	    }
1551 +
	    else if (PackageOps.find(Pkg.FullName()) != PackageOps.end())
1552 +
	       ++wannabeInstances;
1553 +
	    if (multiArchInstances == false)
1554 +
	    {
1555 +
	       auto const V = Cache[Pkg].InstVerIter(Cache);
1556 +
	       if (V.end() == false && (Pkg->CurrentVer == 0 || V != Pkg.CurrentVer()))
1557 +
		  multiArchInstances = ((V->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same);
1558 +
	    }
1559 +
	 }
1560 +
	 /* theoretically the installed check would be enough as some wannabe will
1561 +
	    be first and hence be the crossgrade we were looking for, but #844300
1562 +
	    prevents this so we keep these situations explicit removes.
1563 +
	    It is also the reason why neither of them can be a M-A:same package */
1564 +
	 if (installedInstances == 1 && wannabeInstances == 1 && multiArchInstances == false)
1436 1565
	 {
1437 1566
	    auto const FirstInstall = std::find_if_not(I, List.end(),
1438 1567
		  [](Item const &i) { return i.Op == Item::Remove || i.Op == Item::Purge; });
@@ -1994,6 +2123,24 @@
Loading
1994 2123
1995 2124
   if (noopDPkgInvocation == false)
1996 2125
   {
2126 +
      if (d->dpkg_error.empty() && (PackagesDone + 1) != PackagesTotal)
2127 +
      {
2128 +
	 std::string pkglist;
2129 +
	 for (auto const &PO: PackageOps)
2130 +
	    if (PO.second.size() != PackageOpsDone[PO.first])
2131 +
	    {
2132 +
	       if (pkglist.empty() == false)
2133 +
		  pkglist.append(" ");
2134 +
	       pkglist.append(PO.first);
2135 +
	    }
2136 +
	 /* who cares about correct progress? As we depend on it for skipping actions
2137 +
	    our parsing should be correct. People will no doubt be confused if they see
2138 +
	    this message, but the dpkg warning about unknown packages isn't much better
2139 +
	    from a user POV and combined we might have a chance to figure out what is wrong */
2140 +
	 _error->Warning("APT had planned for dpkg to do more than it reported back (%u vs %u).\n"
2141 +
	       "Affected packages: %s", PackagesDone, PackagesTotal, pkglist.c_str());
2142 +
      }
2143 +
1997 2144
      std::string const oldpkgcache = _config->FindFile("Dir::cache::pkgcache");
1998 2145
      if (oldpkgcache.empty() == false && RealFileExists(oldpkgcache) == true &&
1999 2146
	  RemoveFile("pkgDPkgPM::Go", oldpkgcache))
@@ -2000 +2147 @@
Loading

@@ -931,14 +931,18 @@
Loading
931 931
}
932 932
									/*}}}*/
933 933
// EDSP::WriteError - format an error message to be send to file descriptor /*{{{*/
934 +
static std::string formatMessage(std::string const &msg)
935 +
{
936 +
	return SubstVar(SubstVar(APT::String::Strip(msg), "\n\n", "\n.\n"), "\n", "\n ");
937 +
}
934 938
bool EDSP::WriteError(char const * const uuid, std::string const &message, FILE* output) {
935 939
	fprintf(output, "Error: %s\n", uuid);
936 -
	fprintf(output, "Message: %s\n\n", SubstVar(SubstVar(message, "\n\n", "\n.\n"), "\n", "\n ").c_str());
940 +
	fprintf(output, "Message: %s\n\n", formatMessage(message).c_str());
937 941
	return true;
938 942
}
939 943
bool EDSP::WriteError(char const * const uuid, std::string const &message, FileFd &output) {
940 944
	return WriteOkay(output, "Error: ", uuid, "\n",
941 -
	      "Message: ", SubstVar(SubstVar(message, "\n\n", "\n.\n"), "\n", "\n "),
945 +
	      "Message: ", formatMessage(message),
942 946
	      "\n\n");
943 947
}
944 948
									/*}}}*/
@@ -945 +949 @@
Loading

@@ -662,12 +662,14 @@
Loading
662 662
	 FileFd inp, out;
663 663
	 if (inp.Open(Path, FileFd::ReadOnly, FileFd::Extension) == false)
664 664
	 {
665 -
	    std::cerr << "FAILED to open inp " << Path << std::endl;
665 +
	    if (Debug == true)
666 +
	       std::clog << "FAILED to open inp " << Path << std::endl;
666 667
	    return _error->Error("Failed to open inp %s", Path.c_str());
667 668
	 }
668 669
	 if (out.Open(Itm->DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Empty | FileFd::BufferedWrite, FileFd::Extension) == false)
669 670
	 {
670 -
	    std::cerr << "FAILED to open out " << Itm->DestFile << std::endl;
671 +
	    if (Debug == true)
672 +
	       std::clog << "FAILED to open out " << Itm->DestFile << std::endl;
671 673
	    return _error->Error("Failed to open out %s", Itm->DestFile.c_str());
672 674
	 }
673 675
@@ -686,7 +688,8 @@
Loading
686 688
	 inp.Close();
687 689
688 690
	 if (_error->PendingError() == true) {
689 -
	    std::cerr << "FAILED to read or write files" << std::endl;
691 +
	    if (Debug == true)
692 +
	       std::clog << "FAILED to read or write files" << std::endl;
690 693
	    return false;
691 694
	 }
692 695
@@ -693 +696 @@
Loading

@@ -367,7 +367,7 @@
Loading
367 367
   }
368 368
369 369
   CacheFile Cache;
370 -
   if (Cache.Open() == false)
370 +
   if (Cache.Open(false) == false)
371 371
      return false;
372 372
373 373
   LogCleaner Cleaner;
@@ -374 +374 @@
Loading

@@ -2778,9 +2778,9 @@
Loading
2778 2778
   return result;
2779 2779
}
2780 2780
									/*}}}*/
2781 -
std::string GetTempDir()						/*{{{*/
2781 +
static std::string APT_NONNULL(1) GetTempDirEnv(char const * const env)	/*{{{*/
2782 2782
{
2783 -
   const char *tmpdir = getenv("TMPDIR");
2783 +
   const char *tmpdir = getenv(env);
2784 2784
2785 2785
#ifdef P_tmpdir
2786 2786
   if (!tmpdir)
@@ -2792,10 +2792,15 @@
Loading
2792 2792
	 stat(tmpdir, &st) != 0 || (st.st_mode & S_IFDIR) == 0) // exists and is directory
2793 2793
      tmpdir = "/tmp";
2794 2794
   else if (geteuid() != 0 && // root can do everything anyway
2795 -
	 faccessat(-1, tmpdir, R_OK | W_OK | X_OK, AT_EACCESS | AT_SYMLINK_NOFOLLOW) != 0) // current user has rwx access to directory
2795 +
	 faccessat(AT_FDCWD, tmpdir, R_OK | W_OK | X_OK, AT_EACCESS) != 0) // current user has rwx access to directory
2796 2796
      tmpdir = "/tmp";
2797 2797
2798 2798
   return string(tmpdir);
2799 +
}
2800 +
									/*}}}*/
2801 +
std::string GetTempDir()						/*{{{*/
2802 +
{
2803 +
   return GetTempDirEnv("TMPDIR");
2799 2804
}
2800 2805
std::string GetTempDir(std::string const &User)
2801 2806
{
@@ -3051,6 +3056,32 @@
Loading
3051 3056
	 return _error->Error("Could restore a uid to root, privilege dropping did not work");
3052 3057
   }
3053 3058
3059 +
   if (_config->FindB("APT::Sandbox::ResetEnvironment", true))
3060 +
   {
3061 +
      setenv("HOME", pw->pw_dir, 1);
3062 +
      setenv("USER", pw->pw_name, 1);
3063 +
      setenv("USERNAME", pw->pw_name, 1);
3064 +
      setenv("LOGNAME", pw->pw_name, 1);
3065 +
      auto const shell = flNotDir(pw->pw_shell);
3066 +
      if (shell == "false" || shell == "nologin")
3067 +
	 setenv("SHELL", "/bin/sh", 1);
3068 +
      else
3069 +
	 setenv("SHELL", pw->pw_shell, 1);
3070 +
      auto const apt_setenv_tmp = [](char const * const env) {
3071 +
	 auto const tmpdir = getenv(env);
3072 +
	 if (tmpdir != nullptr)
3073 +
	 {
3074 +
	    auto const ourtmpdir = GetTempDirEnv(env);
3075 +
	    if (ourtmpdir != tmpdir)
3076 +
	       setenv(env, ourtmpdir.c_str(), 1);
3077 +
	 }
3078 +
      };
3079 +
      apt_setenv_tmp("TMPDIR");
3080 +
      apt_setenv_tmp("TEMPDIR");
3081 +
      apt_setenv_tmp("TMP");
3082 +
      apt_setenv_tmp("TEMP");
3083 +
   }
3084 +
3054 3085
   return true;
3055 3086
}
3056 3087
									/*}}}*/
@@ -3057 +3088 @@
Loading

@@ -779,7 +779,7 @@
Loading
779 779
 */
780 780
class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex
781 781
{
782 -
   void * const d;
782 +
   std::string const indexURI;
783 783
784 784
   protected:
785 785
@@ -830,23 +830,19 @@
Loading
830 830
   /** \brief Create an index merge-diff item.
831 831
    *
832 832
    *  \param Owner The pkgAcquire object that owns this item.
833 -
    *
834 -
    *  \param URI The URI of the package index file being
835 -
    *  reconstructed.
836 -
    *
837 -
    *  \param URIDesc A long description of this item.
838 -
    *
839 -
    *  \param ShortDesc A brief description of this item.
840 -
    *
833 +
    *  \param TransactionManager responsible for this item
834 +
    *  \param Target we intend to built via pdiff patching
835 +
    *  \param baseURI is the URI used for the Index, but stripped down to Target
836 +
    *  \param DiffInfo of the patch in question
841 837
    *  \param patch contains infos about the patch this item is supposed
842 838
    *  to download which were read from the index
843 -
    *
844 839
    *  \param allPatches contains all related items so that each item can
845 840
    *  check if it was the last one to complete the download step
846 841
    */
847 842
   pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager,
848 -
                         IndexTarget const &Target, DiffInfo const &patch,
849 -
                         std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches) APT_NONNULL(2, 3, 6);
843 +
			 IndexTarget const &Target, std::string const &indexUsedMirror,
844 +
			 std::string const &indexURI, DiffInfo const &patch,
845 +
                         std::vector<pkgAcqIndexMergeDiffs*> const * const allPatches) APT_NONNULL(2, 3, 8);
850 846
   virtual ~pkgAcqIndexMergeDiffs();
851 847
};
852 848
									/*}}}*/
@@ -863,7 +859,7 @@
Loading
863 859
 */
864 860
class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex
865 861
{
866 -
   void * const d;
862 +
   std::string const indexURI;
867 863
868 864
   private:
869 865
@@ -943,20 +939,16 @@
Loading
943 939
    *  \a diffs is empty, or QueueNextDiff() otherwise.
944 940
    *
945 941
    *  \param Owner The pkgAcquire object that owns this item.
946 -
    *
947 -
    *  \param URI The URI of the package index file being
948 -
    *  reconstructed.
949 -
    *
950 -
    *  \param URIDesc A long description of this item.
951 -
    *
952 -
    *  \param ShortDesc A brief description of this item.
953 -
    *
942 +
    *  \param TransactionManager responsible for this item
943 +
    *  \param Target we want to built via pdiff patching
944 +
    *  \param baseURI is the URI used for the Index, but stripped down to Target
954 945
    *  \param diffs The remaining diffs from the index of diffs.  They
955 946
    *  should be ordered so that each diff appears before any diff
956 947
    *  that depends on it.
957 948
    */
958 949
   pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager,
959 950
                    IndexTarget const &Target,
951 +
		    std::string const &indexUsedMirror, std::string const &indexURI,
960 952
		    std::vector<DiffInfo> const &diffs=std::vector<DiffInfo>()) APT_NONNULL(2, 3);
961 953
   virtual ~pkgAcqIndexDiffs();
962 954
};
@@ -963 +955 @@
Loading

@@ -136,16 +136,19 @@
Loading
136 136
       _error->PendingError() == true)
137 137
      return false;
138 138
139 -
   if (_config->FindB("APT::Get::Fix-Missing",false) == true &&
140 -
	 _config->FindB("APT::Get::Download",true) == false)
139 +
   if (_config->FindB("APT::Get::Download",true) == false)
141 140
   {
142 141
      bool Missing = false;
143 142
      RemoveDownloadNeedingItemsFromFetcher(Fetcher, Missing);
144 143
      if (Missing)
145 -
	 PM->FixMissing();
144 +
      {
145 +
	 if (_config->FindB("APT::Get::Fix-Missing",false))
146 +
	    PM->FixMissing();
147 +
	 else
148 +
	    return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
149 +
      }
146 150
      Fetcher.Shutdown();
147 -
      if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
148 -
	    _error->PendingError() == true)
151 +
      if (_error->PendingError() == true)
149 152
	 return false;
150 153
   }
151 154
@@ -396,7 +399,7 @@
Loading
396 399
/* Remove unused automatic packages */
397 400
bool DoAutomaticRemove(CacheFile &Cache)
398 401
{
399 -
   bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
402 +
   bool Debug = _config->FindB("Debug::pkgAutoRemove",false);
400 403
   bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
401 404
   bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
402 405
@@ -426,11 +429,11 @@
Loading
426 429
      {
427 430
	 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
428 431
	    if(Debug)
429 -
	       std::cout << "We could delete %s" <<  Pkg.FullName(true).c_str() << std::endl;
432 +
	       std::cout << "We could delete " <<  APT::PrettyPkg(Cache, Pkg) << std::endl;
430 433
431 434
	 if (doAutoRemove)
432 435
	 {
433 -
	    if(Pkg.CurrentVer() != 0 && 
436 +
	    if(Pkg.CurrentVer() != 0 &&
434 437
	       Pkg->CurrentState != pkgCache::State::ConfigFiles)
435 438
	       Cache->MarkDelete(Pkg, purgePkgs, 0, false);
436 439
	    else
@@ -475,11 +478,25 @@
Loading
475 478
		  if (R.IsNegative() == true ||
476 479
		      Cache->IsImportantDep(R) == false)
477 480
		     continue;
478 -
		 pkgCache::PkgIterator N = R.ParentPkg();
479 -
		 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
481 +
		 auto const RV = R.ParentVer();
482 +
		 if (unlikely(RV.end() == true))
483 +
		    continue;
484 +
		 auto const RP = RV.ParentPkg();
485 +
		 // check if that dependency comes from an interesting version
486 +
		 if (RP.CurrentVer() == RV)
487 +
		 {
488 +
		    if ((*Cache)[RP].Keep() == false)
489 +
		       continue;
490 +
		 }
491 +
		 else if (Cache[RP].CandidateVerIter(Cache) == RV)
492 +
		 {
493 +
		    if ((*Cache)[RP].NewInstall() == false && (*Cache)[RP].Upgrade() == false)
494 +
		       continue;
495 +
		 }
496 +
		 else // ignore dependency from a non-candidate version
480 497
		    continue;
481 498
		 if (Debug == true)
482 -
		    std::clog << "Save " << APT::PrettyPkg(Cache, Pkg) << " as another installed garbage package depends on it" << std::endl;
499 +
		    std::clog << "Save " << APT::PrettyPkg(Cache, Pkg) << " as another installed package depends on it: " << APT::PrettyPkg(Cache, RP) << std::endl;
483 500
		 Cache->MarkInstall(Pkg, false, 0, false);
484 501
		 if (hideAutoRemove == false)
485 502
		    ++autoRemoveCount;
@@ -495,6 +512,8 @@
Loading
495 512
	 }
496 513
      } while (Changed == true);
497 514
   }
515 +
   // trigger marking now so that the package list below is correct
516 +
   group.release();
498 517
499 518
   // Now see if we had destroyed anything (if we had done anything)
500 519
   if (Cache->BrokenCount() != 0)
@@ -501 +520 @@
Loading

@@ -71,19 +71,19 @@
Loading
71 71
      ListUpdate(Stat, *List);
72 72
   }
73 73
74 +
   if (_config->FindB("pkgCacheFile::Generate", true) == false)
75 +
      return true;
76 +
74 77
   // Rebuild the cache.
75 -
   if (_config->FindB("pkgCacheFile::Generate", true) == true)
76 -
   {
77 -
      pkgCacheFile::RemoveCaches();
78 -
      if (Cache.BuildCaches() == false)
79 -
	 return false;
80 -
   }
78 +
   pkgCacheFile::RemoveCaches();
79 +
   if (Cache.BuildCaches(false) == false)
80 +
      return false;
81 81
82 82
   // show basic stats (if the user whishes)
83 83
   if (_config->FindB("APT::Cmd::Show-Update-Stats", false) == true)
84 84
   {
85 85
      int upgradable = 0;
86 -
      if (Cache.Open() == false)
86 +
      if (Cache.Open(false) == false)
87 87
         return false;
88 88
      for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() != true; ++I)
89 89
      {
@@ -90 +90 @@
Loading

@@ -495,7 +495,7 @@
Loading
495 495
      return _error->Error(_("Failed to fetch some archives."));
496 496
   }
497 497
498 -
   if (_config->FindB("APT::Get::Download-only",false) == true)
498 +
   if (diffOnly || tarOnly || dscOnly || _config->FindB("APT::Get::Download-only",false) == true)
499 499
   {
500 500
      c1out << _("Download complete and in download only mode") << std::endl;
501 501
      return true;
@@ -509,13 +509,9 @@
Loading
509 509
      bool const fixBroken = _config->FindB("APT::Get::Fix-Broken", false);
510 510
      for (unsigned I = 0; I != J; ++I)
511 511
      {
512 -
	 std::string Dir = Dsc[I].Package + '-' + Cache.GetPkgCache()->VS->UpstreamVersion(Dsc[I].Version.c_str());
513 -
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)
512 +
	 if (unlikely(Dsc[I].Dsc.empty() == true))
518 513
	    continue;
514 +
	 std::string const Dir = Dsc[I].Package + '-' + Cache.GetPkgCache()->VS->UpstreamVersion(Dsc[I].Version.c_str());
519 515
520 516
	 // See if the package is already unpacked
521 517
	 struct stat Stat;
@@ -522 +518 @@
Loading

@@ -117,6 +117,12 @@
Loading
117 117
   if (chmod(partial.c_str(), 0700) != 0)
118 118
      _error->WarningE("SetupAPTPartialDirectory", "chmod 0700 of directory %s failed", partial.c_str());
119 119
120 +
   _error->PushToStack();
121 +
   // remove 'old' FAILED files to stop us from collecting them for no reason
122 +
   for (auto const &Failed: GetListOfFilesInDir(partial, "FAILED", false, false))
123 +
      RemoveFile("SetupAPTPartialDirectory", Failed);
124 +
   _error->RevertToStack();
125 +
120 126
   return true;
121 127
}
122 128
bool pkgAcquire::Setup(pkgAcquireStatus *Progress, string const &Lock)
@@ -894,11 +900,27 @@
Loading
894 900
/* */
895 901
bool pkgAcquire::Queue::Enqueue(ItemDesc &Item)
896 902
{
903 +
   // MetaKeysMatch checks whether the two items have no non-matching
904 +
   // meta-keys. If the items are not transaction items, it returns
905 +
   // true, so other items can still be merged.
906 +
   auto MetaKeysMatch = [](pkgAcquire::ItemDesc const &A, pkgAcquire::Queue::QItem const *B) {
907 +
      auto OwnerA = dynamic_cast<pkgAcqTransactionItem*>(A.Owner);
908 +
      if (OwnerA == nullptr)
909 +
	 return true;
910 +
911 +
      for (auto const & OwnerBUncast : B->Owners) {
912 +
	 auto OwnerB = dynamic_cast<pkgAcqTransactionItem*>(OwnerBUncast);
913 +
914 +
	 if (OwnerB != nullptr && OwnerA->GetMetaKey() != OwnerB->GetMetaKey())
915 +
	    return false;
916 +
      }
917 +
      return true;
918 +
   };
897 919
   QItem **OptimalI = &Items;
898 920
   QItem **I = &Items;
899 921
   // move to the end of the queue and check for duplicates here
900 922
   for (; *I != 0; ) {
901 -
      if (Item.URI == (*I)->URI)
923 +
      if (Item.URI == (*I)->URI && MetaKeysMatch(Item, *I))
902 924
      {
903 925
	 if (_config->FindB("Debug::pkgAcquire::Worker",false) == true)
904 926
	    std::cerr << " @ Queue: Action combined for " << Item.URI << " and " << (*I)->URI << std::endl;
@@ -1154,7 +1176,7 @@
Loading
1154 1176
   return Maximum;
1155 1177
}
1156 1178
									/*}}}*/
1157 -
APT_PURE int pkgAcquire::Queue::QItem::GetPriority() const	/*{{{*/
1179 +
APT_PURE int pkgAcquire::Queue::QItem::GetPriority() const		/*{{{*/
1158 1180
{
1159 1181
   int Priority = 0;
1160 1182
   for (auto const &O: Owners)
@@ -1161 +1183 @@
Loading

@@ -1363,41 +1363,43 @@
Loading
1363 1363
   ScopedErrorRevert() { _error->PushToStack(); }
1364 1364
   ~ScopedErrorRevert() { _error->RevertToStack(); }
1365 1365
};
1366 -
static bool CheckValidity(const string &CacheFile,
1366 +
static bool CheckValidity(FileFd &CacheFile, std::string const &CacheFileName,
1367 1367
                          pkgSourceList &List,
1368 1368
                          FileIterator const Start,
1369 1369
                          FileIterator const End,
1370 1370
                          MMap **OutMap = 0,
1371 1371
			  pkgCache **OutCache = 0)
1372 1372
{
1373 +
   if (CacheFileName.empty())
1374 +
      return false;
1373 1375
   ScopedErrorRevert ser;
1376 +
1374 1377
   bool const Debug = _config->FindB("Debug::pkgCacheGen", false);
1375 1378
   // No file, certainly invalid
1376 -
   if (CacheFile.empty() == true || FileExists(CacheFile) == false)
1379 +
   if (CacheFile.Open(CacheFileName, FileFd::ReadOnly, FileFd::None) == false)
1377 1380
   {
1378 1381
      if (Debug == true)
1379 -
	 std::clog << "CacheFile " << CacheFile << " doesn't exist" << std::endl;
1382 +
	 std::clog << "CacheFile " << CacheFileName << " doesn't exist" << std::endl;
1380 1383
      return false;
1381 1384
   }
1382 1385
1383 -
   if (List.GetLastModifiedTime() > GetModificationTime(CacheFile))
1386 +
   if (List.GetLastModifiedTime() > CacheFile.ModificationTime())
1384 1387
   {
1385 1388
      if (Debug == true)
1386 1389
	 std::clog << "sources.list is newer than the cache" << std::endl;
1387 1390
      return false;
1388 1391
   }
1389 1392
1390 1393
   // Map it
1391 -
   FileFd CacheF(CacheFile,FileFd::ReadOnly);
1392 -
   std::unique_ptr<MMap> Map(new MMap(CacheF,0));
1394 +
   std::unique_ptr<MMap> Map(new MMap(CacheFile,0));
1393 1395
   if (unlikely(Map->validData()) == false)
1394 1396
      return false;
1395 1397
   std::unique_ptr<pkgCache> CacheP(new pkgCache(Map.get()));
1396 1398
   pkgCache &Cache = *CacheP.get();
1397 1399
   if (_error->PendingError() || Map->Size() == 0)
1398 1400
   {
1399 1401
      if (Debug == true)
1400 -
	 std::clog << "Errors are pending or Map is empty() for " << CacheFile << std::endl;
1402 +
	 std::clog << "Errors are pending or Map is empty() for " << CacheFileName << std::endl;
1401 1403
      return false;
1402 1404
   }
1403 1405
@@ -1623,13 +1625,12 @@
Loading
1623 1625
   return true;
1624 1626
}
1625 1627
static bool loadBackMMapFromFile(std::unique_ptr<pkgCacheGenerator> &Gen,
1626 -
      std::unique_ptr<DynamicMMap> &Map, OpProgress * const Progress, std::string const &FileName)
1628 +
      std::unique_ptr<DynamicMMap> &Map, OpProgress * const Progress, FileFd &CacheF)
1627 1629
{
1628 1630
   Map.reset(CreateDynamicMMap(NULL, 0));
1629 1631
   if (unlikely(Map->validData()) == false)
1630 1632
      return false;
1631 -
   FileFd CacheF(FileName, FileFd::ReadOnly);
1632 -
   if (CacheF.IsOpen() == false || CacheF.Failed())
1633 +
   if (CacheF.IsOpen() == false || CacheF.Seek(0) == false || CacheF.Failed())
1633 1634
      return false;
1634 1635
   _error->PushToStack();
1635 1636
   map_pointer_t const alloc = Map->RawAllocate(CacheF.Size());
@@ -1661,20 +1662,20 @@
Loading
1661 1662
      return false;
1662 1663
1663 1664
   // Decide if we can write to the files..
1664 -
   string const CacheFile = _config->FindFile("Dir::Cache::pkgcache");
1665 -
   string const SrcCacheFile = _config->FindFile("Dir::Cache::srcpkgcache");
1665 +
   string const CacheFileName = _config->FindFile("Dir::Cache::pkgcache");
1666 +
   string const SrcCacheFileName = _config->FindFile("Dir::Cache::srcpkgcache");
1666 1667
1667 1668
   // ensure the cache directory exists
1668 -
   if (CacheFile.empty() == false || SrcCacheFile.empty() == false)
1669 +
   if (CacheFileName.empty() == false || SrcCacheFileName.empty() == false)
1669 1670
   {
1670 1671
      string dir = _config->FindDir("Dir::Cache");
1671 1672
      size_t const len = dir.size();
1672 1673
      if (len > 5 && dir.find("/apt/", len - 6, 5) == len - 5)
1673 1674
	 dir = dir.substr(0, len - 5);
1674 -
      if (CacheFile.empty() == false)
1675 -
	 CreateDirectory(dir, flNotFile(CacheFile));
1676 -
      if (SrcCacheFile.empty() == false)
1677 -
	 CreateDirectory(dir, flNotFile(SrcCacheFile));
1675 +
      if (CacheFileName.empty() == false)
1676 +
	 CreateDirectory(dir, flNotFile(CacheFileName));
1677 +
      if (SrcCacheFileName.empty() == false)
1678 +
	 CreateDirectory(dir, flNotFile(SrcCacheFileName));
1678 1679
   }
1679 1680
1680 1681
   if (Progress != NULL)
@@ -1683,18 +1684,20 @@
Loading
1683 1684
   bool pkgcache_fine = false;
1684 1685
   bool srcpkgcache_fine = false;
1685 1686
   bool volatile_fine = List.GetVolatileFiles().empty();
1686 -
1687 -
   if (CheckValidity(CacheFile, List, Files.begin(), Files.end(), volatile_fine ? OutMap : NULL,
1687 +
   FileFd CacheFile;
1688 +
   if (CheckValidity(CacheFile, CacheFileName, List, Files.begin(), Files.end(), volatile_fine ? OutMap : NULL,
1688 1689
		     volatile_fine ? OutCache : NULL) == true)
1689 1690
   {
1690 1691
      if (Debug == true)
1691 1692
	 std::clog << "pkgcache.bin is valid - no need to build any cache" << std::endl;
1692 1693
      pkgcache_fine = true;
1693 1694
      srcpkgcache_fine = true;
1694 1695
   }
1696 +
1697 +
   FileFd SrcCacheFile;
1695 1698
   if (pkgcache_fine == false)
1696 1699
   {
1697 -
      if (CheckValidity(SrcCacheFile, List, Files.end(), Files.end()) == true)
1700 +
      if (CheckValidity(SrcCacheFile, SrcCacheFileName, List, Files.end(), Files.end()) == true)
1698 1701
      {
1699 1702
	 if (Debug == true)
1700 1703
	    std::clog << "srcpkgcache.bin is valid - it can be reused" << std::endl;
@@ -1712,10 +1715,10 @@
Loading
1712 1715
   bool Writeable = false;
1713 1716
   if (srcpkgcache_fine == false || pkgcache_fine == false)
1714 1717
   {
1715 -
      if (CacheFile.empty() == false)
1716 -
	 Writeable = access(flNotFile(CacheFile).c_str(),W_OK) == 0;
1717 -
      else if (SrcCacheFile.empty() == false)
1718 -
	 Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0;
1718 +
      if (CacheFileName.empty() == false)
1719 +
	 Writeable = access(flNotFile(CacheFileName).c_str(),W_OK) == 0;
1720 +
      else if (SrcCacheFileName.empty() == false)
1721 +
	 Writeable = access(flNotFile(SrcCacheFileName).c_str(),W_OK) == 0;
1719 1722
1720 1723
      if (Debug == true)
1721 1724
	 std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl;
@@ -1754,8 +1757,8 @@
Loading
1754 1757
	       Files.end(),Files.end()) == false)
1755 1758
	 return false;
1756 1759
1757 -
      if (Writeable == true && SrcCacheFile.empty() == false)
1758 -
	 if (writeBackMMapToFile(Gen.get(), Map.get(), SrcCacheFile) == false)
1760 +
      if (Writeable == true && SrcCacheFileName.empty() == false)
1761 +
	 if (writeBackMMapToFile(Gen.get(), Map.get(), SrcCacheFileName) == false)
1759 1762
	    return false;
1760 1763
   }
1761 1764
@@ -1767,8 +1770,8 @@
Loading
1767 1770
	       Files.begin(), Files.end()) == false)
1768 1771
	 return false;
1769 1772
1770 -
      if (Writeable == true && CacheFile.empty() == false)
1771 -
	 if (writeBackMMapToFile(Gen.get(), Map.get(), CacheFile) == false)
1773 +
      if (Writeable == true && CacheFileName.empty() == false)
1774 +
	 if (writeBackMMapToFile(Gen.get(), Map.get(), CacheFileName) == false)
1772 1775
	    return false;
1773 1776
   }
1774 1777
@@ -1775 +1778 @@
Loading

@@ -180,7 +180,11 @@
Loading
180 180
      return true;
181 181
   }
182 182
183 -
   if (stringcasecmp(Tag,"Content-Range:") == 0)
183 +
   // The Content-Range field only has a meaning in HTTP/1.1 for the
184 +
   // 206 (Partial Content) and 416 (Range Not Satisfiable) responses
185 +
   // according to RFC7233 "Range Requests", §4.2, so only consider it
186 +
   // for such responses.
187 +
   if ((Result == 416 || Result == 206) && stringcasecmp(Tag,"Content-Range:") == 0)
184 188
   {
185 189
      HaveContent = true;
186 190
@@ -770,8 +774,8 @@
Loading
770 774
	 // We need to flush the data, the header is like a 404 w/ error text
771 775
	 case ERROR_WITH_CONTENT_PAGE:
772 776
	 {
773 -
	    Fail();
774 777
	    Server->RunDataToDevNull();
778 +
	    Fail();
775 779
	    break;
776 780
	 }
777 781
@@ -778 +782 @@
Loading

@@ -1144,7 +1144,7 @@
Loading
1144 1144
   pkgCache::PkgIterator I = Cache.PkgBegin();
1145 1145
   for (;I.end() != true; ++I) {
1146 1146
      if (Cache[I].NewInstall() && !(Flags[I->ID] & PreInstalled)) {
1147 -
	 if(_config->FindI("Debug::pkgAutoRemove",false)) {
1147 +
	 if(_config->FindB("Debug::pkgAutoRemove",false)) {
1148 1148
	    std::clog << "Resolve installed new pkg: " << I.FullName(false) 
1149 1149
		      << " (now marking it as auto)" << std::endl;
1150 1150
	 }
@@ -1151 +1151 @@
Loading

@@ -1101,8 +1101,11 @@
Loading
1101 1101
      UseByHash = _config->Find("Acquire::By-Hash", UseByHash);
1102 1102
      {
1103 1103
	 std::string const host = ::URI(URI).Host;
1104 -
	 UseByHash = _config->Find("APT::Acquire::" + host + "::By-Hash", UseByHash);
1105 -
	 UseByHash = _config->Find("Acquire::" + host + "::By-Hash", UseByHash);
1104 +
	 if (host.empty() == false)
1105 +
	 {
1106 +
	    UseByHash = _config->Find("APT::Acquire::" + host + "::By-Hash", UseByHash);
1107 +
	    UseByHash = _config->Find("Acquire::" + host + "::By-Hash", UseByHash);
1108 +
	 }
1106 1109
	 std::map<std::string, std::string>::const_iterator const opt = Options.find("by-hash");
1107 1110
	 if (opt != Options.end())
1108 1111
	    UseByHash = opt->second;
@@ -1109 +1112 @@
Loading

@@ -61,8 +61,19 @@
Loading
61 61
   string Result = Section.Find("Package").to_string();
62 62
63 63
   // Normalize mixed case package names to lower case, like dpkg does
64 -
   // See Bug#807012 for details
65 -
   std::transform(Result.begin(), Result.end(), Result.begin(), tolower_ascii);
64 +
   // See Bug#807012 for details.
65 +
   // Only do this when the package name does not contain a / - as that
66 +
   // indicates that the package name was derived from a filename given
67 +
   // to install or build-dep or similar (Bug#854794)
68 +
   if (likely(Result.find('/') == string::npos))
69 +
   {
70 +
      for (char &c: Result)
71 +
      {
72 +
	 char l = tolower_ascii_inline(c);
73 +
	 if (unlikely(l != c))
74 +
	    c = l;
75 +
      }
76 +
   }
66 77
67 78
   if(unlikely(Result.empty() == true))
68 79
      _error->Error("Encountered a section with no Package: header");
@@ -69 +80 @@
Loading

@@ -365,6 +365,11 @@
Loading
365 365
   curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, DL_MIN_SPEED);
366 366
   curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, timeout);
367 367
368 +
   if(_config->FindB("Acquire::ForceIPv4", false) == true)
369 +
      curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
370 +
   else if(_config->FindB("Acquire::ForceIPv6", false) == true)
371 +
      curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
372 +
368 373
   // debug
369 374
   if (Debug == true)
370 375
      curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
@@ -371 +376 @@
Loading

Learn more Showing 16 files with coverage changes found.

Changes in apt-pkg/acquire-method.cc
-5
+5
Loading file...
Changes in apt-pkg/cacheiterators.h
-1
+1
Loading file...
Changes in apt-pkg/deb/debmetaindex.cc
-2
+2
Loading file...
Changes in apt-private/private-source.cc
-1
+1
Loading file...
Changes in apt-pkg/contrib/fileutl.cc
-2
+2
Loading file...
Changes in apt-pkg/contrib/strutl.cc
-1
+1
Loading file...
methods/file.cc
Loading file...
Changes in apt-private/private-install.cc
-2
+2
Loading file...
Changes in methods/connect.cc
-1
+1
Loading file...
Changes in apt-private/private-moo.cc
-1
+1
Loading file...
Changes in methods/http.cc
-21
+21
Loading file...
Changes in methods/gpgv.cc
-10
+11
Loading file...
Changes in methods/aptmethod.h
-4
+4
Loading file...
Changes in methods/https.cc
-19
+19
Loading file...
Changes in methods/server.cc
-33
+33
Loading file...
Changes in methods/server.h
-1
+1
Loading file...

36 Commits

Hiding 30 contexual commits
Files Coverage
apt-inst 23.56%
apt-pkg -0.14% 78.12%
apt-private 0.09% 85.86%
cmdline 84.90%
ftparchive 74.93%
methods +3.26% 60.64%
test 84.18%
Project Totals (196 files) 77.24%
Loading