Parcourir la source

parse packages from all architectures into the cache

Now that we can dynamically create dependencies and provides as needed
rather than requiring to know with which architectures we will deal
before running we can allow the listparser to parse all records rather
than skipping records of "unknown" architectures.

This can e.g. happen if a user has foreign architecture packages in his
status file without dpkg knowing about this architecture (or apt
configured in this way).

A sideeffect is that now arch:all packages are (correctly) recorded as
available from any Packages file, not just from the native one – which
has its downsides for the resolver as mixed-arch source packages can
appear in different architectures at different times, but that is the
problem of the resolver and dealing with it in the parser is at best a
hack (and also depends on a helpful repository).

Another sideeffect is that his allows :none packages to appear in
Packages files again as we don't do any kind of checks now, but given
that they aren't really supported (anymore) by anyone we can live with
that.
David Kalnischkies il y a 11 ans
Parent
commit
7f8c0eed69

+ 4 - 35
apt-pkg/deb/deblistparser.cc

@@ -50,13 +50,9 @@ static debListParser::WordList PrioList[] = {
 /* Provide an architecture and only this one and "all" will be accepted
 /* Provide an architecture and only this one and "all" will be accepted
    in Step(), if no Architecture is given we will accept every arch
    in Step(), if no Architecture is given we will accept every arch
    we would accept in general with checkArchitecture() */
    we would accept in general with checkArchitecture() */
-debListParser::debListParser(FileFd *File, string const &Arch) :
-   pkgCacheListParser(), d(NULL), Tags(File), Arch(Arch)
+debListParser::debListParser(FileFd *File) :
+   pkgCacheListParser(), d(NULL), Tags(File)
 {
 {
-   if (Arch == "native")
-      this->Arch = _config->Find("APT::Architecture");
-   Architectures = APT::Configuration::getArchitectures();
-   MultiArchEnabled = Architectures.size() > 1;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // ListParser::Package - Return the package name			/*{{{*/
 // ListParser::Package - Return the package name			/*{{{*/
@@ -887,34 +883,7 @@ bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out)
 bool debListParser::Step()
 bool debListParser::Step()
 {
 {
    iOffset = Tags.Offset();
    iOffset = Tags.Offset();
-   while (Tags.Step(Section) == true)
-   {      
-      /* See if this is the correct Architecture, if it isn't then we
-         drop the whole section. A missing arch tag only happens (in theory)
-         inside the Status file, so that is a positive return */
-      string const Architecture = Section.FindS("Architecture");
-
-      if (Arch.empty() == true || Arch == "any" || MultiArchEnabled == false)
-      {
-	 if (APT::Configuration::checkArchitecture(Architecture) == true)
-	    return true;
-	 /* parse version stanzas without an architecture only in the status file
-	    (and as misfortune bycatch flat-archives) */
-	 if ((Arch.empty() == true || Arch == "any") && Architecture.empty() == true)
-	    return true;
-      }
-      else
-      {
-	 if (Architecture == Arch)
-	    return true;
-
-	 if (Architecture == "all" && Arch == _config->Find("APT::Architecture"))
-	    return true;
-      }
-
-      iOffset = Tags.Offset();
-   }   
-   return false;
+   return Tags.Step(Section);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // ListParser::GetPrio - Convert the priority from a string		/*{{{*/
 // ListParser::GetPrio - Convert the priority from a string		/*{{{*/
@@ -950,7 +919,7 @@ bool debListParser::SameVersion(unsigned short const Hash,		/*{{{*/
 									/*}}}*/
 									/*}}}*/
 
 
 debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile)
 debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile)
-   : debListParser(File, ""), DebFile(DebFile)
+   : debListParser(File), DebFile(DebFile)
 {
 {
 }
 }
 
 

+ 3 - 6
apt-pkg/deb/deblistparser.h

@@ -45,9 +45,6 @@ class APT_HIDDEN debListParser : public pkgCacheListParser
    pkgTagFile Tags;
    pkgTagFile Tags;
    pkgTagSection Section;
    pkgTagSection Section;
    map_filesize_t iOffset;
    map_filesize_t iOffset;
-   std::string Arch;
-   std::vector<std::string> Architectures;
-   bool MultiArchEnabled;
 
 
    virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver);
    virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver);
    bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag,
    bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag,
@@ -96,7 +93,7 @@ class APT_HIDDEN debListParser : public pkgCacheListParser
 
 
    APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op);
    APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op);
 
 
