]> git.saurik.com Git - apt.git/blobdiff - ftparchive/apt-ftparchive.cc
* ftparchive/apt-ftparchive.cc:
[apt.git] / ftparchive / apt-ftparchive.cc
index 055d876d0c568bfac9e62c9cc29126caa0c942dc..d0dea7768288edee11aee9a72d2e4473f6ee20c8 100644 (file)
@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
 // -*- mode: cpp; mode: fold -*-
 // Description                                                         /*{{{*/
-// $Id: apt-ftparchive.cc,v 1.2 2001/02/20 07:03:18 jgg Exp $
+// $Id: apt-ftparchive.cc,v 1.8.2.3 2004/01/02 22:01:48 mdz Exp $
 /* ######################################################################
 
    apt-scanpackages - Efficient work-alike for dpkg-scanpackages
 /* ######################################################################
 
    apt-scanpackages - Efficient work-alike for dpkg-scanpackages
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-ftparchive.h"
-#endif
-
 #include "apt-ftparchive.h"
     
 #include <apt-pkg/error.h>
 #include "apt-ftparchive.h"
     
 #include <apt-pkg/error.h>
@@ -24,6 +20,7 @@
 #include <apti18n.h>
 #include <algorithm>
 
 #include <apti18n.h>
 #include <algorithm>
 
+#include <climits>
 #include <sys/time.h>
 #include <regex.h>
 
 #include <sys/time.h>
 #include <regex.h>
 
 #include "writer.h"    
                                                                        /*}}}*/
 
 #include "writer.h"    
                                                                        /*}}}*/
 
-ostream c0out;
-ostream c1out;
-ostream c2out;
+using namespace std;    
+ostream c0out(0);
+ostream c1out(0);
+ostream c2out(0);
 ofstream devnull("/dev/null");
 unsigned Quiet = 0;
 
 ofstream devnull("/dev/null");
 unsigned Quiet = 0;
 
@@ -54,10 +52,15 @@ struct PackageMap
    string PkgFile;
    string BinCacheDB;
    string BinOverride;
    string PkgFile;
    string BinCacheDB;
    string BinOverride;
+   string ExtraOverride;
+
+   // We generate for this given arch
+   string Arch;
    
    // Stuff for the Source File
    string SrcFile;
    string SrcOverride;
    
    // Stuff for the Source File
    string SrcFile;
    string SrcOverride;
+   string SrcExtraOverride;
 
    // Contents 
    string Contents;
 
    // Contents 
    string Contents;
@@ -93,7 +96,8 @@ struct PackageMap
    bool GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats);
    bool GenSources(Configuration &Setup,struct CacheDB::Stats &Stats);
    bool GenContents(Configuration &Setup,
    bool GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats);
    bool GenSources(Configuration &Setup,struct CacheDB::Stats &Stats);
    bool GenContents(Configuration &Setup,
-                   PackageMap *Begin,PackageMap *End,
+                   vector<PackageMap>::iterator Begin,
+                   vector<PackageMap>::iterator End,
                    unsigned long &Left);
    
    PackageMap() : DeLinkLimit(0), Permissions(1), ContentsDone(false), 
                    unsigned long &Left);
    
    PackageMap() : DeLinkLimit(0), Permissions(1), ContentsDone(false), 
@@ -153,11 +157,13 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
    
    // Create a package writer object.
    PackagesWriter Packages(flCombine(CacheDir,BinCacheDB),
    
    // Create a package writer object.
    PackagesWriter Packages(flCombine(CacheDir,BinCacheDB),
-                          flCombine(OverrideDir,BinOverride));
+                          flCombine(OverrideDir,BinOverride),
+                          flCombine(OverrideDir,ExtraOverride),
+                          Arch);
    if (PkgExt.empty() == false && Packages.SetExts(PkgExt) == false)
    if (PkgExt.empty() == false && Packages.SetExts(PkgExt) == false)
