]> git.saurik.com Git - apt.git/commitdiff
bring back deb822 sources.list entries as .sources
authorDavid Kalnischkies <david@kalnischkies.de>
Sun, 21 Jun 2015 21:12:24 +0000 (23:12 +0200)
committerDavid Kalnischkies <david@kalnischkies.de>
Mon, 10 Aug 2015 15:25:26 +0000 (17:25 +0200)
Having two different formats in the same file is very dirty and causes
external tools to fail hard trying to parse them. It is probably not a
good idea for them to parse them in the first place, but they do and we
shouldn't break them if there is a better way.

So we solve this issue for now by giving our deb822 format a new
filename extension ".sources" which unsupporting applications are likely
to ignore an can begin gradually moving forward rather than waiting for
the unknown applications to catch up.

Currently and for the forseeable future apt is going to support both
with the same feature set as documented in the manpage, with the
longtime plan of adopting the 'new' format as default, but that is a
long way to go and might get going more from having an easier time
setting options than from us pushing it explicitely.

18 files changed:
apt-pkg/policy.cc
apt-pkg/sourcelist.cc
apt-pkg/sourcelist.h
apt-pkg/tagfile.cc
apt-pkg/tagfile.h
doc/sources.list.5.xml
test/integration/test-apt-sources-deb822
test/libapt/file-helpers.cc
test/libapt/sourcelist_test.cc
vendor/README
vendor/blankon/apt-vendor.ent
vendor/debian/apt-vendor.ent
vendor/debian/sources.list.in
vendor/raspbian/apt-vendor.ent
vendor/steamos/apt-vendor.ent
vendor/steamos/sources.list.in
vendor/tanglu/apt-vendor.ent
vendor/ubuntu/apt-vendor.ent

index cd48e040cdddb39ad0ee6aeb75245e3baea50f0c..170da7c6383e26e193604d8c3ec81aefbabefeba 100644 (file)
@@ -396,21 +396,6 @@ APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &Fi
    return PFPriority[File->ID];
 }
                                                                        /*}}}*/
-// PreferenceSection class - Overriding the default TrimRecord method  /*{{{*/
-// ---------------------------------------------------------------------
-/* The preference file is a user generated file so the parser should
-   therefore be a bit more friendly by allowing comments and new lines
-   all over the place rather than forcing a special format */
-class PreferenceSection : public pkgTagSection
-{
-   void TrimRecord(bool /*BeforeRecord*/, const char* &End)
-   {
-      for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++)
-        if (Stop[0] == '#')
-           Stop = (const char*) memchr(Stop,'\n',End-Stop);
-   }
-};
-                                                                       /*}}}*/
 // ReadPinDir - Load the pin files from this dir into a Policy         /*{{{*/
 // ---------------------------------------------------------------------
 /* This will load each pin file in the given dir into a Policy. If the
@@ -455,8 +440,8 @@ bool ReadPinFile(pkgPolicy &Plcy,string File)
    pkgTagFile TF(&Fd);
    if (_error->PendingError() == true)
       return false;
-   
-   PreferenceSection Tags;
+
+   pkgUserTagSection Tags;
    while (TF.Step(Tags) == true)
    {
       // can happen when there are only comments in a record
index 6ef99863dd2b3d39d2ca2d61218ba768e335d274..69f7ac0432fabe397fce25eacc195672844dedce 100644 (file)
@@ -82,15 +82,15 @@ bool pkgSourceList::Type::FixupURI(string &URI) const
    return true;
 }
                                                                        /*}}}*/
-bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,
+bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,       /*{{{*/
                                       pkgTagSection &Tags,
-                                      int i,
+                                      unsigned int const i,
                                       FileFd &Fd)
 {
    map<string, string> Options;
 
    string Enabled = Tags.FindS("Enabled");
-   if (Enabled.size() > 0 && StringToBool(Enabled) == false)
+   if (Enabled.empty() == false && StringToBool(Enabled) == false)
       return true;
 
    std::map<char const * const, char const * const> mapping;
@@ -115,46 +115,63 @@ bool pkgSourceList::Type::ParseStanza(vector<metaIndex *> &List,
    // now create one item per suite/section
    string Suite = Tags.FindS("Suites");
    Suite = SubstVar(Suite,"$(ARCH)",_config->Find("APT::Architecture"));
-   string const Section = Tags.FindS("Sections");
-   string URIS = Tags.FindS("URIs");
+   string const Component = Tags.FindS("Components");
+   string const URIS = Tags.FindS("URIs");
+
+   std::vector<std::string> const list_uris = VectorizeString(URIS, ' ');
+   std::vector<std::string> const list_suite = VectorizeString(Suite, ' ');
+   std::vector<std::string> const list_comp = VectorizeString(Component, ' ');
+
+   if (list_uris.empty())
+      // TRANSLATOR: %u is a line number, the first %s is a filename of a file with the extension "second %s" and the third %s is a unique identifier for bugreports
+      return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "URI");
 
-   std::vector<std::string> list_uris = StringSplit(URIS, " ");
-   std::vector<std::string> list_dist = StringSplit(Suite, " ");
-   std::vector<std::string> list_section = StringSplit(Section, " ");
-   
    for (std::vector<std::string>::const_iterator U = list_uris.begin();
         U != list_uris.end(); ++U)
    {
-      std::string URI = (*U);
-      if (!FixupURI(URI))
-      {
-         _error->Error(_("Malformed stanza %u in source list %s (URI parse)"),i,Fd.Name().c_str());
-         return false;
-      }
+      std::string URI = *U;
+      if (U->empty() || FixupURI(URI) == false)
+        return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "URI parse");
+
+      if (list_suite.empty())
+        return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "Suite");
 
-      for (std::vector<std::string>::const_iterator I = list_dist.begin();
-           I != list_dist.end(); ++I)
+      for (std::vector<std::string>::const_iterator S = list_suite.begin();
+           S != list_suite.end(); ++S)
       {
-         for (std::vector<std::string>::const_iterator J = list_section.begin();
-              J != list_section.end(); ++J)
-         {
-            if (CreateItem(List, URI, (*I), (*J), Options) == false)
-            {
-               return false;
-            }
-         }
+        if (S->empty() == false && (*S)[S->size() - 1] == '/')
+        {
+           if (list_comp.empty() == false)
+              return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "absolute Suite Component");
+           if (CreateItem(List, URI, *S, "", Options) == false)
+              return false;
+        }
+        else
+        {
+           if (list_comp.empty())
+              return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "Component");
+
+           for (std::vector<std::string>::const_iterator C = list_comp.begin();
+                 C != list_comp.end(); ++C)
+           {
+              if (CreateItem(List, URI, *S, *C, Options) == false)
+              {
+                 return false;
+              }
+           }
+        }
       }
    }
    return true;
 }
-
+                                                                       /*}}}*/
 // Type::ParseLine - Parse a single line                               /*{{{*/
 // ---------------------------------------------------------------------
 /* This is a generic one that is the 'usual' format for sources.list
    Weird types may override this. */
 bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
                                    const char *Buffer,
-                                   unsigned long const &CurLine,
+                                   unsigned int const CurLine,
                                    string const &File) const
 {
    for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces
@@ -171,10 +188,10 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
         // get one option, e.g. option1=value1
         string option;
         if (ParseQuoteWord(Buffer,option) == false)
-           return _error->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine,File.c_str());
+           return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] unparseable");
 
         if (option.length() < 3)
