Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add versioned dependency support #3

Open
rmarquis opened this issue Jul 4, 2017 · 14 comments
Open

Add versioned dependency support #3

rmarquis opened this issue Jul 4, 2017 · 14 comments

Comments

@rmarquis
Copy link

rmarquis commented Jul 4, 2017

From the bug reports I've collected in the pacaur tracker over the years, I'd say the majority of edge cases are due to AUR versioned dependencies. Checking for version in addition to names for AUR dependencies would avoid these situations.

I've looked into the sources, and my current understanding is that versioning check is implemented in a similar fashion as done in cower with only a name check (please correct me if I'm wrong here).

For example, a few months ago there was a bug in bauerbill, with the ros-indigo-desktop-full package. While aurutils was able to "solve" the tree, it wasn't able to find what was causing the error since it doesn't implement version check either. I simply ran pacaur to pinpoint the issue:

$ pacaur -S ros-indigo-desktop-full
:: Package ros-indigo-desktop-full not found in repositories, trying AUR...
:: resolving dependencies...
:: no results found for sdformat>=4.2.0

Quickly looking at the AUR revealed that only sdformat 4.1.0 was available (this particular issue has been solved since then, though that package deps chain is still broken due to another missing dep).

Most of the time these versioning issues are due to completely unneeded versioning deps in the PKGBUILDs, but it is useful to detect them to make it easy to fix them. There are also a few entirely valid cases (see f.e. https://github.com/falconindy/cower/issues/91, admittedly one of the most complex case I've ever seen).

The drawback of doing versioning check is that it is a bit slower to process (and sometime much slower as implemented in bash in pacaur), but ensuring a build chain won't be broken before starting the build processs is quite important.

See also aurutils/aurutils#10 for a relevant discussion.

@AladW
Copy link

AladW commented Jul 22, 2017

I've filed a bug report for the AUR to support querying versioned package names:

https://bugs.archlinux.org/task/54906

@E5ten
Copy link
Contributor

E5ten commented Apr 28, 2019

Even though versioned depencency support will need the AUR to support querying versioned package names (at least it seems that way) would it be possible for a flag to be added to buildorder to output the versioning string on versioned deps in the buildorder so that the user could check versioned dependencies that are in the buildorder output but otherwise rely on buildorder?

@Morganamilo
Copy link
Contributor

Honestly I don't think proper versioned dependency would be too hard seems as we have access to vercmp via alpm.

@falconindy
Copy link
Owner

Well no, it is that difficult because dependencies don't always match the name -- that's the crux of the issue here. Cases where the dependency matches the package name exactly either Just Works™ (because there can only be one package by that name) or you have an unbuildable package because the AUR package is out of date or strictly incompatible with the Arch package landscape.

Example: you might have a package in the repositories called libfoo, and an AUR package called libfoo-unstable which provides a newer version (i.e. provides=(libfoo=x.y.z)). If an AUR package depends on libfoo>=x.y.z which can only be satisfied by libfoo-unstable, how do you resolve this? The AUR needs functionality similar to libalpm's alpm_find_satisfier that allows searching for dependencies by a depstring which may or may not match a package by that exact name.

@Morganamilo
Copy link
Contributor

Finding all satisfies and versioned dependency support are totally different issues imo.

@falconindy
Copy link
Owner

Please describe a case where having some form of versioned dependency support is useful without full depend (provider) resolution.

@Morganamilo
Copy link
Contributor

If for some reason a package depends on foo=1 but now foo has been upgraded to foo=2. This is going to fail to build but auracle won't tell you this.

auracle is the easiest place to implement this seems as you have access to alpm_depend_t and vercmp.

@falconindy
Copy link
Owner

Yes, I described that case. I don't think it's very useful/interesting because all it represents is an out of date or mothballed AUR package. There should never be a healthy package in this situation.

@Morganamilo
Copy link
Contributor

Yes there shouldn't be but it happens.

@falconindy
Copy link
Owner

Sorry, making a half attempt at fixing the dependency solver just to handle infrequent cases of broken packages isn't something I have interest (or time) to tackle.

I'll fix this once the AUR actually has the support that we need to do this properly.

@Morganamilo
Copy link
Contributor

Alright then, fair enough.

falconindy added a commit that referenced this issue Sep 4, 2020
Originally, I wanted to address the following problem:

When a user callback indicates failure, calling CancelAll() means that
we end up (re)invoking a curl socket callback from a socket callback,
leading to a double free (either in sd-event or curl). One possible
backtrace looks like:

    (gdb) bt
->  #0  aur::AurImpl::DispatchSocketCallback (this=0x618000000480, s=<optimized out>, action=4, io=<optimized out>) at ../src/aur/aur.cc:330
    #1  0x00007ffff74fa4e1 in singlesocket () from /usr/lib/libcurl.so.4
    #2  0x00007ffff74fe622 in curl_multi_remove_handle () from /usr/lib/libcurl.so.4
    #3  0x000055555570e833 in aur::AurImpl::FinishRequest (this=<optimized out>, curl=0x623000005500, result=<optimized out>, dispatch_callback=<optimized out>) at ../src/aur/aur.cc:462
    #4  0x0000555555708cc1 in std::__do_visit<std::__detail::__variant::__deduce_visit_result<void>, aur::AurImpl::Cancel(const value_type&)::Visitor, const std::variant<void*, sd_event_source*>&> (__visitor=...) at /usr/include/c++/10.2.0/variant:869
    #5  std::visit<aur::AurImpl::Cancel(const value_type&)::Visitor, const std::variant<void*, sd_event_source*>&> (__visitor=...) at /usr/include/c++/10.2.0/variant:1710
    #6  aur::AurImpl::Cancel (this=0x618000000480, request=...) at ../src/aur/aur.cc:291
    #7  0x00005555557090f6 in aur::AurImpl::CancelAll (this=0x618000000480) at ../subprojects/abseil-cpp-20200225.2/absl/container/internal/raw_hash_set.h:311
    #8  0x000055555570f08d in aur::AurImpl::CheckFinished (this=0x618000000480) at ../src/aur/aur.cc:485
->  #9  0x000055555570f341 in aur::AurImpl::DispatchSocketCallback (this=0x618000000480, s=<optimized out>, action=4, io=<optimized out>) at ../src/aur/aur.cc:332
    #10 0x00007ffff74fb092 in Curl_multi_closed () from /usr/lib/libcurl.so.4
    #11 0x00007ffff74cc631 in Curl_closesocket () from /usr/lib/libcurl.so.4
    #12 0x00007ffff74df551 in Curl_disconnect () from /usr/lib/libcurl.so.4
    #13 0x00007ffff74fc354 in multi_done () from /usr/lib/libcurl.so.4
    #14 0x00007ffff74fcc91 in multi_runsingle () from /usr/lib/libcurl.so.4
    #15 0x00007ffff74fe1d1 in multi_socket () from /usr/lib/libcurl.so.4
    #16 0x00007ffff74fe354 in curl_multi_socket_action () from /usr/lib/libcurl.so.4
    #17 0x000055555570f60d in aur::AurImpl::OnCurlTimer (userdata=0x618000000480) at ../src/aur/aur.cc:401
    #18 0x00007ffff7466b3e in ?? () from /usr/lib/libsystemd.so.0
    #19 0x00007ffff746821e in sd_event_dispatch () from /usr/lib/libsystemd.so.0
    #20 0x00007ffff746a6a9 in sd_event_run () from /usr/lib/libsystemd.so.0
    #21 0x0000555555704bd3 in aur::AurImpl::Wait (this=0x618000000480) at ../src/aur/aur.cc:495
    #22 0x000055555563ee8a in auracle::Auracle::GetOutdatedPackages (this=<optimized out>, args=std::vector of length 0, capacity 0, packages=<optimized out>) at /usr/include/c++/10.2.0/bits/unique_ptr.h:421
    #23 0x0000555555656816 in auracle::Auracle::Outdated (this=<optimized out>, args=..., options=...) at ../src/auracle/auracle.cc:564
    #24 0x0000555555596c7f in main (argc=<optimized out>, argv=<optimized out>) at ../subprojects/abseil-cpp-20200225.2/absl/container/internal/raw_hash_set.h:311

We could do that by making CancelAll() merely schedule another event
that performs the actual cancellation at a later point in order to avoid
the recursion. However, our cancellation logic is all sorts of weird and
makes assumptions about how events are dispatched (i.e. there might be
multiple at a time). Let's just get rid of all of this and use the
sd-event mechanism of sd_event_exit instead.

This does, however (as did the original proposed solution), have the
side effect of logging multiple times because we potentially open up to
5 connections to the AUR at once, e.g.

  $ build/auracle --baseurl http://129.168.255.1 outdated
  error: UNKNOWN: Connection timed out after 10000 milliseconds
  error: UNKNOWN: Connection timed out after 10000 milliseconds

I suppose one way to fix this would be to do response merging on the
backend to match the request splitting. That way, the frontend only gets
one response. I think that comes with a lot of weird potential behaviors
though (handling of partial failures, to mention one). Would be nicer if
the AUR didn't have the crap behavior and could take POST requests in
order to extend the arg limit.

Whatever, this is a weird edge case.

Fixes #82.
@falconindy falconindy closed this as not planned Won't fix, can't repro, duplicate, stale Jul 30, 2024
@falconindy
Copy link
Owner

2 weeks ago I hadn't looked at the new REST API that apparently now exists and allows querying by "provides". That's 80% of the way there. Auracle can now do a more thorough job of finding dependencies when the names don't directly match. However, versioned dependency support is still lacking. One could potentially do something like:

  • filter out packages provided by the repos
  • query for remaining dependencies, leaving some subset unresolved
  • query for remaining unresolved dependencies by unversioned provides
  • post-hoc filter those results through alpm_pkg_vercmp to discard unsatisfiable packages

Note that the two queries here could be done in parallel, albeit a bit wastefully, or serially, at the cost of performance. Not yet clear which of those approaches results in easier to read code.

@falconindy falconindy reopened this Aug 11, 2024
falconindy added a commit that referenced this issue Aug 11, 2024
This takes in inputs like "curl=8.0.1" or "curl<10" and returns only the
packages that can *actually* satisfy the dependency. This leverages the
"provider" searchby functionality to return candidates that can be
post-filtered to determine if they meet the requirement.

This is a small but significant step towards properly supporting
versioned dependencies as requested in #3. In order to support this in
recursive clones and 'buildorder', we're likely due for some significant
surgery on the PackageCache.
@falconindy
Copy link
Owner

So d36d317 was an easy patch to write and gives us dependency resolution. Thinking about adding this to download or buildorder verbs seems substantially more complicated. If/when you encounter a dependency that has to be solved by a provider, how do you present the options?

  1. Make the selection interactive. Hard pass on this.
  2. Present all the options. Seems obvious, but how do you proceed with the build order in this case? It would be ill-advised to traverse them all to come up with the deps for all the possible providers.
  3. Come up with some heuristic to pick one. Most votes? Most popular? Random? I don't know, but this surely wouldn't be flexible enough for general use.
  4. Present the unresolved provider "stub", let the caller figure it out through the new resolve verb.

Honestly, option 4 seems like the best, but I'm open to other ideas.

@rmarquis
Copy link
Author

rmarquis commented Aug 12, 2024

Option 4 also seems like the best option to me. As long as the output in buildorder makes it clear that an explicit choice needs to be made, that should be more than fine. I can't think of a better alternative (and option 3 just seems the worst to me).

(also thanks to you for working on that old ticket - I'm still enjoying auracle after all these years).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants