{ // repo job finished
m_repoUpdateDone.Set();
m_repoUpdateJob = 0;
+ lock.Leave();
}
else
{ // download job
JobMap::iterator i = find_if(m_downloadJobs.begin(), m_downloadJobs.end(), bind2nd(find_map(), jobID));
if (i != m_downloadJobs.end())
m_downloadJobs.erase(i);
+ lock.Leave();
PrunePackageCache();
}
- lock.Leave();
CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE);
g_windowManager.SendThreadMessage(msg);
if (xml.LoadFile(archive) && CAddonMgr::Get().LoadAddonDescriptionFromMemory(xml.RootElement(), addon))
{
// set the correct path
- addon->Props().path = path;
+ addon->Props().path = items[0]->GetPath();
// install the addon
return DoInstall(addon);
Install(*i);
}
-bool CAddonInstaller::CheckDependencies(const AddonPtr &addon)
+bool CAddonInstaller::CheckDependencies(const AddonPtr &addon, CAddonDatabase *database /* = NULL */)
{
std::vector<std::string> preDeps;
preDeps.push_back(addon->ID());
- return CheckDependencies(addon, preDeps);
+ CAddonDatabase localDB;
+ if (!database)
+ database = &localDB;
+ return CheckDependencies(addon, preDeps, *database);
}
bool CAddonInstaller::CheckDependencies(const AddonPtr &addon,
- std::vector<std::string>& preDeps)
+ std::vector<std::string>& preDeps, CAddonDatabase &database)
{
if (!addon.get())
return true; // a NULL addon has no dependencies
ADDONDEPS deps = addon->GetDeps();
- CAddonDatabase database;
database.Open();
for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i)
{
if (!database.GetAddon(addonID, dep) || !dep->MeetsVersion(version))
{ // we don't have it in a repo, or we have it but the version isn't good enough, so dep isn't satisfied.
CLog::Log(LOGDEBUG, "Addon %s requires %s version %s which is not available", addon->ID().c_str(), addonID.c_str(), version.c_str());
+ database.Close();
return false;
}
}
// TODO: should we assume that installed deps are OK?
if (dep && std::find(preDeps.begin(), preDeps.end(), dep->ID()) == preDeps.end())
{
- if (!CheckDependencies(dep, preDeps))
+ if (!CheckDependencies(dep, preDeps, database))
+ {
+ database.Close();
return false;
+ }
preDeps.push_back(dep->ID());
}
}
+ database.Close();
return true;
}
// Prune packages
// 1. Remove the largest packages, leaving at least 2 for each add-on
- CFileItemList items;
+ CFileItemList items;
+ CAddonDatabase db;
+ db.Open();
for (std::map<CStdString,CFileItemList*>::const_iterator it = packs.begin();
it != packs.end();++it)
{
while (size > limit && i < items.Size())
{
size -= items[i]->m_dwSize;
+ db.RemovePackage(items[i]->GetPath());
CFileUtils::DeleteItem(items[i++],true);
}
while (size > limit && i < items.Size())
{
size -= items[i]->m_dwSize;
+ db.RemovePackage(items[i]->GetPath());
CFileUtils::DeleteItem(items[i++],true);
}
}
CStdString dest="special://home/addons/packages/";
CStdString package = URIUtils::AddFileToFolder("special://home/addons/packages/",
URIUtils::GetFileName(m_addon->Path()));
-
if (URIUtils::HasSlashAtEnd(m_addon->Path()))
{ // passed in a folder - all we need do is copy it across
installFrom = m_addon->Path();
}
else
{
- // zip passed in - download + extract
- CStdString path(m_addon->Path());
- if (!m_referer.empty() && URIUtils::IsInternetStream(path))
+ CStdString md5;
+ CAddonDatabase db;
+ db.Open();
+
+ // check that we don't already have a valid copy
+ if (!m_hash.empty() && CFile::Exists(package))
{
- CURL url(path);
- url.SetProtocolOptions(m_referer);
- path = url.Get();
+ if (db.GetPackageHash(m_addon->ID(), package, md5) && m_hash != md5)
+ {
+ db.RemovePackage(package);
+ CFile::Delete(package);
+ }
}
- if (!CFile::Exists(package) && !DownloadPackage(path, dest))
+
+ // zip passed in - download + extract
+ if (!CFile::Exists(package))
{
- CFile::Delete(package);
- return false;
+ CStdString path(m_addon->Path());
+ if (!m_referer.empty() && URIUtils::IsInternetStream(path))
+ {
+ CURL url(path);
+ url.SetProtocolOptions(m_referer);
+ path = url.Get();
+ }
+
+ if (!DownloadPackage(path, dest))
+ {
+ CFile::Delete(package);
+ return false;
+ }
}
// at this point we have the package - check that it is valid
- if (!CFile::Exists(package) || !CheckHash(package))
+ if (!m_hash.empty())
{
- CFile::Delete(package);
- return false;
+ md5 = CUtil::GetFileMD5(package);
+ if (!md5.Equals(m_hash))
+ {
+ CFile::Delete(package);
+ ReportInstallError(m_addon->ID(), URIUtils::GetFileName(package));
+ CLog::Log(LOGERROR, "MD5 mismatch after download %s", package.c_str());
+ return false;
+ }
+ db.AddPackage(m_addon->ID(), package, md5);
}
// check the archive as well - should have just a single folder in the root
if (archivedFiles.Size() != 1 || !archivedFiles[0]->m_bIsFolder)
{ // invalid package
+ db.RemovePackage(package);
CFile::Delete(package);
return false;
}
toast->ResetTimer();
toast->Close(true);
}
- CSettings::Get().SetString("lookandfeel.skin",m_addon->ID().c_str());
+ if (CSettings::Get().GetString("lookandfeel.skin") == m_addon->ID())
+ CApplicationMessenger::Get().ExecBuiltIn("ReloadSkin", true);
+ else
+ CSettings::Get().SetString("lookandfeel.skin",m_addon->ID().c_str());
}
}
}
}
-bool CAddonInstallJob::CheckHash(const CStdString& zipFile)
-{
- if (m_hash.empty())
- return true;
- CStdString md5 = CUtil::GetFileMD5(zipFile);
- if (!md5.Equals(m_hash))
- {
- CFile::Delete(zipFile);
- ReportInstallError(m_addon->ID(), URIUtils::GetFileName(zipFile));
- CLog::Log(LOGERROR, "MD5 mismatch after download %s", zipFile.c_str());
- return false;
- }
- return true;
-}
-
CStdString CAddonInstallJob::AddonID() const
{
return (m_addon) ? m_addon->ID() : "";