Esempio n. 1
0
bool CAddonInstaller::CheckDependencies(const AddonPtr &addon)
{
  assert(addon.get());
  ADDONDEPS deps = addon->GetDeps();
  CAddonDatabase database;
  database.Open();
  for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i)
  {
    const CStdString &addonID = i->first;
    const AddonVersion &version = i->second.first;
    bool optional = i->second.second;
    AddonPtr dep;
    bool haveAddon = CAddonMgr::Get().GetAddon(addonID, dep);
    if ((haveAddon && !dep->MeetsVersion(version)) || (!haveAddon && !optional))
    { // we have it but our version isn't good enough, or we don't have it and we need it
      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());
        return false;
      }
    }
    // at this point we have our dep, so check that it's OK as well
    // TODO: should we assume that installed deps are OK?
    if (!CheckDependencies(dep))
      return false;
  }
  return true;
}
Esempio n. 2
0
bool CAddonInstallJob::Install(const CStdString &installFrom)
{
  CStdString addonFolder(installFrom);
  URIUtils::RemoveSlashAtEnd(addonFolder);
  addonFolder = URIUtils::AddFileToFolder("special://home/addons/",
                                       URIUtils::GetFileName(addonFolder));

  CFileItemList install;
  install.Add(CFileItemPtr(new CFileItem(installFrom, true)));
  install[0]->Select(true);
  CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/");

  AddonPtr addon;
  if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon))
  { // failed extraction or failed to load addon description
    CStdString addonID = URIUtils::GetFileName(addonFolder);
    ReportInstallError(addonID, addonID);
    CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str());
    DeleteAddon(addonFolder);
    return false;
  }

  // resolve dependencies
  CAddonMgr::Get().FindAddons(); // needed as GetDeps() grabs directly from c-pluff via the addon manager
  ADDONDEPS deps = addon->GetDeps();
  CStdString referer;
  referer.Format("Referer=%s-%s.zip",addon->ID().c_str(),addon->Version().c_str());
  for (ADDONDEPS::iterator it  = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first.Equals("xbmc.metadata"))
      continue;

    const CStdString &addonID = it->first;
    const AddonVersion &version = it->second.first;
    bool optional = it->second.second;
    AddonPtr dependency;
    bool haveAddon = CAddonMgr::Get().GetAddon(addonID, dependency);
    if ((haveAddon && !dependency->MeetsVersion(version)) || (!haveAddon && !optional))
    { // we have it but our version isn't good enough, or we don't have it and we need it
      bool force=(dependency != NULL);
      // dependency is already queued up for install - ::Install will fail
      // instead we wait until the Job has finished. note that we
      // recall install on purpose in case prior installation failed
      if (CAddonInstaller::Get().HasJob(addonID))
      {
        while (CAddonInstaller::Get().HasJob(addonID))
          Sleep(50);
        force = false;
      }
      // don't have the addon or the addon isn't new enough - grab it (no new job for these)
      if (!CAddonInstaller::Get().Install(addonID, force, referer, false))
      {
        DeleteAddon(addonFolder);
        return false;
      }
    }
  }
  return true;
}
Esempio n. 3
0
bool CAddonInstaller::CheckDependencies(const AddonPtr &addon,
                                        std::vector<std::string>& preDeps, CAddonDatabase &database,
                                        std::pair<std::string, std::string> &failedDep)
{
  if (addon == NULL)
    return true; // a NULL addon has no dependencies

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

  ADDONDEPS deps = addon->GetDeps();
  for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i)
  {
    const std::string &addonID = i->first;
    const AddonVersion &version = i->second.first;
    bool optional = i->second.second;
    AddonPtr dep;
    bool haveAddon = CAddonMgr::GetInstance().GetAddon(addonID, dep);
    if ((haveAddon && !dep->MeetsVersion(version)) || (!haveAddon && !optional))
    {
      // we have it but our version isn't good enough, or we don't have it and we need it
      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, "CAddonInstallJob[%s]: requires %s version %s which is not available", addon->ID().c_str(), addonID.c_str(), version.asString().c_str());
        database.Close();

        // fill in the details of the failed dependency
        failedDep.first = addon->ID();
        failedDep.second = version.asString();

        return false;
      }
    }

    // at this point we have our dep, or the dep is optional (and we don't have it) so check that it's OK as well
    // 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, database, failedDep))
      {
        database.Close();
        preDeps.push_back(dep->ID());
        return false;
      }
    }
  }
  database.Close();

  return true;
}
Esempio n. 4
0
bool CAddonInstallJob::Install(const CStdString &installFrom)
{
  CStdString addonFolder(installFrom);
  URIUtils::RemoveSlashAtEnd(addonFolder);
  addonFolder = URIUtils::AddFileToFolder("special://home/addons/",
                                       URIUtils::GetFileName(addonFolder));

  CFileItemList install;
  install.Add(CFileItemPtr(new CFileItem(installFrom, true)));
  install[0]->Select(true);
  CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/");

  AddonPtr addon;
  if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon))
  { // failed extraction or failed to load addon description
    CStdString addonID = URIUtils::GetFileName(addonFolder);
    ReportInstallError(addonID, addonID);
    CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str());
    DeleteAddon(addonFolder);
    return false;
  }

  // resolve dependencies
  CAddonMgr::Get().FindAddons(); // needed as GetDeps() grabs directly from c-pluff via the addon manager
  ADDONDEPS deps = addon->GetDeps();
  CStdString referer;
  referer.Format("Referer=%s-%s.zip",addon->ID().c_str(),addon->Version().c_str());
  for (ADDONDEPS::iterator it  = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first.Equals("xbmc.metadata"))
      continue;
    AddonPtr dependency;
    if (!CAddonMgr::Get().GetAddon(it->first,dependency) || dependency->Version() < it->second.first)
    {
      // don't have the addon or the addon isn't new enough - grab it (no new job for these)
      if (!CAddonInstaller::Get().Install(it->first, dependency != NULL, referer, false))
      {
        DeleteAddon(addonFolder);
        return false;
      }
    }
  }
  return true;
}
Esempio n. 5
0
bool CAddonInstallJob::Install(const CStdString &installFrom)
{
  CStdString addonFolder(installFrom);
  URIUtils::RemoveSlashAtEnd(addonFolder);
  addonFolder = URIUtils::AddFileToFolder("special://home/addons/",
                                       URIUtils::GetFileName(addonFolder));

  CFileItemList install;
  install.Add(CFileItemPtr(new CFileItem(installFrom, true)));
  install[0]->Select(true);
  CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/");

  AddonPtr addon;
  if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon))
  { // failed extraction or failed to load addon description
    CStdString addonID = URIUtils::GetFileName(addonFolder);
    ReportInstallError(addonID, addonID);
    CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str());
    CFileItemList list;
    list.Add(CFileItemPtr(new CFileItem(addonFolder, true)));
    list[0]->Select(true);
    CJobManager::GetInstance().AddJob(new CFileOperationJob(CFileOperationJob::ActionDelete, list, ""), NULL);
    return false;
  }

  // resolve dependencies
  ADDONDEPS deps = addon->GetDeps();
  CStdString referer;
  referer.Format("Referer=%s-%s.zip",addon->ID().c_str(),addon->Version().str.c_str());
  for (ADDONDEPS::iterator it  = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first.Equals("xbmc.metadata"))
      continue;
    AddonPtr dependency;
    if (!CAddonMgr::Get().GetAddon(it->first,dependency))
      CAddonInstaller::Get().Install(it->first, false, referer, false); // no new job for these
  }
  return true;
}
Esempio n. 6
0
bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& repo)
{
  SetText(g_localizeStrings.Get(24079));
  ADDONDEPS deps = m_addon->GetDeps();

  unsigned int totalSteps = static_cast<unsigned int>(deps.size());
  if (ShouldCancel(0, totalSteps))
    return false;

  // The first thing we do is install dependencies
  for (ADDONDEPS::iterator it = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first != "xbmc.metadata")
    {
      const std::string &addonID = it->first;
      const AddonVersion &version = it->second.first;
      bool optional = it->second.second;
      AddonPtr dependency;
      bool haveAddon = CAddonMgr::GetInstance().GetAddon(addonID, dependency, ADDON_UNKNOWN, false);
      if ((haveAddon && !dependency->MeetsVersion(version)) || (!haveAddon && !optional))
      {
        // we have it but our version isn't good enough, or we don't have it and we need it

        // dependency is already queued up for install - ::Install will fail
        // instead we wait until the Job has finished. note that we
        // recall install on purpose in case prior installation failed
        if (CAddonInstaller::GetInstance().HasJob(addonID))
        {
          while (CAddonInstaller::GetInstance().HasJob(addonID))
            Sleep(50);

          if (!CAddonMgr::GetInstance().IsAddonInstalled(addonID))
          {
            CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to install dependency %s", m_addon->ID().c_str(), addonID.c_str());
            ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
            return false;
          }
        }
        // don't have the addon or the addon isn't new enough - grab it (no new job for these)
        else if (IsModal())
        {
          RepositoryPtr repoForDep;
          AddonPtr addon;
          std::string hash;
          if (!CAddonInstaller::GetRepoForAddon(addonID, repoForDep) ||
              !CAddonInstallJob::GetAddonWithHash(addonID, repoForDep->ID(), addon, hash))
          {
            CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to find dependency %s", m_addon->ID().c_str(), addonID.c_str());
            ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
            return false;
          }

          CAddonInstallJob dependencyJob(addon, repoForDep, hash);

          // pass our progress indicators to the temporary job and don't allow it to
          // show progress or information updates (no progress, title or text changes)
          dependencyJob.SetProgressIndicators(GetProgressBar(), GetProgressDialog(), false, false);

          if (!dependencyJob.DoModal())
          {
            CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to install dependency %s", m_addon->ID().c_str(), addonID.c_str());
            ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
            return false;
          }
        }
        else if (!CAddonInstaller::GetInstance().InstallOrUpdate(addonID, false))
        {
          CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to install dependency %s", m_addon->ID().c_str(), addonID.c_str());
          ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
          return false;
        }
      }
    }

    if (ShouldCancel(std::distance(deps.begin(), it), totalSteps))
      return false;
  }

  SetText(g_localizeStrings.Get(24086));
  SetProgress(0);

  // now that we have all our dependencies, we can install our add-on
  if (repo != NULL)
  {
    CFileItemList dummy;
    std::string s = StringUtils::Format("plugin://%s/?action=install&package=%s&version=%s", repo->ID().c_str(),
                                        m_addon->ID().c_str(), m_addon->Version().asString().c_str());
    if (!CDirectory::GetDirectory(s, dummy))
    {
      CLog::Log(LOGERROR, "CAddonInstallJob[%s]: installation of repository failed", m_addon->ID().c_str());
      ReportInstallError(m_addon->ID(), m_addon->ID());
      return false;
    }
  }
  else
  {
    std::string addonFolder = installFrom;
    URIUtils::RemoveSlashAtEnd(addonFolder);
    addonFolder = URIUtils::AddFileToFolder("special://home/addons/", URIUtils::GetFileName(addonFolder));

    CFileItemList install;
    install.Add(CFileItemPtr(new CFileItem(installFrom, true)));
    install[0]->Select(true);

    AddonPtr addon;
    if (!DoFileOperation(CFileOperationJob::ActionReplace, install, "special://home/addons/", false) ||
        !CAddonMgr::GetInstance().LoadAddonDescription(addonFolder, addon))
    {
      // failed extraction or failed to load addon description
      DeleteAddon(addonFolder);

      std::string addonID = URIUtils::GetFileName(addonFolder);
      CLog::Log(LOGERROR, "CAddonInstallJob[%s]: could not read addon description of %s", addonID.c_str(), addonFolder.c_str());
      ReportInstallError(addonID, addonID);
      return false;
    }
  }
  SetProgress(100);

  return true;
}
Esempio n. 7
0
bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& repo)
{
  // The first thing we do is install dependencies
  ADDONDEPS deps = m_addon->GetDeps();
  std::string referer = StringUtils::Format("Referer=%s-%s.zip",m_addon->ID().c_str(),m_addon->Version().asString().c_str());
  for (ADDONDEPS::iterator it  = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first == "xbmc.metadata")
      continue;

    const std::string &addonID = it->first;
    const AddonVersion &version = it->second.first;
    bool optional = it->second.second;
    AddonPtr dependency;
    bool haveAddon = CAddonMgr::Get().GetAddon(addonID, dependency);
    if ((haveAddon && !dependency->MeetsVersion(version)) || (!haveAddon && !optional))
    { // we have it but our version isn't good enough, or we don't have it and we need it
      bool force=(dependency != NULL);
      // dependency is already queued up for install - ::Install will fail
      // instead we wait until the Job has finished. note that we
      // recall install on purpose in case prior installation failed
      if (CAddonInstaller::Get().HasJob(addonID))
      {
        while (CAddonInstaller::Get().HasJob(addonID))
          Sleep(50);
        force = false;
      }
      // don't have the addon or the addon isn't new enough - grab it (no new job for these)
      if (!CAddonInstaller::Get().Install(addonID, force, referer, false))
        return false;
    }
  }

  // now that we have all our dependencies, we can install our add-on
  if (repo)
  {
    CFileItemList dummy;
    std::string s = StringUtils::Format("plugin://%s/?action=install"
                                       "&package=%s&version=%s", repo->ID().c_str(),
                                       m_addon->ID().c_str(),
                                       m_addon->Version().asString().c_str());
    if (!CDirectory::GetDirectory(s, dummy))
      return false;
  }
  else
  {
    std::string addonFolder(installFrom);
    URIUtils::RemoveSlashAtEnd(addonFolder);
    addonFolder = URIUtils::AddFileToFolder("special://home/addons/",
                                         URIUtils::GetFileName(addonFolder));

    CFileItemList install;
    install.Add(CFileItemPtr(new CFileItem(installFrom, true)));
    install[0]->Select(true);
    CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/");

    AddonPtr addon;
    if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon))
    { // failed extraction or failed to load addon description
      std::string addonID = URIUtils::GetFileName(addonFolder);
      ReportInstallError(addonID, addonID);
      CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str());
      DeleteAddon(addonFolder);
      return false;
    }

    // Update the addon manager so that it has the newly installed add-on.
    CAddonMgr::Get().FindAddons();
  }
  return true;
}
Esempio n. 8
0
bool CAddonInstallJob::Install(const std::string &installFrom, const AddonPtr& repo)
{
  SetText(g_localizeStrings.Get(24079));
  ADDONDEPS deps = m_addon->GetDeps();

  unsigned int totalSteps = static_cast<unsigned int>(deps.size());
  if (ShouldCancel(0, totalSteps))
    return false;

  // The first thing we do is install dependencies
  for (ADDONDEPS::iterator it = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first != "xbmc.metadata")
    {
      const std::string &addonID = it->first;
      const AddonVersion &version = it->second.first;
      bool optional = it->second.second;
      AddonPtr dependency;
      bool haveAddon = CAddonMgr::GetInstance().GetAddon(addonID, dependency, ADDON_UNKNOWN, false);
      if ((haveAddon && !dependency->MeetsVersion(version)) || (!haveAddon && !optional))
      {
        // we have it but our version isn't good enough, or we don't have it and we need it

        // dependency is already queued up for install - ::Install will fail
        // instead we wait until the Job has finished. note that we
        // recall install on purpose in case prior installation failed
        if (CAddonInstaller::GetInstance().HasJob(addonID))
        {
          while (CAddonInstaller::GetInstance().HasJob(addonID))
            Sleep(50);

          if (!CAddonMgr::GetInstance().IsAddonInstalled(addonID))
          {
            CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to install dependency %s", m_addon->ID().c_str(), addonID.c_str());
            ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
            return false;
          }
        }
        // don't have the addon or the addon isn't new enough - grab it (no new job for these)
        else if (IsModal())
        {
          RepositoryPtr repoForDep;
          AddonPtr addon;
          std::string hash;
          if (!CAddonInstallJob::GetAddonWithHash(addonID, repoForDep, addon, hash))
          {
            CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to find dependency %s", m_addon->ID().c_str(), addonID.c_str());
            ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
            return false;
          }

          CAddonInstallJob dependencyJob(addon, repoForDep, hash, false);

          // pass our progress indicators to the temporary job and don't allow it to
          // show progress or information updates (no progress, title or text changes)
          dependencyJob.SetProgressIndicators(GetProgressBar(), GetProgressDialog(), false, false);

          if (!dependencyJob.DoModal())
          {
            CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to install dependency %s", m_addon->ID().c_str(), addonID.c_str());
            ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
            return false;
          }
        }
        else if (!CAddonInstaller::GetInstance().InstallOrUpdate(addonID, false))
        {
          CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to install dependency %s", m_addon->ID().c_str(), addonID.c_str());
          ReportInstallError(m_addon->ID(), m_addon->ID(), g_localizeStrings.Get(24085));
          return false;
        }
      }
    }

    if (ShouldCancel(std::distance(deps.begin(), it), totalSteps))
      return false;
  }

  SetText(g_localizeStrings.Get(24086));
  SetProgress(0);

  CFilesystemInstaller fsInstaller;
  if (!fsInstaller.InstallToFilesystem(installFrom, m_addon->ID()))
  {
    ReportInstallError(m_addon->ID(), m_addon->ID());
    return false;
  }

  SetProgress(100);

  return true;
}