]> git.saurik.com Git - apt.git/blobdiff - ftparchive/apt-ftparchive.cc
Merge branch 'feature/edit-sources' into debian/sid
[apt.git] / ftparchive / apt-ftparchive.cc
index 055d876d0c568bfac9e62c9cc29126caa0c942dc..2639bc2f6e77f1dc9f87ff0be4dacac713321e0b 100644 (file)
@@ -1,40 +1,40 @@
 // -*- 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-ftparchive - Efficient work-alike for dpkg-scanpackages
 
    Let contents be disabled from the conf
    
    ##################################################################### */
                                                                        /*}}}*/
 // Include Files                                                       /*{{{*/
-#ifdef __GNUG__
-#pragma implementation "apt-ftparchive.h"
-#endif
+#include <config.h>
 
-#include "apt-ftparchive.h"
-    
 #include <apt-pkg/error.h>
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/cmndline.h>
 #include <apt-pkg/strutl.h>
-#include <config.h>
-#include <apti18n.h>
+#include <apt-pkg/init.h>
 #include <algorithm>
 
+#include <climits>
 #include <sys/time.h>
 #include <regex.h>
 
+#include "apt-ftparchive.h"
 #include "contents.h"
 #include "multicompress.h"
-#include "writer.h"    
+#include "writer.h"
+
+#include <apti18n.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;
 
@@ -54,10 +54,19 @@ struct PackageMap
    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;
+   string SrcExtraOverride;
+
+   // Translation master file
+   bool LongDesc;
+   TranslationWriter *TransWriter;
 
    // Contents 
    string Contents;
@@ -93,11 +102,13 @@ struct PackageMap
    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), 
-        PkgDone(false), SrcDone(false), ContentsMTime(0) {};
+   PackageMap() : LongDesc(true), TransWriter(NULL), DeLinkLimit(0), Permissions(1),
+                 ContentsDone(false), PkgDone(false), SrcDone(false),
+                 ContentsMTime(0) {};
 };
                                                                        /*}}}*/
 
@@ -126,7 +137,7 @@ void PackageMap::GetGeneral(Configuration &Setup,Configuration &Block)
                       Setup.Find("Default::Packages::Extensions",".deb").c_str());
    
    Permissions = Setup.FindI("Default::FileMode",0644);
-   
+
    if (FLFile.empty() == false)
       FLFile = flCombine(Setup.Find("Dir::FileListDir"),FLFile);
    
@@ -153,25 +164,30 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
    
    // 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)
-      return _error->Error("Package extension list is too long");
+      return _error->Error(_("Package extension list is too long"));
    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.InternalPrefix = flCombine(ArchiveDir,InternalPrefix);
 
+   Packages.TransWriter = TransWriter;
+   Packages.LongDescription = LongDesc;
+
    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)
-      return _error->Error("Error Processing directory %s",BaseDir.c_str());
+      return _error->Error(_("Error processing directory %s"),BaseDir.c_str());
    
    c0out << ' ' << BaseDir << ":" << flush;
    
@@ -190,11 +206,11 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
    Packages.Output = 0;      // Just in case
    
    // Finish compressing
-   unsigned long Size;
+   unsigned long long Size;
    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)
@@ -218,8 +234,9 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats)
    
    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)
@@ -237,12 +254,14 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
    SrcDone = true;
    
    // Create a package writer object.
-   SourcesWriter Sources(flCombine(OverrideDir,BinOverride),
-                         flCombine(OverrideDir,SrcOverride));
+   SourcesWriter Sources(_config->Find("APT::FTPArchive::DB"),
+                        flCombine(OverrideDir,BinOverride),
+                        flCombine(OverrideDir,SrcOverride),
+                        flCombine(OverrideDir,SrcExtraOverride));
    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)
-      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;
@@ -256,7 +275,7 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
                      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;
    
@@ -274,11 +293,11 @@ bool PackageMap::GenSources(Configuration &Setup,struct CacheDB::Stats &Stats)
    Sources.Output = 0;      // Just in case
    
    // Finish compressing
-   unsigned long Size;
+   unsigned long long Size;
    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)
