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

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
 	 if (fchmod(iFd,Itm.Mode) != 0)
 	 {
-	    _error->Errno("fchmod",_("Failed to write file %s"), Itm.Name);
 	    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)
 	 {
-	    return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
 	    close(iFd);
-	    return false;
+	    return _error->Errno("fchown",_("Failed to write file %s"), Itm.Name);
 	 }
 	 Fd = iFd;
 	 return true;

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

@@ -189,14 +189,14 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode)
 									/*}}}*/
 // 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,
 				 string const &URIDesc, string const &ShortDesc,
 				 HashString const &ExpectedHash)
    : Item(Owner), ExpectedHash(ExpectedHash)
 {
+   /* XXX: Beware: Currently this class does nothing (of value) anymore ! */
    Debug = _config->FindB("Debug::pkgAcquire::SubIndex",false);
 
    DestFile = _config->FindDir("Dir::State::lists") + "partial/";
@@ -236,17 +236,7 @@ void pkgAcqSubIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*
    Status = StatDone;
    Dequeue();
 
-   // No good Index is provided, so try guessing
-   std::vector<std::string> langs = APT::Configuration::getLanguages(true);
-   for (std::vector<std::string>::const_iterator l = langs.begin();
-	l != langs.end(); ++l)
-   {
-      if (*l == "none") continue;
-      string const file = "Translation-" + *l;
-      new pkgAcqIndexTrans(Owner, Desc.URI.substr(0, Desc.URI.rfind('/')+1).append(file),
-		Desc.Description.erase(Desc.Description.rfind(' ')+1).append(file),
-		file);
-   }
+   // No good Index is provided
 }
 									/*}}}*/
 void pkgAcqSubIndex::Done(string Message,unsigned long long Size,string Md5Hash,	/*{{{*/
@@ -305,38 +295,7 @@ bool pkgAcqSubIndex::ParseIndex(string const &IndexFile)		/*{{{*/
    indexRecords SubIndexParser;
    if (FileExists(IndexFile) == false || SubIndexParser.Load(IndexFile) == false)
       return false;
-
-   std::vector<std::string> lang = APT::Configuration::getLanguages(true);
-   for (std::vector<std::string>::const_iterator l = lang.begin();
-	l != lang.end(); ++l)
-   {
-      if (*l == "none")
-	 continue;
-
-      string file = "Translation-" + *l;
-      indexRecords::checkSum const *Record = SubIndexParser.Lookup(file);
-      HashString expected;
-      if (Record == NULL)
-      {
-	 // FIXME: the Index file provided by debian currently only includes bz2 records
-	 Record = SubIndexParser.Lookup(file + ".bz2");
-	 if (Record == NULL)
-	    continue;
-      }
-      else
-      {
-	 expected = Record->Hash;
-	 if (expected.empty() == true)
-	    continue;
-      }
-
-      IndexTarget target;
-      target.Description = Desc.Description.erase(Desc.Description.rfind(' ')+1).append(file);
-      target.MetaKey = file;
-      target.ShortDesc = file;
-      target.URI = Desc.URI.substr(0, Desc.URI.rfind('/')+1).append(file);
-      new pkgAcqIndexTrans(Owner, &target, expected, &SubIndexParser);
-   }
+   // so something with the downloaded index
    return true;
 }
 									/*}}}*/
@@ -1385,6 +1344,18 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
       return;
    }
 #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();
         Target != IndexTargets->end();
         ++Target)