-      return _error->Error("Package extension list is too long");
+      return _error->Error(_("Package extension list is too long"));
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
-      return _error->Error("Error Processing directory %s",BaseDir.c_str());
+      return _error->Error(_("Error processing directory %s"),BaseDir.c_str());
    
    Packages.PathPrefix = PathPrefix;
    Packages.DirStrip = ArchiveDir;
    
    Packages.PathPrefix = PathPrefix;
    Packages.DirStrip = ArchiveDir;
@@ -165,13 +171,13 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
 
    Packages.Stats.DeLinkBytes = Stats.DeLinkBytes;
    Packages.DeLinkLimit = DeLinkLimit;
 
    Packages.Stats.DeLinkBytes = Stats.DeLinkBytes;
    Packages.DeLinkLimit = DeLinkLimit;
-      
+
    // Create a compressor object
    MultiCompress Comp(flCombine(ArchiveDir,PkgFile),
                      PkgCompress,Permissions);
    Packages.Output = Comp.Input;
    if (_error->PendingError() == true)
    // Create a compressor object
    MultiCompress Comp(flCombine(ArchiveDir,PkgFile),
                      PkgCompress,Permissions);
    Packages.Output = Comp.Input;
    if (_error->PendingError() == true)
-      return _error->Error("Error Processing directory %s",BaseDir.c_str());
+      return _error->Error(_("Error processing directory %s"),BaseDir.c_str());
    
    c0out << ' ' << BaseDir << ":" << flush;
    
    
    c0out << ' ' << BaseDir << ":" << flush;
    
@@ -194,7 +200,7 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
    if (Comp.Finalize(Size) == false)
    {
       c0out << endl;
    if (Comp.Finalize(Size) == false)
    {
       c0out << endl;
-      return _error->Error("Error Processing directory %s",BaseDir.c_str());
+      return _error->Error(_("Error processing directory %s"),BaseDir.c_str());
    }
    
    if (Size != 0)
    }
    
    if (Size != 0)
@@ -218,8 +224,9 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
    
    return !_error->PendingError();
 }
    
    return !_error->PendingError();
 }
+
                                                                        /*}}}*/
                                                                        /*}}}*/
-// PackageMap::GenSources - Actually generate a Package file           /*{{{*/
+// PackageMap::GenSources - Actually generate a Source file            /*{{{*/
 // ---------------------------------------------------------------------
 /* This generates the Sources File described by this object. */
 bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
 // ---------------------------------------------------------------------
 /* This generates the Sources File described by this object. */
 bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
@@ -238,11 +245,12 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
    
    // Create a package writer object.
    SourcesWriter Sources(flCombine(OverrideDir,BinOverride),
    
    // Create a package writer object.
    SourcesWriter Sources(flCombine(OverrideDir,BinOverride),
-                         flCombine(OverrideDir,SrcOverride));
+                        flCombine(OverrideDir,SrcOverride),
+                        flCombine(OverrideDir,SrcExtraOverride));
    if (SrcExt.empty() == false && Sources.SetExts(SrcExt) == false)
    if (SrcExt.empty() == false && Sources.SetExts(SrcExt) == false)
-      return _error->Error("Source extension list is too long");
+      return _error->Error(_("Source extension list is too long"));
    if (_error->PendingError() == true)
    if (_error->PendingError() == true)
-      return _error->Error("Error Processing directory %s",BaseDir.c_str());
+      return _error->Error(_("Error processing directory %s"),BaseDir.c_str());
    
    Sources.PathPrefix = PathPrefix;
    Sources.DirStrip = ArchiveDir;
    
    Sources.PathPrefix = PathPrefix;
    Sources.DirStrip = ArchiveDir;
@@ -256,7 +264,7 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
                      SrcCompress,Permissions);
    Sources.Output = Comp.Input;
    if (_error->PendingError() == true)
                      SrcCompress,Permissions);
    Sources.Output = Comp.Input;
    if (_error->PendingError() == true)
