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

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 лет назад: 11
Родитель
Сommit
c511c5e8ed
86 измененных файлов с 61487 добавлено и 57559 удалено
  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);
 }
 									/*}}}*/
+// 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					/*{{{*/
 // ---------------------------------------------------------------------
 /* 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,
 		       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 (ExpectedHashes.usable() && ExpectedHashes != Hashes)
       {
+         Desc.URI = RealURI;
 	 RenameOnError(HashSumMismatch);
 	 printHashSumComparision(RealURI, ExpectedHashes, Hashes);
          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
        * 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)
-      if (fd.FileSize() > 0)
+      if (fd.Size() > 0)
       {
          pkgTagSection sec;
          pkgTagFile tag(&fd);
@@ -1137,8 +1164,7 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
       }
        
       // Done, move it into position
-      string FinalFile = _config->FindDir("Dir::State::lists");
-      FinalFile += URItoFileName(RealURI);
+      string FinalFile = GetFinalFilename(RealURI, compExt);
       Rename(DestFile,FinalFile);
       chmod(FinalFile.c_str(),0644);
 
@@ -1146,7 +1172,9 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
          will work OK */
       DestFile = _config->FindDir("Dir::State::lists") + "partial/";
       DestFile += URItoFileName(RealURI);
-      
+      if (_config->FindB("Acquire::GzipIndexes",false) && compExt == "gz")
+         DestFile += ".gz";
+
       // Remove the compressed version.
       if (Erase == true)
 	 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");
    if (FileName.empty() == false)
    {
-      // The files timestamp matches
-      if (StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false) == true)
-	 return;
       Decompression = true;
       Local = true;
       DestFile += ".decomp";
@@ -1180,33 +1205,37 @@ void pkgAcqIndex::Done(string Message,unsigned long long Size,HashStringList con
       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)
       Erase = true;
    else
       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;
 
-   // 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";
+
+      Decompression = true;
+      Desc.URI = "copy:" + FileName;
+      QueueURI(Desc);
+
       return;
     }
 
@@ -1254,6 +1283,9 @@ string pkgAcqIndexTrans::Custom600Headers() const
    string Final = _config->FindDir("Dir::State::lists");
    Final += URItoFileName(RealURI);
 
+   if (_config->FindB("Acquire::GzipIndexes",false))
+      Final += ".gz";
+
    struct stat Buf;
    if (stat(Final.c_str(),&Buf) != 0)
       return "\nFail-Ignore: true\nIndex-File: true";
@@ -1606,6 +1638,28 @@ void pkgAcqMetaIndex::AuthDone(string Message)				/*{{{*/
       std::cerr << "Signature verification succeeded: "
                 << 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
    QueueIndexes(true);
 

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

@@ -707,9 +707,18 @@ class pkgAcqIndex : public pkgAcqBaseIndex
     */
    std::string CompressionExtension;
 
+
    /** \brief Do the changes needed to fetch via AptByHash (if needed) */
    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:
    
    // Specialized action members

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

@@ -85,7 +85,9 @@ class FileFd
    bool Skip(unsigned long long To);
    bool Truncate(unsigned long long To);
    unsigned long long Tell();
+   // the size of the file content (compressed files will be uncompressed first)
    unsigned long long Size();
+   // the size of the file itself
    unsigned long long FileSize();
    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
    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
    // name without the dash ("-")
    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 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 "";
-   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)

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

@@ -59,8 +59,8 @@ class pkgDPkgPMPrivate
 {
 public:
    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';
    }
@@ -77,9 +77,9 @@ public:
    APT::Progress::PackageManager *progress;
 
    // pty stuff
-   struct	termios tt;
+   struct termios tt;
    int master;
-   int slave;
+   char * slave;
 
    // signals
    sigset_t sigmask;
@@ -510,7 +510,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf)
    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>:<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