@@ -1422,8 +1393,15 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)				/*{{{*/
 	 if ((*Target)->IsSubIndex() == true)
 	    new pkgAcqSubIndex(Owner, (*Target)->URI, (*Target)->Description,
 				(*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;
       }
 
@@ -1620,6 +1598,13 @@ void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*
 {
    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,
 			MetaSigURI, MetaSigURIDesc, MetaSigShortDesc,
 			MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc,
@@ -1825,7 +1810,18 @@ bool pkgAcqArchive::QueueNext()
 	 else
 	    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
       Local = false;
       Desc.URI = Index->ArchiveURI(PkgFile);

+ 1 - 1
apt-pkg/acquire.cc

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

+ 12 - 3
apt-pkg/algorithms.cc

@@ -471,7 +471,7 @@ bool pkgMinimizeUpgrade(pkgDepCache &Cache)
 // ProblemResolver::pkgProblemResolver - Constructor			/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : Cache(*pCache)
+pkgProblemResolver::pkgProblemResolver(pkgDepCache *pCache) : d(NULL), Cache(*pCache)
 {
    // Allocate memory
    unsigned long Size = Cache.Head().PackageCount;
@@ -556,7 +556,8 @@ void pkgProblemResolver::MakeScores()
          essantial package above most other packages but low enough
 	 to allow an obsolete essential packages to be removed by
 	 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;
 
       // We transform the priority
@@ -631,7 +632,8 @@ void pkgProblemResolver::MakeScores()
    {
       if ((Flags[I->ID] & Protected) != 0)
 	 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;
    }
 }
@@ -1430,6 +1432,13 @@ static int PrioComp(const void *A,const void *B)
    if ((L.ParentPkg()->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
        (R.ParentPkg()->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
      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)
       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(external[1], STDOUT_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!");
 			_exit(100);
 		}
@@ -392,7 +392,9 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 					if (arch[0] != '\0') {
 						char const* archend = arch;
 						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, " ");
 				}

+ 35 - 1
apt-pkg/cachefile.cc

@@ -30,7 +30,7 @@
 // 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)
 {
 }
@@ -178,6 +178,40 @@ void pkgCacheFile::RemoveCaches()
       unlink(pkgcache.c_str());
    if (srcpkgcache.empty() == false && RealFileExists(srcpkgcache) == true)
       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				/*{{{*/

+ 1 - 1
apt-pkg/cachefilter.cc

@@ -18,7 +18,7 @@
 									/*}}}*/
 namespace APT {
 namespace CacheFilter {
-PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) {/*{{{*/
+PackageNameMatchesRegEx::PackageNameMatchesRegEx(std::string const &Pattern) : d(NULL) {/*{{{*/
 	pattern = new regex_t;
 	int const Res = regcomp(pattern, Pattern.c_str(), REG_EXTENDED | REG_ICASE | REG_NOSUB);
 	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 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); }
 	};
 									/*}}}*/
@@ -201,7 +203,9 @@ public:									/*{{{*/
 
 	bool empty() const { return _cont.empty(); };
 	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); };
+	iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); };
 	size_t erase(const pkgCache::PkgIterator x) { return _cont.erase(x); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	size_t size() const { return _cont.size(); };
@@ -507,6 +511,8 @@ public:									/*{{{*/
 		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 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); }
 	};
 									/*}}}*/
@@ -516,7 +522,9 @@ public:									/*{{{*/
 	void insert(const_iterator begin, const_iterator end) { _cont.insert(begin, end); };
 	bool empty() const { return _cont.empty(); };
 	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); };
+	iterator& erase(iterator &position, bool) { return position = _cont.erase((typename Container::iterator)position); };
 	size_t erase(const pkgCache::VerIterator x) { return _cont.erase(x); };
 	void erase(iterator first, iterator last) { _cont.erase(first, last); };
 	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)
 	 {
+	    // 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)
 	       _error->Notice(_("Ignoring '%s' in directory '%s' as it is not a regular file"), Ent->d_name, Dir.c_str());
 	    continue;
@@ -454,6 +461,80 @@ std::vector<string> GetListOfFilesInDir(string const &Dir, std::vector<string> c
    }
    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)
       std::sort(List.begin(),List.end());
    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_iterator compressor = compressors.begin();
    std::string name;
+
+   // compat with the old API
+   if (Mode == ReadOnlyGzip && Compress == None)
+      Compress = Gzip;
+
    switch (Compress)
    {
    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, APT::Configuration::Compressor const &compressor, 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 Sync();
@@ -174,6 +171,7 @@ std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::string
 					bool const &SortList, bool const &AllowNoExt=false);
 std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, std::vector<std::string> const &Ext,
 					bool const &SortList);