@@ -307,8 +326,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,
-                           PackageMap *Begin,PackageMap *End,
-                           unsigned long &Left)
+                            vector<PackageMap>::iterator Begin,
+                            vector<PackageMap>::iterator End,
+                            unsigned long &Left)
 {
    if (Contents.empty() == true)
       return true;
@@ -324,9 +344,9 @@ bool PackageMap::GenContents(Configuration &Setup,
    gettimeofday(&StartTime,0);   
    
    // Create a package writer object.
-   ContentsWriter Contents("");
+   ContentsWriter Contents("", Arch);
    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;
 
@@ -344,11 +364,11 @@ bool PackageMap::GenContents(Configuration &Setup,
       if (_error->PendingError() == true)
         return false;
       
-      unsigned long Size = Head.Size();
+      unsigned long long Size = Head.Size();
       unsigned char Buf[4096];
       while (Size != 0)
       {
-        unsigned long ToRead = Size;
+        unsigned long long ToRead = Size;
         if (Size > sizeof(Buf))
            ToRead = sizeof(Buf);
         
@@ -356,7 +376,7 @@ bool PackageMap::GenContents(Configuration &Setup,
            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;
       }            
@@ -366,7 +386,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;
-   for (PackageMap *I = Begin; I != End; I++)
+   for (vector<PackageMap>::iterator I = Begin; I != End; ++I)
    {
       if (I->Contents != this->Contents)
         continue;
@@ -382,11 +402,11 @@ bool PackageMap::GenContents(Configuration &Setup,
    Contents.Finish();
    
    // Finish compressing
-   unsigned long Size;
+   unsigned long long Size;
    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());
    }
    
@@ -427,10 +447,12 @@ void LoadTree(vector<PackageMap> &PkgList,Configuration &Setup)
                            "$(DIST)/$(SECTION)/source/");
    string DPkg = Setup.Find("TreeDefault::Packages",
                            "$(DIST)/$(SECTION)/binary-$(ARCH)/Packages");
+   string DTrans = Setup.Find("TreeDefault::Translation",
+                           "$(DIST)/$(SECTION)/i18n/Translation-en");
    string DIPrfx = Setup.Find("TreeDefault::InternalPrefix",
                            "$(DIST)/$(SECTION)/");
    string DContents = Setup.Find("TreeDefault::Contents",
-                           "$(DIST)/Contents-$(ARCH)");
+                           "$(DIST)/$(SECTION)/Contents-$(ARCH)");
    string DContentsH = Setup.Find("TreeDefault::Contents::Header","");
    string DBCache = Setup.Find("TreeDefault::BinCacheDB",
                               "packages-$(ARCH).db");
@@ -439,6 +461,12 @@ void LoadTree(vector<PackageMap> &PkgList,Configuration &Setup)
    string DFLFile = Setup.Find("TreeDefault::FileList", "");
    string DSFLFile = Setup.Find("TreeDefault::SourceFileList", "");
 
+   mode_t const Permissions = Setup.FindI("Default::FileMode",0644);
+
+   bool const LongDescription = Setup.FindB("Default::LongDescription",
+                                       _config->FindB("APT::FTPArchive::LongDescription", true));
+   string const TranslationCompress = Setup.Find("Default::Translation::Compress",". gzip").c_str();
+
    // Process 'tree' type sections
    const Configuration::Item *Top = Setup.Tree("tree");
    for (Top = (Top == 0?0:Top->Child); Top != 0;)
@@ -447,20 +475,35 @@ void LoadTree(vector<PackageMap> &PkgList,Configuration &Setup)
       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)
       {
-        const char *Archs = Block.Find("Architectures").c_str();
         string Arch;
+        struct SubstVar const Vars[] = {{"$(DIST)",&Dist},
+                                        {"$(SECTION)",&Section},
+                                        {"$(ARCH)",&Arch},
+                                        {}};
+        mode_t const Perms = Block.FindI("FileMode", Permissions);
+        bool const LongDesc = Block.FindB("LongDescription", LongDescription);
+        TranslationWriter *TransWriter;
+        if (DTrans.empty() == false && LongDesc == false)
+        {
+           string const TranslationFile = flCombine(Setup.FindDir("Dir::ArchiveDir"),
+                       SubstVar(Block.Find("Translation", DTrans.c_str()), Vars));
+           string const TransCompress = Block.Find("Translation::Compress", TranslationCompress);
+           TransWriter = new TranslationWriter(TranslationFile, TransCompress, Perms);
+        }
+        else
+           TransWriter = NULL;
+
+        string const Tmp2 = Block.Find("Architectures");
+        const char *Archs = Tmp2.c_str();
         while (ParseQuoteWord(Archs,Arch) == true)
         {
-           struct SubstVar Vars[] = {{"$(DIST)",&Dist},
-                                     {"$(SECTION)",&Section},
-                                     {"$(ARCH)",&Arch},
-                                     {}};
            PackageMap Itm;
-           
+           Itm.Permissions = Perms;
            Itm.BinOverride = SubstVar(Block.Find("BinOverride"),Vars);
            Itm.InternalPrefix = SubstVar(Block.Find("InternalPrefix",DIPrfx.c_str()),Vars);
 
@@ -471,6 +514,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.SrcExtraOverride = SubstVar(Block.Find("SrcExtraOverride"),Vars);
            }
            else
            {
@@ -478,14 +522,25 @@ 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.Arch = Arch;
+              Itm.LongDesc = LongDesc;
+              if (TransWriter != NULL)
+              {
+                 TransWriter->IncreaseRefCounter();
+                 Itm.TransWriter = TransWriter;
+              }
               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);
            PkgList.push_back(Itm);
         }
+        // we didn't use this TransWriter, so we can release it
+        if (TransWriter != NULL && TransWriter->GetRefCounter() == 0)
+           delete TransWriter;
       }
       
       Top = Top->Next;