@@ -589,12 +589,15 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    std::string action;
 
    // "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")
    {
       pkgname = APT::String::Strip(list[2]);
       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"
    // 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 
    // 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)
    {
-      // 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);
-      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();
    std::string short_pkgname = StringSplit(pkgname, ":")[0];
    std::string arch = "";
@@ -697,28 +699,29 @@ void pkgDPkgPM::ProcessDpkgStatusLine(char *line)
    if (prefix == "status")
    {
       vector<struct DpkgState> const &states = PackageOps[pkg];
-      const char *next_action = NULL;
       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)
    {
-      d->master = d->slave = -1;
+      d->master = -1;
+      if (d->slave != NULL)
+	 free(d->slave);
+      d->slave = NULL;
       return;
    }
 
-   // setup the pty and stuff
-   struct winsize win;
-
+   _error->PushToStack();
    // if tcgetattr for both stdin/stdout returns 0 (no error)
    // 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
 	    // the process is a member of the background process group
 	    // http://www.opengroup.org/onlinepubs/000095399/functions/tcsetattr.html
 	    sigemptyset(&d->sigmask);
 	    sigaddset(&d->sigmask, SIGTTOU);
 	    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.
-      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()
 {
-   if(d->slave > 0)
-      close(d->slave);
+   if (d->slave != NULL)
+      free(d->slave);
+   d->slave = NULL;
    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);
+      d->master = -1;
    }
 }
 
@@ -1407,22 +1477,8 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress)
       pid_t Child = ExecFork(KeepFDs);
       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
 
 	 dpkgChrootDirectory();

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

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

+ 1 - 1
apt-pkg/tagfile.cc

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

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

@@ -14,74 +14,77 @@
 
 #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();
-    return GetLocalitySortedVersionSet(CacheFile, output_set, 
+    return GetLocalitySortedVersionSet(CacheFile, vci,
                                        null_matcher, progress);
 }
 
-bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile, 
-                                 LocalitySortedVersionSet &output_set,
+bool GetLocalitySortedVersionSet(pkgCacheFile &CacheFile,
+                                 APT::VersionContainerInterface * const vci,
                                  Matcher &matcher,
-                                 OpProgress &progress)
+                                 OpProgress * const progress)
 {
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgDepCache *DepCache = CacheFile.GetDepCache();
+   APT::CacheSetHelper helper(false);
 
    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)
    {
-      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)
-         continue;
+	 continue;
 
-      // exclude virtual pkgs
-      if (P.VersionList() == 0)
-         continue;
       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;
 }

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

@@ -62,13 +62,13 @@ public:
 };
 
 // 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,
-                                    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				/*{{{*/

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

@@ -70,6 +70,8 @@ static bool addArgumentsAPTCache(std::vector<CommandLine::Args> &Args, char cons
    else
       return false;
 
+   bool const found_something = Args.empty() == false;
+
    // FIXME: move to the correct command(s)
    addArg('g', "generate", "APT::Cache::Generate", 0);
    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('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)/*{{{*/
@@ -172,6 +175,8 @@ static bool addArgumentsAPTGet(std::vector<CommandLine::Args> &Args, char const
       addArg('s', "no-act", "APT::Get::Simulate", 0);
    }
 
+   bool const found_something = Args.empty() == false;
+
    // FIXME: move to the correct command(s)
    addArg('d',"download-only","APT::Get::Download-Only",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,"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)/*{{{*/

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

@@ -77,15 +77,14 @@ private:
 };
 									/*}}}*/
 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();
         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;
    }
 
-   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);
    LocalitySortedVersionSet bag;
@@ -121,37 +119,34 @@ bool DoList(CommandLine &Cmd)
                             Cache->Head().PackageCount, 
                             Cache->Head().PackageCount,
                             _("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)
    {
       std::stringstream outs;
       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)
    // output the sorted map
+   std::map<std::string, std::string>::const_iterator K;
    for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
 
-
    // be nice and tell the user if there is more to see
    if (bag.size() == 1 && ShowAllVersions == false)
    {
       // start with -1 as we already displayed one version
       int versions = -1;
       pkgCache::VerIterator Ver = *bag.begin();
-      for ( ; Ver.end() == false; Ver++)
-         versions++;
+      for ( ; Ver.end() == false; ++Ver)
+         ++versions;
       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);
    }

+ 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)/*{{{*/
 {
-   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)/*{{{*/
@@ -196,81 +207,90 @@ static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &reco
    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))
+      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						/*{{{*/

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

@@ -23,8 +23,8 @@ APT_PUBLIC extern unsigned int ScreenWidth;
 APT_PUBLIC bool InitOutput();
 
 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

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