-   debListParser(FileFd *File, std::string const &Arch = "");
+   debListParser(FileFd *File);
    virtual ~debListParser();
    virtual ~debListParser();
 };
 };
 
 
@@ -118,8 +115,8 @@ class APT_HIDDEN debTranslationsParser : public debListParser
    virtual std::string Architecture() APT_OVERRIDE { return ""; }
    virtual std::string Architecture() APT_OVERRIDE { return ""; }
    virtual std::string Version() APT_OVERRIDE { return ""; }
    virtual std::string Version() APT_OVERRIDE { return ""; }
 
 
-   debTranslationsParser(FileFd *File, std::string const &Arch = "")
-      : debListParser(File, Arch) {};
+   debTranslationsParser(FileFd *File)
+      : debListParser(File) {};
 };
 };
 
 
 #endif
 #endif

+ 1 - 1
apt-pkg/edsp/edsplistparser.cc

@@ -22,7 +22,7 @@
 									/*}}}*/
 									/*}}}*/
 
 
 // ListParser::edspListParser - Constructor				/*{{{*/
 // ListParser::edspListParser - Constructor				/*{{{*/
-edspListParser::edspListParser(FileFd *File, std::string const &Arch) : debListParser(File, Arch), d(NULL)
+edspListParser::edspListParser(FileFd *File) : debListParser(File), d(NULL)
 {}
 {}
 									/*}}}*/
 									/*}}}*/
 // ListParser::NewVersion - Fill in the version structure		/*{{{*/
 // ListParser::NewVersion - Fill in the version structure		/*{{{*/

+ 1 - 1
apt-pkg/edsp/edsplistparser.h

@@ -38,7 +38,7 @@ class APT_HIDDEN edspListParser : public debListParser
    bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File,
    bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File,
 			std::string const &section);
 			std::string const &section);
 
 
-   edspListParser(FileFd *File, std::string const &Arch = "");
+   edspListParser(FileFd *File);
    virtual ~edspListParser();
    virtual ~edspListParser();
 
 
    protected:
    protected:

+ 1 - 1
apt-pkg/indexfile.cc

@@ -316,7 +316,7 @@ pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg)
    if (Pkg.IsOpen() == false)
    if (Pkg.IsOpen() == false)
       return NULL;
       return NULL;
    _error->PushToStack();
    _error->PushToStack();
-   pkgCacheListParser * const Parser = new debListParser(&Pkg, GetArchitecture());
+   pkgCacheListParser * const Parser = new debListParser(&Pkg);
    bool const newError = _error->PendingError();
    bool const newError = _error->PendingError();
    _error->MergeWithStack();
    _error->MergeWithStack();
    return newError ? NULL : Parser;
    return newError ? NULL : Parser;

+ 37 - 50
apt-pkg/pkgcache.cc

@@ -35,6 +35,8 @@
 #include <stddef.h>
 #include <stddef.h>
 #include <string.h>
 #include <string.h>
 #include <ostream>
 #include <ostream>
+#include <sstream>
+#include <algorithm>
 #include <vector>
 #include <vector>
 #include <string>
 #include <string>
 #include <sys/stat.h>
 #include <sys/stat.h>
@@ -866,10 +868,32 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This describes the version from a release-centric manner. The output is a 
 /* This describes the version from a release-centric manner. The output is a 
    list of Label:Version/Archive */
    list of Label:Version/Archive */