+std::vector<std::string> GetListOfFilesInDir(std::string const &Dir, bool SortList);
 std::string SafeGetCWD();
 void SetCloseExec(int Fd,bool Close);
 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
    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)
    {
       // 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 += 1900;
       else
       {
 	 // 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)
 	 {
 	    // 'ftp' time

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

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

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

@@ -128,7 +128,7 @@ string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string
 {
    string Res ="";
    if (Dist[Dist.size() - 1] != '/')
-      Res += Section + "/i18n/";
+      Res += Section + "/i18n/Translation-";
    return Res + Type;
 }
 
@@ -210,31 +210,17 @@ vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const {
 	if (lang.empty() == true)
 		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);
-			IndexTargets->push_back (Target);
+			IndexTargets->push_back(Target);
 		}
 	}
 

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

@@ -51,8 +51,10 @@ using namespace std;
 class pkgDPkgPMPrivate 
 {
 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;
    // 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)
 {
+   pkgPackageManager::SigINTStop = false;
+
    // Generate the base argument list for dpkg
    std::vector<const char *> Args;
    unsigned long StartSize = 0;
@@ -905,7 +909,7 @@ bool pkgDPkgPM::Go(int OutStatusFd)
       dup2(nullfd, STDIN_FILENO);
       dup2(nullfd, STDOUT_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!");
       _exit(2);
    }
@@ -1429,9 +1433,8 @@ bool pkgDPkgPM::Go(int OutStatusFd)
 }
 
 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		/*{{{*/
 // ---------------------------------------------------------------------
@@ -1446,6 +1449,12 @@ void pkgDPkgPM::Reset()
 /* */
 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::size_type pos;
    FILE *report;
@@ -1533,7 +1542,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg)
 	 if(strstr(strbuf,"Package:") == strbuf)
 	 {
 	    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)
 	       {
 		  fclose(report);

+ 8 - 0
apt-pkg/depcache.cc

@@ -963,6 +963,13 @@ struct CompareProviders {
 	 else if ((B->Flags & pkgCache::Flag::Essential) == pkgCache::Flag::Essential)
 	    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
       if (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) ||
 	  (p->Flags & Flag::Essential) ||
+	  (p->Flags & Flag::Important) ||
 	  userFunc.InRootSet(p) ||
 	  // be nice even then a required package violates the policy (#583517)
 	  // 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());
       
       // 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();
 
       pkgTagFile Parser(&Pkg);
@@ -797,7 +797,7 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name,	/*{{{*/
       string OrigPath = string(*I,CDROM.length());
 
       // Open the package file
-      FileFd Pkg(*I, FileFd::ReadOnly, FileFd::Extension);
+      FileFd Pkg(*I, FileFd::ReadOnly, FileFd::Auto);
       off_t const FileSize = Pkg.Size();
 
       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)
 {
-   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

+ 6 - 8
apt-pkg/orderlist.cc

@@ -82,16 +82,14 @@ pkgOrderList *pkgOrderList::Me = 0;
 // 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);
-   
+
    /* Construct the arrays, egcs 1.0.1 bug requires the package count
       hack */
    unsigned long Size = Cache.Head().PackageCount;

+ 357 - 266
apt-pkg/packagemanager.cc

@@ -36,11 +36,13 @@ bool pkgPackageManager::SigINTStop = false;
 // 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];
-   List = 0;
    Debug = _config->FindB("Debug::pkgPackageManager",false);
+   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
+   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
 }
 									/*}}}*/
 // PM::PackageManager - Destructor					/*{{{*/
@@ -150,7 +152,7 @@ void pkgPackageManager::ImmediateAdd(PkgIterator I, bool UseInstallVer, unsigned
 	 if(!List->IsFlag(D.TargetPkg(), pkgOrderList::Immediate))
 	 {
 	    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);
 	    ImmediateAdd(D.TargetPkg(), UseInstallVer, Depth + 1);
 	 }
@@ -169,10 +171,7 @@ bool pkgPackageManager::CreateOrderList()
    
    delete List;
    List = new pkgOrderList(&Cache);
-   
-   NoImmConfigure = !_config->FindB("APT::Immediate-Configure",true);
-   ImmConfigureAll = _config->FindB("APT::Immediate-Configure-All",false);
-   
+
    if (Debug && ImmConfigureAll) 
       clog << "CreateOrderList(): Adding Immediate flag for all packages because of APT::Immediate-Configure-All" << endl;
    
@@ -184,12 +183,11 @@ bool pkgPackageManager::CreateOrderList()
 	 continue;
       
       // 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)
       {
 	 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);
 	 
 	 if (!ImmConfigureAll) {
@@ -258,7 +256,7 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D,
 
       if (EarlyRemove(D.ParentPkg()) == false)
 	 return _error->Error("Reverse conflicts early remove for package '%s' failed",
-			      Pkg.Name());
+			      Pkg.FullName().c_str());
    }
    return true;
 }
