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 }