-           return _error->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine,File.c_str());
+           return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] too short");
 
         // accept options even if the last has no space before the ]-end marker
         if (option.at(option.length()-1) == ']')
@@ -185,16 +202,16 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
 
         size_t const needle = option.find('=');
         if (needle == string::npos)
-           return _error->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine,File.c_str(), option.c_str());
+           return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] not assignment");
 
         string const key = string(option, 0, needle);
         string const value = string(option, needle + 1, option.length());
 
         if (key.empty() == true)
-           return _error->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine,File.c_str(), option.c_str());
+           return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] no key");
 
         if (value.empty() == true)
-           return _error->Error(_("Malformed line %lu in source list %s ([%s] key %s has no value)"),CurLine,File.c_str(),option.c_str(),key.c_str());
+           return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] no value");
 
         Options[key] = value;
       }
@@ -207,33 +224,33 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
    string Section;
 
    if (ParseQuoteWord(Buffer,URI) == false)
-      return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str());
+      return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "URI");
    if (ParseQuoteWord(Buffer,Dist) == false)
-      return _error->Error(_("Malformed line %lu in source list %s (dist)"),CurLine,File.c_str());
-      
+      return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "Suite");
+
    if (FixupURI(URI) == false)
-      return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str());
+      return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "URI parse");
 
    // Check for an absolute dists specification.
    if (Dist.empty() == false && Dist[Dist.size() - 1] == '/')
    {
       if (ParseQuoteWord(Buffer,Section) == true)
-        return _error->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine,File.c_str());
+        return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "absolute Suite Component");
       Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture"));
       return CreateItem(List, URI, Dist, Section, Options);
    }
-   
+
    // Grab the rest of the dists
    if (ParseQuoteWord(Buffer,Section) == false)
-      return _error->Error(_("Malformed line %lu in source list %s (dist parse)"),CurLine,File.c_str());
-   
+      return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "Component");
+
    do
    {
       if (CreateItem(List, URI, Dist, Section, Options) == false)
         return false;
    }
    while (ParseQuoteWord(Buffer,Section) == true);
-   
+
    return true;
 }
                                                                        /*}}}*/
@@ -242,11 +259,6 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
 /* */
 pkgSourceList::pkgSourceList() : d(NULL)
 {
-}
-
-pkgSourceList::pkgSourceList(string File) : d(NULL)
-{
-   Read(File);
 }
                                                                        /*}}}*/
 // SourceList::~pkgSourceList - Destructor                             /*{{{*/
@@ -305,7 +317,7 @@ void pkgSourceList::Reset()
 // SourceList::Read - Parse the sourcelist file                                /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgSourceList::Read(string File)
+bool pkgSourceList::Read(string const &File)
 {
    Reset();
    return ReadAppend(File);
@@ -314,71 +326,63 @@ bool pkgSourceList::Read(string File)
 // SourceList::ReadAppend - Parse a sourcelist file                    /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgSourceList::ReadAppend(string File)
+bool pkgSourceList::ReadAppend(string const &File)
 {
-   if (_config->FindB("APT::Sources::Use-Deb822", false) == true)
-   {
-      int lines_parsed =ParseFileDeb822(File);
-      if (lines_parsed < 0)
-         return false;
-      else if (lines_parsed > 0)
-         return true;
-      // no lines parsed  ... fall through and use old style parser
-   }
-   return ParseFileOldStyle(File);
+   if (flExtension(File) == "sources")
+      return ParseFileDeb822(File);
+   else
+      return ParseFileOldStyle(File);
 }
 
 // SourceList::ReadFileOldStyle - Read Traditional style sources.list  /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgSourceList::ParseFileOldStyle(string File)
+bool pkgSourceList::ParseFileOldStyle(std::string const &File)
 {
    // Open the stream for reading
    ifstream F(File.c_str(),ios::in /*| ios::nocreate*/);
    if (F.fail() == true)
       return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str());
 
-   // CNC:2003-12-10 - 300 is too short.
-   char Buffer[1024];
-
-   int CurLine = 0;
-   while (F.eof() == false)
+   std::string Buffer;
+   for (unsigned int CurLine = 1; std::getline(F, Buffer); ++CurLine)
    {
-      F.getline(Buffer,sizeof(Buffer));
-      CurLine++;
-      _strtabexpand(Buffer,sizeof(Buffer));
-      if (F.fail() && !F.eof())
-        return _error->Error(_("Line %u too long in source list %s."),
-                             CurLine,File.c_str());
-
-      
-      char *I;
-      // CNC:2003-02-20 - Do not break if '#' is inside [].
-      for (I = Buffer; *I != 0 && *I != '#'; I++)
-         if (*I == '[')
-         {
-           char *b_end = strchr(I + 1, ']');
-            if (b_end != NULL)
-               I = b_end;
-         }
-      *I = 0;
-      
-      const char *C = _strstrip(Buffer);
-      
-      // Comment or blank
-      if (C[0] == '#' || C[0] == 0)
+      // remove comments
+      size_t curpos = 0;
+      while ((curpos = Buffer.find('#', curpos)) != std::string::npos)
+      {
+        size_t const openbrackets = std::count(Buffer.begin(), Buffer.begin() + curpos, '[');
+        size_t const closedbrackets = std::count(Buffer.begin(), Buffer.begin() + curpos, ']');
+        if (openbrackets > closedbrackets)
+        {
+           // a # in an option, unlikely, but oh well, it was supported so stick to it
+           ++curpos;
+           continue;
+        }
+        Buffer.erase(curpos);
+        break;
+      }
+      // remove spaces before/after
+      curpos = Buffer.find_first_not_of(" \t\r");
+      if (curpos != 0)
+        Buffer.erase(0, curpos);
+      curpos = Buffer.find_last_not_of(" \t\r");
+      if (curpos != std::string::npos)
+        Buffer.erase(curpos + 1);
+
+      if (Buffer.empty())
         continue;
-           
+
       // Grok it
-      string LineType;
-      if (ParseQuoteWord(C,LineType) == false)
+      std::string const LineType = Buffer.substr(0, Buffer.find(' '));
+      if (LineType.empty() || LineType == Buffer)
         return _error->Error(_("Malformed line %u in source list %s (type)"),CurLine,File.c_str());
 
       Type *Parse = Type::GetType(LineType.c_str());
       if (Parse == 0)
         return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str());
-      
-      if (Parse->ParseLine(SrcList, C, CurLine, File) == false)
+
+      if (Parse->ParseLine(SrcList, Buffer.c_str() + LineType.length(), CurLine, File) == false)
         return false;
    }
    return true;
@@ -387,30 +391,25 @@ bool pkgSourceList::ParseFileOldStyle(string File)
 // SourceList::ParseFileDeb822 - Parse deb822 style sources.list       /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns: the number of stanzas parsed*/
