Explorar o código

Merge branch 'debian/sid' into debian/experimental

Conflicts:
	apt-pkg/acquire-item.cc
	apt-pkg/acquire-item.h
	apt-pkg/cachefilter.h
	configure.ac
	debian/changelog
Michael Vogt %!s(int64=11) %!d(string=hai) anos
pai
achega
c511c5e8ed
Modificáronse 86 ficheiros con 61487 adicións e 57559 borrados
  1. 83 29
      apt-pkg/acquire-item.cc
  2. 9 0
      apt-pkg/acquire-item.h
  3. 2 0
      apt-pkg/contrib/fileutl.h
  4. 4 0
      apt-pkg/contrib/proxy.cc
  5. 18 6
      apt-pkg/contrib/strutl.cc
  6. 147 91
      apt-pkg/deb/dpkgpm.cc
  7. 1 0
      apt-pkg/deb/dpkgpm.h
  8. 1 1
      apt-pkg/tagfile.cc
  9. 46 43
      apt-private/private-cacheset.cc
  10. 6 6
      apt-private/private-cacheset.h
  11. 7 2
      apt-private/private-cmndline.cc
  12. 18 23
      apt-private/private-list.cc
  13. 95 75
      apt-private/private-output.cc
  14. 2 2
      apt-private/private-output.h
  15. 58 24
      apt-private/private-search.cc
  16. 41 17
      apt-private/private-utils.cc
  17. 2 2
      apt-private/private-utils.h
  18. 1 1
      configure.ac
  19. 78 0
      debian/changelog
  20. 2 0
      debian/gbp.conf
  21. 1 1
      doc/Doxyfile.in
  22. 1 1
      doc/apt-verbatim.ent
  23. 2 2
      doc/po/apt-doc.pot
  24. 7 117
      doc/po/de.po
  25. 29 7
      methods/copy.cc
  26. 4 3
      methods/server.cc
  27. 1 1
      methods/server.h
  28. 3318 0
      po/apt-all.pot
  29. 1194 1192
      po/ar.po
  30. 1335 1333
      po/ast.po
  31. 1337 1335
      po/bg.po
  32. 1186 1184
      po/bs.po
  33. 1339 1337
      po/ca.po
  34. 1321 1315
      po/cs.po
  35. 1408 1406
      po/cy.po
  36. 1327 1321
      po/da.po
  37. 1568 1559
      po/de.po
  38. 1325 1323
      po/dz.po
  39. 1326 1324
      po/el.po
  40. 1344 1342
      po/es.po
  41. 1307 1305
      po/eu.po
  42. 1315 1313
      po/fi.po
  43. 1354 1352
      po/fr.po
  44. 1344 1342
      po/gl.po
  45. 1334 1332
      po/hu.po
  46. 1343 1337
      po/it.po
  47. 1332 1326
      po/ja.po
  48. 1320 1318
      po/km.po
  49. 1325 1323
      po/ko.po
  50. 1167 1165
      po/ku.po
  51. 1263 1261
      po/lt.po
  52. 1323 1321
      po/mr.po
  53. 1330 1328
      po/nb.po
  54. 1314 1312
      po/ne.po
  55. 1352 1350
      po/nl.po
  56. 1322 1320
      po/nn.po
  57. 1338 1336
      po/pl.po
  58. 1335 1333
      po/pt.po
  59. 1328 1326
      po/pt_BR.po
  60. 1326 1324
      po/ro.po
  61. 1341 1339
      po/ru.po
  62. 1325 1323
      po/sk.po
  63. 1322 1320
      po/sl.po
  64. 1343 1341
      po/sv.po
  65. 1300 1294
      po/th.po
  66. 1338 1336
      po/tl.po
  67. 1338 1332
      po/tr.po
  68. 1443 1441
      po/uk.po
  69. 1454 1448
      po/vi.po
  70. 1311 1309
      po/zh_CN.po
  71. 1309 1307
      po/zh_TW.po
  72. 51 4
      prepare-release
  73. 8 2
      test/integration/framework
  74. 1 1
      test/integration/run-tests
  75. 30 1
      test/integration/test-apt-cli-search
  76. 2 3
      test/integration/test-apt-get-changelog
  77. 6 1
      test/integration/test-apt-https-no-redirect
  78. 16 0
      test/integration/test-apt-progress-fd
  79. 6 1
      test/integration/test-apt-progress-fd-error
  80. 36 0
      test/integration/test-apt-update-file
  81. 46 0
      test/integration/test-apt-update-stale
  82. 48 0
      test/integration/test-apt-update-unauth
  83. 4 4
      test/integration/test-architecture-specification-parsing
  84. 17 0
      test/integration/test-bug-762160-relpath
  85. 11 3
      test/integration/test-hashsum-verification
  86. 15 0
      test/libapt/strutil_test.cc

+ 83 - 29
apt-pkg/acquire-item.cc

@@ -1094,6 +1094,31 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
    Item::Failed(Message,Cnf);
    Item::Failed(Message,Cnf);
 }
 }
 									/*}}}*/
 									/*}}}*/
