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

Implement simple by-hash for apt update

This implements a apt update schema that get the indexfiles by the
hash instead of the name. The rational is that updates to the archive
servers/mirrors are not atomic so the client may have the previous
version of the Release file when the server updates to a new
Release file and new Packages/Sources/Translations indexes. By
keeping the files around by their hash we can still get the previous
indexfile without a hashsum mismatch.

Enable with APT::Acquire::By-Hash=1
Michael Vogt лет назад: 12
Родитель
Сommit
50d98a1be2
3 измененных файлов с 73 добавлено и 9 удалено
  1. 21 0
      apt-pkg/acquire-item.cc
  2. 13 9
      apt-pkg/indexrecords.cc
  3. 39 0
      test/integration/test-apt-by-hash-update

+ 21 - 0
apt-pkg/acquire-item.cc

@@ -1020,6 +1020,27 @@ void pkgAcqIndex::Init(string const &URI, string const &URIDesc, string const &S
          FileSize = Record->Size;
    }
 
+   // do the request by-hash
+   if(_config->FindB("APT::Acquire::By-Hash", false) == true &&
+      MetaIndexParser)
+   {
+      indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey);
+      if(Record)
+      {
+         // FIXME: make the hash used a config option or read from release file
+         const HashString *TargetHash = Record->Hashes.find("SHA256");
+         std::string ByHash = "/by-hash/" + TargetHash->HashValue();
+         size_t trailing_slash = Desc.URI.find_last_of("/");
+         Desc.URI = Desc.URI.replace(trailing_slash,
+                                     Desc.URI.substr(trailing_slash+1).size()+1,
+                                     ByHash);
+         std::cerr << Desc.URI << std::endl;
+      } else {
+         _error->Warning("By-Hash requested but can not find record for %s",
+                         MetaKey.c_str());
+      }
+   }
+
    Desc.Description = URIDesc;
    Desc.Owner = this;
    Desc.ShortDesc = ShortDesc;

+ 13 - 9
apt-pkg/indexrecords.cc

@@ -90,8 +90,8 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
    Suite = Section.FindS("Suite");
    Dist = Section.FindS("Codename");
 
-   int i;
-   for (i=0;HashString::SupportedHashes()[i] != NULL; i++)
+   bool FoundHashSum = false;
+   for (int i=0;HashString::SupportedHashes()[i] != NULL; i++)
    {
       if (!Section.Find(HashString::SupportedHashes()[i], Start, End))
 	 continue;
@@ -103,16 +103,20 @@ bool indexRecords::Load(const string Filename)				/*{{{*/
       {
 	 if (!parseSumData(Start, End, Name, Hash, Size))
 	    return false;
-	 indexRecords::checkSum *Sum = new indexRecords::checkSum;
-	 Sum->MetaKeyFilename = Name;
-	 Sum->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
-	 Sum->Size = Size;
-	 Entries[Name] = Sum;
+
+         if (Entries.find(Name) == Entries.end())
+         {
+            indexRecords::checkSum *Sum = new indexRecords::checkSum;
+            Sum->MetaKeyFilename = Name;
+            Sum->Size = Size;
+            Entries[Name] = Sum;
+         }
+         Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash));
+         FoundHashSum = true;
       }
-      break;
    }
 
-   if(HashString::SupportedHashes()[i] == NULL)
+   if(FoundHashSum == false)
    {
       strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str());
       return false;

+ 39 - 0
test/integration/test-apt-by-hash-update

@@ -0,0 +1,39 @@
+#!/bin/sh
+set -e
+
+TESTDIR=$(readlink -f $(dirname $0))
+. $TESTDIR/framework
+
+setupenvironment
+configarchitecture "i386"
+
+insertpackage 'unstable' 'foo' 'all' '1.0'
+
+setupaptarchive --no-update
+
+APTARCHIVE=$(readlink -f ./aptarchive)
+
+# make Packages *only* accessable by-hash for this test
+mkdir -p aptarchive/dists/unstable/main/binary-i386/by-hash
+(cd  aptarchive/dists/unstable/main/binary-i386/by-hash && 
+     mv ../Packages* . &&
+     ln -s Packages.gz  $(sha256sum Packages.gz|cut -f1 -d' ') )
+
+# add sources
+mkdir -p aptarchive/dists/unstable/main/source/by-hash
+(cd  aptarchive/dists/unstable/main/source/by-hash && 
+     ln -s ../Sources.gz  $(sha256sum ../Sources.gz|cut -f1 -d' ') 
+)
+
+
+# ensure we do not know about "foo"
+testequal "Reading package lists...
+Building dependency tree...
+E: Unable to locate package foo" aptget install -q -s foo
+
+# ensure we can apt-get update by hash
+testsuccess aptget update -o APT::Acquire::By-Hash=1
+
+# ensure it keeps working
+testequal "Inst foo (1.0 unstable [all])
+Conf foo (1.0 unstable [all])" aptget install -qq -s foo