-int pkgSourceList::ParseFileDeb822(string File)
+bool pkgSourceList::ParseFileDeb822(string const &File)
 {
-   pkgTagSection Tags;
-   unsigned int i=0;
+   pkgUserTagSection Tags;
+   unsigned int i = 1;
 
    // see if we can read the file
-   _error->PushToStack();
    FileFd Fd(File, FileFd::ReadOnly);
    pkgTagFile Sources(&Fd);
    if (_error->PendingError() == true)
-   {
-      _error->RevertToStack();
-      return 0;
-   }
-   _error->MergeWithStack();
-   
+      return _error->Error(_("Malformed stanza %u in source list %s (type)"),i,File.c_str());
+
    // read step by step
    while (Sources.Step(Tags) == true)
    {
-      if(!Tags.Exists("Types")) 
-         continue;
+      if(Tags.Exists("Types") == false)
+        return _error->Error(_("Malformed stanza %u in source list %s (type)"),i,File.c_str());
 
       string const types = Tags.FindS("Types");
-      std::vector<std::string> list_types = StringSplit(types, " ");
+      std::vector<std::string> const list_types = VectorizeString(types, ' ');
       for (std::vector<std::string>::const_iterator I = list_types.begin();
         I != list_types.end(); ++I)
       {
@@ -418,18 +417,16 @@ int pkgSourceList::ParseFileDeb822(string File)
          if (Parse == 0)
          {
             _error->Error(_("Type '%s' is not known on stanza %u in source list %s"), (*I).c_str(),i,Fd.Name().c_str());
-            return -1;
+            return false;
          }
-         
+
          if (!Parse->ParseStanza(SrcList, Tags, i, Fd))
-            return -1;
+            return false;
 
-         i++;
+         ++i;
       }
    }
-
-   // we are done, return the number of stanzas read
-   return i;
+   return true;
 }
                                                                        /*}}}*/
 // SourceList::FindIndex - Get the index associated with a file                /*{{{*/
@@ -471,9 +468,12 @@ bool pkgSourceList::GetIndexes(pkgAcquire *Owner, bool GetAll) const
 // Based on ReadConfigDir()                                            /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool pkgSourceList::ReadSourceDir(string Dir)
+bool pkgSourceList::ReadSourceDir(string const &Dir)
 {
-   vector<string> const List = GetListOfFilesInDir(Dir, "list", true);
+   std::vector<std::string> ext;
+   ext.push_back("list");
+   ext.push_back("sources");
+   std::vector<std::string> const List = GetListOfFilesInDir(Dir, ext, true);
 
    // Read the files
    for (vector<string>::const_iterator I = List.begin(); I != List.end(); ++I)
index 4f42b3e91f98056239d70c7c1f2b3223873c9ab3..079f3cb3d7345d6dda91169f8c86cfb0154c0ac5 100644 (file)
@@ -72,11 +72,11 @@ class pkgSourceList
       bool FixupURI(std::string &URI) const;
       virtual bool ParseStanza(std::vector<metaIndex *> &List,
                                pkgTagSection &Tags,
-                               int stanza_n,
+                               unsigned int const stanza_n,
                                FileFd &Fd);
       virtual bool ParseLine(std::vector<metaIndex *> &List,
                             const char *Buffer,
-                            unsigned long const &CurLine,std::string const &File) const;
+                            unsigned int const CurLine,std::string const &File) const;
       virtual bool CreateItem(std::vector<metaIndex *> &List,std::string const &URI,
                              std::string const &Dist,std::string const &Section,
                              std::map<std::string, std::string> const &Options) const = 0;
@@ -90,18 +90,19 @@ class pkgSourceList
 
    std::vector<metaIndex *> SrcList;
 
-   int ParseFileDeb822(std::string File);
-   bool ParseFileOldStyle(std::string File);
+   private:
+   APT_HIDDEN bool ParseFileDeb822(std::string const &File);
+   APT_HIDDEN bool ParseFileOldStyle(std::string const &File);
 
    public:
 
    bool ReadMainList();
-   bool Read(std::string File);
+   bool Read(std::string const &File);
 
    // CNC:2003-03-03
    void Reset();
-   bool ReadAppend(std::string File);
-   bool ReadSourceDir(std::string Dir);
+   bool ReadAppend(std::string const &File);
+   bool ReadSourceDir(std::string const &Dir);
    
    // List accessors
    inline const_iterator begin() const {return SrcList.begin();};
@@ -117,7 +118,6 @@ class pkgSourceList
    time_t GetLastModifiedTime();
 
    pkgSourceList();
-   explicit pkgSourceList(std::string File);
    virtual ~pkgSourceList();
 };
 
index 6d7d8185b590bc6ec9f3f0a73ee18eda98c61f24..cc63b213f9cea975472c9d9ad2c19e22678990f0 100644 (file)
@@ -775,6 +775,14 @@ bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::v
 }
                                                                        /*}}}*/
 
+void pkgUserTagSection::TrimRecord(bool /*BeforeRecord*/, const char* &End)/*{{{*/
+{
+   for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++)
+      if (Stop[0] == '#')
+        Stop = (const char*) memchr(Stop,'\n',End-Stop);
+}
+                                                                       /*}}}*/
+
 #include "tagfile-order.c"
 
 // TFRewrite - Rewrite a control record                                        /*{{{*/
index d0d0c7a840b9eb04415fa35d17b3eb3f8357d0db..81fff89f06782557cc054304d5f6b0f09b7637c6 100644 (file)
@@ -142,6 +142,14 @@ class pkgTagSection
    bool Write(FileFd &File, char const * const * const Order = NULL, std::vector<Tag> const &Rewrite = std::vector<Tag>()) const;
 };
 
