summaryrefslogtreecommitdiff
path: root/apt-pkg/depcache.cc
Commit message (Collapse)AuthorAgeFilesLines
* Fix Phased-Update-Percentage probability mistakeAnders Kaseorg2026-04-071-2/+2
| | | | | | | | | | | | | | | | | | Previously a package with Phased-Update-Percentage: n would be updated with probability (n + 1)/101 instead of n/100. For example, a package with Phased-Update-Percentage: 0 could still be updated even though it shouldn’t, and a package with Phased-Update-Percentage: 1 would be installed almost twice as much as it should be. Correct the erroneous math. Note that libstdc++ implements std::uniform_int_distribution in such a way that for a given seed, changing dist(0, 100) to dist(0, 99) has the effect of decreasing each sample by 0 or 1; therefore, this patch will not randomly trigger extra phased updates that had previously been excluded. Fixes: c5bc86d45e003905ef411146e66b414d26fb1ff8 Signed-off-by: Anders Kaseorg <andersk@mit.edu>
* Introduce JSONL performance counter loggingJulian Andres Klode2026-02-101-0/+2
| | | | | | | | Introduce a scoped object that starts measuring performance counters and then dumps them into a JSONL file for later analysis. Add performance contexts for APT::Solver and pkgDepCache::Init() as starting points.
* Revert "depcache: Allow changing multi-arch versions for removed siblings"Julian Andres Klode2025-10-261-4/+0
| | | | | | | | | | | | | | | | This reverts commit 74636b64a7ee56637a3ce4ddc1d060ca9f8b77e1. Adjust the test case accordingly, as it is no longer possible to install libgcc-s1:s390x. We need to sort this out in the ToDepCache translation layer at a later time. Sadly the depcache rejects valid solutions like this; solving this isn't trivial. Technically we need to split up the FromUser and auto-bit handling to solve this, but even then, MarkDelete() with FromUser=0 moves the auto-bit on metapackages; this doesn't happen when doing FromUser=1, so we can't always do FromUser=1. Fixes: a3fca052ca21ad222ac7f2fdd7f3fe84b44beb60
* depcache: Allow changing multi-arch versions for removed siblingsJulian Andres Klode2025-10-251-0/+4
| | | | | Do not prevent us from changing the version of a foreign package because a sibling that is being removed has a different candidate.
* depcache: Add a new UpgradeCount() memberJulian Andres Klode2025-03-091-0/+16
|
* Introduce pkgDepCache::Transaction for transactional depcache updatesJulian Andres Klode2025-03-091-0/+71
|
* refactor: Deduplicate and Move SectionInSubTree to ConfigurationJulian Andres Klode2025-02-181-38/+4
| | | | | Deduplicate the copies in a central one, mark it unavailable to external users.
* solver3: Defer 3.0 'deep' autoremoval to 3.1, fix autoremoveJulian Andres Klode2025-02-141-1/+1
| | | | | | Restore the depcache's MarkRequired logic for 3.0 solver; and change the MarkInstall() call to pass a more correct value for FromUser, to not override an existing automatic status.
* Measure BootSize as integerJulian Andres Klode2025-02-031-2/+2
| | | | I don't know why I used a double here this is awkward.
* Correctly calculate kernel size in /bootJulian Andres Klode2025-02-031-32/+25
| | | | | | | | | | | | Change the code to get the size from the existing vmlinuz, rather than using the package size, which only worked in Ubuntu, and possibly not on all kernel packages either. Refactor the code a bit to avoid the nested if as well, and use off_t to measure and sum the sizes before switching to floating point. Closes: #1085184
* Drop usage of macro APT_OVERRIDE for simple overrideDavid Kalnischkies2025-01-051-2/+2
| | | | | | | | | We were rather inconsistent in using it and as our public headers contain deduction guides (a c++17 feature) it seems silly to try to hide a c++11 feature in a macro, so lets stop this charade and drop the macro and while we are changing all these lines lets apply [[nodiscard]] (another c++17 feature) and other suggestions from clang-tidy and formatting for a little more consistency.
* Do not mark new if we have already installed providersDavid Kalnischkies2024-05-161-0/+19
| | | | | | | | | | | The test is actually documenting another bug hidden a bit by this one as we do not need to install a NEW package in this situation as the upgrade needing it was kept back, but it was protected from considering it to be autoremoveable as all providers tend to be considered protected, but by limiting us to installed providers if we have some we can drag those new packages out of hiding. Now, we "just" have to get right of the NEW package in a next step.
* Do not upgrade rev-deps ear-marked for removalDavid Kalnischkies2024-04-241-2/+5
| | | | | | | | | | | | We schedule reverse dependencies for an upgrade, but we shouldn't do it if we have ear-marked this package for removal later on. Usually the solver will end up doing the right thing like it already did in the included testcase in the end, but given that before it reaches the right end it explored a bad path which can lead to more installs and removals influencing later decisions or are just too hard for the resolver to undo later on, we can just not explore this path to begin with. References: e077370ffcb3669a50a600e80356c2002e6b176d
* Show space estimate for /boot, if separate; or estimate initrd for /usrJulian Andres Klode2024-04-131-0/+56
| | | | | | | | | Calculate an estimate of 110% of the biggest initrd + system.map as the additional space a kernel needs in /boot. If /boot is a different file system than /usr, print the size of the kernels + the additional space they will need separately; otherwise include it in our /usr figure.
* Modernize standard library includesJulian Andres Klode2024-02-201-2/+2
| | | | | | This was automated with sed and git-clang-format, and then I had to fix up the top of policy.cc by hand as git-clang-format accidentally indented it by two spaces.
* Add public phased update APIJulian Andres Klode2024-02-131-2/+53
| | | | | | | | | | | | | | | | This moves the functions of the PhasedUpgrader class into various other classes so they can be publicly exposed. This introduces three new functions: pkgDepCache::PhasingApplied() tells you whether phasing should be applied to the package. pkgProblemResolver::KeepPhasedUpdates() keeps back updates that have phasing applied. pkgCache::VerIterator::IsSecurityUpdate() determines whether this version contains security fixes.
* Use a more gitignore style matchingJulian Andres Klode2023-02-271-2/+2
| | | | | | | | Use a rightmost match for / so that if we end up with a Section: a/b/c, a 'c' matcher still matches. If the section does not contain any /, it can be matched using /pattern, e.g. /c only matches Section: c, but not Section: a/b/c.
* Have values in Section config trees refer to them in all componentsDavid Kalnischkies2023-01-301-12/+26
| | | | | | | | | | | | | | | | | | Hard coding each and every component is not only boring but given that everyone is free to add or use more we end up in situations in which apt behaves differently for the same binary package just because metadata said it is in different components (e.g. non-free vs. non-free-firmware). It is also probably not what the casual user would expect. So we instead treat a value without a component as if it applies for all of them. The previous behaviour can be restored by prefixing the value with "<undefined>/" as in the component is not defined. In an ideal world we would probably use "*/foo" for the new default instead of changing the behaviour for "foo", but it seems rather unlikely that the old behaviour is actually desired. All existing values were duplicated for all (previously) known components in Debian and Ubuntu.
* Add flag to disable upgrade by source and test caseJulian Andres Klode2022-07-241-0/+4
|
* Avoid recursion by looping of other binaries twiceJulian Andres Klode2022-07-241-1/+7
| | | | | | | | First mark them for upgrade without autoInst, so we don't call their "mark other binaries loop"; then call them again with it. Without this change, each binary package would upgrade the next one in the list, recursively.
* Upgrade all binaries in a source packageJulian Andres Klode2022-07-241-0/+27
| | | | | | | | | Schedule all other binaries in the source package for upgrade if the candidate version belongs to the same source version as the package we are upgrading. This will significantly reduce the risk of partial upgrades and should make life a lot easier.
* Mark broken reverse depends for upgradeJulian Andres Klode2022-07-111-0/+34
| | | | | | | | | | | | Currently the solver handles cases where a Breaks b (<< 1) and if we install that a, upgrades b. However, where b Depends a (= 1), b was removed again. This addresses the problem by iterating over installed reverse dependencies of upgrades and upgrading them so that both cases work roughly similarly. LP: #1974196
* Use pkgTagSection::Key in more places in src:aptDavid Kalnischkies2022-04-011-4/+5
| | | | | | | | | | The speed critical paths were converted earlier, but the remaining could benefit a tiny bit from this as well especially as we have the facility now available and can therefore brush up the code in various places in the process as well. Also takes the time to add the hidden Exists method advertised in the headers, but previously not implemented.
* Avoid using unqualified make_pair potentially triggering ftbfsDavid Kalnischkies2022-03-211-1/+1
| | | | | | | | If the includes are slightly changed, we end with an error here: apt/apt-pkg/depcache.cc:2059:31: error: ‘make_pair’ was not declared in this scope; did you mean ‘std::make_pair’? Yes, we mean std::make_pair, but we can avoid the explicit call altogether by using emplace_back instead of push_back.
* Spelling fixesVille Skyttä2021-11-271-24/+24
|
* Do not remove Essential/Protected due to dependenciesJulian Andres Klode2021-11-171-0/+18
| | | | | | | | Suggesting the removal of Essential and Protected packages as a solution leads to situations where YouTubers end up removing their desktop. Let's not remove such packages ourselves.
* Increase recursion limits from 100 to 3000David Kalnischkies2021-08-291-4/+4
| | | | | | | | | | | | | | | | | | | If you install dpkg on an empty status file with all recommends and suggests apt wants to install 4000+ packages. The deepest chain seemingly being 236 steps long. And dpkg isn't even the worst (~259). That is a problem as libapt has a hardcoded recursion limit for MarkInstall and friends … set to 100. We are saved by the fact that chains without suggests are much shorter (dpkg has 5, max seems ~43), but I ignored Conflicts in these chains, which typically trigger upgrades, so if two of the worst are chained together we suddenly get dangerously close to the limit still. So, lets just increase the limit into oblivion as it is really just a safety measure we should not be running into to begin with. MarkPackage was running years without it after all. 3000 is picked as a nice number as any other and because it is roughly the half of the stack crashs I saw previously in this branch.
* Stop autoremover from endlessly exploring cyclic providersDavid Kalnischkies2021-08-281-1/+1
| | | | | | | | | | | | | | | | | | | | fullyExplored is needed to keep track of having explored all providers of a package name, while Marked is tracking if we have explored a given real package (along its chosen version), so we should stop MarkPackage from exploring a (real) package if it is marked and let fullyExplored only guard the looping over the individual dependencies. The testcase is deceptively simple, but in practice only an ecosystem like rust who makes heavy use of cyclic dependency relations intermixed with versioned provides actually triggers this as seen by the buggy code being in use for four months in Debian and Ubuntu development releases. (easier to trigger if most packages are marked manual installed) Note that the testcase is successful already due to the earlier changes as we exit the recursion eventually and all packages are marked as they need to be already, but this fix does work standalone as well. Closes: #992993
* Don't venture too deeply in AutoRemovers MarkPackageDavid Kalnischkies2021-08-281-9/+16
| | | | | | MarkInstall has the same depth limit, so lets use this arbitrary limit to avoid trying to hard as that usually means we will never stop – at least not until we crash, which is not a very good error case.
* Move hidden MarkPackage to a static functionDavid Kalnischkies2021-08-281-88/+93
| | | | | | | | | | We can't have external users as its marked hidden and as we don't even have users outside of pkgDepCache itself we can remove the function completely from the public eye. That adds many new parameters, but it also allows to add a few more like avoiding constantly checking the debug config value. Gbp-Dch: Ignore
* Simplify selection of highest source version providersDavid Kalnischkies2021-08-281-6/+3
| | | | | | | | | The old code is a bit longer and does a sort (N*log(N)) + find (at most N) It is replaced by max_element (N) + remove_if (N). The practical difference is minimal as the N we operate on is rather small, but the replacement is hopefully easier to understand at a glance as well. Gbp-Dch: Ignore
* Store versioned kernel package detectors in d-pointerDavid Kalnischkies2021-04-261-8/+8
| | | | | | | They are kinda costly, so it makes more sense to keep them around in private storage rather than generate them all the time in the MarkPackage method. We do keep them lazy through as we have that implemented already.
* Call MarkAndSweep only manually in apt-get for autoremoveDavid Kalnischkies2021-04-261-15/+19
| | | | | | | | | | | | | | | | | | | | | | | An interactive tool like aptitude needs these flags current far more often than we do as a user can see them in apt only in one very well defined place – the autoremove display block – so we don't need to run it up to four times while a normal "apt install" is processed as that is just busywork. The effect on runtime is minimal, as a single run doesn't take too long anyhow, but it cuts down tremendously on debug output at the expense of requiring some manual handholding. This is opt-in so that aptitude doesn't need to change nor do we need to change our own tools like "apt list" where it is working correctly as intended. A special flag and co is needed as we want to prevent the ActionGroup inside pkgDepCache::Init to be inhibited already so we need to insert ourselves while the DepCache is still in the process of being built. This is also the reason why the debug output in some tests changed to all unmarked, but that is fine as the marking could have been already obsoleted by the actions taken, just inhibited by a proper action group.
* Reexplore providers of marked packages if some didn't satisfy beforeDavid Kalnischkies2021-04-261-78/+82
| | | | | | | | | | | | | | | | The autoremove algorithm would mark a package previously after exploring it once, but it could have been that it ignored some providers due to them not satisfying the (versioned) dependency. A later dependency which they might satisfy would encounter the package as already marked and hence doesn't explore the providers anymore leaving us with internal errors (as in the contrived new testcase). This is resolved by introducing a new flag denoting if we explored every provider already and only skip exploring if that is true, which sounds bad but is really not such a common occurrence that it seems noticeable in practice. It also helps us marking virtual packages as explored now which would previously be tried each time they are encountered mostly hiding this problem for the (far more common) fully virtual package.
* Mark only provides from protected versioned kernel packagesDavid Kalnischkies2021-04-251-26/+58
| | | | | | | | | | | | | | | | An out-of-tree kernel module which doesn't see many new versions can pile up a considerable amount of packages if it is depended on via another packages (e.g.: v4l2loopback-utils recommends v4l2loopback-modules) which in turn can prevent the old kernels from being removed if they happen to have a dependency on the images. To prevent this we check if a provider is a versioned kernel package (like an out-of-tree module) and if so check if that module package is part of the protected kernel set – if not it is probably good to go. We only do this if at least one provider is from a protected kernel though so that the dependency remains satisfied (this can happen e.g. if the module is currently not buildable against a protected kernel).
* Do not make DefaultRootSetFunc2 public symbolJulian Andres Klode2021-02-121-1/+1
|
* Show 'Done' always for 'Building dependency tree'David Kalnischkies2021-02-041-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | For years I subconsciously thought this is wrong but ignored it: $ LANG=C apt install -s Reading package lists... Done Building dependency tree Reading state information... Done Then I noticed: $ LANG=C apt install -s -o dir::state::extended_states=/dev/null Reading package lists... Done Building dependency tree... Done That can't be! Then it really should be: $ LANG=C apt install -s Reading package lists... Done Building dependency tree... Done Reading state information... Done This oddity seems to be in since the introduction of the auto bit in 2005 which makes this rather hard to solve in theory, but in practice no front end seems to call the readStateFile method directly, so we might actually be lucky. The alternative would be to call Done in the calling method and again at the end of readStateFile while dropping it from the current place, but as that is more shuffling around it could be more upsetting for other front ends. Not sure, but now that I have seen it, I want to have it fixed one way or another… aptitude at least seems not to explode. References: afb1e2e3bb580077c6c917e6ea98baad8f3c39b3
* Determine autoremovable kernels at run-timeJulian Andres Klode2021-01-041-6/+24
| | | | | | | | | | | | | | | | | | | | | | | Our kernel autoremoval helper script protects the currently booted kernel, but it only runs whenever we install or remove a kernel, causing it to protect the kernel that was booted at that point in time, which is not necessarily the same kernel as the one that is running right now. Reimplement the logic in C++ such that we can calculate it at run-time: Provide a function to produce a regular expression that matches all kernels that need protecting, and by changing the default root set function in the DepCache to make use of that expression. Note that the code groups the kernels by versions as before, and then marks all kernel packages with the same version. This optimized version inserts a virtual package $kernel into the cache when building it to avoid having to iterate over all packages in the cache to find the installed ones, significantly improving performance at a minor cost when building the cache. LP: #1615381
* depcache: Cache our InRootSetFuncJulian Andres Klode2021-01-041-7/+19
| | | | | This avoids the cost of setting up the function every time we mark and sweep.
* Merge branch 'master' into 'master'Julian Andres Klode2020-08-041-1/+2
|\ | | | | | | | | Support marking all newly installed packages as automatically installed See merge request apt-team/apt!110
| * Support marking all newly installed packages as automatically installedNicolas Schier2020-06-081-1/+2
| | | | | | | | | | | | | | Add option '--mark-auto' to 'apt install' that marks all newly installed packages as automatically installed. Signed-off-by: Nicolas Schier <nicolas@fjasle.eu>
* | Filter out impossible solutions for protected propagationDavid Kalnischkies2020-07-021-3/+18
| | | | | | | | | | | | | | | | If the package providing the given solution is tagged already for removal (or at least for "not installing") we can ignore this solution as a possibility as it is not one, which means we can avoid exploring the option and potentially forward the protected flag further if that helps in reducing the possibilities to a single one.
* | Delay removals due to Conflicts until Depends are resolvedDavid Kalnischkies2020-07-021-76/+101
|/ | | | | | | | | | | | | | | | | Marking a package for removal is fine if we know that we have to remove that package, but if we are in an alternative branch we might not go this route in the end and hence have a package pointlessly marked for removal which isn't questioned later on. We check if we are allowed to remove that package to avoid working on the positive dependencies if not, but we mark them for removal only after all the other dependencies are successfully resolved. In an ideal world we would let the problemResolver do its job on them, but the resolver might decide against doing the removal exploring another option like the next alternative, which might be a good idea, but is not the behaviour we had before, so that is the best we can do for now without changing the resolver drastically.
* Deal with duplicates in the solution space of a depDavid Kalnischkies2020-06-031-22/+27
| | | | | | | | | | | | | While we process the possible solutions we might modify other solutions like discarding their candidates and such, so that then we reach them they might no longer be proper candidates. We also try to drop duplicates early on to avoid the simple cases of these which test-explore-or-groups-in-markinstall triggers via its explicit duplication but could also come via multiple provides. It only worked previously as were ignoring current versions which usually is okay expect if they are marked for removal and we want to reinstate them so the ProblemResolver can decide which one later on.
* Don't update candidate provides map if the same as currentDavid Kalnischkies2020-05-251-6/+6
|
* Don't set variables to conditionally override them 2 lines laterDavid Kalnischkies2020-05-251-5/+7
| | | | Gbp-Dch: Ignore
* Allow pkgDepCache to be asked to check internal consistencyDavid Kalnischkies2020-05-241-5/+88
| | | | | | | | For speed reasons pkgDepCache initializes its state once and then has a battery of update calls you have to invoke in the right order to update the various states – all in the name of speed. In debug and/or simulation mode we can sacrifice this speed for a bit of extra checking though to verify that we haven't made some critical mistake like #961266.
* Keep status number if candidate is discarded for kept back displayDavid Kalnischkies2020-05-231-0/+2
| | | | | | | | | | | | | | | | It looks like hack and therefore I wanted this to be a very isolated commit so we can find it & revert it easily if need be, but for now it seems to work. The idea is that Status is telling us how the candidate is in relation to the current installed version which is used to figure out if a package is "kept back" by the algorithm or not, but by discarding the candidate version we loose this information. Ideally we would keep better tabs on what we do to a package and why, but for now that seems okayish. It will cause the wrong version to be displayed though as if the package is installed the installed version becomes the candidate and hence (installed => installed) is displayed.
* Known-bad candidate versions are not an upgrade optionDavid Kalnischkies2020-05-231-1/+9
| | | | | | | | | | | | | If we have a negative dependency to deal with we prefer to install an upgrade rather than remove the current version. That is why we split the method rather explicitly in two in 57df273 but there is a case we didn't react to: If we have seen the candidate before as a "satisfier" of this negative dependency there is no point in trying to upgrade to it later on. We keep that info by candidate discard if we can, but even if we can't we can at least keep that info around locally. This "fixes" (or would hide) the problem described in 04a020d as well as you don't have to discard installations you never make.
* Reset candidate version explicitly for internal state-keepingDavid Kalnischkies2020-05-231-12/+16
| | | | | | | | | | | | | | | | | | | | | | | | For a (partially) installed package like the one MarkInstall operates on at the moment we want to discard the candidate from, we have to first remove the package from the internal state keeping to have proper broken counts and such and only then reset the candidate version which is a trivial operation in comparison. Take a look at the testcase: Now, what is the problem? Correct, git:i386. Didn't see that coming, right? It is M-A:foreign so apt tries to switch the architecture of git here (which is pointless, it knows that this won't work, but lets fix that in another commit) will eventually realize that it can't install it and wants to discard the candidate of git:i386 first removing the broken indication like it should, removing the install flag and then reapplies the broken indication: Expect it doesn't as it wants to do that over the candidate version which the package no longer had so seemingly nothing is broken. It is a bit of a hairball to figure out which commit it is exactly that is wrong here as they are all influencing each other a bit, but >= 2.1 is an acceptable ballpark. Bisect says 57df273 but that is mostly a lie. Closes: #961266