Browse Source

deal with partially downloaded changelogs

Changelogs are relatively small and we have no hashes for them, but we
had partial support for them before, so lets stick to it.

This also deletes the (partial) file before moving the downloaded file
into its place – rename(2) should be doing this by itself, but testing
on semaphoreci suggests that this isn't always the case (error is "Stale
file handle") and we don't need an atomic replace here, so be explicit.

Git-Dch: Ignore
David Kalnischkies 10 years ago
parent
commit
872bd44716
2 changed files with 25 additions and 2 deletions
  1. 19 2
      apt-pkg/acquire-item.cc
  2. 6 0
      test/integration/test-apt-get-changelog

+ 19 - 2
apt-pkg/acquire-item.cc

@@ -3145,7 +3145,21 @@ void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFi
 
    DestFile = flCombine(TemporaryDirectory, DestFileName);
    if (DestDir.empty() == false)
+   {
       d->FinalFile = flCombine(DestDir, DestFileName);
+      if (RealFileExists(d->FinalFile))
+      {
+	 FileFd file1, file2;
+	 if (file1.Open(DestFile, FileFd::WriteOnly | FileFd::Create | FileFd::Exclusive) &&
+	       file2.Open(d->FinalFile, FileFd::ReadOnly) && CopyFile(file2, file1))
+	 {
+	    struct timeval times[2];
+	    times[0].tv_sec = times[1].tv_sec = file2.ModificationTime();
+	    times[0].tv_usec = times[1].tv_usec = 0;
+	    utimes(DestFile.c_str(), times);
+	 }
+      }
+   }
 
    Desc.ShortDesc = "Changelog";
    strprintf(Desc.Description, "%s %s %s Changelog", URI::SiteOnly(Desc.URI).c_str(), SrcName.c_str(), SrcVersion.c_str());
@@ -3292,7 +3306,6 @@ void pkgAcqChangelog::Failed(string const &Message, pkgAcquire::MethodConfig con
       ErrorText = errText;
    else
       ErrorText = errText + " (" + ErrorText + ")";
-   return;
 }
 									/*}}}*/
 // AcqChangelog::Done - Item downloaded OK				/*{{{*/
@@ -3301,7 +3314,11 @@ void pkgAcqChangelog::Done(string const &Message,HashStringList const &CalcHashe
 {
    Item::Done(Message,CalcHashes,Cnf);
    if (d->FinalFile.empty() == false)
-      Rename(DestFile, d->FinalFile);
+   {
+      if (RemoveFile("pkgAcqChangelog::Done", d->FinalFile) == false ||
+	    Rename(DestFile, d->FinalFile) == false)
+	 Status = StatError;
+   }
 
    Complete = true;
 }

+ 6 - 0
test/integration/test-apt-get-changelog

@@ -94,9 +94,15 @@ testsuccess aptget changelog foo foo -d
 testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
 testfileequal 'foo.changelog' "$(cat  aptarchive/pool/main/f/foo/foo_1.0/changelog)"
 echo 'bogus' > foo.changelog
+touch -d 'now + 1 hour' foo.changelog
 testsuccess aptget changelog foo foo -d
 testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
 testfileequal 'foo.changelog' "$(cat  aptarchive/pool/main/f/foo/foo_1.0/changelog)"
+echo -n 'bogus' > foo.changelog
+touch -d "$(stat -c%y aptarchive/pool/main/f/foo/foo_1.0/changelog)" foo.changelog
+testsuccess aptget changelog foo foo -d
+testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644"
+testequal 'bogus1.0) stable; urgency=low' head -n 1 foo.changelog
 rm -f foo.changelog
 
 # no @CHANGEPATH@ in the URI