+
+/* For user generated file the parser should be a bit more relaxed in exchange
+   for being a bit slower to allow comments and new lines all over the place */
+class pkgUserTagSection : public pkgTagSection
+{
+   virtual void TrimRecord(bool BeforeRecord, const char* &End);
+};
+
 class pkgTagFilePrivate;
 class pkgTagFile
 {
index 6ebba3528d1e6fe7537e384d53a52d2fd8c04416..8506017adf57aebddafa7608f6852fb5ca6c0e8e 100644 (file)
  
  <refsect1><title>Description</title>
    <para>
-   The source list <filename>/etc/apt/sources.list</filename> is designed to support
-   any number of active sources and a variety of source media. The file lists one
-   source per line, with the most preferred source listed first. The information available
-   from the configured sources is acquired by <command>apt-get update</command>
-   (or by an equivalent command from another APT front-end).
-   </para>
-   <para>
-   Each line specifying a source starts with type (e.g. <literal>deb-src</literal>)
-   followed by options and arguments for this type.
-   Individual entries cannot be continued onto a following line. Empty lines
-   are ignored, and a <literal>#</literal> character anywhere on a line marks
-   the remainder of that line as a comment.
+      The source list <filename>/etc/apt/sources.list</filename> and the the
+      files contained in <filename>/etc/apt/sources.list.d/</filename> are
+      designed to support any number of active sources and a variety of source
+      media. The files list one source per line (one line style) or contain multiline
+      stanzas defining one or more sources per stanza (deb822 style), with the
+      most preferred source listed first. The information available from the
+      configured sources is acquired by <command>apt-get update</command> (or
+      by an equivalent command from another APT front-end).
    </para>
  </refsect1>
  
  <refsect1><title>sources.list.d</title>
-   <para>The <filename>/etc/apt/sources.list.d</filename> directory provides
-   a way to add sources.list entries in separate files.
-   The format is the same as for the regular <filename>sources.list</filename> file.
-   File names need to end with
-   <filename>.list</filename> and may only contain letters (a-z and A-Z),
-   digits (0-9), underscore (_), hyphen (-) and period (.) characters.
-   Otherwise APT will print a notice that it has ignored a file, unless that
-   file matches a pattern in the <literal>Dir::Ignore-Files-Silently</literal>
-   configuration list - in which case it will be silently ignored.</para>
+    <para>The <filename>/etc/apt/sources.list.d</filename> directory provides
+       a way to add sources.list entries in separate files.
+       Two different file formats are allowed as described in the next two sections.
+       Filenames need to have either the extension <filename>.list</filename> or
+       <filename>.sources</filename> depending on the contained format.
+       The filenames may only contain letters (a-z and A-Z),
+       digits (0-9), underscore (_), hyphen (-) and period (.) characters.
+       Otherwise APT will print a notice that it has ignored a file, unless that
+       file matches a pattern in the <literal>Dir::Ignore-Files-Silently</literal>
+       configuration list - in which case it will be silently ignored.</para>
  </refsect1>
 
- <refsect1><title>The deb and deb-src types</title>
+ <refsect1><title>one line style format</title>
+    <para>
+       Files in this format have the extension <filename>.list</filename>.
+       Each line specifying a source starts with a type (e.g. <literal>deb-src</literal>)
+       followed by options and arguments for this type.
+
+       Individual entries cannot be continued onto a following line. Empty lines
+       are ignored, and a <literal>#</literal> character anywhere on a line marks
+       the remainder of that line as a comment. Consequently an entry can be
+       disabled by commenting out the entire line.
+
+       If options should be provided they are separated by spaces and all of
+       them together are enclosed by square brackets (<literal>[]</literal>)
+       included in the line after the type separated from it with a space.
+       If an option allows multiple values these are separated from each other
+       with a comma (<literal>,</literal>). An option name is separated from its
+       value(s) by a equal sign (<literal>=</literal>). Multivalue options have
+       also <literal>-=</literal> and <literal>+=</literal> as separator which
+       instead of replacing the default with the given value(s) modify the default
+       value(s) to remove or include the given values.
+   </para><para>
+       This is the traditional format and supported by all apt versions.
+       Note that not all options as described below are supported by all apt versions.
+       Note also that some older applications parsing this format on its own might not
+       expect to encounter options as they were uncommon before the introduction of
+       multi-architecture support.
+    </para>
+ </refsect1>
+
+ <refsect1><title>deb822 style format</title>
+    <para>
+       Files in this format have the extension <filename>.sources</filename>.
+       The format is similar in syntax to other files used by Debian and its
+       derivatives, like the metadata itself apt will download from the configured
+       sources or the <filename>debian/control</filename> file in a Debian source package.
+
+       Individual entries are separated by an empty line, additional empty
+       lines are ignored, and a <literal>#</literal> character at the start of
+       the line marks the entire line as a comment. An entry can hence be
+       disabled by commenting out each line belonging to the stanza, but it is
+       usually easier to add the field "Enabled: no" to the stanza to disable
+       the entry. Removing the field or setting it to yes reenables it.
+
+       Options have the same syntax as every other field: A fieldname separated by
+       a colon (<literal>:</literal>) and optionally spaces from its value(s).
+       Note especially that multiple values are separated by spaces, not by
+       commas as in the one line format. Multivalue fields like <literal>Architectures</literal>
+       also have <literal>Architectures-Add</literal> and <literal>Architectures-Remove</literal>
+       to modify the default value rather than replacing it.
+   </para><para>
+       This is a new format supported by apt itself since version 1.1. Previous
+       versions ignore such files with a notice message as described earlier.
+       It is intended to make this format gradually the default format and
+       deprecating the previously described one line style format as it is
+       easier to create, extend and modify by humans and machines alike
+       especially if a lot of sources and/or options are involved.
+
+       Developers who are working with and/or parsing apt sources are highly
+       encouraged to add support for this format and to contact the APT team
+       to coordinate and share this work. Users can freely adopt this format
+       already, but could encounter problems with software not supporting
+       the format yet.
+    </para>
+ </refsect1>
+
+ <refsect1><title>The deb and deb-src types: General Format</title>
    <para>The <literal>deb</literal> type references a typical two-level Debian
    archive, <filename>distribution/component</filename>. The
-   <literal>distribution</literal> is generally an archive name like
+   <literal>distribution</literal> is generally a suite name like
    <literal>stable</literal> or <literal>testing</literal> or a codename like
    <literal>&stable-codename;</literal> or <literal>&testing-codename;</literal>
    while component is one of <literal>main</literal>, <literal>contrib</literal> or
    code in the same form as the <literal>deb</literal> type.
    A <literal>deb-src</literal> line is required to fetch source indexes.</para>
 
-   <para>The format for a <filename>sources.list</filename> entry using the
+   <para>The format for two one line style entries using the
    <literal>deb</literal> and <literal>deb-src</literal> types is:</para>
 
-   <literallayout>deb [ options ] uri suite [component1] [component2] [...]</literallayout>
+   <literallayout>deb [ option1=value1 option2=value2 ] uri suite [component1] [component2] [...]
+deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [...]</literallayout>
 
-   <para>Alternatively a rfc822 style format is also supported:
+   <para>Alternatively the equivalent entry in deb822 style looks like this:
    <literallayout>
      Types: deb deb-src
-     URIs: http://example.com
-     Suites: stable testing
-     Sections: component1 component2
-     Description: short
-      long long long
-     [option1]: [option1-value]
-
-     Types: deb
-     URIs: http://another.example.com
-     Suites: experimental
-     Sections: component1 component2
-     Enabled: no
-     Description: short
-      long long long
-     [option1]: [option1-value]
+     URIs: uri
+     Suites: suite
+     Components: [component1] [component2] [...]
+     option1: value1
+     option2: value2
    </literallayout>
    </para>
 
    <para>The URI for the <literal>deb</literal> type must specify the base of the
-   Debian distribution, from which APT will find the information it needs. 
-   <literal>suite</literal> can specify an exact path, in which case the 
+   Debian distribution, from which APT will find the information it needs.
+   <literal>suite</literal> can specify an exact path, in which case the
    components must be omitted and <literal>suite</literal> must end with
    a slash (<literal>/</literal>). This is useful for the case when only a
-   particular sub-section of the archive denoted by the URI is of interest.
+   particular sub-directory of the archive denoted by the URI is of interest.
    If <literal>suite</literal> does not specify an exact path, at least
    one <literal>component</literal> must be present.</para>
 
-   <para><literal>suite</literal> may also contain a variable, 
+   <para><literal>suite</literal> may also contain a variable,
    <literal>$(ARCH)</literal>
    which expands to the Debian architecture (such as <literal>amd64</literal> or
    <literal>armel</literal>) used on the system. This permits architecture-independent
    of interest when specifying an exact path, <literal>APT</literal> will
    automatically generate a URI with the current architecture otherwise.</para>
 
-   <para>In the traditional style sources.list format since only one
-   distribution can be specified per line it may be necessary to have
-   multiple lines for the same URI, if a subset of all available
-   distributions or components at that location is desired.  APT will
-   sort the URI list after it has generated a complete set internally,
-   and will collapse multiple references to the same Internet host,
-   for instance, into a single connection, so that it does not
-   inefficiently establish an FTP connection, close it, do something
-   else, and then re-establish a connection to that same host. This
-   feature is useful for accessing busy FTP sites with limits on the
-   number of simultaneous anonymous users. APT also parallelizes
-   connections to different hosts to more effectively deal with sites
-   with low bandwidth.</para>
-
-   <para><literal>options</literal> is always optional and needs to be surrounded by
-   square brackets. It can consist of multiple settings in the form
-   <literal><replaceable>setting</replaceable>=<replaceable>value</replaceable></literal>.
-   Multiple settings are separated by spaces. The following settings are supported by APT
-   (note however that unsupported settings will be ignored silently):
-   <itemizedlist>
-   <listitem><para><literal>arch=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
-   can be used to specify for which architectures information should
-   be downloaded. If this option is not set all architectures defined by the
-   <literal>APT::Architectures</literal> option will be downloaded.</para></listitem>
-
-   <listitem><para><literal>arch+=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
-   and <literal>arch-=<replaceable>arch1</replaceable>,<replaceable>arch2</replaceable>,…</literal>
-   which can be used to add/remove architectures from the set which will be downloaded.</para></listitem>
-
-   <listitem><para><literal>lang=<replaceable>lang1</replaceable>,<replaceable>lang2</replaceable>,…</literal>,
-   <literal>lang+=<replaceable>lang1</replaceable>,<replaceable>lang2</replaceable>,…</literal> and
-   <literal>lang-=<replaceable>lang1</replaceable>,<replaceable>lang2</replaceable>,…</literal> functioning in
-   the same way as the <literal>arch</literal>-options described before. They can be used to specify for
-   which languages apt will acquire metadata, like translated package descriptions, for. If not specified, the
-   default set is defined by the <literal>Acquire::Languages</literal> config option.</para></listitem>
-
-   <listitem><para><literal>target=<replaceable>target1</replaceable>,<replaceable>target2</replaceable>,…</literal>,
-   <literal>target+=<replaceable>target1</replaceable>,<replaceable>target2</replaceable>,…</literal> and
-   <literal>target-=<replaceable>target1</replaceable>,<replaceable>target2</replaceable>,…</literal> again functioning in
-   the same way as the <literal>arch</literal>-options described before. They can be used to specify which
-   targets apt will try to acquire from this source. If not specified, the default set is defined by
-   the <literal>APT::Acquire::Targets</literal> configuration scope.</para></listitem>
-
-   <listitem><para><literal>trusted=yes</literal> can be set to indicate that packages
-   from this source are always authenticated even if the <filename>Release</filename> file
-   is not signed or the signature can't be checked. This disables parts of &apt-secure;
-   and should therefore only be used in a local and trusted context. <literal>trusted=no</literal>
-   is the opposite which handles even correctly authenticated sources as not authenticated.</para></listitem>
-   </itemizedlist></para>
+   <para>Especially in the one line style format since only one distribution
+      can be specified per line it may be necessary to have multiple lines for
+      the same URI, if a subset of all available distributions or components at
+      that location is desired.  APT will sort the URI list after it has
+      generated a complete set internally, and will collapse multiple
+      references to the same Internet host, for instance, into a single
+      connection, so that it does not inefficiently establish a
+      connection, close it, do something else, and then re-establish a
+      connection to that same host. APT also parallelizes connections to
+      different hosts to more effectively deal with sites with low
+      bandwidth.</para>
 
    <para>It is important to list sources in order of preference, with the most
    preferred source listed first. Typically this will result in sorting
    by speed from fastest to slowest (CD-ROM followed by hosts on a local
    network, followed by distant Internet hosts, for example).</para>
 
-   <para>Some examples:</para>
-   <literallayout>
-deb http://ftp.debian.org/debian &stable-codename; main contrib non-free
-deb http://security.debian.org/ &stable-codename;/updates main contrib non-free
-   </literallayout>
+   <para>As an example, the sources for your distribution could look like this
+      in one line style format:
+      <literallayout>&sourceslist-list-format;</literallayout> or like this in
+      deb822 style format:
+      <literallayout>&sourceslist-sources-format;</literallayout></para>
+ </refsect1>
 
+ <refsect1><title>The deb and deb-src types: Options</title>
+    <para>Each source entry can have options specified modifying which and how
+       the source is accessed and data acquired from it. Format, syntax and names
+       of the options varies between the two formats one line and deb822 style
+       as described, but they have both the same options available. For simplicity
+       we list the deb822 fieldname and provide the one line name in brackets.
+       Remember that beside setting multivalue options explicitly, there is also
+       the option to modify them based on the default, but we aren't listing those
+       names explicitly here. Unsupported options are silently ignored by all
+       APT versions.
+
+       <itemizedlist>
+         <listitem><para><literal>Architectures</literal>
+               (<literal>arch</literal>) is a multivalue option defining for
+               which architectures information should be downloaded. If this
+               option isn't set the default is all architectures as defined by
+               the <literal>APT::Architectures</literal> config option.
+         </para></listitem>
+
+         <listitem><para><literal>Languages</literal>
+               (<literal>lang</literal>) is a multivalue option defining for
+               which languages information like translated package
+               descriptions should be downloaded.  If this option isn't set
+               the default is all languages as defined by the
+               <literal>Acquire::Languages</literal> config option.
+         </para></listitem>
+
+         <listitem><para><literal>Targets</literal>
+               (<literal>target</literal>) is a multivalue option defining
+               which download targets apt will try to acquire from this
+               source. If not specified, the default set is defined by the
+               <literal>APT::Acquire::Targets</literal> configuration scope.
+         </para></listitem>
+
+         <listitem><para><literal>Trusted</literal> (<literal>trusted</literal>)
+               is a tri-state value which defaults to APT deciding if a source
+               is considered trusted or if warnings should be raised before e.g.
+               packages are installed from this source. This option can be used
+               to override this decision either with the value <literal>yes</literal>,
+               which lets APT consider this source always as a trusted source
+               even if it has no or fails authentication checks by disabling parts
+               of &apt-secure; and should therefore only be used in a local and trusted
+               context (if at all) as otherwise security is breached. The opposite
+               can be achieved with the value no, which causes the source to be handled
+               as untrusted even if the authentication checks passed successfully.
+               The default value can't be set explicitly.
+         </para></listitem>
+       </itemizedlist>
+
+    </para>
  </refsect1>
 
  <refsect1><title>URI specification</title>
@@ -247,34 +313,70 @@ deb http://security.debian.org/ &stable-codename;/updates main contrib non-free
  </refsect1>
  
  <refsect1><title>Examples</title>
-   <para>Uses the archive stored locally (or NFS mounted) at /home/jason/debian
+   <para>Uses the archive stored locally (or NFS mounted) at /home/apt/debian
    for stable/main, stable/contrib, and stable/non-free.</para>
-   <literallayout>deb file:/home/jason/debian stable main contrib non-free</literallayout>
+   <literallayout>deb file:/home/apt/debian stable main contrib non-free</literallayout>
+   <literallayout>Types: deb
+URIs: file:/home/apt/debian
+Suites: stable
+Components: main contrib non-free</literallayout>
 
    <para>As above, except this uses the unstable (development) distribution.</para>
-   <literallayout>deb file:/home/jason/debian unstable main contrib non-free</literallayout>
+   <literallayout>deb file:/home/apt/debian unstable main contrib non-free</literallayout>
+   <literallayout>Types: deb
+URIs: file:/home/apt/debian
+Suites: unstable
+Components: main contrib non-free</literallayout>
 
    <para>Source line for the above</para>
-   <literallayout>deb-src file:/home/jason/debian unstable main contrib non-free</literallayout>
+   <literallayout>deb-src file:/home/apt/debian unstable main contrib non-free</literallayout>
+   <literallayout>Types: deb-src
+URIs: file:/home/apt/debian
+Suites: unstable
+Components: main contrib non-free</literallayout>
+
 
    <para>The first line gets package information for the architectures in <literal>APT::Architectures</literal>
    while the second always retrieves <literal>amd64</literal> and <literal>armel</literal>.</para>
-   <literallayout>deb http://ftp.debian.org/debian &stable-codename; main
-deb [ arch=amd64,armel ] http://ftp.debian.org/debian &stable-codename; main</literallayout>
+   <literallayout>deb http://httpredir.debian.org/debian &stable-codename; main
+deb [ arch=amd64,armel ] http://httpredir.debian.org/debian &stable-codename; main</literallayout>
+   <literallayout>Types: deb
+URIs: http://httpredir.debian.org/debian
+Suites: &stable-codename;
+Components: main
+
+Types: deb
+URIs: http://httpredir.debian.org/debian
+Suites: &stable-codename;
+Components: main
+Architectures: amd64 armel
+</literallayout>
 
    <para>Uses HTTP to access the archive at archive.debian.org, and uses only
    the hamm/main area.</para>
    <literallayout>deb http://archive.debian.org/debian-archive hamm main</literallayout>
+   <literallayout>Types: deb
+URIs: http://archive.debian.org/debian-archive
+Suites: hamm
+Components: main</literallayout>
 
    <para>Uses FTP to access the archive at ftp.debian.org, under the debian
    directory, and uses only the &stable-codename;/contrib area.</para>
    <literallayout>deb ftp://ftp.debian.org/debian &stable-codename; contrib</literallayout>
+   <literallayout>Types: deb
+URIs: ftp://ftp.debian.org/debian
+Suites: &stable-codename;
+Components: contrib</literallayout>
 
    <para>Uses FTP to access the archive at ftp.debian.org, under the debian
    directory, and uses only the unstable/contrib area. If this line appears as
    well as the one in the previous example in <filename>sources.list</filename>
    a single FTP session will be used for both resource lines.</para>
    <literallayout>deb ftp://ftp.debian.org/debian unstable contrib</literallayout>
+   <literallayout>Types: deb
+URIs: ftp://ftp.debian.org/debian
+Suites: unstable
+Components: contrib</literallayout>
 
    <para>Uses HTTP to access the archive at ftp.tlh.debian.org, under the
    universe directory, and uses only files found under
@@ -284,15 +386,32 @@ deb [ arch=amd64,armel ] http://ftp.debian.org/debian &stable-codename; main</li
    illustrates how to use the substitution variable; official debian
    archives are not structured like this]
    <literallayout>deb http://ftp.tlh.debian.org/universe unstable/binary-$(ARCH)/</literallayout>
