Browse Source

merge 'after squeeze release'-stuff

[ David Kalnischkies ]
* apt-pkg/depcache.cc:
  - add SetCandidateRelease() to set a candidate version and
    the candidates of dependencies if needed to a specified
    release (Closes: #572709)
* cmdline/apt-get.cc:
  - if --print-uris is used don't setup downloader as we don't need
    progress, lock nor the directories it would create otherwise
  - show dependencies of essential packages which are going to remove
    only if they cause the remove of this essential (Closes: #601961)
  - keep not installed garbage packages uninstalled instead of showing
    in the autoremove section and installing those (Closes: #604222)
  - change pkg/release behavior to use the new SetCandidateRelease
    so installing packages from experimental or backports is easier
  - really do not show packages in the extra section if they were
    requested on the commandline, e.g. with a modifier (Closes: #184730)
* debian/control:
  - add Vcs-Browser now that loggerhead works again (Closes: #511168)
  - depend on debhelper 7 to raise compat level
  - depend on dpkg-dev (>= 1.15.8) to have c++ symbol mangling
* apt-pkg/contrib/fileutl.cc:
  - add a RealFileExists method and check that your configuration files
    are real files to avoid endless loops if not (Closes: #604401)
  - ignore non-regular files in GetListOfFilesInDir (Closes: #594694)
* apt-pkg/contrib/weakptr.h:
  - include stddefs.h to fix compile error (undefined NULL) with gcc-4.6
* methods/https.cc:
  - fix CURLOPT_SSL_VERIFYHOST by really passing 2 to it if enabled
* deb/dpkgpm.cc:
  - fix popen/fclose mismatch reported by cppcheck. Thanks to Petter
    Reinholdtsen for report and patch! (Closes: #607803)
* doc/apt.conf.5.xml:
  - fix multipl{y,e} spelling error reported by Jakub Wilk (Closes: #607636)
* apt-inst/contrib/extracttar.cc:
  - let apt-utils work with encoded tar headers if uid/gid are large.
    Thanks to Nobuhiro Hayashi for the patch! (Closes: #330162)
* apt-pkg/cacheiterator.h:
  - do not segfault if cache is not build (Closes: #254770)
* doc/apt-get.8.xml:
  - remove duplicated mentioning of --install-recommends
* doc/sources.list.5.xml:
  - remove obsolete references to non-us (Closes: #594495)
* debian/rules:
  - use -- instead of deprecated -u for dh_gencontrol
  - remove shlibs.local creation and usage
  - show differences in the symbol files, but never fail
* pre-build.sh:
  - remove as it is not needed for a working 'bzr bd'
* debian/{apt,apt-utils}.symbols:
  - ship experimental unmangled c++ symbol files
* methods/rred.cc:
  - operate optional on gzip compressed pdiffs
* apt-pkg/acquire-item.cc:
  - don't uncompress downloaded pdiff files before feeding it to rred
  - try downloading clearsigned InRelease before trying Release.gpg
  - change the internal handling of Extensions in pkgAcqIndex
  - add a special uncompressed compression type to prefer those files
  - download and use i18n/Index to choose which Translations to download
* cmdline/apt-key:
  - don't set trustdb-name as non-root so 'list' and 'finger'
    can be used without being root (Closes: #393005, #592107)
* apt-pkg/deb/deblistparser.cc:
  - rewrite LoadReleaseInfo to cope with clearsigned Releasefiles
* ftparchive/writer.cc:
  - add config option to search for more patterns in release command
  - include Index files by default in the Release file
* methods/{gzip,bzip}.cc:
  - print a good error message if FileSize() is zero
* apt-pkg/aptconfiguration.cc:
  - remove the inbuilt Translation files whitelist
David Kalnischkies 13 years ago
parent
commit
3eb9e25785
90 changed files with 4229 additions and 850 deletions
  1. 0 3
      .bzr-builddeb/default.conf
  2. 8 4
      apt-inst/contrib/extracttar.cc
  3. 1 3
      apt-inst/extract.cc
  4. 312 93
      apt-pkg/acquire-item.cc
  5. 96 4
      apt-pkg/acquire-item.h
  6. 20 39
      apt-pkg/aptconfiguration.cc
  7. 9 9
      apt-pkg/cacheiterators.h
  8. 35 13
      apt-pkg/contrib/fileutl.cc
  9. 2 0
      apt-pkg/contrib/fileutl.h
  10. 1 1
      apt-pkg/contrib/progress.cc
  11. 17 0
      apt-pkg/contrib/strutl.cc
  12. 1 0
      apt-pkg/contrib/strutl.h
  13. 2 1
      apt-pkg/contrib/weakptr.h
  14. 7 1
      apt-pkg/deb/debindexfile.cc
  15. 79 35
      apt-pkg/deb/deblistparser.cc
  16. 70 39
      apt-pkg/deb/debmetaindex.cc
  17. 2 0
      apt-pkg/deb/debmetaindex.h
  18. 3 7
      apt-pkg/deb/dpkgpm.cc
  19. 175 7
      apt-pkg/depcache.cc
  20. 19 0
      apt-pkg/depcache.h
  21. 2 1
      apt-pkg/indexcopy.cc
  22. 10 7
      apt-pkg/indexrecords.cc
  23. 3 3
      apt-pkg/init.cc
  24. 3 1
      apt-pkg/policy.cc
  25. 3 3
      apt-pkg/sourcelist.cc
  26. 7 3
      apt-pkg/tagfile.cc
  27. 2 0
      apt-pkg/tagfile.h
  28. 2 2
      apt-pkg/vendorlist.cc
  29. 68 33
      cmdline/apt-get.cc
  30. 6 1
      cmdline/apt-key
  31. 9 0
      debian/NEWS
  32. 1 0
      debian/apt-transport-https.dirs
  33. 1 0
      debian/apt-transport-https.install
  34. 1 0
      debian/apt-utils.install
  35. 119 0
      debian/apt-utils.symbols
  36. 0 0
      debian/apt.bug-script
  37. 0 1
      debian/apt.dirs
  38. 5 0
      debian/apt.install
  39. 0 0
      debian/apt.lintian-overrides
  40. 1263 0
      debian/apt.symbols
  41. 73 2
      debian/changelog
  42. 1 1
      debian/compat
  43. 2 1
      debian/control
  44. 3 0
      debian/libapt-pkg-dev.install
  45. 37 82
      debian/rules
  46. 7 4
      doc/apt-ftparchive.1.xml
  47. 0 8
      doc/apt-get.8.xml
  48. 3 2
      doc/apt-secure.8.xml
  49. 5 6
      doc/apt.conf.5.xml
  50. 2 1
      doc/examples/configure-index
  51. 4 76
      doc/files.sgml
  52. 13 17
      doc/sources.list.5.xml
  53. 16 11
      ftparchive/writer.cc
  54. 2 0
      ftparchive/writer.h
  55. 1 2
      methods/bzip2.cc
  56. 1 2
      methods/gzip.cc
  57. 2 4
      methods/https.cc
  58. 1 1
      methods/makefile
  59. 40 9
      methods/rred.cc
  60. 202 192
      po/apt-all.pot
  61. 0 3
      pre-build.sh
  62. 42 0
      test/integration/Packages-bug-593360-modifiers-in-names
  63. 68 0
      test/integration/Packages-bug-604222-new-and-autoremove
  64. 42 0
      test/integration/Packages-bug-64141-install-dependencies-for-on-hold
  65. 18 0
      test/integration/Packages-releasefile-verification
  66. 21 0
      test/integration/Packages-releasefile-verification-new
  67. 15 1
      test/integration/create-test-data
  68. BIN
      test/integration/deb-bug-330162-encoded-tar-header.deb
  69. 152 34
      test/integration/framework
  70. BIN
      test/integration/marvinparanoid.pub
  71. BIN
      test/integration/marvinparanoid.sec
  72. 13 1
      test/integration/run-tests
  73. 42 0
      test/integration/status-bug-601961-install-info
  74. 10 0
      test/integration/status-bug-604222-new-and-autoremove
  75. 33 0
      test/integration/status-bug-64141-install-dependencies-for-on-hold
  76. 57 0
      test/integration/test-bug-254770-segfault-if-cache-not-buildable
  77. 11 0
      test/integration/test-bug-330162-encoded-tar-header
  78. 64 0
      test/integration/test-bug-593360-modifiers-in-names
  79. 28 34
      test/integration/test-bug-595691-empty-and-broken-archive-files
  80. 1 0
      test/integration/test-bug-601016-description-translation
  81. 38 0
      test/integration/test-bug-601961-install-info
  82. 66 0
      test/integration/test-bug-604222-new-and-autoremove
  83. 66 0
      test/integration/test-bug-604401-files-are-directories
  84. 34 0
      test/integration/test-bug-64141-install-dependencies-for-on-hold
  85. 3 3
      test/integration/test-compressed-indexes
  86. 2 8
      test/integration/test-pdiff-usage
  87. 419 0
      test/integration/test-release-candidate-switching
  88. 160 0
      test/integration/test-releasefile-verification
  89. 40 31
      test/libapt/getlanguages_test.cc
  90. 5 0
      test/libapt/run-tests

+ 0 - 3
.bzr-builddeb/default.conf

@@ -1,5 +1,2 @@
 [BUILDDEB]
 native = true
-
-[HOOKS]
-pre-build=./pre-build.sh

+ 8 - 4
apt-inst/contrib/extracttar.cc

@@ -195,10 +195,14 @@ bool ExtractTar::Go(pkgDirStream &Stream)
       // Decode all of the fields
       pkgDirStream::Item Itm;
       if (StrToNum(Tar->Mode,Itm.Mode,sizeof(Tar->Mode),8) == false ||
-	  StrToNum(Tar->UserID,Itm.UID,sizeof(Tar->UserID),8) == false ||
-	  StrToNum(Tar->GroupID,Itm.GID,sizeof(Tar->GroupID),8) == false ||
-	  StrToNum(Tar->Size,Itm.Size,sizeof(Tar->Size),8) == false ||
-	  StrToNum(Tar->MTime,Itm.MTime,sizeof(Tar->MTime),8) == false ||
+          (Base256ToNum(Tar->UserID,Itm.UID,8) == false &&
+	     StrToNum(Tar->UserID,Itm.UID,sizeof(Tar->UserID),8) == false) ||
+          (Base256ToNum(Tar->GroupID,Itm.GID,8) == false &&
+	     StrToNum(Tar->GroupID,Itm.GID,sizeof(Tar->GroupID),8) == false) ||
+          (Base256ToNum(Tar->Size,Itm.Size,12) == false &&
+	     StrToNum(Tar->Size,Itm.Size,sizeof(Tar->Size),8) == false) ||
+          (Base256ToNum(Tar->MTime,Itm.MTime,12) == false &&
+	     StrToNum(Tar->MTime,Itm.MTime,sizeof(Tar->MTime),8) == false) ||
 	  StrToNum(Tar->Major,Itm.Major,sizeof(Tar->Major),8) == false ||
 	  StrToNum(Tar->Minor,Itm.Minor,sizeof(Tar->Minor),8) == false)
 	 return _error->Error(_("Corrupted archive"));

+ 1 - 3
apt-inst/extract.cc

@@ -372,7 +372,6 @@ bool pkgExtract::HandleOverwrites(pkgFLCache::NodeIterator Nde,
    pkgFLCache::NodeIterator TmpNde = Nde;
    unsigned long DiverOwner = 0;
    unsigned long FileGroup = Nde->File;
-   const char *FirstOwner = 0;
    for (; Nde.end() == false && FileGroup == Nde->File; Nde++)
    {
       if ((Nde->Flags & pkgFLCache::Node::Diversion) != 0)
@@ -392,8 +391,7 @@ bool pkgExtract::HandleOverwrites(pkgFLCache::NodeIterator Nde,
          if something has already been diverted by this diversion */
       if (FPkg.Offset() == DiverOwner)
 	 continue;
-      FirstOwner = FPkg.Name();
-      
+
       // Now see if this package matches one in a replace depends
       pkgCache::DepIterator Dep = Ver.DependsList();
       bool Ok = false;

+ 312 - 93
apt-pkg/acquire-item.cc

@@ -184,6 +184,153 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
    }
 }
 									/*}}}*/
+// AcqSubIndex::AcqSubIndex - Constructor				/*{{{*/
+// ---------------------------------------------------------------------
+/* Get the DiffIndex file first and see if there are patches availabe 
+ * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
+ * patches. If anything goes wrong in that process, it will fall back to
+ * the original packages file
+ */
+pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
+				 string const &URIDesc, string const &ShortDesc,
+				 HashString const &ExpectedHash)
+   : Item(Owner), ExpectedHash(ExpectedHash)
+{
+   Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
+
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(URI);
+
+   Desc.URI = URI;
+   Desc.Description = URIDesc;
+   Desc.Owner = this;
+   Desc.ShortDesc = ShortDesc;
+
+   QueueURI(Desc);
+
+   if(Debug)
+      std::clog << "pkgAcqSubIndex: " << Desc.URI << std::endl;
+}
+									/*}}}*/
+// AcqSubIndex::Custom600Headers - Insert custom request headers	/*{{{*/
+// ---------------------------------------------------------------------
+/* The only header we use is the last-modified header. */
+string pkgAcqSubIndex::Custom600Headers()
+{
+   string Final = _config->FindDir("Dir::State::lists");
+   Final += URItoFileName(Desc.URI);
+
+   struct stat Buf;
+   if (stat(Final.c_str(),&Buf) != 0)
+      return "\nIndex-File: true";
+   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+}
+									/*}}}*/
+void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
+{
+   if(Debug)
+      std::clog << "pkgAcqSubIndex failed: " << Desc.URI << std::endl;
+
+   Complete = false;
+   Status = StatDone;
+   Dequeue();
+
+   // No good Index is provided, so try guessing
+   std::vector<std::string> langs = APT::Configuration::getLanguages(true);
+   for (std::vector<std::string>::const_iterator l = langs.begin();
+	l != langs.end(); ++l)
+   {
+      if (*l == "none") continue;
+      string const file = "Translation-" + *l;
+      new pkgAcqIndexTrans(Owner, Desc.URI.substr(0, Desc.URI.rfind('/')+1).append(file),
+		Desc.Description.erase(Desc.Description.rfind(' ')+1).append(file),
+		file);
+   }
+}
+									/*}}}*/
+void pkgAcqSubIndex::Done(string Message,unsigned long Size,string Md5Hash,	/*{{{*/
+			   pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqSubIndex::Done(): " << Desc.URI << std::endl;
+
+   string FileName = LookupTag(Message,"Filename");
+   if (FileName.empty() == true)
+   {
+      Status = StatError;
+      ErrorText = "Method gave a blank filename";
+      return;
+   }
+
+   if (FileName != DestFile)
+   {
+      Local = true;
+      Desc.URI = "copy:" + FileName;
+      QueueURI(Desc);
+      return;
+   }
+
+   Item::Done(Message,Size,Md5Hash,Cnf);
+
+   string FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(Desc.URI);
+
+   // sucess in downloading the index
+   // rename the index
+   if(Debug)
+      std::clog << "Renaming: " << DestFile << " -> " << FinalFile << std::endl;
+   Rename(DestFile,FinalFile);
+   chmod(FinalFile.c_str(),0644);
+   DestFile = FinalFile;
+
+   if(ParseIndex(DestFile) == false)
+      return Failed("", NULL);
+
+   Complete = true;
+   Status = StatDone;
+   Dequeue();
+   return;
+}
+									/*}}}*/
+bool pkgAcqSubIndex::ParseIndex(string const &IndexFile)		/*{{{*/
+{
+   indexRecords SubIndexParser;
+   if (FileExists(IndexFile) == false || SubIndexParser.Load(IndexFile) == false)
+      return false;
+
+   std::vector<std::string> lang = APT::Configuration::getLanguages(true);
+   for (std::vector<std::string>::const_iterator l = lang.begin();
+	l != lang.end(); ++l)
+   {
+      if (*l == "none")
+	 continue;
+
+      string file = "Translation-" + *l;
+      indexRecords::checkSum const *Record = SubIndexParser.Lookup(file);
+      HashString expected;
+      if (Record == NULL)
+      {
+	 // FIXME: the Index file provided by debian currently only includes bz2 records
+	 Record = SubIndexParser.Lookup(file + ".bz2");
+	 if (Record == NULL)
+	    continue;
+      }
+      else
+      {
+	 expected = Record->Hash;
+	 if (expected.empty() == true)
+	    continue;
+      }
+
+      IndexTarget target;
+      target.Description = Desc.Description.erase(Desc.Description.rfind(' ')+1).append(file);
+      target.MetaKey = file;
+      target.ShortDesc = file;
+      target.URI = Desc.URI.substr(0, Desc.URI.rfind('/')+1).append(file);
+      new pkgAcqIndexTrans(Owner, &target, expected, &SubIndexParser);
+   }
+   return true;
+}
+									/*}}}*/
 // AcqDiffIndex::AcqDiffIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* Get the DiffIndex file first and see if there are patches availabe 
@@ -570,24 +717,7 @@ void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,	/*
    FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
 
    // sucess in downloading a diff, enter ApplyDiff state
-   if(State == StateFetchDiff) 
-   {
-
-      if(Debug)
-	 std::clog << "Sending to gzip method: " << FinalFile << std::endl;
-
-      string FileName = LookupTag(Message,"Filename");
-      State = StateUnzipDiff;
-      Local = true;
-      Desc.URI = "gzip:" + FileName;
-      DestFile += ".decomp";
-      QueueURI(Desc);
-      Mode = "gzip";
-      return;
-   } 
-
-   // sucess in downloading a diff, enter ApplyDiff state
-   if(State == StateUnzipDiff) 
+   if(State == StateFetchDiff)
    {
 
       // rred excepts the patch as $FinalFile.ed
@@ -639,29 +769,61 @@ pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
 			 HashString ExpectedHash, string comprExt)
    : Item(Owner), RealURI(URI), ExpectedHash(ExpectedHash)
 {
+   if(comprExt.empty() == true)
+   {
+      // autoselect the compression method
+      std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+      for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+	 comprExt.append(*t).append(" ");
+      if (comprExt.empty() == false)
+	 comprExt.erase(comprExt.end()-1);
+   }
+   CompressionExtension = comprExt;
+
+   Init(URI, URIDesc, ShortDesc);
+}
+pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, IndexTarget const *Target,
+			 HashString const &ExpectedHash, indexRecords const *MetaIndexParser)
+   : Item(Owner), RealURI(Target->URI), ExpectedHash(ExpectedHash)
+{
+   // autoselect the compression method
+   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
+   CompressionExtension = "";
+   if (ExpectedHash.empty() == false)
+   {
+      for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+	 if (*t == "uncompressed" || MetaIndexParser->Exists(string(Target->MetaKey).append(".").append(*t)) == true)
+	    CompressionExtension.append(*t).append(" ");
+   }
+   else
+   {
+      for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
+	 CompressionExtension.append(*t).append(" ");
+   }
+   if (CompressionExtension.empty() == false)
+      CompressionExtension.erase(CompressionExtension.end()-1);
+
+   Init(Target->URI, Target->Description, Target->ShortDesc);
+}
+									/*}}}*/
+// AcqIndex::Init - defered Constructor					/*{{{*/
+void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &ShortDesc) {
    Decompression = false;
    Erase = false;
 
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile += URItoFileName(URI);
 
-   if(comprExt.empty()) 
-   {
-      // autoselect the compression method
-      std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-      if (types.empty() == true)
-	 comprExt = "plain";
-      else
-	 comprExt = "." + types[0];
-   }
-   CompressionExtension = ((comprExt == "plain" || comprExt == ".") ? "" : comprExt);
-
-   Desc.URI = URI + CompressionExtension;
+   std::string const comprExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
+   if (comprExt == "uncompressed")
+      Desc.URI = URI;
+   else
+      Desc.URI = URI + '.' + comprExt;
 
    Desc.Description = URIDesc;
    Desc.Owner = this;
    Desc.ShortDesc = ShortDesc;
-      
+
    QueueURI(Desc);
 }
 									/*}}}*/
@@ -683,37 +845,18 @@ string pkgAcqIndex::Custom600Headers()
 									/*}}}*/
 void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
 {
-   std::vector<std::string> types = APT::Configuration::getCompressionTypes();
-
-   for (std::vector<std::string>::const_iterator t = types.begin();
-	t != types.end(); t++)
+   size_t const nextExt = CompressionExtension.find(' ');
+   if (nextExt != std::string::npos)
    {
-      // jump over all already tried compression types
-      const unsigned int nameLen = Desc.URI.size() - (*t).size();
-      if(Desc.URI.substr(nameLen) != *t)
-	 continue;
-
-      // we want to try it with the next extension (and make sure to 
-      // not skip over the end)
-      t++;
-      if (t == types.end())
-	 break;
-
-      // queue new download
-      Desc.URI = Desc.URI.substr(0, nameLen) + *t;
-      new pkgAcqIndex(Owner, RealURI, Desc.Description, Desc.ShortDesc,
-      ExpectedHash, string(".").append(*t));
-      
-      Status = StatDone;
-      Complete = false;
-      Dequeue();
+      CompressionExtension = CompressionExtension.substr(nextExt+1);
+      Init(RealURI, Desc.Description, Desc.ShortDesc);
       return;
    }
 
    // on decompression failure, remove bad versions in partial/
-   if(Decompression && Erase) {
+   if (Decompression && Erase) {
       string s = _config->FindDir("Dir::State::lists") + "partial/";
-      s += URItoFileName(RealURI);
+      s.append(URItoFileName(RealURI));
       unlink(s.c_str());
    }
 
@@ -790,8 +933,8 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
       Status = StatError;
       ErrorText = "Method gave a blank filename";
    }
-   
-   string compExt = flExtension(flNotDir(URI(Desc.URI).Path));
+
+   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
 
    // The files timestamp matches
    if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) {
@@ -824,12 +967,7 @@ void pkgAcqIndex::Done(string Message,unsigned long Size,string Hash,
    // get the binary name for your used compression type
    decompProg = _config->Find(string("Acquire::CompressionTypes::").append(compExt),"");
    if(decompProg.empty() == false);
-   // flExtensions returns the full name if no extension is found
-   // this is why we have this complicated compare operation here
-   // FIMXE: add a new flJustExtension() that return "" if no
-   //        extension is found and use that above so that it can
-   //        be tested against ""
-   else if(compExt == flNotDir(URI(Desc.URI).Path))
+   else if(compExt == "uncompressed")
       decompProg = "copy";
    else {
       _error->Error("Unsupported extension: %s", compExt.c_str());
@@ -850,6 +988,11 @@ pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner,
 			    string URI,string URIDesc,string ShortDesc) 
   : pkgAcqIndex(Owner, URI, URIDesc, ShortDesc, HashString(), "")
 {
+}
+pkgAcqIndexTrans::pkgAcqIndexTrans(pkgAcquire *Owner, IndexTarget const *Target,
+			 HashString const &ExpectedHash, indexRecords const *MetaIndexParser)
+  : pkgAcqIndex(Owner, Target, ExpectedHash, MetaIndexParser)
+{
 }
 									/*}}}*/
 // AcqIndexTrans::Custom600Headers - Insert custom request headers	/*{{{*/
@@ -870,6 +1013,15 @@ string pkgAcqIndexTrans::Custom600Headers()
 /* */
 void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
 {
+   size_t const nextExt = CompressionExtension.find(' ');
+   if (nextExt != std::string::npos)
+   {
+      CompressionExtension = CompressionExtension.substr(nextExt+1);
+      Init(RealURI, Desc.Description, Desc.ShortDesc);
+      Status = StatIdle;
+      return;
+   }
+
    if (Cnf->LocalOnly == true || 
        StringToBool(LookupTag(Message,"Transient-Failure"),false) == false)
    {      
@@ -879,7 +1031,7 @@ void pkgAcqIndexTrans::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
       Dequeue();
       return;
    }
-   
+
    Item::Failed(Message,Cnf);
 }
 									/*}}}*/
@@ -1094,6 +1246,8 @@ void pkgAcqMetaIndex::Done(string Message,unsigned long Size,string Hash,	/*{{{*
    {
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
+      if (SigFile == DestFile)
+	 SigFile = FinalFile;
       Rename(DestFile,FinalFile);
       chmod(FinalFile.c_str(),0644);
       DestFile = FinalFile;
@@ -1127,6 +1281,8 @@ void pkgAcqMetaIndex::RetrievalDone(string Message)			/*{{{*/
    {
       string FinalFile = _config->FindDir("Dir::State::lists");
       FinalFile += URItoFileName(RealURI);
+      if (SigFile == DestFile)
+	 SigFile = FinalFile;
       DestFile = FinalFile;
    }
    Complete = true;
@@ -1158,6 +1314,10 @@ void pkgAcqMetaIndex::AuthDone(string Message)				/*{{{*/
    // Download further indexes with verification
    QueueIndexes(true);
 
+   // is it a clearsigned MetaIndex file?
+   if (DestFile == SigFile)
+      return;
+
    // Done, move signature file into position
    string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
       URItoFileName(RealURI) + ".gpg";
@@ -1174,27 +1334,41 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
       HashString ExpectedIndexHash;
       if (verify)
       {
-         const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
-         if (!Record)
-         {
-            Status = StatAuthError;
-            ErrorText = "Unable to find expected entry  "
-               + (*Target)->MetaKey + " in Meta-index file (malformed Release file?)";
-            return;
-         }
-         ExpectedIndexHash = Record->Hash;
-         if (_config->FindB("Debug::pkgAcquire::Auth", false))
-         {
-            std::cerr << "Queueing: " << (*Target)->URI << std::endl;
-            std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
-         }
-         if (ExpectedIndexHash.empty())
-         {
-            Status = StatAuthError;
-            ErrorText = "Unable to find hash sum for "
-               + (*Target)->MetaKey + " in Meta-index file";
-            return;
-         }
+	 const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey);
+	 if (Record == NULL)
+	 {
+	    if ((*Target)->IsOptional() == false)
+	    {
+	       Status = StatAuthError;
+	       strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str());
+	       return;
+	    }
+	 }
+	 else
+	 {
+	    ExpectedIndexHash = Record->Hash;
+	    if (_config->FindB("Debug::pkgAcquire::Auth", false))
+	    {
+	       std::cerr << "Queueing: " << (*Target)->URI << std::endl;
+	       std::cerr << "Expected Hash: " << ExpectedIndexHash.toStr() << std::endl;
+	    }
+	    if (ExpectedIndexHash.empty() == true && (*Target)->IsOptional() == false)
+	    {
+	       Status = StatAuthError;
+	       strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str());
+	       return;
+	    }
+	 }
+      }
+
+      if ((*Target)->IsOptional() == true)
+      {
+	 if ((*Target)->IsSubIndex() == true)
+	    new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
+				(*Target)->ShortDesc, ExpectedIndexHash);
+	 else
+	    new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+	 continue;
       }
 
       /* Queue Packages file (either diff or full packages files, depending
@@ -1206,8 +1380,7 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
 	 new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
 			     (*Target)->ShortDesc, ExpectedIndexHash);
       else
-	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
-			    (*Target)->ShortDesc, ExpectedIndexHash);
+	 new pkgAcqIndex(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
    }
 }
 									/*}}}*/
@@ -1317,13 +1490,20 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    if (AuthPass == true)
    {
       // gpgv method failed, if we have a good signature 
-      string LastGoodSigFile = _config->FindDir("Dir::State::lists") +
-	 "partial/" + URItoFileName(RealURI) + ".gpg.reverify";
+      string LastGoodSigFile = _config->FindDir("Dir::State::lists");
+      if (DestFile == SigFile)
+	 LastGoodSigFile.append(URItoFileName(RealURI));
+      else
+	 LastGoodSigFile.append("partial/").append(URItoFileName(RealURI)).append(".gpg.reverify");
+
       if(FileExists(LastGoodSigFile))
       {
-	 string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
-	    URItoFileName(RealURI) + ".gpg";
-	 Rename(LastGoodSigFile,VerifiedSigFile);
+	 if (DestFile != SigFile)
+	 {
+	    string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+					URItoFileName(RealURI) + ".gpg";
+	    Rename(LastGoodSigFile,VerifiedSigFile);
+	 }
 	 Status = StatTransientNetworkError;
 	 _error->Warning(_("A error occurred during the signature "
 			   "verification. The repository is not updated "
@@ -1347,6 +1527,35 @@ void pkgAcqMetaIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
    QueueIndexes(false);
 }
 									/*}}}*/
+pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner,		/*{{{*/
+		string const &URI, string const &URIDesc, string const &ShortDesc,
+		string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc,
+		string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc,
+		const vector<struct IndexTarget*>* IndexTargets,
+		indexRecords* MetaIndexParser) :
+	pkgAcqMetaIndex(Owner, URI, URIDesc, ShortDesc, "", IndexTargets, MetaIndexParser),
+	MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc),
+	MetaSigURI(MetaSigURI), MetaSigURIDesc(MetaSigURIDesc), MetaSigShortDesc(MetaSigShortDesc)
+{
+   SigFile = DestFile;
+}
+									/*}}}*/
+void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/
+{
+   if (AuthPass == false)
+   {
+      new pkgAcqMetaSig(Owner,
+			MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
+			MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
+			IndexTargets, MetaIndexParser);
+      if (Cnf->LocalOnly == true ||
+	  StringToBool(LookupTag(Message, "Transient-Failure"), false) == false)
+	 Dequeue();
+   }
+   else
+      pkgAcqMetaIndex::Failed(Message, Cnf);
+}
+									/*}}}*/
 // AcqArchive::AcqArchive - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* This just sets up the initial fetch environment and queues the first
@@ -1793,3 +2002,13 @@ string pkgAcqFile::Custom600Headers()
    return "";
 }
 									/*}}}*/
+bool IndexTarget::IsOptional() const {
+   if (strncmp(ShortDesc.c_str(), "Translation", 11) != 0)
+      return false;
+   return true;
+}
+bool IndexTarget::IsSubIndex() const {
+   if (ShortDesc != "TranslationIndex")
+      return false;
+   return true;
+}

+ 96 - 4
apt-pkg/acquire-item.h

@@ -287,6 +287,50 @@ struct DiffInfo {
    unsigned long size;
 };
 									/*}}}*/
+/** \brief An item that is responsible for fetching a SubIndex		{{{
+ *
+ *  The MetaIndex file includes only records for important indexes
+ *  and records for these SubIndex files so these can carry records
+ *  for addition files like PDiffs and Translations
+ */
+class pkgAcqSubIndex : public pkgAcquire::Item
+{
+ protected:
+   /** \brief If \b true, debugging information will be written to std::clog. */
+   bool Debug;
+
+   /** \brief The item that is currently being downloaded. */
+   pkgAcquire::ItemDesc Desc;
+
+   /** \brief The Hash that this file should have after download
+    */
+   HashString ExpectedHash;
+
+ public:
+   // Specialized action members
+   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+		     pkgAcquire::MethodConfig *Cnf);
+   virtual string DescURI() {return Desc.URI;};
+   virtual string Custom600Headers();
+   virtual bool ParseIndex(string const &IndexFile);
+
+   /** \brief Create a new pkgAcqDiffIndex.
+    *
+    *  \param Owner The Acquire object that owns this item.
+    *
+    *  \param URI The URI of the list file to download.
+    *
+    *  \param URIDesc A long description of the list file to download.
+    *
+    *  \param ShortDesc A short description of the list file to download.
+    *
+    *  \param ExpectedHash The list file's MD5 signature.
+    */
+   pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,string const &URIDesc,
+		   string const &ShortDesc, HashString const &ExpectedHash);
+};
+									/*}}}*/
 /** \brief An item that is responsible for fetching an index file of	{{{
  *  package list diffs and starting the package list's download.
  *
@@ -449,7 +493,7 @@ class pkgAcqIndexDiffs : public pkgAcquire::Item
 	 StateFetchDiff,
 	 
 	 /** \brief The diff is currently being uncompressed. */
-	 StateUnzipDiff,
+	 StateUnzipDiff, // FIXME: No longer used
 
 	 /** \brief The diff is currently being applied. */
 	 StateApplyDiff
@@ -528,8 +572,8 @@ class pkgAcqIndex : public pkgAcquire::Item
    /** \brief The expected hashsum of the decompressed index file. */
    HashString ExpectedHash;
 
-   /** \brief The compression-related file extension that is being
-    *  added to the downloaded file (e.g., ".gz" or ".bz2").
+   /** \brief The compression-related file extensions that are being
+    *  added to the downloaded file one by one if first fails (e.g., "gz bz2").
     */
    string CompressionExtension;
 
@@ -540,7 +584,7 @@ class pkgAcqIndex : public pkgAcquire::Item
    virtual void Done(string Message,unsigned long Size,string Md5Hash,
 		     pkgAcquire::MethodConfig *Cnf);
    virtual string Custom600Headers();
-   virtual string DescURI() {return RealURI + CompressionExtension;};
+   virtual string DescURI() {return Desc.URI;};
    virtual string HashSum() {return ExpectedHash.toStr(); };
 
    /** \brief Create a pkgAcqIndex.
@@ -565,6 +609,9 @@ class pkgAcqIndex : public pkgAcquire::Item
    pkgAcqIndex(pkgAcquire *Owner,string URI,string URIDesc,
 	       string ShortDesc, HashString ExpectedHash, 
 	       string compressExt="");
+   pkgAcqIndex(pkgAcquire *Owner, struct IndexTarget const * const Target,
+			 HashString const &ExpectedHash, indexRecords const *MetaIndexParser);
+   void Init(string const &URI, string const &URIDesc, string const &ShortDesc);
 };
 									/*}}}*/
 /** \brief An acquire item that is responsible for fetching a		{{{
@@ -594,6 +641,8 @@ class pkgAcqIndexTrans : public pkgAcqIndex
     */
    pkgAcqIndexTrans(pkgAcquire *Owner,string URI,string URIDesc,
 		    string ShortDesc);
+   pkgAcqIndexTrans(pkgAcquire *Owner, struct IndexTarget const * const Target,
+		    HashString const &ExpectedHash, indexRecords const *MetaIndexParser);
 };
 									/*}}}*/
 /** \brief Information about an index file. */				/*{{{*/
@@ -612,8 +661,18 @@ struct IndexTarget
     *  looked up within the meta signature file.
     */
    string MetaKey;
+
+   //FIXME: We should use virtual methods here instead…
+   bool IsOptional() const;
+   bool IsSubIndex() const;
 };
 									/*}}}*/
+/** \brief Information about an optional index file. */			/*{{{*/
+struct OptionalIndexTarget : public IndexTarget
+{
+};
+									/*}}}*/
+
 /** \brief An acquire item that downloads the detached signature	{{{
  *  of a meta-index (Release) file, then queues up the release
  *  file itself.
@@ -772,6 +831,39 @@ class pkgAcqMetaIndex : public pkgAcquire::Item
 		   indexRecords* MetaIndexParser);
 };
 									/*}}}*/
+/** \brief An item repsonsible for downloading clearsigned metaindexes	{{{*/
+class pkgAcqMetaClearSig : public pkgAcqMetaIndex
+{
+   /** \brief The URI of the meta-index file for the detached signature */
+   string MetaIndexURI;
+
+   /** \brief A "URI-style" description of the meta-index file */
+   string MetaIndexURIDesc;
+
+   /** \brief A brief description of the meta-index file */
+   string MetaIndexShortDesc;
+
+   /** \brief The URI of the detached meta-signature file if the clearsigned one failed. */
+   string MetaSigURI;
+
+   /** \brief A "URI-style" description of the meta-signature file */
+   string MetaSigURIDesc;
+
+   /** \brief A brief description of the meta-signature file */
+   string MetaSigShortDesc;
+
+public:
+   void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+
+   /** \brief Create a new pkgAcqMetaClearSig. */
+   pkgAcqMetaClearSig(pkgAcquire *Owner,
+		string const &URI, string const &URIDesc, string const &ShortDesc,
+		string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc,
+		string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc,
+		const vector<struct IndexTarget*>* IndexTargets,
+		indexRecords* MetaIndexParser);
+};
+									/*}}}*/
 /** \brief An item that is responsible for fetching a package file.	{{{
  *
  *  If the package file already exists in the cache, nothing will be

+ 20 - 39
apt-pkg/aptconfiguration.cc

@@ -90,6 +90,14 @@ const Configuration::getCompressionTypes(bool const &Cached) {
 		types.push_back(Types->Tag);
 	}
 
+	// add the special "uncompressed" type
+	if (std::find(types.begin(), types.end(), "uncompressed") == types.end())
+	{
+		string const uncompr = _config->FindFile("Dir::Bin::uncompressed", "");
+		if (uncompr.empty() == true || FileExists(uncompr) == true)
+			types.push_back("uncompressed");
+	}
+
 	return types;
 }
 									/*}}}*/
@@ -155,33 +163,6 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 	}
 	closedir(D);
 
-	// get the environment language codes: LC_MESSAGES (and later LANGUAGE)
-	// we extract both, a long and a short code and then we will
-	// check if we actually need both (rare) or if the short is enough
-	string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale);
-	size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2;
-	size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3);
-
-	string envLong = envMsg.substr(0,lenLong);
-	string const envShort = envLong.substr(0,lenShort);
-	bool envLongIncluded = true;
-
-	// to save the servers from unneeded queries, we only try also long codes
-	// for languages it is realistic to have a long code translation file…
-	// TODO: Improve translation acquire system to drop them dynamic
-	char const *needLong[] = { "cs", "en", "pt", "sv", "zh", NULL };
-	if (envLong != envShort) {
-		for (char const **l = needLong; *l != NULL; l++)
-			if (envShort.compare(*l) == 0) {
-				envLongIncluded = false;
-				break;
-			}
-	}
-
-	// we don't add the long code, but we allow the user to do so
-	if (envLongIncluded == true)
-		envLong.clear();
-
 	// FIXME: Remove support for the old APT::Acquire::Translation
 	// it was undocumented and so it should be not very widthly used
 	string const oldAcquire = _config->Find("APT::Acquire::Translation","");
@@ -203,12 +184,22 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 			return codes;
 	}
 
-	// It is very likely we will need to environment codes later,
+	// get the environment language codes: LC_MESSAGES (and later LANGUAGE)
+	// we extract both, a long and a short code and then we will
+	// check if we actually need both (rare) or if the short is enough
+	string const envMsg = string(Locale == 0 ? std::setlocale(LC_MESSAGES, NULL) : *Locale);
+	size_t const lenShort = (envMsg.find('_') != string::npos) ? envMsg.find('_') : 2;
+	size_t const lenLong = (envMsg.find_first_of(".@") != string::npos) ? envMsg.find_first_of(".@") : (lenShort + 3);
+
+	string const envLong = envMsg.substr(0,lenLong);
+	string const envShort = envLong.substr(0,lenShort);
+
+	// It is very likely we will need the environment codes later,
 	// so let us generate them now from LC_MESSAGES and LANGUAGE
 	std::vector<string> environment;
 	if (envShort != "C") {
 		// take care of LC_MESSAGES
-		if (envLongIncluded == false)
+		if (envLong != envShort)
 			environment.push_back(envLong);
 		environment.push_back(envShort);
 		// take care of LANGUAGE
@@ -225,16 +216,6 @@ std::vector<std::string> const Configuration::getLanguages(bool const &All,
 					continue;
 				if (std::find(environment.begin(), environment.end(), *e) != environment.end())
 					continue;
-				if (e->find('_') != string::npos) {
-					// Drop LongCodes here - ShortCodes are also included
-					string const shorty = e->substr(0, e->find('_'));
-					char const **n = needLong;
-					for (; *n != NULL; ++n)
-						if (shorty == *n)
-							break;
-					if (*n == NULL)
-						continue;
-				}
 				++addedLangs;
 				environment.push_back(*e);
 			}

+ 9 - 9
apt-pkg/cacheiterators.h

@@ -96,7 +96,7 @@ class pkgCache::GrpIterator: public Iterator<Group, GrpIterator> {
 
 	protected:
 	inline Group* OwnerPointer() const {
-		return Owner->GrpP;
+		return (Owner != 0) ? Owner->GrpP : 0;
 	};
 
 	public:
@@ -137,7 +137,7 @@ class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> {
 
 	protected:
 	inline Package* OwnerPointer() const {
-		return Owner->PkgP;
+		return (Owner != 0) ? Owner->PkgP : 0;
 	};
 
 	public:
@@ -184,7 +184,7 @@ class pkgCache::PkgIterator: public Iterator<Package, PkgIterator> {
 class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 	protected:
 	inline Version* OwnerPointer() const {
-		return Owner->VerP;
+		return (Owner != 0) ? Owner->VerP : 0;
 	};
 
 	public:
@@ -241,7 +241,7 @@ class pkgCache::VerIterator : public Iterator<Version, VerIterator> {
 class pkgCache::DescIterator : public Iterator<Description, DescIterator> {
 	protected:
 	inline Description* OwnerPointer() const {
-		return Owner->DescP;
+		return (Owner != 0) ? Owner->DescP : 0;
 	};
 
 	public:
@@ -270,7 +270,7 @@ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> {
 
 	protected:
 	inline Dependency* OwnerPointer() const {
-		return Owner->DepP;
+		return (Owner != 0) ? Owner->DepP : 0;
 	};
 
 	public:
@@ -315,7 +315,7 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
 
 	protected:
 	inline Provides* OwnerPointer() const {
-		return Owner->ProvideP;
+		return (Owner != 0) ? Owner->ProvideP : 0;
 	};
 
 	public:
@@ -349,7 +349,7 @@ class pkgCache::PrvIterator : public Iterator<Provides, PrvIterator> {
 class pkgCache::PkgFileIterator : public Iterator<PackageFile, PkgFileIterator> {
 	protected:
 	inline PackageFile* OwnerPointer() const {
-		return Owner->PkgFileP;
+		return (Owner != 0) ? Owner->PkgFileP : 0;
 	};
 
 	public:
@@ -382,7 +382,7 @@ class pkgCache::PkgFileIterator : public Iterator<PackageFile, PkgFileIterator>
 class pkgCache::VerFileIterator : public pkgCache::Iterator<VerFile, VerFileIterator> {
 	protected:
 	inline VerFile* OwnerPointer() const {
-		return Owner->VerFileP;
+		return (Owner != 0) ? Owner->VerFileP : 0;
 	};
 
 	public:
@@ -401,7 +401,7 @@ class pkgCache::VerFileIterator : public pkgCache::Iterator<VerFile, VerFileIter
 class pkgCache::DescFileIterator : public Iterator<DescFile, DescFileIterator> {
 	protected:
 	inline DescFile* OwnerPointer() const {
-		return Owner->DescFileP;
+		return (Owner != 0) ? Owner->DescFileP : 0;
 	};
 
 	public:

+ 35 - 13
apt-pkg/contrib/fileutl.cc

@@ -191,7 +191,7 @@ int GetLock(string File,bool Errors)
 									/*}}}*/
 // FileExists - Check if a file exists					/*{{{*/
 // ---------------------------------------------------------------------
-/* */
+/* Beware: Directories are also files! */
 bool FileExists(string File)
 {
    struct stat Buf;
@@ -200,6 +200,17 @@ bool FileExists(string File)
    return true;
 }
 									/*}}}*/
+// RealFileExists - Check if a file exists and if it is really a file	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool RealFileExists(string File)
+{
+   struct stat Buf;
+   if (stat(File.c_str(),&Buf) != 0)
+      return false;
+   return ((Buf.st_mode & S_IFREG) != 0);
+}
+									/*}}}*/
 // DirectoryExists - Check if a directory exists and is really one	/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -304,6 +315,13 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
    }
 
    std::vector<string> List;
+
+   if (DirectoryExists(Dir.c_str()) == false)
+   {
+      _error->Error(_("List of files can't be created as '%s' is not a directory"), Dir.c_str());
+      return List;
+   }
+
    Configuration::MatchAgainstConfig SilentIgnore("Dir::Ignore-Files-Silently");
    DIR *D = opendir(Dir.c_str());
    if (D == 0) 
@@ -318,6 +336,20 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
       if (Ent->d_name[0] == '.')
 	 continue;
 
+      // Make sure it is a file and not something else
+      string const File = flCombine(Dir,Ent->d_name);
+#ifdef _DIRENT_HAVE_D_TYPE
+      if (Ent->d_type != DT_REG)
+#endif
+      {
+	 if (RealFileExists(File.c_str()) == false)
+	 {
+	    if (SilentIgnore.Match(Ent->d_name) == false)
+	       _error->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent->d_name, Dir.c_str());
+	    continue;
+	 }
+      }
+
       // check for accepted extension:
       // no extension given -> periods are bad as hell!
       // extensions given -> "" extension allows no extension
@@ -331,7 +363,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
 	       if (Debug == true)
 		  std::clog << "Bad file: " << Ent->d_name << " → no extension" << std::endl;
 	       if (SilentIgnore.Match(Ent->d_name) == false)
-		  _error->Notice("Ignoring file '%s' in directory '%s' as it has no filename extension", Ent->d_name, Dir.c_str());
+		  _error->Notice(_("Ignoring file '%s' in directory '%s' as it has no filename extension"), Ent->d_name, Dir.c_str());
 	       continue;
 	    }
 	 }
@@ -340,7 +372,7 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
 	    if (Debug == true)
 	       std::clog << "Bad file: " << Ent->d_name << " → bad extension »" << flExtension(Ent->d_name) << "«" << std::endl;
 	    if (SilentIgnore.Match(Ent->d_name) == false)
-	       _error->Notice("Ignoring file '%s' in directory '%s' as it has an invalid filename extension", Ent->d_name, Dir.c_str());
+	       _error->Notice(_("Ignoring file '%s' in directory '%s' as it has an invalid filename extension"), Ent->d_name, Dir.c_str());
 	    continue;
 	 }
       }
@@ -373,16 +405,6 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
 	 continue;
       }
 
-      // Make sure it is a file and not something else
-      string const File = flCombine(Dir,Ent->d_name);
-      struct stat St;
-      if (stat(File.c_str(),&St) != 0 || S_ISREG(St.st_mode) == 0)
-      {
-	 if (Debug == true)
-	    std::clog << "Bad file: " << Ent->d_name << " → stat says not a good file" << std::endl;
-	 continue;
-      }
-
       if (Debug == true)
 	 std::clog << "Accept file: " << Ent->d_name << " in " << Dir << std::endl;
       List.push_back(File);

+ 2 - 0
apt-pkg/contrib/fileutl.h

@@ -72,6 +72,7 @@ class FileFd
    // Simple manipulators
    inline int Fd() {return iFd;};
    inline void Fd(int fd) {iFd = fd;};
+   inline gzFile gzFd() {return gz;};
    inline bool IsOpen() {return iFd >= 0;};
    inline bool Failed() {return (Flags & Fail) == Fail;};
    inline void EraseOnFailure() {Flags |= DelOnFail;};
@@ -93,6 +94,7 @@ bool RunScripts(const char *Cnf);
 bool CopyFile(FileFd &From,FileFd &To);
 int GetLock(string File,bool Errors = true);
 bool FileExists(string File);
+bool RealFileExists(string File);
 bool DirectoryExists(string const &Path) __attrib_const;
 bool CreateDirectory(string const &Parent, string const &Path);
 

+ 1 - 1
apt-pkg/contrib/progress.cc

@@ -135,7 +135,7 @@ bool OpProgress::CheckChange(float Interval)
 OpTextProgress::OpTextProgress(Configuration &Config) : 
                                NoUpdate(false), NoDisplay(false), LastLen(0) 
 {
-   if (Config.FindI("quiet",0) >= 1)
+   if (Config.FindI("quiet",0) >= 1 || Config.FindB("quiet::NoUpdate", false) == true)
       NoUpdate = true;
    if (Config.FindI("quiet",0) >= 2)
       NoDisplay = true;

+ 17 - 0
apt-pkg/contrib/strutl.cc

@@ -968,6 +968,23 @@ bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base)
    return true;
 }
 									/*}}}*/
+// Base256ToNum - Convert a fixed length binary to a number             /*{{{*/
+// ---------------------------------------------------------------------
+/* This is used in decoding the 256bit encoded fixed length fields in
+   tar files */
+bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len)
+{
+   if ((Str[0] & 0x80) == 0)
+      return false;
+   else
+   {
+      Res = Str[0] & 0x7F;
+      for(unsigned int i = 1; i < Len; ++i)
+         Res = (Res<<8) + Str[i];
+      return true;
+   }
+}
+									/*}}}*/
 // HexDigit - Convert a hex character into an integer			/*{{{*/
 // ---------------------------------------------------------------------
 /* Helper for Hex2Num */

+ 1 - 0
apt-pkg/contrib/strutl.h

@@ -52,6 +52,7 @@ string LookupTag(const string &Message,const char *Tag,const char *Default = 0);
 int StringToBool(const string &Text,int Default = -1);
 bool ReadMessages(int Fd, vector<string> &List);
 bool StrToNum(const char *Str,unsigned long &Res,unsigned Len,unsigned Base = 0);
+bool Base256ToNum(const char *Str,unsigned long &Res,unsigned int Len);
 bool Hex2Num(const string &Str,unsigned char *Num,unsigned int Length);
 bool TokSplitString(char Tok,char *Input,char **List,
 		    unsigned long ListMax);

+ 2 - 1
apt-pkg/contrib/weakptr.h

@@ -21,8 +21,9 @@
 #ifndef WEAK_POINTER_H
 #define WEAK_POINTER_H
 
-#include <cstdlib>
 #include <set>
+#include <stddef.h>
+
 /**
  * Class for objects providing support for weak pointers.
  *

+ 7 - 1
apt-pkg/deb/debindexfile.cc

@@ -324,8 +324,14 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
       return _error->Error("Problem with MergeList %s",PackageFile.c_str());
 
    // Check the release file
-   string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
+   string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
+   bool releaseExists = false;
    if (FileExists(ReleaseFile) == true)
+      releaseExists = true;
+   else
+      ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
+
+   if (releaseExists == true || FileExists(ReleaseFile) == true)
    {
       FileFd Rel(ReleaseFile,FileFd::ReadOnly);
       if (_error->PendingError() == true)

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

@@ -783,45 +783,89 @@ bool debListParser::Step()
 bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,
 				    FileFd &File, string component)
 {
-   pkgTagFile Tags(&File, File.Size() + 256); // XXX
-   pkgTagSection Section;
-   if (Tags.Step(Section) == false)
-      return false;
-
-   // FIXME: Do we need it now for multi-arch?
-   // mvo: I don't think we need to fill that in (it's unused since apt-0.6)
-//    FileI->Architecture = WriteUniqString(Arch);
-   
    // apt-secure does no longer download individual (per-section) Release
    // file. to provide Component pinning we use the section name now
    FileI->Component = WriteUniqString(component);
 
-   const char *Start;
-   const char *Stop;
-   if (Section.Find("Suite",Start,Stop) == true)
-      FileI->Archive = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Component",Start,Stop) == true)
-      FileI->Component = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Version",Start,Stop) == true)
-      FileI->Version = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Origin",Start,Stop) == true)
-      FileI->Origin = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Codename",Start,Stop) == true)
-      FileI->Codename = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Label",Start,Stop) == true)
-      FileI->Label = WriteUniqString(Start,Stop - Start);
-   if (Section.Find("Architecture",Start,Stop) == true)
-      FileI->Architecture = WriteUniqString(Start,Stop - Start);
-   
-   if (Section.FindFlag("NotAutomatic",FileI->Flags,
-			pkgCache::Flag::NotAutomatic) == false)
-      _error->Warning("Bad NotAutomatic flag");
-   if (Section.FindFlag("ButAutomaticUpgrades",FileI->Flags,
-			pkgCache::Flag::ButAutomaticUpgrades) == false)
-      _error->Warning("Bad ButAutomaticUpgrades flag");
-   // overrule the NotAutomatic setting if needed as they are both present for compatibility
-   else if ((FileI->Flags & pkgCache::Flag::ButAutomaticUpgrades) == pkgCache::Flag::ButAutomaticUpgrades)
-      FileI->Flags &= ~pkgCache::Flag::NotAutomatic;
+   FILE* release = fdopen(dup(File.Fd()), "r");
+   if (release == NULL)
+      return false;
+
+   char buffer[101];
+   bool gpgClose = false;
+   while (fgets(buffer, sizeof(buffer), release) != NULL)
+   {
+      size_t len = 0;
+
+      // Skip empty lines
+      for (; buffer[len] == '\r' && buffer[len] == '\n'; ++len);
+      if (buffer[len] == '\0')
+	 continue;
+
+      // only evalute the first GPG section
+      if (strncmp("-----", buffer, 5) == 0)
+      {
+	 if (gpgClose == true)
+	    break;
+	 gpgClose = true;
+	 continue;
+      }
+
+      // seperate the tag from the data
+      for (; buffer[len] != ':' && buffer[len] != '\0'; ++len);
+      if (buffer[len] == '\0')
+	 continue;
+      char* dataStart = buffer + len;
+      for (++dataStart; *dataStart == ' '; ++dataStart);
+      char* dataEnd = dataStart;
+      for (++dataEnd; *dataEnd != '\0'; ++dataEnd);
+
+      // which datastorage need to be updated
+      map_ptrloc* writeTo = NULL;
+      if (buffer[0] == ' ')
+	 ;
+      #define APT_PARSER_WRITETO(X, Y) else if (strncmp(Y, buffer, len) == 0) writeTo = &X;
+      APT_PARSER_WRITETO(FileI->Archive, "Suite")
+      APT_PARSER_WRITETO(FileI->Component, "Component")
+      APT_PARSER_WRITETO(FileI->Version, "Version")
+      APT_PARSER_WRITETO(FileI->Origin, "Origin")
+      APT_PARSER_WRITETO(FileI->Codename, "Codename")
+      APT_PARSER_WRITETO(FileI->Label, "Label")
+      #undef APT_PARSER_WRITETO
+      #define APT_PARSER_FLAGIT(X) else if (strncmp(#X, buffer, len) == 0) \
+	 pkgTagSection::FindFlag(FileI->Flags, pkgCache::Flag:: X, dataStart, dataEnd-1);
+      APT_PARSER_FLAGIT(NotAutomatic)
+      APT_PARSER_FLAGIT(ButAutomaticUpgrades)
+      #undef APT_PARSER_FLAGIT
+
+      // load all data from the line and save it
+      string data;
+      if (writeTo != NULL)
+	 data.append(dataStart, dataEnd);
+      if (sizeof(buffer) - 1 == (dataEnd - buffer))
+      {
+	 while (fgets(buffer, sizeof(buffer), release) != NULL)
+	 {
+	    if (writeTo != NULL)
+	       data.append(buffer);
+	    if (strlen(buffer) != sizeof(buffer) - 1)
+	       break;
+	 }
+      }
+      if (writeTo != NULL)
+      {
+	 // remove spaces and stuff from the end of the data line
+	 for (std::string::reverse_iterator s = data.rbegin();
+	      s != data.rend(); ++s)
+	 {
+	    if (*s != '\r' && *s != '\n' && *s != ' ')
+	       break;
+	    *s = '\0';
+	 }
+	 *writeTo = WriteUniqString(data);
+      }
+   }
+   fclose(release);
 
    return !_error->PendingError();
 }

+ 70 - 39
apt-pkg/deb/debmetaindex.cc

@@ -119,6 +119,29 @@ string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section)
       return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section);
 }
 
+string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string &Section) const
+{
+   string Res ="";
+   if (Dist[Dist.size() - 1] != '/')
+      Res += Section + "/i18n/";
+   return Res + Type;
+}
+
+string debReleaseIndex::TranslationIndexURI(const char *Type, const string &Section) const
+{
+   string Res;
+   if (Dist[Dist.size() - 1] == '/')
+   {
+      if (Dist != "/")
+         Res = URI + Dist;
+      else 
+         Res = URI;
+      return Res + Type;
+   }
+   else
+      return URI + "dists/" + Dist + "/" + TranslationIndexURISuffix(Type, Section);
+}
+
 debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) {
 	this->URI = URI;
 	this->Dist = Dist;
@@ -155,6 +178,7 @@ vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const {
 	if (IndexTargets->empty() == false && ArchEntries.size() == 1)
 		return IndexTargets;
 
+	std::set<std::string> sections;
 	for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
 	     a != ArchEntries.end(); ++a) {
 		if (a->first == "source")
@@ -167,6 +191,37 @@ vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const {
 			Target->URI = IndexURI(Target->ShortDesc.c_str(), (*I)->Section, a->first);
 			Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section, a->first);
 			IndexTargets->push_back (Target);
+			sections.insert((*I)->Section);
+		}
+	}
+
+	// get the Translations:
+	// - if its a dists-style repository get the i18n/Index first
+	// - if its flat try to acquire files by guessing
+	if (Dist[Dist.size() - 1] == '/') {
+		std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
+		for (std::set<std::string>::const_iterator s = sections.begin();
+		     s != sections.end(); ++s) {
+			for (std::vector<std::string>::const_iterator l = lang.begin();
+			     l != lang.end(); l++) {
+				if (*l == "none") continue;
+				IndexTarget * Target = new OptionalIndexTarget();
+				Target->ShortDesc = "Translation-" + *l;
+				Target->MetaKey = TranslationIndexURISuffix(l->c_str(), *s);
+				Target->URI = TranslationIndexURI(l->c_str(), *s);
+				Target->Description = Info (Target->ShortDesc.c_str(), *s);
+				IndexTargets->push_back(Target);
+			}
+		}
+	} else {
+		for (std::set<std::string>::const_iterator s = sections.begin();
+		     s != sections.end(); ++s) {
+			IndexTarget * Target = new OptionalIndexTarget();
+			Target->ShortDesc = "TranslationIndex";
+			Target->MetaKey = TranslationIndexURISuffix("Index", *s);
+			Target->URI = TranslationIndexURI("Index", *s);
+			Target->Description = Info (Target->ShortDesc.c_str(), *s);
+			IndexTargets->push_back (Target);
 		}
 	}
 
@@ -182,58 +237,34 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const
 	 new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
 			 (*Target)->ShortDesc, HashString());
       }
-      // this is normally created in pkgAcqMetaSig, but if we run
-      // in --print-uris mode, we add it here
-      new pkgAcqMetaIndex(Owner, MetaIndexURI("Release"),
-		     MetaIndexInfo("Release"), "Release",
-		     MetaIndexURI("Release.gpg"), 
-		     ComputeIndexTargets(),
-		     new indexRecords (Dist));
-
    }
 
-   new pkgAcqMetaSig(Owner, MetaIndexURI("Release.gpg"),
-		     MetaIndexInfo("Release.gpg"), "Release.gpg",
-		     MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
-		     ComputeIndexTargets(),
-		     new indexRecords (Dist));
-
-	// Queue the translations
-	std::vector<std::string> const lang = APT::Configuration::getLanguages(true);
-	map<string, set<string> > sections;
-	for (map<string, vector<debSectionEntry const*> >::const_iterator a = ArchEntries.begin();
-	     a != ArchEntries.end(); ++a) {
-		if (a->first == "source")
-			continue;
-		for (vector<debSectionEntry const*>::const_iterator I = a->second.begin();
-		     I != a->second.end(); I++)
-			sections[(*I)->Section].insert(lang.begin(), lang.end());
-	}
-
-	for (map<string, set<string> >::const_iterator s = sections.begin();
-	     s != sections.end(); ++s)
-		for (set<string>::const_iterator l = s->second.begin();
-		     l != s->second.end(); l++) {
-			if (*l == "none") continue;
-			debTranslationsIndex i = debTranslationsIndex(URI,Dist,s->first,(*l).c_str());
-			i.GetIndexes(Owner);
-		}
+	new pkgAcqMetaClearSig(Owner, MetaIndexURI("InRelease"),
+		MetaIndexInfo("InRelease"), "InRelease",
+		MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release",
+		MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg",
+		ComputeIndexTargets(),
+		new indexRecords (Dist));
 
 	return true;
 }
 
 bool debReleaseIndex::IsTrusted() const
 {
-   string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
-      URItoFileName(MetaIndexURI("Release")) + ".gpg";
-   
    if(_config->FindB("APT::Authentication::TrustCDROM", false))
       if(URI.substr(0,strlen("cdrom:")) == "cdrom:")
 	 return true;
-   
+
+   string VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+      URItoFileName(MetaIndexURI("Release")) + ".gpg";
+
    if (FileExists(VerifiedSigFile))
       return true;
-   return false;
+
+   VerifiedSigFile = _config->FindDir("Dir::State::lists") +
+      URItoFileName(MetaIndexURI("InRelease"));
+
+   return FileExists(VerifiedSigFile);
 }
 
 vector <pkgIndexFile *> *debReleaseIndex::GetIndexFiles() {

+ 2 - 0
apt-pkg/deb/debmetaindex.h

@@ -37,6 +37,8 @@ class debReleaseIndex : public metaIndex {
    string IndexURISuffix(const char *Type, string const &Section, string const &Arch="native") const;
    string SourceIndexURI(const char *Type, const string &Section) const;
    string SourceIndexURISuffix(const char *Type, const string &Section) const;
+   string TranslationIndexURI(const char *Type, const string &Section) const;
+   string TranslationIndexURISuffix(const char *Type, const string &Section) const;
    virtual vector <pkgIndexFile *> *GetIndexFiles();
 
    virtual bool IsTrusted() const;

+ 3 - 7
apt-pkg/deb/dpkgpm.cc

@@ -322,7 +322,6 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 	 return _error->Errno("fdopen","Faild to open new FD");
       
       // Feed it the filenames.
-      bool Die = false;
       if (Version <= 1)
       {
 	 for (vector<Item>::iterator I = List.begin(); I != List.end(); I++)
@@ -339,14 +338,11 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
 	       into the pipe. */
 	    fprintf(F,"%s\n",I->File.c_str());
 	    if (ferror(F) != 0)
-	    {
-	       Die = true;
 	       break;
-	    }
 	 }
       }
       else
-	 Die = !SendV2Pkgs(F);
+	 SendV2Pkgs(F);
 
       fclose(F);
       
@@ -1415,7 +1411,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
       {
 	 while( fgets(buf, sizeof(buf), log) != NULL)
 	    fprintf(report, " %s", buf);
-	 fclose(log);
+	 pclose(log);
       }
    }
 
@@ -1431,7 +1427,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
       {
 	 while( fgets(buf, sizeof(buf), log) != NULL)
 	    fprintf(report, " %s", buf);
-	 fclose(log);
+	 pclose(log);
       }
    }
 

+ 175 - 7
apt-pkg/depcache.cc

@@ -10,6 +10,7 @@
 // Include Files							/*{{{*/
 #include <apt-pkg/depcache.h>
 #include <apt-pkg/version.h>
+#include <apt-pkg/versionmatch.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/algorithms.h>
@@ -166,7 +167,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog)			/*{{{*/
 {
    FileFd state_file;
    string const state = _config->FindFile("Dir::State::extended_states");
-   if(FileExists(state)) {
+   if(RealFileExists(state)) {
       state_file.Open(state, FileFd::ReadOnly);
       int const file_size = state_file.Size();
       if(Prog != NULL)
@@ -225,7 +226,7 @@ bool pkgDepCache::writeStateFile(OpProgress *prog, bool InstalledOnly)	/*{{{*/
    string const state = _config->FindFile("Dir::State::extended_states");
 
    // if it does not exist, create a empty one
-   if(!FileExists(state)) 
+   if(!RealFileExists(state)) 
    {
       StateFile.Open(state, FileFd::WriteAtomic);
       StateFile.Close();
@@ -1329,8 +1330,6 @@ void pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst,
 	   for (DepIterator D = instVer.DependsList(); D.end() != true; D++)
 	     {
 	       //FIXME: deal better with or-groups(?)
-	       DepIterator LocalStart = D;
-
 	       if(IsImportantDep(D) && !D.IsCritical() &&
 		  Start.TargetPkg() == D.TargetPkg())
 		 {
@@ -1510,15 +1509,19 @@ void pkgDepCache::SetReInstall(PkgIterator const &Pkg,bool To)
 /* */
 void pkgDepCache::SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo)
 {
-   ActionGroup group(*this);
 
    pkgCache::PkgIterator Pkg = TargetVer.ParentPkg();
    StateCache &P = PkgState[Pkg->ID];
 
+   if (P.CandidateVer == TargetVer)
+      return;
+
+   ActionGroup group(*this);
+
    RemoveSizes(Pkg);
    RemoveStates(Pkg);
 
-   if (P.CandidateVer == P.InstallVer)
+   if (P.CandidateVer == P.InstallVer && P.Install() == true)
       P.InstallVer = (Version *)TargetVer;
    P.CandidateVer = (Version *)TargetVer;
    P.Update(Pkg,*this);
@@ -1549,7 +1552,171 @@ void pkgDepCache::SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo)
       }
    }
 }
+									/*}}}*/
+// DepCache::SetCandidateRelease - Change the candidate version		/*{{{*/
+// ---------------------------------------------------------------------
+/* changes the candidate of a package and walks over all its dependencies
+   to check if it needs to change the candidate of the dependency, too,
+   to reach a installable versionstate */
+bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer,
+					std::string const &TargetRel)
+{
+   std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
+   return SetCandidateRelease(TargetVer, TargetRel, Changed);
+}
+bool pkgDepCache::SetCandidateRelease(pkgCache::VerIterator TargetVer,
+					std::string const &TargetRel,
+					std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > &Changed)
+{
+   ActionGroup group(*this);
+   SetCandidateVersion(TargetVer);
+
+   if (TargetRel == "installed" || TargetRel == "candidate") // both doesn't make sense in this context
+      return true;
+
+   pkgVersionMatch Match(TargetRel, pkgVersionMatch::Release);
+   // save the position of the last element we will not undo - if we have to
+   std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::iterator newChanged = --(Changed.end());
+
+   for (pkgCache::DepIterator D = TargetVer.DependsList(); D.end() == false; ++D)
+   {
+      if (D->Type != pkgCache::Dep::PreDepends && D->Type != pkgCache::Dep::Depends &&
+	  ((D->Type != pkgCache::Dep::Recommends && D->Type != pkgCache::Dep::Suggests) ||
+	   IsImportantDep(D) == false))
+	 continue;
+
+      // walk over an or-group and check if we need to do anything
+      // for simpilicity no or-group is handled as a or-group including one dependency
+      pkgCache::DepIterator Start = D;
+      bool itsFine = false;
+      for (bool stillOr = true; stillOr == true; ++Start)
+      {
+	 stillOr = (Start->CompareOp & Dep::Or) == Dep::Or;
+	 pkgCache::PkgIterator const P = Start.TargetPkg();
+	 // virtual packages can't be a solution
+	 if (P.end() == true || (P->ProvidesList == 0 && P->VersionList == 0))
+	    continue;
+	 pkgCache::VerIterator const Cand = PkgState[P->ID].CandidateVerIter(*this);
+	 // no versioned dependency - but is it installable?
+	 if (Start.TargetVer() == 0 || Start.TargetVer()[0] == '\0')
+	 {
+	    // Check if one of the providers is installable
+	    if (P->ProvidesList != 0)
+	    {
+	       pkgCache::PrvIterator Prv = P.ProvidesList();
+	       for (; Prv.end() == false; ++Prv)
+	       {
+		  pkgCache::VerIterator const C = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this);
+		  if (C.end() == true || C != Prv.OwnerVer() ||
+		      (VersionState(C.DependsList(), DepInstall, DepCandMin, DepCandPolicy) & DepCandMin) != DepCandMin)
+		     continue;
+		  break;
+	       }
+	       if (Prv.end() == true)
+		  continue;
+	    }
+	    // no providers, so check if we have an installable candidate version
+	    else if (Cand.end() == true ||
+		(VersionState(Cand.DependsList(), DepInstall, DepCandMin, DepCandPolicy) & DepCandMin) != DepCandMin)
+	       continue;
+	    itsFine = true;
+	    break;
+	 }
+	 if (Cand.end() == true)
+	    continue;
+	 // check if the current candidate is enough for the versioned dependency - and installable?
+	 if (VS().CheckDep(P.CandVersion(), Start->CompareOp, Start.TargetVer()) == true &&
+	     (VersionState(Cand.DependsList(), DepInstall, DepCandMin, DepCandPolicy) & DepCandMin) == DepCandMin)
+	 {
+	    itsFine = true;
+	    break;
+	 }
+      }
+
+      if (itsFine == true) {
+	 // something in the or-group was fine, skip all other members
+	 for (; (D->CompareOp & Dep::Or) == Dep::Or; ++D);
+	 continue;
+      }
+
+      // walk again over the or-group and check each if a candidate switch would help
+      itsFine = false;
+      for (bool stillOr = true; stillOr == true; ++D)
+      {
+	 stillOr = (D->CompareOp & Dep::Or) == Dep::Or;
+	 // changing candidate will not help if the dependency is not versioned
+	 if (D.TargetVer() == 0 || D.TargetVer()[0] == '\0')
+	 {
+	    if (stillOr == true)
+	       continue;
+	    break;
+	 }
+
+	 pkgCache::VerIterator V;
+	 if (TargetRel == "newest")
+	    V = D.TargetPkg().VersionList();
+	 else
+	    V = Match.Find(D.TargetPkg());
+
+	 // check if the version from this release could satisfy the dependency
+	 if (V.end() == true || VS().CheckDep(V.VerStr(), D->CompareOp, D.TargetVer()) == false)
+	 {
+	    if (stillOr == true)
+	       continue;
+	    break;
+	 }
+
+	 pkgCache::VerIterator oldCand = PkgState[D.TargetPkg()->ID].CandidateVerIter(*this);
+	 if (V == oldCand)
+	 {
+	    // Do we already touched this Version? If so, their versioned dependencies are okay, no need to check again
+	    for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
+		 c != Changed.end(); ++c)
+	    {
+	       if (c->first->ParentPkg != V->ParentPkg)
+		  continue;
+	       itsFine = true;
+	       break;
+	    }
+	 }
+
+	 if (itsFine == false)
+	 {
+	    // change the candidate
+	    Changed.push_back(make_pair(oldCand, TargetVer));
+	    if (SetCandidateRelease(V, TargetRel, Changed) == false)
+	    {
+	       if (stillOr == false)
+		  break;
+	       // undo the candidate changing
+	       SetCandidateVersion(oldCand);
+	       Changed.pop_back();
+	       continue;
+	    }
+	    itsFine = true;
+	 }
+
+	 // something in the or-group was fine, skip all other members
+	 for (; (D->CompareOp & Dep::Or) == Dep::Or; ++D);
+	 break;
+      }
 
+      if (itsFine == false && (D->Type == pkgCache::Dep::PreDepends || D->Type == pkgCache::Dep::Depends))
+      {
+	 // undo all changes which aren't lead to a solution
+	 for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = ++newChanged;
+	      c != Changed.end(); ++c)
+	    SetCandidateVersion(c->first);
+	 Changed.erase(newChanged, Changed.end());
+	 return false;
+      }
+   }
+   return true;
+}
+									/*}}}*/
+// DepCache::MarkAuto - set the Auto flag for a package			/*{{{*/
+// ---------------------------------------------------------------------
+/* */
 void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto)
 {
   StateCache &state = PkgState[Pkg->ID];
@@ -1752,10 +1919,11 @@ void pkgDepCache::MarkPackage(const pkgCache::PkgIterator &pkg,
       return;
 
    VerIterator const currver = pkg.CurrentVer();
-   VerIterator const candver = state.CandidateVerIter(*this);
    VerIterator const instver = state.InstVerIter(*this);
 
 #if 0
+   VerIterator const candver = state.CandidateVerIter(*this);
+
    // If a package was garbage-collected but is now being marked, we
    // should re-select it 
    // For cases when a pkg is set to upgrade and this trigger the

+ 19 - 0
apt-pkg/depcache.h

@@ -396,6 +396,25 @@ class pkgDepCache : protected pkgCache::Namespace
 
    void SetReInstall(PkgIterator const &Pkg,bool To);
    void SetCandidateVersion(VerIterator TargetVer, bool const &Pseudo = true);
+   bool SetCandidateRelease(pkgCache::VerIterator TargetVer,
+				std::string const &TargetRel);
+   /** Set the candidate version for dependencies too if needed.
+    *
+    *  Sets not only the candidate version as SetCandidateVersion does,
+    *  but walks also down the dependency tree and checks if it is required
+    *  to set the candidate of the dependency to a version from the given
+    *  release, too.
+    *
+    *  \param TargetVer new candidate version of the package
+    *  \param TargetRel try to switch to this release if needed
+    *  \param[out] Changed a list of pairs consisting of the \b old
+    *              version of the changed package and the version which
+    *              required the switch of this dependency
+    *  \return \b true if the switch was successful, \b false otherwise
+    */
+   bool SetCandidateRelease(pkgCache::VerIterator TargetVer,
+			    std::string const &TargetRel,
+			    std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > &Changed);
 
    /** Set the "is automatically installed" flag of Pkg. */
    void MarkAuto(const PkgIterator &Pkg, bool Auto);

+ 2 - 1
apt-pkg/indexcopy.cc

@@ -722,7 +722,8 @@ bool SigVerify::RunGPGV(std::string const &File, std::string const &FileGPG,
    }
 
    Args.push_back(FileGPG.c_str());
-   Args.push_back(File.c_str());
+   if (FileGPG != File)
+      Args.push_back(File.c_str());
    Args.push_back(NULL);
 
    if (Debug == true)

+ 10 - 7
apt-pkg/indexrecords.cc

@@ -55,14 +55,17 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
    }
 
    pkgTagSection Section;
-   if (TagFile.Step(Section) == false)
-   {
-      strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
-      return false;
-   }
-
    const char *Start, *End;
-   Section.Get (Start, End, 0);
+   // Skip over sections beginning with ----- as this is an idicator for clearsigns
+   do {
+      if (TagFile.Step(Section) == false)
+      {
+	 strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str());
+	 return false;
+      }
+
+      Section.Get (Start, End, 0);
+   } while (End - Start > 5 && strncmp(Start, "-----", 5) == 0);
 
    Suite = Section.FindS("Suite");
    Dist = Section.FindS("Codename");

