Просмотр исходного кода

merged from debian-experimental2

Michael Vogt лет назад: 14
Родитель
Сommit
b829fb2602
53 измененных файлов с 1127 добавлено и 613 удалено
  1. 2 4
      apt-inst/dirstream.cc
  2. 45 49
      apt-pkg/acquire-item.cc
  3. 1 1
      apt-pkg/acquire.cc
  4. 12 3
      apt-pkg/algorithms.cc
  5. 4 2
      apt-pkg/aptconfiguration.cc
  6. 35 1
      apt-pkg/cachefile.cc
  7. 1 1
      apt-pkg/cachefilter.cc
  8. 8 0
      apt-pkg/cacheset.h
  9. 86 0
      apt-pkg/contrib/fileutl.cc
  10. 2 4
      apt-pkg/contrib/fileutl.h
  11. 3 3
      apt-pkg/contrib/strutl.cc
  12. 1 1
      apt-pkg/deb/deblistparser.cc
  13. 11 25
      apt-pkg/deb/debmetaindex.cc
  14. 15 6
      apt-pkg/deb/dpkgpm.cc
  15. 8 0
      apt-pkg/depcache.cc
  16. 2 2
      apt-pkg/indexcopy.cc
  17. 4 1
      apt-pkg/indexrecords.cc
  18. 6 8
      apt-pkg/orderlist.cc
  19. 357 266
      apt-pkg/packagemanager.cc
  20. 1 1
      apt-pkg/pkgrecords.cc
  21. 2 2
      apt-pkg/pkgsystem.cc
  22. 1 1
      apt-pkg/sourcelist.cc
  23. 1 1
      apt-pkg/srcrecords.cc
  24. 4 1
      apt-pkg/tagfile.cc
  25. 2 2
      apt-pkg/version.cc
  26. 2 1
      cmdline/acqprogress.cc
  27. 1 1
      cmdline/apt-cache.cc
  28. 3 4
      cmdline/apt-cdrom.cc
  29. 2 2
      cmdline/apt-extracttemplates.cc
  30. 43 6
      cmdline/apt-get.cc
  31. 116 20
      cmdline/apt-mark.cc
  32. 69 5
      debian/changelog
  33. 3 2
      ftparchive/cachedb.h
  34. 1 0
      ftparchive/writer.cc
  35. 4 5
      methods/ftp.cc
  36. 9 11
      methods/http.cc
  37. 5 6
      methods/http.h
  38. 2 4
      methods/https.h
  39. 1 1
      methods/mirror.cc
  40. 3 1
      methods/rsh.cc
  41. 0 42
      test/integration/Packages-bug-64141-install-dependencies-for-on-hold
  42. 50 22
      test/integration/framework
  43. 21 0
      test/integration/skip-avoid-avoiding-breaks-predepends
  44. 0 33
      test/integration/status-bug-64141-install-dependencies-for-on-hold
  45. 3 3
      test/integration/test-bug-549968-install-depends-of-not-installed
  46. 17 6
      test/integration/test-bug-612099-multiarch-conflicts
  47. 17 25
      test/integration/test-bug-618288-multiarch-same-lockstep
  48. 1 8
      test/integration/test-bug-624218-Translation-file-handling
  49. 15 5
      test/integration/test-bug-64141-install-dependencies-for-on-hold
  50. 6 5
      test/integration/test-conflicts-loop
  51. 10 10
      test/integration/test-pin-non-existent-package
  52. 29 0
      test/integration/test-releasefile-verification
  53. 80 0
      test/integration/test-suggest-installed-multiarch-silbing

+ 2 - 4
apt-inst/dirstream.cc

@@ -46,15 +46,13 @@ bool pkgDirStream::DoItem(Item &Itm,int &Fd)
 	 // fchmod deals with umask and fchown sets the ownership
 	 // fchmod deals with umask and fchown sets the ownership
 	 if (fchmod(iFd,Itm.Mode) != 0)
 	 if (fchmod(iFd,Itm.Mode) != 0)
 	 {
 	 {
-	    _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
 	    close(iFd);
 	    close(iFd);
-	    return false;
+	    return _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
 	 }
 	 }
 	 if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
 	 if (fchown(iFd,Itm.UID,Itm.GID) != 0 && errno != EPERM)
 	 {
 	 {
-	    return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
 	    close(iFd);
 	    close(iFd);
-	    return false;
+	    return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
 	 }
 	 }
 	 Fd = iFd;
 	 Fd = iFd;
 	 return true;
 	 return true;

+ 45 - 49
apt-pkg/acquire-item.cc

@@ -189,14 +189,14 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
 									/*}}}*/
 									/*}}}*/
 // AcqSubIndex::AcqSubIndex - Constructor				/*{{{*/
 // AcqSubIndex::AcqSubIndex - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
-/* Get the Index file first and see if there are languages available
- * If so, create a pkgAcqIndexTrans for the found language(s).
- */
+/* Get a sub-index file based on checksums from a 'master' file and
+   possibly query additional files */
 pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
 pkgAcqSubIndex::pkgAcqSubIndex(pkgAcquire *Owner, string const &URI,
 				 string const &URIDesc, string const &ShortDesc,
 				 string const &URIDesc, string const &ShortDesc,
 				 HashString const &ExpectedHash)
 				 HashString const &ExpectedHash)
    : Item(Owner), ExpectedHash(ExpectedHash)
    : Item(Owner), ExpectedHash(ExpectedHash)
 {
 {
+   /* XXX: Beware: Currently this class does nothing (of value) anymore ! */
    Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
    Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
 
 
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
@@ -236,17 +236,7 @@ void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*
    Status = StatDone;
    Status = StatDone;
    Dequeue();
    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);
-   }
+   // No good Index is provided
 }
 }
 									/*}}}*/
 									/*}}}*/
 void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,	/*{{{*/
 void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,	/*{{{*/
@@ -305,38 +295,7 @@ bool pkgAcqSubIndex::ParseIndex(string const &IndexFile)		/*{{{*/
    indexRecords SubIndexParser;
    indexRecords SubIndexParser;
    if (FileExists(IndexFile) == false || SubIndexParser.Load(IndexFile) == false)
    if (FileExists(IndexFile) == false || SubIndexParser.Load(IndexFile) == false)
       return 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);
-   }
+   // so something with the downloaded index
    return true;
    return true;
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1385,6 +1344,18 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
       return;
       return;
    }
    }
 #endif
 #endif
+   bool transInRelease = false;
+   {
+      std::vector<std::string> const keys = MetaIndexParser->MetaKeys();
+      for (std::vector<std::string>::const_iterator k = keys.begin(); k != keys.end(); ++k)
+	 // FIXME: Feels wrong to check for hardcoded string here, but what should we do else…
+	 if (k->find("Translation-") != std::string::npos)
+	 {
+	    transInRelease = true;
+	    break;
+	 }
+   }
+
    for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
    for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
         Target != IndexTargets->end();
         Target != IndexTargets->end();
         ++Target)
         ++Target)
@@ -1422,8 +1393,15 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
 	 if ((*Target)->IsSubIndex() == true)
 	 if ((*Target)->IsSubIndex() == true)
 	    new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
 	    new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
 				(*Target)->ShortDesc, ExpectedIndexHash);
 				(*Target)->ShortDesc, ExpectedIndexHash);
-	 else
-	    new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+	 else if (transInRelease == false || MetaIndexParser->Exists((*Target)->MetaKey) == true)
+	 {
+	    if (_config->FindB("Acquire::PDiffs",true) == true && transInRelease == true &&
+		MetaIndexParser->Exists(string((*Target)->MetaKey).append(".diff/Index")) == true)
+	       new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
+				   (*Target)->ShortDesc, ExpectedIndexHash);
+	    else
+	       new pkgAcqIndexTrans(Owner, *Target, ExpectedIndexHash, MetaIndexParser);
+	 }
 	 continue;
 	 continue;
       }
       }
 
 
@@ -1620,6 +1598,13 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
 {
 {
    if (AuthPass == false)
    if (AuthPass == false)
    {
    {
+      // Remove the 'old' InRelease file if we try Release.gpg now as otherwise
+      // the file will stay around and gives a false-auth impression (CVE-2012-0214)
+      string FinalFile = _config->FindDir("Dir::State::lists");
+      FinalFile.append(URItoFileName(RealURI));
+      if (FileExists(FinalFile))
+	 unlink(FinalFile.c_str());
+
       new pkgAcqMetaSig(Owner,
       new pkgAcqMetaSig(Owner,
 			MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
 			MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
 			MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
 			MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
@@ -1825,7 +1810,18 @@ bool pkgAcqArchive::QueueNext()
 	 else
 	 else
 	    PartialSize = Buf.st_size;
 	    PartialSize = Buf.st_size;
       }
       }
-      
+
+      // Disables download of archives - useful if no real installation follows,
+      // e.g. if we are just interested in proposed installation order
+      if (_config->FindB("Debug::pkgAcqArchive::NoQueue", false) == true)
+      {
+	 Complete = true;
+	 Local = true;
+	 Status = StatDone;
+	 StoreFilename = DestFile = FinalFile;
+	 return true;
+      }
+
       // Create the item
       // Create the item
       Local = false;
       Local = false;
       Desc.URI = Index->ArchiveURI(PkgFile);
       Desc.URI = Index->ArchiveURI(PkgFile);

+ 1 - 1
apt-pkg/acquire.cc

@@ -766,7 +766,7 @@ void pkgAcquire::Queue::Bump()
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // AcquireStatus::pkgAcquireStatus - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgAcquireStatus::pkgAcquireStatus() : Update(true), MorePulses(false)
+pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Update(true), MorePulses(false)
 {
 {
    Start();
    Start();
 }
 }

+ 12 - 3
apt-pkg/algorithms.cc

@@ -471,7 +471,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
+pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : d(NULL), Cache(*pCache)
 {
 {
    // Allocate memory
    // Allocate memory
    unsigned long Size = Cache.Head().PackageCount;
    unsigned long Size = Cache.Head().PackageCount;
@@ -556,7 +556,8 @@ void pkgProblemResolver::MakeScores()
          essantial package above most other packages but low enough
          essantial package above most other packages but low enough
 	 to allow an obsolete essential packages to be removed by
 	 to allow an obsolete essential packages to be removed by
 	 a conflicts on a powerfull normal package (ie libc6) */
 	 a conflicts on a powerfull normal package (ie libc6) */
-      if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+      if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential
+	  || (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
 	 Score += PrioEssentials;
 	 Score += PrioEssentials;
 
 
       // We transform the priority
       // We transform the priority
@@ -631,7 +632,8 @@ void pkgProblemResolver::MakeScores()
    {
    {
       if ((Flags[I->ID] & Protected) != 0)
       if ((Flags[I->ID] & Protected) != 0)
 	 Scores[I->ID] += AddProtected;
 	 Scores[I->ID] += AddProtected;
-      if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
+      if ((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential ||
+          (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
 	 Scores[I->ID] += AddEssential;
 	 Scores[I->ID] += AddEssential;
    }
    }
 }
 }
@@ -1430,6 +1432,13 @@ static int PrioComp(const void *A,const void *B)
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
        (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
        (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
      return -1;
      return -1;
+
+   if ((L.ParentPkg()->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important &&
+       (R.ParentPkg()->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
+     return 1;
+   if ((L.ParentPkg()->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important &&
+       (R.ParentPkg()->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
+     return -1;
    
    
    if (L->Priority != R->Priority)
    if (L->Priority != R->Priority)
       return R->Priority - L->Priority;
       return R->Priority - L->Priority;

+ 4 - 2
apt-pkg/aptconfiguration.cc

@@ -376,7 +376,7 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 			dup2(nullfd, STDIN_FILENO);
 			dup2(nullfd, STDIN_FILENO);
 			dup2(external[1], STDOUT_FILENO);
 			dup2(external[1], STDOUT_FILENO);
 			dup2(nullfd, STDERR_FILENO);
 			dup2(nullfd, STDERR_FILENO);
-			execv(Args[0], (char**) &Args[0]);
+			execvp(Args[0], (char**) &Args[0]);
 			_error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!");
 			_error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!");
 			_exit(100);
 			_exit(100);
 		}
 		}
@@ -392,7 +392,9 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 					if (arch[0] != '\0') {
 					if (arch[0] != '\0') {
 						char const* archend = arch;
 						char const* archend = arch;
 						for (; isspace(*archend) == 0 && *archend != '\0'; ++archend);
 						for (; isspace(*archend) == 0 && *archend != '\0'; ++archend);
-						archs.push_back(string(arch, (archend - arch)));
+						string a(arch, (archend - arch));
+						if (std::find(archs.begin(), archs.end(), a) == archs.end())
+							archs.push_back(a);
 					}
 					}
 					arch = strtok(NULL, " ");
 					arch = strtok(NULL, " ");
 				}
 				}

+ 35 - 1
apt-pkg/cachefile.cc

@@ -30,7 +30,7 @@
 // CacheFile::CacheFile - Constructor					/*{{{*/
 // CacheFile::CacheFile - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgCacheFile::pkgCacheFile() : Map(NULL), Cache(NULL), DCache(NULL),
+pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL),
 				SrcList(NULL), Policy(NULL)
 				SrcList(NULL), Policy(NULL)
 {
 {
 }
 }
@@ -178,6 +178,40 @@ void pkgCacheFile::RemoveCaches()
       unlink(pkgcache.c_str());
       unlink(pkgcache.c_str());
    if (srcpkgcache.empty() == false && RealFileExists(srcpkgcache) == true)
    if (srcpkgcache.empty() == false && RealFileExists(srcpkgcache) == true)
       unlink(srcpkgcache.c_str());
       unlink(srcpkgcache.c_str());
+   if (pkgcache.empty() == false)
+   {
+      std::string cachedir = flNotFile(pkgcache);
+      std::string cachefile = flNotDir(pkgcache);
+      if (cachedir.empty() != true && cachefile.empty() != true && DirectoryExists(cachedir) == true)
+      {
+	 cachefile.append(".");
+	 std::vector<std::string> caches = GetListOfFilesInDir(cachedir, false);
+	 for (std::vector<std::string>::const_iterator file = caches.begin(); file != caches.end(); ++file)
+	 {
+	    std::string nuke = flNotDir(*file);
+	    if (strncmp(cachefile.c_str(), nuke.c_str(), cachefile.length()) != 0)
+	       continue;
+	    unlink(file->c_str());
+	 }
+      }
+   }
+
+   if (srcpkgcache.empty() == true)
+      return;
+
+   std::string cachedir = flNotFile(srcpkgcache);
+   std::string cachefile = flNotDir(srcpkgcache);
+   if (cachedir.empty() == true || cachefile.empty() == true || DirectoryExists(cachedir) == false)
+      return;
+   cachefile.append(".");
+   std::vector<std::string> caches = GetListOfFilesInDir(cachedir, false);
+   for (std::vector<std::string>::const_iterator file = caches.begin(); file != caches.end(); ++file)
+   {
+      std::string nuke = flNotDir(*file);
+      if (strncmp(cachefile.c_str(), nuke.c_str(), cachefile.length()) != 0)
+	 continue;
+      unlink(file->c_str());
+   }
 }
 }
 									/*}}}*/
 									/*}}}*/
 // CacheFile::Close - close the cache files				/*{{{*/
 // CacheFile::Close - close the cache files				/*{{{*/

+ 1 - 1
apt-pkg/cachefilter.cc

@@ -18,7 +18,7 @@
 									/*}}}*/
 									/*}}}*/
 namespace APT {
 namespace APT {
 namespace CacheFilter {
 namespace CacheFilter {
-PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) {/*{{{*/
+PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) : d(NULL) {/*{{{*/
 	pattern = new regex_t;
 	pattern = new regex_t;
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	if (Res == 0)
 	if (Res == 0)

+ 8 - 0
apt-pkg/cacheset.h

@@ -191,6 +191,8 @@ public:									/*{{{*/
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
+		inline iterator& operator=(iterator const &i) { _iter = i._iter; return *this; };
+		inline iterator& operator=(typename Container::iterator const &i) { _iter = i; return *this; };
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 	};
 	};
 									/*}}}*/
 									/*}}}*/
@@ -201,7 +203,9 @@ public:									/*{{{*/
 
 
 	bool empty() const { return _cont.empty(); };
 	bool empty() const { return _cont.empty(); };
 	void clear() { return _cont.clear(); };
 	void clear() { return _cont.clear(); };
+	//FIXME: on ABI break, replace the first with the second without bool
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
+	iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); };
 	size_t erase(const pkgCache::PkgIterator x) { return _cont.erase(x); };
 	size_t erase(const pkgCache::PkgIterator x) { return _cont.erase(x); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	size_t size() const { return _cont.size(); };
 	size_t size() const { return _cont.size(); };
@@ -507,6 +511,8 @@ public:									/*{{{*/
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline iterator operator++(int) { iterator tmp(*this); operator++(); return tmp; }
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator!=(iterator const &i) const { return _iter != i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
 		inline bool operator==(iterator const &i) const { return _iter == i._iter; };
+		inline iterator& operator=(iterator const &i) { _iter = i._iter; return *this; };
+		inline iterator& operator=(typename Container::iterator const &i) { _iter = i; return *this; };
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 		friend std::ostream& operator<<(std::ostream& out, iterator i) { return operator<<(out, *i); }
 	};
 	};
 									/*}}}*/
 									/*}}}*/
@@ -516,7 +522,9 @@ public:									/*{{{*/
 	void insert(const_iterator begin, const_iterator end) { _cont.insert(begin, end); };
 	void insert(const_iterator begin, const_iterator end) { _cont.insert(begin, end); };
 	bool empty() const { return _cont.empty(); };
 	bool empty() const { return _cont.empty(); };
 	void clear() { return _cont.clear(); };
 	void clear() { return _cont.clear(); };
+	//FIXME: on ABI break, replace the first with the second without bool
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
 	void erase(iterator position) { _cont.erase((typename Container::iterator)position); };
+	iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); };
 	size_t erase(const pkgCache::VerIterator x) { return _cont.erase(x); };
 	size_t erase(const pkgCache::VerIterator x) { return _cont.erase(x); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	size_t size() const { return _cont.size(); };
 	size_t size() const { return _cont.size(); };

+ 86 - 0
apt-pkg/contrib/fileutl.cc

@@ -387,6 +387,13 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
       {
       {
 	 if (RealFileExists(File.c_str()) == false)
 	 if (RealFileExists(File.c_str()) == false)
 	 {
 	 {
+	    // do not show ignoration warnings for directories
+	    if (
+#ifdef _DIRENT_HAVE_D_TYPE
+		Ent->d_type == DT_DIR ||
+#endif
+		DirectoryExists(File.c_str()) == true)
+	       continue;
 	    if (SilentIgnore.Match(Ent->d_name) == 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());
 	       _error->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent->d_name, Dir.c_str());
 	    continue;
 	    continue;
@@ -454,6 +461,80 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
    }
    }
    closedir(D);
    closedir(D);
 
 
+   if (SortList == true)
+      std::sort(List.begin(),List.end());
+   return List;
+}
+std::vector<string> GetListOfFilesInDir(string const &Dir, bool SortList)
+{
+   bool const Debug = _config->FindB("Debug::GetListOfFilesInDir", false);
+   if (Debug == true)
+      std::clog << "Accept in " << Dir << " all regular files" << std::endl;
+
+   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;
+   }
+
+   DIR *D = opendir(Dir.c_str());
+   if (D == 0)
+   {
+      _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
+      return List;
+   }
+
+   for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D)) 
+   {
+      // skip "hidden" files
+      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 (Debug == true)
+	       std::clog << "Bad file: " << Ent->d_name << " → it is not a real file" << std::endl;
+	    continue;
+	 }
+      }
+
+      // Skip bad filenames ala run-parts
+      const char *C = Ent->d_name;
+      for (; *C != 0; ++C)
+	 if (isalpha(*C) == 0 && isdigit(*C) == 0
+	     && *C != '_' && *C != '-' && *C != '.')
+	    break;
+
+      // we don't reach the end of the name -> bad character included
+      if (*C != 0)
+      {
+	 if (Debug == true)
+	    std::clog << "Bad file: " << Ent->d_name << " → bad character »" << *C << "« in filename" << std::endl;
+	 continue;
+      }
+
+      // skip filenames which end with a period. These are never valid
+      if (*(C - 1) == '.')
+      {
+	 if (Debug == true)
+	    std::clog << "Bad file: " << Ent->d_name << " → Period as last character" << std::endl;
+	 continue;
+      }
+
+      if (Debug == true)
+	 std::clog << "Accept file: " << Ent->d_name << " in " << Dir << std::endl;
+      List.push_back(File);
+   }
+   closedir(D);
+
    if (SortList == true)
    if (SortList == true)
       std::sort(List.begin(),List.end());
       std::sort(List.begin(),List.end());
    return List;
    return List;
@@ -890,6 +971,11 @@ bool FileFd::OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compre
    std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
    std::vector<APT::Configuration::Compressor> const compressors = APT::Configuration::getCompressors();
    std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
    std::vector<APT::Configuration::Compressor>::const_iterator compressor = compressors.begin();
    std::string name;
    std::string name;
+
+   // compat with the old API
+   if (Mode == ReadOnlyGzip && Compress == None)
+      Compress = Gzip;
+
    switch (Compress)
    switch (Compress)
    {
    {
    case None: name = "."; break;
    case None: name = "."; break;

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

@@ -108,10 +108,7 @@ class FileFd
    bool OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose=false);
    bool OpenDescriptor(int Fd, unsigned int const Mode, CompressMode Compress, bool AutoClose=false);
    bool OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose=false);
    bool OpenDescriptor(int Fd, unsigned int const Mode, APT::Configuration::Compressor const &compressor, bool AutoClose=false);
    inline bool OpenDescriptor(int Fd, unsigned int const Mode, bool AutoClose=false) {
    inline bool OpenDescriptor(int Fd, unsigned int const Mode, bool AutoClose=false) {
-      if (Mode == ReadOnlyGzip)
-         return OpenDescriptor(Fd, Mode, Gzip, AutoClose);
-      else
-         return OpenDescriptor(Fd, Mode, None, AutoClose);
+      return OpenDescriptor(Fd, Mode, None, AutoClose);
    };
    };
    bool Close();
    bool Close();
    bool Sync();
    bool Sync();
@@ -174,6 +171,7 @@ std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::string
 					bool const &SortList, bool const &AllowNoExt=false);
 					bool const &SortList, bool const &AllowNoExt=false);
 std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::vector<std::string> const &Ext,
 std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::vector<std::string> const &Ext,
 					bool const &SortList);
 					bool const &SortList);
