+
+bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
+{
+ if(Debug)
+ std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile
+ << std::endl;
+
+ pkgTagSection Tags;
+ string ServerSha1;
+ vector<DiffInfo> available_patches;
+
+ FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
+ pkgTagFile TF(&Fd);
+ if (_error->PendingError() == true)
+ return false;
+
+ if(TF.Step(Tags) == true)
+ {
+ string local_sha1;
+ bool found = false;
+ DiffInfo d;
+ string size;
+
+ string tmp = Tags.FindS("SHA1-Current");
+ std::stringstream ss(tmp);
+ ss >> ServerSha1;
+
+ FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
+ SHA1Summation SHA1;
+ SHA1.AddFD(fd.Fd(), fd.Size());
+ local_sha1 = string(SHA1.Result());
+
+ if(local_sha1 == ServerSha1)
+ {
+ // we have the same sha1 as the server
+ if(Debug)
+ std::clog << "Package file is up-to-date" << std::endl;
+ // set found to true, this will queue a pkgAcqIndexDiffs with
+ // a empty availabe_patches
+ found = true;
+ }
+ else
+ {
+ if(Debug)
+ std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
+
+ // check the historie and see what patches we need
+ string history = Tags.FindS("SHA1-History");
+ std::stringstream hist(history);
+ while(hist >> d.sha1 >> size >> d.file)
+ {
+ d.size = atoi(size.c_str());
+ // read until the first match is found
+ if(d.sha1 == local_sha1)
+ found=true;
+ // from that point on, we probably need all diffs
+ if(found)
+ {
+ if(Debug)
+ std::clog << "Need to get diff: " << d.file << std::endl;
+ available_patches.push_back(d);
+ }
+ }
+ }
+
+ // no information how to get the patches, bail out
+ if(!found)
+ {
+ if(Debug)
+ std::clog << "Can't find a patch in the index file" << std::endl;
+ // Failed will queue a big package file
+ Failed("", NULL);
+ }
+ else
+ {
+ // queue the diffs
+ new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+ ExpectedMD5, available_patches);
+ Complete = false;
+ Status = StatDone;
+ Dequeue();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+ if(Debug)
+ std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << std::endl
+ << "Falling back to normal index file aquire" << std::endl;
+
+ new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc,
+ ExpectedMD5);
+
+ Complete = false;
+ Status = StatDone;
+ Dequeue();
+}
+
+void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
+ pkgAcquire::MethodConfig *Cnf)
+{
+ if(Debug)
+ std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl;
+
+ Item::Done(Message,Size,Md5Hash,Cnf);
+
+ string FinalFile;
+ FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
+
+ // sucess in downloading the index
+ // rename the index
+ FinalFile += string(".IndexDiff");
+ if(Debug)
+ std::clog << "Renaming: " << DestFile << " -> " << FinalFile
+ << std::endl;
+ Rename(DestFile,FinalFile);
+ chmod(FinalFile.c_str(),0644);
+ DestFile = FinalFile;
+
+ if(!ParseDiffIndex(DestFile))
+ return Failed("", NULL);
+
+ Complete = true;
+ Status = StatDone;
+ Dequeue();
+ return;
+}
+
+
+
+// AcqIndexDiffs::AcqIndexDiffs - Constructor
+// ---------------------------------------------------------------------
+/* The package diff is added to the queue. one object is constructed
+ * for each diff and the index
+ */
+pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
+ string URI,string URIDesc,string ShortDesc,
+ string ExpectedMD5, vector<DiffInfo> diffs)
+ : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5),
+ available_patches(diffs)
+{
+
+ DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+ DestFile += URItoFileName(URI);
+
+ Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+ Desc.Description = URIDesc;
+ Desc.Owner = this;
+ Desc.ShortDesc = ShortDesc;
+
+ if(available_patches.size() == 0)
+ {
+ // we are done (yeah!)
+ Finish(true);
+ }
+ else
+ {
+ // get the next diff
+ State = StateFetchDiff;
+ QueueNextDiff();
+ }
+}
+
+