+ 3 - 3
apt-pkg/init.cc

@@ -97,10 +97,10 @@ bool pkgInitConfig(Configuration &Cnf)
    const char *Cfg = getenv("APT_CONFIG");
    if (Cfg != 0)
    {
-      if (FileExists(Cfg) == true)
+      if (RealFileExists(Cfg) == true)
 	 Res &= ReadConfigFile(Cnf,Cfg);
       else
-	 _error->WarningE("FileExists",_("Unable to read %s"),Cfg);
+	 _error->WarningE("RealFileExists",_("Unable to read %s"),Cfg);
    }
 
    // Read the configuration parts dir
@@ -112,7 +112,7 @@ bool pkgInitConfig(Configuration &Cnf)
 
    // Read the main config file
    string FName = Cnf.FindFile("Dir::Etc::main");
-   if (FileExists(FName) == true)
+   if (RealFileExists(FName) == true)
       Res &= ReadConfigFile(Cnf,FName);
 
    if (Res == false)

+ 3 - 1
apt-pkg/policy.cc

@@ -45,6 +45,8 @@ using namespace std;
    file matches the V0 policy engine. */
 pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner)
 {
+   if (Owner == 0 || &(Owner->Head()) == 0)
+      return;
    PFPriority = new signed short[Owner->Head().PackageFileCount];
    Pins = new Pin[Owner->Head().PackageCount];
 
@@ -328,7 +330,7 @@ bool ReadPinFile(pkgPolicy &Plcy,string File)
    if (File.empty() == true)
       File = _config->FindFile("Dir::Etc::Preferences");
 
-   if (FileExists(File) == false)
+   if (RealFileExists(File) == false)
       return true;
    
    FileFd Fd(File,FileFd::ReadOnly);

+ 3 - 3
apt-pkg/sourcelist.cc

@@ -197,7 +197,7 @@ bool pkgSourceList::ReadMainList()
    string Main = _config->FindFile("Dir::Etc::sourcelist");
    string Parts = _config->FindDir("Dir::Etc::sourceparts");
    
-   if (FileExists(Main) == true)
+   if (RealFileExists(Main) == true)
       Res &= ReadAppend(Main);
    else if (DirectoryExists(Parts) == false)
       // Only warn if there are no sources.list.d.
@@ -205,9 +205,9 @@ bool pkgSourceList::ReadMainList()
 
    if (DirectoryExists(Parts) == true)
       Res &= ReadSourceDir(Parts);
-   else if (FileExists(Main) == false)
+   else if (RealFileExists(Main) == false)
       // Only warn if there is no sources.list file.
-      _error->WarningE("FileExists", _("Unable to read %s"), Main.c_str());
+      _error->WarningE("RealFileExists", _("Unable to read %s"), Main.c_str());
 
    return Res;
 }