@@ -32,61 +32,95 @@ bool FullTextSearch(CommandLine &CmdL)					/*{{{*/
    pkgCacheFile CacheFile;
    pkgCache *Cache = CacheFile.GetPkgCache();
    pkgDepCache::Policy *Plcy = CacheFile.GetPolicy();
-   pkgRecords records(CacheFile);
    if (unlikely(Cache == NULL || Plcy == NULL))
       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>::const_iterator K;
 
    LocalitySortedVersionSet bag;
    OpTextProgress progress(*_config);
    progress.OverallProgress(0, 100, 50,  _("Sorting"));
-   GetLocalitySortedVersionSet(CacheFile, bag, progress);
+   GetLocalitySortedVersionSet(CacheFile, &bag, &progress);
    LocalitySortedVersionSet::iterator V = bag.begin();
 
    progress.OverallProgress(50, 100, 50,  _("Full Text Search"));
    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;
+   std::vector<bool> PkgsDone(Cache->Head().PackageCount, false);
    for ( ;V != bag.end(); ++V)
    {
       if (Done%500 == 0)
          progress.Progress(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();
       pkgRecords::Parser &parser = records.Lookup(Desc.FileList());
-     
+      std::string const LongDesc = parser.LongDesc();
+
       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();
 
    // FIXME: SORT! and make sorting flexible (alphabetic, by pkg status)
    // output the sorted map
+   std::map<std::string, std::string>::const_iterator K;
    for (K = output_map.begin(); K != output_map.end(); ++K)
       std::cout << (*K).second << std::endl;
 

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

@@ -8,45 +8,69 @@
 #include <cstdlib>
 #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();
    if (Process == 0)
    {
       const char *Args[3];
-      Args[0] = pager.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);
       exit(100);
    }
-         
+
    // 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();
    if (Process == 0)
    {
+      // likely installed, provided by sensible-utils
+      std::string const editor = _config->Find("Dir::Bin::Editor",
+	    "sensible-editor");
       const char *Args[3];
       Args[0] = editor.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);
       exit(100);
    }
-         
+
    // 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>
 
-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

+ 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)
 
 PACKAGE="apt"
-PACKAGE_VERSION="1.1~exp2"
+PACKAGE_VERSION="1.1~exp3"
 PACKAGE_MAIL="APT Development Team <deity@lists.debian.org>"
 AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
 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
 
+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
 
   [ Michael Vogt ]

+ 2 - 0
debian/gbp.conf

@@ -3,3 +3,5 @@ prebuild = ./prepare-release pre-export
 postbuild = ./prepare-release post-build
 debian-branch = debian/experimental
 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.
 # 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
 # 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' -->
-<!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 -->
 <!ENTITY oldstable-codename "squeeze">

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

@@ -6,9 +6,9 @@
 #, fuzzy
 msgid ""
 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"
-"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"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"

+ 7 - 117
doc/po/de.po

@@ -5,10 +5,10 @@
 #
 msgid ""
 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"
 "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"
 "Language-Team: German <debian-l10n-german@lists.debian.org>\n"
 "Language: de\n"
@@ -750,12 +750,6 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>
 #: 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 ""
 "<literal>upgrade</literal> is used to install the newest versions of all "
 "packages currently installed on the system from the sources enumerated in "
@@ -4591,17 +4585,6 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><para>
 #: 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 ""
 "<literal>Dir::Cache</literal> contains locations pertaining to local cache "
 "information, such as the two package caches <literal>srcpkgcache</literal> "
@@ -4618,8 +4601,9 @@ msgstr ""
 "Paketzwischenspeicher <literal>srcpkgcache</literal> und <literal>pkgcache</"
 "literal>, sowie den Ort, an den heruntergeladene Archive platziert werden, "
 "<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 "
 "den »pkgcache« auszuschalten. Wie <literal>Dir::State</literal> ist das "
 "Standardverzeichnis in <literal>Dir::Cache</literal> enthalten."
@@ -8549,7 +8533,7 @@ msgstr "jgg@debian.org"
 #. type: Content of: <book><bookinfo><releaseinfo>
 #: guide.dbk:21 offline.dbk:21
 msgid "Version &apt-product-version;"
-msgstr ""
+msgstr "Version &apt-product-version;"
 
 #. type: Content of: <book><bookinfo><abstract><para>
 #: guide.dbk:25
