Преглед изворни кода

* merged latest fixes from debian-sid
* apt-pkg/contrib/sha1.cc:
- fix illegally casts of on-stack buffer to a type requiring more
alignment than it has resulting in segfaults on sparc (Closes: #634696)
* apt-pkg/contrib/cdromutl.cc:
- fix escape problem when looking for the mounted devices
* apt-pkg/contrib/strutl.{h,cc}, test/libapt/strutil_test.cc:
- add new DeEscapeString() similar to DeQuoteString but
unescape character escapes like \0XX and \xXX (plus added
test)
* refresh po/*

* cmdline/apt-get.cc:
- fix missing download progress in apt-get download
- do not require unused partial dirs in 'source' (Closes: #633510)
- buildconflicts effect all architectures
- implement MultiarchCross for build-dep and source (Closes: #632221)
* cmdline/apt-key:
- use a tmpfile instead of /etc/apt/secring.gpg (Closes: #632596)
* debian/apt.postinst:
- remove /etc/apt/secring.gpg if it is an empty file
* doc/apt-cache.8.xml:
- apply madison typofix from John Feuerstein, thanks! (Closes: #633455)
* apt-pkg/policy.cc:
- emit an error on unknown APT::Default-Release value (Closes: #407511)
* apt-pkg/aptconfiguration.cc:
- ensure that native architecture is if not specified otherwise the
first architecture in the Architectures vector
* apt-pkg/deb/deblistparser.cc:
- Strip only :any and :native if MultiArch should be stripped as it is
save to ignore them in non-MultiArch contexts but if the dependency
is a specific architecture (and not the native) do not strip

Michael Vogt пре 15 година
родитељ
комит
0b7d641cf1
76 измењених фајлова са 23142 додато и 18282 уклоњено
  1. 2 0
      apt-pkg/acquire.h
  2. 1 1
      apt-pkg/aptconfiguration.cc
  3. 3 1
      apt-pkg/contrib/cdromutl.cc
  4. 1 1
      apt-pkg/contrib/configuration.cc
  5. 1 1
      apt-pkg/contrib/configuration.h
  6. 2 3
      apt-pkg/contrib/sha1.cc
  7. 61 0
      apt-pkg/contrib/strutl.cc
  8. 4 0
      apt-pkg/contrib/strutl.h
  9. 6 3
      apt-pkg/deb/deblistparser.cc
  10. 16 2
      apt-pkg/policy.cc
  11. 203 104
      cmdline/apt-get.cc
  12. 4 1
      cmdline/apt-key
  13. 5 0
      debian/apt.postinst
  14. 44 2
      debian/changelog
  15. 1 1
      doc/apt-cache.8.xml
  16. 24 3
      doc/apt-get.8.xml
  17. 1 0
      doc/examples/configure-index
  18. 1 1
      doc/po/apt-doc.pot
  19. 2 2
      doc/po/de.po
  20. 1 1
      doc/po/es.po
  21. 1 1
      doc/po/fr.po
  22. 1 1
      doc/po/it.po
  23. 2 2
      doc/po/ja.po
  24. 2 2
      doc/po/pl.po
  25. 2 2
      doc/po/pt.po
  26. 4 1
      doc/po/pt_BR.po
  27. 519 416
      po/ar.po
  28. 533 420
      po/ast.po
  29. 535 421
      po/bg.po
  30. 515 415
      po/bs.po
  31. 620 631
      po/ca.po
  32. 529 420
      po/cs.po
  33. 527 420
      po/cy.po
  34. 531 420
      po/da.po
  35. 533 420
      po/de.po
  36. 523 420
      po/dz.po
  37. 524 419
      po/el.po
  38. 534 420
      po/es.po
  39. 524 419
      po/eu.po
  40. 524 419
      po/fi.po
  41. 536 420
      po/fr.po
  42. 596 559
      po/gl.po
  43. 526 419
      po/hu.po
  44. 597 562
      po/it.po
  45. 534 421
      po/ja.po
  46. 521 418
      po/km.po
  47. 533 420
      po/ko.po
  48. 515 415
      po/ku.po
  49. 521 419
      po/lt.po
  50. 521 418
      po/mr.po
  51. 530 421
      po/nb.po
  52. 521 418
      po/ne.po
  53. 526 419
      po/nl.po
  54. 522 419
      po/nn.po
  55. 526 419
      po/pl.po
  56. 533 420
      po/pt.po
  57. 526 419
      po/pt_BR.po
  58. 526 419
      po/ro.po
  59. 534 420
      po/ru.po
  60. 529 420
      po/sk.po
  61. 545 454
      po/sl.po
  62. 533 420
      po/sv.po
  63. 521 418
      po/th.po
  64. 526 419
      po/tl.po
  65. 524 419
      po/uk.po
  66. 529 420
      po/vi.po
  67. 528 422
      po/zh_CN.po
  68. 527 420
      po/zh_TW.po
  69. 42 3
      test/integration/framework
  70. 47 0
      test/integration/test-bug-407511-fail-invalid-default-release
  71. 183 0
      test/integration/test-bug-632221-cross-dependency-satisfaction
  72. 38 4
      test/libapt/assert.h
  73. 6 0
      test/libapt/getarchitectures_test.cc
  74. 2 2
      test/libapt/getlanguages_test.cc
  75. 6 0
      test/libapt/makefile
  76. 46 0
      test/libapt/strutil_test.cc

+ 2 - 0
apt-pkg/acquire.h

@@ -349,6 +349,8 @@ class pkgAcquire
     */
    bool Setup(pkgAcquireStatus *Progress = NULL, string const &Lock = "");
 
+   void SetLog(pkgAcquireStatus *Progress) { Log = Progress; }
+
    /** \brief Construct a new pkgAcquire. */
    pkgAcquire(pkgAcquireStatus *Log) __deprecated;
    pkgAcquire();

+ 1 - 1
apt-pkg/aptconfiguration.cc

@@ -352,7 +352,7 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 
 	if (archs.empty() == true ||
 	    std::find(archs.begin(), archs.end(), arch) == archs.end())
-		archs.push_back(arch);
+		archs.insert(archs.begin(), arch);
 
 	// erase duplicates and empty strings
 	for (std::vector<string>::reverse_iterator a = archs.rbegin();

+ 3 - 1
apt-pkg/contrib/cdromutl.cc

@@ -258,7 +258,9 @@ string FindMountPointForDevice(const char *devnode)
                if(TokSplitString(' ', buf, out, 10))
                {
                   fclose(f);
-                  return string(out[1]);
+                  // unescape the \0XXX chars in the path
+                  string mount_point = out[1];
+                  return DeEscapeString(mount_point);
                }
             }
          }

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

@@ -345,7 +345,7 @@ void Configuration::Set(const char *Name,const string &Value)
 // Configuration::Set - Set an integer value				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
-void Configuration::Set(const char *Name,int const Value)
+void Configuration::Set(const char *Name,int const &Value)
 {
    Item *Itm = Lookup(Name,true);
    if (Itm == 0)

+ 1 - 1
apt-pkg/contrib/configuration.h

@@ -84,7 +84,7 @@ class Configuration
    void CndSet(const char *Name,const string &Value);
    void CndSet(const char *Name,const int Value);
    void Set(const char *Name,const string &Value);
-   void Set(const char *Name,const int Value);
+   void Set(const char *Name,const int &Value);
    
    inline bool Exists(const string &Name) const {return Exists(Name.c_str());};
    bool Exists(const char *Name) const;

+ 2 - 3
apt-pkg/contrib/sha1.cc

@@ -74,10 +74,9 @@ static void SHA1Transform(uint32_t state[5],uint8_t const buffer[64])
       uint32_t l[16];
    }
    CHAR64LONG16;