+// pkgAcqIndex::GetFinalFilename - Return the full final file path      /*{{{*/
+std::string pkgAcqIndex::GetFinalFilename(std::string const &URI,
+                                          std::string const &compExt)
+{
+   std::string FinalFile = _config->FindDir("Dir::State::lists");
+   FinalFile += URItoFileName(URI);
+   if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
+      FinalFile += ".gz";
+   return FinalFile;
+}
+									/*}}}*/
+// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit		/*{{{*/
+void pkgAcqIndex::ReverifyAfterIMS(std::string const &FileName)
+{
+   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
+   if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
+      DestFile += ".gz";
+
+   string FinalFile = GetFinalFilename(RealURI, compExt);
+   Rename(FinalFile, FileName);
+   Decompression = true;
+   Desc.URI = "copy:" + FileName;
+   QueueURI(Desc);
+}
+									/*}}}*/
 // AcqIndex::Done - Finished a fetch					/*{{{*/
 // AcqIndex::Done - Finished a fetch					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* This goes through a number of states.. On the initial fetch the
 /* This goes through a number of states.. On the initial fetch the
@@ -1104,12 +1129,14 @@ void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)	/*{{{*/
 void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes,
 void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes,
 		       pkgAcquire::MethodConfig *Cfg)
 		       pkgAcquire::MethodConfig *Cfg)
 {
 {
-   Item::Done(Message,Size,Hashes,Cfg);
+   Item::Done(Message,Size,Hash,Cfg);
+   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
 
 
    if (Decompression == true)
    if (Decompression == true)
    {
    {
       if (ExpectedHashes.usable() && ExpectedHashes != Hashes)
       if (ExpectedHashes.usable() && ExpectedHashes != Hashes)
       {
       {
+         Desc.URI = RealURI;
 	 RenameOnError(HashSumMismatch);
 	 RenameOnError(HashSumMismatch);
 	 printHashSumComparision(RealURI, ExpectedHashes, Hashes);
 	 printHashSumComparision(RealURI, ExpectedHashes, Hashes);
          return;
          return;
@@ -1121,9 +1148,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
       /* Always verify the index file for correctness (all indexes must
       /* Always verify the index file for correctness (all indexes must
        * have a Package field) (LP: #346386) (Closes: #627642) 
        * have a Package field) (LP: #346386) (Closes: #627642) 
        */
        */
-      FileFd fd(DestFile, FileFd::ReadOnly);
+      FileFd fd(DestFile, FileFd::ReadOnlyGzip);
       // Only test for correctness if the file is not empty (empty is ok)
       // Only test for correctness if the file is not empty (empty is ok)
-      if (fd.FileSize() > 0)
+      if (fd.Size() > 0)
       {
       {
          pkgTagSection sec;
          pkgTagSection sec;
          pkgTagFile tag(&fd);
          pkgTagFile tag(&fd);
@@ -1137,8 +1164,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
       }
       }
        
        
       // Done, move it into position
       // Done, move it into position
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI);
+      string FinalFile = GetFinalFilename(RealURI, compExt);
       Rename(DestFile,FinalFile);
       Rename(DestFile,FinalFile);
       chmod(FinalFile.c_str(),0644);
       chmod(FinalFile.c_str(),0644);
 
 
@@ -1146,7 +1172,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
          will work OK */
          will work OK */
       DestFile = _config->FindDir("Dir::State::lists") + "partial/";
       DestFile = _config->FindDir("Dir::State::lists") + "partial/";
       DestFile += URItoFileName(RealURI);
       DestFile += URItoFileName(RealURI);
-      
+      if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
+         DestFile += ".gz";
+
       // Remove the compressed version.
       // Remove the compressed version.
       if (Erase == true)
       if (Erase == true)
 	 unlink(DestFile.c_str());
 	 unlink(DestFile.c_str());
@@ -1161,9 +1189,6 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
    string FileName = LookupTag(Message,"Alt-Filename");
    string FileName = LookupTag(Message,"Alt-Filename");
    if (FileName.empty() == false)
    if (FileName.empty() == false)
    {
    {
-      // The files timestamp matches
-      if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
-	 return;
       Decompression = true;
       Decompression = true;
       Local = true;
       Local = true;
       DestFile += ".decomp";
       DestFile += ".decomp";
@@ -1180,33 +1205,37 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
       ErrorText = "Method gave a blank filename";
       ErrorText = "Method gave a blank filename";
    }
    }
 
 
-   std::string const compExt = CompressionExtension.substr(0, CompressionExtension.find(' '));
-
-   // The files timestamp matches
-   if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) {
-       if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
-	  // Update DestFile for .gz suffix so that the clean operation keeps it
-	  DestFile += ".gz";
-      return;
-    }
-
    if (FileName == DestFile)
    if (FileName == DestFile)
       Erase = true;
       Erase = true;
    else
    else
       Local = true;
       Local = true;
-   
+
+   // do not reverify cdrom sources as apt-cdrom may rewrite the Packages
+   // file when its doing the indexcopy
+   if (RealURI.substr(0,6) == "cdrom:" &&
+       StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+      return;
+
+   // The files timestamp matches, for non-local URLs reverify the local
+   // file, for local file, uncompress again to ensure the hashsum is still
+   // matching the Release file
+   if (!Local && StringToBool(LookupTag(Message,"IMS-Hit"),false) == true)
+   {
+      ReverifyAfterIMS(FileName);
+      return;
+   }
    string decompProg;
    string decompProg;
 
 
-   // If we enable compressed indexes and already have gzip, keep it
-   if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local) {
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI) + ".gz";
-      Rename(DestFile,FinalFile);
-      chmod(FinalFile.c_str(),0644);
-      
-      // Update DestFile for .gz suffix so that the clean operation keeps it
-      DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   // If we enable compressed indexes, queue for hash verification
+   if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz" && !Local) 
+   {
+      DestFile = _config->FindDir("Dir::State::lists");
       DestFile += URItoFileName(RealURI) + ".gz";
       DestFile += URItoFileName(RealURI) + ".gz";
+
+      Decompression = true;
+      Desc.URI = "copy:" + FileName;
+      QueueURI(Desc);
+
       return;
       return;
     }
     }
 
 
@@ -1254,6 +1283,9 @@ string pkgAcqIndexTrans::Custom600Headers() const
    string Final = _config->FindDir("Dir::State::lists");
    string Final = _config->FindDir("Dir::State::lists");
    Final += URItoFileName(RealURI);
    Final += URItoFileName(RealURI);
 
 
+   if (_config->FindB("Acquire::GzipIndexes",false))
+      Final += ".gz";
+
    struct stat Buf;
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
    if (stat(Final.c_str(),&Buf) != 0)
       return "\nFail-Ignore: true\nIndex-File: true";
       return "\nFail-Ignore: true\nIndex-File: true";
@@ -1606,6 +1638,28 @@ void pkgAcqMetaIndex::AuthDone(string Message)				/*{{{*/
       std::cerr << "Signature verification succeeded: "
       std::cerr << "Signature verification succeeded: "
                 << DestFile << std::endl;
                 << DestFile << std::endl;
 
 
+   // do not trust any previously unverified content that we may have
+   string LastGoodSigFile = _config->FindDir("Dir::State::lists").append("partial/").append(URItoFileName(RealURI));
+   if (DestFile != SigFile)
+      LastGoodSigFile.append(".gpg");
+   LastGoodSigFile.append(".reverify");
+   if(IMSHit == false && RealFileExists(LastGoodSigFile) == false)
+   {
+      for (vector <struct IndexTarget*>::const_iterator Target = IndexTargets->begin();
+           Target != IndexTargets->end();
+           ++Target)
+      {
+         // remove old indexes
+         std::string index = _config->FindDir("Dir::State::lists") +
+            URItoFileName((*Target)->URI);
+         unlink(index.c_str());
+         // and also old gzipindexes
+         index += ".gz";
+         unlink(index.c_str());
+      }
+   }
+
+
    // Download further indexes with verification
    // Download further indexes with verification
    QueueIndexes(true);
    QueueIndexes(true);
 
 

+ 9 - 0
apt-pkg/acquire-item.h

@@ -707,9 +707,18 @@ class pkgAcqIndex : public pkgAcqBaseIndex
     */
     */
    std::string CompressionExtension;
    std::string CompressionExtension;
 
 
+
    /** \brief Do the changes needed to fetch via AptByHash (if needed) */
    /** \brief Do the changes needed to fetch via AptByHash (if needed) */
    void InitByHashIfNeeded(const std::string MetaKey);
    void InitByHashIfNeeded(const std::string MetaKey);
 
 
+   /** \brief Get the full pathname of the final file for the given URI
+    */
+   std::string GetFinalFilename(std::string const &URI,
+                                std::string const &compExt);
+
+   /** \brief Schedule file for verification after a IMS hit */
+   void ReverifyAfterIMS(std::string const &FileName);
+
    public:
    public:
    
    
    // Specialized action members
    // Specialized action members

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

@@ -85,7 +85,9 @@ class FileFd
    bool Skip(unsigned long long To);
    bool Skip(unsigned long long To);
    bool Truncate(unsigned long long To);
    bool Truncate(unsigned long long To);
    unsigned long long Tell();
    unsigned long long Tell();
+   // the size of the file content (compressed files will be uncompressed first)
    unsigned long long Size();
    unsigned long long Size();
+   // the size of the file itself
    unsigned long long FileSize();
    unsigned long long FileSize();
    time_t ModificationTime();
    time_t ModificationTime();
 
 

+ 4 - 0
apt-pkg/contrib/proxy.cc

@@ -26,6 +26,10 @@ bool AutoDetectProxy(URI &URL)
    // we support both http/https debug options
    // we support both http/https debug options
    bool Debug = _config->FindB("Debug::Acquire::"+URL.Access,false);
    bool Debug = _config->FindB("Debug::Acquire::"+URL.Access,false);
 
 
+   // the user already explicitly set a proxy for this host
+   if(_config->Find("Acquire::"+URL.Access+"::proxy::"+URL.Host, "") != "")
+      return true;
+
    // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old
    // option is "Acquire::http::Proxy-Auto-Detect" but we allow the old
    // name without the dash ("-")
    // name without the dash ("-")
    std::string AutoDetectProxyCmd = _config->Find("Acquire::"+URL.Access+"::Proxy-Auto-Detect",
    std::string AutoDetectProxyCmd = _config->Find("Acquire::"+URL.Access+"::Proxy-Auto-Detect",

+ 18 - 6
apt-pkg/contrib/strutl.cc

@@ -45,14 +45,26 @@ using namespace std;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 namespace APT {
 namespace APT {
    namespace String {
    namespace String {
-std::string Strip(const std::string &s)
+std::string Strip(const std::string &str)
 {
 {
-   size_t start = s.find_first_not_of(" \t\n");
-   // only whitespace
-   if (start == string::npos)
+   // ensure we have at least one character
+   if (str.empty() == true)
+      return str;
+
+   char const * const s = str.c_str();
+   size_t start = 0;
+   for (; isspace(s[start]) != 0; ++start)
+      ; // find the first not-space
+
+   // string contains only whitespaces
+   if (s[start] == '\0')
       return "";
       return "";
-   size_t end = s.find_last_not_of(" \t\n");
-   return s.substr(start, end-start+1);
+
+   size_t end = str.length() - 1;
+   for (; isspace(s[end]) != 0; --end)
+      ; // find the last not-space
+
+   return str.substr(start, end - start + 1);
 }
 }
 
 
 bool Endswith(const std::string &s, const std::string &end)
 bool Endswith(const std::string &s, const std::string &end)

+ 147 - 91
apt-pkg/deb/dpkgpm.cc

@@ -59,8 +59,8 @@ class pkgDPkgPMPrivate
 {
 {
 public:
 public:
    pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
    pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0),
-			term_out(NULL), history_out(NULL), 
-                        progress(NULL), master(-1), slave(-1)
+			term_out(NULL), history_out(NULL),
+                        progress(NULL), master(-1), slave(NULL)
    {
    {
       dpkgbuf[0] = '\0';
       dpkgbuf[0] = '\0';
    }
    }
@@ -77,9 +77,9 @@ public:
    APT::Progress::PackageManager *progress;
    APT::Progress::PackageManager *progress;
 
 
    // pty stuff
    // pty stuff
-   struct	termios tt;
+   struct termios tt;
    int master;
    int master;
-   int slave;
+   char * slave;
 
 
    // signals
    // signals
    sigset_t sigmask;
    sigset_t sigmask;
@@ -510,7 +510,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
    return result;
    return result;
 }
 }
 									/*}}}*/
 									/*}}}*/
-// DPkgPM::DoStdin - Read stdin and pass to slave pty			/*{{{*/
+// DPkgPM::DoStdin - Read stdin and pass to master pty			/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /*
 /*
 */
 */
@@ -564,8 +564,8 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
       'status:   <pkg>: <pkg  qstate>'
       'status:   <pkg>: <pkg  qstate>'
       'status:   <pkg>:<arch>: <pkg  qstate>'
       'status:   <pkg>:<arch>: <pkg  qstate>'
       
       
-      'processing: {install,configure,remove,purge,disappear,trigproc}: pkg'
-      'processing: {install,configure,remove,purge,disappear,trigproc}: trigger'
+      'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: pkg'
+      'processing: {install,upgrade,configure,remove,purge,disappear,trigproc}: trigger'
    */
    */
 
 
    // we need to split on ": " (note the appended space) as the ':' is
    // we need to split on ": " (note the appended space) as the ':' is
@@ -589,12 +589,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    std::string action;
    std::string action;
 
 
    // "processing" has the form "processing: action: pkg or trigger"
    // "processing" has the form "processing: action: pkg or trigger"
-   // with action = ["install", "configure", "remove", "purge", "disappear",
-   //                "trigproc"]
+   // with action = ["install", "upgrade", "configure", "remove", "purge",
+   //                "disappear", "trigproc"]
    if (prefix == "processing")
    if (prefix == "processing")
    {
    {
       pkgname = APT::String::Strip(list[2]);
       pkgname = APT::String::Strip(list[2]);
       action = APT::String::Strip(list[1]);
       action = APT::String::Strip(list[1]);
+      // we don't care for the difference (as dpkg doesn't really either)
+      if (action == "upgrade")
+	 action = "install";
    }
    }
    // "status" has the form: "status: pkg: state"
    // "status" has the form: "status: pkg: state"
    // with state in ["half-installed", "unpacked", "half-configured", 
    // with state in ["half-installed", "unpacked", "half-configured", 
@@ -638,27 +641,26 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    // at this point we know that we should have a valid pkgname, so build all 
    // at this point we know that we should have a valid pkgname, so build all 
    // the info from it
    // the info from it
 
 
-   // dpkg does not send always send "pkgname:arch" so we add it here 
-   // if needed
+   // dpkg does not always send "pkgname:arch" so we add it here if needed
    if (pkgname.find(":") == std::string::npos)
    if (pkgname.find(":") == std::string::npos)
    {
    {
-      // find the package in the group that is in a touched by dpkg
-      // if there are multiple dpkg will send us a full pkgname:arch
+      // find the package in the group that is touched by dpkg
+      // if there are multiple pkgs dpkg would send us a full pkgname:arch
       pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname);
       pkgCache::GrpIterator Grp = Cache.FindGrp(pkgname);
-      if (Grp.end() == false) 
+      if (Grp.end() == false)
       {
       {
-          pkgCache::PkgIterator P = Grp.PackageList();
-          for (; P.end() != true; P = Grp.NextPkg(P))
-          {
-              if(Cache[P].Mode != pkgDepCache::ModeKeep)
-              {
-                  pkgname = P.FullName();
-                  break;
-              }
-          }
+	 pkgCache::PkgIterator P = Grp.PackageList();
+	 for (; P.end() != true; P = Grp.NextPkg(P))
+	 {
+	    if(Cache[P].Keep() == false || Cache[P].ReInstall() == true)
+	    {
+	       pkgname = P.FullName();
+	       break;
+	    }
+	 }
       }
       }
    }
    }
-   
+
    const char* const pkg = pkgname.c_str();
    const char* const pkg = pkgname.c_str();
    std::string short_pkgname = StringSplit(pkgname, ":")[0];
    std::string short_pkgname = StringSplit(pkgname, ":")[0];
    std::string arch = "";
    std::string arch = "";
@@ -697,28 +699,29 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    if (prefix == "status")
    if (prefix == "status")
    {
    {
       vector<struct DpkgState> const &states = PackageOps[pkg];
       vector<struct DpkgState> const &states = PackageOps[pkg];
-      const char *next_action = NULL;
       if(PackageOpsDone[pkg] < states.size())
       if(PackageOpsDone[pkg] < states.size())
-         next_action = states[PackageOpsDone[pkg]].state;
-      // check if the package moved to the next dpkg state
-      if(next_action && (action == next_action))
       {
       {
-         // only read the translation if there is actually a next
-         // action
-         const char *translation = _(states[PackageOpsDone[pkg]].str);
-         std::string msg;
-
-         // we moved from one dpkg state to a new one, report that
-         PackageOpsDone[pkg]++;
-         PackagesDone++;
-
-         strprintf(msg, translation, i18n_pkgname.c_str());
-         d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
-         
+         char const * const next_action = states[PackageOpsDone[pkg]].state;
+	 if (next_action && Debug == true)
+	    std::clog << "(parsed from dpkg) pkg: " << short_pkgname
+	       << " action: " << action << " (expected: '" << next_action << "' "
+	       << PackageOpsDone[pkg] << " of " << states.size() << ")" << endl;
+
+	 // check if the package moved to the next dpkg state
+	 if(next_action && (action == next_action))
+	 {
+	    // only read the translation if there is actually a next action
+	    char const * const translation = _(states[PackageOpsDone[pkg]].str);
+
+	    // we moved from one dpkg state to a new one, report that
+	    ++PackageOpsDone[pkg];
+	    ++PackagesDone;
+
+	    std::string msg;
+	    strprintf(msg, translation, i18n_pkgname.c_str());
+	    d->progress->StatusChanged(pkgname, PackagesDone, PackagesTotal, msg);
+	 }
       }
       }
-      if (Debug == true) 
-         std::clog << "(parsed from dpkg) pkg: " << short_pkgname
-                   << " action: " << action << endl;
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -1046,60 +1049,127 @@ void pkgDPkgPM::StartPtyMagic()
 {
 {
    if (_config->FindB("Dpkg::Use-Pty", true) == false)
    if (_config->FindB("Dpkg::Use-Pty", true) == false)
    {
    {
-      d->master = d->slave = -1;
+      d->master = -1;
+      if (d->slave != NULL)
+	 free(d->slave);
+      d->slave = NULL;
       return;
       return;
    }
    }
 
 
-   // setup the pty and stuff
-   struct winsize win;
-
+   _error->PushToStack();
    // if tcgetattr for both stdin/stdout returns 0 (no error)
    // if tcgetattr for both stdin/stdout returns 0 (no error)
    // we do the pty magic
    // we do the pty magic
-   _error->PushToStack();
-   if (tcgetattr(STDIN_FILENO, &d->tt) == 0 &&
-       tcgetattr(STDOUT_FILENO, &d->tt) == 0)
+   if (tcgetattr(STDOUT_FILENO, &d->tt) == 0 &&
+	 tcgetattr(STDIN_FILENO, &d->tt) == 0)
    {
    {
-       if (ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&win) < 0)
-       {
-           _error->Errno("ioctl", _("ioctl(TIOCGWINSZ) failed"));
-       } else if (openpty(&d->master, &d->slave, NULL, &d->tt, &win) < 0)
-       {
-           _error->Errno("openpty", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
-           d->master = d->slave = -1;
-        } else {
-	    struct termios rtt;
-	    rtt = d->tt;
-	    cfmakeraw(&rtt);
-	    rtt.c_lflag &= ~ECHO;
-	    rtt.c_lflag |= ISIG;
+      d->master = posix_openpt(O_RDWR | O_NOCTTY);
+      if (d->master == -1)
+	 _error->Errno("posix_openpt", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+      else if (unlockpt(d->master) == -1)
+      {
+	 _error->Errno("unlockpt", "Unlocking the slave of master fd %d failed!", d->master);
+	 close(d->master);
+	 d->master = -1;
+      }
+      else
+      {
+	 char const * const slave_name = ptsname(d->master);
+	 if (slave_name == NULL)
+	 {
+	    _error->Errno("unlockpt", "Getting name for slave of master fd %d failed!", d->master);
+	    close(d->master);
+	    d->master = -1;
+	 }
+	 else
+	 {
+	    d->slave = strdup(slave_name);
+	    if (d->slave == NULL)
+	    {
+	       _error->Errno("strdup", "Copying name %s for slave of master fd %d failed!", slave_name, d->master);
+	       close(d->master);
+	       d->master = -1;
+	    }
+	    struct winsize win;
+	    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) < 0)
+	       _error->Errno("ioctl", "Getting TIOCGWINSZ from stdout failed!");
+	    if (ioctl(d->master, TIOCSWINSZ, &win) < 0)
+	       _error->Errno("ioctl", "Setting TIOCSWINSZ for master fd %d failed!", d->master);
+	    if (tcsetattr(d->master, TCSANOW, &d->tt) == -1)
+	       _error->Errno("tcsetattr", "Setting in Start via TCSANOW for master fd %d failed!", d->master);
+
+	    struct termios raw_tt;
+	    raw_tt = d->tt;
+	    cfmakeraw(&raw_tt);
+	    raw_tt.c_lflag &= ~ECHO;
+	    raw_tt.c_lflag |= ISIG;
 	    // block SIGTTOU during tcsetattr to prevent a hang if
 	    // block SIGTTOU during tcsetattr to prevent a hang if
 	    // the process is a member of the background process group
 	    // the process is a member of the background process group
 	    // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
 	    // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
 	    sigemptyset(&d->sigmask);
 	    sigemptyset(&d->sigmask);
 	    sigaddset(&d->sigmask, SIGTTOU);
 	    sigaddset(&d->sigmask, SIGTTOU);
 	    sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask);
 	    sigprocmask(SIG_BLOCK,&d->sigmask, &d->original_sigmask);
-	    tcsetattr(0, TCSAFLUSH, &rtt);
-	    sigprocmask(SIG_SETMASK, &d->original_sigmask, 0);
-        }
+	    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw_tt) == -1)
+	       _error->Errno("tcsetattr", "Setting in Start via TCSAFLUSH for stdout failed!");
+	    sigprocmask(SIG_SETMASK, &d->original_sigmask, NULL);
+	 }
       }
       }
-   // complain only if stdout is either a terminal (but still failed) or is an invalid
+   }
+   else
+   {
+      // complain only if stdout is either a terminal (but still failed) or is an invalid
       // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
       // descriptor otherwise we would complain about redirection to e.g. /dev/null as well.
-      else if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
-         _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+      if (isatty(STDOUT_FILENO) == 1 || errno == EBADF)
+	 _error->Errno("tcgetattr", _("Can not write log (%s)"), _("Is stdout a terminal?"));
+   }
 
 
-      if (_error->PendingError() == true)
-	 _error->DumpErrors(std::cerr);
-      _error->RevertToStack();
+   if (_error->PendingError() == true)
+   {
+      if (d->master != -1)
+      {
+	 close(d->master);
+	 d->master = -1;
+      }
+      _error->DumpErrors(std::cerr);
+   }
+   _error->RevertToStack();
 }
 }
+void pkgDPkgPM::SetupSlavePtyMagic()
+{
+   if(d->master == -1)
+      return;
+
+   if (close(d->master) == -1)
+      _error->FatalE("close", "Closing master %d in child failed!", d->master);
+   if (setsid() == -1)
+      _error->FatalE("setsid", "Starting a new session for child failed!");
+
+   int const slaveFd = open(d->slave, O_RDWR);
+   if (slaveFd == -1)
+      _error->FatalE("open", _("Can not write log (%s)"), _("Is /dev/pts mounted?"));
+
+   if (ioctl(slaveFd, TIOCSCTTY, 0) < 0)
+      _error->FatalE("ioctl", "Setting TIOCSCTTY for slave fd %d failed!", slaveFd);
+   else
+   {
+      for (unsigned short i = 0; i < 3; ++i)
+	 if (dup2(slaveFd, i) == -1)
+	    _error->FatalE("dup2", "Dupping %d to %d in child failed!", slaveFd, i);
 
 
+      if (tcsetattr(0, TCSANOW, &d->tt) < 0)
+	 _error->FatalE("tcsetattr", "Setting in Setup via TCSANOW for slave fd %d failed!", slaveFd);
+   }
+}
 void pkgDPkgPM::StopPtyMagic()
 void pkgDPkgPM::StopPtyMagic()
 {
 {
-   if(d->slave > 0)
-      close(d->slave);
+   if (d->slave != NULL)
+      free(d->slave);
+   d->slave = NULL;
    if(d->master >= 0) 
    if(d->master >= 0) 
    {
    {
-      tcsetattr(0, TCSAFLUSH, &d->tt);
+      if (tcsetattr(0, TCSAFLUSH, &d->tt) == -1)
+	 _error->FatalE("tcsetattr", "Setting in Stop via TCSAFLUSH for stdin failed!");
       close(d->master);
       close(d->master);
+      d->master = -1;
    }
    }
 }
 }
 
 
@@ -1407,22 +1477,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       pid_t Child = ExecFork(KeepFDs);
       pid_t Child = ExecFork(KeepFDs);
       if (Child == 0)
       if (Child == 0)
       {
       {
-         // This is the child
-	 if(d->slave >= 0 && d->master >= 0) 
-	 {
-	    setsid();
-	    int res = ioctl(d->slave, TIOCSCTTY, 0);
-            if (res < 0) {
-               std::cerr << "ioctl(TIOCSCTTY) failed for fd: " 
-                         << d->slave << std::endl;
-            } else {
-               close(d->master);
-               dup2(d->slave, 0);
-               dup2(d->slave, 1);
-               dup2(d->slave, 2);
-               close(d->slave);
-            }
-	 }
+	 // This is the child
+	 SetupSlavePtyMagic();
 	 close(fd[0]); // close the read end of the pipe
 	 close(fd[0]); // close the read end of the pipe
 
 
 	 dpkgChrootDirectory();
 	 dpkgChrootDirectory();

+ 1 - 0
apt-pkg/deb/dpkgpm.h

@@ -110,6 +110,7 @@ class pkgDPkgPM : public pkgPackageManager
    // helper
    // helper
    void BuildPackagesProgressMap();
    void BuildPackagesProgressMap();
    void StartPtyMagic();
    void StartPtyMagic();
+   void SetupSlavePtyMagic();
    void StopPtyMagic();
    void StopPtyMagic();
    
    
    // input processing
    // input processing

+ 1 - 1
apt-pkg/tagfile.cc

@@ -601,7 +601,7 @@ static const char *iTFRewritePackageOrder[] = {
                           "Conffiles",
                           "Conffiles",
                           "Filename",
                           "Filename",
                           "Size",
                           "Size",
-                          "MD5Sum",
+                          "MD5sum",
                           "SHA1",
                           "SHA1",
                           "SHA256",
                           "SHA256",
                           "SHA512",
                           "SHA512",

+ 46 - 43
apt-private/private-cacheset.cc

@@ -14,74 +14,77 @@
 
 
 #include <apti18n.h>
 #include <apti18n.h>
 
 
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                 LocalitySortedVersionSet &output_set,
-                                 OpProgress &progress)
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                 APT::VersionContainerInterface * const vci,
+                                 OpProgress * const progress)
 {
 {
     Matcher null_matcher = Matcher();
     Matcher null_matcher = Matcher();
-    return GetLocalitySortedVersionSet(CacheFile, output_set, 
+    return GetLocalitySortedVersionSet(CacheFile, vci,
                                        null_matcher, progress);
                                        null_matcher, progress);
 }
 }
 
 
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                 LocalitySortedVersionSet &output_set,
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                 APT::VersionContainerInterface * const vci,
                                  Matcher &matcher,
                                  Matcher &matcher,
-                                 OpProgress &progress)
+                                 OpProgress * const progress)
 {
 {
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgDepCache *DepCache = CacheFile.GetDepCache();
    pkgDepCache *DepCache = CacheFile.GetDepCache();
+   APT::CacheSetHelper helper(false);
 
 
    int Done=0;
    int Done=0;
-   progress.SubProgress(Cache->Head().PackageCount, _("Sorting"));
+   if (progress != NULL)
+      progress->SubProgress(Cache->Head().PackageCount, _("Sorting"));
+
+   bool const insertCurrentVer = _config->FindB("APT::Cmd::Installed", false);
+   bool const insertUpgradable = _config->FindB("APT::Cmd::Upgradable", false);
+   bool const insertManualInstalled = _config->FindB("APT::Cmd::Manual-Installed", false);
+
    for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
    for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
    {
    {
-      if (Done%500 == 0)
-         progress.Progress(Done);
-      Done++;
+      if (progress != NULL)
+      {
+	 if (Done % 500 == 0)
+	    progress->Progress(Done);
+	 ++Done;
+      }
+
+      // exclude virtual pkgs
+      if (P->VersionList == 0)
+	 continue;
 
 
       if ((matcher)(P) == false)
       if ((matcher)(P) == false)
-         continue;
+	 continue;
 
 
-      // exclude virtual pkgs
-      if (P.VersionList() == 0)
-         continue;
       pkgDepCache::StateCache &state = (*DepCache)[P];
       pkgDepCache::StateCache &state = (*DepCache)[P];
-      if (_config->FindB("APT::Cmd::Installed") == true)
+      if (insertCurrentVer == true)
       {
       {
-         if (P.CurrentVer() != NULL)
-         {
-            output_set.insert(P.CurrentVer());
-         }
+	 if (P->CurrentVer != 0)
+	    vci->FromPackage(vci, CacheFile, P, APT::VersionContainerInterface::INSTALLED, helper);
       }
       }
-      else if (_config->FindB("APT::Cmd::Upgradable") == true)
+      else if (insertUpgradable == true)
       {
       {
-         if(P.CurrentVer() && state.Upgradable())
-         {
-             pkgPolicy *policy = CacheFile.GetPolicy();
-             output_set.insert(policy->GetCandidateVer(P));
-         }
+	 if(P.CurrentVer() && state.Upgradable())
+	    vci->FromPackage(vci, CacheFile, P, APT::VersionContainerInterface::CANDIDATE, helper);
       }
       }
-      else if (_config->FindB("APT::Cmd::Manual-Installed") == true)
+      else if (insertManualInstalled == true)
       {
       {
-         if (P.CurrentVer() && 
-             ((*DepCache)[P].Flags & pkgCache::Flag::Auto) == false)
-         {
-             pkgPolicy *policy = CacheFile.GetPolicy();
-             output_set.insert(policy->GetCandidateVer(P));
-         }
+	 if (P.CurrentVer() &&
+	       ((*DepCache)[P].Flags & pkgCache::Flag::Auto) == false)
+	    vci->FromPackage(vci, CacheFile, P, APT::VersionContainerInterface::CANDIDATE, helper);
       }
       }
-      else 
+      else
       {
       {
-         pkgPolicy *policy = CacheFile.GetPolicy();
-         if (policy->GetCandidateVer(P).IsGood())
-            output_set.insert(policy->GetCandidateVer(P));
-         else 
-            // no candidate, this may happen for packages in 
-            // dpkg "deinstall ok config-file" state - we pick the first ver
-            // (which should be the only one)
-            output_set.insert(P.VersionList());
+         if (vci->FromPackage(vci, CacheFile, P, APT::VersionContainerInterface::CANDIDATE, helper) == false)
+	 {
+	    // no candidate, this may happen for packages in
+	    // dpkg "deinstall ok config-file" state - we pick the first ver
+	    // (which should be the only one)
+	    vci->insert(P.VersionList());
+	 }
       }
       }
    }
    }
-   progress.Done();
+   if (progress != NULL)
+      progress->Done();
    return true;
    return true;
 }
 }

+ 6 - 6
apt-private/private-cacheset.h

@@ -62,13 +62,13 @@ public:
 };
 };
 
 
 // FIXME: add default argument for OpProgress (or overloaded function)
 // FIXME: add default argument for OpProgress (or overloaded function)
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                    LocalitySortedVersionSet &output_set,
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                    APT::VersionContainerInterface * const vci,
                                     Matcher &matcher,
                                     Matcher &matcher,
-                                    OpProgress &progress);
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                    LocalitySortedVersionSet &output_set,
-                                    OpProgress &progress);
+                                    OpProgress * const progress);
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                    APT::VersionContainerInterface * const vci,
+                                    OpProgress * const progress);
 
 
 
 
 // CacheSetHelper saving virtual packages				/*{{{*/
 // CacheSetHelper saving virtual packages				/*{{{*/

