Open kentfredric opened 9 years ago
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
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.
I guess my problem is specific because I know a resolution to a conflict that should be indicated.
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:
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.
current Pod says:
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 causesself
to be brokenfoo
will be broken by installingself
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 whereMoose
is present? ShouldMoose
be removed prior to installingself
?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
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.