-   CHAR64LONG16 *block;
+   CHAR64LONG16 workspace, *block;
 
-   uint8_t workspace[64];
-   block = (CHAR64LONG16 *)workspace;
+   block = &workspace;
    memcpy(block,buffer,sizeof(workspace));
 
    /* Copy context->state[] to working vars */

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

@@ -1240,7 +1240,68 @@ bool CheckDomainList(const string &Host,const string &List)
    return false;
 }
 									/*}}}*/
+// DeEscapeString - unescape (\0XX and \xXX) from a string      	/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+string DeEscapeString(const string &input)
+{
+   char tmp[3];
+   string::const_iterator it, escape_start;
+   string output, octal, hex;
+   for (it = input.begin(); it != input.end(); it++) 
+   {
+      // just copy non-escape chars
+      if (*it != '\\')
+      {
+         output += *it;
+         continue;
+      }
 
+      // deal with double escape
+      if (*it == '\\' && 
+          (it + 1 < input.end()) &&  it[1] == '\\')
+      {
+         // copy
+         output += *it;
+         // advance iterator one step further
+         it += 1;
+         continue;
+      }
+        
+      // ensure we have a char to read
+      if (it + 1 == input.end())
+         continue;
+
+      // read it
+      it++;
+      switch (*it)
+      {
+         case '0':
+            if (it + 2 <= input.end()) {
+               tmp[0] = it[1];
+               tmp[1] = it[2];
+               tmp[2] = 0;
+               output += (char)strtol(tmp, 0, 8);
+               it += 2;
+            }
+            break;
+         case 'x':
+            if (it + 2 <= input.end()) {
+               tmp[0] = it[1];
+               tmp[1] = it[2];
+               tmp[2] = 0;
+               output += (char)strtol(tmp, 0, 16);
+               it += 2;
+            }
+            break;
+         default:
+            // FIXME: raise exception here?
+            break;
+      }
+   }
+   return output;
+}
+									/*}}}*/
 // URI::CopyFrom - Copy from an object					/*{{{*/
 // ---------------------------------------------------------------------
 /* This parses the URI into all of its components */

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

@@ -39,6 +39,10 @@ bool ParseCWord(const char *&String,string &Res);
 string QuoteString(const string &Str,const char *Bad);
 string DeQuoteString(const string &Str);
 string DeQuoteString(string::const_iterator const &begin, string::const_iterator const &end);
+
+// unescape (\0XX and \xXX) from a string
+string DeEscapeString(const string &input);
+
 string SizeToStr(double Bytes);
 string TimeToStr(unsigned long Sec);
 string Base64Encode(const string &Str);

+ 6 - 3
apt-pkg/deb/deblistparser.cc

@@ -456,7 +456,7 @@ const char *debListParser::ConvertRelation(const char *I,unsigned int &Op)
  *
  * The complete architecture, consisting of <kernel>-<cpu>.
  */
-static string CompleteArch(std::string& arch) {
+static string CompleteArch(std::string const &arch) {
     if (arch == "armel")              return "linux-arm";
     if (arch == "armhf")              return "linux-arm";
     if (arch == "lpia")               return "linux-i386";
@@ -495,9 +495,13 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
    Package.assign(Start,I - Start);
 
    // We don't want to confuse library users which can't handle MultiArch
+   string const arch = _config->Find("APT::Architecture");
    if (StripMultiArch == true) {
       size_t const found = Package.rfind(':');
-      if (found != string::npos)
+      if (found != string::npos &&
+	  (strcmp(Package.c_str() + found, ":any") == 0 ||
+	   strcmp(Package.c_str() + found, ":native") == 0 ||
+	   strcmp(Package.c_str() + found + 1, arch.c_str()) == 0))
 	 Package = Package.substr(0,found);
    }
 
@@ -538,7 +542,6 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop,
 
    if (ParseArchFlags == true)
    {
-      string arch = _config->Find("APT::Architecture");
       string completeArch = CompleteArch(arch);
 
       // Parse an architecture

+ 16 - 2
apt-pkg/policy.cc

@@ -56,8 +56,22 @@ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner)
    // The config file has a master override.
    string DefRel = _config->Find("APT::Default-Release");
    if (DefRel.empty() == false)
-      CreatePin(pkgVersionMatch::Release,"",DefRel,990);
-      
+   {
+      bool found = false;
+      // FIXME: make ExpressionMatches static to use it here easily
+      pkgVersionMatch vm("", pkgVersionMatch::None);
+      for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F)
+      {
+	 if ((F->Archive != 0 && vm.ExpressionMatches(DefRel, F.Archive()) == true) ||
+	     (F->Codename != 0 && vm.ExpressionMatches(DefRel, F.Codename()) == true) ||
+	     (F->Version != 0 && vm.ExpressionMatches(DefRel, F.Version()) == true))
+	    found = true;
+      }
+      if (found == false)
+	 _error->Error(_("The value '%s' is invalid for APT::Default-Release as such a release is not available in the sources"), DefRel.c_str());
+      else
+	 CreatePin(pkgVersionMatch::Release,"",DefRel,990);
+   }
    InitDefaults();
 }
 									/*}}}*/

+ 203 - 104
cmdline/apt-get.cc

@@ -1393,6 +1393,14 @@ bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache,
 	 return AllowFail;
    }
 
+   if (_config->FindB("Debug::BuildDeps",false) == true)
+   {
+      if (Remove == true)
+	 cout << "  Trying to remove " << Pkg << endl;
+      else
+	 cout << "  Trying to install " << Pkg << endl;
+   }
+
    if (Remove == true)
    {
       TryToRemove RemoveAction(Cache, &Fix);
@@ -2280,7 +2288,7 @@ bool DoDownload(CommandLine &CmdL)
 
    pkgAcquire Fetcher;
    AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
-   if (_config->FindB("APT::Get::Print-URIs") == true)
+   if (_config->FindB("APT::Get::Print-URIs") == false)
       Fetcher.Setup(&Stat);
 
    pkgRecords Recs(Cache);
@@ -2375,8 +2383,7 @@ bool DoSource(CommandLine &CmdL)
    // Create the download object
    AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));   
    pkgAcquire Fetcher;
-   if (Fetcher.Setup(&Stat) == false)
-      return false;
+   Fetcher.SetLog(&Stat);
 
    DscFile *Dsc = new DscFile[CmdL.FileSize()];
    