@@ -296,9 +294,9 @@ bool pkgPackageManager::ConfigureAll()
       if (ConfigurePkgs == true && SmartConfigure(Pkg, 0) == false) {
          if (ImmConfigureAll)
             _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
-            _error->Error("Internal error, packages left unconfigured. %s",Pkg.Name());
+            _error->Error("Internal error, packages left unconfigured. %s",Pkg.FullName().c_str());
 	 return false;
       }
       
@@ -323,11 +321,11 @@ bool pkgPackageManager::ConfigureAll()
 bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 {
    // 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) {
       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)
         clog << " (Only Correct Dependencies)";
       clog << endl;
@@ -338,103 +336,135 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
    /* 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 
       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)
 		     std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl;
+	          Bad = false;
+		  break;
 	       }
 	       else
 	       {
-		  List->Flag(Pkg,pkgOrderList::Loop);
 		  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 (Debug)
-         _error->Warning(_("Could not configure '%s'. "),Pkg.Name());
+         _error->Warning(_("Could not configure '%s'. "),Pkg.FullName().c_str());
       return false;
    }
    
@@ -444,7 +474,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
    static bool const ConfigurePkgs = (conf == "all" || conf == "smart");
 
    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)
       return false;
@@ -464,7 +494,7 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth)
 
    // Sanity Check
    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;
 }
@@ -487,7 +517,8 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
 
    // Essential packages get special treatment
    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;
 
    /* 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 &&
 	   IsEssential == false; ++D)
 	 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;
    }
 
@@ -508,7 +540,7 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg)
 				"removing the essential package %s due to a "
 				"Conflicts/Pre-Depends loop. This is often bad, "
 				"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);
@@ -544,193 +576,252 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c
    bool PkgLoop = List->IsFlag(Pkg,pkgOrderList::Loop);
 
    if (Debug) {
-      clog << OutputInDepth(Depth) << "SmartUnPack " << Pkg.Name();
+      clog << OutputInDepth(Depth) << "SmartUnPack " << Pkg.FullName();
       VerIterator InstallVer = VerIterator(Cache,Cache[Pkg].InstallVer);
       if (Pkg.CurrentVer() == 0)
-        cout << " (install version " << InstallVer.VerStr() << ")";
+        clog << " (install version " << InstallVer.VerStr() << ")";
       else
-        cout << " (replace version " << Pkg.CurrentVer().VerStr() << " with " << InstallVer.VerStr() << ")";
+        clog << " (replace version " << Pkg.CurrentVer().VerStr() << " with " << InstallVer.VerStr() << ")";
       if (PkgLoop)
-        cout << " (Only Perform PreUnpack Checks)";
-      cout << endl;
+        clog << " (Only Perform PreUnpack Checks)";
+      clog << endl;
    }
 
    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.
-      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
-      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. */
-   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.
    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. 
          if (SmartConfigure(Pkg, Depth + 1) == false)
             _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;