+static std::string PkgFileIteratorToRelString(pkgCache::PkgFileIterator const &File)
+{
+   std::string Res;
+   if (File.Label() != 0)
+      Res = Res + File.Label() + ':';
+
+   if (File.Archive() != 0)
+   {
+      if (File.Version() == 0)
+	 Res += File.Archive();
+      else
+	 Res = Res + File.Version() + '/' +  File.Archive();
+   }
+   else
+   {
+      // No release file, print the host name that this came from
+      if (File.Site() == 0 || File.Site()[0] == 0)
+	 Res += "localhost";
+      else
+	 Res += File.Site();
+   }
+   return Res;
+}
 string pkgCache::VerIterator::RelStr() const
 string pkgCache::VerIterator::RelStr() const
 {
 {
-   bool First = true;
-   string Res;
+   std::vector<std::string> RelStrs;
    for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
    for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I)
    {
    {
       // Do not print 'not source' entries'
       // Do not print 'not source' entries'
@@ -877,58 +901,21 @@ string pkgCache::VerIterator::RelStr() const
       if (File.Flagged(pkgCache::Flag::NotSource))
       if (File.Flagged(pkgCache::Flag::NotSource))
 	 continue;
 	 continue;
 
 
-      // See if we have already printed this out..
-      bool Seen = false;
-      for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J)
-      {
-	 pkgCache::PkgFileIterator const File2 = J.File();
-	 if (File2.Label() == 0 || File.Label() == 0)
-	    continue;
-
-	 if (strcmp(File.Label(),File2.Label()) != 0)
-	    continue;
-	 
-	 if (File2.Version() == File.Version())
-	 {
-	    Seen = true;
-	    break;
-	 }
-	 if (File2.Version() == 0 || File.Version() == 0)
-	    break;
-	 if (strcmp(File.Version(),File2.Version()) == 0)
-	    Seen = true;
-      }
-      
-      if (Seen == true)
+      std::string const RS = PkgFileIteratorToRelString(File);
+      if (std::find(RelStrs.begin(), RelStrs.end(), RS) != RelStrs.end())
 	 continue;
 	 continue;
-      
-      if (First == false)
-	 Res += ", ";
-      else
-	 First = false;
-      
-      if (File.Label() != 0)
-	 Res = Res + File.Label() + ':';
 
 
-      if (File.Archive() != 0)
-      {
-	 if (File.Version() == 0)
-	    Res += File.Archive();
-	 else
-	    Res = Res + File.Version() + '/' +  File.Archive();
-      }
-      else
-      {
-	 // No release file, print the host name that this came from
-	 if (File.Site() == 0 || File.Site()[0] == 0)
-	    Res += "localhost";
-	 else
-	    Res += File.Site();
-      }      
+      RelStrs.push_back(RS);
+   }
+   std::ostringstream os;
+   if (likely(RelStrs.empty() == false))
+   {
+      std::copy(RelStrs.begin(), RelStrs.end()-1, std::ostream_iterator<std::string>(os, ", "));
+      os << *RelStrs.rbegin();
    }
    }
    if (S->ParentPkg != 0)
    if (S->ParentPkg != 0)
-      Res.append(" [").append(Arch()).append("]");
-   return Res;
+      os << " [" << Arch() << "]";
+   return os.str();
 }
 }
 									/*}}}*/
 									/*}}}*/
 // VerIterator::MultiArchType - string representing MultiArch flag	/*{{{*/
 // VerIterator::MultiArchType - string representing MultiArch flag	/*{{{*/

+ 2 - 1
test/integration/test-apt-cache

@@ -54,7 +54,8 @@ testsuccessequal 'bar' aptcache pkgnames bar
 testsuccessequal 'fancy
 testsuccessequal 'fancy
 foo' aptcache pkgnames f
 foo' aptcache pkgnames f
 
 
-testsuccessequal "       foo |          1 | file:$(readlink -f .)/aptarchive unstable/main amd64 Packages" aptcache madison foo
+testsuccessequal "       foo |          1 | file:$(readlink -f .)/aptarchive unstable/main amd64 Packages
+       foo |          1 | file:$(readlink -f .)/aptarchive unstable/main i386 Packages" aptcache madison foo
 
 
 ### depends
 ### depends
 
 

