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

Please clarify conflicts documentation regards to intent #93

Open
kentfredric opened this issue Apr 12, 2015 · 4 comments
Open

Please clarify conflicts documentation regards to intent #93

kentfredric opened this issue Apr 12, 2015 · 4 comments

Comments

@kentfredric
Copy link
Contributor

current Pod says:

conflicts

    These libraries cannot be installed when the phase is in operation. This is a very rare situation, and the conflicts relationship should be used with great caution, or not at all.

What needs to be expanded on is the nature of the conflict this represents ( esp, in comparison to x_breaks )

Its unclear here what the semantics of self->{conflict}->{foo} = $range actually mean in terms of a install tool.

Possible interpretations include

  • foo being installed causes self to be broken
  • foo will be broken by installing self

And the nature of the breakage is unclear, as is the resolution one should take to resolve it.

  • self conflicts Moose

Should self reject being installed where Moose is present?
Should Moose be removed prior to installing self?

These are questions my head gets confused with every time I think "Oh, there's a module that causes problems for me if its installed", and I can't remember if I want conflicts or x_breaks ( and the availability of both and the lack of clarity on their usage further complicates things ).

Even https://metacpan.org/pod/Dist::Zilla::Plugin::Breaks has rather unclear verbage

Add metadata about potential breakages to your distribution

  1. Is that metadata about dependencies that might cause me to become broken?
  2. Or is that metadata about dependents I might be breaking.

Because this line directly contradicts the abstract if the abstract implies [1].

but rather indicates what modules will likely not work once your distribution is installed.

This line further clarifies its cases [2]

These modules are not prerequisites -- our distribution does not use those modules, but rather those modules use us, which suggests the abstract is misleading, and that this module indicates

"I will cause foo to be broken because they use us"

But then how it is different from conflicts is unclear.

My case that is presently thwarting me is even worse than this, because I neither use the module, and the module in question does not use me ( so it is inappropriate to state a dependency ).

I do not break it either, however, it breaks me. ( That is, the breakage appears simply when I run my code, not when it runs its ).

However, due to something I use using Module::Pluggable, the thing that is a problem is effectively use'd by me.

And I have no idea what I'm supposed to do dependency wise to express this mess.

And its even less clear to anticipate from the spec what a conflicts/breaks recognizing tool should do when confronted with such a situation.

Upgrades/Downgardes/Uninstalls are all on the table for both, deferring the problem to USER doesn't solve the essential qunadry about what the recommended action is.

Prereqs are simple:
X < Y = Downgrade X to be less than Y
X > Y = Upgrade X to be more than Y
X != Y = Upgrade or Downgrade X until it is not Y ( But still make sure X is available ).

Conflicts/Breaks are much harder, because there's the implication of uninstalls being the default option.
Conflict X > Y = Downgrade X to be less than Y or uninstall it ?
Conflict X < Y = Upgrade X to be more than Y or uninstall it?
Conflict X != Y = Uh ...
Conflict X = Y = Roll a 1D3 and pick your upgrade/downgrade/uninstall options.
Conflict X < Y , > Z, != M = BDSM loving Raptors on bicycles take me now.

@karenetheridge
Copy link
Member

Its [sic] unclear here what the semantics of self->{conflict}->{foo} = $range actually mean in terms of a install tool.

Possible interpretations include

foo being installed causes self to be broken
foo will be broken by installing self

conflicts is the former. x_breaks is the latter.

And the nature of the breakage is unclear, as is the resolution one should take to resolve it.

That's up to the client. It could opt to not install the distribution,
claiming an unreconcilable prerequisite. Or it could possibly choose to
upgrade foo to a more recent version (if there is one), or downgrade foo
to a less recent version (if there is one), if doing so doesn't violate other
constraints being considered simultaneously.

I would expect CPAN.pm, cpanplus and metacpan to all choose the former route -
fall over and die if it encountered a conflict currently in effect. I'd
expect @mstrout's vapour cdx solver to do something more akin to the latter,
as it will have sufficient state information to be able to choose something
intelligently.

I can't remember if I want conflicts or x_breaks ( and the availability of both and the lack of clarity on their usage further complicates things )

x_breaks vs. a regular prerq is easy: pick the one that doesn't result in a
circular dependency :)

Moose is a good example because it's quite obvious which things it is
dependent on, vs. dependent on it. If there is a problem between Moose and
List::Util interacting, then Moose should declare a regular prereq on the
fixed version(s) (perhaps expressing it in terms of != 0.123). If there is a
problem between Moose and MooseX::Aliases, it should declare an x_breaks.

I don't think I've ever seen a real example of a conflict that wasn't
contrived simply for the sake of exercising the toolchain. Maybe there are
two alternative implementations of an algorithm, and installing one doesn't
just supersede the other (as in Alt::)?

I'm making this change in Dist::Zilla::Plugin::Breaks:

-# ABSTRACT: Add metadata about potential breakages to your distribution
+# ABSTRACT: Add metadata about potential breakages caused by your distribution

@karenetheridge
Copy link
Member

One other difference between conflicts and x_breaks is the behaviour it can prevent. A matching conflicts entry can block a distribution from being installed. An x_breaks entry cannot cause a distribution to fail prereq checks - it is purely data to inform possible post-release actions.

@kentfredric
Copy link
Contributor Author

I guess my problem is specific because I know a resolution to a conflict that should be indicated.

  • I don't want to depend on X
  • And I now know X versions > Y fix the problem
  • And I want to coerce installing a non-broken version if a broken one exists.

That's moderately straight forward to do with Makefile.PL hacking, but I feel such behaviour to be so common ( Old X is broken, get a new one ) that it should have some syntax for it.

conflicts is inappropriate because it is not a requirement, and I would not wish it to be.
x_breaks is inappropriate because I'm not breaking it, its breaking me.

And the other approach using a prereq doesn't work because:

  • There's no !< dep.
  • And even if their was, "!<" would likely imply "Should have X, but not older than Y", where I don't care if X is missing.

@karenetheridge
Copy link
Member

My case that is presently thwarting me is even worse than this, because I neither use the module, and the module in question does not use me ( so it is inappropriate to state a dependency ).

I do not break it either, however, it breaks me. ( That is, the breakage appears simply when I run my code, not when it runs its ).

However, due to something I use using Module::Pluggable, the thing that is a problem is effectively use'd by me.

And I have no idea what I'm supposed to do dependency wise to express this mess.

This sounds like a case for [DynamicPrereqs] :) -- in pseudocode, you'd want to say in Makefile.PL:

- if Module::Pluggable is installed,
- and it is in the version range that is problematic,
- then add an extra prerequisite on a version that will get us out of a bad combination.

I do this in several distributions, e.g. this one in Test::LWP::UserAgent for a bug that has absolutely nothing to do with me, but still gives me test failures:

[DynamicPrereqs]
-raw = |# see RT#103423
-raw = |$WriteMakefileArgs{PREREQ_PM}{'IO::Socket::IP'} = $FallbackPrereqs{'IO::Socket::IP'} = '0.31'
-raw = |  if eval { require IO::Socket::SSL; 1 } or eval { require IO::Socket::INET6; 1 };

It's not a case for x_breaks, because it's not the other thing that becomes broken by you -- it's you that is broken by the other thing.

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

3 participants