@@ -8569,7 +8553,7 @@ msgstr ""
 #. type: Content of: <book><bookinfo><legalnotice><title>
 #: guide.dbk:32 offline.dbk:33
 msgid "License Notice"
-msgstr ""
+msgstr "Lizenzhinweis"
 
 #. type: Content of: <book><bookinfo><legalnotice><para>
 #: guide.dbk:34 offline.dbk:35
@@ -10158,97 +10142,3 @@ msgstr "  # apt-get -o dir::cache::archives=\"/Platte/\" dist-upgrade\n"
 #: offline.dbk:242
 msgid "Which will use the already fetched archives on the disc."
 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/error.h>
 #include <apt-pkg/hashes.h>
+#include <apt-pkg/configuration.h>
 
 #include <string>
 #include <sys/stat.h>
@@ -27,19 +28,35 @@
 class CopyMethod : public pkgAcqMethod
 {
    virtual bool Fetch(FetchItem *Itm);
+   void CalculateHashes(FetchResult &Res);
    
    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					/*{{{*/
 // ---------------------------------------------------------------------
 /* */
 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
    struct stat Buf;
@@ -54,6 +71,14 @@ bool CopyMethod::Fetch(FetchItem *Itm)
    Res.IMSHit = false;      
    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
    FileFd From(File,FileFd::ReadOnly);
    FileFd To(Itm->DestFile,FileFd::WriteAtomic);
@@ -82,10 +107,7 @@ bool CopyMethod::Fetch(FetchItem *Itm)
    if (utimes(Res.Filename.c_str(), times) != 0)
       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);
    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
    parse error occurred */
-ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File)
+ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File,
+                                                      const std::string &Uri)
 {
    State = Header;
    
@@ -66,7 +67,7 @@ ServerState::RunHeadersResult ServerState::RunHeaders(FileFd * const File)
 	 continue;
 
       if (Owner->Debug == true)
-	 clog << Data;
+	 clog << "Answer for: " << Uri << endl << Data;
       
       for (string::const_iterator I = Data.begin(); I < Data.end(); ++I)
       {
@@ -485,7 +486,7 @@ int ServerMethod::Loop()
       Fetch(0);
       
       // Fetch the next URL header data from the server.
-      switch (Server->RunHeaders(File))
+      switch (Server->RunHeaders(File, Queue->Uri))
       {
 	 case ServerState::RUN_HEADERS_OK:
 	 break;

+ 1 - 1
methods/server.h

@@ -68,7 +68,7 @@ struct ServerState
       RUN_HEADERS_PARSE_ERROR
    };
    /** \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;};
    virtual void Reset() {Major = 0; Minor = 0; Result = 0; Code[0] = '\0'; Size = 0;

Разница между файлами не показана из-за своего большого размера
+ 3318 - 0
po/apt-all.pot


Разница между файлами не показана из-за своего большого размера
+ 1194 - 1192
po/ar.po


Разница между файлами не показана из-за своего большого размера
+ 1335 - 1333
po/ast.po


Разница между файлами не показана из-за своего большого размера
+ 1337 - 1335
po/bg.po


Разница между файлами не показана из-за своего большого размера
+ 1186 - 1184
po/bs.po


Разница между файлами не показана из-за своего большого размера
+ 1339 - 1337
po/ca.po


Разница между файлами не показана из-за своего большого размера
+ 1321 - 1315
po/cs.po


Разница между файлами не показана из-за своего большого размера
+ 1408 - 1406
po/cy.po


Разница между файлами не показана из-за своего большого размера
+ 1327 - 1321
po/da.po


Разница между файлами не показана из-за своего большого размера
+ 1568 - 1559
po/de.po


Разница между файлами не показана из-за своего большого размера
+ 1325 - 1323
po/dz.po


Разница между файлами не показана из-за своего большого размера
+ 1326 - 1324
po/el.po


Разница между файлами не показана из-за своего большого размера
+ 1344 - 1342
po/es.po


Разница между файлами не показана из-за своего большого размера
+ 1307 - 1305
po/eu.po


Разница между файлами не показана из-за своего большого размера
+ 1315 - 1313
po/fi.po


Разница между файлами не показана из-за своего большого размера
+ 1354 - 1352
po/fr.po


Разница между файлами не показана из-за своего большого размера
+ 1344 - 1342
po/gl.po


Разница между файлами не показана из-за своего большого размера
+ 1334 - 1332
po/hu.po


Разница между файлами не показана из-за своего большого размера
+ 1343 - 1337
po/it.po


Разница между файлами не показана из-за своего большого размера
+ 1332 - 1326
po/ja.po


Разница между файлами не показана из-за своего большого размера
+ 1320 - 1318
po/km.po


Разница между файлами не показана из-за своего большого размера
+ 1325 - 1323
po/ko.po


Разница между файлами не показана из-за своего большого размера
+ 1167 - 1165
po/ku.po


Разница между файлами не показана из-за своего большого размера
+ 1263 - 1261
po/lt.po


Разница между файлами не показана из-за своего большого размера
+ 1323 - 1321
po/mr.po


Разница между файлами не показана из-за своего большого размера
+ 1330 - 1328
po/nb.po


Разница между файлами не показана из-за своего большого размера
+ 1314 - 1312
po/ne.po


Разница между файлами не показана из-за своего большого размера
+ 1352 - 1350
po/nl.po


Разница между файлами не показана из-за своего большого размера
+ 1322 - 1320
po/nn.po


Разница между файлами не показана из-за своего большого размера
+ 1338 - 1336
po/pl.po


Разница между файлами не показана из-за своего большого размера
+ 1335 - 1333
po/pt.po


Разница между файлами не показана из-за своего большого размера
+ 1328 - 1326
po/pt_BR.po


Разница между файлами не показана из-за своего большого размера
+ 1326 - 1324
po/ro.po


Разница между файлами не показана из-за своего большого размера
+ 1341 - 1339
po/ru.po


Разница между файлами не показана из-за своего большого размера
+ 1325 - 1323
po/sk.po


Разница между файлами не показана из-за своего большого размера
+ 1322 - 1320
po/sl.po


Разница между файлами не показана из-за своего большого размера
+ 1343 - 1341
po/sv.po


Разница между файлами не показана из-за своего большого размера
+ 1300 - 1294
po/th.po


Разница между файлами не показана из-за своего большого размера
+ 1338 - 1336
po/tl.po


Разница между файлами не показана из-за своего большого размера
+ 1338 - 1332
po/tr.po


Разница между файлами не показана из-за своего большого размера
+ 1443 - 1441
po/uk.po


Разница между файлами не показана из-за своего большого размера
+ 1454 - 1448
po/vi.po


Разница между файлами не показана из-за своего большого размера
+ 1311 - 1309
po/zh_CN.po


Разница между файлами не показана из-за своего большого размера
+ 1309 - 1307
po/zh_TW.po


+ 51 - 4
prepare-release

@@ -123,16 +123,63 @@ elif [ "$1" = 'buildlog' ]; 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 '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
 	echo >&1 "Usage:\t$0 pre-export
 \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
 »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.
 
-»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

+ 8 - 2
test/integration/framework

@@ -4,7 +4,7 @@ EXIT_CODE=0
 
 # we all like colorful messages
 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'
 	fi
 fi
@@ -1019,7 +1019,13 @@ testfileequal() {
 
 testempty() {
 	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() {

+ 1 - 1
test/integration/run-tests

@@ -22,7 +22,7 @@ done
 export MSGLEVEL="${MSGLEVEL:-3}"
 
 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'
 	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'
 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"
 
 setupaptarchive
@@ -33,16 +36,42 @@ foo/unstable 1.0 all
 testequal "foo/unstable 1.0 all
   $DESCR
 " 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
 testequal "foo/unstable 1.0 all
   $DESCR
 " 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
 testequal "foo/unstable 1.0 all
   $DESCR
 " 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
 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)"
 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
 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
 
 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
 dlstatus:1:20: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: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:40:Unpacking 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
 testfailure aptget install foo1 foo2 -y -o APT::Status-Fd=3
 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}]"
 buildsimplenativepackage 'pkg-arch-no-foo' "$NATIVE" '1.0' 'stable' "Build-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]
 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'
         [ "$(aptcache show apt 2>&1)" = "E: No packages found" ] && msgpass || msgfail
         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
         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\\", 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)
 {
    std::vector<std::string> result = StringSplit("", "");