@@ -2622,12 +2629,17 @@ bool DoSource(CommandLine &CmdL)
 	 // Try to compile it with dpkg-buildpackage
 	 if (_config->FindB("APT::Get::Compile",false) == true)
 	 {
+	    string buildopts = _config->Find("APT::Get::Host-Architecture");
+	    if (buildopts.empty() == false)
+	       buildopts = "-a " + buildopts + " ";
+	    buildopts.append(_config->Find("DPkg::Build-Options","-b -uc"));
+
 	    // Call dpkg-buildpackage
 	    char S[500];
 	    snprintf(S,sizeof(S),"cd %s && %s %s",
 		     Dir.c_str(),
 		     _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
-		     _config->Find("DPkg::Build-Options","-b -uc").c_str());
+		     buildopts.c_str());
 	    
 	    if (system(S) != 0)
 	    {
@@ -2689,8 +2701,19 @@ bool DoBuildDep(CommandLine &CmdL)
    if (Fetcher.Setup(&Stat) == false)
       return false;
 
+   bool StripMultiArch;
+   string hostArch = _config->Find("APT::Get::Host-Architecture");
+   if (hostArch.empty() == false)
+   {
+      std::vector<std::string> archs = APT::Configuration::getArchitectures();
+      if (std::find(archs.begin(), archs.end(), hostArch) == archs.end())
+	 return _error->Error(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch.c_str());
+      StripMultiArch = false;
+   }
+   else
+      StripMultiArch = true;
+
    unsigned J = 0;
-   bool const StripMultiArch = APT::Configuration::getArchitectures().size() <= 1;
    for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
    {
       string Src;
@@ -2724,7 +2747,7 @@ bool DoBuildDep(CommandLine &CmdL)
 	 ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
 	 continue;
       }
-      
+
       // Install the requested packages
       vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
       pkgProblemResolver Fix(Cache);
@@ -2735,6 +2758,16 @@ bool DoBuildDep(CommandLine &CmdL)
 
          if (skipAlternatives == true)
          {
+            /*
+             * if there are alternatives, we've already picked one, so skip
+             * the rest
+             *
+             * TODO: this means that if there's a build-dep on A|B and B is
+             * installed, we'll still try to install A; more importantly,
+             * if A is currently broken, we cannot go back and try B. To fix 
+             * this would require we do a Resolve cycle for each package we 
+             * add to the install list. Ugh
+             */
             if (!hasAlternatives)
                skipAlternatives = false; // end of or group
             continue;
@@ -2743,27 +2776,117 @@ bool DoBuildDep(CommandLine &CmdL)
          if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
 	     (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
          {
-            pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
+            pkgCache::GrpIterator Grp = Cache->FindGrp((*D).Package);
             // Build-conflicts on unknown packages are silently ignored
-            if (Pkg.end() == true)
+            if (Grp.end() == true)
                continue;
 
-            pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
-
-            /* 
-             * Remove if we have an installed version that satisfies the 
-             * version criteria
-             */
-            if (IV.end() == false && 
-                Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
-               TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
+	    for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
+	    {
+	       pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
+	       /*
+		* Remove if we have an installed version that satisfies the
+		* version criteria
+		*/
+	       if (IV.end() == false &&
+		   Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
+		  TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
+	    }
          }
 	 else // BuildDep || BuildDepIndep
          {
-	    pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
             if (_config->FindB("Debug::BuildDeps",false) == true)
                  cout << "Looking for " << (*D).Package << "...\n";
 
+	    pkgCache::PkgIterator Pkg;
+
+	    // Cross-Building?
+	    if (StripMultiArch == false)
+	    {
+	       size_t const colon = D->Package.find(":");
+	       if (colon != string::npos &&
+		   (strcmp(D->Package.c_str() + colon, ":any") == 0 || strcmp(D->Package.c_str() + colon, ":native") == 0))
+		  Pkg = Cache->FindPkg(D->Package.substr(0,colon));
+	       else
+		  Pkg = Cache->FindPkg(D->Package);
+
+	       // We need to decide if host or build arch, so find a version we can look at
+	       pkgCache::VerIterator Ver;
+
+	       // a bad version either is invalid or doesn't satify dependency
+	       #define BADVER(Ver) Ver.end() == true || \
+				   (Ver.end() == false && D->Version.empty() == false && \
+				    Cache->VS().CheckDep(Ver.VerStr(),D->Op,D->Version.c_str()) == false)
+
+	       if (Pkg.end() == false)
+	       {
+		  Ver = (*Cache)[Pkg].InstVerIter(*Cache);
+		  if (BADVER(Ver))
+		     Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
+	       }
+	       if (BADVER(Ver))
+	       {
+		  pkgCache::PkgIterator HostPkg = Cache->FindPkg(D->Package, hostArch);
+		  if (HostPkg.end() == false)
+		  {
+		     Ver = (*Cache)[HostPkg].InstVerIter(*Cache);
+		     if (BADVER(Ver))
+		        Ver = (*Cache)[HostPkg].CandidateVerIter(*Cache);
+		  }
+	       }
+	       if ((BADVER(Ver)) == false)
+	       {
+		  string forbidden;
+		  if (Ver->MultiArch == pkgCache::Version::None || Ver->MultiArch == pkgCache::Version::All);
+		  else if (Ver->MultiArch == pkgCache::Version::Same)
+		  {
+		     if (colon != string::npos)
+			Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
+		     else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
+			forbidden = "Multi-Arch: same";
+		     // :native gets the buildArch
+		  }
+		  else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign)
+		  {
+		     if (colon != string::npos)
+			forbidden = "Multi-Arch: foreign";
+		  }
+		  else if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed)
+		  {
+		     if (colon == string::npos)
+			Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
+		     else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
+		     {
+			// prefer any installed over preferred non-installed architectures
+			pkgCache::GrpIterator Grp = Ver.ParentPkg().Group();
+			// we don't check for version here as we are better of with upgrading than remove and install
+			for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
+			   if (Pkg.CurrentVer().end() == false)
+			      break;
+			if (Pkg.end() == true)
+			   Pkg = Grp.FindPreferredPkg(true);
+		     }
+		     // native gets buildArch
+		  }
+		  if (forbidden.empty() == false)
+		  {
+		     if (_config->FindB("Debug::BuildDeps",false) == true)
+			cout << " :any is not allowed from M-A: same package " << (*D).Package << endl;
+		     if (hasAlternatives)
+			continue;
+		     return _error->Error(_("%s dependency for %s can't be satisfied "
+					    "because %s is not allowed on '%s' packages"),
+					  Last->BuildDepType(D->Type), Src.c_str(),
+					  D->Package.c_str(), "Multi-Arch: same");
+		  }
+	       }
+	       else if (_config->FindB("Debug::BuildDeps",false) == true)
+		  cout << " No multiarch info as we have no satisfying installed nor candidate for " << D->Package << " on build or host arch" << endl;
+	       #undef BADVER
+	    }
+	    else
+	       Pkg = Cache->FindPkg(D->Package);
+
 	    if (Pkg.end() == true)
             {
                if (_config->FindB("Debug::BuildDeps",false) == true)
@@ -2778,99 +2901,74 @@ bool DoBuildDep(CommandLine &CmdL)
                                     (*D).Package.c_str());
             }
 
-            /*
-             * if there are alternatives, we've already picked one, so skip
-             * the rest
-             *
-             * TODO: this means that if there's a build-dep on A|B and B is
-             * installed, we'll still try to install A; more importantly,
-             * if A is currently broken, we cannot go back and try B. To fix 
-             * this would require we do a Resolve cycle for each package we 
-             * add to the install list. Ugh
-             */
-                       
-	    /* 
-	     * If this is a virtual package, we need to check the list of
-	     * packages that provide it and see if any of those are
-	     * installed
-	     */
-            pkgCache::PrvIterator Prv = Pkg.ProvidesList();
-            for (; Prv.end() != true; Prv++)
-	    {
-               if (_config->FindB("Debug::BuildDeps",false) == true)
-                    cout << "  Checking provider " << Prv.OwnerPkg().FullName() << endl;
-
-	       if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
-	          break;
-            }
-            
-            // Get installed version and version we are going to install
 	    pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
+	    if (IV.end() == false)
+	    {
+	       if (_config->FindB("Debug::BuildDeps",false) == true)
+		  cout << "  Is installed\n";
 
-            if ((*D).Version[0] != '\0') {
-                 // Versioned dependency
-
-                 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
-
-                 for (; CV.end() != true; CV++)
-                 {
-                      if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
-                           break;
-                 }
-                 if (CV.end() == true)
-		 {
-		   if (hasAlternatives)
-		   {
-		      continue;
-		   }
-		   else
-		   {
-                      return _error->Error(_("%s dependency for %s cannot be satisfied "
-                                             "because no available versions of package %s "
-                                             "can satisfy version requirements"),
-                                           Last->BuildDepType((*D).Type),Src.c_str(),
-                                           (*D).Package.c_str());
-		   }
-		 }
-            }
-            else
-            {
-               // Only consider virtual packages if there is no versioned dependency
-               if (Prv.end() == false)
-               {
-                  if (_config->FindB("Debug::BuildDeps",false) == true)
-                     cout << "  Is provided by installed package " << Prv.OwnerPkg().FullName() << endl;
-                  skipAlternatives = hasAlternatives;
-                  continue;
-               }
-            }
+	       if (D->Version.empty() == true ||
+		   Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
+	       {
+		  skipAlternatives = hasAlternatives;
+		  continue;
+	       }
 
-            if (IV.end() == false)
-            {
-               if (_config->FindB("Debug::BuildDeps",false) == true)
-                  cout << "  Is installed\n";
+	       if (_config->FindB("Debug::BuildDeps",false) == true)
+		  cout << "    ...but the installed version doesn't meet the version requirement\n";
 
-               if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
-               {
-                  skipAlternatives = hasAlternatives;
-                  continue;
-               }
+	       if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
+		  return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
+					Last->BuildDepType((*D).Type), Src.c_str(), Pkg.FullName(true).c_str());
+	    }
 
-               if (_config->FindB("Debug::BuildDeps",false) == true)
-                  cout << "    ...but the installed version doesn't meet the version requirement\n";
-
-               if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
-               {
-                  return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
-                                       Last->BuildDepType((*D).Type),
-                                       Src.c_str(),
-                                       Pkg.FullName(true).c_str());
-               }
-            }
+	    // Only consider virtual packages if there is no versioned dependency
+	    if ((*D).Version.empty() == true)
+	    {
+	       /*
+		* If this is a virtual package, we need to check the list of
+		* packages that provide it and see if any of those are
+		* installed
+		*/
+	       pkgCache::PrvIterator Prv = Pkg.ProvidesList();
+	       for (; Prv.end() != true; Prv++)
+	       {
+		  if (_config->FindB("Debug::BuildDeps",false) == true)
+		     cout << "  Checking provider " << Prv.OwnerPkg().FullName() << endl;
 
+		  if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
+		     break;
+	       }
 
-            if (_config->FindB("Debug::BuildDeps",false) == true)
-               cout << "  Trying to install " << (*D).Package << endl;
+	       if (Prv.end() == false)
+	       {
+		  if (_config->FindB("Debug::BuildDeps",false) == true)
+		     cout << "  Is provided by installed package " << Prv.OwnerPkg().FullName() << endl;
+		  skipAlternatives = hasAlternatives;
+		  continue;
+	       }
+	    }
+	    else // versioned dependency
+	    {
+	       pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
+	       if (CV.end() == true ||
+		   Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == false)
+	       {
+		  if (hasAlternatives)
+		     continue;
+		  else if (CV.end() == false)
+		     return _error->Error(_("%s dependency for %s cannot be satisfied "
+					    "because candidate version of package %s "
+					    "can't satisfy version requirements"),
+					  Last->BuildDepType(D->Type), Src.c_str(),
+					  D->Package.c_str());
+		  else
+		     return _error->Error(_("%s dependency for %s cannot be satisfied "
+					    "because package %s has no candidate version"),
+					  Last->BuildDepType(D->Type), Src.c_str(),
+					  D->Package.c_str());
+	       }
+	    }
 
             if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false) == true)
             {
@@ -3257,6 +3355,7 @@ int main(int argc,const char *argv[])					/*{{{*/
       {'m',"ignore-missing","APT::Get::Fix-Missing",0},
       {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
       {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
+      {'a',"host-architecture","APT::Get::Host-Architecture",CommandLine::HasArg},
       {0,"download","APT::Get::Download",0},
       {0,"fix-missing","APT::Get::Fix-Missing",0},
       {0,"ignore-hold","APT::Ignore-Hold",0},      

+ 4 - 1
cmdline/apt-key

@@ -5,9 +5,12 @@ unset GREP_OPTIONS
 
 # We don't use a secret keyring, of course, but gpg panics and
 # implodes if there isn't one available
-GPG_CMD='gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /etc/apt/secring.gpg'
+SECRETKEYRING="$(mktemp)"
+trap "rm -f '${SECRETKEYRING}'" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM
+GPG_CMD="gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring ${SECRETKEYRING}"
 
 if [ "$(id -u)" -eq 0 ]; then
+	# we could use a tmpfile here too, but creation of this tends to be time-consuming
 	GPG_CMD="$GPG_CMD --trustdb-name /etc/apt/trustdb.gpg"
 fi
 

+ 5 - 0
debian/apt.postinst

@@ -15,6 +15,11 @@ set -e
 
 case "$1" in
     configure)
+	SECRING='/etc/apt/secring.gpg'
+	# test if secring is an empty normal file
+	if test -f $SECRING -a ! -s $SECRING; then
+		rm -f $SECRING
+	fi
 	apt-key update
     ;;
 

+ 44 - 2
debian/changelog

@@ -1,11 +1,15 @@
 apt (0.8.16~exp4) UNRELEASED; urgency=low
 
+  [ Julian Andres Klode ]
   * apt-pkg/pkgcache.h:
     - [ABI break] Add pkgCache::Header::CacheFileSize, storing the cache size
   * apt-pkg/pkgcachegen.cc:
     - Write the file size to the cache
   * apt-pkg/pkgcache.cc:
     - Check that cache is at least CacheFileSize bytes large (LP: #16467)
+  
+  [ Michael Vogt ]
+  * merged latest fixes from debian-sid
 
  -- Julian Andres Klode <jak@debian.org>  Wed, 20 Jul 2011 16:23:55 +0200
 
@@ -73,7 +77,25 @@ apt (0.8.16~exp1) experimental; urgency=low
 
  -- Michael Vogt <mvo@debian.org>  Wed, 29 Jun 2011 12:40:31 +0200
 
-apt (0.8.15.3) UNRELEASED; urgency=low
+apt (0.8.15.4) unstable; urgency=low
+
+  [ David Miller ]
+  * apt-pkg/contrib/sha1.cc:
+    - fix illegally casts of on-stack buffer to a type requiring more
+      alignment than it has resulting in segfaults on sparc (Closes: #634696)
+
+  [ Michael Vogt ]
+  * apt-pkg/contrib/cdromutl.cc:
+    - fix escape problem when looking for the mounted devices
+  * apt-pkg/contrib/strutl.{h,cc}, test/libapt/strutil_test.cc:
+    - add new DeEscapeString() similar to DeQuoteString but
+      unescape character escapes like \0XX and \xXX (plus added
+      test)
+  * refresh po/*
+  
+ -- Michael Vogt <mvo@debian.org>  Tue, 26 Jul 2011 12:12:27 +0200
+
+apt (0.8.15.3) unstable; urgency=low
 
   [ Michael Vogt ]
   * apt-pkg/acquire-item.cc:
@@ -81,6 +103,8 @@ apt (0.8.15.3) UNRELEASED; urgency=low
   * apt-pkg/algorithms.cc:
     - Hold back packages that would enter "policy-broken" state on upgrade
       when doing a "apt-get upgrade"
+  * cmdline/apt-get.cc:
+    - fix missing download progress in apt-get download
 
   [ David Kalnischkies ]
   * apt-pkg/pkgcachegen.cc:
@@ -92,12 +116,30 @@ apt (0.8.15.3) UNRELEASED; urgency=low
     - document APT::Architectures list (Closes: #612102)
   * cmdline/apt-get.cc:
     - restore all important dependencies for garbage packages (LP: #806274)
+    - do not require unused partial dirs in 'source' (Closes: #633510)
+    - buildconflicts effect all architectures
+    - implement MultiarchCross for build-dep and source (Closes: #632221)
   * apt-pkg/init.cc:
     - use CndSet in pkgInitConfig (Closes: #629617)
   * apt-pkg/depcache.cc:
     - change default of APT::AutoRemove::SuggestsImportant to true
+  * cmdline/apt-key:
+    - use a tmpfile instead of /etc/apt/secring.gpg (Closes: #632596)
+  * debian/apt.postinst:
+    - remove /etc/apt/secring.gpg if it is an empty file
+  * doc/apt-cache.8.xml:
+    - apply madison typofix from John Feuerstein, thanks! (Closes: #633455)
+  * apt-pkg/policy.cc:
+    - emit an error on unknown APT::Default-Release value (Closes: #407511)
+  * apt-pkg/aptconfiguration.cc:
+    - ensure that native architecture is if not specified otherwise the
+      first architecture in the Architectures vector
+  * apt-pkg/deb/deblistparser.cc:
+    - Strip only :any and :native if MultiArch should be stripped as it is
+      save to ignore them in non-MultiArch contexts but if the dependency
+      is a specific architecture (and not the native) do not strip
 
- -- David Kalnischkies <kalnischkies@gmail.com>  Fri, 15 Jul 2011 09:29:37 +0200
+ -- Michael Vogt <mvo@debian.org>  Mon, 25 Jul 2011 15:04:43 +0200
 
 apt (0.8.15.2) unstable; urgency=high
 

+ 1 - 1
doc/apt-cache.8.xml

@@ -263,7 +263,7 @@ Reverse Provides:
      about the priority selection of the named package.</para></listitem>
      </varlistentry>
 
-     <varlistentry><term>madison <replaceable>/[ pkg(s) ]</replaceable></term>
+     <varlistentry><term>madison <replaceable>[ pkg(s) ]</replaceable></term>
      <listitem><para><literal>apt-cache</literal>'s <literal>madison</literal> command attempts to mimic
      the output format and a subset of the functionality of the Debian
      archive management tool, <literal>madison</literal>.  It displays

+ 24 - 3
doc/apt-get.8.xml

@@ -54,6 +54,13 @@
 			<replaceable>target_release</replaceable>
 		</arg>
       </arg>
+      <arg>
+		<option>-a=</option>
+		<arg choice='plain'>
+			<replaceable>default_architecture</replaceable>
+		</arg>
+      </arg>
+
 
       <group choice="req">
          <arg choice='plain'>update</arg>
@@ -254,8 +261,10 @@
 
      <para>If the <option>--compile</option> option is specified
      then the package will be compiled to a binary .deb using
-     <command>dpkg-buildpackage</command>, if <option>--download-only</option>
-     is specified then the source package will not be unpacked.</para>
+     <command>dpkg-buildpackage</command> for the architecture as
+     defined by the <command>--host-architecture</command> option.
+     If <option>--download-only</option> is specified then the source package
+     will not be unpacked.</para>
 
      <para>A specific source version can be retrieved by postfixing the source name
      with an equals and then the version to fetch, similar to the mechanism
@@ -270,7 +279,9 @@
 
      <varlistentry><term>build-dep</term>
      <listitem><para><literal>build-dep</literal> causes apt-get to install/remove packages in an 
-     attempt to satisfy the build dependencies for a source package.</para></listitem>
+     attempt to satisfy the build dependencies for a source package. By default the dependencies are
+     satisfied to build the package nativly. If desired a host-architecture can be specified
+     with the <option>--host-architecture</option> option instead.</para></listitem>
      </varlistentry>
 
      <varlistentry><term>check</term>
@@ -438,6 +449,16 @@
      Configuration Item: <literal>APT::Get::Show-Versions</literal>.</para></listitem>
      </varlistentry>
 
+     <varlistentry><term><option>-a</option></term>
+                   <term><option>--host-architecture</option></term>
+     <listitem><para>This option controls the architecture packages are built for
+     by <command>apt-get source --compile</command> and how cross-builddependencies
+     are satisfied. By default is not set which means that the host architecture
+     is the same as the build architecture (which is defined by <literal>APT::Architecture</literal>)
+     Configuration Item: <literal>APT::Get::Host-Architecture</literal>
+     </para></listitem>
+     </varlistentry>
+
      <varlistentry><term><option>-b</option></term><term><option>--compile</option></term>
                    <term><option>--build</option></term>
      <listitem><para>Compile source packages after downloading them.

+ 1 - 0
doc/examples/configure-index

@@ -32,6 +32,7 @@ APT
   // Options for apt-get
   Get 
   {
+     Host-Architecture "armel";
      Arch-Only "false";
      AllowUnauthenticated "false";
      AutomaticRemove "false";       

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

@@ -928,7 +928,7 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
 msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>

+ 2 - 2
doc/po/de.po

@@ -1230,8 +1230,8 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
-msgstr "madison <replaceable>/[ Paket(e) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
+msgstr "madison <replaceable>[ Paket(e) ]</replaceable>"
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>
 #: apt-cache.8.xml:267

+ 1 - 1
doc/po/es.po

@@ -1303,7 +1303,7 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
 msgstr "madison <replaceable>[ paquete(s) ]</replaceable>"
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>

+ 1 - 1
doc/po/fr.po

@@ -1225,7 +1225,7 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
 msgstr "madison <replaceable>[ paquet(s) ]</replaceable>"
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>

+ 1 - 1
doc/po/it.po

@@ -893,7 +893,7 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
 msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>

+ 2 - 2
doc/po/ja.po

@@ -1304,8 +1304,8 @@ msgstr ""
 # type: Content of: <refentry><refsect1><refsect2><para><programlisting>
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
-msgstr "madison <replaceable>/[ pkg(s) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
+msgstr "madison <replaceable>[ pkg(s) ]</replaceable>"
 
 # type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>

+ 2 - 2
doc/po/pl.po

@@ -1311,8 +1311,8 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
-msgstr "madison <replaceable>/[ pakiet(y) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
+msgstr "madison <replaceable>[ pakiet(y) ]</replaceable>"
 
 #
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>

+ 2 - 2
doc/po/pt.po

@@ -1255,8 +1255,8 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
-msgstr "madison <replaceable>/[ pacote(s) ]</replaceable>"
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
+msgstr "madison <replaceable>[ pacote(s) ]</replaceable>"
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>
 #: apt-cache.8.xml:267

+ 4 - 1
doc/po/pt_BR.po

@@ -943,8 +943,11 @@ msgstr ""
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><term>
 #: apt-cache.8.xml:266
-msgid "madison <replaceable>/[ pkg(s) ]</replaceable>"
+#, fuzzy
+msgid "madison <replaceable>[ pkg(s) ]</replaceable>"
 msgstr ""
+"<programlisting>\n"
+"apt-get install <replaceable>pacote</replaceable>/testing\n"
 
 #. type: Content of: <refentry><refsect1><variablelist><varlistentry><listitem><para>
 #: apt-cache.8.xml:267

Разлика између датотеке није приказан због своје велике величине
+ 519 - 416
po/ar.po


Разлика између датотеке није приказан због своје велике величине
+ 533 - 420
po/ast.po


Разлика између датотеке није приказан због своје велике величине
+ 535 - 421
po/bg.po


Разлика између датотеке није приказан због своје велике величине
+ 515 - 415
po/bs.po


Разлика између датотеке није приказан због своје велике величине
+ 620 - 631
po/ca.po


Разлика између датотеке није приказан због своје велике величине
+ 529 - 420
po/cs.po


Разлика између датотеке није приказан због своје велике величине
+ 527 - 420
po/cy.po


Разлика између датотеке није приказан због своје велике величине
+ 531 - 420
po/da.po


Разлика између датотеке није приказан због своје велике величине
+ 533 - 420
po/de.po


Разлика између датотеке није приказан због своје велике величине
+ 523 - 420
po/dz.po


Разлика између датотеке није приказан због своје велике величине
+ 524 - 419
po/el.po


Разлика између датотеке није приказан због своје велике величине
+ 534 - 420
po/es.po


Разлика између датотеке није приказан због своје велике величине
+ 524 - 419
po/eu.po


Разлика између датотеке није приказан због своје велике величине
+ 524 - 419
po/fi.po


Разлика између датотеке није приказан због своје велике величине
+ 536 - 420
po/fr.po


Разлика између датотеке није приказан због своје велике величине
+ 596 - 559
po/gl.po


Разлика између датотеке није приказан због своје велике величине
+ 526 - 419
po/hu.po


Разлика између датотеке није приказан због своје велике величине
+ 597 - 562
po/it.po


Разлика између датотеке није приказан због своје велике величине
+ 534 - 421
po/ja.po


Разлика између датотеке није приказан због своје велике величине
+ 521 - 418
po/km.po


Разлика између датотеке није приказан због своје велике величине
+ 533 - 420
po/ko.po


Разлика између датотеке није приказан због своје велике величине
+ 515 - 415
po/ku.po


Разлика између датотеке није приказан због своје велике величине
+ 521 - 419
po/lt.po


Разлика између датотеке није приказан због своје велике величине
+ 521 - 418
po/mr.po


Разлика између датотеке није приказан због своје велике величине
+ 530 - 421
po/nb.po


Разлика између датотеке није приказан због своје велике величине
+ 521 - 418
po/ne.po


Разлика између датотеке није приказан због своје велике величине
+ 526 - 419
po/nl.po


Разлика између датотеке није приказан због своје велике величине
+ 522 - 419
po/nn.po


Разлика између датотеке није приказан због своје велике величине
+ 526 - 419
po/pl.po


Разлика између датотеке није приказан због своје велике величине
+ 533 - 420
po/pt.po


Разлика између датотеке није приказан због своје велике величине
+ 526 - 419
po/pt_BR.po


Разлика између датотеке није приказан због своје велике величине
+ 526 - 419
po/ro.po


Разлика између датотеке није приказан због своје велике величине
+ 534 - 420
po/ru.po


Разлика између датотеке није приказан због своје велике величине
+ 529 - 420
po/sk.po


Разлика између датотеке није приказан због своје велике величине
+ 545 - 454
po/sl.po


Разлика између датотеке није приказан због своје велике величине
+ 533 - 420
po/sv.po


Разлика између датотеке није приказан због своје велике величине
+ 521 - 418
po/th.po


Разлика између датотеке није приказан због своје велике величине
+ 526 - 419
po/tl.po


Разлика између датотеке није приказан због своје велике величине
+ 524 - 419
po/uk.po


Разлика између датотеке није приказан због своје велике величине
+ 529 - 420
po/vi.po


Разлика између датотеке није приказан због своје велике величине
+ 528 - 422
po/zh_CN.po


Разлика између датотеке није приказан због своје велике величине
+ 527 - 420
po/zh_TW.po


+ 42 - 3
test/integration/framework

@@ -151,6 +151,7 @@ setupenvironment() {
 
 configarchitecture() {
 	local CONFFILE=rootdir/etc/apt/apt.conf.d/01multiarch.conf
+	rm -f $CONFFILE
 	echo "APT::Architecture \"$1\";" > $CONFFILE
 	shift
 	while [ -n "$1" ]; do
@@ -429,6 +430,27 @@ Filename: pool/main/${NAME}/${NAME}_${VERSION}_${arch}.deb" >> $FILE
 	done
 }
 
+insertsource() {
+	local RELEASE="$1"
+	local NAME="$2"
+	local ARCH="$3"
+	local VERSION="$4"
+	local DEPENDENCIES="$5"
+	local ARCHS=""
+	local SPATH="aptarchive/dists/${RELEASE}/main/source"
+	mkdir -p $SPATH
+	local FILE="${SPATH}/Sources"
+	echo "Package: $NAME
+Binary: $NAME
+Version: $VERSION
+Maintainer: Joe Sixpack <joe@example.org>
+Architecture: $ARCH" >> $FILE
+	test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE
+	echo "Files:
+ d41d8cd98f00b204e9800998ecf8427e 0 ${NAME}_${VERSION}.dsc
+ d41d8cd98f00b204e9800998ecf8427e 0 ${NAME}_${VERSION}.tar.gz" >> $FILE
+}
+
 insertinstalledpackage() {
 	local NAME="$1"
 	local ARCH="$2"
@@ -481,6 +503,10 @@ buildaptarchivefromfiles() {
 	generatereleasefiles
 }
 
+# can be overridden by testcases for their pleasure
+getcodenamefromsuite() { echo -n "$1"; }
+getreleaseversionfromsuite() { true; }
+
 generatereleasefiles() {
 	msgninfo "\tGenerate Release files… "
 	local DATE="${1:-now}"
@@ -489,9 +515,22 @@ generatereleasefiles() {
 			aptftparchive -qq release $dir -o APT::FTPArchive::Release::Patterns::='Translation-*' > $dir/Index
 		done
 		for dir in $(find ./aptarchive/dists -mindepth 1 -maxdepth 1 -type d); do
-			local CODENAME="$(echo "$dir" | cut -d'/' -f 4)"
-			aptftparchive -qq release $dir -o APT::FTPArchive::Release::Suite="${CODENAME}" -o APT::FTPArchive::Release::Codename="${CODENAME}" | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference
-			if [ "$CODENAME" = "experimental" -o "$CODENAME" = "experimental2" ]; then
+			local SUITE="$(echo "$dir" | cut -d'/' -f 4)"
+			local CODENAME="$(getcodenamefromsuite $SUITE)"
+			local VERSION="$(getreleaseversionfromsuite $SUITE)"
+			if [ -z "$VERSION" ]; then
+				aptftparchive -qq release $dir \
+					-o APT::FTPArchive::Release::Suite="${SUITE}" \
+					-o APT::FTPArchive::Release::Codename="${CODENAME}" \
+						| sed -e '/0 Release$/ d' > $dir/Release # remove the self reference
+			else
+				aptftparchive -qq release $dir \
+					-o APT::FTPArchive::Release::Suite="${SUITE}" \
+					-o APT::FTPArchive::Release::Codename="${CODENAME}" \
+					-o APT::FTPArchive::Release::Version="${VERSION}" \
+						| sed -e '/0 Release$/ d' > $dir/Release # remove the self reference
+			fi
+			if [ "$SUITE" = "experimental" -o "$SUITE" = "experimental2" ]; then
 				sed -i '/^Date: / a\
 NotAutomatic: yes' $dir/Release
 			fi

+ 47 - 0
test/integration/test-bug-407511-fail-invalid-default-release

@@ -0,0 +1,47 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'i386'
+
+insertpackage 'unstable' 'cool' 'all' '1.0-1'
+
+getcodenamefromsuite() {
+	if [ "$SUITE" = 'unstable' ]; then
+		echo -n 'sid'
+	else
+		echo -n "$SUITE"
+	fi
+}
+getreleaseversionfromsuite() {
+	if [ "$SUITE" = 'unstable' ]; then
+		echo -n '42.0'
+	else
+		echo -n '0.8.15'
+	fi
+}
+
+setupaptarchive
+
+passdist() {
+	msgtest "Test that target-release is accepted" $1
+	aptget dist-upgrade -t $1 -qq && msgpass || msgfail
+}
+
+faildist() {
+	msgtest "Test that target-release is refused" $1
+	aptget dist-upgrade -t $1 -qq 2> /dev/null && msgfail || msgpass
+}
+
+passdist unstable
+passdist sid
+faildist sidd
+faildist stable
+passdist 42.0
+passdist 42.*
+passdist 42*
+passdist 4*.0
+faildist 21.0
+faildist 21*

+ 183 - 0
test/integration/test-bug-632221-cross-dependency-satisfaction

@@ -0,0 +1,183 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+setupenvironment
+configarchitecture 'amd64' 'armel'
+
+insertinstalledpackage 'build-essential' 'all' '11.5'
+
+insertpackage 'unstable' 'doxygen' 'amd64,armel' '1.0'
+insertpackage 'unstable' 'libc6' 'amd64,armel' '1.0' 'Multi-Arch: same'
+insertpackage 'unstable' 'libc6-dev' 'amd64,armel' '1.0' 'Depends: libc6
+Multi-Arch: same'
+insertpackage 'unstable' 'cool' 'amd64,armel' '1.0' 'Multi-Arch: allowed'
+insertpackage 'unstable' 'amdboot' 'amd64' '1.0'
+insertpackage 'unstable' 'foreigner' 'amd64,armel' '1.0' 'Multi-Arch: foreign'
+
+insertsource 'unstable' 'apt' 'any' '0.8.15' 'Build-Depends: doxygen, libc6-dev, libc6-dev:native, cool:any, amdboot:amd64, foreigner'
+
+setupaptarchive
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  amdboot cool doxygen foreigner libc6 libc6-dev
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+Inst amdboot (1.0 unstable [amd64])
+Inst cool (1.0 unstable [amd64])
+Inst doxygen (1.0 unstable [amd64])
+Inst foreigner (1.0 unstable [amd64])
+Inst libc6 (1.0 unstable [amd64])
+Inst libc6-dev (1.0 unstable [amd64])
+Conf amdboot (1.0 unstable [amd64])
+Conf cool (1.0 unstable [amd64])
+Conf doxygen (1.0 unstable [amd64])
+Conf foreigner (1.0 unstable [amd64])
+Conf libc6 (1.0 unstable [amd64])
+Conf libc6-dev (1.0 unstable [amd64])' aptget build-dep apt -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  amdboot cool doxygen foreigner libc6 libc6:armel libc6-dev libc6-dev:armel
+0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
+Inst amdboot (1.0 unstable [amd64])
+Inst cool (1.0 unstable [amd64])
+Inst doxygen (1.0 unstable [amd64])
+Inst foreigner (1.0 unstable [amd64])
+Inst libc6:armel (1.0 unstable [armel])
+Inst libc6 (1.0 unstable [amd64])
+Inst libc6-dev:armel (1.0 unstable [armel])
+Inst libc6-dev (1.0 unstable [amd64])
+Conf amdboot (1.0 unstable [amd64])
+Conf cool (1.0 unstable [amd64])
+Conf doxygen (1.0 unstable [amd64])
+Conf foreigner (1.0 unstable [amd64])
+Conf libc6 (1.0 unstable [amd64])
+Conf libc6:armel (1.0 unstable [armel])
+Conf libc6-dev (1.0 unstable [amd64])
+Conf libc6-dev:armel (1.0 unstable [armel])' aptget build-dep apt -s -a armel
+
+configarchitecture 'armel' 'amd64'
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  amdboot:amd64 cool doxygen foreigner libc6 libc6-dev
+0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
+Inst amdboot:amd64 (1.0 unstable [amd64])
+Inst cool (1.0 unstable [armel])
+Inst doxygen (1.0 unstable [armel])
+Inst foreigner (1.0 unstable [armel])
+Inst libc6 (1.0 unstable [armel])
+Inst libc6-dev (1.0 unstable [armel])
+Conf amdboot:amd64 (1.0 unstable [amd64])
+Conf cool (1.0 unstable [armel])
+Conf doxygen (1.0 unstable [armel])
+Conf foreigner (1.0 unstable [armel])
+Conf libc6 (1.0 unstable [armel])
+Conf libc6-dev (1.0 unstable [armel])' aptget build-dep apt -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  amdboot:amd64 cool doxygen foreigner libc6:amd64 libc6 libc6-dev:amd64
+  libc6-dev
+0 upgraded, 8 newly installed, 0 to remove and 0 not upgraded.
+Inst amdboot:amd64 (1.0 unstable [amd64])
+Inst cool (1.0 unstable [armel])
+Inst doxygen (1.0 unstable [armel])
+Inst foreigner (1.0 unstable [armel])
+Inst libc6 (1.0 unstable [armel])
+Inst libc6:amd64 (1.0 unstable [amd64])
+Inst libc6-dev (1.0 unstable [armel])
+Inst libc6-dev:amd64 (1.0 unstable [amd64])
+Conf amdboot:amd64 (1.0 unstable [amd64])
+Conf cool (1.0 unstable [armel])
+Conf doxygen (1.0 unstable [armel])
+Conf foreigner (1.0 unstable [armel])
+Conf libc6:amd64 (1.0 unstable [amd64])
+Conf libc6 (1.0 unstable [armel])
+Conf libc6-dev:amd64 (1.0 unstable [amd64])
+Conf libc6-dev (1.0 unstable [armel])' aptget build-dep apt -s -a amd64
+
+configarchitecture 'amd64' 'armel'
+
+insertinstalledpackage 'cool' 'amd64' '0.5'
+insertinstalledpackage 'foreigner' 'armel' '0.5'
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  amdboot doxygen libc6 libc6-dev
+0 upgraded, 4 newly installed, 0 to remove and 2 not upgraded.
+Inst amdboot (1.0 unstable [amd64])
+Inst doxygen (1.0 unstable [amd64])
+Inst libc6 (1.0 unstable [amd64])
+Inst libc6-dev (1.0 unstable [amd64])
+Conf amdboot (1.0 unstable [amd64])
+Conf doxygen (1.0 unstable [amd64])
+Conf libc6 (1.0 unstable [amd64])
+Conf libc6-dev (1.0 unstable [amd64])' aptget build-dep apt -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  amdboot doxygen libc6 libc6:armel libc6-dev libc6-dev:armel
+0 upgraded, 6 newly installed, 0 to remove and 2 not upgraded.
+Inst amdboot (1.0 unstable [amd64])
+Inst doxygen (1.0 unstable [amd64])
+Inst libc6:armel (1.0 unstable [armel])
+Inst libc6 (1.0 unstable [amd64])
+Inst libc6-dev:armel (1.0 unstable [armel])
+Inst libc6-dev (1.0 unstable [amd64])
+Conf amdboot (1.0 unstable [amd64])
+Conf doxygen (1.0 unstable [amd64])
+Conf libc6 (1.0 unstable [amd64])
+Conf libc6:armel (1.0 unstable [armel])
+Conf libc6-dev (1.0 unstable [amd64])
+Conf libc6-dev:armel (1.0 unstable [armel])' aptget build-dep apt -s -a armel
+
+configarchitecture 'armel' 'amd64'
+
+# cool 0.5 is not M-A: allowed, so amd64 is not acceptable
+testequal 'Reading package lists...
+Building dependency tree...
+The following packages will be REMOVED:
+  cool:amd64
+The following NEW packages will be installed:
+  amdboot:amd64 cool doxygen libc6 libc6-dev
+0 upgraded, 5 newly installed, 1 to remove and 1 not upgraded.
+Remv cool:amd64 [0.5]
+Inst amdboot:amd64 (1.0 unstable [amd64])
+Inst cool (1.0 unstable [armel])
+Inst doxygen (1.0 unstable [armel])
+Inst libc6 (1.0 unstable [armel])
+Inst libc6-dev (1.0 unstable [armel])
+Conf amdboot:amd64 (1.0 unstable [amd64])
+Conf cool (1.0 unstable [armel])
+Conf doxygen (1.0 unstable [armel])
+Conf libc6 (1.0 unstable [armel])
+Conf libc6-dev (1.0 unstable [armel])' aptget build-dep apt -s
+
+testequal 'Reading package lists...
+Building dependency tree...
+The following NEW packages will be installed:
+  amdboot:amd64 doxygen libc6:amd64 libc6 libc6-dev:amd64 libc6-dev
+0 upgraded, 6 newly installed, 0 to remove and 2 not upgraded.
+Inst amdboot:amd64 (1.0 unstable [amd64])
+Inst doxygen (1.0 unstable [armel])
+Inst libc6 (1.0 unstable [armel])
+Inst libc6:amd64 (1.0 unstable [amd64])
+Inst libc6-dev (1.0 unstable [armel])
+Inst libc6-dev:amd64 (1.0 unstable [amd64])
+Conf amdboot:amd64 (1.0 unstable [amd64])
+Conf doxygen (1.0 unstable [armel])
+Conf libc6:amd64 (1.0 unstable [amd64])
+Conf libc6 (1.0 unstable [armel])
+Conf libc6-dev:amd64 (1.0 unstable [amd64])
+Conf libc6-dev (1.0 unstable [armel])' aptget build-dep apt -s -a amd64
+
+

+ 38 - 4
test/libapt/assert.h

@@ -1,9 +1,9 @@
 #include <iostream>
 
-#define equals(x,y) assertEquals(x, y, __LINE__)
+#define equals(x,y) assertEquals(y, x, __LINE__)
 
 template < typename X, typename Y >
-void OutputAssert(X expect, char const* compare, Y get, unsigned long const &line) {
+void OutputAssertEqual(X expect, char const* compare, Y get, unsigned long const &line) {
 	std::cerr << "Test FAILED: »" << expect << "« " << compare << " »" << get << "« at line " << line << std::endl;
 }
 
@@ -11,11 +11,45 @@ template < typename X, typename Y >
 void assertEquals(X expect, Y get, unsigned long const &line) {
 	if (expect == get)
 		return;
-	OutputAssert(expect, "==", get, line);
+	OutputAssertEqual(expect, "==", get, line);
 }
 
 void assertEquals(unsigned int const &expect, int const &get, unsigned long const &line) {
 	if (get < 0)
-		OutputAssert(expect, "==", get, line);
+		OutputAssertEqual(expect, "==", get, line);
 	assertEquals<unsigned int const&, unsigned int const&>(expect, get, line);
 }
+
+void assertEquals(int const &expect, unsigned int const &get, unsigned long const &line) {
+	if (expect < 0)
+		OutputAssertEqual(expect, "==", get, line);
+	assertEquals<unsigned int const&, unsigned int const&>(expect, get, line);
+}
+
+
+#define equalsOr2(x,y,z) assertEqualsOr2(y, z, x, __LINE__)
+
+template < typename X, typename Y >
+void OutputAssertEqualOr2(X expect1, X expect2, char const* compare, Y get, unsigned long const &line) {
+	std::cerr << "Test FAILED: »" << expect1 << "« or »" << expect2 << "« " << compare << " »" << get << "« at line " << line << std::endl;
+}
+
+template < typename X, typename Y >
+void assertEqualsOr2(X expect1, X expect2, Y get, unsigned long const &line) {
+	if (expect1 == get || expect2 == get)
+		return;
+	OutputAssertEqualOr2(expect1, expect2, "==", get, line);
+}
+
+void assertEqualsOr2(unsigned int const &expect1, unsigned int const &expect2, int const &get, unsigned long const &line) {
+	if (get < 0)
+		OutputAssertEqualOr2(expect1, expect2, "==", get, line);
+	assertEqualsOr2<unsigned int const&, unsigned int const&>(expect1, expect2, get, line);
+}
+
+void assertEqualsOr2(int const &expect1, int const &expect2, unsigned int const &get, unsigned long const &line) {
+	if (expect1 < 0 && expect2 < 0)
+		OutputAssertEqualOr2(expect1, expect2, "==", get, line);
+	assertEqualsOr2<unsigned int const&, unsigned int const&>(expect1, expect2, get, line);
+}
+

+ 6 - 0
test/libapt/getarchitectures_test.cc

@@ -39,6 +39,12 @@ int main(int argc,char *argv[])
 	_config->Set("APT::Architecture", "armel");
 	vec = APT::Configuration::getArchitectures(false);
 	equals(vec.size(), 2);
+	equals(vec[0], "armel");
+	equals(vec[1], "i386");
+
+	_config->Set("APT::Architectures::2", "armel");
+	vec = APT::Configuration::getArchitectures(false);
+	equals(vec.size(), 2);
 	equals(vec[0], "i386");
 	equals(vec[1], "armel");
 

+ 2 - 2
test/libapt/getlanguages_test.cc

@@ -138,8 +138,8 @@ int main(int argc,char *argv[])
 	equals(vec[1], "de");
 	equals(vec[2], "en");
 	equals(vec[3], "none");
-	equals(vec[4], "pt");
-	equals(vec[5], "tr");
+	equalsOr2(vec[4], "pt", "tr");
+	equalsOr2(vec[5], "tr", "pt");
 
 	_config->Set("Dir::State::lists", "/non-existing-dir");
 	_config->Set("Acquire::Languages::1", "none");

+ 6 - 0
test/libapt/makefile

@@ -52,3 +52,9 @@ PROGRAM = HashSums${BASENAME}
 SLIBS = -lapt-pkg
 SOURCE = hashsums_test.cc
 include $(PROGRAM_H)
+
+# test the strutils stuff
+PROGRAM = StrUtil${BASENAME}
+SLIBS = -lapt-pkg
+SOURCE = strutil_test.cc
+include $(PROGRAM_H)

+ 46 - 0
test/libapt/strutil_test.cc

@@ -0,0 +1,46 @@
+#include <apt-pkg/strutl.h>
+
+#include "assert.h"
+
+int main(int argc,char *argv[])
+{
+   string input, output, expected;
+
+   // no input
+   input = "foobar";
+   expected = "foobar";
+   output = DeEscapeString(input);
+   equals(output, expected);
+
+   // hex and octal
+   input = "foo\\040bar\\x0abaz";
+   expected = "foo bar\nbaz";
+   output = DeEscapeString(input);
+   equals(output, expected);
+
+   // at the end
+   input = "foo\\040";
+   expected = "foo ";
+   output = DeEscapeString(input);
+   equals(output, expected);
+
+   // double escape
+   input = "foo\\\\ x";
+   expected = "foo\\ x";
+   output = DeEscapeString(input);
+   equals(output, expected);
+
+   // double escape at the end
+   input = "\\\\foo\\\\";
+   expected = "\\foo\\";
+   output = DeEscapeString(input);
+   equals(output, expected);
+
+   // the string that we actually need it for
+   input = "/media/Ubuntu\\04011.04\\040amd64";
+   expected = "/media/Ubuntu 11.04 amd64";
+   output = DeEscapeString(input);
+   equals(output, expected);
+
+   return 0;
+}