*/
pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
string URI,string URIDesc,string ShortDesc,
- string ExpectedMD5, vector<DiffInfo> diffs)
- : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), available_patches(diffs)
+ string ExpectedMD5, vector<DiffInfo> diffs)
+ : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5),
+ available_patches(diffs)
{
DestFile = _config->FindDir("Dir::State::lists") + "partial/";
return;
}
- if(available_patches.size() == 0)
+ if(available_patches.size() == 0) {
+ State = StateFetchIndex;
QueueDiffIndex(URI);
- else
+ } else {
+ State = StateFetchDiff;
QueueNextDiff();
+ }
}
void pkgAcqIndexDiffs::QueueDiffIndex(string URI)
/* The only header we use is the last-modified header. */
string pkgAcqIndexDiffs::Custom600Headers()
{
- if(DestFile.rfind(".IndexDiff") == string::npos)
+ // we only care for the IndexDiff file
+ if(State != StateFetchIndex)
return string("");
string Final = _config->FindDir("Dir::State::lists");
void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
{
- if(Debug)
- std::clog << "Failed(): " << Desc.URI << std::endl
- << "Falling back to big package file" << std::endl;
+ std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
+ << "Falling back to normal index file aquire" << std::endl;
new pkgAcqIndex(Owner, RealURI, Desc.Description,Desc.ShortDesc,
ExpectedMD5);
Finish();
}
-// this needs to be rewriten to not depend on the external ed
-bool pkgAcqIndexDiffs::ApplyDiff(string PatchFile)
-{
- char *error;
- int res=0;
-
- string FinalFile = _config->FindDir("Dir::State::lists");
- FinalFile += URItoFileName(RealURI);
-
- int Process = ExecFork();
- if (Process == 0)
- {
- chdir(_config->FindDir("Dir::State::lists").c_str());
- // for some reason "red" fails with the pdiffs from p.d.o/~aba ?!?
- string cmd = "(zcat " + PatchFile + "; echo \"wq\" ) | /bin/ed " + FinalFile + " >/dev/null 2>/dev/null";
- if(Debug)
- std::clog << "Runing: " << cmd << std::endl;
- res = system(cmd.c_str());
- _exit(WEXITSTATUS(res));
- }
- if(!ExecWait(Process, error, true)) {
- //_error->Error("Patch failed: %s ", error);
- return false;
- }
-
- return true;
-}
bool pkgAcqIndexDiffs::QueueNextDiff()
{
+
// calc sha1 of the just patched file
string FinalFile = _config->FindDir("Dir::State::lists");
FinalFile += URItoFileName(RealURI);
SHA1Summation SHA1;
SHA1.AddFD(fd.Fd(), fd.Size());
string local_sha1 = string(SHA1.Result());
+ if(Debug)
+ std::clog << "QueueNextDiff: "
+ << FinalFile << " (" << local_sha1 << ")"<<std::endl;
// remove all patches until the next matching patch is found
// this requires the Index file to be ordered
for(vector<DiffInfo>::iterator I=available_patches.begin();
- (*I).sha1 == local_sha1 || I != available_patches.end();
- I++)
+ available_patches.size() > 0 && I != available_patches.end()
+ && (*I).sha1 != local_sha1;
+ I++) {
available_patches.erase(I);
-
+ }
// error checking and falling back if no patch was found
if(available_patches.size() == 0) {
bool found = false;
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)
Item::Done(Message,Size,Md5Hash,Cnf);
- int len = Desc.URI.size();
- // sucess in downloading the index
- if(Desc.URI.substr(len-strlen("Index"),len-1) == "Index") {
+ string FinalFile;
+ FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
- // rename
- string FinalFile = _config->FindDir("Dir::State::lists");
- FinalFile += URItoFileName(RealURI) + string(".IndexDiff");
+ // sucess in downloading the index
+ if(State == StateFetchIndex)
+ {
+ // rename the index
+ FinalFile += string(".IndexDiff");
if(Debug)
std::clog << "Renaming: " << DestFile << " -> " << FinalFile
<< std::endl;
return Finish();
}
- // sucess in downloading a diff
- if(Desc.URI.find(".diff") != string::npos) {
- ApplyDiff(DestFile);
+ // sucess in downloading a diff, enter ApplyDiff state
+ if(State == StateFetchDiff)
+ {
+
+ if(Debug)
+ std::clog << "Sending to gzip method: " << FinalFile << std::endl;
+
+ string FileName = LookupTag(Message,"Filename");
+ State = StateUnzipDiff;
+ Desc.URI = "gzip:" + FileName;
+ DestFile += ".decomp";
+ QueueURI(Desc);
+ Mode = "gzip";
+ return;
+ }
+
+ // sucess in downloading a diff, enter ApplyDiff state
+ if(State == StateUnzipDiff)
+ {
+
+ // rred excepts the patch as $FinalFile.ed
+ Rename(DestFile,FinalFile+".ed");
+
+ if(Debug)
+ std::clog << "Sending to rred method: " << FinalFile << std::endl;
+
+ State = StateApplyDiff;
+ Desc.URI = "rred:" + FinalFile;
+ QueueURI(Desc);
+ Mode = "rred";
+ return;
+ }
+
+
+ // success in download/apply a diff, queue next (if needed)
+ if(State == StateApplyDiff)
+ {
+ // remove the just applied patch
available_patches.erase(available_patches.begin());
+ // move into place
+ if(Debug)
+ {
+ std::clog << "Moving patched file in place: " << std::endl
+ << DestFile << " -> " << FinalFile << std::endl;
+ }
+ Rename(DestFile,FinalFile);
+
+ // see if there is more to download
if(available_patches.size() > 0) {
new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
ExpectedMD5, available_patches);
- } else {
- Finish(true);
- return;
- }
+ return Finish();
+ } else
+ return Finish(true);
}
-
- Finish();
}