+   <literallayout>Types: deb
+URIs: http://ftp.tlh.debian.org/universe
+Suites: unstable/binary-$(ARCH)/</literallayout>
    </para>
+
+   <para>Uses HTTP to get binary packages as well as sources from the stable, testing and unstable
+      suites and the components main and contrib.</para>
+   <literallayout>deb http://httpredir.debian.org/debian stable main contrib
+deb-src http://httpredir.debian.org/debian stable main contrib
+deb http://httpredir.debian.org/debian testing main contrib
+deb-src http://httpredir.debian.org/debian testing main contrib
+deb http://httpredir.debian.org/debian unstable main contrib
+deb-src http://httpredir.debian.org/debian unstable main contrib</literallayout>
+   <literallayout>Types: deb deb-src
+URIs: http://httpredir.debian.org/debian
+Suites: stable testing unstable
+Components: main contrib
+</literallayout>
+
  </refsect1>
+
  <refsect1><title>See Also</title>
-   <para>&apt-cache; &apt-conf;
+   <para>&apt-get;, &apt-conf;
    </para>
  </refsect1>
 
  &manbugs;
-</refentry>
 
+</refentry>
index 51fe7bcfee68b0729b954c9c2b26b72abb66098d..adfe0e0037e1ffc5e87b4d1f12d8f8218a8a49db 100755 (executable)
@@ -7,9 +7,8 @@ TESTDIR=$(readlink -f $(dirname $0))
 setupenvironment
 configarchitecture 'i386'
 
-echo 'APT::Sources::Use-Deb822 "true";' > rootdir/etc/apt/apt.conf.d/00enabledeb822
-
-SOURCES='rootdir/etc/apt/sources.list'
+LISTS='rootdir/etc/apt/sources.list.d/test.list'
+SOURCES='rootdir/etc/apt/sources.list.d/test.sources'
 BASE='# some comment
 # that contains a : as well
 #Types: meep
@@ -17,23 +16,48 @@ BASE='# some comment
 Types: deb
 URIs: http://ftp.debian.org/debian
 Suites: stable
-Sections: main
+Components: main
 Description: summay
  and the long part'
 
-msgtest 'Test sources.list' 'old style'
-echo "deb http://ftp.debian.org/debian stable main" > $SOURCES
+msgcleantest() {
+        rm -f $LISTS $SOURCES
+        msgtest "$@"
+}
+
+msgcleantest 'Test sources.list' 'old style'
+echo "deb http://ftp.debian.org/debian stable main" > $LISTS
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
+'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
+
+msgcleantest 'Test sources.list' 'old style with options'
+echo "deb [trusted=yes arch+=armel,powerpc] http://ftp.debian.org/debian stable main" > $LISTS
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
+'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/binary-powerpc/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-powerpc_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
+
+msgcleantest 'Test sources.list' 'old style with comments'
+echo "deb http://ftp.debian.org/debian stable main # non-free" > $LISTS
+testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
+'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
+'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
+
+msgcleantest 'Test sources.list' 'old style with option comments'
+echo "deb [trusted=yes#yeahreally] http://ftp.debian.org/debian stable main # non-free" > $LISTS
 testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
 
-msgtest 'Test sources.list' 'simple deb822'
+msgcleantest 'Test sources.list' 'simple deb822'
 echo "$BASE"  > $SOURCES
 testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
 
-msgtest 'Test deb822 with' 'two entries'
+msgcleantest 'Test deb822 with' 'two entries'
 # Two entries
 echo "$BASE" > $SOURCES
 echo "" >> $SOURCES
@@ -46,7 +70,7 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb
 'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris
 
 # two suite entries
-msgtest 'Test deb822 with' 'two Suite entries'
+msgcleantest 'Test deb822 with' 'two Suite entries'
 echo "$BASE"  | sed -e "s/stable/stable unstable/" > $SOURCES
 testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
@@ -55,7 +79,7 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb
 'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 
 'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris
 
-msgtest 'Test deb822' 'architecture option'
+msgcleantest 'Test deb822' 'architecture option'
 echo "$BASE" > $SOURCES
 echo "Architectures: amd64 armel" >> $SOURCES
 testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
