/* * Copyright 2018-2025, Andrew Lindesay . * All rights reserved. Distributed under the terms of the MIT License. * * Note that this file included code earlier from `MainWindow.cpp` and * copyrights have been latterly been carried across in 2021. */ #include "PopulatePkgSizesProcess.h" #include #include "Logger.h" #include "PackageKitUtils.h" #include "PackageUtils.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "PopulatePkgSizesProcess" PopulatePkgSizesProcess::PopulatePkgSizesProcess(Model* model) : fModel(model), fProgress(0) { } PopulatePkgSizesProcess::~PopulatePkgSizesProcess() { } const char* PopulatePkgSizesProcess::Name() const { return "PopulatePkgSizesProcess"; } const char* PopulatePkgSizesProcess::Description() const { return B_TRANSLATE("Populating package sizes"); } float PopulatePkgSizesProcess::Progress() { return fProgress; } status_t PopulatePkgSizesProcess::RunInternal() { int32 countPkgs; int32 countPkgSized = 0; int32 countPkgUnsized = 0; HDINFO("[%s] will populate size for pkgs without a size", Name()); const std::vector packages = _SnapshotOfPackages(); std::vector updatedPackages; countPkgs = static_cast(packages.size()); for (int32 i = 0; i < countPkgs; i++) { PackageInfoRef package = packages[i]; const char* packageName = package->Name().String(); if (!package.IsSet()) HDFATAL("package is not set"); PackageLocalInfoRef localInfo = package->LocalInfo(); if (_ShouldDeriveSize(localInfo)) { off_t derivedSize = _DeriveSize(package); if (derivedSize > 0) { PackageLocalInfoBuilder localInfoBuilder; if (localInfo.IsSet()) localInfoBuilder = PackageLocalInfoBuilder(localInfo); localInfoBuilder.WithSize(derivedSize); PackageLocalInfoRef localInfo = localInfoBuilder.BuildRef(); updatedPackages.push_back( PackageInfoBuilder(package).WithLocalInfo(localInfo).BuildRef()); countPkgSized++; HDDEBUG("[%s] did derive a size for package [%s]", Name(), packageName); } else { countPkgUnsized++; HDDEBUG("[%s] unable to derive a size for package [%s]", Name(), packageName); } } _SetProgress(static_cast(i) / static_cast(countPkgs)); } fModel->AddPackagesWithChange(updatedPackages, PKG_CHANGED_LOCAL_INFO); _SetProgress(1.0); HDINFO("[%s] did populate size for %" B_PRId32 " packages with %" B_PRId32 " already having a size and %" B_PRId32 " unable to derive a size", Name(), countPkgSized, countPkgs - (countPkgSized + countPkgUnsized), countPkgUnsized); return B_OK; } const std::vector PopulatePkgSizesProcess::_SnapshotOfPackages() const { return fModel->Packages(); } bool PopulatePkgSizesProcess::_ShouldDeriveSize(PackageLocalInfoRef localInfo) const { if (!localInfo.IsSet()) return true; if (localInfo->Size() > 0) return false; PackageState state = localInfo->State(); return state == ACTIVATED || state == INSTALLED; } off_t PopulatePkgSizesProcess::_DeriveSize(const PackageInfoRef package) const { BPath path; if (PackageKitUtils::DeriveLocalFilePath(package, path) == B_OK) { BEntry entry(path.Path()); struct stat s = {}; if (entry.GetStat(&s) == B_OK) return s.st_size; else HDDEBUG("unable to get the size of local file [%s]", path.Path()); } else { HDDEBUG("unable to get the local file of package [%s]", package->Name().String()); } return 0; } void PopulatePkgSizesProcess::_SetProgress(float value) { if (!_ShouldProcessProgress() && value != 1.0 && (value - fProgress) < 0.1) return; fProgress = value; _NotifyChanged(); }