+ 7 - 2
apt-private/private-cmndline.cc

@@ -70,6 +70,8 @@ static bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char cons
    else
    else
       return false;
       return false;
 
 
+   bool const found_something = Args.empty() == false;
+
    // FIXME: move to the correct command(s)
    // FIXME: move to the correct command(s)
    addArg('g', "generate", "APT::Cache::Generate", 0);
    addArg('g', "generate", "APT::Cache::Generate", 0);
    addArg('t', "target-release", "APT::Default-Release", CommandLine::HasArg);
    addArg('t', "target-release", "APT::Default-Release", CommandLine::HasArg);
@@ -77,7 +79,8 @@ static bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char cons
 
 
    addArg('p', "pkg-cache", "Dir::Cache::pkgcache", CommandLine::HasArg);
    addArg('p', "pkg-cache", "Dir::Cache::pkgcache", CommandLine::HasArg);
    addArg('s', "src-cache", "Dir::Cache::srcpkgcache", CommandLine::HasArg);
    addArg('s', "src-cache", "Dir::Cache::srcpkgcache", CommandLine::HasArg);
-   return true;
+
+   return found_something;
 }
 }
 									/*}}}*/
 									/*}}}*/
 static bool addArgumentsAPTCDROM(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
 static bool addArgumentsAPTCDROM(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
@@ -172,6 +175,8 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
       addArg('s', "no-act", "APT::Get::Simulate", 0);
       addArg('s', "no-act", "APT::Get::Simulate", 0);
    }
    }
 
 
+   bool const found_something = Args.empty() == false;
+
    // FIXME: move to the correct command(s)
    // FIXME: move to the correct command(s)
    addArg('d',"download-only","APT::Get::Download-Only",0);
    addArg('d',"download-only","APT::Get::Download-Only",0);
    addArg('y',"yes","APT::Get::Assume-Yes",0);
    addArg('y',"yes","APT::Get::Assume-Yes",0);
@@ -197,7 +202,7 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
    addArg(0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean);
    addArg(0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean);
    addArg(0,"fix-policy","APT::Get::Fix-Policy-Broken",0);
    addArg(0,"fix-policy","APT::Get::Fix-Policy-Broken",0);
 
 
-   return true;
+   return found_something;
 }
 }
 									/*}}}*/
 									/*}}}*/
 static bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/
 static bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const * const Cmd)/*{{{*/

+ 18 - 23
apt-private/private-list.cc

@@ -77,15 +77,14 @@ private:
 };
 };
 									/*}}}*/
 									/*}}}*/
 static void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records,/*{{{*/
 static void ListAllVersions(pkgCacheFile &CacheFile, pkgRecords &records,/*{{{*/
-                     pkgCache::PkgIterator P,    
-                     std::ostream &outs,
-                     bool include_summary=true)
+                     pkgCache::PkgIterator const &P, std::ostream &outs,
+                     std::string const &format)
 {
 {
    for (pkgCache::VerIterator Ver = P.VersionList();
    for (pkgCache::VerIterator Ver = P.VersionList();
         Ver.end() == false; ++Ver)
         Ver.end() == false; ++Ver)
    {
    {
-      ListSingleVersion(CacheFile, records, Ver, outs, include_summary);
-      outs << "\n";
+      ListSingleVersion(CacheFile, records, Ver, outs, format);
+      outs << std::endl;
    }
    }
 }
 }
 									/*}}}*/
 									/*}}}*/
@@ -109,10 +108,9 @@ bool DoList(CommandLine &Cmd)
       patterns = Cmd.FileList + 1;
       patterns = Cmd.FileList + 1;
    }
    }
 
 
-   std::map<std::string, std::string> output_map;
-   std::map<std::string, std::string>::const_iterator K;
-
-   bool includeSummary = _config->FindB("APT::Cmd::List-Include-Summary");
+   std::string format = "${color:highlight}${Package}${color:neutral}/${Origin} ${Version} ${Architecture}${ }${apt:Status}";
+   if (_config->FindB("APT::Cmd::List-Include-Summary", false) == true)
+      format += "\n  ${Description}\n";
 
 
    PackageNameMatcher matcher(patterns);
    PackageNameMatcher matcher(patterns);
    LocalitySortedVersionSet bag;
    LocalitySortedVersionSet bag;