+std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, bool SortList);
 std::string SafeGetCWD();
 std::string SafeGetCWD();
 void SetCloseExec(int Fd,bool Close);
 void SetCloseExec(int Fd,bool Close);
 void SetNonBlock(int Fd,bool Block);
 void SetNonBlock(int Fd,bool Block);

+ 3 - 3
apt-pkg/contrib/strutl.cc

@@ -910,17 +910,17 @@ bool StrToTime(const string &Val,time_t &Result)
 
 
    // Handle RFC 1123 time
    // Handle RFC 1123 time
    Month[0] = 0;
    Month[0] = 0;
-   if (sscanf(I," %d %3s %d %d:%d:%d GMT",&Tm.tm_mday,Month,&Tm.tm_year,
+   if (sscanf(I," %2d %3s %4d %2d:%2d:%2d GMT",&Tm.tm_mday,Month,&Tm.tm_year,
 	      &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) != 6)
 	      &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) != 6)
    {
    {
       // Handle RFC 1036 time
       // Handle RFC 1036 time
-      if (sscanf(I," %d-%3s-%d %d:%d:%d GMT",&Tm.tm_mday,Month,
+      if (sscanf(I," %2d-%3s-%3d %2d:%2d:%2d GMT",&Tm.tm_mday,Month,
 		 &Tm.tm_year,&Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) == 6)
 		 &Tm.tm_year,&Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec) == 6)
 	 Tm.tm_year += 1900;
 	 Tm.tm_year += 1900;
       else
       else
       {
       {
 	 // asctime format
 	 // asctime format
-	 if (sscanf(I," %3s %d %d:%d:%d %d",Month,&Tm.tm_mday,
+	 if (sscanf(I," %3s %2d %2d:%2d:%2d %4d",Month,&Tm.tm_mday,
 		    &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec,&Tm.tm_year) != 6)
 		    &Tm.tm_hour,&Tm.tm_min,&Tm.tm_sec,&Tm.tm_year) != 6)
 	 {
 	 {
 	    // 'ftp' time
 	    // 'ftp' time

+ 1 - 1
apt-pkg/deb/deblistparser.cc

@@ -249,7 +249,7 @@ bool debListParser::UsePackage(pkgCache::PkgIterator &Pkg,
       return false;
       return false;
 
 
    if (strcmp(Pkg.Name(),"apt") == 0)
    if (strcmp(Pkg.Name(),"apt") == 0)
-      Pkg->Flags |= pkgCache::Flag::Important;
+      Pkg->Flags |= pkgCache::Flag::Essential | pkgCache::Flag::Important;
    
    
    if (ParseStatus(Pkg,Ver) == false)
    if (ParseStatus(Pkg,Ver) == false)
       return false;
       return false;

+ 11 - 25
apt-pkg/deb/debmetaindex.cc

@@ -128,7 +128,7 @@ string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string
 {
 {
    string Res ="";
    string Res ="";
    if (Dist[Dist.size() - 1] != '/')
    if (Dist[Dist.size() - 1] != '/')
-      Res += Section + "/i18n/";
+      Res += Section + "/i18n/Translation-";
    return Res + Type;
    return Res + Type;
 }
 }
 
 
@@ -210,31 +210,17 @@ vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const {
 	if (lang.empty() == true)
 	if (lang.empty() == true)
 		return IndexTargets;
 		return IndexTargets;
 
 
-	// 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] == '/') {
-		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) {
-				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 OptionalSubIndexTarget();
-			Target->ShortDesc = "TranslationIndex";
-			Target->MetaKey = TranslationIndexURISuffix("Index", *s);
-			Target->URI = TranslationIndexURI("Index", *s);
+	// get the Translation-* files, later we will skip download of non-existent if we have an index
+	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) {
+			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);
 			Target->Description = Info (Target->ShortDesc.c_str(), *s);
-			IndexTargets->push_back (Target);
+			IndexTargets->push_back(Target);
 		}
 		}
 	}
 	}
 
 

+ 15 - 6
apt-pkg/deb/dpkgpm.cc

@@ -51,8 +51,10 @@ using namespace std;
 class pkgDPkgPMPrivate 
 class pkgDPkgPMPrivate 
 {
 {
 public:
 public:
-   pkgDPkgPMPrivate() : dpkgbuf_pos(0), term_out(NULL), history_out(NULL)
+   pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
+			term_out(NULL), history_out(NULL)
    {
    {
+      dpkgbuf[0] = '\0';
    }
    }
    bool stdin_is_dev_null;
    bool stdin_is_dev_null;
    // the buffer we use for the dpkg status-fd reading
    // the buffer we use for the dpkg status-fd reading
@@ -860,6 +862,8 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds,
 */
 */
 bool pkgDPkgPM::Go(int OutStatusFd)
 bool pkgDPkgPM::Go(int OutStatusFd)
 {
 {
+   pkgPackageManager::SigINTStop = false;
+
    // Generate the base argument list for dpkg
    // Generate the base argument list for dpkg
    std::vector<const char *> Args;
    std::vector<const char *> Args;
    unsigned long StartSize = 0;
    unsigned long StartSize = 0;
@@ -905,7 +909,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       dup2(nullfd, STDIN_FILENO);
       dup2(nullfd, STDIN_FILENO);
       dup2(nullfd, STDOUT_FILENO);
       dup2(nullfd, STDOUT_FILENO);
       dup2(nullfd, STDERR_FILENO);
       dup2(nullfd, STDERR_FILENO);
-      execv(Args[0], (char**) &Args[0]);
+      execvp(Args[0], (char**) &Args[0]);
       _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
       _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
       _exit(2);
       _exit(2);
    }
    }
@@ -1429,9 +1433,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 }
 }
 
 
 void SigINT(int sig) {
 void SigINT(int sig) {
-   if (_config->FindB("APT::Immediate-Configure-All",false)) 
-      pkgPackageManager::SigINTStop = true;
-} 
+   pkgPackageManager::SigINTStop = true;
+}
 									/*}}}*/
 									/*}}}*/
 // pkgDpkgPM::Reset - Dump the contents of the command list		/*{{{*/
 // pkgDpkgPM::Reset - Dump the contents of the command list		/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
@@ -1446,6 +1449,12 @@ void pkgDPkgPM::Reset()
 /* */
 /* */
 void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) 
 void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) 
 {
 {
+   // If apport doesn't exist or isn't installed do nothing
+   // This e.g. prevents messages in 'universes' without apport
+   pkgCache::PkgIterator apportPkg = Cache.FindPkg("apport");
+   if (apportPkg.end() == true || apportPkg->CurrentVer == 0)
+      return;
+
    string pkgname, reportfile, srcpkgname, pkgver, arch;
    string pkgname, reportfile, srcpkgname, pkgver, arch;
    string::size_type pos;
    string::size_type pos;
    FILE *report;
    FILE *report;
@@ -1533,7 +1542,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
 	 if(strstr(strbuf,"Package:") == strbuf)
 	 if(strstr(strbuf,"Package:") == strbuf)
 	 {
 	 {
 	    char pkgname[255], version[255];
 	    char pkgname[255], version[255];
-	    if(sscanf(strbuf, "Package: %s %s", pkgname, version) == 2)
+	    if(sscanf(strbuf, "Package: %254s %254s", pkgname, version) == 2)
 	       if(strcmp(pkgver.c_str(), version) == 0)
 	       if(strcmp(pkgver.c_str(), version) == 0)
 	       {
 	       {
 		  fclose(report);
 		  fclose(report);

+ 8 - 0
apt-pkg/depcache.cc

@@ -963,6 +963,13 @@ struct CompareProviders {
 	 else if ((B->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
 	 else if ((B->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
 	    return true;
 	    return true;
       }
       }
+      if ((A->Flags & pkgCache::Flag::Important) != (B->Flags & pkgCache::Flag::Important))
+      {
+	 if ((A->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
+	    return false;
+	 else if ((B->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important)
+	    return true;
+      }
       // higher priority seems like a good idea
       // higher priority seems like a good idea
       if (AV->Priority != BV->Priority)
       if (AV->Priority != BV->Priority)
 	 return AV->Priority < BV->Priority;
 	 return AV->Priority < BV->Priority;
@@ -1641,6 +1648,7 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc)
    {
    {
       if(!(PkgState[p->ID].Flags & Flag::Auto) ||
       if(!(PkgState[p->ID].Flags & Flag::Auto) ||
 	  (p->Flags & Flag::Essential) ||
 	  (p->Flags & Flag::Essential) ||
+	  (p->Flags & Flag::Important) ||
 	  userFunc.InRootSet(p) ||
 	  userFunc.InRootSet(p) ||
 	  // be nice even then a required package violates the policy (#583517)
 	  // be nice even then a required package violates the policy (#583517)
 	  // and do the full mark process also for required packages
 	  // and do the full mark process also for required packages

+ 2 - 2
apt-pkg/indexcopy.cc

@@ -85,7 +85,7 @@ bool IndexCopy::CopyPackages(string CDROM,string Name,vector<string> &List,
       string OrigPath = string(*I,CDROM.length());
       string OrigPath = string(*I,CDROM.length());
       
       
       // Open the package file
       // Open the package file
-      FileFd Pkg(*I + GetFileName(), FileFd::ReadOnly, FileFd::Extension);
+      FileFd Pkg(*I + GetFileName(), FileFd::ReadOnly, FileFd::Auto);
       off_t const FileSize = Pkg.Size();
       off_t const FileSize = Pkg.Size();
 
 
       pkgTagFile Parser(&Pkg);
       pkgTagFile Parser(&Pkg);
@@ -797,7 +797,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
       string OrigPath = string(*I,CDROM.length());
       string OrigPath = string(*I,CDROM.length());
 
 
       // Open the package file
       // Open the package file
-      FileFd Pkg(*I, FileFd::ReadOnly, FileFd::Extension);
+      FileFd Pkg(*I, FileFd::ReadOnly, FileFd::Auto);
       off_t const FileSize = Pkg.Size();
       off_t const FileSize = Pkg.Size();
 
 
       pkgTagFile Parser(&Pkg);
       pkgTagFile Parser(&Pkg);

+ 4 - 1
apt-pkg/indexrecords.cc

@@ -44,7 +44,10 @@ time_t indexRecords::GetValidUntil() const
 
 
 const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 const indexRecords::checkSum *indexRecords::Lookup(const string MetaKey)
 {
 {
-   return Entries[MetaKey];
+   std::map<std::string, indexRecords::checkSum* >::const_iterator sum = Entries.find(MetaKey);
+   if (sum == Entries.end())
+      return NULL;
+   return sum->second;
 }
 }
 
 
 bool indexRecords::Exists(string const &MetaKey) const
 bool indexRecords::Exists(string const &MetaKey) const

+ 6 - 8
apt-pkg/orderlist.cc

@@ -82,16 +82,14 @@ pkgOrderList *pkgOrderList::Me = 0;
 // OrderList::pkgOrderList - Constructor				/*{{{*/
 // OrderList::pkgOrderList - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgOrderList::pkgOrderList(pkgDepCache *pCache) : Cache(*pCache)
+pkgOrderList::pkgOrderList(pkgDepCache *pCache) : Cache(*pCache),
+						  Primary(NULL), Secondary(NULL),
+						  RevDepends(NULL), Remove(NULL),
+						  AfterEnd(NULL), FileList(NULL),
+						  LoopCount(-1), Depth(0)
 {
 {
-   FileList = 0;
-   Primary = 0;
-   Secondary = 0;
-   RevDepends = 0;
-   Remove = 0;
-   LoopCount = -1;
    Debug = _config->FindB("Debug::pkgOrderList",false);
    Debug = _config->FindB("Debug::pkgOrderList",false);
-   
+
    /* Construct the arrays, egcs 1.0.1 bug requires the package count
    /* Construct the arrays, egcs 1.0.1 bug requires the package count
       hack */
       hack */
    unsigned long Size = Cache.Head().PackageCount;
    unsigned long Size = Cache.Head().PackageCount;

+ 357 - 266
apt-pkg/packagemanager.cc

@@ -36,11 +36,13 @@ bool pkgPackageManager::SigINTStop = false;
 // PM::PackageManager - Constructor					/*{{{*/
 // PM::PackageManager - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
-pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache)
+pkgPackageManager::pkgPackageManager(pkgDepCache *pCache) : Cache(*pCache),
+							    List(NULL), Res(Incomplete)
 {
 {
    FileNames = new string[Cache.Head().PackageCount];
    FileNames = new string[Cache.Head().PackageCount];
-   List = 0;
    Debug = _config->FindB("Debug::pkgPackageManager",false);
    Debug = _config->FindB("Debug::pkgPackageManager",false);
+   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
+   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
 }
 }
 									/*}}}*/
 									/*}}}*/
 // PM::PackageManager - Destructor					/*{{{*/
 // PM::PackageManager - Destructor					/*{{{*/
@@ -150,7 +152,7 @@ void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer, unsigned
 	 if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate))
 	 if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate))
 	 {
 	 {
 	    if(Debug)
 	    if(Debug)
-	       clog << OutputInDepth(Depth) << "ImmediateAdd(): Adding Immediate flag to " << D.TargetPkg() << " cause of " << D.DepType() << " " << I.Name() << endl;
+	       clog << OutputInDepth(Depth) << "ImmediateAdd(): Adding Immediate flag to " << D.TargetPkg() << " cause of " << D.DepType() << " " << I.FullName() << endl;
 	    List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
 	    List->Flag(D.TargetPkg(),pkgOrderList::Immediate);
 	    ImmediateAdd(D.TargetPkg(), UseInstallVer, Depth + 1);
 	    ImmediateAdd(D.TargetPkg(), UseInstallVer, Depth + 1);
 	 }
 	 }
@@ -169,10 +171,7 @@ bool pkgPackageManager::CreateOrderList()
    
    
    delete List;
    delete List;
    List = new pkgOrderList(&Cache);
    List = new pkgOrderList(&Cache);
-   
-   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
-   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
-   
+
    if (Debug && ImmConfigureAll) 
    if (Debug && ImmConfigureAll) 
       clog << "CreateOrderList(): Adding Immediate flag for all packages because of APT::Immediate-Configure-All" << endl;
       clog << "CreateOrderList(): Adding Immediate flag for all packages because of APT::Immediate-Configure-All" << endl;
    
    
@@ -184,12 +183,11 @@ bool pkgPackageManager::CreateOrderList()
 	 continue;
 	 continue;
       
       
       // Mark the package and its dependends for immediate configuration
       // Mark the package and its dependends for immediate configuration
-      if ((((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential ||
-	   (I->Flags & pkgCache::Flag::Important) == pkgCache::Flag::Important) &&
+      if ((((I->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential) &&
 	  NoImmConfigure == false) || ImmConfigureAll)
 	  NoImmConfigure == false) || ImmConfigureAll)
       {
       {
 	 if(Debug && !ImmConfigureAll)
 	 if(Debug && !ImmConfigureAll)
-	    clog << "CreateOrderList(): Adding Immediate flag for " << I.Name() << endl;
+	    clog << "CreateOrderList(): Adding Immediate flag for " << I.FullName() << endl;
 	 List->Flag(I,pkgOrderList::Immediate);
 	 List->Flag(I,pkgOrderList::Immediate);
 	 
 	 
 	 if (!ImmConfigureAll) {
 	 if (!ImmConfigureAll) {
@@ -258,7 +256,7 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D,
 
 
       if (EarlyRemove(D.ParentPkg()) == false)
       if (EarlyRemove(D.ParentPkg()) == false)
 	 return _error->Error("Reverse conflicts early remove for package '%s' failed",
 	 return _error->Error("Reverse conflicts early remove for package '%s' failed",
-			      Pkg.Name());
+			      Pkg.FullName().c_str());
    }
    }
    return true;
    return true;
 }
 }
@@ -296,9 +294,9 @@ bool pkgPackageManager::ConfigureAll()
       if (ConfigurePkgs == true && SmartConfigure(Pkg, 0) == false) {
       if (ConfigurePkgs == true && SmartConfigure(Pkg, 0) == false) {
          if (ImmConfigureAll)
          if (ImmConfigureAll)
             _error->Error(_("Could not perform immediate configuration on '%s'. "
             _error->Error(_("Could not perform immediate configuration on '%s'. "
-			"Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.Name(),1);
+			"Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.FullName().c_str(),1);
          else
          else
-            _error->Error("Internal error, packages left unconfigured. %s",Pkg.Name());
+            _error->Error("Internal error, packages left unconfigured. %s",Pkg.FullName().c_str());
 	 return false;
 	 return false;
       }
       }
       
       
@@ -323,11 +321,11 @@ bool pkgPackageManager::ConfigureAll()
 bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 {
 {
    // If this is true, only check and correct and dependencies without the Loop flag
    // If this is true, only check and correct and dependencies without the Loop flag
-   bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop);
+   bool const PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop);
 
 
    if (Debug) {
    if (Debug) {
       VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer);
       VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer);
-      clog << OutputInDepth(Depth) << "SmartConfigure " << Pkg.Name() << " (" << InstallVer.VerStr() << ")";
+      clog << OutputInDepth(Depth) << "SmartConfigure " << Pkg.FullName() << " (" << InstallVer.VerStr() << ")";
       if (PkgLoop)
       if (PkgLoop)
         clog << " (Only Correct Dependencies)";
         clog << " (Only Correct Dependencies)";
       clog << endl;
       clog << endl;
@@ -338,103 +336,135 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
    /* Because of the ordered list, most dependencies should be unpacked, 
    /* Because of the ordered list, most dependencies should be unpacked, 
       however if there is a loop (A depends on B, B depends on A) this will not 
       however if there is a loop (A depends on B, B depends on A) this will not 
       be the case, so check for dependencies before configuring. */
       be the case, so check for dependencies before configuring. */
-   bool Bad = false;
-   for (DepIterator D = instVer.DependsList();
-	D.end() == false; )
-   {
-      // Compute a single dependency element (glob or)
-      pkgCache::DepIterator Start;
-      pkgCache::DepIterator End;
-      D.GlobOr(Start,End);
-      
-      if (End->Type == pkgCache::Dep::Depends) 
-          Bad = true;
-
-      // Check for dependanices that have not been unpacked, probably due to loops.
-      while (End->Type == pkgCache::Dep::Depends) {
-         PkgIterator DepPkg;
-         VerIterator InstallVer;
-         SPtrArray<Version *> VList = Start.AllTargets();
-         
-         // Check through each version of each package that could satisfy this dependancy
-	 for (Version **I = VList; *I != 0; I++) {
-	    VerIterator Ver(Cache,*I);
-	    DepPkg = Ver.ParentPkg();
-	    InstallVer = VerIterator(Cache,Cache[DepPkg].InstallVer);
-
-	    // Check if the current version of the package is avalible and will satisfy this dependancy
-	    if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true && 
-		!List->IsFlag(DepPkg,pkgOrderList::Removed) && DepPkg.State() == PkgIterator::NeedsNothing)
+   bool Bad = false, Changed = false;
+   do {
+      Changed = false;
+      for (DepIterator D = instVer.DependsList(); D.end() == false; )
+      {
+	 // Compute a single dependency element (glob or)
+	 pkgCache::DepIterator Start, End;
+	 D.GlobOr(Start,End);
+
+	 if (End->Type != pkgCache::Dep::Depends)
+	    continue;
+	 Bad = true;
+
+	 // Search for dependencies which are unpacked but aren't configured yet (maybe loops)
+	 for (DepIterator Cur = Start; true; ++Cur)
+	 {
+	    SPtrArray<Version *> VList = Cur.AllTargets();
+
+	    for (Version **I = VList; *I != 0; ++I)
 	    {
 	    {
-	       Bad = false;
-	       break;
-	    }
-	    
-	    // Check if the version that is going to be installed will satisfy the dependancy
-	    if (Cache[DepPkg].InstallVer == *I) {
-	       if (List->IsFlag(DepPkg,pkgOrderList::UnPacked)) {
-	          if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop) {
-	            // This dependancy has already been dealt with by another SmartConfigure on Pkg
-	            Bad = false;
-	            break;
-                  } else if (List->IsFlag(Pkg,pkgOrderList::Loop)) {
-	            /* Check for a loop to prevent one forming
-	               If A depends on B and B depends on A, SmartConfigure will
-	               just hop between them if this is not checked. Dont remove the 
-	               loop flag after finishing however as loop is already set.
-	               This means that there is another SmartConfigure call for this 
-	               package and it will remove the loop flag */
-	             Bad = !SmartConfigure(DepPkg, Depth + 1);
-	          } else {
-	            /* Check for a loop to prevent one forming
-	               If A depends on B and B depends on A, SmartConfigure will
-	               just hop between them if this is not checked */
-	            List->Flag(Pkg,pkgOrderList::Loop);
-	            Bad = !SmartConfigure(DepPkg, Depth + 1);
-	            List->RmFlag(Pkg,pkgOrderList::Loop);
-	          }
-	          // If SmartConfigure was succesfull, Bad is false, so break
-	          if (!Bad) break;
-	       } else if (List->IsFlag(DepPkg,pkgOrderList::Configured)) {
-	          Bad = false;
-	          break;
+	       VerIterator Ver(Cache,*I);
+	       PkgIterator DepPkg = Ver.ParentPkg();
+
+	       // Check if the current version of the package is available and will satisfy this dependency
+	       if (DepPkg.CurrentVer() == Ver && List->IsNow(DepPkg) == true &&
+		   List->IsFlag(DepPkg,pkgOrderList::Removed) == false &&
+		   DepPkg.State() == PkgIterator::NeedsNothing)
+	       {
+		  Bad = false;
+		  break;
+	       }
+
+	       // Check if the version that is going to be installed will satisfy the dependency
+	       if (Cache[DepPkg].InstallVer != *I)
+		  continue;
+
+	       if (List->IsFlag(DepPkg,pkgOrderList::UnPacked))
+	       {
+		  if (List->IsFlag(DepPkg,pkgOrderList::Loop) && PkgLoop)
+		  {
+		    // This dependency has already been dealt with by another SmartConfigure on Pkg
+		    Bad = false;
+		    break;
+		  }
+		  /* Check for a loop to prevent one forming
+		       If A depends on B and B depends on A, SmartConfigure will
+		       just hop between them if this is not checked. Dont remove the
+		       loop flag after finishing however as loop is already set.
+		       This means that there is another SmartConfigure call for this
+		       package and it will remove the loop flag */
+		  if (PkgLoop == false)
+		     List->Flag(Pkg,pkgOrderList::Loop);
+		  if (SmartConfigure(DepPkg, Depth + 1) == true)
+		  {
+		     Bad = false;
+		     if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
+			Changed = true;
+		  }
+		  if (PkgLoop == false)
+		    List->RmFlag(Pkg,pkgOrderList::Loop);
+		  // If SmartConfigure was succesfull, Bad is false, so break
+		  if (Bad == false)
+		     break;
+	       }
+	       else if (List->IsFlag(DepPkg,pkgOrderList::Configured))
+	       {
+		  Bad = false;
+		  break;
 	       }
 	       }
 	    }
 	    }
-	 }
-	 
-	 /* If the dependany is still not satisfied, try, if possible, unpacking a package to satisfy it */
-	 if (InstallVer != 0 && Bad) {
-	    if (List->IsNow(DepPkg)) {
-	       Bad = false;
-	       if (List->IsFlag(Pkg,pkgOrderList::Loop))
+	    if (Cur == End)
+	       break;
+         }
+
+	 if (Bad == false)
+	    continue;
+
+	 // Check for dependencies that have not been unpacked, probably due to loops.
+	 for (DepIterator Cur = Start; true; ++Cur)
+	 {
+	    SPtrArray<Version *> VList = Cur.AllTargets();
+
+	    for (Version **I = VList; *I != 0; ++I)
+	    {
+	       VerIterator Ver(Cache,*I);
+	       PkgIterator DepPkg = Ver.ParentPkg();
+
+	       // Check if the version that is going to be installed will satisfy the dependency
+	       if (Cache[DepPkg].InstallVer != *I || List->IsNow(DepPkg) == false)
+		  continue;
+
+	       if (PkgLoop == true)
 	       {
 	       {
 		  if (Debug)
 		  if (Debug)
 		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
 		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
+	          Bad = false;
+		  break;
 	       }
 	       }
 	       else
 	       else
 	       {
 	       {
-		  List->Flag(Pkg,pkgOrderList::Loop);
 		  if (Debug)
 		  if (Debug)
-		     cout << OutputInDepth(Depth) << "Unpacking " << DepPkg.Name() << " to avoid loop" << endl;
-		  SmartUnPack(DepPkg, true, Depth + 1);
-		  List->RmFlag(Pkg,pkgOrderList::Loop);
+		     clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl;
+		  if (PkgLoop == false)
+		     List->Flag(Pkg,pkgOrderList::Loop);
+		  if (SmartUnPack(DepPkg, true, Depth + 1) == true)
+		  {
+		     Bad = false;
+		     if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
+		        Changed = true;
+		  }
+		  if (PkgLoop == false)
+		     List->RmFlag(Pkg,pkgOrderList::Loop);
+		  if (Bad == false)
+		     break;
 	       }
 	       }
 	    }
 	    }
+
+	    if (Cur == End)
+	       break;
 	 }
 	 }
-	 
-	 if (Start==End) {
-	    if (Bad && Debug && List->IsFlag(DepPkg,pkgOrderList::Loop) == false)
-		  std::clog << OutputInDepth(Depth) << "Could not satisfy dependencies for " << Pkg.Name() << std::endl;
-	    break;
-	 } else {
-            Start++;
-         }
+
+	 if (Bad == true && Changed == false && Debug == true)
+	    std::clog << OutputInDepth(Depth) << "Could not satisfy " << Start << std::endl;
       }
       }
-   }
+   } while (Changed == true);
    
    
    if (Bad) {
    if (Bad) {
       if (Debug)
       if (Debug)
-         _error->Warning(_("Could not configure '%s'. "),Pkg.Name());
+         _error->Warning(_("Could not configure '%s'. "),Pkg.FullName().c_str());
       return false;
       return false;
    }
    }
    
    
@@ -444,7 +474,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
    static bool const ConfigurePkgs = (conf == "all" || conf == "smart");
    static bool const ConfigurePkgs = (conf == "all" || conf == "smart");
 
 
    if (List->IsFlag(Pkg,pkgOrderList::Configured)) 
    if (List->IsFlag(Pkg,pkgOrderList::Configured)) 
-      return _error->Error("Internal configure error on '%s'.", Pkg.Name());
+      return _error->Error("Internal configure error on '%s'.", Pkg.FullName().c_str());
 
 
    if (ConfigurePkgs == true && Configure(Pkg) == false)
    if (ConfigurePkgs == true && Configure(Pkg) == false)
       return false;
       return false;
@@ -464,7 +494,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 
 
    // Sanity Check
    // Sanity Check
    if (List->IsFlag(Pkg,pkgOrderList::Configured) == false)
    if (List->IsFlag(Pkg,pkgOrderList::Configured) == false)
-      return _error->Error(_("Could not configure '%s'. "),Pkg.Name());
+      return _error->Error(_("Could not configure '%s'. "),Pkg.FullName().c_str());
 
 
    return true;
    return true;
 }
 }
@@ -487,7 +517,8 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
 
 
    // Essential packages get special treatment
    // Essential packages get special treatment
    bool IsEssential = false;
    bool IsEssential = false;
-   if ((Pkg->Flags & pkgCache::Flag::Essential) != 0)
+   if ((Pkg->Flags & pkgCache::Flag::Essential) != 0 ||
+       (Pkg->Flags & pkgCache::Flag::Important) != 0)
       IsEssential = true;
       IsEssential = true;
 
 
    /* Check for packages that are the dependents of essential packages and 
    /* Check for packages that are the dependents of essential packages and 
@@ -497,7 +528,8 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
       for (DepIterator D = Pkg.RevDependsList(); D.end() == false &&
       for (DepIterator D = Pkg.RevDependsList(); D.end() == false &&
 	   IsEssential == false; ++D)
 	   IsEssential == false; ++D)
 	 if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
 	 if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends)
-	    if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0)
+	    if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0 ||
+	        (D.ParentPkg()->Flags & pkgCache::Flag::Important) != 0)
 	       IsEssential = true;
 	       IsEssential = true;
    }
    }
 
 
@@ -508,7 +540,7 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
 				"removing the essential package %s due to a "
 				"removing the essential package %s due to a "
 				"Conflicts/Pre-Depends loop. This is often bad, "
 				"Conflicts/Pre-Depends loop. This is often bad, "
 				"but if you really want to do it, activate the "
 				"but if you really want to do it, activate the "
-				"APT::Force-LoopBreak option."),Pkg.Name());
+				"APT::Force-LoopBreak option."),Pkg.FullName().c_str());
    }
    }
    
    
    bool Res = SmartRemove(Pkg);
    bool Res = SmartRemove(Pkg);
@@ -544,193 +576,252 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
    bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop);
    bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop);
 
 
    if (Debug) {
    if (Debug) {
-      clog << OutputInDepth(Depth) << "SmartUnPack " << Pkg.Name();
+      clog << OutputInDepth(Depth) << "SmartUnPack " << Pkg.FullName();
       VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer);
       VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer);
       if (Pkg.CurrentVer() == 0)
       if (Pkg.CurrentVer() == 0)
-        cout << " (install version " << InstallVer.VerStr() << ")";
+        clog << " (install version " << InstallVer.VerStr() << ")";
       else
       else
-        cout << " (replace version " << Pkg.CurrentVer().VerStr() << " with " << InstallVer.VerStr() << ")";
+        clog << " (replace version " << Pkg.CurrentVer().VerStr() << " with " << InstallVer.VerStr() << ")";
       if (PkgLoop)
       if (PkgLoop)
-        cout << " (Only Perform PreUnpack Checks)";
-      cout << endl;
+        clog << " (Only Perform PreUnpack Checks)";
+      clog << endl;
    }
    }
 
 
    VerIterator const instVer = Cache[Pkg].InstVerIter(Cache);
    VerIterator const instVer = Cache[Pkg].InstVerIter(Cache);
 
 
    /* PreUnpack Checks: This loop checks and attempts to rectify and problems that would prevent the package being unpacked.
    /* PreUnpack Checks: This loop checks and attempts to rectify and problems that would prevent the package being unpacked.
-      It addresses: PreDepends, Conflicts, Obsoletes and Breaks (DpkgBreaks). Any resolutions that do not require it should 
+      It addresses: PreDepends, Conflicts, Obsoletes and Breaks (DpkgBreaks). Any resolutions that do not require it should
       avoid configuration (calling SmartUnpack with Immediate=true), this is because when unpacking some packages with
       avoid configuration (calling SmartUnpack with Immediate=true), this is because when unpacking some packages with
-      complex dependancy structures, trying to configure some packages while breaking the loops can complicate things . 
-      This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured), 
+      complex dependancy structures, trying to configure some packages while breaking the loops can complicate things .
+      This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured),
       or by the ConfigureAll call at the end of the for loop in OrderInstall. */
       or by the ConfigureAll call at the end of the for loop in OrderInstall. */
-   for (DepIterator D = instVer.DependsList();
-	D.end() == false; )
-   {
-      // Compute a single dependency element (glob or)
-      pkgCache::DepIterator Start;
-      pkgCache::DepIterator End;
-      D.GlobOr(Start,End);
-      
-      while (End->Type == pkgCache::Dep::PreDepends)
+   bool Changed = false;
+   do {
+      Changed = false;
+      for (DepIterator D = instVer.DependsList(); D.end() == false; )
       {
       {
-	 if (Debug)
-	    clog << OutputInDepth(Depth) << "PreDepends order for " << Pkg.Name() << std::endl;
-
-	 // Look for possible ok targets.
-	 SPtrArray<Version *> VList = Start.AllTargets();
-	 bool Bad = true;
-	 for (Version **I = VList; *I != 0 && Bad == true; I++)
-	 {
-	    VerIterator Ver(Cache,*I);
-	    PkgIterator Pkg = Ver.ParentPkg();
-	    
-	    // See if the current version is ok
-	    if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true && 
-		Pkg.State() == PkgIterator::NeedsNothing)
+	 // Compute a single dependency element (glob or)
+	 pkgCache::DepIterator Start, End;
+	 D.GlobOr(Start,End);
+
+	 if (End->Type == pkgCache::Dep::PreDepends)
+         {
+	    bool Bad = true;
+	    if (Debug)
+	       clog << OutputInDepth(Depth) << "PreDepends order for " << Pkg.FullName() << std::endl;
+
+	    // Look for easy targets: packages that are already okay
+	    for (DepIterator Cur = Start; Bad == true; ++Cur)
 	    {
 	    {
-	       Bad = false;
-	       if (Debug)
-		  clog << OutputInDepth(Depth) << "Found ok package " << Pkg.Name() << endl;
-	       continue;
-	    }
-	 }
-	 
-	 // Look for something that could be configured.
-	 for (Version **I = VList; *I != 0 && Bad == true; I++)
-	 {
-	    VerIterator Ver(Cache,*I);
-	    PkgIterator Pkg = Ver.ParentPkg();
-	    
-	    // Not the install version 
-	    if (Cache[Pkg].InstallVer != *I || 
-		(Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
-	       continue;
-	       
-	    if (List->IsFlag(Pkg,pkgOrderList::Configured)) {
-	       Bad = false;
-	       continue;
+	       SPtrArray<Version *> VList = Start.AllTargets();
+	       for (Version **I = VList; *I != 0; ++I)
+	       {
+		  VerIterator Ver(Cache,*I);
+		  PkgIterator Pkg = Ver.ParentPkg();
+
+		  // See if the current version is ok
+		  if (Pkg.CurrentVer() == Ver && List->IsNow(Pkg) == true &&
+		      Pkg.State() == PkgIterator::NeedsNothing)
+		  {
+		     Bad = false;
+		     if (Debug)
+			clog << OutputInDepth(Depth) << "Found ok package " << Pkg.FullName() << endl;
+		     break;
+		  }
+	       }
+	       if (Cur == End)
+		  break;
 	    }
 	    }
 
 
-            // check if it needs unpack or if if configure is enough
-            if (!List->IsFlag(Pkg,pkgOrderList::UnPacked))
-            {
-               if (Debug)
-                  clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << Pkg.Name() << endl;
-               // SmartUnpack with the ImmediateFlag to ensure its really ready
-               Bad = !SmartUnPack(Pkg, true, Depth + 1);
-            } else {
-               if (Debug)
-                  clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << Pkg.Name() << endl;
-               Bad = !SmartConfigure(Pkg, Depth + 1);
-            }
-         }
+	    // Look for something that could be configured.
+	    for (DepIterator Cur = Start; Bad == true; ++Cur)
+	    {
+	       SPtrArray<Version *> VList = Start.AllTargets();
+	       for (Version **I = VList; *I != 0; ++I)
+	       {
+		  VerIterator Ver(Cache,*I);
+		  PkgIterator Pkg = Ver.ParentPkg();
+
+		  // Not the install version
+		  if (Cache[Pkg].InstallVer != *I ||
+		      (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing))
+		     continue;
+
+		  if (List->IsFlag(Pkg,pkgOrderList::Configured))
+		  {
+		     Bad = false;
+		     break;
+		  }
+
+		  // check if it needs unpack or if if configure is enough
+		  if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == false)
+		  {
+		     if (Debug)
+			clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << Pkg.FullName() << endl;
+		     // SmartUnpack with the ImmediateFlag to ensure its really ready
+		     if (SmartUnPack(Pkg, true, Depth + 1) == true)
+		     {
+			Bad = false;
+			if (List->IsFlag(Pkg,pkgOrderList::Loop) == false)
+			   Changed = true;
+			break;
+		     }
+		  }
+		  else
+		  {
+		     if (Debug)
+			clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << Pkg.FullName() << endl;
+		     if (SmartConfigure(Pkg, Depth + 1) == true)
+		     {
+			Bad = false;
+			if (List->IsFlag(Pkg,pkgOrderList::Loop) == false)
+			   Changed = true;
+			break;
+		     }
+		  }
+	       }
+	    }
 
 
-	 /* If this or element did not match then continue on to the
-	    next or element until a matching element is found */
-	 if (Bad == true)
-	 {
-	    // This triggers if someone make a pre-depends/depend loop.
-	    if (Start == End)
-	       return _error->Error("Couldn't configure pre-depend %s for %s, "
-				    "probably a dependency cycle.",
-				    End.TargetPkg().Name(),Pkg.Name());
-	    ++Start;
+	    if (Bad == true)
+	    {
+	       if (Start == End)
+		  return _error->Error("Couldn't configure pre-depend %s for %s, "
+					"probably a dependency cycle.",
+					End.TargetPkg().FullName().c_str(),Pkg.FullName().c_str());
+	    }
+	    else
+	       continue;
 	 }
 	 }
-	 else 
-	    break;
-      }
-      
-      if (End->Type == pkgCache::Dep::Conflicts || 
-	  End->Type == pkgCache::Dep::Obsoletes)
-      {
-	 /* Look for conflicts. Two packages that are both in the install
-	    state cannot conflict so we don't check.. */
-	 SPtrArray<Version *> VList = End.AllTargets();
-	 for (Version **I = VList; *I != 0; I++)
+	 else if (End->Type == pkgCache::Dep::Conflicts ||
+		  End->Type == pkgCache::Dep::Obsoletes)
 	 {
 	 {
-	    VerIterator Ver(Cache,*I);
-	    PkgIterator ConflictPkg = Ver.ParentPkg();
-	    VerIterator InstallVer(Cache,Cache[ConflictPkg].InstallVer);
-	    
-	    // See if the current version is conflicting
-	    if (ConflictPkg.CurrentVer() == Ver && List->IsNow(ConflictPkg))
-	    { 
-	       cout << OutputInDepth(Depth) << Pkg.Name() << " conflicts with " << ConflictPkg.Name() << endl;
-	       /* If a loop is not present or has not yet been detected, attempt to unpack packages 
-	          to resolve this conflict. If there is a loop present, remove packages to resolve this conflict */
-	       if (!List->IsFlag(ConflictPkg,pkgOrderList::Loop)) {
-	          if (Cache[ConflictPkg].Keep() == 0 && Cache[ConflictPkg].InstallVer != 0) {
-	              if (Debug)
-                        cout << OutputInDepth(Depth) << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.Name() << " to prevent conflict" << endl;
-                      List->Flag(Pkg,pkgOrderList::Loop);
-	              SmartUnPack(ConflictPkg,false, Depth + 1);
-	              // Remove loop to allow it to be used later if needed
-	              List->RmFlag(Pkg,pkgOrderList::Loop);
-                  } else {
-                      if (EarlyRemove(ConflictPkg) == false)
-                         return _error->Error("Internal Error, Could not early remove %s",ConflictPkg.Name());
-                  }
-	       } else {
-	          if (!List->IsFlag(ConflictPkg,pkgOrderList::Removed)) {
-	              if (Debug)
-                         cout << OutputInDepth(Depth) << "Because of conficts knot, removing " << ConflictPkg.Name() << " to conflict violation" << endl;
-	              if (EarlyRemove(ConflictPkg) == false)
-                          return _error->Error("Internal Error, Could not early remove %s",ConflictPkg.Name());
-	          }
+	    /* Look for conflicts. Two packages that are both in the install
+	       state cannot conflict so we don't check.. */
+	    SPtrArray<Version *> VList = End.AllTargets();
+	    for (Version **I = VList; *I != 0; I++)
+	    {
+	       VerIterator Ver(Cache,*I);
+	       PkgIterator ConflictPkg = Ver.ParentPkg();
+	       VerIterator InstallVer(Cache,Cache[ConflictPkg].InstallVer);
+
+	       // See if the current version is conflicting
+	       if (ConflictPkg.CurrentVer() == Ver && List->IsNow(ConflictPkg))
+	       {
+		  clog << OutputInDepth(Depth) << Pkg.FullName() << " conflicts with " << ConflictPkg.FullName() << endl;
+		  /* If a loop is not present or has not yet been detected, attempt to unpack packages
+		     to resolve this conflict. If there is a loop present, remove packages to resolve this conflict */
+		  if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) == false)
+		  {
+		     if (Cache[ConflictPkg].Keep() == 0 && Cache[ConflictPkg].InstallVer != 0)
+		     {
+			if (Debug)
+			   clog << OutputInDepth(Depth) << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.FullName() << " to prevent conflict" << endl;
+			List->Flag(Pkg,pkgOrderList::Loop);
+			if (SmartUnPack(ConflictPkg,false, Depth + 1) == true)
+			   if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) == false)
+			      Changed = true;
+			// Remove loop to allow it to be used later if needed
+			List->RmFlag(Pkg,pkgOrderList::Loop);
+		     }
+		     else if (EarlyRemove(ConflictPkg) == false)
+			return _error->Error("Internal Error, Could not early remove %s (1)",ConflictPkg.FullName().c_str());
+		  }
+		  else if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == false)
+		  {
+		     if (Debug)
+			clog << OutputInDepth(Depth) << "Because of conficts knot, removing " << ConflictPkg.FullName() << " to conflict violation" << endl;
+		     if (EarlyRemove(ConflictPkg) == false)
+			return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str());
+		  }
 	       }
 	       }
 	    }
 	    }
 	 }
 	 }
-      }
-      
-      // Check for breaks
-      if (End->Type == pkgCache::Dep::DpkgBreaks) {
-         SPtrArray<Version *> VList = End.AllTargets();
-	 for (Version **I = VList; *I != 0; I++)
+	 else if (End->Type == pkgCache::Dep::DpkgBreaks)
 	 {
 	 {
-	    VerIterator Ver(Cache,*I);
-	    PkgIterator BrokenPkg = Ver.ParentPkg();
-	    VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
-	    if (BrokenPkg.CurrentVer() != Ver)
+	    SPtrArray<Version *> VList = End.AllTargets();
+	    for (Version **I = VList; *I != 0; ++I)
 	    {
 	    {
-	       if (Debug)
-		  std::clog << OutputInDepth(Depth) << "  Ignore not-installed version " << Ver.VerStr() << " of " << Pkg.FullName() << " for " << End << std::endl;
-	       continue;
-	    }
+	       VerIterator Ver(Cache,*I);
+	       PkgIterator BrokenPkg = Ver.ParentPkg();
+	       if (BrokenPkg.CurrentVer() != Ver)
+	       {
+		  if (Debug)
+		     std::clog << OutputInDepth(Depth) << "  Ignore not-installed version " << Ver.VerStr() << " of " << Pkg.FullName() << " for " << End << std::endl;
+		  continue;
+	       }
 
 
-	    // Check if it needs to be unpacked
-	    if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false && 
-	        List->IsNow(BrokenPkg)) {
-	      if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) {
-	        // This dependancy has already been dealt with by another SmartUnPack on Pkg
-	        break;
-	      } else if (List->IsFlag(Pkg,pkgOrderList::Loop)) {
-	        /* Found a break, so unpack the package, but dont remove loop as already set.
-	           This means that there is another SmartUnPack call for this 
-	           package and it will remove the loop flag. */
-	        if (Debug) 
-	          cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-	            
-	        SmartUnPack(BrokenPkg, false, Depth + 1);
-	      } else {
-                List->Flag(Pkg,pkgOrderList::Loop);
-	        // Found a break, so unpack the package
-	        if (Debug) 
-	          cout << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.Name() << " to avoid break" << endl;
-	         
-	        SmartUnPack(BrokenPkg, false, Depth + 1);
-	        List->RmFlag(Pkg,pkgOrderList::Loop);
-	      }
-	    }
-	    
-	    // Check if a package needs to be removed
-	    if (Cache[BrokenPkg].Delete() == true && !List->IsFlag(BrokenPkg,pkgOrderList::Configured)) {
-	      if (Debug) 
-	         cout << OutputInDepth(Depth) << "  Removing " << BrokenPkg.Name() << " to avoid break" << endl;
-	      SmartRemove(BrokenPkg);
+	       // Check if it needs to be unpacked
+	       if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false &&
+		   List->IsNow(BrokenPkg))
+	       {
+		  if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop)
+		  {
+		     // This dependancy has already been dealt with by another SmartUnPack on Pkg
+		     break;
+		  }
+		  else
+		  {
+		     // Found a break, so see if we can unpack the package to avoid it
+		     // but do not set loop if another SmartUnPack already deals with it
+		     // Also, avoid it if the package we would unpack pre-depends on this one
+		     VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer);
+		     bool circle = false;
+		     for (pkgCache::DepIterator D = InstallVer.DependsList(); D.end() == false; ++D)
+		     {
+			if (D->Type != pkgCache::Dep::PreDepends)
+			   continue;
+			SPtrArray<Version *> VL = D.AllTargets();
+			for (Version **I = VL; *I != 0; ++I)
+			{
+			   VerIterator V(Cache,*I);
+			   PkgIterator P = V.ParentPkg();
+			   // we are checking for installation as an easy 'protection' against or-groups and (unchosen) providers
+			   if (P->CurrentVer == 0 || P != Pkg || (P.CurrentVer() != V && Cache[P].InstallVer != V))
+			      continue;
+			   circle = true;
+			   break;
+			}
+			if (circle == true)
+			   break;
+		     }
+		     if (circle == true)
+		     {
+			if (Debug)
+			   clog << OutputInDepth(Depth) << "  Avoiding " << End << " avoided as " << BrokenPkg.FullName() << " has a pre-depends on " << Pkg.FullName() << std::endl;
+			continue;
+		     }
+		     else
+		     {
+			if (Debug)
+			{
+			   clog << OutputInDepth(Depth) << "  Unpacking " << BrokenPkg.FullName() << " to avoid " << End;
+			   if (PkgLoop == true)
+			      clog << " (Looping)";
+			   clog << std::endl;
+			}
+			if (PkgLoop == false)
+			   List->Flag(Pkg,pkgOrderList::Loop);
+			if (SmartUnPack(BrokenPkg, false, Depth + 1) == true)
+			{
+			   if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) == false)
+			      Changed = true;
+			}
+			if (PkgLoop == false)
+			   List->RmFlag(Pkg,pkgOrderList::Loop);
+		     }
+		  }
+	       }
+	       // Check if a package needs to be removed
+	       else if (Cache[BrokenPkg].Delete() == true && List->IsFlag(BrokenPkg,pkgOrderList::Configured) == false)
+	       {
+		  if (Debug)
+		     clog << OutputInDepth(Depth) << "  Removing " << BrokenPkg.FullName() << " to avoid " << End << endl;
+		  SmartRemove(BrokenPkg);
+	       }
 	    }
 	    }
 	 }
 	 }
       }
       }
-   }
+   } while (Changed == true);
    
    
    // Check for reverse conflicts.
    // Check for reverse conflicts.
    if (CheckRConflicts(Pkg,Pkg.RevDependsList(),
    if (CheckRConflicts(Pkg,Pkg.RevDependsList(),
@@ -787,7 +878,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
       // Perform immedate configuration of the package. 
       // Perform immedate configuration of the package. 
          if (SmartConfigure(Pkg, Depth + 1) == false)
          if (SmartConfigure(Pkg, Depth + 1) == false)
             _error->Warning(_("Could not perform immediate configuration on '%s'. "
             _error->Warning(_("Could not perform immediate configuration on '%s'. "
-               "Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.Name(),2);
+               "Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.FullName().c_str(),2);
    }
    }
    
    
    return true;
    return true;
@@ -827,11 +918,11 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
       {
       {
          if (!List->IsFlag(Pkg,pkgOrderList::Configured) && !NoImmConfigure) {
          if (!List->IsFlag(Pkg,pkgOrderList::Configured) && !NoImmConfigure) {
             if (SmartConfigure(Pkg, 0) == false && Debug)
             if (SmartConfigure(Pkg, 0) == false && Debug)
-               _error->Warning("Internal Error, Could not configure %s",Pkg.Name());
+               _error->Warning("Internal Error, Could not configure %s",Pkg.FullName().c_str());
             // FIXME: The above warning message might need changing
             // FIXME: The above warning message might need changing
          } else {
          } else {
 	    if (Debug == true)
 	    if (Debug == true)
-	       clog << "Skipping already done " << Pkg.Name() << endl;
+	       clog << "Skipping already done " << Pkg.FullName() << endl;
 	 }
 	 }
 	 continue;
 	 continue;
 	 
 	 
@@ -840,7 +931,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
       if (List->IsMissing(Pkg) == true)
       if (List->IsMissing(Pkg) == true)
       {
       {
 	 if (Debug == true)
 	 if (Debug == true)
-	    clog << "Sequence completed at " << Pkg.Name() << endl;
+	    clog << "Sequence completed at " << Pkg.FullName() << endl;
 	 if (DoneSomething == false)
 	 if (DoneSomething == false)
 	 {
 	 {
 	    _error->Error("Internal Error, ordering was unable to handle the media swap");
 	    _error->Error("Internal Error, ordering was unable to handle the media swap");
@@ -854,7 +945,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
 	  Pkg.State() == pkgCache::PkgIterator::NeedsNothing &&
 	  Pkg.State() == pkgCache::PkgIterator::NeedsNothing &&
 	  (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
 	  (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)
       {
       {
-	 _error->Error("Internal Error, trying to manipulate a kept package (%s)",Pkg.Name());
+	 _error->Error("Internal Error, trying to manipulate a kept package (%s)",Pkg.FullName().c_str());
 	 return Failed;
 	 return Failed;
       }
       }
       
       
@@ -887,7 +978,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
       if (List->IsFlag(*I,pkgOrderList::Configured) == false)
       if (List->IsFlag(*I,pkgOrderList::Configured) == false)
       {
       {
 	 _error->Error("Internal error, packages left unconfigured. %s",
 	 _error->Error("Internal error, packages left unconfigured. %s",
-		       PkgIterator(Cache,*I).Name());
+		       PkgIterator(Cache,*I).FullName().c_str());
 	 return Failed;
 	 return Failed;
       }
       }
    }
    }

+ 1 - 1
apt-pkg/pkgrecords.cc

@@ -22,7 +22,7 @@
 // Records::pkgRecords - Constructor					/*{{{*/
 // Records::pkgRecords - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This will create the necessary structures to access the status files */
 /* This will create the necessary structures to access the status files */
-pkgRecords::pkgRecords(pkgCache &Cache) : Cache(Cache), 
+pkgRecords::pkgRecords(pkgCache &Cache) : d(NULL), Cache(Cache),
   Files(Cache.HeaderP->PackageFileCount)
   Files(Cache.HeaderP->PackageFileCount)
 {
 {
    for (pkgCache::PkgFileIterator I = Cache.FileBegin();
    for (pkgCache::PkgFileIterator I = Cache.FileBegin();

+ 2 - 2
apt-pkg/pkgsystem.cc

@@ -26,11 +26,11 @@ unsigned long pkgSystem::GlobalListLen = 0;
 // System::pkgSystem - Constructor					/*{{{*/
 // System::pkgSystem - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Add it to the global list.. */
 /* Add it to the global list.. */
-pkgSystem::pkgSystem()
+pkgSystem::pkgSystem() : Label(NULL), VS(NULL)
 {
 {
    assert(GlobalListLen < sizeof(SysList)/sizeof(*SysList));
    assert(GlobalListLen < sizeof(SysList)/sizeof(*SysList));
    SysList[GlobalListLen] = this;
    SysList[GlobalListLen] = this;
-   GlobalListLen++;
+   ++GlobalListLen;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // System::GetSystem - Get the named system				/*{{{*/
 // System::GetSystem - Get the named system				/*{{{*/

+ 1 - 1
apt-pkg/sourcelist.cc

@@ -33,7 +33,7 @@ unsigned long pkgSourceList::Type::GlobalListLen = 0;
 // Type::Type - Constructor						/*{{{*/
 // Type::Type - Constructor						/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Link this to the global list of items*/
 /* Link this to the global list of items*/
-pkgSourceList::Type::Type()
+pkgSourceList::Type::Type() : Name(NULL), Label(NULL)
 {
 {
    ItmList[GlobalListLen] = this;
    ItmList[GlobalListLen] = this;
    GlobalListLen++;
    GlobalListLen++;

+ 1 - 1
apt-pkg/srcrecords.cc

@@ -25,7 +25,7 @@
 // SrcRecords::pkgSrcRecords - Constructor				/*{{{*/
 // SrcRecords::pkgSrcRecords - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Open all the source index files */
 /* Open all the source index files */
-pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : Files(0), Current(0)
+pkgSrcRecords::pkgSrcRecords(pkgSourceList &List) : d(NULL), Files(0), Current(0)
 {
 {
    for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); ++I)
    for (pkgSourceList::const_iterator I = List.begin(); I != List.end(); ++I)
    {
    {

+ 4 - 1
apt-pkg/tagfile.cc

@@ -30,7 +30,10 @@ using std::string;
 class pkgTagFilePrivate
 class pkgTagFilePrivate
 {
 {
 public:
 public:
-   pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Size(Size)
+   pkgTagFilePrivate(FileFd *pFd, unsigned long long Size) : Fd(*pFd), Buffer(NULL),
+							     Start(NULL), End(NULL),
+							     Done(false), iOffset(0),
+							     Size(Size)
    {
    {
    }
    }
    FileFd &Fd;
    FileFd &Fd;

+ 2 - 2
apt-pkg/version.cc

@@ -23,10 +23,10 @@ unsigned long pkgVersioningSystem::GlobalListLen = 0;
 // pkgVS::pkgVersioningSystem - Constructor				/*{{{*/
 // pkgVS::pkgVersioningSystem - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Link to the global list of versioning systems supported */
 /* Link to the global list of versioning systems supported */
-pkgVersioningSystem::pkgVersioningSystem()
+pkgVersioningSystem::pkgVersioningSystem() : Label(NULL)
 {
 {
    VSList[GlobalListLen] = this;
    VSList[GlobalListLen] = this;
-   GlobalListLen++;
+   ++GlobalListLen;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // pkgVS::GetVS - Find a VS by name					/*{{{*/
 // pkgVS::GetVS - Find a VS by name					/*{{{*/

+ 2 - 1
cmdline/acqprogress.cc

@@ -31,8 +31,9 @@ using namespace std;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
 AcqTextStatus::AcqTextStatus(unsigned int &ScreenWidth,unsigned int Quiet) :
-    ScreenWidth(ScreenWidth), Quiet(Quiet)
+    ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet)
 {
 {
+   BlankLine[0] = 0;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // AcqTextStatus::Start - Downloading has started			/*{{{*/
 // AcqTextStatus::Start - Downloading has started			/*{{{*/

+ 1 - 1
cmdline/apt-cache.cc

@@ -1739,7 +1739,7 @@ int main(int argc,const char *argv[])					/*{{{*/
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {'o',"option",0,CommandLine::ArbItem},
       {0,"installed","APT::Cache::Installed",0},
       {0,"installed","APT::Cache::Installed",0},
-      {0,"pre-depends","APT::Cache::ShowPreDepends",0},
+      {0,"pre-depends","APT::Cache::ShowPre-Depends",0},
       {0,"depends","APT::Cache::ShowDepends",0},
       {0,"depends","APT::Cache::ShowDepends",0},
       {0,"recommends","APT::Cache::ShowRecommends",0},
       {0,"recommends","APT::Cache::ShowRecommends",0},
       {0,"suggests","APT::Cache::ShowSuggests",0},
       {0,"suggests","APT::Cache::ShowSuggests",0},

+ 3 - 4
cmdline/apt-cdrom.cc

@@ -150,10 +150,9 @@ bool DoAdd(CommandLine &)
    bool res = true;
    bool res = true;
 
 
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true);
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect", true);
-   unsigned int count = 0;
-   
    if (AutoDetect && UdevCdroms.Dlopen())
    if (AutoDetect && UdevCdroms.Dlopen())
    {
    {
+      unsigned int count = 0;
       while (AutoDetectCdrom(UdevCdroms, count))
       while (AutoDetectCdrom(UdevCdroms, count))
 	 res &= cdrom.Add(&log);
 	 res &= cdrom.Add(&log);
    } else {
    } else {
@@ -178,10 +177,10 @@ bool DoIdent(CommandLine &)
    bool res = true;
    bool res = true;
 
 
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect");
    bool AutoDetect = _config->FindB("Acquire::cdrom::AutoDetect");
-   unsigned int count = 0;
-   
+
    if (AutoDetect && UdevCdroms.Dlopen())
    if (AutoDetect && UdevCdroms.Dlopen())
    {
    {
+      unsigned int count = 0;
       while (AutoDetectCdrom(UdevCdroms, count))
       while (AutoDetectCdrom(UdevCdroms, count))
 	 res &= cdrom.Ident(ident, &log);
 	 res &= cdrom.Ident(ident, &log);
    } else {
    } else {

+ 2 - 2
cmdline/apt-extracttemplates.cc

@@ -53,8 +53,8 @@ pkgCache *DebFile::Cache = 0;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 DebFile::DebFile(const char *debfile)
 DebFile::DebFile(const char *debfile)
-	: File(debfile, FileFd::ReadOnly), Control(0), DepOp(0), 
-          PreDepOp(0), Config(0), Template(0), Which(None)
+	: File(debfile, FileFd::ReadOnly), Size(0), Control(NULL), ControlLen(0),
+	  DepOp(0), PreDepOp(0), Config(0), Template(0), Which(None)
 {
 {
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 43 - 6
cmdline/apt-get.cc

@@ -713,11 +713,32 @@ public:
 	}
 	}
 
 
 	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
 	virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
-		APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
-		if (verset.empty() == false)
-			return *(verset.begin());
-		if (ShowError == true)
-			ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+		if (Pkg->ProvidesList != 0)
+		{
+			APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
+			if (verset.empty() == false)
+				return *(verset.begin());
+			if (ShowError == true)
+				ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
+		}
+		else
+		{
+			pkgCache::GrpIterator Grp = Pkg.Group();
+			pkgCache::PkgIterator P = Grp.PackageList();
+			for (; P.end() != true; P = Grp.NextPkg(P))
+			{
+				if (P == Pkg)
+					continue;
+				if (P->CurrentVer != 0) {
+					// TRANSLATORS: Note, this is not an interactive question
+					ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
+						 Pkg.FullName(true).c_str(), P.FullName(true).c_str());
+					break;
+				}
+			}
+			if (P.end() == true)
+				ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+		}
 		return pkgCache::VerIterator(Cache, 0);
 		return pkgCache::VerIterator(Cache, 0);
 	}
 	}
 
 
@@ -904,7 +925,23 @@ struct TryToRemove {
       if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
       if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
 	  (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
 	  (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
       {
       {
-	 ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+	 pkgCache::GrpIterator Grp = Pkg.Group();
+	 pkgCache::PkgIterator P = Grp.PackageList();
+	 for (; P.end() != true; P = Grp.NextPkg(P))
+	 {
+	    if (P == Pkg)
+	       continue;
+	    if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled))
+	    {
+	       // TRANSLATORS: Note, this is not an interactive question
+	       ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"),
+			Pkg.FullName(true).c_str(), P.FullName(true).c_str());
+	       break;
+	    }
+	 }
+	 if (P.end() == true)
+	    ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str());
+
 	 // MarkInstall refuses to install packages on hold
 	 // MarkInstall refuses to install packages on hold
 	 Pkg->SelectedState = pkgCache::State::Hold;
 	 Pkg->SelectedState = pkgCache::State::Hold;
       }
       }

+ 116 - 20
cmdline/apt-mark.cc

@@ -14,9 +14,15 @@
 #include <apt-pkg/init.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/fileutl.h>
 
 
 #include <algorithm>
 #include <algorithm>
+#include <errno.h>
 #include <unistd.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 									/*}}}*/
 									/*}}}*/
@@ -158,13 +164,63 @@ bool DoHold(CommandLine &CmdL)
    if (unlikely(Cache == NULL))
    if (unlikely(Cache == NULL))
       return false;
       return false;
 
 
+   // Generate the base argument list for dpkg
+   std::vector<const char *> Args;
+   string Tmp = _config->Find("Dir::Bin::dpkg","dpkg");
+   {
+      string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/");
+      size_t dpkgChrootLen = dpkgChrootDir.length();
+      if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0)
+      {
+	 if (dpkgChrootDir[dpkgChrootLen - 1] == '/')
+	    --dpkgChrootLen;
+	 Tmp = Tmp.substr(dpkgChrootLen);
+      }
+   }
+   Args.push_back(Tmp.c_str());
+
+   // Stick in any custom dpkg options
+   Configuration::Item const *Opts = _config->Tree("DPkg::Options");
+   if (Opts != 0)
+   {
+      Opts = Opts->Child;
+      for (; Opts != 0; Opts = Opts->Next)
+      {
+	 if (Opts->Value.empty() == true)
+	    continue;
+	 Args.push_back(Opts->Value.c_str());
+      }
+   }
+
+   size_t const BaseArgs = Args.size();
+   // we need to detect if we can qualify packages with the architecture or not
+   Args.push_back("--assert-multi-arch");
+   Args.push_back(NULL);
+
+
+   pid_t dpkgAssertMultiArch = ExecFork();
+   if (dpkgAssertMultiArch == 0)
+   {
+      std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
+      if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0)
+	 _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --assert-multi-arch", chrootDir.c_str());
+      // redirect everything to the ultimate sink as we only need the exit-status
+      int const nullfd = open("/dev/null", O_RDONLY);
+      dup2(nullfd, STDIN_FILENO);
+      dup2(nullfd, STDOUT_FILENO);
+      dup2(nullfd, STDERR_FILENO);
+      execvp(Args[0], (char**) &Args[0]);
+      _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
+      _exit(2);
+   }
+
    APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1);
    APT::PackageList pkgset = APT::PackageList::FromCommandLine(CacheFile, CmdL.FileList + 1);
    if (pkgset.empty() == true)
    if (pkgset.empty() == true)
       return _error->Error(_("No packages found"));
       return _error->Error(_("No packages found"));
 
 
    bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0;
    bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0;
 
 
-   for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
+   for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end();)
    {
    {
       if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold)
       if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold)
       {
       {
@@ -172,9 +228,25 @@ bool DoHold(CommandLine &CmdL)
 	    ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
 	    ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
 	 else
 	 else
 	    ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str());
 	    ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str());
-	 pkgset.erase(Pkg);
-	 continue;
+	 Pkg = pkgset.erase(Pkg, true);
+      }
+      else
+	 ++Pkg;
+   }
+
+   bool dpkgMultiArch = false;
+   if (dpkgAssertMultiArch > 0)
+   {
+      int Status = 0;
+      while (waitpid(dpkgAssertMultiArch, &Status, 0) != dpkgAssertMultiArch)
+      {
+	 if (errno == EINTR)
+	    continue;
+	 _error->WarningE("dpkgGo", _("Waited for %s but it wasn't there"), "dpkg --assert-multi-arch");
+	 break;
       }
       }
+      if (WIFEXITED(Status) == true && WEXITSTATUS(Status) == 0)
+	 dpkgMultiArch = true;
    }
    }
 
 
    if (pkgset.empty() == true)
    if (pkgset.empty() == true)
@@ -192,36 +264,60 @@ bool DoHold(CommandLine &CmdL)
       return true;
       return true;
    }
    }
 
 
-   string dpkgcall = _config->Find("Dir::Bin::dpkg", "dpkg");
-   std::vector<string> const dpkgoptions = _config->FindVector("DPkg::options");
-   for (std::vector<string>::const_iterator o = dpkgoptions.begin();
-	o != dpkgoptions.end(); ++o)
-      dpkgcall.append(" ").append(*o);
-   dpkgcall.append(" --set-selections");
-   FILE *dpkg = popen(dpkgcall.c_str(), "w");
-   if (dpkg == NULL)
-      return _error->Errno("DoHold", "fdopen on dpkg stdin failed");
+   Args.erase(Args.begin() + BaseArgs, Args.end());
+   Args.push_back("--set-selections");
+   Args.push_back(NULL);
+
+   int external[2] = {-1, -1};
+   if (pipe(external) != 0)
+      return _error->WarningE("DoHold", "Can't create IPC pipe for dpkg --set-selections");
 
 
+   pid_t dpkgSelection = ExecFork();
+   if (dpkgSelection == 0)
+   {
+      close(external[1]);
+      std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
+      if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0)
+	 _error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --set-selections", chrootDir.c_str());
+      int const nullfd = open("/dev/null", O_RDONLY);
+      dup2(external[0], STDIN_FILENO);
+      dup2(nullfd, STDOUT_FILENO);
+      dup2(nullfd, STDERR_FILENO);
+      execvp(Args[0], (char**) &Args[0]);
+      _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!");
+      _exit(2);
+   }
+
+   FILE* dpkg = fdopen(external[1], "w");
    for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
    for (APT::PackageList::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
    {
    {
       if (MarkHold == true)
       if (MarkHold == true)
       {
       {
-	 fprintf(dpkg, "%s hold\n", Pkg.FullName(true).c_str());
+	 fprintf(dpkg, "%s hold\n", Pkg.FullName(!dpkgMultiArch).c_str());
 	 ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
 	 ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
       }
       }
       else
       else
       {
       {
-	 fprintf(dpkg, "%s install\n", Pkg.FullName(true).c_str());
+	 fprintf(dpkg, "%s install\n", Pkg.FullName(!dpkgMultiArch).c_str());
 	 ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
 	 ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
       }
       }
    }
    }
+   fclose(dpkg);
 
 
-   int const status = pclose(dpkg);
-   if (status == -1)
-      return _error->Errno("DoHold", "dpkg execution failed in the end");
-   if (WIFEXITED(status) == false || WEXITSTATUS(status) != 0)
-      return _error->Error(_("Executing dpkg failed. Are you root?"));
-   return true;
+   if (dpkgSelection > 0)
+   {
+      int Status = 0;
+      while (waitpid(dpkgSelection, &Status, 0) != dpkgSelection)
+      {
+	 if (errno == EINTR)
+	    continue;
+	 _error->WarningE("dpkgGo", _("Waited for %s but it wasn't there"), "dpkg --set-selection");
+	 break;
+      }
+      if (WIFEXITED(Status) == true && WEXITSTATUS(Status) == 0)
+	 return true;
+   }
+   return _error->Error(_("Executing dpkg failed. Are you root?"));
 }
 }
 									/*}}}*/
 									/*}}}*/
 /* ShowHold - show packages set on hold in dpkg status			{{{*/
 /* ShowHold - show packages set on hold in dpkg status			{{{*/

+ 69 - 5
debian/changelog

@@ -1,9 +1,34 @@
-apt (0.8.16~exp13) UNRELEASED; urgency=low
+apt (0.8.16~exp14) UNRELEASED; urgency=low
+
+  [ Michael Vogt ]
+  * apt-pkg/packagemanager.cc:
+    - fix inconsistent clog/cout usage in the debug output
+  
+  [ David Kalnischkies ]
+  * apt-pkg/packagemanager.cc:
+    - recheck all dependencies if we changed a package in SmartConfigure
+      as this could break an earlier dependency (LP: #940396)
+    - recheck dependencies in SmartUnpack after a change, too
+
+ -- David Kalnischkies <kalnischkies@gmail.com>  Tue, 13 Mar 2012 12:38:35 +0100
+
+apt (0.8.16~exp13) experimental; urgency=low
 
 
   [ David Kalnischkies ]
   [ David Kalnischkies ]
+  * apt-pkg/acquire-item.cc:
+    - remove 'old' InRelease file if we can't get a new one before
+      proceeding with Release.gpg to avoid the false impression of a still
+      trusted repository by a (still present) old InRelease file.
+      Thanks to Simon Ruderich for reporting this issue! (CVE-2012-0214)
+    - add Debug::pkgAcqArchive::NoQueue to disable package downloading
   * apt-pkg/deb/dpkgpm.cc:
   * apt-pkg/deb/dpkgpm.cc:
     - chroot if needed before dpkg --assert-multi-arch
     - chroot if needed before dpkg --assert-multi-arch
     - ensure that dpkg binary doesn't have the chroot-directory prefixed
     - ensure that dpkg binary doesn't have the chroot-directory prefixed
+    - call dpkg --assert-multi-arch with execvp instead of execv
+    - save the universe by not printing messages about apport if a package
+      with this name is not installed (Closes: #619646)
+    - handle a SIGINT in all modes as a break after the currently running
+      dpkg transaction instead of ignoring it completely
   * apt-pkg/depcache.cc:
   * apt-pkg/depcache.cc:
     - if a M-A:same package is marked for reinstall, mark all it's installed
     - if a M-A:same package is marked for reinstall, mark all it's installed
       silbings for reinstallation as well (LP: #859188)
       silbings for reinstallation as well (LP: #859188)
@@ -13,8 +38,35 @@ apt (0.8.16~exp13) UNRELEASED; urgency=low
     - if a file without an extension is requested send an 'Accept: text/*'
     - if a file without an extension is requested send an 'Accept: text/*'
       header to avoid that the server chooses unsupported compressed files
       header to avoid that the server chooses unsupported compressed files
       in a content-negotation attempt (Closes: #657560)
       in a content-negotation attempt (Closes: #657560)
+    - remove the arbitrary MAXLEN limit for response lines (Closes: #658346)
   * apt-pkg/aptconfiguration.cc:
   * apt-pkg/aptconfiguration.cc:
     - chroot if needed before calling dpkg --print-foreign-architectures
     - chroot if needed before calling dpkg --print-foreign-architectures
+    - ensure that architectures are not added multiple times
+  * cmdline/apt-mark.cc:
+    - detect if dpkg has multiarch support before calling --set-selections
+    - correctly ignore already (un)hold packages
+  * apt-pkg/cachefile.cc:
+    - clean up lost atomic cachefiles with 'clean' (Closes: #650513)
+  * apt-pkg/indexrecords.cc:
+    - do not create empty Entries as a sideeffect of Lookup()
+  * apt-pkg/acquire-item.cc:
+    - drop support for i18n/Index file (introduced in 0.8.11) and use
+      the Release file instead to get the Translations (Closes: #649314)
+    - use pdiff for Translation-* files if available (Closes: #657902)
+  * ftparchive/writer.cc:
+    - add 'Translation-*' to the default patterns
+  * cmdline/apt-get.cc:
+    - if a package can't be removed as it is not installed, suggest to
+      the user an (installed) multiarch silbing with 'Did you mean?'
+    - improve 'error' message for packages which are only referenced
+      e.g. in a Depends line and are now requested for removal
+  * cmdline/apt-cache.cc:
+    - correct --pre-depends option by using dash consistently (LP: #940837)
+  * apt-pkg/packagemanager.cc:
+    - do not try to a void a breaks if the broken package pre-depends
+      on the breaker, but let dpkg auto-deconfigure it
+  * apt-pkg/contrib/fileutl.cc:
+    - do not warn about the ignoring of directories (Closes: #662762)
 
 
   [ Steve Langasek ]
   [ Steve Langasek ]
   * cmdline/apt-get.cc:
   * cmdline/apt-get.cc:
@@ -27,7 +79,9 @@ apt (0.8.16~exp13) UNRELEASED; urgency=low
       of them in a single iteration (Closes: #657695, LP: #922485)
       of them in a single iteration (Closes: #657695, LP: #922485)
     - use a signed int instead of short for score calculation as upgrades
     - use a signed int instead of short for score calculation as upgrades
       become so big now that it can overflow (Closes: #657732, LP: #917173)
       become so big now that it can overflow (Closes: #657732, LP: #917173)
-  
+  * Fix IndexCopy::CopyPackages and TranslationsCopy::CopyTranslations to
+    handle compressed files again (LP: #924182, closes: #658096)
+
   [ Michael Vogt ]
   [ Michael Vogt ]
   * apt-pkg/deb/dpkgpm.cc:
   * apt-pkg/deb/dpkgpm.cc:
     - fix crash when a package is in removed but residual config state
     - fix crash when a package is in removed but residual config state
@@ -35,10 +89,20 @@ apt (0.8.16~exp13) UNRELEASED; urgency=low
   * apt-pkg/contrib/fileutl.h:
   * apt-pkg/contrib/fileutl.h:
     - fix compat with FileFd::OpenDescriptor() in ReadOnlyGzip mode
     - fix compat with FileFd::OpenDescriptor() in ReadOnlyGzip mode
   * apt-pkg/packagemanager.cc:
   * apt-pkg/packagemanager.cc:
-    - when calculating pre-dependencies ensure that both unpack and
-      configure are considered (instead of only configure) LP: #927993
+    - fix bug in predepends handling - ensure that packages that needs
+      unpackaging are unpacked before they are configured (LP: #927993)
+
+  [ Julian Andres Klode ]
+  * apt-pkg/deb/deblistparser.cc:
+    - Set the Essential flag on APT instead of only Important
+  * apt-pkg/packagemanager.cc:
+    - Do not use immediate configuration for packages with the Important flag
+  * Treat the Important flag like the Essential flag with those differences:
+    - No Immediate configuration (see above)
+    - Not automatically installed during dist-upgrade
+    - No higher score for installation ordering
 
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Mon, 30 Jan 2012 19:17:09 +0100
+ -- Michael Vogt <mvo@debian.org>  Tue, 06 Mar 2012 18:12:57 +0100
 
 
 apt (0.8.16~exp12) experimental; urgency=low
 apt (0.8.16~exp12) experimental; urgency=low
 
 

+ 3 - 2
ftparchive/cachedb.h

@@ -126,7 +126,8 @@ class CacheDB
          Misses += S.Misses; 
          Misses += S.Misses; 
          DeLinkBytes += S.DeLinkBytes;
          DeLinkBytes += S.DeLinkBytes;
       };
       };
-      Stats() : Bytes(0), MD5Bytes(0), SHA1Bytes(0), SHA256Bytes(0), Packages(0), Misses(0), DeLinkBytes(0) {};
+      Stats() : Bytes(0), MD5Bytes(0), SHA1Bytes(0), SHA256Bytes(0),
+		SHA512Bytes(0),Packages(0), Misses(0), DeLinkBytes(0) {};
    } Stats;
    } Stats;
    
    
    bool ReadyDB(std::string const &DB);
    bool ReadyDB(std::string const &DB);
@@ -142,7 +143,7 @@ class CacheDB
    
    
    bool Clean();
    bool Clean();
    
    
-   CacheDB(std::string const &DB) : Dbp(0), Fd(NULL), DebFile(0) {ReadyDB(DB);};
+   CacheDB(std::string const &DB) : Dbp(0), Fd(NULL), DebFile(0) {TmpKey[0]='\0'; ReadyDB(DB);};
    ~CacheDB() {ReadyDB(std::string()); delete DebFile;};
    ~CacheDB() {ReadyDB(std::string()); delete DebFile;};
 };
 };
     
     

+ 1 - 0
ftparchive/writer.cc

@@ -941,6 +941,7 @@ ReleaseWriter::ReleaseWriter(string const &DB)
       AddPattern("Packages.bz2");
       AddPattern("Packages.bz2");
       AddPattern("Packages.lzma");
       AddPattern("Packages.lzma");
       AddPattern("Packages.xz");
       AddPattern("Packages.xz");
+      AddPattern("Translation-*");
       AddPattern("Sources");
       AddPattern("Sources");
       AddPattern("Sources.gz");
       AddPattern("Sources.gz");
       AddPattern("Sources.bz2");
       AddPattern("Sources.bz2");

+ 4 - 5
methods/ftp.cc

@@ -77,6 +77,7 @@ FTPConn::FTPConn(URI Srv) : Len(0), ServerFd(-1), DataFd(-1),
 {
 {
    Debug = _config->FindB("Debug::Acquire::Ftp",false);
    Debug = _config->FindB("Debug::Acquire::Ftp",false);
    PasvAddr = 0;
    PasvAddr = 0;
+   Buffer[0] = '\0';
 }
 }
 									/*}}}*/
 									/*}}}*/
 // FTPConn::~FTPConn - Destructor					/*{{{*/
 // FTPConn::~FTPConn - Destructor					/*{{{*/
@@ -621,8 +622,7 @@ bool FTPConn::ExtGoPasv()
    }
    }
    
    
    // Get a new passive address.
    // Get a new passive address.
-   int Res;
-   if ((Res = getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr)) != 0)
+   if (getaddrinfo(IP.c_str(),PStr,&Hints,&PasvAddr) != 0)
       return true;
       return true;
    
    
    return true;
    return true;
@@ -720,14 +720,13 @@ bool FTPConn::CreateDataFd()
    DataListenFd = -1;
    DataListenFd = -1;
 
 
    // Get the information for a listening socket.
    // Get the information for a listening socket.
-   struct addrinfo *BindAddr = 0;
+   struct addrinfo *BindAddr = NULL;
    struct addrinfo Hints;
    struct addrinfo Hints;
    memset(&Hints,0,sizeof(Hints));
    memset(&Hints,0,sizeof(Hints));
    Hints.ai_socktype = SOCK_STREAM;
    Hints.ai_socktype = SOCK_STREAM;
    Hints.ai_flags |= AI_PASSIVE;
    Hints.ai_flags |= AI_PASSIVE;
    Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
    Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
-   int Res;
-   if ((Res = getaddrinfo(0,"0",&Hints,&BindAddr)) != 0)
+   if (getaddrinfo(0,"0",&Hints,&BindAddr) != 0 || BindAddr == NULL)
       return _error->Error(_("getaddrinfo was unable to get a listening socket"));
       return _error->Error(_("getaddrinfo was unable to get a listening socket"));
    
    
    // Construct the socket
    // Construct the socket

+ 9 - 11
methods/http.cc

@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <errno.h>
 #include <errno.h>
 #include <string.h>
 #include <string.h>
+#include <climits>
 #include <iostream>
 #include <iostream>
 #include <map>
 #include <map>
 
 
@@ -534,10 +535,6 @@ bool ServerState::HeaderLine(string Line)
    if (Line.empty() == true)
    if (Line.empty() == true)
       return true;
       return true;
 
 
-   // The http server might be trying to do something evil.
-   if (Line.length() >= MAXLEN)
-      return _error->Error(_("Got a single header line over %u chars"),MAXLEN);
-
    string::size_type Pos = Line.find(' ');
    string::size_type Pos = Line.find(' ');
    if (Pos == string::npos || Pos+1 > Line.length())
    if (Pos == string::npos || Pos+1 > Line.length())
    {
    {
@@ -561,7 +558,7 @@ bool ServerState::HeaderLine(string Line)
       // Evil servers return no version
       // Evil servers return no version
       if (Line[4] == '/')
       if (Line[4] == '/')
       {
       {
-	 int const elements = sscanf(Line.c_str(),"HTTP/%u.%u %u%[^\n]",&Major,&Minor,&Result,Code);
+	 int const elements = sscanf(Line.c_str(),"HTTP/%3u.%3u %3u%359[^\n]",&Major,&Minor,&Result,Code);
 	 if (elements == 3)
 	 if (elements == 3)
 	 {
 	 {
 	    Code[0] = '\0';
 	    Code[0] = '\0';
@@ -575,7 +572,7 @@ bool ServerState::HeaderLine(string Line)
       {
       {
 	 Major = 0;
 	 Major = 0;
 	 Minor = 9;
 	 Minor = 9;
-	 if (sscanf(Line.c_str(),"HTTP %u%[^\n]",&Result,Code) != 2)
+	 if (sscanf(Line.c_str(),"HTTP %3u%359[^\n]",&Result,Code) != 2)
 	    return _error->Error(_("The HTTP server sent an invalid reply header"));
 	    return _error->Error(_("The HTTP server sent an invalid reply header"));
       }
       }
 
 
@@ -585,7 +582,7 @@ bool ServerState::HeaderLine(string Line)
 	 Persistent = false;
 	 Persistent = false;
       else
       else
       {
       {
-	 if (Major == 1 && Minor <= 0)
+	 if (Major == 1 && Minor == 0)
 	    Persistent = false;
 	    Persistent = false;
 	 else
 	 else
 	    Persistent = true;
 	    Persistent = true;
@@ -603,9 +600,10 @@ bool ServerState::HeaderLine(string Line)
       // The length is already set from the Content-Range header
       // The length is already set from the Content-Range header
       if (StartPos != 0)
       if (StartPos != 0)
 	 return true;
 	 return true;
-      
-      if (sscanf(Val.c_str(),"%llu",&Size) != 1)
-	 return _error->Error(_("The HTTP server sent an invalid Content-Length header"));
+
+      Size = strtoull(Val.c_str(), NULL, 10);
+      if (Size == ULLONG_MAX)
+	 return _error->Errno("HeaderLine", _("The HTTP server sent an invalid Content-Length header"));
       return true;
       return true;
    }
    }
 
 
@@ -1329,7 +1327,7 @@ int HttpMethod::Loop()
                after the same URI is seen twice in a queue item. */
                after the same URI is seen twice in a queue item. */
             StringVector &R = Redirected[Queue->DestFile];
             StringVector &R = Redirected[Queue->DestFile];
             bool StopRedirects = false;
             bool StopRedirects = false;
-            if (R.size() == 0)
+            if (R.empty() == true)
                R.push_back(Queue->Uri);
                R.push_back(Queue->Uri);
             else if (R[0] == "STOP" || R.size() > 10)
             else if (R[0] == "STOP" || R.size() > 10)
                StopRedirects = true;
                StopRedirects = true;

+ 5 - 6
methods/http.h

@@ -11,8 +11,6 @@
 #ifndef APT_HTTP_H
 #ifndef APT_HTTP_H
 #define APT_HTTP_H
 #define APT_HTTP_H
 
 
-#define MAXLEN 360
-
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/strutl.h>
 
 
 #include <string>
 #include <string>
@@ -92,7 +90,7 @@ struct ServerState
    unsigned int Major;
    unsigned int Major;
    unsigned int Minor;
    unsigned int Minor;
    unsigned int Result;
    unsigned int Result;
-   char Code[MAXLEN];
+   char Code[360];
    
    
    // These are some statistics from the last parsed header lines
    // These are some statistics from the last parsed header lines
    unsigned long long Size;
    unsigned long long Size;
@@ -117,9 +115,10 @@ struct ServerState
   
   
    bool HeaderLine(std::string Line);
    bool HeaderLine(std::string Line);
    bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
    bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
-   void Reset() {Major = 0; Minor = 0; Result = 0; Size = 0; StartPos = 0;
-                 Encoding = Closes; time(&Date); ServerFd = -1; 
-                 Pipeline = true;};
+   void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0;
+		 StartPos = 0; Encoding = Closes; time(&Date); HaveContent = false;
+		 State = Header; Persistent = false; ServerFd = -1;
+		 Pipeline = true;};
 
 
    /** \brief Result of the header acquire */
    /** \brief Result of the header acquire */
    enum RunHeadersResult {
    enum RunHeadersResult {

+ 2 - 4
methods/https.h

@@ -8,10 +8,8 @@
    ##################################################################### */
    ##################################################################### */
 									/*}}}*/
 									/*}}}*/
 
 
-#ifndef APT_HTTP_H
-#define APT_HTTP_H
-
-#define MAXLEN 360
+#ifndef APT_HTTPS_H
+#define APT_HTTPS_H
 
 
 #include <iostream>
 #include <iostream>
 #include <curl/curl.h>
 #include <curl/curl.h>

+ 1 - 1
methods/mirror.cc

@@ -147,7 +147,7 @@ bool MirrorMethod::DownloadMirrorFile(string mirror_uri_str)
    // append all architectures
    // append all architectures
    std::vector<std::string> vec = APT::Configuration::getArchitectures();
    std::vector<std::string> vec = APT::Configuration::getArchitectures();
    for (std::vector<std::string>::const_iterator I = vec.begin();
    for (std::vector<std::string>::const_iterator I = vec.begin();
-        I != vec.end(); I++)
+        I != vec.end(); ++I)
       if (I == vec.begin())
       if (I == vec.begin())
          fetch += "?arch" + (*I);
          fetch += "?arch" + (*I);
       else
       else

+ 3 - 1
methods/rsh.cc

@@ -42,7 +42,9 @@ int RSHMethod::FailFd = -1;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 RSHConn::RSHConn(URI Srv) : Len(0), WriteFd(-1), ReadFd(-1),
 RSHConn::RSHConn(URI Srv) : Len(0), WriteFd(-1), ReadFd(-1),
-                            ServerName(Srv), Process(-1) {}
+                            ServerName(Srv), Process(-1) {
+   Buffer[0] = '\0';
+}
 									/*}}}*/
 									/*}}}*/
 // RSHConn::RSHConn - Destructor					/*{{{*/
 // RSHConn::RSHConn - Destructor					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------

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

@@ -1,42 +0,0 @@
-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]

+ 50 - 22
test/integration/framework

@@ -29,7 +29,8 @@ msgtest() {
 	while [ -n "$1" ]; do
 	while [ -n "$1" ]; do
 		echo -n "${CINFO}$1${CCMD} " >&2;
 		echo -n "${CINFO}$1${CCMD} " >&2;
 		echo -n "$(echo "$2" | sed -e 's/^aptc/apt-c/' -e 's/^aptg/apt-g/' -e 's/^aptf/apt-f/')${CINFO} " >&2;
 		echo -n "$(echo "$2" | sed -e 's/^aptc/apt-c/' -e 's/^aptg/apt-g/' -e 's/^aptf/apt-f/')${CINFO} " >&2;
-		shift 2
+		shift
+		if [ -n "$1" ]; then shift; else break; fi
 	done
 	done
 	echo -n "…${CNORMAL} " >&2;
 	echo -n "…${CNORMAL} " >&2;
 }
 }
@@ -114,9 +115,9 @@ addtrap() {
 
 
 setupenvironment() {
 setupenvironment() {
 	TMPWORKINGDIRECTORY=$(mktemp -d)
 	TMPWORKINGDIRECTORY=$(mktemp -d)
-	local TESTDIR=$(readlink -f $(dirname $0))
+	TESTDIRECTORY=$(readlink -f $(dirname $0))
 	msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… "
 	msgninfo "Preparing environment for ${CCMD}$(basename $0)${CINFO} in ${TMPWORKINGDIRECTORY}… "
-	BUILDDIRECTORY="${TESTDIR}/../../build/bin"
+	BUILDDIRECTORY="${TESTDIRECTORY}/../../build/bin"
 	test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
 	test -x "${BUILDDIRECTORY}/apt-get" || msgdie "You need to build tree first"
 	local OLDWORKINGDIRECTORY=$(pwd)
 	local OLDWORKINGDIRECTORY=$(pwd)
 	addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;"
 	addtrap "cd /; rm -rf $TMPWORKINGDIRECTORY; cd $OLDWORKINGDIRECTORY;"
@@ -126,25 +127,19 @@ setupenvironment() {
 	mkdir -p etc/apt/apt.conf.d etc/apt/sources.list.d etc/apt/trusted.gpg.d etc/apt/preferences.d
 	mkdir -p etc/apt/apt.conf.d etc/apt/sources.list.d etc/apt/trusted.gpg.d etc/apt/preferences.d
 	mkdir -p var/cache var/lib var/log
 	mkdir -p var/cache var/lib var/log
 	mkdir -p var/lib/dpkg/info var/lib/dpkg/updates var/lib/dpkg/triggers
 	mkdir -p var/lib/dpkg/info var/lib/dpkg/updates var/lib/dpkg/triggers
-	local STATUSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/status-/' -e 's/^skip-/status-/')
-	if [ -f "${TESTDIR}/${STATUSFILE}" ]; then
-		cp "${TESTDIR}/${STATUSFILE}" var/lib/dpkg/status
-	else
-		touch var/lib/dpkg/status
-	fi
 	touch var/lib/dpkg/available
 	touch var/lib/dpkg/available
 	mkdir -p usr/lib/apt
 	mkdir -p usr/lib/apt
 	ln -s ${BUILDDIRECTORY}/methods usr/lib/apt/methods
 	ln -s ${BUILDDIRECTORY}/methods usr/lib/apt/methods
 	cd ..
 	cd ..
 	local PACKAGESFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Packages-/' -e 's/^skip-/Packages-/')
 	local PACKAGESFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Packages-/' -e 's/^skip-/Packages-/')
-	if [ -f "${TESTDIR}/${PACKAGESFILE}" ]; then
-		cp "${TESTDIR}/${PACKAGESFILE}" aptarchive/Packages
+	if [ -f "${TESTDIRECTORY}/${PACKAGESFILE}" ]; then
+		cp "${TESTDIRECTORY}/${PACKAGESFILE}" aptarchive/Packages
 	fi
 	fi
 	local SOURCESSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Sources-/' -e 's/^skip-/Sources-/')
 	local SOURCESSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/Sources-/' -e 's/^skip-/Sources-/')
-	if [ -f "${TESTDIR}/${SOURCESSFILE}" ]; then
-		cp "${TESTDIR}/${SOURCESSFILE}" aptarchive/Sources
+	if [ -f "${TESTDIRECTORY}/${SOURCESSFILE}" ]; then
+		cp "${TESTDIRECTORY}/${SOURCESSFILE}" aptarchive/Sources
 	fi
 	fi
-	cp $(find $TESTDIR -name '*.pub' -o -name '*.sec') keys/
+	cp $(find $TESTDIRECTORY -name '*.pub' -o -name '*.sec') keys/
 	ln -s ${TMPWORKINGDIRECTORY}/keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
 	ln -s ${TMPWORKINGDIRECTORY}/keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg
 	echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf
 	echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf
 	echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf
 	echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf
@@ -156,7 +151,9 @@ setupenvironment() {
 	echo "DPKG::options:: \"--root=${TMPWORKINGDIRECTORY}/rootdir\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--root=${TMPWORKINGDIRECTORY}/rootdir\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-not-root\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-not-root\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-bad-path\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--force-bad-path\";" >> aptconfig.conf
-	echo "DPKG::options:: \"--force-architecture\";" >> aptconfig.conf # Added to test multiarch before dpkg is ready for it…
+	if ! $(which dpkg) --assert-multi-arch; then
+		echo "DPKG::options:: \"--force-architecture\";" >> aptconfig.conf # Added to test multiarch before dpkg is ready for it…
+	fi
 	echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
 	echo "DPKG::options:: \"--log=${TMPWORKINGDIRECTORY}/rootdir/var/log/dpkg.log\";" >> aptconfig.conf
 	echo 'quiet::NoUpdate "true";' >> aptconfig.conf
 	echo 'quiet::NoUpdate "true";' >> aptconfig.conf
 	export LC_ALL=C
 	export LC_ALL=C
@@ -170,13 +167,17 @@ getarchitecture() {
 		if [ -n "$ARCH" ]; then
 		if [ -n "$ARCH" ]; then
 			echo $ARCH
 			echo $ARCH
 		else
 		else
-			dpkg-architecture -qDEB_BUILD_ARCH
+			dpkg --print-architecture
 		fi
 		fi
 	else
 	else
 		echo $1
 		echo $1
 	fi
 	fi
 }
 }
 
 
+getarchitectures() {
+	echo "$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+}
+
 configarchitecture() {
 configarchitecture() {
 	local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf
 	local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf
 	rm -f $CONFFILE
 	rm -f $CONFFILE
@@ -186,6 +187,30 @@ configarchitecture() {
 		echo "APT::Architectures:: \"$(getarchitecture $1)\";" >> $CONFFILE
 		echo "APT::Architectures:: \"$(getarchitecture $1)\";" >> $CONFFILE
 		shift
 		shift
 	done
 	done
+	configdpkg
+}
+
+configdpkg() {
+	if [ ! -e rootdir/var/lib/dpkg/status ]; then
+		local STATUSFILE=$(echo "$(basename $0)" | sed -e 's/^test-/status-/' -e 's/^skip-/status-/')
+		if [ -f "${TESTDIRECTORY}/${STATUSFILE}" ]; then
+			cp "${TESTDIRECTORY}/${STATUSFILE}" rootdir/var/lib/dpkg/status
+		else
+			echo -n > rootdir/var/lib/dpkg/status
+		fi
+	fi
+	if $(which dpkg) --assert-multi-arch; then
+		local ARCHS="$(getarchitectures)"
+		if echo "$ARCHS" | grep -E -q '[^ ]+ [^ ]+'; then
+			DPKGARCH="$(dpkg --print-architecture)"
+			for ARCH in ${ARCHS}; do
+				if [ "${ARCH}" != "${DPKGARCH}" ]; then dpkg --add-architecture ${ARCH}; fi
+			done
+			if [ "0" = "$(dpkg -l dpkg 2> /dev/null | grep '^i' | wc -l)" ]; then
+				insertinstalledpackage 'dpkg' "all" '1.16.2~wipmultiarch~fake'
+			fi
+		fi
+	fi
 }
 }
 
 
 setupsimplenativepackage() {
 setupsimplenativepackage() {
@@ -350,7 +375,7 @@ createaptftparchiveconfig() {
 	local ARCHS="$(find pool/ -name '*.deb' | grep -oE '_[a-z0-9-]+\.deb$' | sort | uniq | sed -e '/^_all.deb$/ d' -e 's#^_\([a-z0-9-]*\)\.deb$#\1#' | tr '\n' ' ')"
 	local ARCHS="$(find pool/ -name '*.deb' | grep -oE '_[a-z0-9-]+\.deb$' | sort | uniq | sed -e '/^_all.deb$/ d' -e 's#^_\([a-z0-9-]*\)\.deb$#\1#' | tr '\n' ' ')"
 	if [ -z "$ARCHS" ]; then
 	if [ -z "$ARCHS" ]; then
 		# the pool is empty, so we will operate on faked packages - let us use the configured archs
 		# the pool is empty, so we will operate on faked packages - let us use the configured archs
-		ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+		ARCHS="$(getarchitectures)"
 	fi
 	fi
 	echo -n 'Dir {
 	echo -n 'Dir {
 	ArchiveDir "' >> ftparchive.conf
 	ArchiveDir "' >> ftparchive.conf
@@ -432,7 +457,7 @@ insertpackage() {
 	local ARCHS=""
 	local ARCHS=""
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 		if [ "$arch" = "all" ]; then
 		if [ "$arch" = "all" ]; then
-			ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+			ARCHS="$(getarchitectures)"
 		else
 		else
 			ARCHS="$arch"
 			ARCHS="$arch"
 		fi
 		fi
@@ -486,7 +511,8 @@ insertinstalledpackage() {
 	local VERSION="$3"
 	local VERSION="$3"
 	local DEPENDENCIES="$4"
 	local DEPENDENCIES="$4"
 	local PRIORITY="${5:-optional}"
 	local PRIORITY="${5:-optional}"
-	local FILE="rootdir/var/lib/dpkg/status"
+	local FILE='rootdir/var/lib/dpkg/status'
+	local INFO='rootdir/var/lib/dpkg/info'
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 		echo "Package: $NAME
 		echo "Package: $NAME
 Status: install ok installed
 Status: install ok installed
@@ -502,6 +528,11 @@ Version: $VERSION" >> $FILE
  YOU did something horribly wrong! They are autogenerated
  YOU did something horribly wrong! They are autogenerated
  und used only by testcases for APT and surf no other propose…
  und used only by testcases for APT and surf no other propose…
 " >> $FILE
 " >> $FILE
+		if [ "$(dpkg-query -W --showformat='${Multi-Arch}')" = 'same' ]; then
+			echo -n > ${INFO}/${NAME}:${arch}.list
+		else
+			echo -n > ${INFO}/${NAME}.list
+		fi
 	done
 	done
 }
 }
 
 
@@ -542,9 +573,6 @@ generatereleasefiles() {
 	# both should be given in notation date/touch can understand
 	# both should be given in notation date/touch can understand
 	msgninfo "\tGenerate Release files… "
 	msgninfo "\tGenerate Release files… "
 	if [ -e aptarchive/dists ]; then
 	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
 		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
 			local SUITE="$(echo "$dir" | cut -d'/' -f 4)"
 			local SUITE="$(echo "$dir" | cut -d'/' -f 4)"
 			local CODENAME="$(getcodenamefromsuite $SUITE)"
 			local CODENAME="$(getcodenamefromsuite $SUITE)"

+ 21 - 0
test/integration/skip-avoid-avoiding-breaks-predepends

@@ -0,0 +1,21 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'native'
+
+insertinstalledpackage 'looping' 'native' '1'
+insertinstalledpackage 'loop1' 'native' '1' 'Depends: loop2 (= 1)'
+insertinstalledpackage 'loop2' 'native' '1' 'Depends: loop1 (= 1)'
+
+buildsimplenativepackage 'looping' 'native' '1.15.7.2' 'stable' 'Breaks: loop2 (<= 1)'
+buildsimplenativepackage 'loop1' 'native' '2' 'stable' 'Depends: loop2 (= 2)'
+buildsimplenativepackage 'loop2' 'native' '2' 'stable' 'Depends: loop1 (= 2)
+Pre-Depends: looping (>= 1.15)'
+
+setupaptarchive
+
+aptget dist-upgrade -y -o Debug::pkgOrderList=1 #-qq 2>&1 > /dev/null
+testdpkginstalled looping loop1 loop2

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

@@ -1,33 +0,0 @@
-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

+ 3 - 3
test/integration/test-bug-549968-install-depends-of-not-installed

@@ -14,13 +14,13 @@ setupaptarchive
 
 
 # We check the Markers here as the autoremove nuker will also
 # We check the Markers here as the autoremove nuker will also
 # prevent it, but to late - its better to fail earlier
 # prevent it, but to late - its better to fail earlier
-testequal 'Reading package lists...
+testequal "Reading package lists...
 Building dependency tree...
 Building dependency tree...
   MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1
   MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1
     Ignore MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) as its mode (Keep) is protected
     Ignore MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) as its mode (Keep) is protected
-Package extracoolstuff is not installed, so not removed
+Package 'extracoolstuff' is not installed, so not removed
 The following NEW packages will be installed:
 The following NEW packages will be installed:
   coolstuff
   coolstuff
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
 Inst coolstuff (1.0 unstable [all])
 Inst coolstuff (1.0 unstable [all])
-Conf coolstuff (1.0 unstable [all])' aptget install coolstuff extracoolstuff- -o Debug::pkgDepCache::Marker=1 -s
+Conf coolstuff (1.0 unstable [all])" aptget install coolstuff extracoolstuff- -o Debug::pkgDepCache::Marker=1 -s

+ 17 - 6
test/integration/test-bug-612099-multiarch-conflicts

@@ -16,7 +16,7 @@ buildsimplenativepackage 'foobar' 'amd64' '1.0' 'stable' 'Depends: libc6'
 setupaptarchive
 setupaptarchive
 
 
 aptget install libc6:i386 -t stable -y -qq 2>&1 > /dev/null
 aptget install libc6:i386 -t stable -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6
+testdpkginstalled libc6:i386
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
 Reading state information...
 Reading state information...
@@ -75,8 +75,13 @@ The following packages will be upgraded:
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 Inst libc6 [1.0] (2.0 testing [all])
 Inst libc6 [1.0] (2.0 testing [all])
 Conf libc6 (2.0 testing [all])' aptget upgrade -t testing -s
 Conf libc6 (2.0 testing [all])' aptget upgrade -t testing -s
-aptget upgrade -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6
+# FIXME: on amd64 systems this test wouldn't run with a real upgrade
+# as APT (here i386) disagree about the native architecture, so
+# we fake it here:
+#aptget upgrade -y -qq 2>&1 > /dev/null
+aptget purge libc6 -y -qq 2>&1 >/dev/null
+aptget install libc6:i386 -y -qq 2>&1 >/dev/null
+testdpkginstalled libc6:all
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
@@ -125,7 +130,7 @@ buildsimplenativepackage 'foobar-same' 'amd64' '1.0' 'stable' 'Depends: libc6-sa
 setupaptarchive
 setupaptarchive
 
 
 aptget install libc6-same:i386 -t stable -y -qq 2>&1 > /dev/null
 aptget install libc6-same:i386 -t stable -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6-same
+testdpkginstalled libc6-same:i386
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
@@ -168,8 +173,14 @@ The following packages will be upgraded:
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 Inst libc6-same [1.0] (2.0 testing [all])
 Inst libc6-same [1.0] (2.0 testing [all])
 Conf libc6-same (2.0 testing [all])' aptget upgrade -t testing -s
 Conf libc6-same (2.0 testing [all])' aptget upgrade -t testing -s
-aptget upgrade -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6-same
+# FIXME: on amd64 systems this test wouldn't run with a real upgrade
+# as APT (here i386) disagree about the native architecture, so
+# we fake it here:
+#aptget upgrade -y -qq 2>&1 > /dev/null
+aptget purge libc6-same -y -qq 2>&1 >/dev/null
+aptget install libc6-same:i386 -y -qq 2>&1 >/dev/null
+testdpkginstalled libc6-same:all
+
 
 
 testequal "Reading package lists...
 testequal "Reading package lists...
 Building dependency tree...
 Building dependency tree...

+ 17 - 25
test/integration/test-bug-618288-multiarch-same-lockstep

@@ -16,30 +16,22 @@ buildsimplenativepackage 'apt' 'i386' '2' 'unstable' 'Depends: libsame (= 2)' ''
 buildsimplenativepackage 'apt2' 'amd64' '2' 'unstable' 'Depends: libsame (= 2)' '' 'required'
 buildsimplenativepackage 'apt2' 'amd64' '2' 'unstable' 'Depends: libsame (= 2)' '' 'required'
 
 
 setupaptarchive
 setupaptarchive
+aptget dist-upgrade -s 2>&1 > output.apt
 
 
 # order in switch libsame:{amd64,i386} are unpacked is irrelevant, as both are installed - but we need to do it together
 # order in switch libsame:{amd64,i386} are unpacked is irrelevant, as both are installed - but we need to do it together
-testequalor2 'Reading package lists...
-Building dependency tree...
-The following packages will be upgraded:
-  apt:i386 apt2 libsame libsame:i386
-4 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
-Inst libsame:i386 [1] (2 unstable [i386]) [libsame:amd64 on libsame:i386] [libsame:i386 on libsame:amd64] [libsame:amd64 apt:i386 ]
-Inst libsame [1] (2 unstable [amd64]) [apt2:amd64 apt:i386 ]
-Conf libsame:i386 (2 unstable [i386]) [apt2:amd64 apt:i386 ]
-Conf libsame (2 unstable [amd64]) [apt2:amd64 apt:i386 ]
-Inst apt2 [1] (2 unstable [amd64]) [apt:i386 ]
-Conf apt2 (2 unstable [amd64]) [apt:i386 ]
-Inst apt:i386 [1] (2 unstable [i386])
-Conf apt:i386 (2 unstable [i386])' 'Reading package lists...
-Building dependency tree...
-The following packages will be upgraded:
-  apt:i386 apt2 libsame libsame:i386
-4 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
-Inst libsame [1] (2 unstable [amd64]) [libsame:amd64 on libsame:i386] [libsame:i386 on libsame:amd64] [libsame:i386 apt2:amd64 ]
-Inst libsame:i386 [1] (2 unstable [i386]) [apt2:amd64 apt:i386 ]
-Conf libsame:i386 (2 unstable [i386]) [apt2:amd64 apt:i386 ]
-Conf libsame (2 unstable [amd64]) [apt2:amd64 apt:i386 ]
-Inst apt2 [1] (2 unstable [amd64]) [apt:i386 ]
-Conf apt2 (2 unstable [amd64]) [apt:i386 ]
-Inst apt:i386 [1] (2 unstable [i386])
-Conf apt:i386 (2 unstable [i386])' aptget dist-upgrade -s
+LS_U_AMD="$(grep -o -n '^Inst libsame ' output.apt | cut -d: -f1)"
+LS_U_INT="$(grep -o -n '^Inst libsame:i386 ' output.apt | cut -d: -f1)"
+LS_C_AMD="$(grep -o -n '^Conf libsame ' output.apt | cut -d: -f1)"
+LS_C_INT="$(grep -o -n '^Conf libsame:i386 ' output.apt | cut -d: -f1)"
+
+msgtest 'Test if libsame:amd64 unpack before configure'
+test "$LS_U_AMD" -lt "$LS_C_AMD" && msgpass || msgfail
+
+msgtest 'Test if libsame:i386 unpack before configure'
+test "$LS_U_INT" -lt "$LS_C_INT" && msgpass || msgfail
+
+msgtest 'Test if libsame:amd64 unpack is before libsame:i386 configure'
+test "$LS_U_AMD" -lt "$LS_C_INT" && msgpass || msgfail
+
+msgtest 'Test if libsame:i386 unpack is before libsame:amd64 configure'
+test "$LS_U_INT" -lt "$LS_C_AMD" && msgpass || msgfail

+ 1 - 8
test/integration/test-bug-624218-Translation-file-handling

@@ -42,16 +42,9 @@ msgtest 'Download of nothing if none is forced' 'with Index'
 aptget update -o Acquire::Languages=none | grep -q -e 'Translation' && msgfail || msgpass
 aptget update -o Acquire::Languages=none | grep -q -e 'Translation' && msgfail || msgpass
 rm -rf rootdir/var/lib/apt/lists
 rm -rf rootdir/var/lib/apt/lists
 
 
-sed -i '/i18n\/Index$/ d' $(find aptarchive -name 'Release')
+sed -i '/i18n\/Translation-.*$/ d' $(find aptarchive -name 'Release')
 signreleasefiles
 signreleasefiles
 
 
-# we have to try as not every archive includes the i18n Index in the Release file - if it has one at all
-msgtest 'Download no Translation- if forced language is non-existent' 'with not-announced Index'
-aptget update -o Acquire::Languages=ast_DE | grep -q -e 'Translation-' && msgfail || msgpass
-rm -rf rootdir/var/lib/apt/lists
-
-find aptarchive -name 'Index' -delete
-
 msgtest 'Download of en as forced language' 'without Index'
 msgtest 'Download of en as forced language' 'without Index'
 aptget update -o Acquire::Languages=en | grep -q -e 'Translation-en ' && msgpass || msgfail
 aptget update -o Acquire::Languages=en | grep -q -e 'Translation-en ' && msgpass || msgfail
 rm -rf rootdir/var/lib/apt/lists
 rm -rf rootdir/var/lib/apt/lists

+ 15 - 5
test/integration/test-bug-64141-install-dependencies-for-on-hold

@@ -4,7 +4,19 @@ set -e
 TESTDIR=$(readlink -f $(dirname $0))
 TESTDIR=$(readlink -f $(dirname $0))
 . $TESTDIR/framework
 . $TESTDIR/framework
 setupenvironment
 setupenvironment
-configarchitecture "i386"
+configarchitecture 'native' 'strange-arch'
+
+insertpackage 'unstable' 'unrelated' 'strange-arch' '1'
+
+insertinstalledpackage 'apt' 'native' '0.8.9' 'Depends: libc6 (>= 2.3.4)'
+insertinstalledpackage 'libc6' 'native' '2.4.1-1'
+insertinstalledpackage 'oldcrap' 'all' '1-1'
+
+insertpackage 'unstable' 'apt' 'native' '0.8.10' 'Depends: libc6 (>= 2.10), libdb4.8
+Breaks: oldcrap'
+insertpackage 'unstable' 'libc6' 'native' '2.11.2-7'
+insertpackage 'unstable' 'libdb4.8' 'native' '4.8.30-3'
+
 setupaptarchive
 setupaptarchive
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
@@ -16,11 +28,10 @@ The following NEW packages will be installed:
 The following packages will be upgraded:
 The following packages will be upgraded:
   apt libc6
   apt libc6
 2 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
 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.
+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
 E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only
 
 
-echo 'apt hold' | dpkg --set-selections
+aptmark hold apt -qq
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
@@ -29,6 +40,5 @@ The following packages have been kept back:
 The following packages will be upgraded:
 The following packages will be upgraded:
   libc6
   libc6
 1 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
 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.
 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'
 E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only -o Test='hold-back-apt'

+ 6 - 5
test/integration/test-conflicts-loop

@@ -20,14 +20,15 @@ Building dependency tree...
 The following packages will be upgraded:
 The following packages will be upgraded:
   openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib
   openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib
 3 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
 3 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
-  openjdk-6-jre-lib conflicts with openjdk-6-jre
-    openjdk-6-jre conflicts with openjdk-6-jre-headless
-      openjdk-6-jre-headless conflicts with openjdk-6-jre
+  openjdk-6-jre-lib:i386 conflicts with openjdk-6-jre:i386
+    openjdk-6-jre:i386 conflicts with openjdk-6-jre-headless:i386
+      openjdk-6-jre-headless:i386 conflicts with openjdk-6-jre:i386
 Remv openjdk-6-jre [6b16-1.8-0ubuntu1]
 Remv openjdk-6-jre [6b16-1.8-0ubuntu1]
-      openjdk-6-jre-headless conflicts with openjdk-6-jre-lib
+      openjdk-6-jre-headless:i386 conflicts with openjdk-6-jre-lib:i386
 Remv openjdk-6-jre-lib [6b16-1.8-0ubuntu1]
 Remv openjdk-6-jre-lib [6b16-1.8-0ubuntu1]
 Inst openjdk-6-jre-headless [6b16-1.8-0ubuntu1] (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])
 Inst openjdk-6-jre-headless [6b16-1.8-0ubuntu1] (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])
-    openjdk-6-jre conflicts with openjdk-6-jre-lib
+    openjdk-6-jre:i386 conflicts with openjdk-6-jre-lib:i386
+    openjdk-6-jre:i386 conflicts with openjdk-6-jre-lib:i386
 Inst openjdk-6-jre [6b16-1.8-0ubuntu1] (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])
 Inst openjdk-6-jre [6b16-1.8-0ubuntu1] (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])
 Inst openjdk-6-jre-lib [6b16-1.8-0ubuntu1] (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])
 Inst openjdk-6-jre-lib [6b16-1.8-0ubuntu1] (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])
 Conf openjdk-6-jre-lib (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])
 Conf openjdk-6-jre-lib (6b20-1.9.8-0ubuntu1~10.04.1 unstable [i386])

+ 10 - 10
test/integration/test-pin-non-existent-package

@@ -6,7 +6,7 @@ TESTDIR=$(readlink -f $(dirname $0))
 setupenvironment
 setupenvironment
 configarchitecture "i386"
 configarchitecture "i386"
 
 
-insertpackage 'unstable' 'apt' 'i386' '0.8.15'
+insertpackage 'unstable' 'rapt' 'i386' '0.8.15'
 insertpackage 'unstable' 'arch' 'i386' '1.0'
 insertpackage 'unstable' 'arch' 'i386' '1.0'
 
 
 setupaptarchive
 setupaptarchive
@@ -22,40 +22,40 @@ testcandidate() {
 	fi
 	fi
 }
 }
 
 
-testcandidate apt '0.8.15'
+testcandidate rapt '0.8.15'
 testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0
 testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
-0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade --trivial-only
 
 
-echo 'Package: apt
+echo 'Package: rapt
 Pin: release a=unstable
 Pin: release a=unstable
 Pin-Priority: -1' > rootdir/etc/apt/preferences
 Pin-Priority: -1' > rootdir/etc/apt/preferences
 
 
-testcandidate apt '(none)'
+testcandidate rapt '(none)'
 testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0
 testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
-0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade --trivial-only
 
 
 echo '
 echo '
 Package: doesntexist
 Package: doesntexist
 Pin: release a=unstable
 Pin: release a=unstable
 Pin-Priority: 1000' >> rootdir/etc/apt/preferences
 Pin-Priority: 1000' >> rootdir/etc/apt/preferences
 
 
-testcandidate apt '(none)'
+testcandidate rapt '(none)'
 
 
 echo '
 echo '
-Package: apt
+Package: rapt
 Pin: release a=unstable
 Pin: release a=unstable
 Pin-Priority: 1000' >> rootdir/etc/apt/preferences
 Pin-Priority: 1000' >> rootdir/etc/apt/preferences
 
 
-testcandidate apt '(none)'
+testcandidate rapt '(none)'
 testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0
 testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0
 
 
 testequal 'Reading package lists...
 testequal 'Reading package lists...
 Building dependency tree...
 Building dependency tree...
-0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget dist-upgrade --trivial-only
 
 
 echo 'Package: arch:amd64
 echo 'Package: arch:amd64
 Pin: release a=unstable
 Pin: release a=unstable

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

@@ -153,6 +153,35 @@ runtest() {
 	installaptold
 	installaptold
 }
 }
 
 
+runtest2() {
+	prepare ${PKGFILE}
+	rm -rf rootdir/var/lib/apt/lists
+	signreleasefiles 'Joe Sixpack'
+	msgtest 'Cold archive signed by' 'Joe Sixpack'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+
+	# New .deb but now an unsigned archive. For example MITM to circumvent
+	# package verification.
+	prepare ${PKGFILE}-new
+	find aptarchive/ -name InRelease -delete
+	find aptarchive/ -name Release.gpg -delete
+	msgtest 'Warm archive signed by' 'nobody'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	failaptnew
+
+	# Unsigned archive from the beginning must also be detected.
+	rm -rf rootdir/var/lib/apt/lists
+	msgtest 'Cold archive signed by' 'nobody'
+	aptget update 2>&1 | grep -E '^(W|E): ' > /dev/null && msgfail || msgpass
+	testequal "$(cat ${PKGFILE}-new)
+" aptcache show apt
+	failaptnew
+}
+runtest2
+
+
 DELETEFILE="InRelease"
 DELETEFILE="InRelease"
 runtest
 runtest
 DELETEFILE="Release.gpg"
 DELETEFILE="Release.gpg"

+ 80 - 0
test/integration/test-suggest-installed-multiarch-silbing

@@ -0,0 +1,80 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64' 'i386' 'armel'
+
+insertinstalledpackage 'foo' 'i386' '1'
+insertpackage 'unstable' 'foo' 'amd64,i386' '1'
+
+insertinstalledpackage 'foo2' 'i386' '1'
+insertpackage 'unstable' 'foo2' 'i386' '1'
+
+insertinstalledpackage 'foo3' 'amd64' '1'
+insertpackage 'unstable' 'foo3' 'amd64,i386' '1'
+
+insertinstalledpackage 'samefoo' 'i386,amd64' '1' 'Multi-Arch: same'
+insertpackage 'unstable' 'samefoo' 'amd64,i386,armel' '1' 'Multi-Arch: same'
+
+insertinstalledpackage 'samefoo2' 'i386' '1' 'Multi-Arch: same'
+insertpackage 'unstable' 'samefoo2' 'amd64,i386,armel' '1' 'Multi-Arch: same'
+
+insertinstalledpackage 'mozplugger' 'i386' '1' 'Depends: iceweasel | fireweasel'
+insertinstalledpackage 'fireweasel' 'i386' '1'
+insertpackage 'unstable' 'mozplugger' 'i386,amd64' '1' 'Depends: iceweasel | fireweasel'
+
+setupaptarchive
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo' is not installed, so not removed. Did you mean 'foo:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove foo -s
+
+testequal "Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  foo2:i386
+0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
+Remv foo2:i386 [1]" aptget remove foo2 -s
+
+testequal "Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  foo3
+0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
+Remv foo3 [1]" aptget remove foo3 -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'foo3:i386' is not installed, so not removed. Did you mean 'foo3'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove foo3:i386 -s
+
+testequalor2 "Reading package lists...
+Building dependency tree...
+Package 'samefoo:armel' is not installed, so not removed. Did you mean 'samefoo'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." "Reading package lists...
+Building dependency tree...
+Package 'samefoo:armel' is not installed, so not removed. Did you mean 'samefoo:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove samefoo:armel -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'samefoo2' is not installed, so not removed. Did you mean 'samefoo2:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove samefoo2 -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'samefoo2:armel' is not installed, so not removed. Did you mean 'samefoo2:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove samefoo2:armel -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'iceweasel' is not installed, so not removed
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove iceweasel -s
+
+testequal "Reading package lists...
+Building dependency tree...
+Package 'fireweasel' is not installed, so not removed. Did you mean 'fireweasel:i386'?
+0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget remove fireweasel:amd64 -s