reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

synchronize.cpp (2983B)


      1 /* ReaPack: Package manager for REAPER
      2  * Copyright (C) 2015-2025  Christian Fillion
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU Lesser General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 #include "task.hpp"
     19 
     20 #include "config.hpp"
     21 #include "download.hpp"
     22 #include "filesystem.hpp"
     23 #include "index.hpp"
     24 #include "reapack.hpp"
     25 #include "transaction.hpp"
     26 
     27 SynchronizeTask::SynchronizeTask(const Remote &remote, const bool stale,
     28     const bool fullSync, const InstallOpts &opts, Transaction *tx)
     29   : Task(tx), m_remote(remote), m_indexPath(Index::pathFor(m_remote.name())),
     30     m_opts(opts), m_stale(stale), m_fullSync(fullSync)
     31 {
     32 }
     33 
     34 bool SynchronizeTask::start()
     35 {
     36   const auto &netConfig = g_reapack->config()->network;
     37 
     38   time_t mtime = 0, now = time(nullptr);
     39   FS::mtime(m_indexPath, &mtime);
     40 
     41   const time_t threshold = netConfig.staleThreshold;
     42   if(!m_stale && mtime && (!threshold || mtime > now - threshold))
     43     return true;
     44 
     45   auto dl = new FileDownload(m_indexPath, m_remote.url(),
     46     netConfig, Download::NoCacheFlag);
     47   dl->setName(m_remote.name());
     48 
     49   dl->onFinishAsync >> [=] {
     50     if(dl->save())
     51       tx()->receipt()->setIndexChanged();
     52   };
     53 
     54   tx()->threadPool()->push(dl);
     55   return true;
     56 }
     57 
     58 void SynchronizeTask::commit()
     59 {
     60   if(!FS::exists(m_indexPath))
     61     return;
     62 
     63   const IndexPtr &index = tx()->loadIndex(m_remote); // TODO: reuse m_indexPath
     64   if(!index || !m_fullSync)
     65     return;
     66 
     67   for(const Package *pkg : index->packages())
     68     synchronize(pkg);
     69 
     70   if(m_opts.promptObsolete && !m_remote.isProtected()) {
     71     for(const auto &entry : tx()->registry()->getEntries(m_remote.name())) {
     72       if(!entry.test(Registry::Entry::PinnedFlag) &&
     73           !index->find(entry.category, entry.package))
     74         tx()->addObsolete(entry);
     75     }
     76   }
     77 }
     78 
     79 void SynchronizeTask::synchronize(const Package *pkg)
     80 {
     81   const auto &entry = tx()->registry()->getEntry(pkg);
     82 
     83   if(!entry && !m_opts.autoInstall)
     84     return;
     85 
     86   const bool pres = m_opts.bleedingEdge || entry.test(Registry::Entry::BleedingEdgeFlag);
     87   const Version *latest = pkg->lastVersion(pres, entry.version);
     88 
     89   if(!latest)
     90     return;
     91 
     92   if(entry.version == latest->name()) {
     93     if(FS::allExists(latest->files()))
     94       return; // latest version is really installed, nothing to do here!
     95   }
     96   else if(entry.test(Registry::Entry::PinnedFlag) || latest->name() < entry.version)
     97     return;
     98 
     99   tx()->install(latest, entry, entry.flags);
    100 }