@@ -63,17 +87,30 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb
 'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 
 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
 
-
-msgtest 'Test old-style sources.list file which has' 'malformed dist'
-echo "deb http://ftp.debian.org" > $SOURCES
-testequal --nomsg "E: Malformed line 1 in source list $TMPWORKINGDIRECTORY/rootdir/etc/apt/sources.list (dist)
+msgcleantest 'Test old-style' 'suite arch variable'
+echo 'deb http://ftp.tlh.debian.org/universe unstable/binary-$(ARCH)/' > $LISTS
+testequal --nomsg "'http://ftp.tlh.debian.org/universe/unstable/binary-i386/InRelease' ftp.tlh.debian.org_universe_unstable_binary-i386_InRelease 0 
+'http://ftp.tlh.debian.org/universe/unstable/binary-i386/Packages.bz2' ftp.tlh.debian.org_universe_unstable_binary-i386_Packages 0 
+'http://ftp.tlh.debian.org/universe/unstable/binary-i386/en.bz2' ftp.tlh.debian.org_universe_unstable_binary-i386_en 0 " aptget update --print-uris
+
+msgcleantest 'Test deb822' 'suite arch variable'
+echo 'Types: deb
+URIs: http://ftp.tlh.debian.org/universe
+Suites: stable/binary-$(ARCH)/' > $SOURCES
+testequal --nomsg "'http://ftp.tlh.debian.org/universe/stable/binary-i386/InRelease' ftp.tlh.debian.org_universe_stable_binary-i386_InRelease 0 
+'http://ftp.tlh.debian.org/universe/stable/binary-i386/Packages.bz2' ftp.tlh.debian.org_universe_stable_binary-i386_Packages 0 
+'http://ftp.tlh.debian.org/universe/stable/binary-i386/en.bz2' ftp.tlh.debian.org_universe_stable_binary-i386_en 0 " aptget update --print-uris
+
+msgcleantest 'Test old-style sources.list file which has' 'malformed dist'
+echo "deb http://ftp.debian.org" > $LISTS
+testequal --nomsg "E: Malformed entry 1 in list file $TMPWORKINGDIRECTORY/$LISTS (Suite)
 E: The list of sources could not be read."  aptget update --print-uris
 
-msgtest 'Test deb822 sources.list file which has' 'malformed URI'
+msgcleantest 'Test deb822 sources.list file which has' 'malformed URI'
 echo "Types: deb
 Suites: stable
 " > $SOURCES
-testequal --nomsg  "E: Malformed stanza 0 in source list $TMPWORKINGDIRECTORY/rootdir/etc/apt/sources.list (URI parse)
+testequal --nomsg  "E: Malformed entry 1 in sources file $TMPWORKINGDIRECTORY/$SOURCES (URI)
 E: The list of sources could not be read."  aptget update --print-uris
 
 # with Enabled: false
@@ -82,7 +119,7 @@ echo "Enabled: no" >> $SOURCES
 testempty aptget update --print-uris
 
 # multiple URIs
-msgtest 'Test deb822 sources.list file which has' 'Multiple URIs work'
+msgcleantest 'Test deb822 sources.list file which has' 'Multiple URIs work'
 echo "$BASE"  | sed -e 's#http://ftp.debian.org/debian#http://ftp.debian.org/debian http://ftp.de.debian.org/debian#' > $SOURCES
 testequal --nomsg  "'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp.de.debian.org_debian_dists_stable_InRelease 0 
 'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0 
@@ -92,7 +129,7 @@ testequal --nomsg  "'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp
 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
 
 # multiple Type in one field
-msgtest 'Test deb822 sources.list file which has' 'Multiple Types work'
+msgcleantest 'Test deb822 sources.list file which has' 'Multiple Types work'
 echo "$BASE"  | sed -e 's#Types: deb#Types: deb deb-src#' > $SOURCES
 testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 
 'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0 
@@ -100,7 +137,7 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb
 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris
 
 # a Suite
-msgtest 'Test deb822 sources.list file which has' 'a exact path and no sections'
+msgcleantest 'Test deb822 sources.list file which has' 'an exact path and no sections'
 cat > $SOURCES <<EOF
 Types: deb
 URIs: http://emacs.naquadah.org