@@ -121,37 +119,34 @@ bool DoList(CommandLine &Cmd)
                             Cache->Head().PackageCount, 
                             Cache->Head().PackageCount, 
                             Cache->Head().PackageCount,
                             Cache->Head().PackageCount,
                             _("Listing"));
                             _("Listing"));
-   GetLocalitySortedVersionSet(CacheFile, bag, matcher, progress);
-   bool ShowAllVersions = _config->FindB("APT::Cmd::All-Versions", false);
+   GetLocalitySortedVersionSet(CacheFile, &bag, matcher, &progress);
+   bool const ShowAllVersions = _config->FindB("APT::Cmd::All-Versions", false);
+   std::map<std::string, std::string> output_map;
    for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); ++V)
    for (LocalitySortedVersionSet::iterator V = bag.begin(); V != bag.end(); ++V)
    {
    {
       std::stringstream outs;
       std::stringstream outs;
       if(ShowAllVersions == true)
       if(ShowAllVersions == true)
-      {
-         ListAllVersions(CacheFile, records, V.ParentPkg(), outs, includeSummary);
-         output_map.insert(std::make_pair<std::string, std::string>(
-            V.ParentPkg().Name(), outs.str()));
-      } else {
-         ListSingleVersion(CacheFile, records, V, outs, includeSummary);
-         output_map.insert(std::make_pair<std::string, std::string>(
-                           V.ParentPkg().Name(), outs.str()));
-      }
+         ListAllVersions(CacheFile, records, V.ParentPkg(), outs, format);
+      else
+         ListSingleVersion(CacheFile, records, V, outs, format);
+      output_map.insert(std::make_pair<std::string, std::string>(
+	       V.ParentPkg().Name(), outs.str()));
    }
    }
 
 
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // output the sorted map
    // output the sorted map
+   std::map<std::string, std::string>::const_iterator K;
    for (K = output_map.begin(); K != output_map.end(); ++K)
    for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
       std::cout << (*K).second << std::endl;
 
 
-
    // be nice and tell the user if there is more to see
    // be nice and tell the user if there is more to see
    if (bag.size() == 1 && ShowAllVersions == false)
    if (bag.size() == 1 && ShowAllVersions == false)
    {
    {
       // start with -1 as we already displayed one version
       // start with -1 as we already displayed one version
       int versions = -1;
       int versions = -1;
       pkgCache::VerIterator Ver = *bag.begin();
       pkgCache::VerIterator Ver = *bag.begin();
-      for ( ; Ver.end() == false; Ver++)
-         versions++;
+      for ( ; Ver.end() == false; ++Ver)
+         ++versions;
       if (versions > 0)
       if (versions > 0)
          _error->Notice(P_("There is %i additional version. Please use the '-a' switch to see it", "There are %i additional versions. Please use the '-a' switch to see them.", versions), versions);
          _error->Notice(P_("There is %i additional version. Please use the '-a' switch to see it", "There are %i additional versions. Please use the '-a' switch to see them.", versions), versions);
    }
    }

+ 95 - 75
apt-private/private-output.cc

@@ -164,15 +164,26 @@ static std::string GetVersion(pkgCacheFile &/*CacheFile*/, pkgCache::VerIterator
 									/*}}}*/
 									/*}}}*/
 static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 static std::string GetArchitecture(pkgCacheFile &CacheFile, pkgCache::PkgIterator P)/*{{{*/
 {
 {
-   pkgPolicy *policy = CacheFile.GetPolicy();
-   pkgCache::VerIterator inst = P.CurrentVer();
-   pkgCache::VerIterator cand = policy->GetCandidateVer(P);
-
-   // this may happen for packages in dpkg "deinstall ok config-file" state
-   if (inst.IsGood() == false && cand.IsGood() == false)
-      return P.VersionList().Arch();
-
-   return inst ? inst.Arch() : cand.Arch();
+   if (P->CurrentVer == 0)
+   {
+      pkgDepCache * const DepCache = CacheFile.GetDepCache();
+      pkgDepCache::StateCache const &state = (*DepCache)[P];
+      if (state.CandidateVer != NULL)
+      {
+	 pkgCache::VerIterator const CandV(CacheFile, state.CandidateVer);
+	 return CandV.Arch();
+      }
+      else
+      {
+	 pkgCache::VerIterator const V = P.VersionList();
+	 if (V.end() == false)
+	    return V.Arch();
+	 else
+	    return P.Arch();
+      }
+   }
+   else
+      return P.CurrentVer().Arch();
 }
 }
 									/*}}}*/
 									/*}}}*/
 static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
 static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
@@ -196,81 +207,90 @@ static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &reco
    return ShortDescription;
    return ShortDescription;
 }
 }
 									/*}}}*/
 									/*}}}*/
-void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
-                       pkgCache::VerIterator V, std::ostream &out,
-                       bool include_summary)
+static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &records, pkgCache::PkgIterator P)/*{{{*/
 {
 {
-   pkgCache::PkgIterator P = V.ParentPkg();
+   pkgPolicy *policy = CacheFile.GetPolicy();
 
 
-   pkgDepCache *DepCache = CacheFile.GetDepCache();
-   pkgDepCache::StateCache &state = (*DepCache)[P];
+   pkgCache::VerIterator ver;
+   if (P->CurrentVer != 0)
+      ver = P.CurrentVer();
+   else
+      ver = policy->GetCandidateVer(P);
+
+   std::string const EmptyDescription = "(none)";
+   if(ver.end() == true)
+      return EmptyDescription;
 
 
-   std::string suite = GetArchiveSuite(CacheFile, V);
-   std::string name_str = P.Name();
+   pkgCache::DescIterator const Desc = ver.TranslatedDescription();
+   pkgRecords::Parser & parser = records.Lookup(Desc.FileList());
+   std::string const longdesc = parser.LongDesc();
+   if (longdesc.empty() == true)
+      return EmptyDescription;
+   return SubstVar(longdesc, "\n ", "\n  ");
+}
+									/*}}}*/
+void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,	/*{{{*/
+                       pkgCache::VerIterator const &V, std::ostream &out,
+                       std::string const &format)
+{
+   pkgCache::PkgIterator const P = V.ParentPkg();
+   pkgDepCache * const DepCache = CacheFile.GetDepCache();
+   pkgDepCache::StateCache const &state = (*DepCache)[P];
 
 
+   std::string output;
    if (_config->FindB("APT::Cmd::use-format", false))
    if (_config->FindB("APT::Cmd::use-format", false))
+      output = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
+   else
+      output = format;
+
+   // FIXME: some of these names are really icky – and all is nowhere documented
+   output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
+   output = SubstVar(output, "${Package}", P.Name());
+   std::string const ArchStr = GetArchitecture(CacheFile, P);
+   output = SubstVar(output, "${Architecture}", ArchStr);
+   std::string const InstalledVerStr = GetInstalledVersion(CacheFile, P);
+   output = SubstVar(output, "${installed:Version}", InstalledVerStr);
+   std::string const CandidateVerStr = GetCandidateVersion(CacheFile, P);
+   output = SubstVar(output, "${candidate:Version}", CandidateVerStr);
+   std::string const VersionStr = GetVersion(CacheFile, V);
+   output = SubstVar(output, "${Version}", VersionStr);
+   output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
+
+   std::string StatusStr = "";
+   if (P->CurrentVer != 0)
    {
    {
-      std::string format = _config->Find("APT::Cmd::format", "${db::Status-Abbrev} ${Package} ${Version} ${Origin} ${Description}");
-      std::string output = format;
-   
-      output = SubstVar(output, "${db::Status-Abbrev}", GetFlagsStr(CacheFile, P));
-      output = SubstVar(output, "${Package}", name_str);
-      output = SubstVar(output, "${installed:Version}", GetInstalledVersion(CacheFile, P));
-      output = SubstVar(output, "${candidate:Version}", GetCandidateVersion(CacheFile, P));
-      output = SubstVar(output, "${Version}", GetVersion(CacheFile, V));
-      output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
-      output = SubstVar(output, "${Origin}", GetArchiveSuite(CacheFile, V));
-      out << output;
-   } else {
-      // raring/linux-kernel version [upradable: new-version]
-      //    description
-      pkgPolicy *policy = CacheFile.GetPolicy();
-      std::string VersionStr = GetVersion(CacheFile, V);
-      std::string CandidateVerStr = GetCandidateVersion(CacheFile, P);
-      std::string InstalledVerStr = GetInstalledVersion(CacheFile, P);
-      std::string StatusStr;
-      if(P.CurrentVer() == V && state.Upgradable())
+      if (P.CurrentVer() == V)
       {
       {
-         strprintf(StatusStr, _("[installed,upgradable to: %s]"),
-                   CandidateVerStr.c_str());
-      } else if (P.CurrentVer() == V) {
-         if(!V.Downloadable())
-            StatusStr = _("[installed,local]");
-         else
-            if(V.Automatic() && state.Garbage)
-               StatusStr = _("[installed,auto-removable]");
-            else if (state.Flags & pkgCache::Flag::Auto)
-               StatusStr = _("[installed,automatic]");
-            else
-               StatusStr = _("[installed]");
-      } else if (P.CurrentVer() && 
-                 policy->GetCandidateVer(P) == V && 
-                 state.Upgradable()) {
-            strprintf(StatusStr, _("[upgradable from: %s]"),
-                      InstalledVerStr.c_str());
-      } else {
-         if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
-            StatusStr = _("[residual-config]");
-         else
-            StatusStr = "";
-      }
-      out << std::setiosflags(std::ios::left)
-          << _config->Find("APT::Color::Highlight", "")
-          << name_str 
-          << _config->Find("APT::Color::Neutral", "")
-          << "/" << suite
-          << " "
-          << VersionStr << " " 
-          << GetArchitecture(CacheFile, P);
-      if (StatusStr != "") 
-         out << " " << StatusStr;
-      if (include_summary)
-      {
-         out << std::endl 
-             << "  " << GetShortDescription(CacheFile, records, P)
-             << std::endl;
+	 if (state.Upgradable() && state.CandidateVer != NULL)
+	    strprintf(StatusStr, _("[installed,upgradable to: %s]"),
+		  CandidateVerStr.c_str());
+	 else if (V.Downloadable() == false)
+	    StatusStr = _("[installed,local]");
+	 else if(V.Automatic() == true && state.Garbage == true)
+	    StatusStr = _("[installed,auto-removable]");
+	 else if ((state.Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto)
+	    StatusStr = _("[installed,automatic]");
+	 else
+	    StatusStr = _("[installed]");
       }
       }
+      else if (state.CandidateVer == V && state.Upgradable())
+	 strprintf(StatusStr, _("[upgradable from: %s]"),
+	       InstalledVerStr.c_str());
    }
    }
+   else if (V.ParentPkg()->CurrentState == pkgCache::State::ConfigFiles)
+      StatusStr = _("[residual-config]");
+   output = SubstVar(output, "${apt:Status}", StatusStr);
+   output = SubstVar(output, "${color:highlight}", _config->Find("APT::Color::Highlight", ""));
+   output = SubstVar(output, "${color:neutral}", _config->Find("APT::Color::Neutral", ""));
+   output = SubstVar(output, "${Description}", GetShortDescription(CacheFile, records, P));
+   output = SubstVar(output, "${LongDescription}", GetLongDescription(CacheFile, records, P));
+   output = SubstVar(output, "${ }${ }", "${ }");
+   output = SubstVar(output, "${ }\n", "\n");
+   output = SubstVar(output, "${ }", " ");
+   if (APT::String::Endswith(output, " ") == true)
+      output.erase(output.length() - 1);
+
+   out << output;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // ShowList - Show a list						/*{{{*/
 // ShowList - Show a list						/*{{{*/

+ 2 - 2
apt-private/private-output.h

@@ -23,8 +23,8 @@ APT_PUBLIC extern unsigned int ScreenWidth;
 APT_PUBLIC bool InitOutput();
 APT_PUBLIC bool InitOutput();
 
 
 void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,
 void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records,
-                       pkgCache::VerIterator V, std::ostream &out,
-                       bool include_summary=true);
+                       pkgCache::VerIterator const &V, std::ostream &out,
+                       std::string const &format);
 
 
 
 
 // helper to describe global state
 // helper to describe global state

+ 58 - 24
apt-private/private-search.cc

@@ -32,61 +32,95 @@ bool FullTextSearch(CommandLine &CmdL)					/*{{{*/
    pkgCacheFile CacheFile;
    pkgCacheFile CacheFile;
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
    pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
-   pkgRecords records(CacheFile);
    if (unlikely(Cache == NULL || Plcy == NULL))
    if (unlikely(Cache == NULL || Plcy == NULL))
       return false;
       return false;
 
 