-      return _error->Error("Error Processing directory %s",BaseDir.c_str());
+      return _error->Error(_("Error processing directory %s"),BaseDir.c_str());
 
    c0out << ' ' << BaseDir << ":" << flush;
    
 
    c0out << ' ' << BaseDir << ":" << flush;
    
@@ -278,7 +286,7 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
    if (Comp.Finalize(Size) == false)
    {
       c0out << endl;
    if (Comp.Finalize(Size) == false)
    {
       c0out << endl;
-      return _error->Error("Error Processing directory %s",BaseDir.c_str());
+      return _error->Error(_("Error processing directory %s"),BaseDir.c_str());
    }
       
    if (Size != 0)
    }
       
    if (Size != 0)
@@ -307,8 +315,9 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
    It searches the given iterator range for other package files that map
    into this contents file and includes their data as well when building. */
 bool PackageMap::GenContents(Configuration &Setup,
    It searches the given iterator range for other package files that map
    into this contents file and includes their data as well when building. */
 bool PackageMap::GenContents(Configuration &Setup,
-                           PackageMap *Begin,PackageMap *End,
-                           unsigned long &Left)
+                            vector<PackageMap>::iterator Begin,
+                            vector<PackageMap>::iterator End,
+                            unsigned long &Left)
 {
    if (Contents.empty() == true)
       return true;
 {
    if (Contents.empty() == true)
       return true;
@@ -326,7 +335,7 @@ bool PackageMap::GenContents(Configuration &Setup,
    // Create a package writer object.
    ContentsWriter Contents("");
    if (PkgExt.empty() == false && Contents.SetExts(PkgExt) == false)
    // Create a package writer object.
    ContentsWriter Contents("");
    if (PkgExt.empty() == false && Contents.SetExts(PkgExt) == false)
-      return _error->Error("Package extension list is too long");
+      return _error->Error(_("Package extension list is too long"));
    if (_error->PendingError() == true)
       return false;
 
    if (_error->PendingError() == true)
       return false;
 
@@ -356,7 +365,7 @@ bool PackageMap::GenContents(Configuration &Setup,
            return false;
         
         if (fwrite(Buf,1,ToRead,Comp.Input) != ToRead)
            return false;
         
         if (fwrite(Buf,1,ToRead,Comp.Input) != ToRead)
-           return _error->Errno("fwrite","Error writing header to contents file");
+           return _error->Errno("fwrite",_("Error writing header to contents file"));
         
         Size -= ToRead;
       }            
         
         Size -= ToRead;
       }            
@@ -366,7 +375,7 @@ bool PackageMap::GenContents(Configuration &Setup,
       files associated with this contents file into one great big honking
       memory structure, then dump the sorted version */
    c0out << ' ' << this->Contents << ":" << flush;
       files associated with this contents file into one great big honking
       memory structure, then dump the sorted version */
    c0out << ' ' << this->Contents << ":" << flush;
-   for (PackageMap *I = Begin; I != End; I++)
+   for (vector<PackageMap>::iterator I = Begin; I != End; I++)
    {
       if (I->Contents != this->Contents)
         continue;
    {
       if (I->Contents != this->Contents)
         continue;
@@ -386,7 +395,7 @@ bool PackageMap::GenContents(Configuration &Setup,
    if (Comp.Finalize(Size) == false || _error->PendingError() == true)
    {
       c0out << endl;
    if (Comp.Finalize(Size) == false || _error->PendingError() == true)
    {
       c0out << endl;
-      return _error->Error("Error Processing Contents %s",
+      return _error->Error(_("Error processing contents %s"),
                           this->Contents.c_str());
    }
    
                           this->Contents.c_str());
    }
    
@@ -447,12 +456,14 @@ void LoadTree(vector<PackageMap> &PkgList,Configuration &Setup)
       string Dist = Top->Tag;
 
       // Parse the sections
       string Dist = Top->Tag;
 
       // Parse the sections
-      const char *Sections = Block.Find("Sections").c_str();
+      string Tmp = Block.Find("Sections");
+      const char *Sections = Tmp.c_str();
       string Section;
       while (ParseQuoteWord(Sections,Section) == true)
       {
       string Section;
       while (ParseQuoteWord(Sections,Section) == true)
       {
-        const char *Archs = Block.Find("Architectures").c_str();
+        string Tmp2 = Block.Find("Architectures");
         string Arch;
         string Arch;
+        const char *Archs = Tmp2.c_str();
         while (ParseQuoteWord(Archs,Arch) == true)
         {
            struct SubstVar Vars[] = {{"$(DIST)",&Dist},
         while (ParseQuoteWord(Archs,Arch) == true)
         {
            struct SubstVar Vars[] = {{"$(DIST)",&Dist},
@@ -471,6 +482,7 @@ void LoadTree(vector<PackageMap> &PkgList,Configuration &Setup)
               Itm.SrcFile = SubstVar(Block.Find("Sources",DSources.c_str()),Vars);
               Itm.Tag = SubstVar("$(DIST)/$(SECTION)/source",Vars);
               Itm.FLFile = SubstVar(Block.Find("SourceFileList",DSFLFile.c_str()),Vars);
               Itm.SrcFile = SubstVar(Block.Find("Sources",DSources.c_str()),Vars);
               Itm.Tag = SubstVar("$(DIST)/$(SECTION)/source",Vars);
               Itm.FLFile = SubstVar(Block.Find("SourceFileList",DSFLFile.c_str()),Vars);
+              Itm.SrcExtraOverride = SubstVar(Block.Find("SrcExtraOverride"),Vars);
            }
            else
            {
            }
            else
            {
@@ -478,9 +490,11 @@ void LoadTree(vector<PackageMap> &PkgList,Configuration &Setup)
               Itm.BaseDir = SubstVar(Block.Find("Directory",DDir.c_str()),Vars);
               Itm.PkgFile = SubstVar(Block.Find("Packages",DPkg.c_str()),Vars);
               Itm.Tag = SubstVar("$(DIST)/$(SECTION)/$(ARCH)",Vars);
               Itm.BaseDir = SubstVar(Block.Find("Directory",DDir.c_str()),Vars);
               Itm.PkgFile = SubstVar(Block.Find("Packages",DPkg.c_str()),Vars);
               Itm.Tag = SubstVar("$(DIST)/$(SECTION)/$(ARCH)",Vars);
+              Itm.Arch = Arch;
               Itm.Contents = SubstVar(Block.Find("Contents",DContents.c_str()),Vars);
               Itm.ContentsHead = SubstVar(Block.Find("Contents::Header",DContentsH.c_str()),Vars);
               Itm.FLFile = SubstVar(Block.Find("FileList",DFLFile.c_str()),Vars);
               Itm.Contents = SubstVar(Block.Find("Contents",DContents.c_str()),Vars);
               Itm.ContentsHead = SubstVar(Block.Find("Contents::Header",DContentsH.c_str()),Vars);
               Itm.FLFile = SubstVar(Block.Find("FileList",DFLFile.c_str()),Vars);
+              Itm.ExtraOverride = SubstVar(Block.Find("ExtraOverride"),Vars);
            }
 
            Itm.GetGeneral(Setup,Block);
            }
 
            Itm.GetGeneral(Setup,Block);
@@ -508,6 +522,8 @@ void LoadBinDir(vector<PackageMap> &PkgList,Configuration &Setup)
       Itm.SrcFile = Block.Find("Sources");
       Itm.BinCacheDB = Block.Find("BinCacheDB");
       Itm.BinOverride = Block.Find("BinOverride");
       Itm.SrcFile = Block.Find("Sources");
       Itm.BinCacheDB = Block.Find("BinCacheDB");
       Itm.BinOverride = Block.Find("BinOverride");
+      Itm.ExtraOverride = Block.Find("ExtraOverride");
+      Itm.SrcExtraOverride = Block.Find("SrcExtraOverride");
       Itm.SrcOverride = Block.Find("SrcOverride");
       Itm.BaseDir = Top->Tag;
       Itm.FLFile = Block.Find("FileList");
       Itm.SrcOverride = Block.Find("SrcOverride");
       Itm.BaseDir = Top->Tag;
       Itm.FLFile = Block.Find("FileList");
@@ -528,16 +544,17 @@ void LoadBinDir(vector<PackageMap> &PkgList,Configuration &Setup)
 /* */
 bool ShowHelp(CommandLine &CmdL)
 {
 /* */
 bool ShowHelp(CommandLine &CmdL)
 {
-   ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
-           COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
+   ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
+           COMMON_ARCH,__DATE__,__TIME__);
    if (_config->FindB("version") == true)
       return true;
 
    cout << 
    if (_config->FindB("version") == true)
       return true;
 
    cout << 
-      "Usage: apt-ftparchive [options] command\n"
-      "Commands: packges binarypath [overridefile [pathprefix]]\n"
+    _("Usage: apt-ftparchive [options] command\n"
+      "Commands: packages binarypath [overridefile [pathprefix]]\n"
       "          sources srcpath [overridefile [pathprefix]]\n"
       "          contents path\n"
       "          sources srcpath [overridefile [pathprefix]]\n"
       "          contents path\n"
+      "          release path\n"
       "          generate config [groups]\n"
       "          clean config\n"
       "\n"
       "          generate config [groups]\n"
       "          clean config\n"
       "\n"
@@ -555,9 +572,9 @@ bool ShowHelp(CommandLine &CmdL)
       "\n"
       "The 'packages' and 'sources' command should be run in the root of the\n"
       "tree. BinaryPath should point to the base of the recursive search and \n"
       "\n"
       "The 'packages' and 'sources' command should be run in the root of the\n"
       "tree. BinaryPath should point to the base of the recursive search and \n"
-      "override file should contian the override flags. Pathprefix is\n"
+      "override file should contain the override flags. Pathprefix is\n"
       "appended to the filename fields if present. Example usage from the \n"
       "appended to the filename fields if present. Example usage from the \n"
-      "debian archive:\n"
+      "Debian archive:\n"
       "   apt-ftparchive packages dists/potato/main/binary-i386/ > \\\n"
       "               dists/potato/main/binary-i386/Packages\n"
       "\n"
       "   apt-ftparchive packages dists/potato/main/binary-i386/ > \\\n"
       "               dists/potato/main/binary-i386/Packages\n"
       "\n"
@@ -570,7 +587,7 @@ bool ShowHelp(CommandLine &CmdL)
       "  --no-delink Enable delinking debug mode\n"
       "  --contents  Control contents file generation\n"
       "  -c=?  Read this configuration file\n"
       "  --no-delink Enable delinking debug mode\n"
       "  --contents  Control contents file generation\n"
       "  -c=?  Read this configuration file\n"
-      "  -o=?  Set an arbitary configuration option" << endl;
+      "  -o=?  Set an arbitrary configuration option") << endl;
    
    return true;
 }
    
    return true;
 }
@@ -589,7 +606,7 @@ bool SimpleGenPackages(CommandLine &CmdL)
    
    // Create a package writer object.
    PackagesWriter Packages(_config->Find("APT::FTPArchive::DB"),
    
    // Create a package writer object.
    PackagesWriter Packages(_config->Find("APT::FTPArchive::DB"),
-                          Override);   
+                          Override, "");   
    if (_error->PendingError() == true)
       return false;
    
    if (_error->PendingError() == true)
       return false;
    
@@ -658,6 +675,30 @@ bool SimpleGenSources(CommandLine &CmdL)
 
    return true;
 }
 
    return true;
 }
+                                                                       /*}}}*/
+// SimpleGenRelease - Generate a Release file for a directory tree     /*{{{*/
+// ---------------------------------------------------------------------
+bool SimpleGenRelease(CommandLine &CmdL)
+{
+   if (CmdL.FileSize() < 2)
+      return ShowHelp(CmdL);
+
+   string Dir = CmdL.FileList[1];
+
+   ReleaseWriter Release("");
+   Release.DirStrip = Dir;
+
+   if (_error->PendingError() == true)
+      return false;
+
+   if (Release.RecursiveScan(Dir) == false)
+      return false;
+
+   Release.Finish();
+
+   return true;
+}
+
                                                                        /*}}}*/
 // Generate - Full generate, using a config file                       /*{{{*/
 // ---------------------------------------------------------------------
                                                                        /*}}}*/
 // Generate - Full generate, using a config file                       /*{{{*/
 // ---------------------------------------------------------------------
@@ -687,10 +728,10 @@ bool Generate(CommandLine &CmdL)
    // Generate packages
    if (CmdL.FileSize() <= 2)
    {
    // Generate packages
    if (CmdL.FileSize() <= 2)
    {
-      for (PackageMap *I = PkgList.begin(); I != PkgList.end(); I++)
+      for (vector<PackageMap>::iterator I = PkgList.begin(); I != PkgList.end(); I++)
         if (I->GenPackages(Setup,Stats) == false)
            _error->DumpErrors();
         if (I->GenPackages(Setup,Stats) == false)
            _error->DumpErrors();
-      for (PackageMap *I = PkgList.begin(); I != PkgList.end(); I++)
+      for (vector<PackageMap>::iterator I = PkgList.begin(); I != PkgList.end(); I++)
         if (I->GenSources(Setup,SrcStats) == false)
            _error->DumpErrors();
    }
         if (I->GenSources(Setup,SrcStats) == false)
            _error->DumpErrors();
    }
@@ -699,13 +740,13 @@ bool Generate(CommandLine &CmdL)
       // Make a choice list out of the package list..
       RxChoiceList *List = new RxChoiceList[2*PkgList.size()+1];
       RxChoiceList *End = List;
       // Make a choice list out of the package list..
       RxChoiceList *List = new RxChoiceList[2*PkgList.size()+1];
       RxChoiceList *End = List;
-      for (PackageMap *I = PkgList.begin(); I != PkgList.end(); I++)
+      for (vector<PackageMap>::iterator I = PkgList.begin(); I != PkgList.end(); I++)
       {
       {
-        End->UserData = I;
+        End->UserData = &(*I);
         End->Str = I->BaseDir.c_str();
         End++;
         
         End->Str = I->BaseDir.c_str();
         End++;
         
-        End->UserData = I;
+        End->UserData = &(*I);
         End->Str = I->Tag.c_str();
         End++;  
       }
         End->Str = I->Tag.c_str();
         End++;  
       }
@@ -715,7 +756,7 @@ bool Generate(CommandLine &CmdL)
       if (RegexChoice(List,CmdL.FileList + 2,CmdL.FileList + CmdL.FileSize()) == 0)
       {
         delete [] List;
       if (RegexChoice(List,CmdL.FileList + 2,CmdL.FileList + CmdL.FileSize()) == 0)
       {
         delete [] List;
-        return _error->Error("No selections matched");
+        return _error->Error(_("No selections matched"));
       }
       _error->DumpErrors();
       
       }
       _error->DumpErrors();
       
@@ -755,7 +796,7 @@ bool Generate(CommandLine &CmdL)
 
    // Sort the contents file list by date
    string ArchiveDir = Setup.FindDir("Dir::ArchiveDir");
 
    // Sort the contents file list by date
    string ArchiveDir = Setup.FindDir("Dir::ArchiveDir");
-   for (PackageMap *I = PkgList.begin(); I != PkgList.end(); I++)
+   for (vector<PackageMap>::iterator I = PkgList.begin(); I != PkgList.end(); I++)
    {
       struct stat A;
       if (MultiCompress::GetStat(flCombine(ArchiveDir,I->Contents),
    {
       struct stat A;
       if (MultiCompress::GetStat(flCombine(ArchiveDir,I->Contents),
@@ -772,7 +813,7 @@ bool Generate(CommandLine &CmdL)
       hashes of the .debs this means they have not changed either so the 
       contents must be up to date. */
    unsigned long MaxContentsChange = Setup.FindI("Default::MaxContentsChange",UINT_MAX)*1024;
       hashes of the .debs this means they have not changed either so the 
       contents must be up to date. */
    unsigned long MaxContentsChange = Setup.FindI("Default::MaxContentsChange",UINT_MAX)*1024;
-   for (PackageMap *I = PkgList.begin(); I != PkgList.end(); I++)
+   for (vector<PackageMap>::iterator I = PkgList.begin(); I != PkgList.end(); I++)
    {
       // This record is not relevent
       if (I->ContentsDone == true ||
    {
       // This record is not relevent
       if (I->ContentsDone == true ||
@@ -788,7 +829,7 @@ bool Generate(CommandLine &CmdL)
       {
         if (MultiCompress::GetStat(flCombine(ArchiveDir,I->PkgFile),I->PkgCompress,B) == false)
         {
       {
         if (MultiCompress::GetStat(flCombine(ArchiveDir,I->PkgFile),I->PkgCompress,B) == false)
         {
-           _error->Warning("Some files are missing in the package file group `%s'",I->PkgFile.c_str());
+           _error->Warning(_("Some files are missing in the package file group `%s'"),I->PkgFile.c_str());
            continue;
         }
         
            continue;
         }
         
@@ -840,7 +881,7 @@ bool Clean(CommandLine &CmdL)
 
    string CacheDir = Setup.FindDir("Dir::CacheDir");
    
 
    string CacheDir = Setup.FindDir("Dir::CacheDir");
    
-   for (PackageMap *I = PkgList.begin(); I != PkgList.end(); )
+   for (vector<PackageMap>::iterator I = PkgList.begin(); I != PkgList.end(); )
    {
       c0out << I->BinCacheDB << endl;
       CacheDB DB(flCombine(CacheDir,I->BinCacheDB));
    {
       c0out << I->BinCacheDB << endl;
       CacheDB DB(flCombine(CacheDir,I->BinCacheDB));
@@ -857,6 +898,7 @@ bool Clean(CommandLine &CmdL)
 
 int main(int argc, const char *argv[])
 {
 
 int main(int argc, const char *argv[])
 {
+   setlocale(LC_ALL, "");
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
       {0,"md5","APT::FTPArchive::MD5",0},
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
       {0,"md5","APT::FTPArchive::MD5",0},
@@ -874,6 +916,7 @@ int main(int argc, const char *argv[])
    CommandLine::Dispatch Cmds[] = {{"packages",&SimpleGenPackages},
                                    {"contents",&SimpleGenContents},
                                    {"sources",&SimpleGenSources},
    CommandLine::Dispatch Cmds[] = {{"packages",&SimpleGenPackages},
                                    {"contents",&SimpleGenContents},
                                    {"sources",&SimpleGenSources},
+                                   {"release",&SimpleGenRelease},
                                    {"generate",&Generate},
                                    {"clean",&Clean},
                                   {"help",&ShowHelp},
                                    {"generate",&Generate},
                                    {"clean",&Clean},
                                   {"help",&ShowHelp},
@@ -897,9 +940,9 @@ int main(int argc, const char *argv[])
    }
    
    // Setup the output streams
    }
    
    // Setup the output streams
-   c0out.rdbuf(cout.rdbuf());
-   c1out.rdbuf(cout.rdbuf());
-   c2out.rdbuf(cout.rdbuf());
+   c0out.rdbuf(clog.rdbuf());
+   c1out.rdbuf(clog.rdbuf());
+   c2out.rdbuf(clog.rdbuf());
    Quiet = _config->FindI("quiet",0);
    if (Quiet > 0)
       c0out.rdbuf(devnull.rdbuf());
    Quiet = _config->FindI("quiet",0);
    if (Quiet > 0)
       c0out.rdbuf(devnull.rdbuf());