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

Already on GitHub? Sign in to your account

Option to reinstall only if the versions are *different*. #182

Closed
schwern opened this Issue Dec 11, 2012 · 9 comments

Comments

Projects
None yet
3 participants
Contributor

schwern commented Dec 11, 2012

cpanminus will normally only reinstall a module if its a newer version. There's --reinstall to always install the module no matter what version is installed. I'd like an option like --reinstall but it will only install if 1) the module is not already installed or 2) the installed version is different.

This is handy if you're installing a large system with very specific versions, such as from a local CPAN or pinto mirror, but have to interrupt the process and restart it. I don't want to have to reinstall everything, just what's different.

--reinstall-if-different-version maybe?

Owner

miyagawa commented Dec 11, 2012

Putting the name discussion aside, the actual feature (for the use case you describe) might be much trickier to implement than it sounds, because --reinstall only takes effect (as of today) for the given argument, not the dependencies.

Suppose you have Foo 0.02 and Bar 0.03 in your lib, and Foo requires Bar 0.02 (for the simplicity, imagine Foo always requires Bar 0.02 regardless of its own versions) in the build dependencies.

a) Foo 0.03 and Bar 0.04 is available on CPAN, and you run cpanm --reinstall Foo will pull Foo 0.03, but not Bar 0.04 because the dependency is already satisfied.

b) You put up a DarkPAN/orepan/Pinto mirror with Foo 0.01 and Bar 0.02, and run cpanm --reinstall-if-different-version Foo against that mirror - that will install Foo 0.01 (as you suggested) but not downgrade Bar to 0.02, because the dependency check will pass through.

We could mangle the post-configure dep check logic to check mirror versions as well but it is a tricky process anyway because we can't hook into the builder at all.

By the way this is precisely the problem I want to tackle with with Carton rather than just cpanminus. With or without carton, I'm sure you end up having to have an isolate library path (cpanm -L) to install from scratch, than downgrading stuff.

Contributor

schwern commented Dec 11, 2012

Leaving the implementation details aside, I can see two separate use cases. One where you ONLY want to reinstall the asked for module, as it works now. One where you want to reinstall everything. The latter is for cases like mine where I want an exact reproduction. The former seems more like what people would want for ad-hoc installs.

Maybe there needs to be a separate flag to control how dependencies are resolved? 1) Only upgrade deps if necessary (current default behavior), 2) always upgrade deps to the latest version, 3) always reinstall deps (like --reinstall), 4) reinstall deps if different (what I'm proposing).

In that, it would make sense to unify the primary and dep install flags. --reinstall=<style> and --resolve-dependencies=<style> with the "style" options sharing the same name. A bare --reinstall acts like it does now.

What do you think?

Owner

miyagawa commented Dec 11, 2012

I recommend using -L to reinstall the exact dependency set, i.e. to "begin from scratch". I've been putting a lot of efforts to make it work. Try if you haven't and see if that meets your needs. I know it doesn't exactly do what you propose, but i'm sure it will achieve what you want.

In the early days of cpanm development I thought about introducing that kind of "dependency-check" policy, but ended up doing a traditional "have this module this version or later" check.

On the other hand, to support "conflicts" and such, we should evolve the post-configure check more than just that, for sure. So there seems to be a place to do that kind of thing.

Owner

miyagawa commented Dec 12, 2012

By supporting conflicts (or more specifically, what CPAN::Version::Requirements requires), you will be in theory able to "rewrite" dependencies as you go to "> 1.000" with "== 1.000" upon a re-installation time, so that CPAN tools will croak if the requirement version doesn't match with what you have in the CPAN mirror.

That's the ultimate goal that I would like to achieve with Carton, with or without DarkPAN generator like Pinto, since carton already has the ability to "bundle" the deps into a deployable mirrors with 02package by itself.

A small thought experiment:
A pragma-modification like "use Module#version;" is made (the '#' is just
an example character here), or a suitable other Makefile.PL specification
(say, new terms requires_exactly or requires_range). This allows a package
to specify that this dependency at this version must exist. If there is a
later version of the dependency already in the installed tree, and the
required specific older version does not exist, $module_installer should
end up being able to force that older version to be installed under a
version-specific directory. When a 'use Module#version;' is encountered,
the appropriate (older) installed dependency is used. The latest version of
a package then is the default when 'use'd in the traditional way, but an
earlier package may be deliberately pulled.

Does that sound completely unfeasible?
There's probably some magic which happens in perl's guts that would make
this impossible, however :)

