5

I have been using Dist::Zilla for a project at work, and I've declared all my dependencies in the [Prereqs / Requires] section. That's fine so far.

Now I found that the latest version of one of my dependencies breaks backwards compatibility, so I want to limit the range of versions that I depend on. Something like what cpanm supports:

# from perldoc cpanm
cpanm Plack~">= 1.0000, < 2.0000"  # latest of 1.xxxx
cpanm Plack@0.9990                 # specific version. same as Plack~"== 0.9990"

Or Module::Build:

'Other::Module' => '>= 1.2, != 1.5, < 2.0',

In general, how do I declare this type of dependency using Dist::Zilla?

Fabrice Gabolde
  • 215
  • 2
  • 8
  • I'll just point out for reference that you should be very careful with limiting the maximum version of a dependency. While the feature is there and works on modern toolchain, CPAN is not a package manager, so if another dependency decides it needs a newer version of that module than you allow, the CPAN installer won't be able to work it out; you can't have two versions of the same module installed. Additionally there's nothing preventing the newer version from just being installed by some later process, since this version check will only happen when your module is installed. – Grinnz Nov 01 '18 at 23:44

2 Answers2

6

Dist::Zilla::Prereqs uses CPAN::Meta::Spec to do the prereqs. That doc describes the syntax in the Version Ranges chapter.

Some fields (prereq, optional_features) indicate the particular version(s) of some other module that may be required as a prerequisite. This section details the Version Range type used to provide this information.

The simplest format for a Version Range is just the version number itself, e.g. 2.4. This means that at least version 2.4 must be present. To indicate that any version of a prerequisite is okay, even if the prerequisite doesn't define a version at all, use the version 0.

Alternatively, a version range may use the operators < (less than), <= (less than or equal), > (greater than), >= (greater than or equal), == (equal), and != (not equal). For example, the specification < 2.0 means that any version of the prerequisite less than 2.0 is suitable.

For more complicated situations, version specifications may be AND-ed together using commas. The specification >= 1.2, != 1.5, < 2.0 indicates a version that must be at least 1.2, less than 2.0, and not equal to 1.5.

So your prereqs would become:

[Prereqs]
Plack = >= 1.0000, < 2.0000
Plack = == 0.9990
Other::Module = >= 1.2, != 1.5, < 2.0

Note the single = that separates the module name (key) from the version or version range (value).

Those versions mean:

  • >= 1.0000, < 2.0000

    Larger or equal to 1.0000 and smaller than 2.0000

  • == 0.9990

    Exactly version 0.9990

  • = 1.2, != 1.5, < 2.0

    Greater or equal to 12 and not 1.5 and smaller than 2.0

As you can see, that's exactly the same as for the cpanfile or Module::Build.

Community
  • 1
  • 1
simbabque
  • 53,749
  • 8
  • 73
  • 136
  • Note that I can't verify this. – simbabque Oct 21 '16 at 10:16
  • 1
    (How do I edit comments?) I set `Search::Elasticsearch = >= 2.03, < 5.00` and upgraded Search::Elasticsearch, and now `listdeps --missing` lists it. – Fabrice Gabolde Oct 21 '16 at 12:16
  • @fab there is a = too much I think. You can only say that edit comments for five minutes. There is an edit link. If your comment is the last one you can also copy it, delete it, paste and add and then post it. – simbabque Oct 21 '16 at 12:35
  • Doesn't show up for me, I guess I need more karma. I think the dist.ini still needs to be valid INI; if I remove the `=` dzil complains that ``Search::Elasticsearch >' is not a module name`. – Fabrice Gabolde Oct 21 '16 at 13:38
  • I'm looking through github: https://github.com/search?p=11&q=language%3AINI+%22%5BPrereqs%5D%22&ref=searchresults&type=Code&utf8=%E2%9C%93 try finding a file that has this kind of syntax and hope that works ;) – simbabque Oct 21 '16 at 13:51
  • @Fabrice see above – simbabque Oct 21 '16 at 14:08
  • 1
    @KitPeters you're right. The `=` is required, because the whole `>= 1.2, != 1.5, < 2.0` together is the _version string_. I see it too now. Will update. Thanks for pointing it out. – simbabque Feb 22 '17 at 20:26
2

simbaque above was almost right, and Fabrice Gabolde had the rest (I don't know how to link names).

The way to do this:

[Prereqs]
Plack = >= 1.000, < 2.000
Other::Module = == 1.0
Other::Other::Module = >= 1.2, != 1.5, < 2.0

ETA: simbaque has since corrected their answer; leaving this one for posterity.

Aurelia Peters
  • 2,169
  • 1
  • 20
  • 34