index 3871928685cd33d5563593707d52b938de631ce4..6811c4158661f6f4f5d711193ff0e95868ca7137 100644 (file)
@@ -56,10 +56,17 @@ void helperCreateLink(std::string const &dir, std::string const &targetname, std
 void helperCreateTemporaryFile(std::string const &id, FileFd &fd, std::string * const filename, char const * const content)
 {
    std::string name("apt-test-");
-   name.append(id).append(".XXXXXXXX");
+   name.append(id);
+   size_t const giventmp = name.find(".XXXXXX.");
+   if (giventmp == std::string::npos)
+      name.append(".XXXXXX");
    char * tempfile = strdup(name.c_str());
    ASSERT_STRNE(NULL, tempfile);
-   int tempfile_fd = mkstemp(tempfile);
+   int tempfile_fd;
+   if (giventmp == std::string::npos)
+      tempfile_fd = mkstemp(tempfile);
+   else
+      tempfile_fd = mkstemps(tempfile, name.length() - (giventmp + 7));
    ASSERT_NE(-1, tempfile_fd);
    if (filename != NULL)
       *filename = tempfile;
index 9e6f822133f0b1d61c6690e74ee94650db762d69..83c441092f6622e43db9b31199c6a58ae7ce1f13 100644 (file)
 
 #include "file-helpers.h"
 
-class SourceList : public pkgSourceList {
-   public:
-      using pkgSourceList::ParseFileDeb822;
-};
-
 TEST(SourceListTest,ParseFileDeb822)
 {
    FileFd fd;
    std::string tempfile;
-   createTemporaryFile("parsefiledeb822", fd, &tempfile,
+   createTemporaryFile("parsefiledeb822.XXXXXX.sources", fd, &tempfile,
       "Types: deb\n"
       "URIs: http://ftp.debian.org/debian\n"
       "Suites: stable\n"
-      "Sections: main\n"
+      "Components: main\n"
       "Description: short\n"
       " long description that can be very long\n"
       "\n"
       "Types: deb\n"
       "URIs: http://ftp.debian.org/debian\n"
       "Suites: unstable\n"
-      "Sections: main non-free\n");
+      "Components: main non-free\n");
    fd.Close();
 
-   SourceList sources;
-   EXPECT_EQ(2, sources.ParseFileDeb822(tempfile));
+   pkgSourceList sources;
+   EXPECT_EQ(true, sources.Read(tempfile));
    EXPECT_EQ(2, sources.size());
 
    if (tempfile.empty() == false)
index c2fabbd4c5387e38e99063788880c679758098ad..6846c8455455d887666a6e6880117e30e1d21e59 100644 (file)
@@ -44,6 +44,10 @@ apt-key script and the keyring-package in particular as a dependency for apt.
 
 The field current-codename is optional and can be used in sources.list.in.
 
+The fields sourceslist-list-format and sourceslist-sources-format are used as
+examples in the sources.list manpage and the first one is additionally
+available in the sources.list.in template.
+They should in general reflect the default sources of your distro.
 
 == sources.list.in
 
@@ -55,6 +59,7 @@ You can use some placeholders in this file, namely:
 * &debian-oldstable-codename;
 * &debian-testing-codename;
 * &ubuntu-codename;
+* &sourceslist-list-format;
 with the value you would expect based on the name.
 
 The placeholder &current-codename; is yours and can be set in apt-vendor.ent
@@ -63,4 +68,5 @@ The placeholder &current-codename; is yours and can be set in apt-vendor.ent
 == apt.conf-*
 
 Files in your vendor directory following this naming scheme will be picked up
-by the debian/rules file and installed in /etc/apt/apt.conf.d/ directory.
+by the debian/rules file and installed in /etc/apt/apt.conf.d/ directory, with
+"apt.conf-" removed from the beginning of the filename.
index 2600eb715c9057daf61f0ecf822cb7b44f70dc45..ea7625f907db4276b1f0a28fdedc4afe23c0743f 100644 (file)
@@ -6,3 +6,12 @@
 <!ENTITY keyring-master-filename "/usr/share/keyrings/blankon-master-keyring.gpg">
 <!ENTITY keyring-uri "http://arsip.blankonlinux.or.id/blankon/project/blankon-archive-keyring.gpg">
 <!ENTITY current-codename "tambora">
+
+<!ENTITY sourceslist-list-format "deb http://arsip.blankonlinux.or.id/blankon &current-codename; main restricted
+deb http://arsip.blankonlinux.or.id/blankon &current-codename;-security main restricted
+deb http://arsip.blankonlinux.or.id/blankon &current-codename;-updates main restricted">
+
+<!ENTITY sourceslist-sources-format "Types: deb
+URIs: http://arsip.blankonlinux.or.id/blankon
+Suites: &current-codename; &current-codename;-security &current-codename;-updates
+Components: main restricted">
index 6cda5995c9cc6c7c3ac679b15d79297f8b06de6f..8b26da3853634ad2bb8388d888e7288eec3909ed 100644 (file)
@@ -5,3 +5,15 @@
 <!ENTITY keyring-removed-filename "<filename>/usr/share/keyrings/debian-archive-removed-keys.gpg</filename>">
 <!ENTITY keyring-master-filename "">
 <!ENTITY keyring-uri "">
+
+<!ENTITY sourceslist-list-format "deb http://httpredir.debian.org/debian &stable-codename; main contrib non-free
+deb http://security.debian.org &stable-codename;/updates main contrib non-free">
+<!ENTITY sourceslist-sources-format "Types: deb
+URIs: http://httpredir.debian.org/debian
+Suites: &stable-codename;
+Components: main contrib non-free
+
+Types: deb
+URIs: http://security.debian.org
+Suites: &stable-codename;/updates
+Components: main contrib non-free">
index 2e430296a83697771481889f370c4f84c676caa3..c36fb16a73a5202cf280eba8ca79c2eb7ff22d09 100644 (file)
@@ -1,7 +1,6 @@
 # See sources.list(5) manpage for more information
 # Remember that CD-ROMs, DVDs and such are managed through the apt-cdrom tool.
-deb http://ftp.us.debian.org/debian &debian-stable-codename; main contrib non-free
-deb http://security.debian.org &debian-stable-codename;/updates main contrib non-free
+&sourceslist-list-format;
 
 # Uncomment if you want the apt-get source function to work
 #deb-src http://ftp.us.debian.org/debian &debian-stable-codename; main contrib non-free
index e359d20019e556d33f4f34cd5733c7d93088f5bb..dc69f3c03a27787f18d565f5d77e872a55409b09 100644 (file)
@@ -5,3 +5,9 @@
 <!ENTITY keyring-removed-filename "<filename>/usr/share/keyrings/raspbian-archive-removed-keys.gpg</filename>">
 <!ENTITY keyring-master-filename "">
 <!ENTITY keyring-uri "">
+
+<!ENTITY sourceslist-list-format "deb http://mirrordirector.raspbian.org/raspbian &stable-codename; main contrib non-free">
+<!ENTITY sourceslist-sources-format "Types: deb
+URIs: http://mirrordirector.raspbian.org/raspbian
+Suites: &stable-codename;
+Components: main contrib non-free">
index dc1b798e6d3ed7261918f2e1d4da447758e6a2be..7cf100fc4ce10b82f13429827fe2b662ac80ca3c 100644 (file)
@@ -6,3 +6,10 @@
 <!ENTITY keyring-master-filename "">
 <!ENTITY keyring-uri "">
 <!ENTITY current-codename "alchemist">
+
+<!ENTITY sourceslist-list-format "deb http://repo.steampowered.com/steamos &current-codename; main contrib non-free
+deb-src http://repo.steampowered.com/steamos &current-codename; main contrib non-free">
+<!ENTITY sourceslist-sources-format "Types: deb deb-src
+URIs: http://repo.steampowered.com/steamos
+Suites: &current-codename;
+Components: main contrib non-free">
index 69174d0905478cd2a13825a05115d82cbca89b95..246d2e336e49ea7db281b3e5b4e79808ff7a6b52 100644 (file)
@@ -1,5 +1,3 @@
 # See sources.list(5) manpage for more information
 # Remember that CD-ROMs, DVDs and such are managed through the apt-cdrom tool.
-
-deb http://repo.steampowered.com/steamos &current-codename; main contrib non-free
-deb-src http://repo.steampowered.com/steamos &current-codename; main contrib non-free
+&sourceslist-list-format;
index d2442209c4f428f1f6d2ec3bdfdf716a8dcda1bf..f5cd813bfaa6496b908b3e1b093df34b2f646a9b 100644 (file)
@@ -6,3 +6,9 @@
 <!ENTITY keyring-master-filename "">
 <!ENTITY keyring-uri "">
 <!ENTITY current-codename "bartholomea">
+
+<!ENTITY sourceslist-list-format "deb http://archive.tanglu.org/tanglu &current-codename; main contrib non-free">
+<!ENTITY sourceslist-sources-format "Types: deb
+URIs: http://archive.tanglu.org/tanglu
+Suites: &current-codename;
+Components: main contrib non-free">
index caa5326995f1901cc4ac3f7c0031506a0252adcd..dcebc920967ea7de01731d21caf79025225f0934 100644 (file)
@@ -5,3 +5,16 @@
 <!ENTITY keyring-removed-filename "<filename>/usr/share/keyrings/ubuntu-archive-removed-keys.gpg</filename>">
 <!ENTITY keyring-master-filename "/usr/share/keyrings/ubuntu-master-keyring.gpg">
 <!ENTITY keyring-uri "http://archive.ubuntu.com/ubuntu/project/ubuntu-archive-keyring.gpg">
+
+<!ENTITY sourceslist-list-format "deb http://us.archive.ubuntu.com/ubuntu &ubuntu-codename; main restricted
+deb http://security.ubuntu.com/ubuntu &ubuntu-codename;-security main restricted
+deb http://us.archive.ubuntu.com/ubuntu &ubuntu-codename;-updates main restricted">
+<!ENTITY sourceslist-sources-format "Types: deb
+URIs: http://us.archive.ubuntu.com/ubuntu
+Suites: &ubuntu-codename; &ubuntu-codename;-updates
+Components: main restricted
+
+Types: deb
+URIs: http://security.ubuntu.com/ubuntu
+Suites: &ubuntu-codename;-security
+Components: main restricted">