+ 8 - 11
test/integration/test-bug-612958-use-dpkg-multiarch-config

@@ -5,22 +5,19 @@ TESTDIR=$(readlink -f $(dirname $0))
 . $TESTDIR/framework
 . $TESTDIR/framework
 setupenvironment
 setupenvironment
 configarchitecture 'i386'
 configarchitecture 'i386'
-setupaptarchive
-
-insertinstalledpackage 'libapt' 'i386' '1.0'
-insertinstalledpackage 'libapt' 'amd64' '1.0'
-insertinstalledpackage 'libapt' 'armel' '1.0'
 
 
 testpass() {
 testpass() {
-	rm rootdir/var/cache/apt/*.bin
-	msgtest 'Test architecture handling' "$1 with $2"
-	testsuccess --nomsg aptcache show libapt:$2
+	msgtest 'Test architecture handling success' "$1 with $2"
+	rm -f archs.conf
+	aptconfig dump --no-empty --format='%V%n' APT::Architectures > archs.conf
+	testsuccess --nomsg grep "^$2\$" archs.conf
 }
 }
 
 
 testfail() {
 testfail() {
-	rm rootdir/var/cache/apt/*.bin
-	msgtest 'Test architecture handling' "$1 with $2"
-	testfailure --nomsg aptcache show libapt:$2
+	msgtest 'Test architecture handling failure' "$1 with $2"
+	rm -f archs.conf
+	aptconfig dump --no-empty --format='%V%n' APT::Architectures > archs.conf
+	testfailure --nomsg grep "^$2\$" archs.conf
 }
 }
 
 
 testpass 'no config' 'i386'
 testpass 'no config' 'i386'

+ 0 - 8
test/integration/test-bug-686346-package-missing-architecture

@@ -11,7 +11,6 @@ insertinstalledpackage 'pkgd' 'none' '1'
 insertpackage 'unstable' 'pkga' 'amd64' '2' 'Depends: pkgb'
 insertpackage 'unstable' 'pkga' 'amd64' '2' 'Depends: pkgb'
 insertpackage 'unstable' 'pkgb' 'amd64' '2'
 insertpackage 'unstable' 'pkgb' 'amd64' '2'
 insertpackage 'unstable' 'pkgc' 'amd64' '1' 'Conflicts: pkgb'
 insertpackage 'unstable' 'pkgc' 'amd64' '1' 'Conflicts: pkgb'
-insertpackage 'unstable' 'pkge' 'none' '1'
 
 
 setupaptarchive
 setupaptarchive
 
 
@@ -41,13 +40,6 @@ Inst pkga (2 unstable [amd64])
 Conf pkgb (2 unstable [amd64])
 Conf pkgb (2 unstable [amd64])
 Conf pkga (2 unstable [amd64])' aptget install pkga -s
 Conf pkga (2 unstable [amd64])' aptget install pkga -s
 
 
-# ensure that arch-less stanzas from Packages files are ignored
-msgtest 'Package is distributed in the Packages files' 'pkge'
-grep -q 'Package: pkge' $(find aptarchive -name 'Packages') && msgpass || msgfail
-testnopackage pkge
-testnopackage pkge:none
-testnopackage pkge:*
-
 # do not automatically change from none-arch to whatever-arch as
 # do not automatically change from none-arch to whatever-arch as
 # this breaks other none packages and dpkg has this ruleset as
 # this breaks other none packages and dpkg has this ruleset as
 # this difference seems so important that it has to be maintained …
 # this difference seems so important that it has to be maintained …

+ 91 - 0
test/integration/test-parse-all-archs-into-cache

@@ -0,0 +1,91 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'i386'
+
+insertpackage 'unstable' 'bar' 'i386' '1' 'Depends: foo'
+insertpackage 'unstable' 'foo' 'i386' '1' 'Multi-Arch: foreign
+Depends: libfoo1'
+insertpackage 'unstable' 'libfoo1' 'i386' '1' 'Multi-Arch: same'
+insertpackage 'experimental' 'foo' 'i386' '2' 'Multi-Arch: foreign
+Depends: libfoo1 (>= 2)'
+insertpackage 'experimental' 'libfoo1' 'i386' '2' 'Multi-Arch: same'
+
+# note: the system has amd64 not configured!
+insertinstalledpackage 'foo' 'amd64' '1' 'Multi-Arch: foreign
+Depends: libfoo1'
+
+setupaptarchive
+
+testfailureequal "Reading package lists...
+Building dependency tree...
+You might want to run 'apt-get -f install' to correct these.
+The following packages have unmet dependencies:
+ foo:amd64 : Depends: libfoo1:amd64 but it is not installable
+E: Unmet dependencies. Try using -f." aptget check -s
+
+insertinstalledpackage 'libfoo1' 'amd64' '1' 'Multi-Arch: same'
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...' aptget check -s
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+The following extra packages will be installed:
+  libfoo1
+The following packages will be REMOVED:
+  foo:amd64
+The following NEW packages will be installed:
+  foo libfoo1
+0 upgraded, 2 newly installed, 1 to remove and 0 not upgraded.
+Remv foo:amd64 [1]
+Inst libfoo1 (1 unstable [i386])
+Inst foo (1 unstable [i386])
+Conf libfoo1 (1 unstable [i386])
+Conf foo (1 unstable [i386])' aptget install foo -s
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+The following extra packages will be installed:
+  libfoo1
+The following packages will be REMOVED:
+  foo:amd64 libfoo1:amd64
+The following NEW packages will be installed:
+  foo libfoo1
+0 upgraded, 2 newly installed, 2 to remove and 0 not upgraded.
+Remv foo:amd64 [1]
+Remv libfoo1:amd64 [1]
+Inst libfoo1 (2 experimental [i386])
+Inst foo (2 experimental [i386])
+Conf libfoo1 (2 experimental [i386])
+Conf foo (2 experimental [i386])' aptget install foo/experimental -s
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+The following extra packages will be installed:
+  foo libfoo1
+The following packages will be REMOVED:
+  foo:amd64
+The following NEW packages will be installed:
+  bar foo libfoo1
+0 upgraded, 3 newly installed, 1 to remove and 0 not upgraded.
+Remv foo:amd64 [1]
+Inst libfoo1 (1 unstable [i386])
+Inst foo (1 unstable [i386])
+Inst bar (1 unstable [i386])
+Conf libfoo1 (1 unstable [i386])
+Conf foo (1 unstable [i386])
+Conf bar (1 unstable [i386])' aptget install bar -s
+
+configarchitecture 'i386' 'amd64'
+
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  bar
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst bar (1 unstable [i386])
+Conf bar (1 unstable [i386])' aptget install bar -s

+ 4 - 2
test/integration/test-specific-architecture-dependencies

@@ -289,12 +289,14 @@ The following NEW packages will be installed:
 Inst foo-native-depender (1 unstable [amd64])
 Inst foo-native-depender (1 unstable [amd64])
 Conf foo-native-depender (1 unstable [amd64])' aptget install foo-native-depender -s
 Conf foo-native-depender (1 unstable [amd64])' aptget install foo-native-depender -s
 
 
-# libold:i386 is installed, but we don't see it as i386 isn't configured
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
+The following packages will be REMOVED:
+  libold:i386
 The following NEW packages will be installed:
 The following NEW packages will be installed:
   breaker-x32
   breaker-x32
-0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
+Remv libold:i386 [1]
 Inst breaker-x32 (1 unstable [amd64])
 Inst breaker-x32 (1 unstable [amd64])
 Conf breaker-x32 (1 unstable [amd64])' aptget install breaker-x32:amd64 -s
 Conf breaker-x32 (1 unstable [amd64])' aptget install breaker-x32:amd64 -s