@@ -827,11 +918,11 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
       {
          if (!List->IsFlag(Pkg,pkgOrderList::Configured) && !NoImmConfigure) {
             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
          } else {
 	    if (Debug == true)
-	       clog << "Skipping already done " << Pkg.Name() << endl;
+	       clog << "Skipping already done " << Pkg.FullName() << endl;
 	 }
 	 continue;
 	 
@@ -840,7 +931,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
       if (List->IsMissing(Pkg) == true)
       {
 	 if (Debug == true)
-	    clog << "Sequence completed at " << Pkg.Name() << endl;
+	    clog << "Sequence completed at " << Pkg.FullName() << endl;
 	 if (DoneSomething == false)
 	 {
 	    _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 &&
 	  (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;
       }
       
@@ -887,7 +978,7 @@ pkgPackageManager::OrderResult pkgPackageManager::OrderInstall()
       if (List->IsFlag(*I,pkgOrderList::Configured) == false)
       {
 	 _error->Error("Internal error, packages left unconfigured. %s",
-		       PkgIterator(Cache,*I).Name());
+		       PkgIterator(Cache,*I).FullName().c_str());
 	 return Failed;
       }
    }

+ 1 - 1
apt-pkg/pkgrecords.cc

@@ -22,7 +22,7 @@
 // Records::pkgRecords - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* 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)
 {
    for (pkgCache::PkgFileIterator I = Cache.FileBegin();

+ 2 - 2
apt-pkg/pkgsystem.cc

@@ -26,11 +26,11 @@ unsigned long pkgSystem::GlobalListLen = 0;
 // System::pkgSystem - Constructor					/*{{{*/
 // ---------------------------------------------------------------------
 /* Add it to the global list.. */
-pkgSystem::pkgSystem()
+pkgSystem::pkgSystem() : Label(NULL), VS(NULL)
 {
    assert(GlobalListLen < sizeof(SysList)/sizeof(*SysList));
    SysList[GlobalListLen] = this;
-   GlobalListLen++;
+   ++GlobalListLen;
 }
 									/*}}}*/
 // 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						/*{{{*/
 // ---------------------------------------------------------------------
 /* Link this to the global list of items*/
-pkgSourceList::Type::Type()
+pkgSourceList::Type::Type() : Name(NULL), Label(NULL)
 {
    ItmList[GlobalListLen] = this;
    GlobalListLen++;

+ 1 - 1
apt-pkg/srcrecords.cc

@@ -25,7 +25,7 @@
 // SrcRecords::pkgSrcRecords - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* 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)
    {

+ 4 - 1
apt-pkg/tagfile.cc

@@ -30,7 +30,10 @@ using std::string;
 class pkgTagFilePrivate
 {
 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;

+ 2 - 2
apt-pkg/version.cc

@@ -23,10 +23,10 @@ unsigned long pkgVersioningSystem::GlobalListLen = 0;
 // pkgVS::pkgVersioningSystem - Constructor				/*{{{*/
 // ---------------------------------------------------------------------
 /* Link to the global list of versioning systems supported */
-pkgVersioningSystem::pkgVersioningSystem()
+pkgVersioningSystem::pkgVersioningSystem() : Label(NULL)
 {
    VSList[GlobalListLen] = this;
-   GlobalListLen++;
+   ++GlobalListLen;
 }
 									/*}}}*/
 // 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) :
-    ScreenWidth(ScreenWidth), Quiet(Quiet)
+    ScreenWidth(ScreenWidth), ID(0), Quiet(Quiet)
 {
+   BlankLine[0] = 0;
 }
 									/*}}}*/
 // 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},
       {'o',"option",0,CommandLine::ArbItem},
       {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,"recommends","APT::Cache::ShowRecommends",0},
       {0,"suggests","APT::Cache::ShowSuggests",0},

+ 3 - 4
cmdline/apt-cdrom.cc

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

+ 2 - 2
cmdline/apt-extracttemplates.cc

@@ -53,8 +53,8 @@ pkgCache *DebFile::Cache = 0;
 // ---------------------------------------------------------------------
 /* */
 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) {
-		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);
 	}
 
@@ -904,7 +925,23 @@ struct TryToRemove {
       if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
 	  (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
 	 Pkg->SelectedState = pkgCache::State::Hold;
       }

+ 116 - 20
cmdline/apt-mark.cc

@@ -14,9 +14,15 @@
 #include <apt-pkg/init.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/pkgsystem.h>
+#include <apt-pkg/fileutl.h>
 
 #include <algorithm>
+#include <errno.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
 
 #include <apti18n.h>
 									/*}}}*/
@@ -158,13 +164,63 @@ bool DoHold(CommandLine &CmdL)
    if (unlikely(Cache == NULL))
       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);
    if (pkgset.empty() == true)
       return _error->Error(_("No packages found"));
 
    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)
       {
@@ -172,9 +228,25 @@ bool DoHold(CommandLine &CmdL)
 	    ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
 	 else
 	    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)
@@ -192,36 +264,60 @@ bool DoHold(CommandLine &CmdL)
       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)
    {
       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());
       }
       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());
       }
    }