@@ -497,6 +552,8 @@ void LoadTree(vector<PackageMap> &PkgList,Configuration &Setup)
 /* */
 void LoadBinDir(vector<PackageMap> &PkgList,Configuration &Setup)
 {
+   mode_t const Permissions = Setup.FindI("Default::FileMode",0644);
+
    // Process 'bindirectory' type sections
    const Configuration::Item *Top = Setup.Tree("bindirectory");
    for (Top = (Top == 0?0:Top->Child); Top != 0;)
@@ -508,12 +565,15 @@ void LoadBinDir(vector<PackageMap> &PkgList,Configuration &Setup)
       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.InternalPrefix = Block.Find("InternalPrefix",Top->Tag.c_str());
       Itm.Contents = Block.Find("Contents");
       Itm.ContentsHead = Block.Find("Contents::Header");
+      Itm.Permissions = Block.FindI("FileMode", Permissions);
       
       Itm.GetGeneral(Setup,Block);
       PkgList.push_back(Itm);
@@ -528,16 +588,17 @@ void LoadBinDir(vector<PackageMap> &PkgList,Configuration &Setup)
 /* */
 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,PACKAGE_VERSION,
+           COMMON_ARCH,__DATE__,__TIME__);
    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"
+      "          release path\n"
       "          generate config [groups]\n"
       "          clean config\n"
       "\n"
@@ -555,9 +616,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"
-      "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"
-      "debian archive:\n"
+      "Debian archive:\n"
       "   apt-ftparchive packages dists/potato/main/binary-i386/ > \\\n"
       "               dists/potato/main/binary-i386/Packages\n"
       "\n"
@@ -570,7 +631,7 @@ bool ShowHelp(CommandLine &CmdL)
       "  --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;
 }
@@ -589,7 +650,7 @@ bool SimpleGenPackages(CommandLine &CmdL)
    
    // Create a package writer object.
    PackagesWriter Packages(_config->Find("APT::FTPArchive::DB"),
-                          Override);   
+                          Override, "", _config->Find("APT::FTPArchive::Architecture"));
    if (_error->PendingError() == true)
       return false;
    
@@ -612,7 +673,7 @@ bool SimpleGenContents(CommandLine &CmdL)
       return ShowHelp(CmdL);
    
    // Create a package writer object.
-   ContentsWriter Contents(_config->Find("APT::FTPArchive::DB"));
+   ContentsWriter Contents(_config->Find("APT::FTPArchive::DB"), _config->Find("APT::FTPArchive::Architecture"));
    if (_error->PendingError() == true)
       return false;
    