-   const char **patterns;
-   patterns = CmdL.FileList + 1;
+   // Make sure there is at least one argument
+   unsigned int const NumPatterns = CmdL.FileSize() -1;
+   if (NumPatterns < 1)
+      return _error->Error(_("You must give at least one search pattern"));
+
+#define APT_FREE_PATTERNS() for (std::vector<regex_t>::iterator P = Patterns.begin(); \
+      P != Patterns.end(); ++P) { regfree(&(*P)); }
+
+   // Compile the regex pattern
+   std::vector<regex_t> Patterns;
+   for (unsigned int I = 0; I != NumPatterns; ++I)
+   {
+      regex_t pattern;
+      if (regcomp(&pattern, CmdL.FileList[I + 1], REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0)
+      {
+	 APT_FREE_PATTERNS();
+	 return _error->Error("Regex compilation error");
+      }
+      Patterns.push_back(pattern);
+   }
+
+   bool const NamesOnly = _config->FindB("APT::Cache::NamesOnly", false);
 
 
    std::map<std::string, std::string> output_map;
    std::map<std::string, std::string> output_map;
-   std::map<std::string, std::string>::const_iterator K;
 
 
    LocalitySortedVersionSet bag;
    LocalitySortedVersionSet bag;
    OpTextProgress progress(*_config);
    OpTextProgress progress(*_config);
    progress.OverallProgress(0, 100, 50,  _("Sorting"));
    progress.OverallProgress(0, 100, 50,  _("Sorting"));
-   GetLocalitySortedVersionSet(CacheFile, bag, progress);
+   GetLocalitySortedVersionSet(CacheFile, &bag, &progress);
    LocalitySortedVersionSet::iterator V = bag.begin();
    LocalitySortedVersionSet::iterator V = bag.begin();
 
 
    progress.OverallProgress(50, 100, 50,  _("Full Text Search"));
    progress.OverallProgress(50, 100, 50,  _("Full Text Search"));
    progress.SubProgress(bag.size());
    progress.SubProgress(bag.size());
+   pkgRecords records(CacheFile);
+
+   std::string format = "${color:highlight}${Package}${color:neutral}/${Origin} ${Version} ${Architecture}${ }${apt:Status}\n";
+   if (_config->FindB("APT::Cache::ShowFull",false) == false)
+      format += "  ${Description}\n";
+   else
+      format += "  ${LongDescription}\n";
+
    int Done = 0;
    int Done = 0;
+   std::vector<bool> PkgsDone(Cache->Head().PackageCount, false);
    for ( ;V != bag.end(); ++V)
    for ( ;V != bag.end(); ++V)
    {
    {
       if (Done%500 == 0)
       if (Done%500 == 0)
          progress.Progress(Done);
          progress.Progress(Done);
       ++Done;
       ++Done;
-      
-      int i;
+
+      // we want to list each package only once
+      pkgCache::PkgIterator const P = V.ParentPkg();
+      if (PkgsDone[P->ID] == true)
+	 continue;
+
+      char const * const PkgName = P.Name();
       pkgCache::DescIterator Desc = V.TranslatedDescription();
       pkgCache::DescIterator Desc = V.TranslatedDescription();
       pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
       pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
-     
+      std::string const LongDesc = parser.LongDesc();
+
       bool all_found = true;
       bool all_found = true;
-      for(i=0; patterns[i] != NULL; ++i)
+      for (std::vector<regex_t>::const_iterator pattern = Patterns.begin();
+	    pattern != Patterns.end(); ++pattern)
       {
       {
-         // FIXME: use regexp instead of simple find()
-         const char *pattern = patterns[i];
-         all_found &=  (
-            strstr(V.ParentPkg().Name(), pattern) != NULL ||
-            strcasestr(parser.ShortDesc().c_str(), pattern) != NULL ||
-            strcasestr(parser.LongDesc().c_str(), pattern) != NULL);
-         // search patterns are AND by default so we can skip looking further
-         // on the first mismatch
-         if(all_found == false)
-            break;
+	 if (regexec(&(*pattern), PkgName, 0, 0, 0) == 0)
+	    continue;
+	 else if (NamesOnly == false && regexec(&(*pattern), LongDesc.c_str(), 0, 0, 0) == 0)
+	    continue;
+	 // search patterns are AND, so one failing fails all
+	 all_found = false;
+	 break;
       }
       }
-      if (all_found)
+      if (all_found == true)
       {
       {
-            std::stringstream outs;
-            ListSingleVersion(CacheFile, records, V, outs);
-            output_map.insert(std::make_pair<std::string, std::string>(
-                                 V.ParentPkg().Name(), outs.str()));
+	 PkgsDone[P->ID] = true;
+	 std::stringstream outs;
+	 ListSingleVersion(CacheFile, records, V, outs, format);
+	 output_map.insert(std::make_pair<std::string, std::string>(
+		  PkgName, outs.str()));
       }
       }
    }
    }
+   APT_FREE_PATTERNS();
    progress.Done();
    progress.Done();
 
 
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // output the sorted map
    // output the sorted map
+   std::map<std::string, std::string>::const_iterator K;
    for (K = output_map.begin(); K != output_map.end(); ++K)
    for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
       std::cout << (*K).second << std::endl;
 
 

+ 41 - 17
apt-private/private-utils.cc

@@ -8,45 +8,69 @@
 #include <cstdlib>
 #include <cstdlib>
 #include <unistd.h>
 #include <unistd.h>
 
 
-// DisplayFileInPager - Display File with pager        			/*{{{*/
-void DisplayFileInPager(std::string filename)
+// DisplayFileInPager - Display File with pager				/*{{{*/
+void DisplayFileInPager(std::string const &filename)
 {
 {
-   std::string pager = _config->Find("Dir::Bin::Pager", 
-                                        "/usr/bin/sensible-pager");
-
    pid_t Process = ExecFork();
    pid_t Process = ExecFork();
    if (Process == 0)
    if (Process == 0)
    {
    {
       const char *Args[3];
       const char *Args[3];
-      Args[0] = pager.c_str();
       Args[1] = filename.c_str();
       Args[1] = filename.c_str();
-      Args[2] = 0;
+      Args[2] = NULL;
+      if (isatty(STDOUT_FILENO) == 1)
+      {
+	 // likely installed, provided by sensible-utils
+	 std::string const pager = _config->Find("Dir::Bin::Pager",
+	       "sensible-pager");
+	 Args[0] = pager.c_str();
+	 execvp(Args[0],(char **)Args);
+	 // lets try some obvious alternatives
+	 Args[0] = getenv("PAGER");
+	 if (Args[0] != NULL)
+	    execvp(Args[0],(char **)Args);
+
+	 Args[0] = "pager";
+	 execvp(Args[0],(char **)Args);
+      }
+      // we could read the file ourselves, but… meh
+      Args[0] = "cat";
       execvp(Args[0],(char **)Args);
       execvp(Args[0],(char **)Args);
       exit(100);
       exit(100);
    }
    }
-         
+
    // Wait for the subprocess
    // Wait for the subprocess
-   ExecWait(Process, "sensible-pager", false);
+   ExecWait(Process, "pager", false);
 }
 }
 									/*}}}*/
 									/*}}}*/
-// EditFileInSensibleEditor - Edit File with editor    			/*{{{*/
-void EditFileInSensibleEditor(std::string filename)
+// EditFileInSensibleEditor - Edit File with editor			/*{{{*/
+void EditFileInSensibleEditor(std::string const &filename)
 {
 {
-   std::string editor = _config->Find("Dir::Bin::Editor", 
-                                        "/usr/bin/sensible-editor");
-
    pid_t Process = ExecFork();
    pid_t Process = ExecFork();
    if (Process == 0)
    if (Process == 0)
    {
    {
+      // likely installed, provided by sensible-utils
+      std::string const editor = _config->Find("Dir::Bin::Editor",
+	    "sensible-editor");
       const char *Args[3];
       const char *Args[3];
       Args[0] = editor.c_str();
       Args[0] = editor.c_str();
       Args[1] = filename.c_str();
       Args[1] = filename.c_str();
-      Args[2] = 0;
+      Args[2] = NULL;
+      execvp(Args[0],(char **)Args);
+      // the usual suspects we can try as an alternative
+      Args[0] = getenv("VISUAL");
+      if (Args[0] != NULL)
+	 execvp(Args[0],(char **)Args);
+
+      Args[0] = getenv("EDITOR");
+      if (Args[0] != NULL)
+	 execvp(Args[0],(char **)Args);
+
+      Args[0] = "editor";
       execvp(Args[0],(char **)Args);
       execvp(Args[0],(char **)Args);
       exit(100);
       exit(100);
    }
    }
-         
+
    // Wait for the subprocess
    // Wait for the subprocess
-   ExecWait(Process, "sensible-editor", false);
+   ExecWait(Process, "editor", false);
 }
 }
 									/*}}}*/
 									/*}}}*/

+ 2 - 2
apt-private/private-utils.h

@@ -5,7 +5,7 @@
 
 
 #include <string>
 #include <string>
 
 
-APT_PUBLIC void DisplayFileInPager(std::string filename);
-APT_PUBLIC void EditFileInSensibleEditor(std::string filename);
+APT_PUBLIC void DisplayFileInPager(std::string const &filename);
+APT_PUBLIC void EditFileInSensibleEditor(std::string const &filename);
 
 
 #endif
 #endif

+ 1 - 1
configure.ac

@@ -18,7 +18,7 @@ AC_CONFIG_AUX_DIR(buildlib)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in)
 
 
 PACKAGE="apt"
 PACKAGE="apt"
-PACKAGE_VERSION="1.1~exp2"
+PACKAGE_VERSION="1.1~exp3"
 PACKAGE_MAIL="APT Development Team <deity@lists.debian.org>"
 PACKAGE_MAIL="APT Development Team <deity@lists.debian.org>"
 AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
 AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
 AC_DEFINE_UNQUOTED(PACKAGE_VERSION,"$PACKAGE_VERSION")
 AC_DEFINE_UNQUOTED(PACKAGE_VERSION,"$PACKAGE_VERSION")

+ 78 - 0
debian/changelog

@@ -68,6 +68,84 @@ apt (1.1~exp1) experimental; urgency=low
 
 
  -- Michael Vogt <mvo@debian.org>  Thu, 19 Jun 2014 12:01:48 +0200
  -- Michael Vogt <mvo@debian.org>  Thu, 19 Jun 2014 12:01:48 +0200
 
 