+   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			{{{*/

+ 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 ]
+  * 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:
     - chroot if needed before dpkg --assert-multi-arch
     - 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:
     - if a M-A:same package is marked for reinstall, mark all it's installed
       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/*'
       header to avoid that the server chooses unsupported compressed files
       in a content-negotation attempt (Closes: #657560)
+    - remove the arbitrary MAXLEN limit for response lines (Closes: #658346)
   * apt-pkg/aptconfiguration.cc:
     - 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 ]
   * 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)
     - use a signed int instead of short for score calculation as upgrades
       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 ]
   * apt-pkg/deb/dpkgpm.cc:
     - 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:
     - fix compat with FileFd::OpenDescriptor() in ReadOnlyGzip mode
   * 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
 

+ 3 - 2
ftparchive/cachedb.h

@@ -126,7 +126,8 @@ class CacheDB
          Misses += S.Misses; 
          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;
    
    bool ReadyDB(std::string const &DB);
@@ -142,7 +143,7 @@ class CacheDB
    
    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;};
 };
     

+ 1 - 0
ftparchive/writer.cc

@@ -941,6 +941,7 @@ ReleaseWriter::ReleaseWriter(string const &DB)
       AddPattern("Packages.bz2");
       AddPattern("Packages.lzma");
       AddPattern("Packages.xz");
+      AddPattern("Translation-*");
       AddPattern("Sources");
       AddPattern("Sources.gz");
       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);
    PasvAddr = 0;
+   Buffer[0] = '\0';
 }
 									/*}}}*/
 // FTPConn::~FTPConn - Destructor					/*{{{*/
@@ -621,8 +622,7 @@ bool FTPConn::ExtGoPasv()
    }
    
    // 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;
@@ -720,14 +720,13 @@ bool FTPConn::CreateDataFd()
    DataListenFd = -1;
 
    // Get the information for a listening socket.
-   struct addrinfo *BindAddr = 0;
+   struct addrinfo *BindAddr = NULL;
    struct addrinfo Hints;
    memset(&Hints,0,sizeof(Hints));
    Hints.ai_socktype = SOCK_STREAM;
    Hints.ai_flags |= AI_PASSIVE;
    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"));
    
    // Construct the socket

+ 9 - 11
methods/http.cc

@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <climits>
 #include <iostream>
 #include <map>
 
@@ -534,10 +535,6 @@ bool ServerState::HeaderLine(string Line)
    if (Line.empty() == 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(' ');
    if (Pos == string::npos || Pos+1 > Line.length())
    {
@@ -561,7 +558,7 @@ bool ServerState::HeaderLine(string Line)
       // Evil servers return no version
       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)
 	 {
 	    Code[0] = '\0';
@@ -575,7 +572,7 @@ bool ServerState::HeaderLine(string Line)
       {
 	 Major = 0;
 	 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"));
       }
 
@@ -585,7 +582,7 @@ bool ServerState::HeaderLine(string Line)
 	 Persistent = false;
       else
       {
-	 if (Major == 1 && Minor <= 0)
+	 if (Major == 1 && Minor == 0)
 	    Persistent = false;
 	 else
 	    Persistent = true;
@@ -603,9 +600,10 @@ bool ServerState::HeaderLine(string Line)
       // The length is already set from the Content-Range header
       if (StartPos != 0)
 	 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;
    }
 
@@ -1329,7 +1327,7 @@ int HttpMethod::Loop()
                after the same URI is seen twice in a queue item. */
             StringVector &R = Redirected[Queue->DestFile];
             bool StopRedirects = false;
-            if (R.size() == 0)
+            if (R.empty() == true)
                R.push_back(Queue->Uri);
             else if (R[0] == "STOP" || R.size() > 10)
                StopRedirects = true;

+ 5 - 6
methods/http.h

@@ -11,8 +11,6 @@
 #ifndef APT_HTTP_H
 #define APT_HTTP_H
 
-#define MAXLEN 360
-
 #include <apt-pkg/strutl.h>
 
 #include <string>
@@ -92,7 +90,7 @@ struct ServerState
    unsigned int Major;
    unsigned int Minor;
    unsigned int Result;
-   char Code[MAXLEN];
+   char Code[360];
    
    // These are some statistics from the last parsed header lines
    unsigned long long Size;
@@ -117,9 +115,10 @@ struct ServerState
   
    bool HeaderLine(std::string Line);
    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 */
    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 <curl/curl.h>

+ 1 - 1
methods/mirror.cc

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

+ 3 - 1
methods/rsh.cc

@@ -42,7 +42,9 @@ int RSHMethod::FailFd = -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					/*{{{*/
 // ---------------------------------------------------------------------

+ 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
 		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;
-		shift 2
+		shift
+		if [ -n "$1" ]; then shift; else break; fi
 	done
 	echo -n "…${CNORMAL} " >&2;
 }
@@ -114,9 +115,9 @@ addtrap() {
 
 setupenvironment() {
 	TMPWORKINGDIRECTORY=$(mktemp -d)
-	local TESTDIR=$(readlink -f $(dirname $0))
+	TESTDIRECTORY=$(readlink -f $(dirname $0))
 	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"
 	local OLDWORKINGDIRECTORY=$(pwd)
 	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 var/cache var/lib var/log
 	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
 	mkdir -p usr/lib/apt
 	ln -s ${BUILDDIRECTORY}/methods usr/lib/apt/methods
 	cd ..
 	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
 	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
-	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
 	echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > 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:: \"--force-not-root\";" >> 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 'quiet::NoUpdate "true";' >> aptconfig.conf
 	export LC_ALL=C
@@ -170,13 +167,17 @@ getarchitecture() {
 		if [ -n "$ARCH" ]; then
 			echo $ARCH
 		else
-			dpkg-architecture -qDEB_BUILD_ARCH
+			dpkg --print-architecture
 		fi
 	else
 		echo $1
 	fi
 }
 
+getarchitectures() {
+	echo "$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+}
+
 configarchitecture() {
 	local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf
 	rm -f $CONFFILE
@@ -186,6 +187,30 @@ configarchitecture() {
 		echo "APT::Architectures:: \"$(getarchitecture $1)\";" >> $CONFFILE
 		shift
 	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() {
@@ -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' ' ')"
 	if [ -z "$ARCHS" ]; then
 		# 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
 	echo -n 'Dir {
 	ArchiveDir "' >> ftparchive.conf
@@ -432,7 +457,7 @@ insertpackage() {
 	local ARCHS=""
 	for arch in $(echo "$ARCH" | sed -e 's#,#\n#g' | sed -e "s#^native\$#$(getarchitecture 'native')#"); do
 		if [ "$arch" = "all" ]; then
-			ARCHS="$(aptconfig dump | grep APT::Architecture | cut -d'"' -f 2 | sed '/^$/ d' | sort | uniq | tr '\n' ' ')"
+			ARCHS="$(getarchitectures)"
 		else
 			ARCHS="$arch"
 		fi
@@ -486,7 +511,8 @@ insertinstalledpackage() {
 	local VERSION="$3"
 	local DEPENDENCIES="$4"
 	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
 		echo "Package: $NAME
 Status: install ok installed
@@ -502,6 +528,11 @@ Version: $VERSION" >> $FILE
  YOU did something horribly wrong! They are autogenerated
  und used only by testcases for APT and surf no other propose…
 " >> $FILE
+		if [ "$(dpkg-query -W --showformat='${Multi-Arch}')" = 'same' ]; then
+			echo -n > ${INFO}/${NAME}:${arch}.list
+		else
+			echo -n > ${INFO}/${NAME}.list
+		fi
 	done
 }
 
@@ -542,9 +573,6 @@ generatereleasefiles() {
 	# both should be given in notation date/touch can understand
 	msgninfo "\tGenerate Release files… "
 	if [ -e aptarchive/dists ]; then
-		for dir in $(find ./aptarchive/dists -mindepth 3 -maxdepth 3 -type d -name 'i18n'); do
-			aptftparchive -qq release $dir -o APT::FTPArchive::Release::Patterns::='Translation-*' > $dir/Index
-		done
 		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
 			local SUITE="$(echo "$dir" | cut -d'/' -f 4)"
 			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
 # prevent it, but to late - its better to fail earlier
-testequal 'Reading package lists...
+testequal "Reading package lists...
 Building dependency tree...
   MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1
     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:
   coolstuff
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
 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
 
 aptget install libc6:i386 -t stable -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6
+testdpkginstalled libc6:i386
 testequal 'Reading package lists...
 Building dependency tree...
 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.
 Inst libc6 [1.0] (2.0 testing [all])
 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...
 Building dependency tree...
@@ -125,7 +130,7 @@ buildsimplenativepackage 'foobar-same' 'amd64' '1.0' 'stable' 'Depends: libc6-sa
 setupaptarchive
 
 aptget install libc6-same:i386 -t stable -y -qq 2>&1 > /dev/null
-testdpkginstalled libc6-same
+testdpkginstalled libc6-same:i386
 
 testequal 'Reading package lists...
 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.
 Inst libc6-same [1.0] (2.0 testing [all])
 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...
 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'
 
 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
-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
 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
 
-# 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'
 aptget update -o Acquire::Languages=en | grep -q -e 'Translation-en ' && msgpass || msgfail
 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/framework
 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
 
 testequal 'Reading package lists...
@@ -16,11 +28,10 @@ The following NEW packages will be installed:
 The following packages will be upgraded:
   apt libc6
 2 upgraded, 1 newly installed, 1 to remove and 0 not upgraded.
-Need to get 0 B/6724 kB of archives.
-After this operation, 1523 kB of additional disk space will be used.
+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
 
-echo 'apt hold' | dpkg --set-selections
+aptmark hold apt -qq
 
 testequal 'Reading package lists...
 Building dependency tree...
@@ -29,6 +40,5 @@ The following packages have been kept back:
 The following packages will be upgraded:
   libc6
 1 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.
-Need to get 0 B/3881 kB of archives.
 After this operation, 0 B of additional disk space will be used.
 E: Trivial Only specified but this is not a trivial operation.' aptget dist-upgrade --trivial-only -o Test='hold-back-apt'

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

@@ -20,14 +20,15 @@ Building dependency tree...
 The following packages will be upgraded:
   openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib
 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]
-      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]
 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-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])

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

@@ -6,7 +6,7 @@ TESTDIR=$(readlink -f $(dirname $0))
 setupenvironment
 configarchitecture "i386"
 
-insertpackage 'unstable' 'apt' 'i386' '0.8.15'
+insertpackage 'unstable' 'rapt' 'i386' '0.8.15'
 insertpackage 'unstable' 'arch' 'i386' '1.0'
 
 setupaptarchive
@@ -22,40 +22,40 @@ testcandidate() {
 	fi
 }
 
-testcandidate apt '0.8.15'
+testcandidate rapt '0.8.15'
 testequal 'N: Unable to locate package doesntexist' aptcache policy doesntexist -q=0
 testequal 'Reading package lists...
 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-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 'Reading package lists...
 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: doesntexist
 Pin: release a=unstable
 Pin-Priority: 1000' >> rootdir/etc/apt/preferences
 
-testcandidate apt '(none)'
+testcandidate rapt '(none)'
 
 echo '
-Package: apt
+Package: rapt
 Pin: release a=unstable
 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 'Reading package lists...
 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
 Pin: release a=unstable

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

@@ -153,6 +153,35 @@ runtest() {
 	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"
 runtest
 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