summaryrefslogtreecommitdiff
path: root/apt-pkg/depcache.cc
Commit message (Collapse)AuthorAgeFilesLines
* 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
* Propagate protected to already satisfied dependenciesDavid Kalnischkies2020-05-181-33/+36
| | | | | | | | The previous commit deals with negative, now we add the positive side of things as well which makes this a recursive endevour. As we can push the protected flag forward only if a single solution for a dependency exists it is easy for trees to not get it, so if resolving becomes difficult it won't help at all.
* Propagate protected to already satisfied conflictsDavid Kalnischkies2020-05-181-30/+82
| | | | | | | | | | | If we propagate protected e.g. due to a user request we should also act upon (at the moment) satisfied negative dependencies so that the resolver knows that installing this package later is not an option. That the problem resolver is trying bad solutions is a bug by itself which existed before and after and should be worked on. Closes: #960705
* Deal with protected solution providers firstDavid Kalnischkies2020-05-181-3/+6
| | | | | | | | For positive dependencies this isn't giving much as the dependency should already be satisfied by such a provider if its protectiveness would help, but it doesn't hurt to check them first and for negative dependencies it means that we check those first which are the most likely to fail to be removed – which is a good idea.
* Move the MarkInstall helpers into static functionsDavid Kalnischkies2020-05-181-59/+72
| | | | | | | | Reducing the scope of these helpers might allow us to move them elsewhere and share them or it is a rather pointless exercise, we will see where it leads us to later on. Gbp-Dch: Ignore
* Keep going if a dep is bad for user requests to improve errorsDavid Kalnischkies2020-05-181-18/+47
| | | | | | | | | | | | | | We exit early from installing dependencies of a package only if it is not a user request to avoid polluting the state with installs which might not be needed (or detrimental even) for alternative choices. We do continue with installing dependencies though if it is a user request as it will improve error reporting for apt and can even help aptitude not hang itself so much as we trim the problem space down for its resolver dealing with all the easy things. Similar things can be said about the testcase I have short-circuit previously… keep going test, do what you should do to report errors!
* Allow aptitude to MarkInstall broken packages via FromUserDavid Kalnischkies2020-05-081-5/+8
| | | | | | | | | | | | | | | | | | apt marks packages coming from the commandline among others as protected to ensure the various resolver parts do not fiddle with the state of these packages. aptitude (and potentially others) do not so the state is modified (to a Keep which for uninstalled means it is not going to be installed) due to being uninstallable before the call fails – basically reverting at least some state changes the call made before it realized it has to fail, which is usually a good idea, except if users expect you to not do it. They do set the FromUser option though which has beside controlling autobit also gained the notion of "the user is always right" over time and can be used for this one here as well preventing the state revert. References: 0de399391372450d0162b5a09bfca554b2d27c3d Reported-By: Jessica Clarke <jrtc27@debian.org> on IRC
* Protect a package while resolving in MarkInstallDavid Kalnischkies2020-04-271-8/+27
| | | | | | | | Strange things happen if while resolving the dependencies of a package said dependencies want to remove the package. The allow-scores test e.g. removed the preferred alternative in favor of the last one now that they were exclusive. In our or-group for Recommends we would "just" not statisfy the Recommends and for Depends we engage the ProblemResolver…
* Prefer upgrading installed orgroup membersDavid Kalnischkies2020-04-271-50/+48
| | | | | | | | In normal upgrade scenarios this is no problem as the orgroup member will be marked for upgrade already, but on a not fully upgraded system (or while you operate on a different target release) we would go with our usual "first come first serve" approach which might lead us to install another provider who comes earlier – bad if the providers conflict.
* Propagate Protected flag to single-option dependenciesDavid Kalnischkies2020-04-271-4/+20
| | | | | | | | | | | | | | | If a package is protected and has a dependency satisfied only by a single package (or conflicts with a package) this package must be part of the solution and so we can help later actions not exploring dead ends by propagating the protected flag to these "pseudo-protected" packages. An (obscure) bug this can help prevent (to some extend) is shown in test-apt-never-markauto-sections by not causing irreversible autobit transfers. As a sideeffect it seems also to help our crude ShowBroken to display slightly more helpful messages involving the packages which are actually in conflict.
* Fail earlier on impossible Conflicts in MarkInstallDavid Kalnischkies2020-04-271-16/+23
| | | | | | | | MarkDelete is not recursive as MarkInstall is and we can not conflict with ourselves anyhow, so we can move the unavoidable deletes before changing the state of the package in question avoiding the need for the state update in case of conflicts we can not deal with (e.g. the package conflicts with an explicit user request).
* Split up MarkInstall into private helper methodsDavid Kalnischkies2020-04-271-64/+101
| | | | | Should be easier to move the code bits around then and it helps in documenting a bit what the blocks do and how they interact (or not).
* Discard candidate if its dependencies can't be satisfiedDavid Kalnischkies2020-04-271-0/+17
| | | | | | We do pretty much the same in IsInstallOk, but here we have already set the state, so we have to unroll the state as well to sort-of replicate the state we were in before this MarkInstall failed.
* Refactor and reorder MarkInstall codeDavid Kalnischkies2020-04-271-134/+145
| | | | | | | This fixes no bugs per se, but the idea is to delay more costly changes and check easier things first. It e.g. inhibits the moving of the autobit until we are sure that this MarkInstall call isn't going to fail (e.g. because a dependency isn't satisfiable).