Gaz

On 11 December 2012 23:14, Tatsuhiko Miyagawa notifications@github.comwrote:

I recommend using -L to reinstall the exact dependency set, i.e. to
"begin from scratch". I've been putting a lot of efforts to make it work.
Try if you haven't and see if that meets your needs. I know it doesn't *
exactly* do what you propose, but i'm sure it will achieve what you
want.

In the early days of cpanm development I thought about introducing that
kind of "dependency-check" policy, but ended up doing a traditional "have
this module this version or later" check.

On the other hand, to support "conflicts" and such, we should evolve the
post-configure check more than just that, for sure. So there seems to be a
place to do that kind of thing.


Reply to this email directly or view it on GitHubhttps://github.com/miyagawa/cpanminus/issues/182#issuecomment-11269319.

Owner

miyagawa commented Dec 12, 2012

or a suitable other Makefile.PL specification (say, new terms requires_exactly or requires_range).

that's already done in Meta Spec 2.0
http://search.cpan.org/~dagolden/CPAN-Meta-2.120921/lib/CPAN/Meta/Spec.pm#Version_Ranges
http://search.cpan.org/~dagolden/CPAN-Meta-Requirements-2.122/lib/CPAN/Meta/Requirements.pm
But there's no client that supports that (yet)

Contributor

schwern commented Dec 13, 2012

-L is close, and it saves me a lot of recompiling vs --reinstall, but doesn't match what I want in detail. I need to reproduce an existing CentOS Perl installation to work with their packaged Perl. sitelib is /usr/lib/perl5/site_perl but sitearchlib is /usr/lib64/perl5/site_perl so it doesn't follow the normal pattern. I can move directories around post-installation, I'll see if I can make it work.

The end goal is to reproduce an existing Perl installation exactly, which uses the system perl package, but being able to install from a fixed Pinto server. This is actually a transitional goal, the real goal is to get them off the system perl, but first we have to test that we've captured their Perl modules in Pinto and that all works. Moving the perl installation location brings its own set of issues.

I already have all the tarballs of the exact versions in Pinto. I also have a hand written META.json with the version dependencies set exactly using "== 1.23' version ranges, not that it does a lot of good right now as no system I know of honors them end-to-end, but the metadata is there.

Owner

miyagawa commented Feb 1, 2013

The latest devel has a support for version range check in end-to-end, including the exact version e.g. '== 1.23', with or without using cpanfile (you can also handwrite MYMETA files to feed after configuration).

This means two things:

a) cpanm Module~==VERSION (or Module@VERSION as a shortcut), as well as version spec in MYMETA files, will try to find the exact version from metacpan (unless you specify --mirror-only, which sounds like your case)

b) cpanm Module~SPEC, as well as version specs in MYMETA files, will be used when compared with the version found in the mirror. If your Pinto mirror has CGI 3.12, and your MYMETA specifies CGI == 3.11, cpanm will refuse to install it because it doesn't satisfy the requirement.

Also, when an exact requirement is given "== 2.11" it will override --skip-installed automatically, if the version you have and try to install is different. This sounds like matching very close to what you described originally.

It's still not 100% clear if this matches the desired behavior here, but it's probably worth pointing it out.

Owner

miyagawa commented Apr 13, 2013

closing for now.

@miyagawa miyagawa closed this Apr 13, 2013

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