+apt (1.0.9.1) unstable; urgency=high
+
+  [ Michael Vogt ]
+  * Allow override of Proxy-Auto-Detect by the users configuration
+    (Closes: 759264)
+  * fix ci autopkgtest
+  * fix regression from 1.0.9 when file:/// source are used and
+    those are on a different partition than the apt state directory
+    and add regression test
+
+  [ Trần Ngọc Quân ]
+  * l10n: vi.po (636t): Update program translation
+
+  [ Chris Leick ]
+  * Updated German documentation translation
+
+  [ Mert Dirik ]
+  * Turkish program translation update (Closes: 761394)
+
+ -- Michael Vogt <mvo@debian.org>  Tue, 16 Sep 2014 20:52:25 +0200
+
+apt (1.0.9) unstable; urgency=high
+
+  * SECURITY UPDATE:
+    - incorrect invalidating of unauthenticated data (CVE-2014-0488)
+    - incorect verification of 304 reply (CVE-2014-0487)
+    - incorrect verification of Acquire::Gzip indexes (CVE-2014-0489)
+
+ -- Michael Vogt <mvo@debian.org>  Mon, 15 Sep 2014 08:34:46 +0200
+
+apt (1.0.8) unstable; urgency=medium
+
+  [ Holger Wansing ]
+  * German program translation update (Closes: 758837)
+
+  [ Américo Monteiro ]
+  * Portuguese manpages translation update (Closes: 759608)
+
+  [ Warren He ]
+  * initialize iPolicyBrokenCount in DepCache::Update (Closes: 758397)
+
+  [ Andreas Oberritter ]
+  * Avoid yielding blank lines with APT::Cmd::use-format=true
+
+  [ Michael Vogt ]
+  * Make Proxy-Auto-Detect check for each host (Closes: #759264)
+  * Add testcase for apt list --all-versions
+  * * apt-pkg/deb/dpkgpm.cc:
+    - update string matching for dpkg I/O errors. (LP: #1363257)
+    - properly parse the dpkg status line so that package name 
+      is properly set and an apport report is created. Thanks 
+      to Anders Kaseorg for the patch  (LP: #1353171)
+  * Use heap to allocate PatternMatch to avoid potential stack overflow
+    (Closes: 759612)
+  * Run autopkgtest tests with "env -i" to avoid pollution from the host env
+    (Closes: #759655)
+  * test/integration/test-ubuntu-bug-346386-apt-get-update-paywall: 
+    - use downloadfile() to fix test failure
+  * Fix incorrect upgradable listing in "apt list" 
+    (thanks to Michael Musenbrock) (Closes: #753297)
+  * apt-pkg/cachefile.cc:
+    - ensure we have a Policy in CacheFile.BuildDepCache()
+  * methods/http.cc:
+    - Improve Debug::Acquire::http debug output
+
+  [ Dimitri John Ledkov ]
+  * apt-ftparchive: make Packages & Sources generation optional, 
+    during Generate call
+
+  [ David Kalnischkies ]
+  * support regular expressions in 'apt search'
+  * implement --full in apt search
+  * fix progress report for upgrade and reinstall
+  * rework PTY magic to fix stair-stepping on kfreebsd (Closes: 759684)
+  * don't call pager in non-terminals for changelog (Closes: 755040)
+
+ -- Michael Vogt <mvo@debian.org>  Tue, 09 Sep 2014 20:09:11 +0200
+
 apt (1.0.7) unstable; urgency=medium
 apt (1.0.7) unstable; urgency=medium
 
 
   [ Michael Vogt ]
   [ Michael Vogt ]

+ 2 - 0
debian/gbp.conf

@@ -3,3 +3,5 @@ prebuild = ./prepare-release pre-export
 postbuild = ./prepare-release post-build
 postbuild = ./prepare-release post-build
 debian-branch = debian/experimental
 debian-branch = debian/experimental
 debian-tag = %(version)s
 debian-tag = %(version)s
+export-dir = ../build-area
+sign-tags = True

+ 1 - 1
doc/Doxyfile.in

@@ -1128,7 +1128,7 @@ HTML_COLORSTYLE_GAMMA  = 80
 # The default value is: YES.
 # The default value is: YES.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
 
-HTML_TIMESTAMP         = YES
+HTML_TIMESTAMP         = NO
 
 
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # documentation will contain sections that can be hidden and shown after the
 # documentation will contain sections that can be hidden and shown after the

+ 1 - 1
doc/apt-verbatim.ent

@@ -225,7 +225,7 @@
 ">
 ">
 
 
 <!-- this will be updated by 'prepare-release' -->
 <!-- this will be updated by 'prepare-release' -->
-<!ENTITY apt-product-version "1.0.7">
+<!ENTITY apt-product-version "1.0.9.1">
 
 
 <!-- (Code)names for various things used all over the place -->
 <!-- (Code)names for various things used all over the place -->
 <!ENTITY oldstable-codename "squeeze">
 <!ENTITY oldstable-codename "squeeze">

+ 2 - 2
doc/po/apt-doc.pot

@@ -6,9 +6,9 @@
 #, fuzzy
 #, fuzzy
 msgid ""
 msgid ""
 msgstr ""
 msgstr ""
-"Project-Id-Version: apt-doc 1.0.7\n"
+"Project-Id-Version: apt-doc 1.0.8\n"
 "Report-Msgid-Bugs-To: APT Development Team <deity@lists.debian.org>\n"
 "Report-Msgid-Bugs-To: APT Development Team <deity@lists.debian.org>\n"
-"POT-Creation-Date: 2014-08-28 00:44+0000\n"
+"POT-Creation-Date: 2014-09-18 07:57+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"

+ 7 - 117
doc/po/de.po

@@ -5,10 +5,10 @@
 #
 #
 msgid ""
 msgid ""
 msgstr ""
 msgstr ""
-"Project-Id-Version: apt-doc 1.0.4\n"
+"Project-Id-Version: apt-doc 1.0.8\n"
 "Report-Msgid-Bugs-To: APT Development Team <deity@lists.debian.org>\n"
 "Report-Msgid-Bugs-To: APT Development Team <deity@lists.debian.org>\n"
 "POT-Creation-Date: 2014-08-28 00:20+0000\n"
 "POT-Creation-Date: 2014-08-28 00:20+0000\n"
-"PO-Revision-Date: 2014-07-04 00:34+0200\n"
+"PO-Revision-Date: 2014-09-14 14:46+0200\n"
 "Last-Translator: Chris Leick <c.leick@vollbio.de>\n"
 "Last-Translator: Chris Leick <c.leick@vollbio.de>\n"
 "Language-Team: German <debian-l10n-german@lists.debian.org>\n"
 "Language-Team: German <debian-l10n-german@lists.debian.org>\n"
 "Language: de\n"
 "Language: de\n"
@@ -750,12 +750,6 @@ msgstr ""
 
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>
 #: apt.8.xml:101
 #: apt.8.xml:101
-#, fuzzy
-#| msgid ""
-#| "<literal>upgrade</literal> is used to install the newest versions of all "
-#| "packages currently installed on the system from the sources enumerated in "
-#| "<filename>/etc/apt/sources.list</filename>. New package will be "
-#| "installed, but existing package will never removed."
 msgid ""
 msgid ""
 "<literal>upgrade</literal> is used to install the newest versions of all "
 "<literal>upgrade</literal> is used to install the newest versions of all "
 "packages currently installed on the system from the sources enumerated in "
 "packages currently installed on the system from the sources enumerated in "
@@ -4591,17 +4585,6 @@ msgstr ""
 
 
 #. type: Content of: <refentry><refsect1><para>
 #. type: Content of: <refentry><refsect1><para>
 #: apt.conf.5.xml:601
 #: apt.conf.5.xml:601
-#, fuzzy
-#| msgid ""
-#| "<literal>Dir::Cache</literal> contains locations pertaining to local "
-#| "cache information, such as the two package caches <literal>srcpkgcache</"
-#| "literal> and <literal>pkgcache</literal> as well as the location to place "
-#| "downloaded archives, <literal>Dir::Cache::archives</literal>. Generation "
-#| "of caches can be turned off by setting their names to the empty string. "
-#| "This will slow down startup but save disk space. It is probably "
-#| "preferable to turn off the pkgcache rather than the srcpkgcache. Like "
-#| "<literal>Dir::State</literal> the default directory is contained in "
-#| "<literal>Dir::Cache</literal>"
 msgid ""
 msgid ""
 "<literal>Dir::Cache</literal> contains locations pertaining to local cache "
 "<literal>Dir::Cache</literal> contains locations pertaining to local cache "
 "information, such as the two package caches <literal>srcpkgcache</literal> "
 "information, such as the two package caches <literal>srcpkgcache</literal> "
@@ -4618,8 +4601,9 @@ msgstr ""
 "Paketzwischenspeicher <literal>srcpkgcache</literal> und <literal>pkgcache</"
 "Paketzwischenspeicher <literal>srcpkgcache</literal> und <literal>pkgcache</"
 "literal>, sowie den Ort, an den heruntergeladene Archive platziert werden, "
 "literal>, sowie den Ort, an den heruntergeladene Archive platziert werden, "
 "<literal>Dir::Cache::archives</literal>. Die Generierung von "
 "<literal>Dir::Cache::archives</literal>. Die Generierung von "
-"Zwischenspeichern kann ausgeschaltet werden, indem ihre Namen auf leere "
-"Zeichenketten gesetzt werden. Dies wird den Start verlangsamen, aber "
+"Zwischenspeichern kann ausgeschaltet werden, indem "
+"<literal>pkgcache</literal> oder <literal>srcpkgcache</literal> auf "
+"<literal>\"\"</literal> wird. Dies wird den Start verlangsamen, aber "
 "Plattenplatz sparen. Es ist vermutlich vorzuziehen, statt des »srcpkgcache«s "
 "Plattenplatz sparen. Es ist vermutlich vorzuziehen, statt des »srcpkgcache«s "
 "den »pkgcache« auszuschalten. Wie <literal>Dir::State</literal> ist das "
 "den »pkgcache« auszuschalten. Wie <literal>Dir::State</literal> ist das "
 "Standardverzeichnis in <literal>Dir::Cache</literal> enthalten."
 "Standardverzeichnis in <literal>Dir::Cache</literal> enthalten."
@@ -8549,7 +8533,7 @@ msgstr "jgg@debian.org"
 #. type: Content of: <book><bookinfo><releaseinfo>
 #. type: Content of: <book><bookinfo><releaseinfo>
 #: guide.dbk:21 offline.dbk:21
 #: guide.dbk:21 offline.dbk:21
 msgid "Version &apt-product-version;"
 msgid "Version &apt-product-version;"
-msgstr ""
+msgstr "Version &apt-product-version;"
 
 
 #. type: Content of: <book><bookinfo><abstract><para>
 #. type: Content of: <book><bookinfo><abstract><para>
 #: guide.dbk:25
 #: guide.dbk:25
@@ -8569,7 +8553,7 @@ msgstr ""
 #. type: Content of: <book><bookinfo><legalnotice><title>
 #. type: Content of: <book><bookinfo><legalnotice><title>
 #: guide.dbk:32 offline.dbk:33
 #: guide.dbk:32 offline.dbk:33
 msgid "License Notice"
 msgid "License Notice"
-msgstr ""
+msgstr "Lizenzhinweis"
 
 
 #. type: Content of: <book><bookinfo><legalnotice><para>
 #. type: Content of: <book><bookinfo><legalnotice><para>
 #: guide.dbk:34 offline.dbk:35
 #: guide.dbk:34 offline.dbk:35
@@ -10158,97 +10142,3 @@ msgstr "  # apt-get -o dir::cache::archives=\"/Platte/\" dist-upgrade\n"
 #: offline.dbk:242
 #: offline.dbk:242
 msgid "Which will use the already fetched archives on the disc."
 msgid "Which will use the already fetched archives on the disc."
 msgstr "Es wird die bereits auf die Platte heruntergeladenen Archive benutzen."
 msgstr "Es wird die bereits auf die Platte heruntergeladenen Archive benutzen."
-
-#~ msgid "$Id: guide.sgml,v 1.7 2003/04/26 23:26:13 doogie Exp $"
-#~ msgstr "$Id: guide.sgml,v 1.7 2003/04/26 23:26:13 doogie Exp $"
-
-#~ msgid "<pubdate></pubdate>"
-#~ msgstr "<pubdate></pubdate>"
-
-#~ msgid "$Id: offline.sgml,v 1.8 2003/02/12 15:06:41 doogie Exp $"
-#~ msgstr "$Id: offline.sgml,v 1.8 12.02.2003 15:06:41 doogie Exp $"
-
-#~ msgid "<name>Jason Gunthorpe </name><email>jgg@debian.org</email>"
-#~ msgstr "<name>Jason Gunthorpe </name><email>jgg@debian.org</email>"
-
-#~ msgid "Copyright &copy; Jason Gunthorpe, 1998."
-#~ msgstr "Copyright &copy; Jason Gunthorpe, 1998."
-
-#~ msgid "Copyright &copy; Jason Gunthorpe, 1999."
-#~ msgstr "Copyright &copy; Jason Gunthorpe, 1999."
-
-#~ msgid "apt"
-#~ msgstr "apt"
-
-#~ msgid "16 June 1998"
-#~ msgstr "16. Juni 1998"
-
-#~ msgid "Debian"
-#~ msgstr "Debian"
-
-#~ msgid "NAME"
-#~ msgstr "NAME"
-
-#~ msgid "apt - Advanced Package Tool"
-#~ msgstr "apt - Fortschrittliches Paketwerkzeug (Advanced Package Tool)"
-
-#~ msgid "SYNOPSIS"
-#~ msgstr "ÜBERSICHT"
-
-#~ msgid "B<apt>"
-#~ msgstr "B<apt>"
-
-#~ msgid "DESCRIPTION"
-#~ msgstr "BESCHREIBUNG"
-
-#, fuzzy
-#~ msgid ""
-#~ "For normal day to day package management there are several frontends "
-#~ "available, such as B<aptitude>(8)  for the command line or "
-#~ "B<synaptic>(8)  for the X Window System. Some options are only "
-#~ "implemented in B<apt-get>(8)  though."
-#~ msgstr ""
-#~ "APT ist ein Verwaltungssystem für Softwarepakete. Für normale alltägliche "
-#~ "Paketverwaltung sind mehrere Oberflächen, wie B<aptitude>(8) für die "
-#~ "Befehlszeile oder B<synaptic>(8) für das X-Window-System, verfügbar. "
-#~ "Einige Optionen sind jedoch nur in B<apt-get>(8) implementiert."
-
-#~ msgid "SEE ALSO"
-#~ msgstr "SIEHE AUCH"
-
-#, fuzzy
-#~ msgid ""
-#~ "B<apt>(8), B<apt-cache>(8), B<apt-get>(8), B<apt.conf>(5), B<sources."
-#~ "list>(5), B<apt_preferences>(5), B<apt-secure>(8)"
-#~ msgstr ""
-#~ "B<apt-cache>(8), B<apt-get>(8), B<apt.conf>(5), B<sources.list>(5), "
-#~ "B<apt_preferences>(5), B<apt-secure>(8)"
-
-#~ msgid "DIAGNOSTICS"
-#~ msgstr "DIAGNOSE"
-
-#~ msgid "apt returns zero on normal operation, decimal 100 on error."
-#~ msgstr ""
-#~ "APT gibt bei normalen Operationen 0 zurück, dezimal 100 bei Fehlern."
-
-#~ msgid "BUGS"
-#~ msgstr "FEHLER"
-
-#~ msgid "This manpage isn't even started."
-#~ msgstr "Diese Handbuchseite wurde noch nicht mal begonnen."
-
-#~ msgid ""
-#~ "See E<lt>http://bugs.debian.org/aptE<gt>.  If you wish to report a bug in "
-#~ "B<apt>, please see I</usr/share/doc/debian/bug-reporting.txt> or the "
-#~ "B<reportbug>(1)  command."
-#~ msgstr ""
-#~ "siehe auch E<lt>http://bugs.debian.org/aptE<gt>. Wenn Sie einen Fehler in "
-#~ "B<apt> berichten möchten, sehen Sie sich bitte I</usr/share/doc/debian/"
-#~ "bug-reporting.txt> oder den Befehl B<reportbug>(1) an."
-
-#~ msgid "AUTHOR"
-#~ msgstr "AUTOR"
-
-#~ msgid "apt was written by the APT team E<lt>apt@packages.debian.orgE<gt>."
-#~ msgstr ""
-#~ "APT wurde vom APT-Team E<lt>apt@packages.debian.orgE<gt> geschrieben."

+ 29 - 7
methods/copy.cc

@@ -16,6 +16,7 @@
 #include <apt-pkg/acquire-method.h>
 #include <apt-pkg/acquire-method.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/hashes.h>
 #include <apt-pkg/hashes.h>
+#include <apt-pkg/configuration.h>
 
 
 #include <string>
 #include <string>
 #include <sys/stat.h>
 #include <sys/stat.h>
@@ -27,19 +28,35 @@
 class CopyMethod : public pkgAcqMethod
 class CopyMethod : public pkgAcqMethod
 {
 {
    virtual bool Fetch(FetchItem *Itm);
    virtual bool Fetch(FetchItem *Itm);
+   void CalculateHashes(FetchResult &Res);
    
    
    public:
    public:
    
    
-   CopyMethod() : pkgAcqMethod("1.0",SingleInstance) {};
+   CopyMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {};
 };
 };
 
 
+void CopyMethod::CalculateHashes(FetchResult &Res)
+{
+   // For gzip indexes we need to look inside the gzip for the hash
+   // We can not use the extension here as its not used in partial 
+   // on a IMS hit
+   FileFd::OpenMode OpenMode = FileFd::ReadOnly;
+   if (_config->FindB("Acquire::GzipIndexes", false) == true)
+      OpenMode = FileFd::ReadOnlyGzip;
+
+   Hashes Hash;
+   FileFd Fd(Res.Filename, OpenMode);
+   Hash.AddFD(Fd);
+   Res.TakeHashes(Hash);
+}
+
 // CopyMethod::Fetch - Fetch a file					/*{{{*/
 // CopyMethod::Fetch - Fetch a file					/*{{{*/
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* */
 /* */
 bool CopyMethod::Fetch(FetchItem *Itm)
 bool CopyMethod::Fetch(FetchItem *Itm)
 {
 {
-   URI Get = Itm->Uri;
-   std::string File = Get.Path;
+   // this ensures that relative paths work in copy
+   std::string File = Itm->Uri.substr(Itm->Uri.find(':')+1);
 
 
    // Stat the file and send a start message
    // Stat the file and send a start message
    struct stat Buf;
    struct stat Buf;
@@ -54,6 +71,14 @@ bool CopyMethod::Fetch(FetchItem *Itm)
    Res.IMSHit = false;      
    Res.IMSHit = false;      
    URIStart(Res);
    URIStart(Res);
    
    
+   // just calc the hashes if the source and destination are identical
+   if (File == Itm->DestFile)
+   {
+      CalculateHashes(Res);
+      URIDone(Res);
+      return true;
+   }
+
    // See if the file exists
    // See if the file exists
    FileFd From(File,FileFd::ReadOnly);
    FileFd From(File,FileFd::ReadOnly);
    FileFd To(Itm->DestFile,FileFd::WriteAtomic);
    FileFd To(Itm->DestFile,FileFd::WriteAtomic);
@@ -82,10 +107,7 @@ bool CopyMethod::Fetch(FetchItem *Itm)
    if (utimes(Res.Filename.c_str(), times) != 0)
    if (utimes(Res.Filename.c_str(), times) != 0)
       return _error->Errno("utimes",_("Failed to set modification time"));
       return _error->Errno("utimes",_("Failed to set modification time"));
 
 
-   Hashes Hash;
-   FileFd Fd(Res.Filename, FileFd::ReadOnly);
-   Hash.AddFD(Fd);
-   Res.TakeHashes(Hash);
+   CalculateHashes(Res);
 
 
    URIDone(Res);
    URIDone(Res);
    return true;
    return true;

+ 4 - 3
methods/server.cc

@@ -44,7 +44,8 @@ time_t ServerMethod::FailTime = 0;
 // ---------------------------------------------------------------------
 // ---------------------------------------------------------------------
 /* Returns 0 if things are OK, 1 if an IO error occurred and 2 if a header
 /* Returns 0 if things are OK, 1 if an IO error occurred and 2 if a header
    parse error occurred */
    parse error occurred */
-ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File)
+ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File,
+                                                      const std::string &Uri)
 {
 {
    State = Header;
    State = Header;
    
    
@@ -66,7 +67,7 @@ ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File)
 	 continue;
 	 continue;
 
 
       if (Owner->Debug == true)
       if (Owner->Debug == true)
-	 clog << Data;
+	 clog << "Answer for: " << Uri << endl << Data;
       
       
       for (string::const_iterator I = Data.begin(); I < Data.end(); ++I)
       for (string::const_iterator I = Data.begin(); I < Data.end(); ++I)
       {
       {
@@ -485,7 +486,7 @@ int ServerMethod::Loop()
       Fetch(0);
       Fetch(0);
       
       
       // Fetch the next URL header data from the server.
       // Fetch the next URL header data from the server.
-      switch (Server->RunHeaders(File))
+      switch (Server->RunHeaders(File, Queue->Uri))
       {
       {
 	 case ServerState::RUN_HEADERS_OK:
 	 case ServerState::RUN_HEADERS_OK:
 	 break;
 	 break;

+ 1 - 1
methods/server.h

@@ -68,7 +68,7 @@ struct ServerState
       RUN_HEADERS_PARSE_ERROR
       RUN_HEADERS_PARSE_ERROR
    };
    };
    /** \brief Get the headers before the data */
    /** \brief Get the headers before the data */
-   RunHeadersResult RunHeaders(FileFd * const File);
+   RunHeadersResult RunHeaders(FileFd * const File, const std::string &Uri);
 
 
    bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
    bool Comp(URI Other) const {return Other.Host == ServerName.Host && Other.Port == ServerName.Port;};
    virtual void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0;
    virtual void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0;

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 3318 - 0
po/apt-all.pot


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1194 - 1192
po/ar.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1335 - 1333
po/ast.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1337 - 1335
po/bg.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1186 - 1184
po/bs.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1339 - 1337
po/ca.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1321 - 1315
po/cs.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1408 - 1406
po/cy.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1327 - 1321
po/da.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1568 - 1559
po/de.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1325 - 1323
po/dz.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1326 - 1324
po/el.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1344 - 1342
po/es.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1307 - 1305
po/eu.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1315 - 1313
po/fi.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1354 - 1352
po/fr.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1344 - 1342
po/gl.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1334 - 1332
po/hu.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1343 - 1337
po/it.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1332 - 1326
po/ja.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1320 - 1318
po/km.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1325 - 1323
po/ko.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1167 - 1165
po/ku.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1263 - 1261
po/lt.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1323 - 1321
po/mr.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1330 - 1328
po/nb.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1314 - 1312
po/ne.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1352 - 1350
po/nl.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1322 - 1320
po/nn.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1338 - 1336
po/pl.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1335 - 1333
po/pt.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1328 - 1326
po/pt_BR.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1326 - 1324
po/ro.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1341 - 1339
po/ru.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1325 - 1323
po/sk.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1322 - 1320
po/sl.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1343 - 1341
po/sv.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1300 - 1294
po/th.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1338 - 1336
po/tl.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1338 - 1332
po/tr.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1443 - 1441
po/uk.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1454 - 1448
po/vi.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1311 - 1309
po/zh_CN.po


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1309 - 1307
po/zh_TW.po


+ 51 - 4
prepare-release

@@ -123,16 +123,63 @@ elif [ "$1" = 'buildlog' ]; then
 elif [ "$1" = 'travis-ci' ]; then
 elif [ "$1" = 'travis-ci' ]; then
 	apt-get install -q --no-install-recommends $(sed -n -e '/^Build-Depends: /,/^Build-Depends-Indep: / {p}' debian/control | sed -e 's#([^)]*)##g' -e 's#^Build-Depends\(-Indep\)\?: ##' | tr -d ',')
 	apt-get install -q --no-install-recommends $(sed -n -e '/^Build-Depends: /,/^Build-Depends-Indep: / {p}' debian/control | sed -e 's#([^)]*)##g' -e 's#^Build-Depends\(-Indep\)\?: ##' | tr -d ',')
 	apt-get install -q --no-install-recommends $(sed -n 's#^Depends: .*@, \(.*\)$#\1#p' debian/tests/control | tr -d ',')
 	apt-get install -q --no-install-recommends $(sed -n 's#^Depends: .*@, \(.*\)$#\1#p' debian/tests/control | tr -d ',')
+elif [ "$1" = 'coverage' ]; then
+	DIR="${2:-./coverage}"
+	git clean -dfX # remove ignored build artefacts for a clean start
+	make CFLAGS+='--coverage' CXXFLAGS+='--coverage'
+	LCOVRC='--rc geninfo_checksum=1 --rc lcov_branch_coverage=1'
+	mkdir "$DIR"
+	lcov --no-external --directory . --capture --initial --output-file "${DIR}/apt.coverage.init" ${LCOVRC}
+	make test
+	./test/integration/run-tests -q
+	lcov --no-external --directory . --capture --output-file "${DIR}/apt.coverage.run" ${LCOVRC}
+	lcov -a "${DIR}/apt.coverage.init" -a "${DIR}/apt.coverage.run"  -o "${DIR}/apt.coverage.total" ${LCOVRC}
+	cp "${DIR}/apt.coverage.total" "${DIR}/apt.coverage.fixed"
+	rewritefile() {
+		file="$1"
+		shift
+		name="$(basename "$file")"
+		while [ -n "$1" ]; do
+			if [ -r "$1/$name" ]; then
+				sed -i "s#$file#$1/$name#" "${DIR}/apt.coverage.fixed"
+				break
+			fi
+			shift
+		done
+		if [ -z "$1" ]; then
+			echo >&2 "Coverage data captured for unknown file $file"
+		fi
+	}
+	grep 'build/include/' "${DIR}/apt.coverage.fixed" | sed "s#^SF:$(pwd)/##" | while read file; do
+		rewritefile "$file" 'apt-pkg' 'apt-pkg/deb' 'apt-pkg/edsp' 'apt-pkg/contrib' \
+		   'apt-inst' 'apt-inst/deb' 'apt-inst/contrib' 'apt-private'
+	done
+	genhtml --output-directory "${DIR}" "${DIR}/apt.coverage.fixed" ${LCOVRC}
 else
 else
 	echo >&1 "Usage:\t$0 pre-export
 	echo >&1 "Usage:\t$0 pre-export
 \t$0 post-build
 \t$0 post-build
-\t$0 library
 
 
-If you use »git buildpackage« you can leave this script alone as it will
+If you use »git buildpackage« you can leave these alone as they will
 be run at the right places auto-magically. Otherwise you should use
 be run at the right places auto-magically. Otherwise you should use
 »pre-export« to update po and pot files as well as version numbering.
 »pre-export« to update po and pot files as well as version numbering.
 »post-build« can be used to run some more or less useful checks later on.
 »post-build« can be used to run some more or less useful checks later on.
 
 
-»library« isn't run automatically but can be useful for maintaining the
-(more or less experimental) symbols files we provide"
+\t$0 library
+\t$0 buildlog filename…
+
+»library« and »buildlog« aren't run automatically but can be useful for
+maintaining the (more or less experimental) symbols files we provide.
+»library« displays the diff between advertised symbols and the once provided
+by the libraries, while »buildlog« extracts this diff from the buildlogs.
+Both will format the diff properly.
+
+\t$0 travis-ci
+\t$0 coverage [output-dir]
+
+»travis-ci« is a shortcut to install all build- as well as test-dependencies
+used by .travis.yml.
+»coverage« does a clean build with the right flags for coverage reporting,
+runs all tests and generates a html report in the end.
+"
+
 fi
 fi

+ 8 - 2
test/integration/framework

@@ -4,7 +4,7 @@ EXIT_CODE=0
 
 
 # we all like colorful messages
 # we all like colorful messages
 if [ "$MSGCOLOR" != 'NO' ]; then
 if [ "$MSGCOLOR" != 'NO' ]; then
-	if ! expr match "$(readlink -f /proc/$$/fd/1)" '/dev/pts/[0-9]\+' > /dev/null; then
+	if [ ! -t 1 ]; then # but check that we output to a terminal
 		export MSGCOLOR='NO'
 		export MSGCOLOR='NO'
 	fi
 	fi
 fi
 fi
@@ -1019,7 +1019,13 @@ testfileequal() {
 
 
 testempty() {
 testempty() {
 	msgtest "Test for no output of" "$*"
 	msgtest "Test for no output of" "$*"
-	test -z "$($* 2>&1)" && msgpass || msgfail
+	local COMPAREFILE="${TMPWORKINGDIRECTORY}/rootdir/tmp/testempty.comparefile"
+	if $* >$COMPAREFILE 2>&1 && test ! -s $COMPAREFILE; then
+		msgpass
+	else
+		cat $COMPAREFILE
+		msgfail
+	fi
 }
 }
 
 
 testequal() {
 testequal() {

+ 1 - 1
test/integration/run-tests

@@ -22,7 +22,7 @@ done
 export MSGLEVEL="${MSGLEVEL:-3}"
 export MSGLEVEL="${MSGLEVEL:-3}"
 
 
 if [ "$MSGCOLOR" != 'NO' ]; then
 if [ "$MSGCOLOR" != 'NO' ]; then
-	if ! expr match "$(readlink -f /proc/$$/fd/1)" '/dev/pts/[0-9]\+' > /dev/null; then
+	if [ ! -t 1 ]; then # but check that we output to a terminal
 		export MSGCOLOR='NO'
 		export MSGCOLOR='NO'
 	fi
 	fi
 fi
 fi

+ 30 - 1
test/integration/test-apt-cli-search

@@ -15,7 +15,10 @@ fi
 
 
 DESCR='Some description that has a unusual word xxyyzz and aabbcc and a UPPERCASE'
 DESCR='Some description that has a unusual word xxyyzz and aabbcc and a UPPERCASE'
 DESCR2='Some other description with the unusual aabbcc only'
 DESCR2='Some other description with the unusual aabbcc only'
-insertpackage 'unstable' 'foo' 'all' '1.0' '' '' "$DESCR"
+insertpackage 'unstable' 'foo' 'all' '1.0' '' '' "$DESCR
+ Long description of stuff and such, with lines
+ .
+ and paragraphs and everything."
 insertpackage 'testing' 'bar' 'i386' '2.0' '' '' "$DESCR2"
 insertpackage 'testing' 'bar' 'i386' '2.0' '' '' "$DESCR2"
 
 
 setupaptarchive
 setupaptarchive
@@ -33,16 +36,42 @@ foo/unstable 1.0 all
 testequal "foo/unstable 1.0 all
 testequal "foo/unstable 1.0 all
   $DESCR
   $DESCR
 " apt search -qq xxyyzz
 " apt search -qq xxyyzz
+testempty apt search -qq --names-only xxyyzz
+
+# search name
+testequal "foo/unstable 1.0 all
+  $DESCR
+" apt search -qq foo
+testequal "foo/unstable 1.0 all
+  $DESCR
+" apt search -qq --names-only foo
 
 
 # search with multiple words is a AND search
 # search with multiple words is a AND search
 testequal "foo/unstable 1.0 all
 testequal "foo/unstable 1.0 all
   $DESCR
   $DESCR
 " apt search -qq aabbcc xxyyzz
 " apt search -qq aabbcc xxyyzz
+testequal "foo/unstable 1.0 all
+  $DESCR
+" apt search -qq 'a+b+c+' 'i*xxy{0,2}zz'
 
 
 # search is not case-sensitive by default
 # search is not case-sensitive by default
 testequal "foo/unstable 1.0 all
 testequal "foo/unstable 1.0 all
   $DESCR
   $DESCR
 " apt search -qq uppercase
 " apt search -qq uppercase
+testequal "foo/unstable 1.0 all
+  $DESCR
+" apt search -qq 'up[pP]erc[Aa]se'
+
+# search is done in the long description
+testequal "foo/unstable 1.0 all
+  $DESCR
+" apt search -qq 'long description'
+testequal "foo/unstable 1.0 all
+  $DESCR
+  Long description of stuff and such, with lines
+  .
+  and paragraphs and everything.
+" apt search --full -qq 'long description'
 
 
 # output is sorted and search word finds both package
 # output is sorted and search word finds both package
 testequal "bar/testing 2.0 i386
 testequal "bar/testing 2.0 i386

+ 2 - 3
test/integration/test-apt-get-changelog

@@ -28,9 +28,8 @@ testsuccess aptget changelog apt -d
 testfileequal 'apt.changelog' "$(cat  aptarchive/pool/apt_1.0/changelog)"
 testfileequal 'apt.changelog' "$(cat  aptarchive/pool/apt_1.0/changelog)"
 rm apt.changelog aptarchive/pool/apt_1.0/changelog
 rm apt.changelog aptarchive/pool/apt_1.0/changelog
 
 
-aptget changelog apt -qq -o APT::Changelogs::Server='http://not-on-the-main-server:8080/' > apt.changelog
-testfileequal 'apt.changelog' "$(cat aptarchive/pool/apt_1.0.changelog)"
-rm apt.changelog
+testequal "$(cat aptarchive/pool/apt_1.0.changelog)" aptget changelog apt \
+	-qq -o APT::Changelogs::Server='http://not-on-the-main-server:8080/'
 
 
 testsuccess aptget changelog apt -d
 testsuccess aptget changelog apt -d
 testfileequal 'apt.changelog' "$(cat aptarchive/pool/apt_1.0.changelog)"
 testfileequal 'apt.changelog' "$(cat aptarchive/pool/apt_1.0.changelog)"

+ 6 - 1
test/integration/test-apt-https-no-redirect

@@ -25,6 +25,11 @@ msgtest 'download of a file does not work if' 'https redirected to http'
 downloadfile 'https://localhost:4433/redirectme/working' redirectfile >curloutput 2>&1 && msgfail || msgpass
 downloadfile 'https://localhost:4433/redirectme/working' redirectfile >curloutput 2>&1 && msgfail || msgpass
 
 
 msgtest 'libcurl has forbidden access in last request to' 'http resource'
 msgtest 'libcurl has forbidden access in last request to' 'http resource'
-grep -q -- 'Protocol http not supported or disabled in libcurl' curloutput && msgpass || msgfail
+if grep -q -E -- 'Protocol "?http"? not supported or disabled in libcurl' curloutput; then
+	msgpass
+else
+	cat curloutput
+	msgfail
+fi
 
 
 
 

+ 16 - 0
test/integration/test-apt-progress-fd

@@ -33,6 +33,22 @@ testsuccess aptget install testing=0.8.15 -y -o APT::Status-Fd=3
 testequal "dlstatus:1:0:Retrieving file 1 of 1
 testequal "dlstatus:1:0:Retrieving file 1 of 1
 dlstatus:1:20:Retrieving file 1 of 1
 dlstatus:1:20:Retrieving file 1 of 1
 pmstatus:dpkg-exec:0:Running dpkg
 pmstatus:dpkg-exec:0:Running dpkg
+pmstatus:testing:0:Installing testing (amd64)
+pmstatus:testing:20:Preparing testing (amd64)
+pmstatus:testing:40:Unpacking testing (amd64)
+pmstatus:testing:60:Preparing to configure testing (amd64)
+pmstatus:dpkg-exec:60:Running dpkg
+pmstatus:testing:60:Configuring testing (amd64)
+pmstatus:testing:80:Configuring testing (amd64)
+pmstatus:testing:100:Installed testing (amd64)" cat apt-progress.log
+
+# reinstall
+exec 3> apt-progress.log
+testsuccess aptget install testing=0.8.15 --reinstall -y -o APT::Status-Fd=3
+testequal "dlstatus:1:0:Retrieving file 1 of 1
+dlstatus:1:0:Retrieving file 1 of 1
+pmstatus:dpkg-exec:0:Running dpkg
+pmstatus:testing:0:Installing testing (amd64)
 pmstatus:testing:20:Preparing testing (amd64)
 pmstatus:testing:20:Preparing testing (amd64)
 pmstatus:testing:40:Unpacking testing (amd64)
 pmstatus:testing:40:Unpacking testing (amd64)
 pmstatus:testing:60:Preparing to configure testing (amd64)
 pmstatus:testing:60:Preparing to configure testing (amd64)

+ 6 - 1
test/integration/test-apt-progress-fd-error

@@ -18,5 +18,10 @@ setupaptarchive
 exec 3> apt-progress.log
 exec 3> apt-progress.log
 testfailure aptget install foo1 foo2 -y -o APT::Status-Fd=3
 testfailure aptget install foo1 foo2 -y -o APT::Status-Fd=3
 msgtest "Ensure correct error message"
 msgtest "Ensure correct error message"
-grep -q "aptarchive/pool/foo2_0.8.15_amd64.deb :40:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log && msgpass || (cat apt-progress.log && msgfail)
+if grep -q "aptarchive/pool/foo2_0.8.15_amd64.deb:40:trying to overwrite '/usr/bin/file-conflict', which is also in package foo1 0.8.15" apt-progress.log; then
+	msgpass
+else
+	cat apt-progress.log
+	msgfail
+fi
 
 

+ 36 - 0
test/integration/test-apt-update-file

@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Ensure that we do not modify file:/// uris (regression test for
+# CVE-2014-0487
+#
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "amd64"
+configcompression 'bz2' 'gz' 
+
+insertpackage 'unstable' 'foo' 'all' '1.0'
+
+umask 022
+setupaptarchive --no-update
+
+# ensure the archive is not writable
+chmod 550 aptarchive/dists/unstable/main/binary-amd64
+
+testsuccess aptget update -qq
+testsuccess aptget update -qq
+aptget update -qq -o Debug::pkgAcquire::Auth=1 2> output.log
+
+# ensure that the hash of the uncompressed file was verified even on a local 
+# ims hit
+canary="SHA512:$(bzcat aptarchive/dists/unstable/main/binary-amd64/Packages.bz2 | sha512sum |cut -f1 -d' ')"
+grep -q "RecivedHash: $canary" output.log
+
+# foo is still available
+testsuccess aptget install -s foo
+
+# the cleanup should still work
+chmod 750 aptarchive/dists/unstable/main/binary-amd64

+ 46 - 0
test/integration/test-apt-update-stale

@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Ensure that a MITM can not stale the Packages/Sources without
+# raising a error message. Note that the Release file is protected
+# via the "Valid-Until" header
+#
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+insertpackage 'unstable' 'foo' 'all' '1.0'
+
+setupaptarchive
+changetowebserver
+aptget update -qq
+
+# insert new version
+mkdir aptarchive/dists/unstable/main/binary-i386/saved
+cp -p aptarchive/dists/unstable/main/binary-i386/Packages* \
+     aptarchive/dists/unstable/main/binary-i386/saved
+insertpackage 'unstable' 'foo' 'all' '2.0'
+
+# not using compressfile for compat with older apt releases
+gzip -c aptarchive/dists/unstable/main/binary-i386/Packages > \
+  aptarchive/dists/unstable/main/binary-i386/Packages.gz
+generatereleasefiles
+signreleasefiles
+
+# ensure that we do not get a I-M-S hit for the Release file
+touch -d "+1hour" aptarchive/dists/unstable/*Release*
+
+# but now only deliver the previous Packages file instead of the new one
+# (simulating a stale attack)
+cp -p aptarchive/dists/unstable/main/binary-i386/saved/Packages* \
+     aptarchive/dists/unstable/main/binary-i386/
+
+# ensure this raises a error
+testequal "W: Failed to fetch http://localhost:8080/dists/unstable/main/binary-i386/Packages  Hash Sum mismatch
+
+E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq
+
+

+ 48 - 0
test/integration/test-apt-update-unauth

@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# Ensure that when going from unauthenticated to authenticated all
+# files are checked again
+#
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+insertpackage 'unstable' 'foo' 'all' '1.0'
+insertsource 'unstable' 'foo' 'all' '1.0'
+
+setupaptarchive
+changetowebserver
+
+runtest() {
+    # start unauthenticated
+    find rootdir/var/lib/apt/lists/ -type f | xargs rm -f
+    rm -f aptarchive/dists/unstable/*Release*
+    aptget update -qq
+
+    # become authenticated
+    generatereleasefiles
+    signreleasefiles
+
+    # and ensure we do download the data again
+    msgtest "Check that the data is check when going to authenticated"
+    if aptget update |grep -q Hit; then
+        msgfail
+    else
+        msgpass
+    fi
+}
+
+for COMPRESSEDINDEXES in 'false' 'true'; do
+	echo "Acquire::GzipIndexes \"$COMPRESSEDINDEXES\";" > rootdir/etc/apt/apt.conf.d/compressindexes
+	if $COMPRESSEDINDEXES; then
+		msgmsg 'Run tests with GzipIndexes enabled'
+	else
+		msgmsg 'Run tests with GzipIndexes disabled'
+	fi
+
+        runtest
+done

+ 4 - 4
test/integration/test-architecture-specification-parsing

@@ -13,10 +13,10 @@ buildsimplenativepackage 'pkg-arch-foo' "$NATIVE" '1.0' 'stable' "Build-Depends:
 Depends: foo [${NATIVE} !${NATIVE}]"
 Depends: foo [${NATIVE} !${NATIVE}]"
 buildsimplenativepackage 'pkg-arch-no-foo' "$NATIVE" '1.0' 'stable' "Build-Depends: foo [!${NATIVE} ${NATIVE}]
 buildsimplenativepackage 'pkg-arch-no-foo' "$NATIVE" '1.0' 'stable' "Build-Depends: foo [!${NATIVE} ${NATIVE}]
 Depends: foo [!${NATIVE} ${NATIVE}]"
 Depends: foo [!${NATIVE} ${NATIVE}]"
-buildsimplenativepackage 'pkg-arch-foo-unrelated-no' "$NATIVE" '1.0' 'stable' "Build-Depends: foo [!kfreebsd-any ${NATIVE}]
-Depends: foo [!kfreebsd-any ${NATIVE}]"
-buildsimplenativepackage 'pkg-arch-foo-unrelated-no2' "$NATIVE" '1.0' 'stable' "Build-Depends: foo [${NATIVE} !kfreebsd-any]
-Depends: foo [${NATIVE} !kfreebsd-any]"
+buildsimplenativepackage 'pkg-arch-foo-unrelated-no' "$NATIVE" '1.0' 'stable' "Build-Depends: foo [!someos-any ${NATIVE}]
+Depends: foo [!someos-any ${NATIVE}]"
+buildsimplenativepackage 'pkg-arch-foo-unrelated-no2' "$NATIVE" '1.0' 'stable' "Build-Depends: foo [${NATIVE} !someos-any]
+Depends: foo [${NATIVE} !someos-any]"
 buildsimplenativepackage 'no-depends' 'armel' '1.0' 'stable' 'Build-Depends: foo [armeb], bar [arm]
 buildsimplenativepackage 'no-depends' 'armel' '1.0' 'stable' 'Build-Depends: foo [armeb], bar [arm]
 Depends: foo [armeb], bar [arm]'
 Depends: foo [armeb], bar [arm]'
 
 

+ 17 - 0
test/integration/test-bug-762160-relpath

@@ -0,0 +1,17 @@
+#!/bin/sh
+# regresion test for bug #762160 where apt-get update fails when a 
+# relative directory is given
+#
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64'
+
+insertpackage 'unstable' 'foo' 'all' '1'
+setupaptarchive
+changetowebserver
+
+testsuccess aptget update -o Dir=./rootdir
+testsuccess aptget update -o Dir=./rootdir 

+ 11 - 3
test/integration/test-hashsum-verification

@@ -64,7 +64,7 @@ runtest() {
         msgtest 'No package from the source available'
         msgtest 'No package from the source available'
         [ "$(aptcache show apt 2>&1)" = "E: No packages found" ] && msgpass || msgfail
         [ "$(aptcache show apt 2>&1)" = "E: No packages found" ] && msgpass || msgfail
         msgtest 'No Packages file in /var/lib/apt/lists'
         msgtest 'No Packages file in /var/lib/apt/lists'
-        [ "$(ls rootdir/var/lib/apt/lists/*Package* 2>/dev/null)" = "" ] && msgpass || msgfail 
+        [ "$(ls rootdir/var/lib/apt/lists/*Package* 2>/dev/null | grep -v FAILED 2>/dev/null)" = "" ] && msgpass || msgfail 
         
         
         # now with the unsigned Release file
         # now with the unsigned Release file
         rm -rf rootdir/var/lib/apt/lists
         rm -rf rootdir/var/lib/apt/lists
@@ -75,5 +75,13 @@ runtest() {
 
 
 }
 }
 
 
-runtest
-
+for COMPRESSEDINDEXES in 'false' 'true'; do
+	echo "Acquire::GzipIndexes \"$COMPRESSEDINDEXES\";" > rootdir/etc/apt/apt.conf.d/compressindexes
+	if $COMPRESSEDINDEXES; then
+		msgmsg 'Run tests with GzipIndexes enabled'
+	else
+		msgmsg 'Run tests with GzipIndexes disabled'
+	fi
+ 
+        runtest
+done

+ 15 - 0
test/libapt/strutil_test.cc

@@ -19,6 +19,21 @@ TEST(StrUtilTest,DeEscapeString)
    EXPECT_EQ("foo\\ x", DeEscapeString("foo\\\\ x"));
    EXPECT_EQ("foo\\ x", DeEscapeString("foo\\\\ x"));
    EXPECT_EQ("\\foo\\", DeEscapeString("\\\\foo\\\\"));
    EXPECT_EQ("\\foo\\", DeEscapeString("\\\\foo\\\\"));
 }
 }
+TEST(StrUtilTest,StringStrip)
+{
+   EXPECT_EQ("", APT::String::Strip(""));
+   EXPECT_EQ("foobar", APT::String::Strip("foobar"));
+   EXPECT_EQ("foo bar", APT::String::Strip("foo bar"));
+
+   EXPECT_EQ("", APT::String::Strip("  "));
+   EXPECT_EQ("", APT::String::Strip(" \r\n   \t "));
+
+   EXPECT_EQ("foo bar", APT::String::Strip("foo bar "));
+   EXPECT_EQ("foo bar", APT::String::Strip("foo bar \r\n \t "));
+   EXPECT_EQ("foo bar", APT::String::Strip("\r\n \t foo bar"));
+   EXPECT_EQ("bar foo", APT::String::Strip("\r\n \t bar foo \r\n \t "));
+   EXPECT_EQ("bar \t\r\n foo", APT::String::Strip("\r\n \t bar \t\r\n foo \r\n \t "));
+}
 TEST(StrUtilTest,StringSplitBasic)
 TEST(StrUtilTest,StringSplitBasic)
 {
 {
    std::vector<std::string> result = StringSplit("", "");
    std::vector<std::string> result = StringSplit("", "");