Пример #1
0
bool CAddonInstaller::DoInstall(const AddonPtr &addon, const CStdString &hash, bool update, const CStdString &referer, bool background)
{
  // check whether we already have the addon installing
  CSingleLock lock(m_critSection);
  if (m_downloadJobs.find(addon->ID()) != m_downloadJobs.end())
    return false;

  // check whether all the dependencies are available or not
  // TODO: we currently assume that dependencies will install correctly (and each of their dependencies and so on).
  //       it may be better to install the dependencies first to minimise the chance of an addon becoming orphaned due to
  //       missing deps.
  if (!CheckDependencies(addon))
  {
    CGUIDialogKaiToast::QueueNotification(addon->Icon(), addon->Name(), g_localizeStrings.Get(24044), TOAST_DISPLAY_TIME, false);
    return false;
  }

  if (background)
  {
    unsigned int jobID = CJobManager::GetInstance().AddJob(new CAddonInstallJob(addon, hash, update, referer), this);
    m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(jobID)));
  }
  else
  {
    m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(0)));
    lock.Leave();
    CAddonInstallJob job(addon, hash, update, referer);
    if (!job.DoWork())
    { // TODO: dump something to debug log?
      return false;
    }
    lock.Enter();
    JobMap::iterator i = m_downloadJobs.find(addon->ID());
    m_downloadJobs.erase(i);
  }
  return true;
}
Пример #2
0
void CAddonInstallJob::ReportInstallError(const CStdString& addonID,
                                                const CStdString& fileName)
{
  AddonPtr addon;
  CAddonDatabase database;
  database.Open();
  database.GetAddon(addonID, addon);
  if (addon)
  {
    AddonPtr addon2;
    CAddonMgr::Get().GetAddon(addonID, addon2);
    CGUIDialogKaiToast::QueueNotification(addon->Icon(),
                                          addon->Name(),
                                          g_localizeStrings.Get(addon2 ? 113 : 114),
                                          TOAST_DISPLAY_TIME, false);
  }
  else
  {
    CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error,
                                          fileName,
                                          g_localizeStrings.Get(114),
                                          TOAST_DISPLAY_TIME, false);
  }
}
Пример #3
0
void CGUIDialogAddonInfo::OnUpdate()
{
  if (!m_localAddon)
    return;

  CAddonDatabase database;
  if (!database.Open())
    return;

  std::vector<std::pair<AddonVersion, std::string>> versions;
  if (!database.GetAvailableVersions(m_localAddon->ID(), versions))
    return;

  CFileItemList items;
  if (XFILE::CDirectory::GetDirectory("special://home/addons/packages/", items, ".zip", DIR_FLAG_NO_FILE_DIRS))
  {
    for (int i = 0; i < items.Size(); ++i)
    {
      std::string packageId;
      std::string versionString;
      if (AddonVersion::SplitFileName(packageId, versionString, items[i]->GetLabel()))
      {
        if (packageId == m_localAddon->ID())
        {
          std::string hash;
          std::string path(items[i]->GetPath());
          if (database.GetPackageHash(m_localAddon->ID(), items[i]->GetPath(), hash))
          {
            std::string md5 = CUtil::GetFileMD5(path);
            if (md5 == hash)
              versions.push_back(std::make_pair(AddonVersion(versionString), LOCAL_CACHE));
          }
        }
      }
    }
  }

  if (versions.empty())
  {
    CGUIDialogOK::ShowAndGetInput(CVariant{21341}, CVariant{21342});
    return;
  }

  auto* dialog = static_cast<CGUIDialogSelect*>(g_windowManager.GetWindow(WINDOW_DIALOG_SELECT));
  dialog->Reset();
  dialog->SetHeading(CVariant{21338});
  dialog->SetUseDetails(true);

  std::stable_sort(versions.begin(), versions.end(), CompareVersion);

  for (const auto& versionInfo : versions)
  {
    CFileItem item(StringUtils::Format(g_localizeStrings.Get(21339).c_str(), versionInfo.first.asString().c_str()));
    if (versionInfo.first == m_localAddon->Version())
      item.Select(true);

    AddonPtr repo;
    if (versionInfo.second == LOCAL_CACHE)
    {
      item.SetProperty("Addon.Summary", g_localizeStrings.Get(24095));
      item.SetIconImage("DefaultAddonRepository.png");
      dialog->Add(item);
    }
    else if (CAddonMgr::GetInstance().GetAddon(versionInfo.second, repo, ADDON_REPOSITORY))
    {
      item.SetProperty("Addon.Summary", repo->Name());
      item.SetIconImage(repo->Icon());
      dialog->Add(item);
    }
  }

  dialog->Open();
  if (dialog->IsConfirmed())
  {
    Close();

    auto selected = versions.at(dialog->GetSelectedLabel());

    //turn auto updating off if downgrading
    if (selected.first < m_localAddon->Version())
      CAddonMgr::GetInstance().AddToUpdateBlacklist(m_localAddon->ID());

    if (selected.second == LOCAL_CACHE)
      CAddonInstaller::GetInstance().InstallFromZip(StringUtils::Format("special://home/addons/packages/%s-%s.zip",
          m_localAddon->ID().c_str(), selected.first.asString().c_str()));
    else
      CAddonInstaller::GetInstance().Install(m_addon->ID(), selected.first, selected.second);
  }
}
Пример #4
0
bool CRepositoryUpdateJob::DoWork()
{
  CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checking for updates.", m_repo->ID().c_str());
  CAddonDatabase database;
  database.Open();

  std::string oldChecksum;
  if (database.GetRepoChecksum(m_repo->ID(), oldChecksum) == -1)
    oldChecksum = "";

  std::string newChecksum;
  VECADDONS addons;
  auto status = m_repo->FetchIfChanged(oldChecksum, newChecksum, addons);

  database.SetLastChecked(m_repo->ID(), m_repo->Version(),
      CDateTime::GetCurrentDateTime().GetAsDBDateTime());

  MarkFinished();

  if (status == CRepository::STATUS_ERROR)
    return false;

  if (status == CRepository::STATUS_NOT_MODIFIED)
  {
    CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checksum not changed.", m_repo->ID().c_str());
    return true;
  }

  //Invalidate art.
  {
    CTextureDatabase textureDB;
    textureDB.Open();
    textureDB.BeginMultipleExecute();

    for (const auto& addon : addons)
    {
      AddonPtr oldAddon;
      if (database.GetAddon(addon->ID(), oldAddon) && addon->Version() > oldAddon->Version())
      {
        if (!oldAddon->Icon().empty() || !oldAddon->FanArt().empty() || !oldAddon->Screenshots().empty())
          CLog::Log(LOGDEBUG, "CRepository: invalidating cached art for '%s'", addon->ID().c_str());
        if (!oldAddon->Icon().empty())
          textureDB.InvalidateCachedTexture(oldAddon->Icon());
        if (!oldAddon->FanArt().empty())
          textureDB.InvalidateCachedTexture(oldAddon->Icon());
        for (const auto& path : oldAddon->Screenshots())
          textureDB.InvalidateCachedTexture(path);
      }
    }
    textureDB.CommitMultipleExecute();
  }

  database.UpdateRepositoryContent(m_repo->ID(), m_repo->Version(), newChecksum, addons);

  //Notify about broken status changes
  for (const auto& addon : addons)
  {
    AddonPtr localAddon;
    if (!CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon))
      continue;

    if (localAddon && localAddon->Version() > addon->Version())
      //We have a newer version locally
      continue;

    AddonPtr oldAddon;
    database.GetAddon(addon->ID(), oldAddon);

    if (database.GetAddonVersion(addon->ID()).first > addon->Version())
      //Newer version in db (ie. in a different repo)
      continue;

    std::string broken = addon->Broken();
    bool isBroken = !addon->Broken().empty();
    bool isBrokenInDb = oldAddon && !oldAddon->Broken().empty();
    if (isBroken && !isBrokenInDb)
    {
      //newly broken
      if (HELPERS::ShowYesNoDialogLines(CVariant{addon->Name()}, CVariant{24096}, CVariant{24097}, CVariant{""})
        == DialogResponse::YES)
      {
        CAddonMgr::GetInstance().DisableAddon(addon->ID());
      }

      CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' marked broken. reason: \"%s\"",
           m_repo->ID().c_str(), addon->ID().c_str(), broken.c_str());

      CEventLog::GetInstance().Add(EventPtr(new CAddonManagementEvent(addon, 24096)));
    }
    else if (!isBroken && isBrokenInDb)
    {
      //Unbroken
      CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' unbroken",
          m_repo->ID().c_str(), addon->ID().c_str());
    }
  }
  return true;
}