@@ -645,7 +706,7 @@ bool SimpleGenSources(CommandLine &CmdL)
                             SOverride.c_str());
        
    // Create a package writer object.
-   SourcesWriter Sources(Override,SOverride);
+   SourcesWriter Sources(_config->Find("APT::FTPArchive::DB"),Override,SOverride);
    if (_error->PendingError() == true)
       return false;
    
@@ -658,6 +719,30 @@ bool SimpleGenSources(CommandLine &CmdL)
 
    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                       /*{{{*/
 // ---------------------------------------------------------------------
@@ -687,10 +772,10 @@ bool Generate(CommandLine &CmdL)
    // 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();
-      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();
    }
@@ -699,13 +784,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;
-      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->UserData = I;
+        End->UserData = &(*I);
         End->Str = I->Tag.c_str();
         End++;  
       }
@@ -715,7 +800,7 @@ bool Generate(CommandLine &CmdL)
       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();
       
@@ -747,15 +832,20 @@ bool Generate(CommandLine &CmdL)
       
       delete [] List;
    }
-   
+
+   // close the Translation master files
+   for (vector<PackageMap>::reverse_iterator I = PkgList.rbegin(); I != PkgList.rend(); ++I)
+      if (I->TransWriter != NULL && I->TransWriter->DecreaseRefCounter() == 0)
+        delete I->TransWriter;
+
    if (_config->FindB("APT::FTPArchive::Contents",true) == false)
       return true;
    
-   c1out << "Done Packages, Starting contents." << endl;
+   c1out << "Packages done, Starting contents." << endl;
 
    // 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),
@@ -772,7 +862,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;
-   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 ||
@@ -788,7 +878,7 @@ bool Generate(CommandLine &CmdL)
       {
         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;
         }
         
@@ -840,7 +930,7 @@ bool Clean(CommandLine &CmdL)
 
    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));
@@ -848,7 +938,7 @@ bool Clean(CommandLine &CmdL)
         _error->DumpErrors();
       
       string CacheDB = I->BinCacheDB;
-      for (; I != PkgList.end() && I->BinCacheDB == CacheDB; I++);
+      for (; I != PkgList.end() && I->BinCacheDB == CacheDB; ++I);
    }
    
    return true;
@@ -857,9 +947,12 @@ bool Clean(CommandLine &CmdL)
 
 int main(int argc, const char *argv[])
 {
+   setlocale(LC_ALL, "");
    CommandLine::Args Args[] = {
       {'h',"help","help",0},
       {0,"md5","APT::FTPArchive::MD5",0},
+      {0,"sha1","APT::FTPArchive::SHA1",0},
+      {0,"sha256","APT::FTPArchive::SHA256",0},
       {'v',"version","version",0},
       {'d',"db","APT::FTPArchive::DB",CommandLine::HasArg},
       {'s',"source-override","APT::FTPArchive::SourceOverride",CommandLine::HasArg},
@@ -868,12 +961,14 @@ int main(int argc, const char *argv[])
       {0,"delink","APT::FTPArchive::DeLinkAct",0},
       {0,"readonly","APT::FTPArchive::ReadOnlyDB",0},
       {0,"contents","APT::FTPArchive::Contents",0},
+      {'a',"arch","APT::FTPArchive::Architecture",CommandLine::HasArg},
       {'c',"config-file",0,CommandLine::ConfigFile},
       {'o',"option",0,CommandLine::ArbItem},
       {0,0,0,0}};
    CommandLine::Dispatch Cmds[] = {{"packages",&SimpleGenPackages},
                                    {"contents",&SimpleGenContents},
                                    {"sources",&SimpleGenSources},
+                                   {"release",&SimpleGenRelease},
                                    {"generate",&Generate},
                                    {"clean",&Clean},
                                   {"help",&ShowHelp},
@@ -881,7 +976,7 @@ int main(int argc, const char *argv[])
 
    // Parse the command line and initialize the package library
    CommandLine CmdL(Args,_config);
-   if (CmdL.Parse(argc,argv) == false)
+   if (pkgInitConfig(*_config) == false || CmdL.Parse(argc,argv) == false)
    {
       _error->DumpErrors();
       return 100;
@@ -897,9 +992,9 @@ int main(int argc, const char *argv[])
    }
    
    // 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());