+ 7 - 3
apt-pkg/tagfile.cc

@@ -399,9 +399,13 @@ bool pkgTagSection::FindFlag(const char *Tag,unsigned long &Flags,
    const char *Stop;
    if (Find(Tag,Start,Stop) == false)
       return true;
-   
-   switch (StringToBool(string(Start,Stop)))
-   {     
+   return FindFlag(Flags, Flag, Start, Stop);
+}
+bool const pkgTagSection::FindFlag(unsigned long &Flags, unsigned long Flag,
+					char const* Start, char const* Stop)
+{
+   switch (StringToBool(string(Start, Stop)))
+   {
       case 0:
       Flags &= ~Flag;
       return true;

+ 2 - 0
apt-pkg/tagfile.h

@@ -60,6 +60,8 @@ class pkgTagSection
    unsigned long long FindULL(const char *Tag, unsigned long long const &Default = 0) const;
    bool FindFlag(const char *Tag,unsigned long &Flags,
 		 unsigned long Flag) const;
+   bool static const FindFlag(unsigned long &Flags, unsigned long Flag,
+				const char* Start, const char* Stop);
    bool Scan(const char *Start,unsigned long MaxLength);
    inline unsigned long size() const {return Stop - Section;};
    void Trim();

+ 2 - 2
apt-pkg/vendorlist.cc

@@ -21,11 +21,11 @@ bool pkgVendorList::ReadMainList()
    Configuration Cnf;
 
    string CnfFile = _config->FindDir("Dir::Etc::vendorparts");
-   if (FileExists(CnfFile) == true)
+   if (DirectoryExists(CnfFile) == true)
       if (ReadConfigDir(Cnf,CnfFile,true) == false)
 	 return false;
    CnfFile = _config->FindFile("Dir::Etc::vendorlist");
-   if (FileExists(CnfFile) == true)
+   if (RealFileExists(CnfFile) == true)
       if (ReadConfigFile(Cnf,CnfFile,true) == false)
 	 return false;
 

+ 68 - 33
cmdline/apt-get.cc

@@ -538,7 +538,9 @@ bool ShowEssential(ostream &out,CacheFile &Cache)
         //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
 	 }
       }
-      
+      else
+	 continue;
+
       if (I->CurrentVer == 0)
 	 continue;
 
@@ -626,6 +628,8 @@ class CacheSetHelperAPTGet : public APT::CacheSetHelper {
 	APT::PackageSet virtualPkgs;
 
 public:
+	std::list<std::pair<pkgCache::VerIterator, std::string> > selectedByRelease;
+
 	CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
 		explicitlyNamed = true;
 	}
@@ -644,9 +648,9 @@ public:
 	}
 	virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
 				 string const &ver, bool const &verIsRel) {
-		if (ver != Ver.VerStr())
-			ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
-				 Ver.VerStr(), Ver.RelStr().c_str(), Pkg.FullName(true).c_str());
+		if (ver == Ver.VerStr())
+			return;
+		selectedByRelease.push_back(make_pair(Ver, ver));
 	}
 
 	bool showVirtualPackageErrors(pkgCacheFile &Cache) {
@@ -827,6 +831,37 @@ struct TryToInstall {
       }
    }
 
+   bool propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > start, std::ostream &out)
+   {
+      for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
+		s != start.end(); ++s)
+	 Cache->GetDepCache()->SetCandidateVersion(s->first);
+
+      bool Success = true;
+      std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
+      for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
+		s != start.end(); ++s)
+      {
+	 Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
+	 // We continue here even if it failed to enhance the ShowBroken output
+	 Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
+      }
+      for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
+	   c != Changed.end(); ++c)
+      {
+	 if (c->second.end() == true)
+	    ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
+		     c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
+	 else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
+	 {
+	    pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
+	    ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
+		     V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
+	 }
+      }
+      return Success;
+   }
+
    void doAutoInstall() {
       for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
 	   P != doAutoInstallLater.end(); ++P) {
@@ -1077,8 +1112,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
    {
       // force a hashsum for compatibility reasons
       _config->CndSet("Acquire::ForceHash", "md5sum");
-      if (Fetcher.Setup(&Stat, "") == false)
-	 return false;
    }
    else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
       return false;
@@ -1608,10 +1641,6 @@ bool DoAutomaticRemove(CacheFile &Cache)
    if(Debug)
       std::cout << "DoAutomaticRemove()" << std::endl;
 
-   // we don't want to autoremove and we don't want to see it, so why calculating?
-   if (doAutoRemove == false && hideAutoRemove == true)
-      return true;
-
    if (doAutoRemove == true &&
 	_config->FindB("APT::Get::Remove",true) == false)
    {
@@ -1622,7 +1651,7 @@ bool DoAutomaticRemove(CacheFile &Cache)
 
    bool purgePkgs = _config->FindB("APT::Get::Purge", false);
    bool smallList = (hideAutoRemove == false &&
-	strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
+		strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
 
    string autoremovelist, autoremoveversions;
    unsigned long autoRemoveCount = 0;
@@ -1645,8 +1674,12 @@ bool DoAutomaticRemove(CacheFile &Cache)
 	 }
 	 else
 	 {
+	    // if the package is a new install and already garbage we don't need to
+	    // install it in the first place, so nuke it instead of show it
+	    if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
+	       Cache->MarkDelete(Pkg, false);
 	    // only show stuff in the list that is not yet marked for removal
-	    if(Cache[Pkg].Delete() == false) 
+	    else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) 
 	    {
 	       ++autoRemoveCount;
 	       // we don't need to fill the strings if we don't need them
@@ -1659,6 +1692,20 @@ bool DoAutomaticRemove(CacheFile &Cache)
 	 }
       }
    }
+
+   // Now see if we had destroyed anything (if we had done anything)
+   if (Cache->BrokenCount() != 0)
+   {
+      c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
+	         "shouldn't happen. Please file a bug report against apt.") << endl;
+      c1out << endl;
+      c1out << _("The following information may help to resolve the situation:") << endl;
+      c1out << endl;
+      ShowBroken(c1out,Cache,false);
+
+      return _error->Error(_("Internal Error, AutoRemover broke stuff"));
+   }
+
    // if we don't remove them, we should show them!
    if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
    {
@@ -1671,18 +1718,6 @@ bool DoAutomaticRemove(CacheFile &Cache)
 	          "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
       c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
    }
-   // Now see if we had destroyed anything (if we had done anything)
-   else if (Cache->BrokenCount() != 0)
-   {
-      c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
-	         "shouldn't happen. Please file a bug report against apt.") << endl;
-      c1out << endl;
-      c1out << _("The following information may help to resolve the situation:") << endl;
-      c1out << endl;
-      ShowBroken(c1out,Cache,false);
-
-      return _error->Error(_("Internal Error, AutoRemover broke stuff"));
-   }
    return true;
 }
 									/*}}}*/
@@ -1775,6 +1810,7 @@ bool DoInstall(CommandLine &CmdL)
       {
 	 if (order[i] == MOD_INSTALL) {
 	    InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
+	    InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
 	    InstallAction.doAutoInstall();
 	 }
 	 else if (order[i] == MOD_REMOVE)
@@ -1839,16 +1875,15 @@ bool DoInstall(CommandLine &CmdL)
 	 pkgCache::PkgIterator I(Cache,Cache.List[J]);
 	 if ((*Cache)[I].Install() == false)
 	    continue;
+	 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
+	 if (Cand.Pseudo() == true)
+	    continue;
 
-	 const char **J;
-	 for (J = CmdL.FileList + 1; *J != 0; J++)
-	    if (strcmp(*J,I.Name()) == 0)
-		break;
-	 
-	 if (*J == 0) {
-	    List += I.FullName(true) + " ";
-	    VersionsList += string(Cache[I].CandVersion) + "\n";
-	 }
+	 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
+	    continue;
+
+	 List += I.FullName(true) + " ";
+	 VersionsList += string(Cache[I].CandVersion) + "\n";
       }
       
       ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);

+ 6 - 1
cmdline/apt-key

@@ -5,7 +5,12 @@ unset GREP_OPTIONS
 
 # We don't use a secret keyring, of course, but gpg panics and
 # implodes if there isn't one available
-GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /etc/apt/secring.gpg --trustdb-name /etc/apt/trustdb.gpg"
+GPG_CMD='gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /etc/apt/secring.gpg'
+
+if ! id -u > /dev/null; then
+	GPG_CMD="$GPG_CMD --trustdb-name /etc/apt/trustdb.gpg"
+fi
+
 GPG="$GPG_CMD"
 
 MASTER_KEYRING=""

+ 9 - 0
debian/NEWS

@@ -1,3 +1,12 @@
+apt (0.8.11) UNRELEASED; urgency=low
+
+  * apt-get install pkg/experimental will now not only switch the
+    candidate of package pkg to the version from the release experimental
+    but also of all dependencies of pkg if the current candidate can't
+    satisfy a versioned dependency.
+
+ -- David Kalnischkies <kalnischkies@gmail.com>  Fri, 03 Dec 2010 14:09:12 +0100
+
 apt (0.7.26~exp3) experimental; urgency=low
 
   * apt-ftparchive now reads the standard configuration files in

+ 1 - 0
debian/apt-transport-https.dirs

@@ -0,0 +1 @@
+usr/lib/apt/methods

+ 1 - 0
debian/apt-transport-https.install

@@ -0,0 +1 @@
+bin/methods/https usr/lib/apt/methods

+ 1 - 0
debian/apt-utils.install

@@ -0,0 +1 @@
+bin/libapt-inst*.so.* usr/lib/

+ 119 - 0
debian/apt-utils.symbols

@@ -0,0 +1,119 @@
+libapt-inst.so.1.2 libapt-inst1.2
+| apt-utils #MINVER#
+* Build-Depends-Package: libapt-pkg-dev
+ (c++)"ExtractTar::Done(bool)@Base" 0.8.0
+ (c++)"ExtractTar::Go(pkgDirStream&)@Base" 0.8.0
+ (c++)"ExtractTar::StartGzip()@Base" 0.8.0
+ (c++)"ExtractTar::ExtractTar(FileFd&, unsigned long, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)@Base" 0.8.0
+ (c++)"ExtractTar::~ExtractTar()@Base" 0.8.0
+ (c++)"debDebFile::GotoMember(char const*)@Base" 0.8.0
+ (c++)"debDebFile::CheckMember(char const*)@Base" 0.8.0
+ (c++)"debDebFile::MergeControl(pkgDataBase&)@Base" 0.8.0
+ (c++)"debDebFile::ControlExtract::DoItem(pkgDirStream::Item&, int&)@Base" 0.8.0
+ (c++)"debDebFile::ControlExtract::~ControlExtract()@Base" 0.8.0
+ (c++)"debDebFile::ExtractArchive(pkgDirStream&)@Base" 0.8.0
+ (c++)"debDebFile::ExtractControl(pkgDataBase&)@Base" 0.8.0
+ (c++)"debDebFile::MemControlExtract::TakeControl(void const*, unsigned long)@Base" 0.8.0
+ (c++)"debDebFile::MemControlExtract::Read(debDebFile&)@Base" 0.8.0
+ (c++)"debDebFile::MemControlExtract::DoItem(pkgDirStream::Item&, int&)@Base" 0.8.0
+ (c++)"debDebFile::MemControlExtract::Process(pkgDirStream::Item&, unsigned char const*, unsigned long, unsigned long)@Base" 0.8.0
+ (c++)"debDebFile::MemControlExtract::~MemControlExtract()@Base" 0.8.0
+ (c++)"debDebFile::debDebFile(FileFd&)@Base" 0.8.0
+ (c++)"pkgExtract::FinishedFile(pkgDirStream::Item&, int)@Base" 0.8.0
+ (c++)"pkgExtract::CheckDirReplace(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned int)@Base" 0.8.0
+ (c++)"pkgExtract::HandleOverwrites(pkgFLCache::NodeIterator, bool)@Base" 0.8.0
+ (c++)"pkgExtract::Fail(pkgDirStream::Item&, int)@Base" 0.8.0
+ (c++)"pkgExtract::DoItem(pkgDirStream::Item&, int&)@Base" 0.8.0
+ (c++)"pkgExtract::Aborted()@Base" 0.8.0
+ (c++)"pkgExtract::Finished()@Base" 0.8.0
+ (c++)"pkgExtract::pkgExtract(pkgFLCache&, pkgCache::VerIterator)@Base" 0.8.0
+ (c++)"pkgExtract::~pkgExtract()@Base" 0.8.0
+ (c++)"pkgFLCache::TreeLookup(unsigned int*, char const*, char const*, unsigned long, unsigned int*, bool)@Base" 0.8.0
+ (c++)"pkgFLCache::AddConfFile(char const*, char const*, pkgFLCache::PkgIterator const&, unsigned char const*)@Base" 0.8.0
+ (c++)"pkgFLCache::AddDiversion(pkgFLCache::PkgIterator const&, char const*, char const*)@Base" 0.8.0
+ (c++)"pkgFLCache::BeginDiverLoad()@Base" 0.8.0
+ (c++)"pkgFLCache::FinishDiverLoad()@Base" 0.8.0
+ (c++)"pkgFLCache::GetPkg(char const*, char const*, bool)@Base" 0.8.0
+ (c++)"pkgFLCache::Header::Header()@Base" 0.8.0
+ (c++)"pkgFLCache::GetNode(char const*, char const*, unsigned int, bool, bool)@Base" 0.8.0
+ (c++)"pkgFLCache::DropNode(unsigned int)@Base" 0.8.0
+ (c++)"pkgFLCache::HashNode(pkgFLCache::NodeIterator const&)@Base" 0.8.0
+ (c++)"pkgFLCache::PrintTree(unsigned int, unsigned long)@Base" 0.8.0
+ (c++)"pkgFLCache::pkgFLCache(DynamicMMap&)@Base" 0.8.0
+ (c++)"pkgDataBase::GetMetaTmp(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.8.0
+ (c++)"pkgDataBase::~pkgDataBase()@Base" 0.8.0
+ (c++)"pkgDirStream::FinishedFile(pkgDirStream::Item&, int)@Base" 0.8.0
+ (c++)"pkgDirStream::Fail(pkgDirStream::Item&, int)@Base" 0.8.0
+ (c++)"pkgDirStream::DoItem(pkgDirStream::Item&, int&)@Base" 0.8.0
+ (c++)"pkgDirStream::Process(pkgDirStream::Item&, unsigned char const*, unsigned long, unsigned long)@Base" 0.8.0
+ (c++)"pkgDirStream::~pkgDirStream()@Base" 0.8.0
+ (c++|optional)"debListParser::~debListParser()@Base" 0.8.0
+ (c++|optional)"pkgCacheGenerator::ListParser::CollectFileProvides(pkgCache&, pkgCache::VerIterator&)@Base" 0.8.0
+ (c++|optional)"pkgCacheGenerator::ListParser::~ListParser()@Base" 0.8.0
+ (c++|optional)"pkgCache::DepIterator::operator++(int)@Base" 0.8.0
+ (c++|optional)"pkgCache::DepIterator::operator++()@Base" 0.8.0
+ (c++|optional)"pkgCache::VerIterator::operator++(int)@Base" 0.8.0
+ (c++|optional)"pkgCache::VerIterator::operator++()@Base" 0.8.0
+ (c++)"ARArchive::LoadHeaders()@Base" 0.8.0
+ (c++)"ARArchive::ARArchive(FileFd&)@Base" 0.8.0
+ (c++)"ARArchive::~ARArchive()@Base" 0.8.0
+ (c++)"debDpkgDB::InitMetaTmp(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)@Base" 0.8.0
+ (c++)"debDpkgDB::LoadChanges()@Base" 0.8.0
+ (c++)"debDpkgDB::ReadConfFiles()@Base" 0.8.0
+ (c++)"debDpkgDB::ReadyFileList(OpProgress&)@Base" 0.8.0
+ (c++)"debDpkgDB::ReadyPkgCache(OpProgress&)@Base" 0.8.0
+ (c++)"debDpkgDB::ReadDiversions()@Base" 0.8.0
+ (c++)"debDpkgDB::ReadFList(OpProgress&)@Base" 0.8.0
+ (c++)"debDpkgDB::debDpkgDB()@Base" 0.8.0
+ (c++)"debDpkgDB::~debDpkgDB()@Base" 0.8.0
+ (c++)"pkgFLCache::NodeIterator::RealPackage() const@Base" 0.8.0
+ (c++)"pkgFLCache::Header::CheckSizes(pkgFLCache::Header&) const@Base" 0.8.0
+ (c++|optional)"pkgCache::DepIterator::OwnerPointer() const@Base" 0.8.0
+ (c++|optional)"pkgCache::VerIterator::OwnerPointer() const@Base" 0.8.0
+ (c++)"ARArchive::FindMember(char const*) const@Base" 0.8.0
+ (c++)"typeinfo for ExtractTar@Base" 0.8.0
+ (c++)"typeinfo for pkgExtract@Base" 0.8.0
+ (c++)"typeinfo for pkgDataBase@Base" 0.8.0
+ (c++)"typeinfo for pkgDirStream@Base" 0.8.0
+ (c++)"typeinfo for debDpkgDB@Base" 0.8.0
+ (c++)"typeinfo for debDebFile::ControlExtract@Base" 0.8.0
+ (c++)"typeinfo for debDebFile::MemControlExtract@Base" 0.8.0
+ (c++|optional)"typeinfo for pkgCacheGenerator::ListParser@Base" 0.8.0
+ (c++|optional)"typeinfo for pkgCache::DepIterator@Base" 0.8.0
+ (c++|optional)"typeinfo for pkgCache::VerIterator@Base" 0.8.0
+ (c++|optional)"typeinfo for pkgCache::Iterator<pkgCache::Dependency, pkgCache::DepIterator>@Base" 0.8.0
+ (c++|optional)"typeinfo for pkgCache::Iterator<pkgCache::Package, pkgCache::PkgIterator>@Base" 0.8.0
+ (c++|optional)"typeinfo for pkgCache::Iterator<pkgCache::Version, pkgCache::VerIterator>@Base" 0.8.0
+ (c++)"typeinfo name for ExtractTar@Base" 0.8.0
+ (c++)"typeinfo name for pkgExtract@Base" 0.8.0
+ (c++)"typeinfo name for pkgDataBase@Base" 0.8.0
+ (c++)"typeinfo name for pkgDirStream@Base" 0.8.0
+ (c++)"typeinfo name for debDpkgDB@Base" 0.8.0
+ (c++)"typeinfo name for debDebFile::ControlExtract@Base" 0.8.0
+ (c++)"typeinfo name for debDebFile::MemControlExtract@Base" 0.8.0
+ (c++|optional)"typeinfo name for pkgCacheGenerator::ListParser@Base" 0.8.0
+ (c++|optional)"typeinfo name for pkgCache::DepIterator@Base" 0.8.0
+ (c++|optional)"typeinfo name for pkgCache::VerIterator@Base" 0.8.0
+ (c++|optional)"typeinfo name for pkgCache::Iterator<pkgCache::Dependency, pkgCache::DepIterator>@Base" 0.8.0
+ (c++|optional)"typeinfo name for pkgCache::Iterator<pkgCache::Package, pkgCache::PkgIterator>@Base" 0.8.0
+ (c++|optional)"typeinfo name for pkgCache::Iterator<pkgCache::Version, pkgCache::VerIterator>@Base" 0.8.0
+ (c++)"vtable for ExtractTar@Base" 0.8.0
+ (c++)"vtable for pkgExtract@Base" 0.8.0
+ (c++)"vtable for pkgDataBase@Base" 0.8.0
+ (c++)"vtable for pkgDirStream@Base" 0.8.0
+ (c++)"vtable for debDpkgDB@Base" 0.8.0
+ (c++)"vtable for debDebFile::ControlExtract@Base" 0.8.0
+ (c++)"vtable for debDebFile::MemControlExtract@Base" 0.8.0
+ (c++|optional)"vtable for pkgCacheGenerator::ListParser@Base" 0.8.0
+ (c++|optional)"vtable for pkgCache::DepIterator@Base" 0.8.0
+ (c++|optional)"vtable for pkgCache::VerIterator@Base" 0.8.0
+ (c++|optional)"vtable for pkgCache::Iterator<pkgCache::Dependency, pkgCache::DepIterator>@Base" 0.8.0
+ (c++|optional)"vtable for pkgCache::Iterator<pkgCache::Package, pkgCache::PkgIterator>@Base" 0.8.0
+ (c++|optional)"vtable for pkgCache::Iterator<pkgCache::Version, pkgCache::VerIterator>@Base" 0.8.0
+### try to ignore std:: template instances
+ (c++|optional)"std::basic_string<char, std::char_traits<char>, std::allocator<char> >& std::basic_string<char, std::char_traits<char>, std::allocator<char> >::append<unsigned char*>(unsigned char*, unsigned char*)@Base" 0.8.0
+ (c++|regex|optional)"^std::basic_string<.+ >\(.+\)@Base$" 0.8.0
+ (c++|regex|optional)"^char\* std::[^ ]+<.+ >::_.+@Base$" 0.8.0
+ (c++|regex|optional)"^typeinfo name for std::iterator<.*>@Base$" 0.8.0
+ (c++|regex|optional)"^typeinfo for std::iterator<.*>@Base$" 0.8.0
+###

debian/bugscript → debian/apt.bug-script


+ 0 - 1
debian/apt.dirs

@@ -13,4 +13,3 @@ var/lib/apt/mirrors/partial
 var/lib/apt/periodic
 var/log/apt
 usr/share/bug/apt
-usr/share/lintian/overrides

+ 5 - 0
debian/apt.install

@@ -0,0 +1,5 @@
+bin/apt-* usr/bin/
+bin/libapt-pkg*.so.* usr/lib/
+bin/methods/* usr/lib/apt/methods/
+scripts/dselect/* usr/lib/dpkg/methods/apt/
+locale usr/share/

share/lintian-overrides → debian/apt.lintian-overrides


File diff suppressed because it is too large
+ 1263 - 0
debian/apt.symbols


+ 73 - 2
debian/changelog

@@ -1,4 +1,75 @@
-apt (0.8.11) unstable; urgency=low
+apt (0.8.11) UNRELEASED; urgency=low
+
+  [ David Kalnischkies ]
+  * apt-pkg/depcache.cc:
+    - add SetCandidateRelease() to set a candidate version and
+      the candidates of dependencies if needed to a specified
+      release (Closes: #572709)
+  * cmdline/apt-get.cc:
+    - if --print-uris is used don't setup downloader as we don't need
+      progress, lock nor the directories it would create otherwise
+    - show dependencies of essential packages which are going to remove
+      only if they cause the remove of this essential (Closes: #601961)
+    - keep not installed garbage packages uninstalled instead of showing
+      in the autoremove section and installing those (Closes: #604222)
+    - change pkg/release behavior to use the new SetCandidateRelease
+      so installing packages from experimental or backports is easier
+    - really do not show packages in the extra section if they were
+      requested on the commandline, e.g. with a modifier (Closes: #184730)
+  * debian/control:
+    - add Vcs-Browser now that loggerhead works again (Closes: #511168)
+    - depend on debhelper 7 to raise compat level
+    - depend on dpkg-dev (>= 1.15.8) to have c++ symbol mangling
+  * apt-pkg/contrib/fileutl.cc:
+    - add a RealFileExists method and check that your configuration files
+      are real files to avoid endless loops if not (Closes: #604401)
+    - ignore non-regular files in GetListOfFilesInDir (Closes: #594694)
+  * apt-pkg/contrib/weakptr.h:
+    - include stddefs.h to fix compile error (undefined NULL) with gcc-4.6
+  * methods/https.cc:
+    - fix CURLOPT_SSL_VERIFYHOST by really passing 2 to it if enabled
+  * deb/dpkgpm.cc:
+    - fix popen/fclose mismatch reported by cppcheck. Thanks to Petter
+      Reinholdtsen for report and patch! (Closes: #607803)
+  * doc/apt.conf.5.xml:
+    - fix multipl{y,e} spelling error reported by Jakub Wilk (Closes: #607636)
+  * apt-inst/contrib/extracttar.cc:
+    - let apt-utils work with encoded tar headers if uid/gid are large.
+      Thanks to Nobuhiro Hayashi for the patch! (Closes: #330162)
+  * apt-pkg/cacheiterator.h:
+    - do not segfault if cache is not build (Closes: #254770)
+  * doc/apt-get.8.xml:
+    - remove duplicated mentioning of --install-recommends
+  * doc/sources.list.5.xml:
+    - remove obsolete references to non-us (Closes: #594495)
+  * debian/rules:
+    - use -- instead of deprecated -u for dh_gencontrol
+    - remove shlibs.local creation and usage
+    - show differences in the symbol files, but never fail
+  * pre-build.sh:
+    - remove as it is not needed for a working 'bzr bd'
+  * debian/{apt,apt-utils}.symbols:
+    - ship experimental unmangled c++ symbol files
+  * methods/rred.cc:
+    - operate optional on gzip compressed pdiffs
+  * apt-pkg/acquire-item.cc:
+    - don't uncompress downloaded pdiff files before feeding it to rred
+    - try downloading clearsigned InRelease before trying Release.gpg
+    - change the internal handling of Extensions in pkgAcqIndex
+    - add a special uncompressed compression type to prefer those files
+    - download and use i18n/Index to choose which Translations to download
+  * cmdline/apt-key:
+    - don't set trustdb-name as non-root so 'list' and 'finger'
+      can be used without being root (Closes: #393005, #592107)
+  * apt-pkg/deb/deblistparser.cc:
+    - rewrite LoadReleaseInfo to cope with clearsigned Releasefiles
+  * ftparchive/writer.cc:
+    - add config option to search for more patterns in release command
+    - include Index files by default in the Release file
+  * methods/{gzip,bzip}.cc:
+    - print a good error message if FileSize() is zero
+  * apt-pkg/aptconfiguration.cc:
+    - remove the inbuilt Translation files whitelist
 
   [ Michael Vogt ]
   * methods/http.cc:
@@ -16,7 +87,7 @@ apt (0.8.11) unstable; urgency=low
       will actually test uncompressed indexes regardless of the internal
       default value of Acquire::GzipIndexes.
 
- -- Michael Vogt <mvo@debian.org>  Tue, 01 Feb 2011 09:38:48 +0100
+ -- David Kalnischkies <kalnischkies@gmail.com>  Fri, 28 Jan 2011 12:22:25 +0100
 
 apt (0.8.10.3) unstable; urgency=low
 

+ 1 - 1
debian/compat

@@ -1 +1 @@
-5
+7

+ 2 - 1
debian/control

@@ -6,9 +6,10 @@ Uploaders: Michael Vogt <mvo@debian.org>, Otavio Salvador <otavio@debian.org>,
  Christian Perrier <bubulle@debian.org>, Daniel Burrows <dburrows@debian.org>,
  Luca Bruno <lethalman88@gmail.com>, Julian Andres Klode <jak@debian.org>
 Standards-Version: 3.9.0
-Build-Depends: debhelper (>= 5.0), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.0), zlib1g-dev | libz-dev, debiandoc-sgml, xsltproc, docbook-xsl, docbook-xml, po4a (>= 0.34-2), autotools-dev, autoconf, automake, doxygen
+Build-Depends: dpkg-dev (>= 1.15.8), debhelper (>= 7.2.3~), libdb-dev, gettext (>= 0.12), libcurl4-gnutls-dev (>= 7.19.0), zlib1g-dev | libz-dev, debiandoc-sgml, xsltproc, docbook-xsl, docbook-xml, po4a (>= 0.34-2), autotools-dev, autoconf, automake, doxygen
 Build-Conflicts: autoconf2.13, automake1.4
 Vcs-Bzr: http://bzr.debian.org/apt/debian-sid/
+Vcs-Browser: http://bzr.debian.org/loggerhead/apt/debian-sid/
 
 Package: apt
 Architecture: any

+ 3 - 0
debian/libapt-pkg-dev.install

@@ -0,0 +1,3 @@
+bin/libapt-pkg*.so usr/lib/
+bin/libapt-inst*.so usr/lib/
+include/apt-pkg/*.h usr/include/apt-pkg/

+ 37 - 82
debian/rules

@@ -2,17 +2,6 @@
 # Made with the aid of dh_make, by Craig Small
 # Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess.
 # Some lines taken from debmake, by Christoph Lameter.
-# $Id: rules,v 1.68 2004/05/30 18:21:43 mdz Exp $
-
-# LD_LIBRARY_PATH=pwd/debian/apt/usr/lib dh_shlibdeps -papt
-# dpkg: /home/jgg/work/apt2/debian/apt/usr/lib/libapt-pkg.so.2.9 not found.
-
-# For the deb builder, you can run 'debian/rules cvs-build', which does all
-# steps nescessary to produce a proper source tarball with the CVS/ removed.
-# It builds in debian/cvs-build/apt-<VER>/, and places files in
-# debian/cvs-build/.  Optionally, you can run 'debian/rules cvs-mkul' to
-# create ../upload-<VER>, with all the files needed to be uploaded placed
-# in it.
 
 export DEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
 export DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
@@ -85,18 +74,8 @@ include buildlib/libversion.mak
 LIBAPTPKG_PROVIDE=libapt-pkg$(LIBAPTPKG_MAJOR)
 LIBAPTINST_PROVIDE=libapt-inst$(LIBAPTINST_MAJOR)
 
-debian/shlibs.local: apt-pkg/makefile
-	# We have 3 shlibs.local files: One for 'apt', one for 'apt-utils' and
-	# one for the rest of the packages. This ensures that each package gets
-	# the right overrides…
-	rm -rf $@ $@.apt $@.apt-utils
-	echo "libapt-pkg $(LIBAPTPKG_MAJOR)" > $@.apt
-
-	echo "libapt-pkg $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@.apt-utils
-	echo "libapt-inst $(LIBAPTINST_MAJOR)" >> $@.apt-utils
-
-	echo "libapt-pkg $(LIBAPTPKG_MAJOR) $(LIBAPTPKG_PROVIDE)" > $@
-	echo "libapt-inst $(LIBAPTINST_MAJOR) $(LIBAPTINST_PROVIDE)" >> $@
+# do not fail as we are just experimenting with symbol files for now
+export DPKG_GENSYMBOLS_CHECK_LEVEL=0
 
 build: build/build-stamp
 build-doc: build/build-doc-stamp
@@ -131,15 +110,12 @@ clean:
 	[ ! -f Makefile ] || $(MAKE) clean distclean
 	rm -rf build
 
-	# Add here commands to clean up after the build process.
-	dh_clean debian/copyright debian/shlibs.local debian/shlibs.local.apt debian/shlibs.local.apt-utils
-
 binary-indep: apt-doc libapt-pkg-doc
 # Build architecture-independent files here.
-libapt-pkg-doc: build-doc debian/shlibs.local
+libapt-pkg-doc: build-doc
 	dh_testdir -p$@
 	dh_testroot -p$@
-	dh_clean -p$@ -k
+	dh_prep -p$@
 	dh_installdirs -p$@
 #
 # libapt-pkg-doc install
@@ -158,14 +134,14 @@ libapt-pkg-doc: build-doc debian/shlibs.local
 	dh_compress -p$@
 	dh_fixperms -p$@
 	dh_installdeb -p$@
-	dh_gencontrol -p$@ -u -Vlibapt-pkg:provides=$(LIBAPTPKG_PROVIDE)
+	dh_gencontrol -p$@ -- -Vlibapt-pkg:provides=$(LIBAPTPKG_PROVIDE)
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 
 apt-doc: build-doc
 	dh_testdir -p$@
 	dh_testroot -p$@
-	dh_clean -p$@ -k
+	dh_prep -p$@
 #
 # apt-doc install
 #
@@ -188,98 +164,80 @@ apt-doc: build-doc
 
 binary-arch: apt libapt-pkg-dev apt-utils apt-transport-https
 apt_MANPAGES = apt-cache apt-cdrom apt-config apt-get apt-key apt-mark apt-secure apt apt.conf apt_preferences sources.list
-apt: build build-doc debian/shlibs.local
+apt: build build-doc
 	dh_testdir -p$@
 	dh_testroot -p$@
-	dh_clean -p$@ -k
+	dh_prep -p$@
 	dh_installdirs -p$@
 #
 # apt install
 #
-	cp $(BLD)/bin/apt-* debian/$@/usr/bin/
-
-	# Remove the bits that are in apt-utils
-	rm $(addprefix debian/$@/usr/bin/apt-,$(APT_UTILS))
-
-	# install the shared libs
-	find $(BLD)/bin/ -type f -name "libapt-pkg*.so.*" -exec cp -a "{}" debian/$@/usr/lib/ \;
-	find $(BLD)/bin/ -type l -name "libapt-pkg*.so.*" -exec cp -a "{}" debian/$@/usr/lib/ \;
-
-	cp $(BLD)/bin/methods/* debian/$@/usr/lib/apt/methods/
-	# https has its own package
-	rm debian/$@/usr/lib/apt/methods/https
-
-	cp $(BLD)/scripts/dselect/* debian/$@/usr/lib/dpkg/methods/apt/
-	cp -r $(BLD)/locale debian/$@/usr/share/
-
-	cp debian/bugscript debian/$@/usr/share/bug/apt/script
-	cp debian/apt.logrotate debian/$@/etc/logrotate.d/apt
-
 	cp debian/apt.conf.autoremove debian/$@/etc/apt/apt.conf.d/01autoremove
 
-	# copy lintian override
-	cp share/lintian-overrides debian/$@/usr/share/lintian/overrides/apt
-
 	# make rosetta happy and remove pot files in po/ (but leave stuff
 	# in po/domains/* untouched) and cp *.po into each domain dir
 	rm -f build/po/*.pot
 	rm -f po/*.pot
 
+	dh_install -p$@ --sourcedir=$(BLD)
+
+	# Remove the bits that are in apt-utils
+	rm $(addprefix debian/$@/usr/bin/apt-,$(APT_UTILS))
+
+	# https has its own package
+	rm debian/$@/usr/lib/apt/methods/https
+
 	# move the mirror failure script in place
 	#mv debian/$@/usr/bin/apt-report-mirror-failure \
 	#   debian/$@/usr/lib/apt/apt-report-mirror-failure \
 
+	dh_bugfiles -p$@
+	dh_lintian -p$@
 	dh_installexamples -p$@ $(BLD)/docs/examples/*
 	dh_installman -p$@ $(wildcard $(patsubst %,doc/%.[158],$(apt_MANPAGES)) $(patsubst %,doc/*/%.*.[158],$(apt_MANPAGES)))
 	dh_installcron -p$@
 	dh_installdocs -p$@
 	dh_installchangelogs -p$@
