summaryrefslogtreecommitdiff
path: root/apt-pkg
Commit message (Collapse)AuthorAgeFilesLines
* Add history undo, redo, and rollback featuresSimon Johnsson2025-10-022-11/+51
|
* History Command and ParsingSimon Johnsson2025-09-262-0/+270
|
* edsp: Do not skip lines (fixes Architecture reading)Julian Andres Klode2025-08-261-31/+31
| | | | | | | | | | | | | | | We skipped the Architecture: line because when the outer loop got to it, the inner loop started and read the next line after it. Get rid of the nested loop instead, and first run a loop to find the request line, and then a second loop to parse the request flags. An alternative would be to use a combined loop that supports non-compliant protocol implementations, but that's harder to read and we don't expect there to be any especially on the request side.
* edsp: Clear architecture cacheJulian Andres Klode2025-08-261-0/+4
| | | | We need to actually use the architecture values we set
* Fix indentation compiler warning with clangBiswapriyo Nath2025-08-261-2/+5
| | | | | | This commit fixes the following compiler warning. cacheiterators.h:423:54: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
* debListParser: Cache `essential` and `myArch` moreJulian Andres Klode2025-08-262-13/+10
| | | | | | | | | | | | | | | | | | | Lookup these variables in the constructor once, rather than once per package. This requires a bit of care as debListParser::UsePackage() defaults to "all" for essential when unset, hence we simply change its == "all" comparisons to == "all" || .empty().# This removes any per-paragraph configuration lookups from the file parser. Also parse myArch from ParseProvides down to ParseDepends() as that call ended up causing it to query APT::Architecture *again* since the function we call is static. Together, the removed config lookups safe about 2.3% of cache generation runtime.
* solver3: Allow any downloadable version to mark a package as not obsoleteJulian Andres Klode2025-08-261-3/+8
| | | | | | | | | | | | Lots of people have pinned an older version that is no longer installable, or more common yesterday, we saw a lot of people who seemingly manually installed a newer version of a deb than in the repositories, causing the package to be considered obsolete, which does not make much sense. Oops: 4c39d922-410f-11f0-bbf9-fa163ec44ecd Oops: a64054f6-4140-11f0-bbfd-fa163ec44ecd Oops: a32196c1-661d-11f0-a97c-fa163ec8ca8c
* solver3: Sort dependency targets against current alternativeJulian Andres Klode2025-08-261-4/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of inadvertently sorting dependency targets against the first alternative in an or group, sort them against the current alternative as we should. Otherwise we ended up sorting gnome-shell | notification-daemon With Package: notification-daemon Package: awesome Provides: notification-daemon into gnome-shell | awesome | notification-daemon <-we sorted this part wrongly-> This fixes a minor difference in test-release-candidate-switching in one case, but not the other where the difference was actually caused by the loss of install argument ordering information in the new solver, so just flip the arguments so both solvers produce the same outcome.
* Fix stuck acquire queues on partial server errorsJulian Andres Klode2025-06-241-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a server responds with two InRelease files, but one is good, and the other indicates a temporary error, we queued the other indices from the good repository for downloading and then queued the retry. The resulting queue ended up with items having fetchAfter=0 before the item with fetchAfter=<something>, causing the Run() loop to not detect a stuck queue. Change the order of the queue such that the highest retry-after items comes first; this ensures that we always see stuck queues. This of course changes the behavior of retries in that if one file fails temporarily we block the entire server. This does seem more beneficial in the common case - if one file fails, probably all of them fail, and there's no point bombarding the server with requests for indices from good repositories until all have failed. The actual root cause is more that the remaining items are Enqueued like this: 1. Enqueue jammy/InRelease (delayed) 2. Enqueue jammy-updates/main all Packages The resulting queue ended up being: jammy-updates/main all Packages jammy/InRelease (delayed) But Enqueue() only calls Cycle() when there are no items in the queue already - after all, any item that is already running will call Cycle() eventually. Or so was the case until we added the retry-after handling. It's unclear why we don't Cycle() all the time when enqueuing a new item, given that our pipeline might not be filled yet, and we could send the request to the server while waiting for data on a running item. Trying to always Cycle() however led to regressions that still need investigating. Given that, this solution certainly is the more easy to reason about one. LP: #2003851
* Include standard headers to fix clang compiler errorBiswapriyo Nath2025-06-183-0/+3
| | | | | | | | This commit fixes the following compiler errors. apt-pkg/acquire.cc:833:51: error: no template named 'function' in namespace 'std' apt-pkg/contrib/error.cc:198:59: error: no member named 'front_inserter' in namespace 'std' apt-pkg/solver3.h:44:22: error: no template named 'is_trivially_constructible_v' in namespace 'std' methods/http.cc:1029:24: error: no member named 'inserter' in namespace 'std'
* solver3: Avoid FTBFS with g++ 14.2 on arm{el,hf}Julian Andres Klode2025-06-101-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With an explicit {} initialization, g++ 14.2 on armhf and armel seems to generate the default constructor for the vector too early, or in the first place, outside of solver3.cc where the constructor is defined. Without {}, this compiles again. In file included from /usr/include/c++/14/vector:66, from /<<PKGBUILDDIR>>/obj-arm-linux-gnueabihf/include/apt-pkg/cachefilter.h:14: /usr/include/c++/14/bits/stl_vector.h: In instantiation of ‘constexpr std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = APT::Solver::Work; _Alloc = std::allocator<APT::Solver::Work>]’: /usr/include/c++/14/bits/stl_vector.h:531:7: required from here 531 | vector() = default; | ^~~~~~ /usr/include/c++/14/bits/stl_vector.h:369:49: error: invalid use of incomplete type ‘struct APT::Solver::Work’ 369 | _M_impl._M_end_of_storage - _M_impl._M_start); | ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ In file included from /<<PKGBUILDDIR>>/apt-pkg/edsp.cc:22: /<<PKGBUILDDIR>>/obj-arm-linux-gnueabihf/include/apt-pkg/solver3.h:87:11: note: forward declaration of ‘struct APT::Solver::Work’ 87 | struct Work; | ^~~~ /usr/include/c++/14/bits/stl_vector.h: In instantiation of ‘constexpr std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = APT::Solver::Solved; _Alloc = std::allocator<APT::Solver::Solved>]’: /usr/include/c++/14/bits/stl_vector.h:531:7: required from here 531 | vector() = default; | ^~~~~~ /usr/include/c++/14/bits/stl_vector.h:369:49: error: invalid use of incomplete type ‘struct APT::Solver::Solved’ 369 | _M_impl._M_end_of_storage - _M_impl._M_start); | ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ /<<PKGBUILDDIR>>/obj-arm-linux-gnueabihf/include/apt-pkg/solver3.h:88:11: note: forward declaration of ‘struct APT::Solver::Solved’ 88 | struct Solved; | ^~~~~~
* Avoid cast alignment warning in cache string viewJulian Andres Klode2025-06-101-1/+1
| | | | | | | | | | | | | | | | | | The cache allocates strings as uint16_t size; char content[]; char zero; Aligned to the uint16_t. When doing the casting, this causes a warning on some architectures that cannot do unaligned loads, such as armhf. Use __builtin_assume_aligned() to explictly say that the pointer is aligned to 16 bits. This is a bit of a backhanded approach, as the warning seems to be actually avoided by the function returning a void* rather than the assumed alignment, but this is very much self-documenting.
* solver3: Filter installed RecommendsJulian Andres Klode2025-06-101-0/+10
| | | | | | When inspecting Recommends of installed packages, filter them to the installed packages only, as we want to avoid switching between alternatives of recommended packages.
* solver3: Explicitly declare and define ~SolverJulian Andres Klode2025-06-102-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On recent armfhf and s390x builds in the PPA, the compiler seems to have generated the destructor at the wrong point where the definitions where not yet complete, and it does seem ill-advised to rely on a default-constructed destructor in the solver for future ABI sake. In file included from /usr/include/c++/14/vector:66, from /<<PKGBUILDDIR>>/obj-arm-linux-gnueabihf/include/apt-pkg/cachefilter.h:14: /usr/include/c++/14/bits/stl_vector.h: In instantiation of ‘constexpr std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = APT::Solver::Work; _Alloc = std::allocator<APT::Solver::Work>]’: /usr/include/c++/14/bits/stl_vector.h:531:7: required from here 531 | vector() = default; | ^~~~~~ /usr/include/c++/14/bits/stl_vector.h:369:49: error: invalid use of incomplete type ‘struct APT::Solver::Work’ 369 | _M_impl._M_end_of_storage - _M_impl._M_start); | ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ In file included from /<<PKGBUILDDIR>>/apt-pkg/edsp.cc:22: /<<PKGBUILDDIR>>/obj-arm-linux-gnueabihf/include/apt-pkg/solver3.h:87:11: note: forward declaration of ‘struct APT::Solver::Work’ 87 | struct Work; | ^~~~ /usr/include/c++/14/bits/stl_vector.h: In instantiation of ‘constexpr std::_Vector_base<_Tp, _Alloc>::~_Vector_base() [with _Tp = APT::Solver::Solved; _Alloc = std::allocator<APT::Solver::Solved>]’: /usr/include/c++/14/bits/stl_vector.h:531:7: required from here 531 | vector() = default; | ^~~~~~ /usr/include/c++/14/bits/stl_vector.h:369:49: error: invalid use of incomplete type ‘struct APT::Solver::Solved’ 369 | _M_impl._M_end_of_storage - _M_impl._M_start); | ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ /<<PKGBUILDDIR>>/obj-arm-linux-gnueabihf/include/apt-pkg/solver3.h:88:11: note: forward declaration of ‘struct APT::Solver::Solved’ 88 | struct Solved; | ^~~~~~
* solver3: Ignore Architecture: all for obsoleted-byJulian Andres Klode2025-06-101-1/+3
| | | | | | | | | | | | In case a new version of the source package is published, we check that if there's a newer binary for the same architecture and then consider the binary obsoleted. This logic did not properly account for Architecture: all packages which are considered as native architecture package with an "All" multi-arch flag set, and hence a native architecture package may inadvertently be considered obsoleted by a package that only built on Architecture: all.
* solver3: Only merge dependencies on the same packageJulian Andres Klode2025-05-281-6/+14
| | | | | Avoid or groups and dependencies on different (virtual) packages, to avoid some common pitfalls like the added xorg test case.
* solver3: Merge Depends into RecommendsJulian Andres Klode2025-05-271-7/+23
| | | | | | | | | | | | | | | | | | | | | | | Merge any hard clauses into optional clauses, such that optional clauses don't end up with more choices. For example if you have Depends: a | b Recommends: a | c This becomes: Depends: a | b Recommends: a We have simulated this with the chaos-actor in the test case and a Depends: git (not satisfied by chaos provider) Recommends: git (satisfied by chaos provider) and the latter constraint is limited to the former.
* solver3: Merge intersecting dependenciesJulian Andres Klode2025-05-272-6/+49
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If a package declares multiple dependencies that can be solved by the same packages we should use the common set of packages to solve them. A common example is requiring the same Debian source version, or the same upstream version as in our test case: git-ng Depends: git (>> 1:2.26.2), git (<< 1:2.26.2-.) The solver expands this to the concrete objects: git-ng Depends: "real git" (= 1:2.26.2-1) | chaos-actor, "real git" (= 1:2.26.2-1) | "real git" (= 1:2.25.1-1) When given an upgrade request, the solver would now choose chaos-actor to satisfy git (>> 1:2.26.2) "real git" (= 1:2.25.1-1) to satisfy git (<< 1:2.26.2-.) To satisfy the two constraints, which is not the intended outcome. Address this problem by introducing a concept of merged clauses: If two dependencies of a package have overlapping solutions, replace the dependency by the intersection, and record the merged clause instead, this leads to a single clause: Depends: git (>> 1:2.26.2) and git (<< 1:2.26.2-.) which expands to just the real git binary. The implementation is a bit finicky in that it removes the variables from the original clause which may not be helpful for debugging, but it records the clauses merged with, as seen in the test case, so the reasoning is clear. LP: #2111792
* solver3: Assume manual packagesJulian Andres Klode2025-05-261-1/+16
| | | | | | | | | | | | | | | | | | | | If we have allowed the removal of manual packages, assume them all before starting the solver. This should ensure that as long as there is a solution that does not remove a manually installed package, it is found. This requires a sweeping set of changes in the test suite, but ensures that we get "safe" behavior from the solver. We have in particular seen that without asserting the installed packages, several people ended up with ubuntu-minimal and perl removed in a situation where that was not warranted, that is, they install winehq, and then pull in some new perl packages in a newer version than the installed one, and the solver chose to create a mismatched version set, which then caused the main perl package to not be installable. Oops: 1b55173a-3526-11f0-b7ac-fa163e171f02 Oops: dbd5149e-36b9-11f0-bb74-fa163ec44ecd
* solver3: Initialize startTime if not set in Pop()Julian Andres Klode2025-05-262-1/+3
| | | | | | | | If the user pushes Assumptions that fail, we could inadvertently timeout during the Pop() as the variable was not initialized. Always initialize it to 0, and if we haven't set an actual time by the time we Pop() set it there.
* solver3: Allow CompareProviders3 with empty packageJulian Andres Klode2025-05-261-1/+1
| | | | | | This can be used to compare arbitrary packages in non-dependency contexts. It remains to be seen whether this is a meaningful approach.
* solver3: If no choice was made nothing to invertJulian Andres Klode2025-05-261-1/+1
| | | | | | | | | We sometimes enqueue no choice as the choice, specifically when an optional clause became unsat as we need to reenqueue it on undo. But of course, this breaks undoing stuff because now it tries to insert !root and then solver breaks.
* solver3: Handle failed assumption in Pop()Julian Andres Klode2025-05-261-0/+7
| | | | | | | | | | | If an Assume() failed, we will have pushed the choices stack, but not actually pushed anything to the solved stack. This would cause a segmentation fault trying to read the referenced entry that doesn't actually exists, namely solved[solved.size()]. Handle this by exiting early as there's nothing to do except pop the entry back out of the array.
* solver3: Remove Work::choiceJulian Andres Klode2025-05-262-15/+7
| | | | | | | | | | | | Instead of having the historic choice here, follow MiniSAT and use the assigned variable from the tail. This should also make the Assume() function work now, albeit we still need to actually migrate to it. This is a first step towards refactoring the Solve() loop to use a propagate/find next literal/assume it kind of loop, albeit there is a bit more to prepare there as we need to also reinsert work items when backtracking.
* Fix error handling with getlineWalter Lozano2025-05-192-2/+2
| | | | | | | | | | | | | | The function getline is used to read data from different streams, however, the error handling is not accurate. From the man page, getline returns -1 on failure and sets errno accordingly, but the current implementation only checks errno to see if there was a failure. With this approach, in case getline returns success but also sets errno it is consider and error. Fix the issue but also checking the return value of getline. Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
* Introduce apt why, apt why-notJulian Andres Klode2025-05-192-0/+23
| | | | | | | | | | | These are implemented somewhat differently from aptitudes why and why-not commands: They produce the actual solver trace for why a particular decision has been taken. For the why-not case, we need to explicitly discover our specified package, as if nothing else depends on it in our graph, it would otherwise always be undiscovered and conflicts not detected (see e.g. level-3 in the test).
* apt-pkg: fixed type comparison in 64bit systems using memsize castHerman Semenov2025-05-192-4/+4
|
* Add 'Include'/'Exclude' options to limit packages used from a repositoryJulian Andres Klode2025-05-197-25/+87
| | | | | | | | | | | | | 'Include' allows limiting a repository to a allowlist of packages, 'Exclude' allows removing packages from a repository. Implementation wise this is not the nicest as it goes via the IndexTarget options, so we first parse our option value into a vector, then we turn the vector into a string, and then vectorize it again. That said, we support both "," and " " as separators due to the construction (we split by "," then we join using " "). Gbp-Dch: full
* solver3: Do not install new packages for SuggestsJulian Andres Klode2025-03-201-0/+5
| | | | | | | | | | As a followup to the previous commit, restore the exact behavior of the old solver to break the Suggests on upgrade here by erasing any choices not previously installed. This ensures that the Suggests never installs any new package, but it will still retain previously installed packages when solver3 is doing autoremove.
* solver3: Handle previously satisfied Suggests lastJulian Andres Klode2025-03-202-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In #2103556 we can see that avahi-daemon Suggests avahi-autoipd, which is previously satisfied by dhcpcd-base due to a Provides; that Provides has now been dropped; and solver3 keeps the update back. As in LP: #2102720 this is a Suggests and it seems wrong for the Suggests to actually influence dependency choices and be able to hold back updates. Instead, satisfy previously satisfied Suggests at the end. For the particular case in this bug report, this results in avahi-autoipd, the real package, to be installed to keep the Suggests working which needs further consideration whether that is the right choice (we can argue either way), but in any case this is a better solution. This in turn breaks the conkeror test which is a somewhat awkward unrealistic test these days as it has no automatically installed packages; because previously something must have had a Suggests on say libdatrie1 or something that was processed first. This would be fine before 5daf6dbfd272be2f8e3c59d4bab4be8c119b7aa1 but as of that commit we no longer rewrite conkeror Depends xulrunner-1.9 | xulrunner-1.9.1 into conkeror Depends xulrunner-1.9.1 | xulrunner-1.9 Because xulrunner-1.9 is manually installed. Mark xulrunner-1.9 as automatically installed to fix the test case. The resulting behavior seems correct: If you manually want xulrunner-1.9 specifically we should not replace it with xulrunner-1.9.1; but if it's automatically installed we should. LP: #2103556
* solver3: Record manual flag before discovering packagesJulian Andres Klode2025-03-201-2/+5
| | | | | | | | | | | | | | | | When discovering packages we look at the manual flag to avoid reordering obsolete manually installed packages last. We inadvertently initialized that flag interlaced with discovering packages so if we discovered packages depending on obsolete, but manually installed, packages first, we were not aware they were manually installed and demoted them. I am struggling to come up with a test case for this as I can't get the package objects in the cache to be in the right order for the bug to trigger. LP: #2102720
* edsp: Dump minimized Dir::Log::Solver logsJulian Andres Klode2025-03-201-1/+1
|
* edsp: Add functionality to only write relevant packagesJulian Andres Klode2025-03-202-0/+46
| | | | | | | | | | | | | Add a variant of WriteLimitedScenario that does not take a pkgset, but creates one on the fly based on the transitive closure of installed packages, to be installed packages, and their dependencies and provides. This includes more packages than strictly necessary, i.e. we do not really need to include foo just because a package we want to install Conflicts with it, but oh well, this is easy to read. Trying to extend the filtering is hard as the dependencies being written are also filtered...
* zstd: The compressor level should be -6, not -19Julian Andres Klode2025-03-201-1/+1
| | | | | We created a very slow zstd, we don't default to high levels for other compressors...
* apt-pkg/solver3.h: avoid static_assert(false)Johannes Schauer Marin Rodrigues2025-03-141-1/+3
| | | | | | | | | | | | | | | | | With older compilers (g++ and clang from Bookworm), static_assert(false) will result in: /home/josch/git/apt/build/include/apt-pkg/solver3.h:52:24: error: static assertion failed: Cannot construct map for key type 52 | static_assert(false, "Cannot construct map for key type"); | ^~~~~ This commit implements the terrible but more valid workaround according to: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html Original solution from here: https://stackoverflow.com/questions/14637356/static-assert-fails-compilation-even-though-template-function-is-called-nowhere/14637534#14637534 That way, apt will compile with compilers in Bookworm again.
* solver3: Only hide ver->pkg clauses, not pkg->ver version selection onesJulian Andres Klode2025-03-131-4/+14
| | | | | | | | Particularly as Helmut pointed out we need to show which version we selected for install if there is only one but there is a versioned conflicts. Reported-By: Helmut Grohne <helmut@subdivi.de> on IRC
* solver3: Fix test-resolve-by-keep-new-recommendJulian Andres Klode2025-03-121-20/+22
| | | | | | | | | | | | | | | | | Reorder the if branches a bit to simplify the understanding of the promotions, and allow us to keep track of which dependency existed in the installed version. Change the rule for promoting new recommends to only promote new recommends to depends in *upgrade* and not *dist-upgrade* per the test-resolve-by-keep-new-recommends test case. This makes some sense: In a dist-upgrade, the solver could otherwise decide to remove an installed package if both the following hold: (1) something needs the upgraded version | something else (2) the upgraded version is not installable due to unsat recommends
* solver3: Fix Recommends/Suggests vs Enhances confusionJulian Andres Klode2025-03-122-1/+14
| | | | | | | | | | | | | | | | | | We accidentally considered an Enhances a reason to keep a package installed, which of course it is not, fix the determination of "existing soft dependency" to only include soft dependencies that should keep a package installed in the autoremover to solve the issue. This also fixes edsp/mantic-upgrade-rel-to-2024-05-29.edsp to not install llvm-13-dev for clang-13 which is an installed package with no upgrade. Also ensure we stop after the first match; the DependsList() is ordered by decreasing priority and we don't want to override Recommends by Suggests in case a package declares both... LP: #2101800
* solver3: Correctly determine 'same' or groupsJulian Andres Klode2025-03-101-9/+29
| | | | | | We incorrectly used the DependencyData of the first or group member, however that only checked that the first or group member was the same and that both either had a next member or not.
* solver3: Print correct reason when registering dependencyJulian Andres Klode2025-03-101-2/+1
| | | | This is relevant when debugging common dependencies.
* solver3: Fix detection of satisfied recommends for pkg variablesJulian Andres Klode2025-03-101-1/+1
| | | | This only worked for version literals lol
* edsp: Set Forbid-New-Install/Forbid-Remove: no if other is setJulian Andres Klode2025-03-101-0/+4
| | | | | | | | The upgrade code may also set Upgrade: yes, and this sets both to yes, so `apt upgrade` dumps behave like `apt-get upgrade` ones, which of course is not intentional. moo
* solver3: Do not prefer new installs over manually installed obsoletesJulian Andres Klode2025-03-092-7/+13
| | | | | | | | | | Only move obsolete packages last that are automatically installed, as we don't want to remove manually installed obsolete packages. Add some missing const annotations to the operator[] arguments as well that were needed. LP: #2100247
* depcache: Add a new UpgradeCount() memberJulian Andres Klode2025-03-092-0/+17
|
* Introduce pkgDepCache::Transaction for transactional depcache updatesJulian Andres Klode2025-03-092-0/+109
|
* solver3: Verbose error messagesJulian Andres Klode2025-03-082-21/+208
| | | | | | | | | | | | | | | | | | | | | | Introduce a new function, LongWhyStr() that returns a longer reason for why something is being installed (or not). This does the same path walk as the other function does, but it renders the clauses at each level, and one per line, so the whole output is a lot more informative. It is a separate function to keep the existing debug messages use the simple single line implication graph We remove the other special case in AddWork() for empty solutions to mke use of the general case in Solve() instead, and then adapt the case in Solve() to the same case as in Enqueue(). This also happens to fix the bug that when we encountered an empty clause we just printed the clause had no solution, but not how we got to install the package with the clause. Adapt the test suite for the changes which is an annoying amount of paperwork.
* solver3: bestReason: Only find actual assignmentsJulian Andres Klode2025-03-071-1/+5
| | | | | | | | | | I marked exim4-daemon-light for install, which marked exim4-daemon-heavy for not install, but now in postfix Conflicts: mail-transport-agent we saw "not exim4-daemon-heavy" as the reason for not installing postfix. Oh noes.
* solver3: Support pretty printing clausesJulian Andres Klode2025-03-062-6/+17
| | | | | This will print the underlying dependency which is nicer to read.
* solver3: cleanup operators for VarJulian Andres Klode2025-03-061-8/+3
| | | | Particularly, use single line and implement operator!=
* solver3: refactor: Return inserted Clause in AddWork()Julian Andres Klode2025-03-062-8/+9
| | | | | This avoids relying on the inserted clause being at the back of the clauses vector.