#include "package_db.h"
#include "package_meta.h"
-#include "package_version.h"
#include "package_source.h"
#include "threebar.h"
#include "Exception.h"
-#include "getopt++/BoolOption.h"
-
-using namespace std;
-
extern ThreeBarProgressPage Progress;
-BoolOption IncludeSource (false, 'I', "include-source", "Automatically include source download");
-
+// Return true if selected checks pass, false if they don't and the
+// user chooses to delete the file; otherwise throw an exception.
static bool
-validateCachedPackage (const std::string& fullname, packagesource & pkgsource)
+validateCachedPackage (const std::string& fullname, packagesource & pkgsource,
+ HWND owner, bool check_hash, bool check_size)
{
- DWORD size = get_file_size(fullname);
- if (size != pkgsource.size)
- {
- Log (LOG_BABBLE) << "INVALID PACKAGE: " << fullname
- << " - Size mismatch: Ini-file: " << pkgsource.size
- << " != On-disk: " << size << endLog;
- return false;
- }
- return true;
+ try
+ {
+ if (check_size)
+ pkgsource.check_size_and_cache (fullname);
+ if (check_hash)
+ pkgsource.check_hash ();
+ return true;
+ }
+ catch (Exception *e)
+ {
+ pkgsource.set_cached ("");
+ const char *filename = fullname.c_str ();
+ if (strncmp (filename, "file://", 7) == 0)
+ filename += 7;
+ if (e->errNo() == APPERR_CORRUPT_PACKAGE
+ && yesno (owner, IDS_QUERY_CORRUPT, filename) == IDYES)
+ remove (filename);
+ else
+ throw e;
+ }
+ return false;
}
-/* 0 on failure
+/* 0 if not cached; may throw exception if validation fails.
*/
int
-check_for_cached (packagesource & pkgsource, bool mirror_mode)
+check_for_cached (packagesource & pkgsource, HWND owner, bool mirror_mode,
+ bool check_hash)
{
- // Already found one.
- if (pkgsource.Cached())
- return 1;
+ /* If the packagesource doesn't have a filename, it can't possibly be in the
+ cache */
+ if (!pkgsource.Canonical())
+ {
+ return 0;
+ }
/* Note that the cache dir is represented by a mirror site of file://local_dir */
std::string prefix = "file://" + local_dir + "/";
- std::string fullname = prefix + (pkgsource.Canonical() ? pkgsource.Canonical() : "");
+ std::string fullname = prefix + pkgsource.Canonical();
if (mirror_mode)
{
/* Just assume correctness of mirror. */
- pkgsource.set_cached (fullname);
+ if (!pkgsource.Cached())
+ pkgsource.set_cached (fullname);
return 1;
}
+ // Already found one, which we can assume to have the right size.
+ if (pkgsource.Cached())
+ {
+ if (validateCachedPackage (pkgsource.Cached(), pkgsource, owner,
+ check_hash, false))
+ return 1;
+ // If we get here, pkgsource.Cached() was corrupt and deleted.
+ pkgsource.set_cached ("");
+ }
+
/*
1) is there a legacy version in the cache dir available.
*/
if (io_stream::exists (fullname))
{
- if (validateCachedPackage (fullname, pkgsource))
- pkgsource.set_cached (fullname);
- else
- throw new Exception (TOSTRING(__LINE__) " " __FILE__,
- "Package validation failure for " + fullname,
- APPERR_CORRUPT_PACKAGE);
- return 1;
+ if (validateCachedPackage (fullname, pkgsource, owner, check_hash, true))
+ return 1;
+ // If we get here, fullname was corrupt and deleted, but it
+ // might have been cached.
+ pkgsource.set_cached ("");
}
/*
std::string fullname = prefix + rfc1738_escape_part (n->key) + "/" +
pkgsource.Canonical ();
if (io_stream::exists(fullname))
- {
- if (validateCachedPackage (fullname, pkgsource))
- pkgsource.set_cached (fullname);
- else
- throw new Exception (TOSTRING(__LINE__) " " __FILE__,
- "Package validation failure for " + fullname,
- APPERR_CORRUPT_PACKAGE);
- return 1;
- }
+ {
+ if (validateCachedPackage (fullname, pkgsource, owner, check_hash,
+ true))
+ return 1;
+ // If we get here, fullname was corrupt and deleted, but it
+ // might have been cached.
+ pkgsource.set_cached ("");
+ }
}
return 0;
}
{
try
{
- if (check_for_cached (pkgsource))
+ if (check_for_cached (pkgsource, owner))
return 0;
}
catch (Exception * e)
}
else
{
- size_t size = get_file_size ("file://" + local + ".tmp");
- if (size == pkgsource.size)
+ try
{
- Log (LOG_PLAIN) << "Downloaded " << local << endLog;
if (_access (local.c_str(), 0) == 0)
remove (local.c_str());
rename ((local + ".tmp").c_str(), local.c_str());
+ pkgsource.check_size_and_cache ("file://" + local);
+ pkgsource.check_hash ();
+ Log (LOG_PLAIN) << "Downloaded " << local << endLog;
success = 1;
- pkgsource.set_cached ("file://" + local);
// FIXME: move the downloaded file to the
// original locations - without the mirror site dir in the way
continue;
}
- else
+ catch (Exception *e)
{
- Log (LOG_PLAIN) << "Download " << local << " wrong size (" <<
- size << " actual vs " << pkgsource.size << " expected)" <<
- endLog;
- remove ((local + ".tmp").c_str());
- continue;
+ remove (local.c_str());
+ pkgsource.set_cached ("");
+ if (e->errNo() == APPERR_CORRUPT_PACKAGE)
+ {
+ Log (LOG_PLAIN) << "Downloaded file " << local
+ << " is corrupt; deleting." << endLog;
+ continue;
+ }
+ else
+ {
+ Log (LOG_PLAIN) << "Unexpected exception while validating "
+ << "downloaded file " << local
+ << "; deleting." << endLog;
+ throw e;
+ }
}
}
}
total_download_bytes_sofar = 0;
download_failures.clear ();
- Progress.SetText1 ("Checking for packages to download...");
+ Progress.SetText1 (IDS_PROGRESS_CHECKING);
Progress.SetText2 ("");
Progress.SetText3 ("");
packagedb db;
- /* calculate the amount needed */
- for (packagedb::packagecollection::iterator i = db.packages.begin ();
- i != db.packages.end (); ++i)
+ const SolverTransactionList &t = db.solution.transactions();
+
+ /* calculate the total size of the download */
+ for (SolverTransactionList::const_iterator i = t.begin (); i != t.end (); ++i)
{
- packagemeta & pkg = *(i->second);
- if (pkg.desired && (pkg.picked () || pkg.srcpicked ()))
- {
- packageversion version = pkg.desired;
- packageversion sourceversion = version.sourcePackage();
- try
- {
- if (pkg.picked())
- {
- if (!check_for_cached (*version.source()))
- total_download_bytes += version.source()->size;
- }
- if (pkg.srcpicked () || IncludeSource)
- {
- if (!check_for_cached (*sourceversion.source()))
- total_download_bytes += sourceversion.source()->size;
- }
- }
- catch (Exception * e)
- {
- // We know what to do with these..
- if (e->errNo() == APPERR_CORRUPT_PACKAGE)
- fatal (owner, IDS_CORRUPT_PACKAGE, pkg.name.c_str());
- // Unexpected exception.
- throw e;
- }
- }
+ if (i->type != SolverTransaction::transInstall)
+ continue;
+ packageversion version = i->version;
+
+ try
+ {
+ if (!check_for_cached (*version.source(), owner))
+ total_download_bytes += version.source()->size;
+ }
+ catch (Exception * e)
+ {
+ // We know what to do with these..
+ if (e->errNo() == APPERR_CORRUPT_PACKAGE)
+ fatal (owner, IDS_CORRUPT_PACKAGE, version.Name().c_str());
+ // Unexpected exception.
+ throw e;
+ }
}
/* and do the download. FIXME: This here we assign a new name for the cached version
* and check that above.
*/
- for (packagedb::packagecollection::iterator i = db.packages.begin ();
- i != db.packages.end (); ++i)
+ for (SolverTransactionList::const_iterator i = t.begin (); i != t.end (); ++i)
{
- packagemeta & pkg = *(i->second);
- if (pkg.desired && (pkg.picked () || pkg.srcpicked ()))
+ if (i->type != SolverTransaction::transInstall)
+ continue;
+ packageversion version = i->version;
+
{
int e = 0;
- packageversion version = pkg.desired;
- packageversion sourceversion = version.sourcePackage();
- if (pkg.picked())
- {
- e += download_one (*version.source(), owner);
- }
- if (sourceversion && (pkg.srcpicked() || IncludeSource))
- {
- e += download_one (*sourceversion.source (), owner);
- }
+ e += download_one (*version.source(), owner);
errors += e;
if (e)
download_failures.push_back (version);
HANDLE *context;
context = (HANDLE *) p;
+ SetThreadUILanguage(langid);
+
try
{
int next_dialog =