+	dh_installlogrotate -p$@
 	dh_strip -p$@
 	dh_compress -p$@
 	dh_fixperms -p$@
-	dh_makeshlibs -p$@ --major=$(LIBAPTPKG_MAJOR) --version-info='$(LIBAPTPKG_PROVIDE)'
+	dh_makeshlibs -p$@
 	dh_installdeb -p$@
-	dh_shlibdeps -p$@ -l$(CURDIR)/debian/apt/usr/lib:$(CURDIR)/debian/$@/usr/lib -- -Ldebian/shlibs.local.apt
-	dh_gencontrol -p$@ -u -Vlibapt-pkg:provides=$(LIBAPTPKG_PROVIDE)
+	dh_shlibdeps -p$@ -l$(CURDIR)/debian/apt/usr/lib:$(CURDIR)/debian/$@/usr/lib
+	dh_gencontrol -p$@ -- -Vlibapt-pkg:provides=$(LIBAPTPKG_PROVIDE)
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 
-libapt-pkg-dev: build debian/shlibs.local
+libapt-pkg-dev: build
 	dh_testdir -p$@
 	dh_testroot -p$@
-	dh_clean -p$@ -k
+	dh_prep -p$@
 	dh_installdirs -p$@
 #
 # libapt-pkg-dev install
 #
-	cp -a $(BLD)/bin/libapt-pkg*.so debian/libapt-pkg-dev/usr/lib/
-	cp -a $(BLD)/bin/libapt-inst*.so debian/libapt-pkg-dev/usr/lib/
-#	ln -s libapt-pkg.so.$(LIBAPTPKG_MAJOR) debian/libapt-pkg-dev/usr/lib/libapt-pkg.so
-	cp $(BLD)/include/apt-pkg/*.h debian/libapt-pkg-dev/usr/include/apt-pkg/
-
+	dh_install -p$@ --sourcedir=$(BLD)
 	dh_installdocs -p$@
-
 	dh_installchangelogs -p$@
 	dh_strip -p$@
 	dh_compress -p$@
 	dh_fixperms -p$@
 	dh_installdeb -p$@
-	dh_gencontrol -p$@ -u -Vlibapt-pkg:provides=$(LIBAPTPKG_PROVIDE) -Vlibapt-inst:provides=$(LIBAPTINST_PROVIDE)
+	dh_gencontrol -p$@ -- -Vlibapt-pkg:provides=$(LIBAPTPKG_PROVIDE) -Vlibapt-inst:provides=$(LIBAPTINST_PROVIDE)
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 
 apt-utils_MANPAGES = apt-sortpkgs apt-ftparchive apt-extracttemplates
-apt-utils: build debian/shlibs.local
+apt-utils: build
 	dh_testdir -p$@
 	dh_testroot -p$@
-	dh_clean -p$@ -k
+	dh_prep -p$@
 	dh_installdirs -p$@
 
-	# install the shared libs
-	find $(BLD)/bin/ -type f -name "libapt-inst*.so.*" -exec cp -a "{}" debian/$@/usr/lib/ \;
-	find $(BLD)/bin/ -type l -name "libapt-inst*.so.*" -exec cp -a "{}" debian/$@/usr/lib/ \;
-
 	cp $(addprefix $(BLD)/bin/apt-,$(APT_UTILS)) debian/$@/usr/bin/
+
+	dh_install -p$@ --sourcedir=$(BLD)
 	dh_installdocs -p$@
 	dh_installexamples -p$@
 
@@ -290,23 +248,20 @@ apt-utils: build debian/shlibs.local
 	dh_strip -p$@
 	dh_compress -p$@
 	dh_fixperms -p$@
-	dh_makeshlibs -p$@ --major=$(LIBAPTINST_MAJOR) --version-info='$(LIBAPTINST_PROVIDE)'
+	dh_makeshlibs -p$@
 	dh_installdeb -p$@
-	dh_shlibdeps -p$@ -l$(CURDIR)/debian/apt/usr/lib:$(CURDIR)/debian/$@/usr/lib -- -Ldebian/shlibs.local.apt-utils
-	dh_gencontrol -p$@ -u -Vlibapt-inst:provides=$(LIBAPTINST_PROVIDE)
+	dh_shlibdeps -p$@ -l$(CURDIR)/debian/apt/usr/lib:$(CURDIR)/debian/$@/usr/lib
+	dh_gencontrol -p$@ -- -Vlibapt-inst:provides=$(LIBAPTINST_PROVIDE)
 	dh_md5sums -p$@
 	dh_builddeb -p$@
 
-apt-transport-https: build debian/shlibs.local libapt-pkg-dev
+apt-transport-https: build libapt-pkg-dev
 	dh_testdir -p$@
 	dh_testroot -p$@
-	dh_clean -p$@ -k
+	dh_prep -p$@
 	dh_installdirs -p$@
 
-	# install the method
-	mkdir --parents debian/$@/usr/lib/apt/methods
-	cp $(BLD)/bin/methods/https debian/$@/usr/lib/apt/methods
-
+	dh_install -p$@ --sourcedir=$(BLD)
 	dh_installdocs -p$@ debian/apt-transport-https.README
 	dh_installexamples -p$@
 
@@ -332,4 +287,4 @@ really-clean: clean
 	rm -f l33ch-stamp
 
 binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary debian/shlibs.local
+.PHONY: build clean binary-indep binary-arch binary

+ 7 - 4
doc/apt-ftparchive.1.xml

@@ -113,10 +113,13 @@
      <varlistentry><term>release</term>
      <listitem><para>
      The <literal>release</literal> command generates a Release file from a
-     directory tree. It recursively searches the given directory for
-     Packages, Packages.gz, Packages.bz2, Sources, Sources.gz,
-     Sources.bz2, Release and md5sum.txt files.  It then writes to
-     stdout a Release file containing an MD5 digest and SHA1 digest
+     directory tree. It recursively searches the given directory for uncompressed
+     <filename>Packages</filename> and <filename>Sources</filename> files and the ones
+     compressed with <command>gzip</command>, <command>bzip2</command> or <command>lzma</command>
+     as well as <filename>Release</filename> and <filename>md5sum.txt</filename> files by default
+     (<literal>APT::FTPArchive::Release::Default-Patterns</literal>). Additional filename patterns
+     can be added by listing them in <literal>APT::FTPArchive::Release::Patterns</literal>.
+     It then writes to stdout a Release file containing a MD5, SHA1 and SHA256 digest
      for each file.</para>
      <para>
      Values for the additional metadata fields in the Release file are

+ 0 - 8
doc/apt-get.8.xml

@@ -434,14 +434,6 @@
      Configuration Item: <literal>APT::Get::Compile</literal>.</para></listitem>
      </varlistentry>
 
-     <varlistentry><term><option>--install-recommends</option></term>
-     <listitem><para>Also install recommended packages.</para></listitem>
-     </varlistentry>
-
-     <varlistentry><term><option>--no-install-recommends</option></term>
-     <listitem><para>Do not install recommended packages.</para></listitem>
-     </varlistentry>
-
      <varlistentry><term><option>--ignore-hold</option></term>
      <listitem><para>Ignore package Holds; This causes <command>apt-get</command> to ignore a hold 
      placed on a package. This may be useful in conjunction with 

+ 3 - 2
doc/apt-secure.8.xml

@@ -148,8 +148,8 @@
    (you should make sure you are using a trusted communication channel
    when retrieving it), add it with <command>apt-key</command> and
    then run <command>apt-get update</command> so that apt can download
-   and verify the <filename>Release.gpg</filename> files from the archives you
-   have configured.
+   and verify the <filename>InRelease</filename> or <filename>Release.gpg</filename>
+   files from the archives you have configured.
    </para>
 </refsect1>
 
@@ -166,6 +166,7 @@
        (provided in apt-utils).</para></listitem>
    
       <listitem><para><emphasis>Sign it</emphasis>. You can do this by running
+      <command>gpg --clearsign -o InRelease Release</command> and
       <command>gpg -abs -o Release.gpg Release</command>.</para></listitem>
 
       <listitem><para><emphasis>Publish the key fingerprint</emphasis>,

+ 5 - 6
doc/apt.conf.5.xml

@@ -442,12 +442,11 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      the bzip2 method (the inbuilt) setting is <literallayout>Dir::Bin::bzip2 "/bin/bzip2";</literallayout>
      Note also that list entries specified on the command line will be added at the end of the list
      specified in the configuration files, but before the default entries. To prefer a type in this case
-     over the ones specified in in the configuration files you can set the option direct - not in list style.
+     over the ones specified in the configuration files you can set the option direct - not in list style.
      This will not override the defined list, it will only prefix the list with this type.</para>
-     <para>While it is possible to add an empty compression type to the order list, but APT in its current
-     version doesn't understand it correctly and will display many warnings about not downloaded files -
-     these warnings are most of the time false negatives. Future versions will maybe include a way to
-     really prefer uncompressed files to support the usage of local mirrors.</para></listitem>
+     <para>The special type <literal>uncompressed</literal> can be used to give uncompressed files a
+     preference, but note that most archives doesn't provide uncompressed files so this is mostly only
+     useable for local mirrors.</para></listitem>
      </varlistentry>
 
      <varlistentry><term>GzipIndexes</term>
@@ -618,7 +617,7 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
 
    <refsect2><title>dpkg trigger usage (and related options)</title>
      <para>APT can call dpkg in a way so it can make aggressive use of triggers over
-     multiply calls of dpkg. Without further options dpkg will use triggers only in between his
+     multiple calls of dpkg. Without further options dpkg will use triggers only in between his
      own run. Activating these options can therefore decrease the time needed to perform the
      install / upgrade. Note that it is intended to activate these options per default in the
      future, but as it changes the way APT calling dpkg drastically it needs a lot more testing.

+ 2 - 1
doc/examples/configure-index

@@ -17,6 +17,7 @@
 */
 
 quiet "0";
+quiet::NoUpdate "true"; // never update progress information - included in -q=1
 
 // Options for APT in general
 APT 
@@ -288,7 +289,7 @@ Acquire
     lzma "lzma";
     gz "gzip";
 
-    Order { "gz"; "lzma"; "bz2"; };
+    Order { "uncompressed"; "gz"; "lzma"; "bz2"; };
   };
 
   Languages

+ 4 - 76
doc/files.sgml

@@ -118,82 +118,10 @@ fastest source listed first. The format of each line is:
 <p>
 The first item, <var>type</var>, indicates the format for the remainder 
 of the line. It is designed to indicate the structure of the distribution
-the line is talking about. Currently the only defined value is <em>deb</em>
-which indicates a standard debian archive with a dists dir.
-
-<sect1>The deb Type
-   <p>
-   The <em>deb</em> type is to be a typical two level debian distributions,
-   dist/<var>distribution</var>/<var>component</var>. Typically distribution
-   is one of stable, unstable or testing while component is one of main, 
-   contrib, non-free or non-us. The format for the deb line is as follows:
-
-   <p>
-   deb <var>uri</var> <var>distribution</var> <var>component</var> 
-   [<var>component</var> ...]
-
-   <p>
-   <var>uri</var> for the <em>deb</em> type must specify the base of the 
-   debian distribution. APT will automatically generate the proper longer 
-   URIs to get the information it needs. <var>distribution</var> can specify
-   an exact path, in this case the components must be omitted and
-   <var>distribution</var> must end in a slash.
-   
-   <p>
-   Since only one distribution can be specified per deb line it may be
-   necessary to list a number of deb lines for the same URI. APT will
-   sort the URI list after it has generated a complete set to allow 
-   connection reuse. It is important to order things in the sourcelist
-   from most preferred to least preferred (fastest to slowest).
-</sect1>
-
-<sect1>URI specification
-<p> 
-URIs in the source list support a large number of access schemes which
-are listed in the sources.list manpage and can be further extended by
-transport binaries placed in /usr/lib/apt/methods. The most important
-builtin schemes are:
-
-<taglist>
-<tag>cdrom<item>
-   The cdrom scheme is special in that If Modified Since queries are never
-   performed and that APT knows how to match a cdrom to the name it
-   was given when first inserted. APT also knows all of the possible 
-   mount points the cdrom drives and that the user should be prompted
-   to insert a CD if it cannot be found. The path is relative to an 
-   arbitrary mount point (of APT's choosing) and must not start with a 
-   slash. The first pathname component is the given name and is purely
-   descriptive and of the users choice. However, if a file in the root of 
-   the cdrom is called '.disk/info' its contents will be used instead of 
-   prompting. The name serves as a tag for the cdrom and should be unique.
-   <example>
-   cdrom:Debian 1.3/debian
-   </example>
-
-<tag>http<item>
-   This scheme specifies a HTTP server for the debian archive. HTTP is preferred
-   over FTP because If Modified Since queries against the Package file are
-   possible as well as deep pipelining and resume capabilities.
-   <example>
-   http://www.debian.org/archive
-   </example>
-
-<tag>ftp<item>
-   This scheme specifies a FTP connection to the server. FTP is limited because
-   there is no support for IMS and is hard to proxy over firewalls.
-   <example>
-   ftp://ftp.debian.org/debian
-   </example>
-
-<tag>file<item>
-   The file scheme allows an arbitrary directory in the file system to be 
-   considered as a debian archive. This is useful for NFS mounts and 
-   local mirrors/archives.
-   <example>
-   file:/var/debian
-   </example>
-</taglist>
-</sect1>
+the line is talking about. Currently the only defined values are <em>deb</em>
+and <em>deb-src</em> which indicate a standard debian (source) archive with a
+dists directory. More about these types and the URI specification can be found
+in the sources.list manpage.
 
 <sect1>Hashing the URI
 <p>

+ 13 - 17
doc/sources.list.5.xml

@@ -63,11 +63,11 @@
  <refsect1><title>The deb and deb-src types</title>
    <para>The <literal>deb</literal> type describes a typical two-level Debian
    archive, <filename>distribution/component</filename>. Typically,
-   <literal>distribution</literal> is generally one of
-   <literal>stable</literal> <literal>unstable</literal> or 
-   <literal>testing</literal> while component is one of <literal>main</literal> 
-   <literal>contrib</literal> <literal>non-free</literal> or
-   <literal>non-us</literal>. The 
+   <literal>distribution</literal> is generally an archivename like
+   <literal>stable</literal> or <literal>testing</literal> or a codename like
+   <literal>&stable-codename;</literal> or <literal>&testing-codename;</literal>
+   while component is one of <literal>main</literal> <literal>contrib</literal> or
+   <literal>non-free</literal>. The
    <literal>deb-src</literal> type describes a debian distribution's source
    code in the same form as the <literal>deb</literal> type.
    A <literal>deb-src</literal> line is required to fetch source indexes.</para>
@@ -218,18 +218,14 @@ deb http://security.debian.org/ &stable-codename;/updates main contrib non-free
    a single FTP session will be used for both resource lines.</para>
    <literallayout>deb ftp://ftp.debian.org/debian unstable contrib</literallayout>
 
-   <para>Uses HTTP to access the archive at nonus.debian.org, under the
-    debian-non-US directory.</para>
-   <literallayout>deb http://nonus.debian.org/debian-non-US stable/non-US main contrib non-free</literallayout>
-
-   <para>Uses HTTP to access the archive at nonus.debian.org, under the
-   debian-non-US directory, and uses only files found under
-   <filename>unstable/binary-i386</filename> on i386 machines, 
-   <filename>unstable/binary-m68k</filename> on m68k, and so
-   forth for other supported architectures. [Note this example only 
-   illustrates how to use the substitution variable; non-us is no longer 
-   structured like this] 
-   <literallayout>deb http://ftp.de.debian.org/debian-non-US unstable/binary-$(ARCH)/</literallayout>
+   <para>Uses HTTP to access the archive at ftp.tlh.debian.org, under the
+   universe directory, and uses only files found under
+   <filename>unstable/binary-i386</filename> on i386 machines,
+   <filename>unstable/binary-amd64</filename> on amd64, and so
+   forth for other supported architectures. [Note this example only
+   illustrates how to use the substitution variable; official debian
+   archives are not structured like this]
+   <literallayout>deb http://ftp.tlh.debian.org/universe unstable/binary-$(ARCH)/</literallayout>
    </para>
  </refsect1>
  

+ 16 - 11
ftparchive/writer.cc

@@ -306,7 +306,7 @@ PackagesWriter::PackagesWriter(string const &DB,string const &Overrides,string c
    Output = stdout;
    SetExts(".deb .udeb");
    DeLinkLimit = 0;
-   
+
    // Process the command line options
    DoMD5 = _config->FindB("APT::FTPArchive::MD5",true);
    DoSHA1 = _config->FindB("APT::FTPArchive::SHA1",true);
@@ -907,16 +907,21 @@ bool ContentsWriter::ReadFromPkgs(string const &PkgFile,string const &PkgCompres
 /* */
 ReleaseWriter::ReleaseWriter(string const &DB)
 {
-   AddPattern("Packages");
-   AddPattern("Packages.gz");
-   AddPattern("Packages.bz2");
-   AddPattern("Packages.lzma");
-   AddPattern("Sources");
-   AddPattern("Sources.gz");
-   AddPattern("Sources.bz2");
-   AddPattern("Sources.lzma");
-   AddPattern("Release");
-   AddPattern("md5sum.txt");
+   if (_config->FindB("APT::FTPArchive::Release::Default-Patterns", true) == true)
+   {
+      AddPattern("Packages");
+      AddPattern("Packages.gz");
+      AddPattern("Packages.bz2");
+      AddPattern("Packages.lzma");
+      AddPattern("Sources");
+      AddPattern("Sources.gz");
+      AddPattern("Sources.bz2");
+      AddPattern("Sources.lzma");
+      AddPattern("Release");
+      AddPattern("Index");
+      AddPattern("md5sum.txt");
+   }
+   AddPatterns(_config->FindVector("APT::FTPArchive::Release::Patterns"));
 
    Output = stdout;
    time_t const now = time(NULL);

+ 2 - 0
ftparchive/writer.h

@@ -69,6 +69,8 @@ class FTWScanner
    bool LoadFileList(string const &BaseDir,string const &File);
    void ClearPatterns() { Patterns.clear(); };
    void AddPattern(string const &Pattern) { Patterns.push_back(Pattern); };
+   void AddPattern(char const *Pattern) { Patterns.push_back(Pattern); };
+   void AddPatterns(std::vector<std::string> const &patterns) { Patterns.insert(Patterns.end(), patterns.begin(), patterns.end()); };
    bool SetExts(string const &Vals);
       
    FTWScanner(string const &Arch = string());

+ 1 - 2
methods/bzip2.cc

@@ -56,9 +56,8 @@ bool Bzip2Method::Fetch(FetchItem *Itm)
    // Open the source and destination files
    FileFd From(Path,FileFd::ReadOnly);
 
-   // FIXME add an error message saying that empty files can't be valid archives
    if(From.FileSize() == 0)
-      return false;
+      return _error->Error(_("Empty files can't be valid archives"));
 
    int GzOut[2];   
    if (pipe(GzOut) < 0)

+ 1 - 2
methods/gzip.cc

@@ -48,9 +48,8 @@ bool GzipMethod::Fetch(FetchItem *Itm)
    // Open the source and destination files
    FileFd From(Path,FileFd::ReadOnlyGzip);
 
-   // FIXME add an error message saying that empty files can't be valid archives
    if(From.FileSize() == 0)
-      return false;
+      return _error->Error(_("Empty files can't be valid archives"));
 
    FileFd To(Itm->DestFile,FileFd::WriteAtomic);   
    To.EraseOnFailure();

+ 2 - 4
methods/https.cc

@@ -143,13 +143,11 @@ bool HttpsMethod::Fetch(FetchItem *Itm)
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, peer_verify);
 
    // ... and hostname against cert CN or subjectAltName
-   int default_verify = 2;
    bool verify = _config->FindB("Acquire::https::Verify-Host",true);
    knob = "Acquire::https::"+remotehost+"::Verify-Host";
    verify = _config->FindB(knob.c_str(),verify);
-   if (!verify)
-      default_verify = 0;
-   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verify);
+   int const default_verify = (verify == true) ? 2 : 0;
+   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, default_verify);
 
    // Also enforce issuer of server certificate using its cert
    string issuercert = _config->Find("Acquire::https::IssuerCert","");

+ 1 - 1
methods/makefile

@@ -67,7 +67,7 @@ include $(PROGRAM_H)
 
 # The rred method
 PROGRAM=rred
-SLIBS = -lapt-pkg $(SOCKETLIBS) $(INTLLIBS)
+SLIBS = -lapt-pkg -lz $(SOCKETLIBS) $(INTLLIBS)
 LIB_MAKES = apt-pkg/makefile
 SOURCE = rred.cc
 include $(PROGRAM_H)

+ 40 - 9
methods/rred.cc

@@ -12,6 +12,7 @@
 #include <utime.h>
 #include <stdio.h>
 #include <errno.h>
+#include <zlib.h>
 #include <apti18n.h>
 										/*}}}*/
 /** \brief RredMethod - ed-style incremential patch method			{{{
@@ -33,11 +34,14 @@ class RredMethod : public pkgAcqMethod {
 	// return values
 	enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE, MMAP_FAILED};
 
-	State applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_file,
+	State applyFile(gzFile &ed_cmds, FILE *in_file, FILE *out_file,
 	             unsigned long &line, char *buffer, Hashes *hash) const;
 	void ignoreLineInFile(FILE *fin, char *buffer) const;
+	void ignoreLineInFile(gzFile &fin, char *buffer) const;
 	void copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lines,
 	                            Hashes *hash, char *buffer) const;
+	void copyLinesFromFileToFile(gzFile &fin, FILE *fout, unsigned int lines,
+	                            Hashes *hash, char *buffer) const;
 
 	State patchFile(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const;
 	State patchMMap(FileFd &Patch, FileFd &From, FileFd &out_file, Hashes *hash) const;
@@ -65,10 +69,10 @@ public:
  *  \param hash the created file for correctness
  *  \return the success State of the ed command executor
  */
-RredMethod::State RredMethod::applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_file,
+RredMethod::State RredMethod::applyFile(gzFile &ed_cmds, FILE *in_file, FILE *out_file,
 			unsigned long &line, char *buffer, Hashes *hash) const {
 	// get the current command and parse it
-	if (fgets(buffer, BUF_SIZE, ed_cmds) == NULL) {
+	if (gzgets(ed_cmds, buffer, BUF_SIZE) == NULL) {
 		if (Debug == true)
 			std::clog << "rred: encounter end of file - we can start patching now." << std::endl;
 		line = 0;
@@ -123,7 +127,7 @@ RredMethod::State RredMethod::applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_
 	unsigned char mode = *idx;
 
 	// save the current position
-	unsigned const long pos = ftell(ed_cmds);
+	unsigned const long pos = gztell(ed_cmds);
 
 	// if this is add or change then go to the next full stop
 	unsigned int data_length = 0;
@@ -157,7 +161,7 @@ RredMethod::State RredMethod::applyFile(FILE *ed_cmds, FILE *in_file, FILE *out_
 
 	// include data from ed script
 	if (mode == MODE_CHANGED || mode == MODE_ADDED) {
-		fseek(ed_cmds, pos, SEEK_SET);
+		gzseek(ed_cmds, pos, SEEK_SET);
 		copyLinesFromFileToFile(ed_cmds, out_file, data_length, hash, buffer);
 	}
 
@@ -183,6 +187,18 @@ void RredMethod::copyLinesFromFileToFile(FILE *fin, FILE *fout, unsigned int lin
 	}
 }
 										/*}}}*/
+void RredMethod::copyLinesFromFileToFile(gzFile &fin, FILE *fout, unsigned int lines,/*{{{*/
+					Hashes *hash, char *buffer) const {
+	while (0 < lines--) {
+		do {
+			gzgets(fin, buffer, BUF_SIZE);
+			size_t const written = fwrite(buffer, 1, strlen(buffer), fout);
+			hash->Add((unsigned char*)buffer, written);
+		} while (strlen(buffer) == (BUF_SIZE - 1) &&
+		       buffer[BUF_SIZE - 2] != '\n');
+	}
+}
+										/*}}}*/
 void RredMethod::ignoreLineInFile(FILE *fin, char *buffer) const {		/*{{{*/
 	fgets(buffer, BUF_SIZE, fin);
 	while (strlen(buffer) == (BUF_SIZE - 1) &&
@@ -192,11 +208,20 @@ void RredMethod::ignoreLineInFile(FILE *fin, char *buffer) const {		/*{{{*/
 	}
 }
 										/*}}}*/
+void RredMethod::ignoreLineInFile(gzFile &fin, char *buffer) const {		/*{{{*/
+	gzgets(fin, buffer, BUF_SIZE);
+	while (strlen(buffer) == (BUF_SIZE - 1) &&
+	       buffer[BUF_SIZE - 2] != '\n') {
+		gzgets(fin, buffer, BUF_SIZE);
+		buffer[0] = ' ';
+	}
+}
+										/*}}}*/
 RredMethod::State RredMethod::patchFile(FileFd &Patch, FileFd &From,		/*{{{*/
 					FileFd &out_file, Hashes *hash) const {
    char buffer[BUF_SIZE];
    FILE* fFrom = fdopen(From.Fd(), "r");
-   FILE* fPatch = fdopen(Patch.Fd(), "r");
+   gzFile fPatch = Patch.gzFd();
    FILE* fTo = fdopen(out_file.Fd(), "w");
 
    /* we do a tail recursion to read the commands in the right order */
@@ -228,6 +253,12 @@ RredMethod::State RredMethod::patchMMap(FileFd &Patch, FileFd &From,		/*{{{*/
 					FileFd &out_file, Hashes *hash) const {
 #ifdef _POSIX_MAPPED_FILES
 	MMap ed_cmds(Patch, MMap::ReadOnly);
+	if (Patch.gzFd() != NULL) {
+		unsigned long mapSize = Patch.Size();
+		DynamicMMap dyn(0, mapSize, 0);
+		gzread(Patch.gzFd(), dyn.Data(), mapSize);
+		ed_cmds = dyn;
+	}
 	MMap in_file(From, MMap::ReadOnly);
 
 	if (ed_cmds.Size() == 0 || in_file.Size() == 0)
@@ -445,7 +476,7 @@ bool RredMethod::Fetch(FetchItem *Itm)						/*{{{*/
    // Open the source and destination files (the d'tor of FileFd will do 
    // the cleanup/closing of the fds)
    FileFd From(Path,FileFd::ReadOnly);
-   FileFd Patch(Path+".ed",FileFd::ReadOnly);
+   FileFd Patch(Path+".ed",FileFd::ReadOnlyGzip);
    FileFd To(Itm->DestFile,FileFd::WriteAtomic);   
    To.EraseOnFailure();
    if (_error->PendingError() == true)
@@ -456,8 +487,8 @@ bool RredMethod::Fetch(FetchItem *Itm)						/*{{{*/
    State const result = patchMMap(Patch, From, To, &Hash);
    if (result == MMAP_FAILED) {
       // retry with patchFile
-      lseek(Patch.Fd(), 0, SEEK_SET);
-      lseek(From.Fd(), 0, SEEK_SET);
+      Patch.Seek(0);
+      From.Seek(0);
       To.Open(Itm->DestFile,FileFd::WriteAtomic);
       if (_error->PendingError() == true)
          return false;

File diff suppressed because it is too large
+ 202 - 192
po/apt-all.pot


+ 0 - 3
pre-build.sh

@@ -1,3 +0,0 @@
-#!/bin/sh
-
-make -f Makefile startup doc

+ 42 - 0
test/integration/Packages-bug-593360-modifiers-in-names

@@ -0,0 +1,42 @@
+Package: g++
+Priority: optional
+Section: devel
+Installed-Size: 40
+Maintainer: Debian GCC Maintainers <debian-gcc@lists.debian.org>
+Architecture: i386
+Source: gcc-defaults (1.96)
+Version: 4:4.4.5-1
+Filename: pool/main/g/gcc-defaults/g++_4.4.5-1_i386.deb
+Size: 1372
+MD5sum: 37e129a4b130e8b96a9b9d5b26a3fffa
+SHA1: d98768d1547389a563e60433268143f42578c3e6
+SHA256: 18d933972392d233127bdd766cfcaaaa2e35f57de47c7af678d599be9613d562
+Description: The GNU C++ compiler
+
+Package: apt
+Priority: important
+Section: admin
+Installed-Size: 5984
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: all
+Version: 0.8.8
+Filename: pool/main/a/apt/apt_0.8.8_i386.deb
+Size: 2140632
+MD5sum: 4283aa3bb751253faf1b2204e0229e4f
+SHA1: 59d432f56901faa86e814a436b8da010ee1c7b8a
+SHA256: 072dcf4359dce9698aeaa54366eb20513f860c2bb6d44a95973c0b2ad413bfab
+Description: Advanced front-end for dpkg
+
+Package: apt+
+Priority: important
+Section: admin
+Installed-Size: 5984
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: all
+Version: 0.8.8
+Filename: pool/main/a/apt/apt_0.8.8_i386.deb
+Size: 2140632
+MD5sum: 4283aa3bb751253faf1b2204e0229e4f
+SHA1: 59d432f56901faa86e814a436b8da010ee1c7b8a
+SHA256: 072dcf4359dce9698aeaa54366eb20513f860c2bb6d44a95973c0b2ad413bfab
+Description: Advanced front-end for dpkg

+ 68 - 0
test/integration/Packages-bug-604222-new-and-autoremove

@@ -0,0 +1,68 @@
+Package: dummy-archive
+Priority: extra
+Section: admin
+Installed-Size: 5984
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: i386
+Version: 0.invalid.0
+Source: dummy-archive
+Depends: libavcodec52, libvtk5-dev | libopenal-dev
+Filename: pool/main/d/dummy/dummy_5.4.2-8_i386.deb
+Size: 2280898
+MD5sum: 569719746f7ec4b96209a6152af20c00
+Description: some dummy package
+
+Package: libvtk5-dev
+Priority: optional
+Section: libdevel
+Installed-Size: 13812
+Maintainer: A. Maitland Bottoms <bottoms@debian.org>
+Architecture: i386
+Source: vtk
+Version: 5.4.2-8
+Depends: libvtk5.4 (= 5.4.2-8)
+Filename: pool/main/v/vtk/libvtk5-dev_5.4.2-8_i386.deb
+Size: 2280898
+MD5sum: 569719746f7ec4b96209a6152af20c00
+Description: VTK header files for building C++ code
+
+Package: libvtk5.4
+Priority: optional
+Section: libs
+Installed-Size: 39372
+Maintainer: A. Maitland Bottoms <bottoms@debian.org>
+Architecture: i386
+Source: vtk
+Version: 5.4.2-8
+Depends: libavcodec52 (>= 4:0.5.1-1)
+Filename: pool/main/v/vtk/libvtk5.4_5.4.2-8_i386.deb
+Size: 13070848
+MD5sum: 3ba7abc3d58ec44e35ae71879406563d
+Description: Visualization Toolkit - A high level 3D visualization library
+
+Package: libopenal-dev
+Priority: optional
+Section: libdevel
+Installed-Size: 140
+Maintainer: Debian Games Team <pkg-games-devel@lists.alioth.debian.org>
+Architecture: i386
+Source: openal-soft
+Version: 1:1.12.854-2
+Filename: pool/main/o/openal-soft/libopenal-dev_1.12.854-2_i386.deb
+Size: 21014
+MD5sum: e0bda4fbf5a3d38ef510a23a1642587f
+Description-de: Software-Implementierung der OpenAL-API (Entwicklungsdateien)
+
+Package: libavcodec52
+Priority: optional
+Section: libs
+Installed-Size: 10772
+Maintainer: Debian multimedia packages maintainers <pkg-multimedia-maintainers@lists.alioth.debian.org>
+Architecture: i386
+Source: ffmpeg
+Version: 4:0.5.2-6
+Conflicts: libvtk5-dev
+Filename: pool/main/f/ffmpeg/libavcodec52_0.5.2-6_i386.deb
+Size: 4001600
+MD5sum: a50aae4c8e8b9dd29612407e61bedc22
+Description-de: Ffmpeg-Codec-Bibliothek

+ 42 - 0
test/integration/Packages-bug-64141-install-dependencies-for-on-hold

@@ -0,0 +1,42 @@
+Package: apt
+Priority: important
+Section: admin
+Installed-Size: 6048
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: i386
+Version: 0.8.10
+Provides: libapt-pkg4.10
+Depends: libc6 (>= 2.10), libdb4.8
+Breaks: oldcrap
+Filename: pool/main/a/apt/apt_0.8.10_i386.deb
+Size: 2160758
+MD5sum: 5aa2234f7b91056d430669cddf6e6e50
+Description: Advanced front-end for dpkg
+
+Package: libc6
+Priority: required
+Section: libs
+Installed-Size: 9356
+Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
+Architecture: i386
+Source: eglibc
+Version: 2.11.2-7
+Provides: glibc-2.11-1
+Filename: pool/main/e/eglibc/libc6_2.11.2-7_i386.deb
+Size: 3880868
+MD5sum: c48fd2854fc62125824267d086600793
+Description: Embedded GNU C Library: Shared libraries
+
+Package: libdb4.8
+Priority: standard
+Section: libs
+Installed-Size: 1488
+Maintainer: Clint Adams <clint@gnu.org>
+Architecture: i386
+Source: db4.8
+Version: 4.8.30-3
+Depends: libc6 (>= 2.3.6-6~)
+Filename: pool/main/d/db4.8/libdb4.8_4.8.30-3_i386.deb
+Size: 681988
+MD5sum: 0d58c15898a95436d2ec480aa22693ff
+Description: Berkeley v4.8 Database Libraries [runtime]

+ 18 - 0
test/integration/Packages-releasefile-verification

@@ -0,0 +1,18 @@
+Package: apt
+Version: 0.7.25.3
+Architecture: i386
+Maintainer: APT Development Team <deity@lists.debian.org>
+Installed-Size: 5244
+Replaces: libapt-pkg-dev (<< 0.3.7), libapt-pkg-doc (<< 0.3.7)
+Provides: libapt-pkg-libc6.9-6-4.8
+Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, bzip2, lzma, python-apt
+Filename: apt.deb
+Size: 0
+MD5sum: d41d8cd98f00b204e9800998ecf8427e
+Description: Advanced front-end for dpkg
+ This is Debian's next generation front-end for the dpkg package manager.
+ It provides the apt-get utility and APT dselect method that provides a
+ simpler, safer way to install and upgrade packages.
+ .
+ APT features complete installation ordering, multiple source capability
+ and several other unique features, see the Users Guide in apt-doc.

+ 21 - 0
test/integration/Packages-releasefile-verification-new

@@ -0,0 +1,21 @@
+Package: apt
+Priority: important
+Section: admin
+Installed-Size: 5672
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: i386
+Version: 0.8.0~pre1
+Replaces: manpages-pl (<< 20060617-3~)
+Provides: libapt-pkg4.10
+Suggests: aptitude | synaptic | wajig, dpkg-dev, apt-doc, bzip2, lzma, python-apt
+Conflicts: python-apt (<< 0.7.93.2~)
+Filename: apt.deb
+Size: 0
+MD5sum: d41d8cd98f00b204e9800998ecf8427e
+Description: Advanced front-end for dpkg
+ This is Debian's next generation front-end for the dpkg package manager.
+ It provides the apt-get utility and APT dselect method that provides a
+ simpler, safer way to install and upgrade packages.
+ .
+ APT features complete installation ordering, multiple source capability
+ and several other unique features, see the Users Guide in apt-doc.

+ 15 - 1
test/integration/create-test-data

@@ -1,6 +1,11 @@
 #!/bin/sh
 set +e # its okay to fail in these script, most of the time the apt* stuff will generate errors
 
+if [ -z "$1" -o -z "$2" ]; then
+	echo "Usage: $0 file codename pkg…"
+	exit 1
+fi
+
 local TESTDIR=$(readlink -f $(dirname $0))
 . $TESTDIR/framework
 BUILDDIRECTORY="${TESTDIR}/../../build/bin"
@@ -16,7 +21,12 @@ TMPGEN=$WORKDIR/Packages
 export LANG=C
 
 LISTOFPKGS=$(aptget install $* -t $CODENAME -so Dir::state::status=$WORKDIR/status -o Dir::Cache::archives=$WORKDIR -o pkgCacheGen::Essential=none -o APT::Immediate-Configure=0 2> /dev/null | awk '/^Inst/ {print $2}' | sed -e "s#\$#/$CODENAME#")
-aptcache show $LISTOFPKGS --no-all-versions 2> /dev/null > $TMPGEN
+if [ -z "$LISTOFPKGS" ]; then
+	echo "List of packages is empty: run apt-get install command again for you now"
+	aptget install $* -t $CODENAME -so Dir::state::status=$WORKDIR/status -o Dir::Cache::archives=$WORKDIR -o pkgCacheGen::Essential=none -o APT::Immediate-Configure=0
+	exit 1
+fi
+aptcache show $LISTOFPKGS --no-all-versions 2> $WORKDIR/error.lst > $TMPGEN
 sed -i $TMPGEN \
 	-e '/^ / d' \
 	-e '/^SHA1: / d' -e '/^SHA256: / d' \
@@ -24,6 +34,10 @@ sed -i $TMPGEN \
 	-e '/^Xul-Appid: / d' \
 	-e '/^Status: / d'
 
+if [ "$CODENAME" = "experimental" ]; then
+	aptcache show $(cat $WORKDIR/error.lst | cut -d"'" -f 4 | sed -e 's#$#/sid#') --no-all-versions 2> /dev/null >> $TMPGEN
+fi
+
 if echo "$GENERATE" | grep '^status-' > /dev/null; then
 	sed -i $TMPGEN -e '/^Package: / a\
 Status: install ok installed' \

BIN
test/integration/deb-bug-330162-encoded-tar-header.deb


+ 152 - 34
test/integration/framework

@@ -39,6 +39,10 @@ fi
 if [ $MSGLEVEL -le 2 ]; then
 	msgmsg() { true; }
 	msgnmsg() { true; }
+	msgtest() { true; }
+	msgpass() { echo -n " ${CPASS}P${CNORMAL}" >&2; }
+	msgskip() { echo -n " ${CWARNING}S${CNORMAL}" >&2; }
+	msgfail() { echo -n " ${CFAIL}FAIL${CNORMAL}" >&2; }
 fi
 if [ $MSGLEVEL -le 3 ]; then
 	msginfo() { true; }
@@ -78,6 +82,20 @@ aptkey() { runapt apt-key $*; }
 dpkg() {
 	$(which dpkg) --root=${TMPWORKINGDIRECTORY}/rootdir --force-not-root --force-bad-path --log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log $*
 }
+aptitude() {
+	if [ -f ./aptconfig.conf ]; then
+		APT_CONFIG=aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY}  $(which aptitude) $*
+	elif [ -f ../aptconfig.conf ]; then
+		APT_CONFIG=../aptconfig.conf LD_LIBRARY_PATH=${BUILDDIRECTORY} $(which aptitude) $*
+	else
+		LD_LIBRARY_PATH=${BUILDDIRECTORY}  $(which aptitude) $*
+	fi
+}
+
+addtrap() {
+	CURRENTTRAP="$CURRENTTRAP $1"
+	trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+}
 
 setupenvironment() {
 	TMPWORKINGDIRECTORY=$(mktemp -d)
@@ -86,8 +104,7 @@ setupenvironment() {
 	BUILDDIRECTORY="${TESTDIR}/../../build/bin"
 	test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
 	local OLDWORKINGDIRECTORY=$(pwd)
-	CURRENTTRAP="cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY"
-	trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+	addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;"
 	cd $TMPWORKINGDIRECTORY
 	mkdir rootdir aptarchive keys
 	cd rootdir
@@ -107,8 +124,10 @@ setupenvironment() {
 	local PACKAGESFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Packages-/' -e 's/^skip-/Packages-/')
 	if [ -f "${TESTDIR}/${PACKAGESFILE}" ]; then
 		cp "${TESTDIR}/${PACKAGESFILE}" aptarchive/Packages
-	else
-		touch aptarchive/Packages
+	fi
+	local SOURCESSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Sources-/' -e 's/^skip-/Sources-/')
+	if [ -f "${TESTDIR}/${SOURCESSFILE}" ]; then
+		cp "${TESTDIR}/${SOURCESSFILE}" aptarchive/Sources
 	fi
 	cp $(find $TESTDIR -name '*.pub' -o -name '*.sec') keys/
 	ln -s ${TMPWORKINGDIRECTORY}/keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
@@ -116,6 +135,7 @@ setupenvironment() {
 	echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf
 	echo "Debug::NoLocking \"true\";" >> aptconfig.conf
 	echo "APT::Get::Show-User-Simulation-Note \"false\";" >> aptconfig.conf
+	echo "Dir::Bin::Methods \"${BUILDDIRECTORY}/methods\";" >> aptconfig.conf
 	echo "Dir::Bin::dpkg \"fakeroot\";" >> aptconfig.conf
 	echo "Dir::Bin::methods \"${BUILDDIRECTORY}/methods\";" >> aptconfig.conf
 	echo "DPKG::options:: \"dpkg\";" >> aptconfig.conf
@@ -123,6 +143,7 @@ setupenvironment() {
 	echo "DPKG::options:: \"--force-not-root\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-bad-path\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
+	echo 'quiet::NoUpdate "true";' >> aptconfig.conf
 	export LC_ALL=C
 	msgdone "info"
 }
@@ -168,8 +189,12 @@ Maintainer: Joe Sixpack <joe@example.org>
 Build-Depends: debhelper (>= 7)
 Standards-Version: 3.9.1
 
-Package: $NAME
-Architecture: $ARCH" > debian/control
+Package: $NAME" > debian/control
+	if [ "$ARCH" = 'all' ]; then
+		echo "Architecture: all" >> debian/control
+	else
+		echo "Architecture: any" >> debian/control
+	fi
 	test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> debian/control
 	if [ -z "$DESCRIPTION" ]; then
 		echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE}
@@ -199,9 +224,57 @@ buildsimplenativepackage() {
 	else
 		DISTSECTION="$(echo "$SECTION" | cut -d'/' -f 1)"
 	fi
-	setupsimplenativepackage "$NAME" "$ARCH" "$VERSION" "$RELEASE" "$DEPENDENCIES" "$DESCRIPTION" "$SECTION"
-	buildpackage "incoming/${NAME}-${VERSION}" "$RELEASE" "$DISTSECTION"
-	rm -rf "incoming/${NAME}-${VERSION}"
+	local BUILDDIR=${TMPWORKINGDIRECTORY}/incoming/${NAME}-${VERSION}
+
+	msgninfo "Build package ${NAME} in ${VERSION} for ${RELEASE} in ${DISTSECTION}… "
+	mkdir -p $BUILDDIR/debian/source
+	echo "* most suckless software product ever" > ${BUILDDIR}/FEATURES
+	echo "#!/bin/sh
+echo '$NAME says \"Hello!\"'" > ${BUILDDIR}/${NAME}
+
+	echo "Copyleft by Joe Sixpack $(date +%Y)" > ${BUILDDIR}/debian/copyright
+	echo "$NAME ($VERSION) $RELEASE; urgency=low
+
+  * Initial release
+
+ -- Joe Sixpack <joe@example.org>  $(date -R)" > ${BUILDDIR}/debian/changelog
+	echo "Source: $NAME
+Section: $SECTION
+Priority: optional
+Maintainer: Joe Sixpack <joe@example.org>
+Standards-Version: 3.9.1
+
+Package: $NAME" > ${BUILDDIR}/debian/control
+	if [ "$ARCH" = 'all' ]; then
+		echo "Architecture: all" >> ${BUILDDIR}/debian/control
+	else
+		echo "Architecture: any" >> ${BUILDDIR}/debian/control
+	fi
+	test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> ${BUILDDIR}/debian/control
+	if [ -z "$DESCRIPTION" ]; then
+		echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE}
+ If you find such a package installed on your system,
+ YOU did something horribly wrong! They are autogenerated
+ und used only by testcases for APT and surf no other propose…" >> ${BUILDDIR}/debian/control
+	else
+		echo "Description: $DESCRIPTION" >> ${BUILDIR}/debian/control
+	fi
+	echo '3.0 (native)' > ${BUILDDIR}/debian/source/format
+	local SRCS="$( (cd ${BUILDDIR}/..; dpkg-source -b ${NAME}-${VERSION} 2>&1) | grep '^dpkg-source: info: building' | grep -o '[a-z0-9._+~-]*$')"
+
+	mkdir -p ${BUILDDIR}/debian/tmp/DEBIAN ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME} ${BUILDDIR}/debian/tmp/usr/bin
+	cp ${BUILDDIR}/debian/copyright ${BUILDDIR}/debian/changelog ${BUILDDIR}/FEATURES ${BUILDDIR}/debian/tmp/usr/share/doc/${NAME}
+	cp ${BUILDDIR}/${NAME} ${BUILDDIR}/debian/tmp/usr/bin
+	(cd ${BUILDDIR}; dpkg-gencontrol -DArchitecture=$ARCH)
+	(cd ${BUILDDIR}/debian/tmp; md5sum $(find usr/ -type f) > DEBIAN/md5sums)
+
+	dpkg-deb --build ${BUILDDIR}/debian/tmp ${BUILDDIR}/.. > /dev/null
+	echo "pool/${NAME}_${VERSION}_${ARCH}.deb" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.pkglist
+	for SRC in $SRCS; do
+		echo "pool/${SRC}" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.srclist
+	done
+	rm -rf "${BUILDDIR}"
+	msgdone "info"
 }
 
 buildpackage() {
@@ -255,6 +328,8 @@ Default {
 	Packages::Compress ". gzip bzip2 lzma";
 	Sources::Compress ". gzip bzip2 lzma";
 	Contents::Compress ". gzip bzip2 lzma";
+	Translation::Compress ". gzip bzip2 lzma";
+	LongDescription "false";
 };
 TreeDefault {
 	Directory "pool/";
@@ -308,6 +383,38 @@ buildaptftparchivedirectorystructure() {
 	done
 }
 
+insertpackage() {
+	local RELEASE="$1"
+	local NAME="$2"
+	local ARCH="$3"
+	local VERSION="$4"
+	local DEPENDENCIES="$5"
+	local ARCHS="$ARCH"
+	if [ "$ARCHS" = "all" ]; then
+		ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+	fi
+	for BUILDARCH in $ARCHS; do
+		local PPATH="aptarchive/dists/${RELEASE}/main/binary-${BUILDARCH}"
+		mkdir -p $PPATH aptarchive/dists/${RELEASE}/main/source
+		touch aptarchive/dists/${RELEASE}/main/source/Sources
+		local FILE="${PPATH}/Packages"
+		echo "Package: $NAME
+Priority: optional
+Section: other
+Installed-Size: 42
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: $ARCH
+Version: $VERSION
+Filename: pool/main/${NAME}/${NAME}_${VERSION}_${ARCH}.deb" >> $FILE
+		test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE
+		echo "Description: an autogenerated dummy ${NAME}=${VERSION}/${RELEASE}
+ If you find such a package installed on your system,
+ YOU did something horribly wrong! They are autogenerated
+ und used only by testcases for APT and surf no other propose…
+" >> $FILE
+	done
+}
+
 buildaptarchivefromincoming() {
 	msginfo "Build APT archive for ${CCMD}$(basename $0)${CINFO} based on incoming packages…"
 	cd aptarchive
@@ -316,36 +423,47 @@ buildaptarchivefromincoming() {
 	[ -e dists ] || buildaptftparchivedirectorystructure
 	msgninfo "\tGenerate Packages, Sources and Contents files… "
 	aptftparchive -qq generate ftparchive.conf
-	msgdone "info"
-	msgninfo "\tGenerate Release files… "
-	for dir in $(find ./dists -mindepth 1 -maxdepth 1 -type d); do
-		aptftparchive -qq release $dir -o APT::FTPArchive::Release::Codename="$(echo "$dir" | cut -d'/' -f 3)" | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference
-	done
 	cd - > /dev/null
 	msgdone "info"
+	generatereleasefiles
 }
 
 buildaptarchivefromfiles() {
 	msginfo "Build APT archive for ${CCMD}$(basename $0)${CINFO} based on prebuild files…"
-	cd aptarchive
-	if [ -f Packages ]; then
-		msgninfo "\tPackages file… "
-		cat Packages | gzip > Packages.gz
-		cat Packages | bzip2 > Packages.bz2
-		cat Packages | lzma > Packages.lzma
+	find aptarchive -name 'Packages' -o -name 'Sources' | while read line; do
+		msgninfo "\t${line} file… "
+		cat ${line} | gzip > ${line}.gz
+		cat ${line} | bzip2 > ${line}.bz2
+		cat ${line} | lzma > ${line}.lzma
 		msgdone "info"
+	done
+	generatereleasefiles
+}
+
+generatereleasefiles() {
+	msgninfo "\tGenerate Release files… "
+	local DATE="${1:-now}"
+	if [ -e aptarchive/dists ]; then
+		for dir in $(find ./aptarchive/dists -mindepth 3 -maxdepth 3 -type d -name 'i18n'); do
+			aptftparchive -qq release $dir -o APT::FTPArchive::Release::Patterns::='Translation-*' > $dir/Index
+		done
+		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
+			local CODENAME="$(echo "$dir" | cut -d'/' -f 4)"
+			aptftparchive -qq release $dir -o APT::FTPArchive::Release::Suite="${CODENAME}" -o APT::FTPArchive::Release::Codename="${CODENAME}" | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference
+			if [ "$CODENAME" = "experimental" -o "$CODENAME" = "experimental2" ]; then
+				sed -i '/^Date: / a\
+NotAutomatic: yes' $dir/Release
+			fi
+		done
+	else
+		aptftparchive -qq release ./aptarchive | sed -e '/0 Release$/ d' > aptarchive/Release # remove the self reference
 	fi
-	if [ -f Sources ]; then
-		msgninfo "\tSources file… "
-		cat Sources | gzip > Sources.gz
-		cat Sources | bzip2 > Sources.bz2
-		cat Sources | lzma > Sources.lzma
-		msgdone "info"
+	if [ "$DATE" != "now" ]; then
+		for release in $(find ./aptarchive -name 'Release'); do
+			touch -d "$1" $release
+		done
 	fi
-	msgninfo "\tRelease file… "
-	aptftparchive -qq release . | sed -e '/0 Release$/ d' > Release # remove the self reference
 	msgdone "info"
-	cd ..
 }
 
 setupdistsaptarchive() {
@@ -405,6 +523,7 @@ signreleasefiles() {
 	done
 	for RELEASE in $(find aptarchive/ -name Release); do
 		gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" -abs -o ${RELEASE}.gpg ${RELEASE}
+		gpg --yes --no-default-keyring $SECKEYS $PUBKEYS --default-key "$SIGNER" --clearsign -o "$(echo "${RELEASE}" | sed 's#/Release$#/InRelease#')" $RELEASE
 	done
 	msgdone "info"
 }
@@ -412,8 +531,7 @@ signreleasefiles() {
 changetowebserver() {
 	if which weborf > /dev/null; then
 		weborf -xb aptarchive/ 2>&1 > /dev/null &
-		CURRENTTRAP="kill $(ps | grep weborf | sed -e 's#^[ ]*##' | cut -d' ' -f 1); $CURRENTTRAP"
-		trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+		addtrap "kill $!;"
 		local APTARCHIVE="file://$(readlink -f ./aptarchive)"
 		for LIST in $(find rootdir/etc/apt/sources.list.d/ -name 'apt-test-*.list'); do
 			sed -i $LIST -e "s#$APTARCHIVE#http://localhost:8080/#"
@@ -447,17 +565,18 @@ testfileequal() {
 
 testequal() {
 	local COMPAREFILE=$(mktemp)
+	addtrap "rm $COMPAREFILE;"
 	echo "$1" > $COMPAREFILE
 	shift
 	msgtest "Test for equality of" "$*"
 	$* 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail
-	rm $COMPAREFILE
 }
 
 testequalor2() {
 	local COMPAREFILE1=$(mktemp)
 	local COMPAREFILE2=$(mktemp)
 	local COMPAREAGAINST=$(mktemp)
+	addtrap "rm $COMPAREFILE1 $COMPAREFILE2 $COMPAREAGAINST;"
 	echo "$1" > $COMPAREFILE1
 	echo "$2" > $COMPAREFILE2
 	shift 2
@@ -468,7 +587,6 @@ testequalor2() {
 		( echo "\n${CINFO}Diff against OR 1${CNORMAL}" "$(checkdiff $COMPAREFILE1 $COMPAREAGAINST)" \
 		       "\n${CINFO}Diff against OR 2${CNORMAL}" "$(checkdiff $COMPAREFILE2 $COMPAREAGAINST)" &&
 		  msgfail )
-	rm $COMPAREFILE1 $COMPAREFILE2 $COMPAREAGAINST
 }
 
 testshowvirtual() {
@@ -485,11 +603,11 @@ N: Can't select versions from package '$1' as it purely virtual"
 	VIRTUAL="${VIRTUAL}
 N: No packages found"
 	local COMPAREFILE=$(mktemp)
+	addtrap "rm $COMPAREFILE;"
 	local ARCH=$(dpkg-architecture -qDEB_HOST_ARCH_CPU)
 	eval `apt-config shell ARCH APT::Architecture`
 	echo "$VIRTUAL" | sed -e "s/:$ARCH//" -e 's/:all//' > $COMPAREFILE
 	aptcache show -q=0 $PACKAGE 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail
-	rm $COMPAREFILE
 }
 
 testnopackage() {

BIN
test/integration/marvinparanoid.pub


BIN
test/integration/marvinparanoid.sec


+ 13 - 1
test/integration/run-tests

@@ -2,7 +2,19 @@
 set -e
 
 DIR=$(readlink -f $(dirname $0))
+if [ "$1" = "-q" ]; then
+	export MSGLEVEL=2
+elif [ "$1" = "-v" ]; then
+	export MSGLEVEL=4
+fi
 for testcase in $(run-parts --list $DIR | grep '/test-'); do
-	echo "\033[1;32mRun Testcase \033[1;35m$(basename ${testcase})\033[0m"
+	if [ "$1" = "-q" ]; then
+		echo -n "\033[1;32mRun Testcase \033[1;35m$(basename ${testcase})\033[0m"
+	else
+		echo "\033[1;32mRun Testcase \033[1;35m$(basename ${testcase})\033[0m"
+	fi
 	${testcase}
+	if [ "$1" = "-q" ]; then
+		echo
+	fi
 done

+ 42 - 0
test/integration/status-bug-601961-install-info

@@ -0,0 +1,42 @@
+Package: dpkg
+Status: install ok installed
+Essential: yes
+Priority: required
+Section: admin
+Installed-Size: 6432
+Maintainer: Dpkg Developers <debian-dpkg@lists.debian.org>
+Architecture: i386
+Version: 1.15.8.5
+Description: Debian package management system
+
+Package: findutils
+Status: install ok installed
+Essential: yes
+Priority: required
+Section: utils
+Installed-Size: 1704
+Maintainer: Andreas Metzler <ametzler@debian.org>
+Architecture: i386
+Version: 4.4.2-1+b1
+Depends: dpkg (>= 1.15.4) | install-info, essentialpkg
+Description: utilities for finding files--find, xargs
+
+Package: install-info
+Status: install ok installed
+Priority: important
+Section: doc
+Installed-Size: 256
+Maintainer: Debian TeX maintainers <debian-tex-maint@lists.debian.org>
+Architecture: i386
+Version: 4.13a.dfsg.1-6
+Description: Manage installed documentation in info format
+
+Package: essentialpkg
+Status: install ok installed
+Priority: important
+Section: other
+Installed-Size: 256
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: i386
+Version: 4.13a.dfsg.1-6
+Description: ultra hypercool important package

+ 10 - 0
test/integration/status-bug-604222-new-and-autoremove

@@ -0,0 +1,10 @@
+Package: libvtk5.4
+Status: install ok installed
+Priority: optional
+Section: libs
+Installed-Size: 39372
+Maintainer: A. Maitland Bottoms <bottoms@debian.org>
+Architecture: i386
+Source: vtk
+Version: 5.4.2-7
+Description: Visualization Toolkit - A high level 3D visualization library

+ 33 - 0
test/integration/status-bug-64141-install-dependencies-for-on-hold

@@ -0,0 +1,33 @@
+Package: apt
+Status: install ok installed
+Priority: important
+Section: admin
+Installed-Size: 6048
+Maintainer: APT Development Team <deity@lists.debian.org>
+Architecture: i386
+Version: 0.8.9
+Provides: libapt-pkg4.10
+Depends: libc6 (>= 2.3.4)
+Description: Advanced front-end for dpkg
+
+Package: libc6
+Status: install ok installed
+Priority: required
+Section: libs
+Installed-Size: 9356
+Maintainer: GNU Libc Maintainers <debian-glibc@lists.debian.org>
+Architecture: i386
+Source: eglibc
+Version: 2.3.5-7
+Provides: glibc-2.11-1
+Description: Embedded GNU C Library: Shared libraries
+
+Package: oldcrap
+Status: install ok installed
+Priority: extra
+Section: oldlibs
+Installed-Size: 1
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: all
+Version: 1-1
+Description: Old crappy nothing package

+ 57 - 0
test/integration/test-bug-254770-segfault-if-cache-not-buildable

@@ -0,0 +1,57 @@
+#!/bin/sh
+set -e
+
+local TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+setupaptarchive
+
+CURRENTTRAP="chmod a+x rootdir/var/lib/dpkg; $CURRENTTRAP"
+trap "$CURRENTTRAP" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+chmod a-x rootdir/var/lib/dpkg
+
+testsegfault() {
+	rm -f rootdir/var/cache/apt/*.bin
+	msgtest "No segfault in" "$*"
+	local TEST="$($* 2>&1 | grep -v 'E:')"
+	if [ -z "$TEST" ]; then
+		msgpass
+	else
+		echo
+		echo $TEST
+		msgfail
+	fi
+}
+
+echo 'quiet 2;' > rootdir/etc/apt/apt.conf.d/00be-quiet
+
+testsegfault aptcache gencaches
+testsegfault aptcache showpkg
+testsegfault aptcache showsrc
+testsegfault aptcache stats
+testsegfault aptcache dump
+testsegfault aptcache dumpavail
+testsegfault aptcache unmet
+testsegfault aptcache search
+testsegfault aptcache show apt
+testsegfault aptcache depends apt
+testsegfault aptcache rdepends apt
+testsegfault aptcache pkgnames apt
+testsegfault aptcache dotty apt
+testsegfault aptcache xvcg apt
+testsegfault aptcache policy apt
+
+testsegfault aptget update
+testsegfault aptget upgrade
+testsegfault aptget dselect-upgrade
+testsegfault aptget dist-upgrade
+testsegfault aptget install apt
+testsegfault aptget remove apt
+testsegfault aptget purge apt
+testsegfault aptget source apt
+testsegfault aptget build-dep apt
+testsegfault aptget check
+testsegfault aptget clean
+testsegfault aptget autoclean
+testsegfault aptget autoremove

+ 11 - 0
test/integration/test-bug-330162-encoded-tar-header

@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+
+local TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+
+msgtest 'Test apt-ftparchive with encoded tar header package'
+cp $TESTDIR/deb-bug-330162-encoded-tar-header.deb aptarchive/
+test -z "$(aptftparchive packages aptarchive/ 2>&1 | grep 'E:')" && msgpass || msgfail

+ 64 - 0
test/integration/test-bug-593360-modifiers-in-names

@@ -0,0 +1,64 @@
+#!/bin/sh
+set -e
+
+local TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  g++
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst g++ (4:4.4.5-1 localhost [i386])
+Conf g++ (4:4.4.5-1 localhost [i386])' aptget install g++ -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  g++
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst g++ (4:4.4.5-1 localhost [i386])
+Conf g++ (4:4.4.5-1 localhost [i386])' aptget install g+++ -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  g++
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst g++ (4:4.4.5-1 localhost [i386])
+Conf g++ (4:4.4.5-1 localhost [i386])' aptget purge g+++ -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst apt (0.8.8 localhost [all])
+Conf apt (0.8.8 localhost [all])' aptget install apt -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  apt+
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst apt+ (0.8.8 localhost [all])
+Conf apt+ (0.8.8 localhost [all])' aptget install apt+ -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  apt+
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst apt+ (0.8.8 localhost [all])
+Conf apt+ (0.8.8 localhost [all])' aptget install apt++ -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  apt+
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst apt+ (0.8.8 localhost [all])
+Conf apt+ (0.8.8 localhost [all])' aptget purge apt++ -s

+ 28 - 34
test/integration/test-bug-595691-empty-and-broken-archive-files

@@ -7,6 +7,7 @@ setupenvironment
 configarchitecture "i386"
 
 buildaptarchive
+touch aptarchive/Packages
 setupflataptarchive
 
 testaptgetupdate() {
@@ -31,7 +32,7 @@ createemptyarchive() {
 	fi
 	touch aptarchive/Packages
 	echo -n "" | $COMPRESSOR > aptarchive/${1}.$COMPRESS
-	aptftparchive release aptarchive/ > aptarchive/Release
+	generatereleasefiles
 	signreleasefiles
 	rm -f aptarchive/Packages
 }
@@ -42,7 +43,7 @@ createemptyfile() {
 		echo -n "" | $COMPRESSOR > aptarchive/Packages.$COMPRESS
 	fi
 	touch aptarchive/Packages aptarchive/${1}.$COMPRESS
-	aptftparchive release aptarchive/ > aptarchive/Release
+	generatereleasefiles
 	signreleasefiles
 	rm -f aptarchive/Packages
 }
@@ -55,6 +56,7 @@ setupcompressor() {
 	lzma) COMPRESS="lzma";;
 	esac
 	echo "Acquire::CompressionTypes::Order { \"${COMPRESS}\"; };
+Dir::Bin::uncompressed \"/does/not/exist\";
 Dir::Bin::gzip \"/does/not/exist\";
 Dir::Bin::bzip2 \"/does/not/exist\";
 Dir::Bin::lzma \"/does/not/exist\";" > rootdir/etc/apt/apt.conf.d/00compressor
@@ -73,31 +75,27 @@ testoverfile() {
 	setupcompressor "$1"
 
 	createemptyfile 'en'
-	testaptgetupdate "Get:1 file:  Release.gpg []
-Get:2 file:  Release []
-Ign file:$(readlink -f aptarchive)/  Translation-en
+	testaptgetupdate "Get:1 file:  InRelease []
+Ign file:  Translation-en
 Reading package lists..." "empty file en.$COMPRESS over file"
 
 	createemptyarchive 'en'
-	testaptgetupdate "Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+	testaptgetupdate "Get:1 file:  InRelease []
 Reading package lists..." "empty archive en.$COMPRESS over file"
 
 	createemptyarchive 'Packages'
 	# FIXME: Why omits the file transport the Packages Get line?
 	#Get:3 file:  Packages []
-	testaptgetupdate "Ign file:$(readlink -f aptarchive)/  Translation-en
-Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+	testaptgetupdate "Get:1 file:  InRelease []
+Ign file:  Translation-en
 Reading package lists..." "empty archive Packages.$COMPRESS over file"
 
 	createemptyfile 'Packages'
-	testaptgetupdate "Ign file:$(readlink -f aptarchive)/  Translation-en
-Get:1 file:  Release.gpg []
-Get:2 file:  Release []
+	testaptgetupdate "Get:1 file:  InRelease []
+Ign file:  Translation-en
 Err file:  Packages
-  Undetermined Error
-W: Failed to fetch file:$(readlink -f aptarchive/Packages.$COMPRESS)  Undetermined Error
+  Empty files can't be valid archives
+W: Failed to fetch ${COMPRESSOR}:$(readlink -f aptarchive/Packages.$COMPRESS)  Empty files can't be valid archives
 
 E: Some index files failed to download, they have been ignored, or old ones used instead." "empty file Packages.$COMPRESS over file"
 }
@@ -106,36 +104,32 @@ testoverhttp() {
 	setupcompressor "$1"
 
 	createemptyfile 'en'
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
-Get:2 http://localhost/  Translation-en
-Get:3 http://localhost  Release []
-Ign http://localhost/  Translation-en
-Get:4 http://localhost  Packages []
+	testaptgetupdate "Get:1 http://localhost  InRelease []
+Get:2 http://localhost  Packages []
+Get:3 http://localhost  Translation-en
+Ign http://localhost  Translation-en
 Reading package lists..." "empty file en.$COMPRESS over http"
 
 	createemptyarchive 'en'
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
-Get:2 http://localhost/  Translation-en []
-Get:3 http://localhost  Release []
-Get:4 http://localhost  Packages []
+	testaptgetupdate "Get:1 http://localhost  InRelease []
+Get:2 http://localhost  Packages []
+Get:3 http://localhost  Translation-en []
 Reading package lists..." "empty archive en.$COMPRESS over http"
 
 	createemptyarchive 'Packages'
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
-Ign http://localhost/  Translation-en
-Get:2 http://localhost  Release []
-Get:3 http://localhost  Packages []
+	testaptgetupdate "Get:1 http://localhost  InRelease []
+Get:2 http://localhost  Packages []
+Ign http://localhost  Translation-en
 Reading package lists..." "empty archive Packages.$COMPRESS over http"
 
 	createemptyfile 'Packages'
 	#FIXME: we should response with a good error message instead
-	testaptgetupdate "Get:1 http://localhost  Release.gpg []
-Ign http://localhost/  Translation-en
-Get:2 http://localhost  Release []
-Get:3 http://localhost  Packages
+	testaptgetupdate "Get:1 http://localhost  InRelease []
+Get:2 http://localhost  Packages
+Ign http://localhost  Translation-en
 Err http://localhost  Packages
-  Undetermined Error
-W: Failed to fetch http://localhost:8080/Packages.$COMPRESS  Undetermined Error
+  Empty files can't be valid archives
+W: Failed to fetch ${COMPRESSOR}:$(readlink -f rootdir/var/lib/apt/lists/partial/localhost:8080_Packages)  Empty files can't be valid archives
 
 E: Some index files failed to download, they have been ignored, or old ones used instead." "empty file Packages.$COMPRESS over http"
 }

+ 1 - 0
test/integration/test-bug-601016-description-translation

@@ -57,6 +57,7 @@ Description-${LOCALE}: Mächtige Oberfläche für dpkg
 testrun() {
 	echo "Acquire::Languages { \"${LOCALE}\"; \"en\"; };" > rootdir/etc/apt/apt.conf.d/00languages
 	export LC_ALL=""
+	rm -rf rootdir/var/lib/apt/lists rootdir/var/cache/apt/
 	setupaptarchive
 	testequal "$LOCALESTANZA" aptcache show apt -o Test=File-${LOCALE}
 	testequal "$NOLONGSTANZA" aptcache show apt -o Acquire::Languages="ww" -o Test=File-${LOCALE}

+ 38 - 0
test/integration/test-bug-601961-install-info

@@ -0,0 +1,38 @@
+#!/bin/sh
+set -e
+
+local TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  findutils
+WARNING: The following essential packages will be removed.
+This should NOT be done unless you know exactly what you are doing!
+  findutils
+0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
+After this operation, 1745 kB disk space will be freed.
+E: Trivial Only specified but this is not a trivial operation.' aptget remove findutils --trivial-only
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  install-info
+0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
+After this operation, 262 kB disk space will be freed.
+E: Trivial Only specified but this is not a trivial operation.' aptget remove install-info --trivial-only
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  essentialpkg findutils
+WARNING: The following essential packages will be removed.
+This should NOT be done unless you know exactly what you are doing!
+  findutils essentialpkg (due to findutils)
+0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded.
+After this operation, 2007 kB disk space will be freed.
+E: Trivial Only specified but this is not a trivial operation.' aptget remove essentialpkg --trivial-only

+ 66 - 0
test/integration/test-bug-604222-new-and-autoremove

@@ -0,0 +1,66 @@
+#!/bin/sh
+set -e
+
+local TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+setupaptarchive
+
+echo 'Package: libvtk5.4
+Auto-Installed: 1
+Architecture: i386' > rootdir/var/lib/apt/extended_states
+
+testequal "Reading package lists...
+Building dependency tree...
+Reading state information...
+The following package was automatically installed and is no longer required:
+  libvtk5.4
+Use 'apt-get autoremove' to remove them.
+The following NEW packages will be installed:
+  libavcodec52
+0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
+Inst libavcodec52 (4:0.5.2-6 localhost [i386])
+Conf libavcodec52 (4:0.5.2-6 localhost [i386])" aptget install libavcodec52 -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Reading state information...
+The following package was automatically installed and is no longer required:
+  libvtk5.4
+Use 'apt-get autoremove' to remove them.
+The following extra packages will be installed:
+  libavcodec52 libopenal-dev libvtk5.4
+The following NEW packages will be installed:
+  dummy-archive libavcodec52 libopenal-dev
+The following packages will be upgraded:
+  libvtk5.4
+1 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
+Need to get 0 B/19.4 MB of archives.
+After this operation, 17.3 MB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install dummy-archive --trivial-only
+
+echo -n > rootdir/var/lib/dpkg/status
+rm rootdir/var/lib/apt/extended_states
+
+CONFLICTING='Reading package lists...
+Building dependency tree...
+  MarkInstall dummy-archive [ i386 ] < none -> 0.invalid.0 > ( admin ) FU=1
+    MarkInstall libavcodec52 [ i386 ] < none -> 4:0.5.2-6 > ( libs ) FU=0
+    MarkInstall libvtk5-dev [ i386 ] < none -> 5.4.2-8 > ( libdevel ) FU=0
+      MarkInstall libvtk5.4 [ i386 ] < none -> 5.4.2-8 > ( libs ) FU=0
+  MarkKeep libvtk5-dev [ i386 ] < none -> 5.4.2-8 > ( libdevel ) FU=0
+  MarkKeep libvtk5-dev [ i386 ] < none -> 5.4.2-8 > ( libdevel ) FU=0
+  MarkDelete libvtk5.4 [ i386 ] < none -> 5.4.2-8 > ( libs ) FU=1
+The following extra packages will be installed:
+  libavcodec52 libopenal-dev
+The following NEW packages will be installed:
+  dummy-archive libavcodec52 libopenal-dev
+0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
+Need to get 0 B/6304 kB of archives.
+After this operation, 17.3 MB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation.'
+
+testequal "$CONFLICTING" aptget install dummy-archive --trivial-only -o Debug::pkgDepCache::Marker=1 -o APT::Get::HideAutoRemove=0
+testequal "$CONFLICTING" aptget install dummy-archive --trivial-only -o Debug::pkgDepCache::Marker=1 -o APT::Get::HideAutoRemove=1
+testequal "$CONFLICTING" aptget install dummy-archive --trivial-only -o Debug::pkgDepCache::Marker=1 -o APT::Get::HideAutoRemove=small

+ 66 - 0
test/integration/test-bug-604401-files-are-directories

@@ -0,0 +1,66 @@
+#!/bin/sh
+set -e
+
+local TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+setupaptarchive
+
+test ! -e rootdir/etc/apt/apt.conf || mv rootdir/etc/apt/apt.conf rootdir/etc/apt/apt.conf.d/000move-away-apt.conf
+
+msgtest "Directory instead of a file as apt.conf ignored"
+mkdir -p rootdir/etc/apt/apt.conf
+aptconfig dump > /dev/null && msgpass || msgfail
+rmdir rootdir/etc/apt/apt.conf
+
+msgtest "Good link instead of a file as apt.conf ignored"
+echo 'Test::APT::Link "good";' > rootdir/etc/apt/good-link.conf
+ln -s rootdir/etc/apt/good-link.conf rootdir/etc/apt/apt.conf
+test -n "$(aptconfig shell TestLink 'Test::APT::Link')" && msgfail || msgpass
+rm rootdir/etc/apt/apt.conf
+
+msgtest "Broken link instead of a file as apt.conf ignored"
+ln -s /tmp/doesnt-exist rootdir/etc/apt/apt.conf
+aptconfig dump > /dev/null && msgpass || msgfail
+rm rootdir/etc/apt/apt.conf
+
+
+test ! -e rootdir/etc/apt/sources.list || mv rootdir/etc/apt/sources.list rootdir/etc/apt/sources.list.d/000move-away-sources.list
+
+msgtest "Directory instead of a file as sources.list ignored"
+mkdir -p rootdir/etc/apt/sources.list
+aptget update --print-uris 2> /dev/null && msgpass || msgfail
+rmdir rootdir/etc/apt/sources.list
+
+msgtest "Good link instead of a file as sources.list ignored"
+echo 'deb file:///tmp/debian sid main' > rootdir/etc/apt/good-link.list
+ln -s rootdir/etc/apt/good-link.list rootdir/etc/apt/sources.list
+test -n "$(aptget update --print-uris)" && msgfail || msgpass
+rm rootdir/etc/apt/sources.list
+
+msgtest "Broken link instead of a file as sources.list ignored"
+ln -s /tmp/doesnt-exist rootdir/etc/apt/sources.list
+test -n "$(aptget update --print-uris)" && msgfail || msgpass
+rm rootdir/etc/apt/sources.list
+
+
+test ! -e rootdir/etc/apt/preferences || mv rootdir/etc/apt/preferences rootdir/etc/apt/preferences.d/000move-away-preferences
+
+msgtest "Directory instead of a file as preferences ignored"
+mkdir -p rootdir/etc/apt/preferences
+aptcache policy > /dev/null 2> /dev/null && msgpass || msgfail
+rmdir rootdir/etc/apt/preferences
+
+msgtest "Good link instead of a file as preferences ignored"
+echo 'Package: apt
+Pin: release a=now
+Pin-Value: 1000' > rootdir/etc/apt/good-link.pref
+ln -s rootdir/etc/apt/good-link.pref rootdir/etc/apt/preferences
+test -n "$(aptcache policy | grep 1000)" && msgfail || msgpass
+rm rootdir/etc/apt/preferences
+
+msgtest "Broken link instead of a file as preferences ignored"
+ln -s /tmp/doesnt-exist rootdir/etc/apt/preferences
+aptcache policy > /dev/null 2> /dev/null && msgpass || msgfail
+rm rootdir/etc/apt/preferences

+ 34 - 0
test/integration/test-bug-64141-install-dependencies-for-on-hold

@@ -0,0 +1,34 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  oldcrap
+The following NEW packages will be installed:
+  libdb4.8
+The following packages will be upgraded:
+  apt libc6
+2 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
+Need to get 0 B/6724 kB of archives.
+After this operation, 1523 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only
+
+echo 'apt hold' | dpkg --set-selections
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following packages have been kept back:
+  apt
+The following packages will be upgraded:
+  libc6
+1 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
+Need to get 0 B/3881 kB of archives.
+After this operation, 0 B of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only -o Test='hold-back-apt'

+ 3 - 3
test/integration/test-compressed-indexes

@@ -16,11 +16,11 @@ local GOODPOLICY="$(aptcache policy testpkg)"
 local GOODSHOWSRC="$(aptcache showsrc testpkg)
 "
 
-test $(echo "$GOODSHOW" | grep -e '^Package: testpkg' -e '^Version: 1.0' -e '^Architecture: i386' | wc -l) -eq 3
+test $(echo "$GOODSHOW" | grep -e '^Package: testpkg' -e '^Version: 1.0' -e '^Architecture: i386' | wc -l) -eq 3 || msgdie 'show is broken'
 testequal "$GOODSHOW" aptcache show testpkg
-test $(echo "$GOODPOLICY" | grep -e '^testpkg:' -e '^  Candidate:' -e '^  Installed: (none)' -e '500 file:/' | wc -l) -eq 4
+test $(echo "$GOODPOLICY" | grep -e '^testpkg:' -e '^  Candidate:' -e '^  Installed: (none)' -e '500 file:/' | wc -l) -eq 4 || msgdie 'policy is broken'
 testequal "$GOODPOLICY" aptcache policy testpkg
-test $(echo "$GOODSHOWSRC" | grep -e '^Package: testpkg' -e '^Format: 3.0 (native)' -e '^Files:' -e '^Checksums-Sha256:' | wc -l) -eq 4
+test $(echo "$GOODSHOWSRC" | grep -e '^Package: testpkg' -e '^Format: 3.0 (native)' -e '^Files:' -e '^Checksums-Sha256:' | wc -l) -eq 4 || msgdie 'showsrc is broken'
 testequal "$GOODSHOWSRC" aptcache showsrc testpkg
 
 

+ 2 - 8
test/integration/test-pdiff-usage

@@ -23,7 +23,6 @@ cat aptarchive/Packages | gzip > aptarchive/Packages.gz
 cat aptarchive/Packages | bzip2 > aptarchive/Packages.bz2
 cat aptarchive/Packages | lzma > aptarchive/Packages.lzma
 rm -rf aptarchive/Packages.diff
-aptftparchive release aptarchive/ > aptarchive/Release
 mkdir -p aptarchive/Packages.diff
 PATCHFILE="aptarchive/Packages.diff/$(date +%Y-%m-%d-%H%M.%S)"
 diff -e ${PKGFILE} ${PKGFILE}-new > ${PATCHFILE} || true
@@ -36,14 +35,9 @@ SHA1-History:
 SHA1-Patches:
  7651fc0ac57cd83d41c63195a9342e2db5650257 19722 2010-08-18-0814.28
  $(sha1sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE) $(basename $PATCHFILE)" > $PATCHINDEX
-sed -i aptarchive/Release \
- -e "/^MD5Sum:/ a\
- \ $(md5sum $PATCHINDEX | cut -d' ' -f 1) $(stat -c%s $PATCHINDEX) Packages.diff/Index" \
- -e "/^SHA1:/ a\
- \ $(sha1sum $PATCHINDEX | cut -d' ' -f 1) $(stat -c%s $PATCHINDEX) Packages.diff/Index" \
- -e "/^SHA256:/ a\
- \ $(sha256sum $PATCHINDEX | cut -d' ' -f 1) $(stat -c%s $PATCHINDEX) Packages.diff/Index"
+generatereleasefiles
 signreleasefiles
+find aptarchive -name 'Packages*' -type f -delete
 aptget update -qq
 
 testnopackage oldstuff

+ 419 - 0
test/integration/test-release-candidate-switching

@@ -0,0 +1,419 @@
+#!/bin/sh
+set -e
+
+local TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture "i386"
+
+insertpackage 'unstable' 'libc6' 'i386' '2.11.2-7+sid'
+insertpackage 'unstable' 'phonon-backend-xine' 'i386' '4:4.6.0really4.4.2-1+sid' 'Provides: phonon-backend'
+insertpackage 'unstable' 'phonon-backend-xine2' 'i386' '4:4.6.0really4.4.2-1+sid'
+insertpackage 'unstable' 'phonon-backend-xine3' 'i386' '4:4.6.0really4.4.2-1+sid'
+insertpackage 'unstable' 'phonon-backend-xine4' 'i386' '4:4.6.0really4.4.2-1+sid'
+insertpackage 'unstable' 'phonon-backend-null' 'i386' '4:4.20.0+sid' 'Provides: phonon-backend'
+insertpackage 'unstable' 'intermediatepkg' 'all' '1.0'
+
+insertpackage 'unstable' 'amarok-common' 'all' '2.3.1-1+sid'
+insertpackage 'unstable' 'amarok-utils' 'i386' '2.3.1-1+sid'
+insertpackage 'unstable' 'libmtp8' 'i386' '0.3.1+sid'
+insertpackage 'unstable' 'amarok' 'i386' '2.3.1-1+sid' 'Depends: amarok-common (= 2.3.1-1+sid), amarok-utils (= 2.3.1-1+sid), phonon-backend-xine | phonon-backend, libmtp8 (>= 0.3.1), libc6'
+
+insertpackage 'experimental' 'amarok-common' 'all' '2.3.2-2+exp'
+insertpackage 'experimental' 'amarok-utils' 'i386' '2.3.2-2+exp'
+insertpackage 'experimental' 'libmtp8' 'i386'  '0.3.3+exp'
+insertpackage 'experimental' 'phonon-backend-xine' 'i386' '5:4.6.0+exp' 'Provides: phonon-backend'
+insertpackage 'experimental' 'phonon-backend-xine2' 'i386' '5:4.6.0+exp' 'Depends: uninstallablepkg
+Provides: phonon-backend-broken'
+insertpackage 'experimental' 'phonon-backend-xine3' 'i386' '5:4.6.0+exp' 'Depends: intermediatepkg (>= 1.5)'
+insertpackage 'experimental' 'phonon-backend-xine4' 'i386' '5:4.6.0+exp' 'Depends: intermediateuninstallablepkg (= 2.0)
+Provides: phonon-backend-broken'
+insertpackage 'experimental' 'intermediatepkg' 'all' '2.0' 'Depends: libc6'
+insertpackage 'experimental' 'intermediateuninstallablepkg' 'all' '2.0' 'Depends: uninstallablepkg'
+insertpackage 'experimental' 'phonon-backend-null' 'i386' '5:4.20.0+exp' 'Provides: phonon-backend'
+insertpackage 'experimental' 'amarok' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), amarok-utils (= 2.3.2-2+exp), phonon-backend-xine | phonon-backend, libmtp8 (>= 0.3.1), libc6'
+
+insertpackage 'experimental2' 'phonon-backend-xine' 'i386' '5:4.00.0+exp' 'Provides: phonon-backend'
+insertpackage 'experimental2' 'amarok-less' 'i386' '2.3.2-2+exp' 'Depends: amarok-common, phonon-backend-xine (>= 5:4.00.0+exp), libmtp8, libc6, amarok-utils'
+insertpackage 'experimental' 'amarok-higher' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-xine (>= 5:4.6.0+exp), libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+
+insertpackage 'experimental' 'amarok-null' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-xine (= 1:1.0-1) | phonon-backend, libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+insertpackage 'experimental' 'amarok-null2' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-null (= 1:1.0-1) | phonon-backend, libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+insertpackage 'experimental' 'amarok-xine' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-xine (= 5:4.6.0+exp) | phonon-backend-null (= 5:4.20.0+exp), libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+insertpackage 'experimental' 'amarok-xine2' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-xine2 (= 5:4.6.0+exp) | phonon-backend-null (= 5:4.20.0+exp), libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+insertpackage 'experimental' 'amarok-xine3' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-xine3 (= 5:4.6.0+exp) | phonon-backend-null (= 5:4.20.0+exp), libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+insertpackage 'experimental' 'amarok-xine4' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-xine4 (= 5:4.6.0+exp) | phonon-backend-null (= 5:4.20.0+exp), libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+insertpackage 'experimental' 'amarok-broken' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp), phonon-backend-broken | phonon-backend-null (= 5:4.20.0+exp), libmtp8 (>= 0.3.1), libc6, amarok-utils (= 2.3.2-2+exp)'
+
+insertpackage 'experimental' 'amarok-recommends' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp)
+Recommends: amarok-utils (= 2.3.2-2+exp), phonon-backend-xine | phonon-backend, libmtp8 (>= 0.3.1), libc6'
+insertpackage 'experimental' 'amarok-recommends2' 'i386' '2.3.2-2+exp' 'Depends: amarok-common (= 2.3.2-2+exp)
+Recommends: amarok-utils (= 2.30.2-2+exp), phonon-backend-xine | phonon-backend, libmtp8 (>= 0.3.1), libc6'
+
+insertpackage 'experimental' 'uninstallablepkg' 'all' '1.0' 'Depends: libmtp8 (>= 10:0.20.1), amarok-utils (= 2.3.2-2+exp)'
+
+setupaptarchive
+
+testequal "Reading package lists...
+Building dependency tree...
+The following extra packages will be installed:
+   amarok-common (2.3.1-1+sid)
+   amarok-utils (2.3.1-1+sid)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+The following NEW packages will be installed:
+   amarok (2.3.1-1+sid)
+   amarok-common (2.3.1-1+sid)
+   amarok-utils (2.3.1-1+sid)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok --trivial-only -V -q=0
+
+testequal "Reading package lists...
+Building dependency tree...
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.3+exp)
+   phonon-backend-xine (4.6.0+exp)
+The following NEW packages will be installed:
+   amarok (2.3.2-2+exp)
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.3+exp)
+   phonon-backend-xine (4.6.0+exp)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok -t experimental --trivial-only -V -q=0
+
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+The following NEW packages will be installed:
+   amarok (2.3.2-2+exp)
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok/experimental --trivial-only -V -q=0
+
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-null'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-null'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-null'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+sid)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-null (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+sid)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-null/experimental --trivial-only -V -q=0
+
+# do not select the same version multiple times
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-null'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+The following NEW packages will be installed:
+   amarok (2.3.2-2+exp)
+   amarok-common (2.3.2-2+exp)
+   amarok-null (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+0 upgraded, 7 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 301 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok/experimental amarok-null/experimental --trivial-only -V -q=0
+
+# … but thighten the version if needed
+# in theory, the second line is wrong, but printing the right version is too much of a hassle
+# (we have to check if later in the Changed list is another change and if so use this version
+#  instead of the current candidate) - and it wouldn't be (really) useful anyway…
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental2 [i386]) for 'amarok-less'
+Selected version '5:4.6.0+exp' (experimental [i386]) for 'phonon-backend-xine' because of 'amarok-less'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-higher'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-higher'
+Selected version '5:4.6.0+exp' (experimental [i386]) for 'phonon-backend-xine' because of 'amarok-higher'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-higher'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0+exp)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-higher (2.3.2-2+exp)
+   amarok-less (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0+exp)
+0 upgraded, 7 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 301 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-less/experimental2 amarok-higher/experimental --trivial-only -V -q=0
+
+# phonon-backend-null can't be used directly, but as it provides it is still fine…
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-null2'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-null2'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-null2'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+sid)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-null2 (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+sid)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-null2/experimental --trivial-only -V -q=0
+
+# if an or-group satisfier is already found, do not set others
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-xine'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-xine'
+Selected version '5:4.6.0+exp' (experimental [i386]) for 'phonon-backend-xine' because of 'amarok-xine'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0+exp)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   amarok-xine (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0+exp)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-xine/experimental --trivial-only -V -q=0
+
+# … but proceed testing if the first doesn't work out
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-xine2'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-xine2'
+Selected version '5:4.20.0+exp' (experimental [i386]) for 'phonon-backend-null' because of 'amarok-xine2'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine2'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+exp)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   amarok-xine2 (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+exp)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-xine2/experimental --trivial-only -V -q=0
+
+# sometimes, the second level need to be corrected, too
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-xine3'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-xine3'
+Selected version '5:4.6.0+exp' (experimental [i386]) for 'phonon-backend-xine3' because of 'amarok-xine3'
+Selected version '2.0' (experimental [all]) for 'intermediatepkg' because of 'phonon-backend-xine3'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine3'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   intermediatepkg (2.0)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine3 (4.6.0+exp)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   amarok-xine3 (2.3.2-2+exp)
+   intermediatepkg (2.0)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine3 (4.6.0+exp)
+0 upgraded, 7 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 301 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-xine3/experimental --trivial-only -V -q=0
+
+# … but proceed testing if the first doesn't work out even in second deep
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-xine4'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-xine4'
+Selected version '5:4.20.0+exp' (experimental [i386]) for 'phonon-backend-null' because of 'amarok-xine4'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine4'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+exp)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   amarok-xine4 (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+exp)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-xine4/experimental --trivial-only -V -q=0
+
+# providers can be broken, too
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-broken'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-broken'
+Selected version '5:4.20.0+exp' (experimental [i386]) for 'phonon-backend-null' because of 'amarok-broken'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-broken'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+exp)
+The following NEW packages will be installed:
+   amarok-broken (2.3.2-2+exp)
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-null (4.20.0+exp)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-broken/experimental --trivial-only -V -q=0
+
+# switch the candidate for recommends too if they should be installed
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-recommends'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-recommends'
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-recommends'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-recommends (2.3.2-2+exp)
+   amarok-utils (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 258 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-recommends/experimental --trivial-only -V -q=0 -o APT::Install-Recommends=1
+
+# … or not if not
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-recommends'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-recommends'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+Recommended packages:
+   amarok-utils (2.3.1-1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+   phonon-backend ()
+   libmtp8 (0.3.1+sid)
+   libc6 (2.11.2-7+sid)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-recommends (2.3.2-2+exp)
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 86.0 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-recommends/experimental --trivial-only -V -q=0 -o APT::Install-Recommends=0
+
+# but broken recommends are not the end of the world
+# FIXME: the version output for recommend packages is a bit strange… but what would be better?
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-recommends2'
+Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-recommends2'
+The following extra packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+Recommended packages:
+   amarok-utils (2.3.1-1+sid)
+The following NEW packages will be installed:
+   amarok-common (2.3.2-2+exp)
+   amarok-recommends2 (2.3.2-2+exp)
+   libc6 (2.11.2-7+sid)
+   libmtp8 (0.3.1+sid)
+   phonon-backend-xine (4.6.0really4.4.2-1+sid)
+0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 215 kB of additional disk space will be used.
+E: Trivial Only specified but this is not a trivial operation." aptget install amarok-recommends2/experimental --trivial-only -V -q=0 -o APT::Install-Recommends=1
+
+# if one depends doesn't work, we don't need to look deeper…
+testequal "Reading package lists...
+Building dependency tree...
+Selected version '1.0' (experimental [all]) for 'uninstallablepkg'
+Some packages could not be installed. This may mean that you have
+requested an impossible situation or if you are using the unstable
+distribution that some required packages have not yet been created
+or been moved out of Incoming.
+The following information may help to resolve the situation:
+
+The following packages have unmet dependencies:
+ uninstallablepkg : Depends: libmtp8 (>= 10:0.20.1) but it is not going to be installed
+                    Depends: amarok-utils (= 2.3.2-2+exp) but 2.3.1-1+sid is to be installed
+E: Broken packages" aptget install uninstallablepkg/experimental --trivial-only -V -q=0

+ 160 - 0
test/integration/test-releasefile-verification

@@ -0,0 +1,160 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+buildaptarchive
+setupflataptarchive
+changetowebserver
+
+prepare() {
+	local DATE="${2:-now}"
+	if [ "$DATE" = 'now' -a "$1" = "${PKGFILE}-new" ]; then
+		DATE='now + 6 days'
+	fi
+	for release in $(find rootdir/var/lib/apt/lists 2> /dev/null); do
+		touch -d 'now - 6 hours' $release
+	done
+	rm -rf rootdir/var/cache/apt/archives
+	rm -f rootdir/var/cache/apt/*.bin
+	cp $1 aptarchive/Packages
+	find aptarchive -name 'Release' -delete
+	cat aptarchive/Packages | gzip > aptarchive/Packages.gz
+	cat aptarchive/Packages | bzip2 > aptarchive/Packages.bz2
+	cat aptarchive/Packages | lzma > aptarchive/Packages.lzma
+	generatereleasefiles "$DATE"
+}
+
+installaptold() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5370 kB of additional disk space will be used.
+Get:1 http://localhost/  apt 0.7.25.3
+Download complete and in download only mode' aptget install apt -dy
+}
+
+installaptnew() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5808 kB of additional disk space will be used.
+Get:1 http://localhost/  apt 0.8.0~pre1
+Download complete and in download only mode' aptget install apt -dy
+}
+
+failaptold() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5370 kB of additional disk space will be used.
+WARNING: The following packages cannot be authenticated!
+  apt
+E: There are problems and -y was used without --force-yes' aptget install apt -dy
+}
+
+failaptnew() {
+	testequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt
+The following NEW packages will be installed:
+  apt
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+After this operation, 5808 kB of additional disk space will be used.
+WARNING: The following packages cannot be authenticated!
+  apt
+E: There are problems and -y was used without --force-yes' aptget install apt -dy
+}
+
+# fake our downloadable file
+touch aptarchive/apt.deb
+
+PKGFILE="${TESTDIR}/$(echo "$(basename $0)" | sed 's#^test-#Packages-#')"
+
+runtest() {
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Cold archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	installaptold
+
+	prepare ${PKGFILE}-new
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Good warm archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	installaptnew
+
+
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Marvin Paranoid'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Cold archive signed by' 'Marvin Paranoid'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgpass || msgfail
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	failaptold
+
+	prepare ${PKGFILE}-new
+	# weborf doesn't support If-Range
+	for release in $(find rootdir/var/lib/apt/lists/partial/ -name '*Release'); do
+		rm $release
+		touch $release
+	done
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Bad warm archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	installaptnew
+
+
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Joe Sixpack'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Cold archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	installaptold
+
+	prepare ${PKGFILE}-new
+	signreleasefiles 'Marvin Paranoid'
+	find aptarchive/ -name "$DELETEFILE" -delete
+	msgtest 'Good warm archive signed by' 'Marvin Paranoid'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgpass || msgfail
+	testequal "$(cat ${PKGFILE})
+" aptcache show apt
+	installaptold
+}
+
+DELETEFILE="InRelease"
+runtest
+DELETEFILE="Release.gpg"
+runtest

+ 40 - 31
test/libapt/getlanguages_test.cc

@@ -26,16 +26,18 @@ int main(int argc,char *argv[])
 	env[1] = "";
 
 	std::vector<std::string> vec = APT::Configuration::getLanguages(false, false, env);
-	equals(vec.size(), 2);
-	equals(vec[0], "de");
-	equals(vec[1], "en");
+	equals(vec.size(), 3);
+	equals(vec[0], "de_DE");
+	equals(vec[1], "de");
+	equals(vec[2], "en");
 
 	// Special: Check if the cache is actually in use
 		env[0] = "en_GB.UTF-8";
 		vec = APT::Configuration::getLanguages(false, true, env);
-		equals(vec.size(), 2);
-		equals(vec[0], "de");
-		equals(vec[1], "en");
+		equals(vec.size(), 3);
+		equals(vec[0], "de_DE");
+		equals(vec[1], "de");
+		equals(vec[2], "en");
 
 	env[0] = "en_GB.UTF-8";
 	vec = APT::Configuration::getLanguages(false, false, env);
@@ -52,19 +54,21 @@ int main(int argc,char *argv[])
 
 	env[0] = "tr_DE@euro";
 	vec = APT::Configuration::getLanguages(false, false, env);
-	equals(vec.size(), 2);
-	equals(vec[0], "tr");
-	equals(vec[1], "en");
+	equals(vec.size(), 3);
+	equals(vec[0], "tr_DE");
+	equals(vec[1], "tr");
+	equals(vec[2], "en");
 
 	env[0] = "de_NO";
-	env[1] = "se_NO:en_GB:nb_NO:nb:no_NO:no:nn_NO:nn:da:sv:en";
+	env[1] = "de_NO:en_GB:nb_NO:nb:no_NO:no:nn_NO:nn:da:sv:en";
 	vec = APT::Configuration::getLanguages(false, false, env);
-	equals(vec.size(), 5);
-	equals(vec[0], "de");
-	equals(vec[1], "en_GB");
-	equals(vec[2], "nb");
-	equals(vec[3], "no");
-	equals(vec[4], "en");
+	equals(vec.size(), 6);
+	equals(vec[0], "de_NO");
+	equals(vec[1], "de");
+	equals(vec[2], "en_GB");
+	equals(vec[3], "nb_NO");
+	equals(vec[4], "nb");
+	equals(vec[5], "en");
 
 	env[0] = "pt_PR.UTF-8";
 	env[1] = "";
@@ -76,9 +80,10 @@ int main(int argc,char *argv[])
 
 	env[0] = "ast_DE.UTF-8";
 	vec = APT::Configuration::getLanguages(false, false, env); // bogus, but syntactical correct
-	equals(vec.size(), 2);
-	equals(vec[0], "ast");
-	equals(vec[1], "en");
+	equals(vec.size(), 3);
+	equals(vec[0], "ast_DE");
+	equals(vec[1], "ast");
+	equals(vec[2], "en");
 
 	env[0] = "C";
 	vec = APT::Configuration::getLanguages(false, false, env);
@@ -113,25 +118,28 @@ int main(int argc,char *argv[])
 	_config->Set("Acquire::Languages::2", "en");
 	env[0] = "de_DE.UTF-8";
 	vec = APT::Configuration::getLanguages(false, false, env);
-	equals(vec.size(), 2);
-	equals(vec[0], "de");
-	equals(vec[1], "en");
+	equals(vec.size(), 3);
+	equals(vec[0], "de_DE");
+	equals(vec[1], "de");
+	equals(vec[2], "en");
 
 	_config->Set("Acquire::Languages::3", "de");
 	env[0] = "de_DE.UTF-8";
 	vec = APT::Configuration::getLanguages(false, false, env);
-	equals(vec.size(), 2);
-	equals(vec[0], "de");
-	equals(vec[1], "en");
+	equals(vec.size(), 3);
+	equals(vec[0], "de_DE");
+	equals(vec[1], "de");
+	equals(vec[2], "en");
 
 	_config->Set("Dir::State::lists", argv[1]);
 	vec = APT::Configuration::getLanguages(true, false, env);
-	equals(vec.size(), 5);
-	equals(vec[0], "de");
-	equals(vec[1], "en");
-	equals(vec[2], "none");
-	equals(vec[3], "pt");
-	equals(vec[4], "tr");
+	equals(vec.size(), 6);
+	equals(vec[0], "de_DE");
+	equals(vec[1], "de");
+	equals(vec[2], "en");
+	equals(vec[3], "none");
+	equals(vec[4], "pt");
+	equals(vec[5], "tr");
 
 	_config->Set("Dir::State::lists", "/non-existing-dir");
 	_config->Set("Acquire::Languages::1", "none");
@@ -140,6 +148,7 @@ int main(int argc,char *argv[])
 	equals(vec.size(), 0);
 	env[0] = "de_DE.UTF-8";
 	vec = APT::Configuration::getLanguages(true, false, env);
+	equals(vec.size(), 2);
 	equals(vec[0], "en");
 	equals(vec[1], "de");
 

+ 5 - 0
test/libapt/run-tests

@@ -39,6 +39,11 @@ do
 			"${tmppath}/invälid.conf" \
 			"${tmppath}/invalíd" \
 			"${tmppath}/01invalíd"
+		mkdir "${tmppath}/invaliddir" \
+			"${tmppath}/directory.conf" \
+			"${tmppath}/directory.list" \
+			"${tmppath}/directory.wron" \
+			"${tmppath}/directory.list.disabled"
 		ln -s "${tmppath}/anormalfile" "${tmppath}/linkedfile.list"
 		ln -s "${tmppath}/non-existing-file" "${tmppath}/brokenlink.list"
 	elif [ $name = "getLanguages${EXT}" ]; then