dlang / dub

Package and build management system for D
MIT License
673 stars 230 forks source link

dub.selections.json woes #829

Closed p0nce closed 8 years ago

p0nce commented 8 years ago

People seem confused by dub.selections.json on IRC.

<canidae> forgive my ignorance, but what's the point of dub.selections.json? i've specified a version in dub.json, why isn't this enough?
<canidae> perhaps there's a way to "disable" dub.selections.json?

In particular it is the 3rd time people ask how to get the latest tags in dependencies (I then advise to remove dub.selections.json + dub clean-caches).

=> dub upgrade is supposed to help but I guess it doesn't work everytime, which is something unrelated.

Honestly I somehow get why dub.selections.json and dub upgrade are there. But it is a bit backwards, it is more common to want the latest available version for everything (according to version selectors of course) that to want to stay on previous versions. If you want to pin dependencies into a specific version, you can always modify dub.json.

The other case I can think of is to pin the version of a sub-dependency, but the case is pretty rare. If a program with dependency A => B => C fail, it's quite easy to reproduce it with a program B => C. And committing dub.selections.json breaks the nice encapsulation of sub-dependencies DUB provides (A => B => C then A shouldn't know C).

Opinion: the cases where we do want dub.selections.json are a small minority. I think it should be an opt-in choice. I remember a time where it wasn't there and never missed it. In particular if a library pins dependencies instead of using SemVer, it creates diamond problems quickly.

canidae commented 8 years ago

Just adding my voice to this. While I'm not exceptionally versed in dub, this is not the first time dub.selections.json has caused versioning issues for me. This time I had a small project using DSFML version "~>2.1". It was incompatible with newer versions of DMD. "dub upgrade" did not update dub.selections.json, changing version in dub.json to "~>2.1.1" and then running "dub upgrade" still didn't do anything. Deleting dub.selections.json did however fix the issue, but it seems quite cumbersome if I have to delete that file each time I need to upgrade some libraries. I don't need a dub.selections.json myself, and it's a feature I've never desired in any project I've worked on (including projects outside Dlang). While it may be useful in some cases, it seems like it's solving a problem only a minority experience. It would be nice if this feature was opt-in.

mihails-strasuns commented 8 years ago

I agree that it is both annoying and error-prone. Just recently I was going mad trying to reason why I can't reproduce build failure from CI on my local machine (on identical commit hash) until I have finally spotted that there is a dub.selections.json left from some old build and dub keeps using old dependencies locally (and CI gets latest ones as defined by dub.sdl because it is fresh clone).

s-ludwig commented 8 years ago

One thing needs to be clearly separated: Bugs are bugs and not conceptual issues. 2/3 of the text in this ticket is based on #528, which is fixed in the latest beta and doesn't have anything to do with dub.selections.json.

Assuming that everything works correctly, I don't think that there is anything error prone to the approach. Any quite frankly, it's vital not only to get a reproducible build across machines, a major issue for other packaging has been that large dependency trees became virtually unmanageable. In theory this wouldn't be the case, if everyone adhered to SemVer and all dependencies were referenced using ~>1.0.0 or ~>1.0, but in practice it's often necessary to manually control which dependencies get upgraded*. The selections file gives that control not only for direct dependencies, but for all of them.

Now let's imagine that we'd do without a per-package set of version selections and we'd always use the latest available versions. There are two possibilities:

I should probably dig up the old discussions about this topic with @jacob-carlborg, or something from Ruby/Bundler. But there simply are a lot of compelling arguments for this approach, even if it may not always seem necessary.

* Especially considering that maybe 80% of the packages have 0.x.x versions, which have no backwards compatibility rules.

s-ludwig commented 8 years ago

BTW, @Dicebot: Do you remember if you got upgrade suggestions during the local build? It would probably help to give them a different color on the console, as currently it's rather difficult so spot such information.

However, this would have happened the same way without a set of selections, if you wouldn't have had the latest dependencies installed on the local machine (except if the automatic upgrade mode was the default). On the other hand, putting dub.selections.json under version control would have solved it no matter what the environment is (it really should be versioned at least in 90% of the cases).

p0nce commented 8 years ago

upgrading is automatic and in the mid of a work day dub suddenly decides to use a newer version of a dependency, resulting in breakage or changed behavior.

This is actually what I'd want, but that's because I use SemVer and ~>1.0. If dub upgrade has that effect (and it seems it has in principle, wasn't aware of it), then it's OK for me.

As for the rest, you made a very good case for the current approach and I think this ticket can be closed.

jacob-carlborg commented 8 years ago

A couple of notes on what's necessary to have dub.selection.json work correctly, assuming it's supposed to work like Gemfile.lock for bundler.

"Implements proper optional dependency semantics, where using an optional dependency can now be controlled using dub.selections.json"

In my opinion that's broken, at least according to how I think dub.selections.json should work.

s-ludwig commented 8 years ago

The dub.selection.json file should never be edited manually.

Why? It would of course be nice to have a CLI for selecting/deselecting optional dependencies and for upgrading specific dependencies. But I don't see any reason to disallow manual edits.

mihails-strasuns commented 8 years ago

Do you remember if you got upgrade suggestions during the local build? It would probably help to give them a different color on the console, as currently it's rather difficult so spot such information.

Certainly not. Though it was rather long time ago and could be fixed in later versions.

However, this would have happened the same way without a set of selections, if you wouldn't have had the latest dependencies installed on the local machine (except if the automatic upgrade mode was the default).

Intuitively I would expect some user prompt whenever upgrade is available if dependency version is open. Which in relation with next statement ..

On the other hand, putting dub.selections.json under version control would have solved it no matter what the environment is

.. is probably what makes me feel most uneasy about this solution. If I wanted to pin dependencies hard I could as well just specified it using ==version in dub.sdl itself, without introducing any new project file to keep in repo.

jacob-carlborg commented 8 years ago

But I don't see any reason to disallow manual edits.

Here's the deal. I want Dub to somehow look down the dependency graph for a project to ensure that the same dependencies are always installed. I though that was how dub.selection.json works but that 's currently not the case.

As soon as you start manually editing dub.selection.json you'll get into problems. The tool cannot longer given the same guarantees about the dependency graph. It will be much easier to get a dependency graph that the tool cannot satisfy. Does Dub generate a selections graph for the optional dependencies as well? If no, then you're back to square one. If yes, then why are the optional dependencies in dub.selection.json instead of in dub.json?

The only reason to manually edit dub.selection.json is to bypass the tool to generate the looked down dependency graph. But why would you want to do that? Either advertising manually editing dub.selection.json or having features to requiring to manually editing dub.selection.json will get you the problems mentioned above.

Why? It would of course be nice to have a CLI for selecting/deselecting optional dependencies and for upgrading specific dependencies.

The solution is really simple, the optional dependencies should go in dub.json, not dub.selection.json.

jacob-carlborg commented 8 years ago

Intuitively I would expect some user prompt whenever upgrade is available if dependency version is open

To me that is very unexpected from a tool, a command line tool. That Dub checks for new dependencies for each build. I would expect that from a GUI application, like a browser, but not from a command line tool.

.. is probably what makes me feel most uneasy about this solution. If I wanted to pin dependencies hard I could as well just specified it using ==version in dub.sdl itself, without introducing any new project file to keep in repo.

It might work with one or two dependencies but when you have 40 dependencies (including indirect dependencies) it's a PITA. If you really want to look down the dependencies in dub.sdl you would need to specify all 40 dependencies including the exact versions. Good luck with trying to find a combination that actually works. And when you upgrade a dependency, you have to do all that again.

But seeing your opinions about the dependencies of DStep (which are 3) I assume you don't have any dependencies at all in your projects πŸ˜ƒ.

mihails-strasuns commented 8 years ago

That Dub checks for new dependencies for each build.

Doesn't it do so anyway already?

It might work with one or two dependencies but when you have 40 dependencies (including indirect dependencies) it's a PITA.

How is it different from doing the same in dub.selections.json? Also forcing transitive dependencies to be not the ones defined in respective projects (without any validation from test suites) is something that just plain scares me.

Though I guess it is a problem of many dub packages declaring version compatibility they don't really check.

But seeing your opinions about the dependencies of DStep (which are 3) I assume you don't have any dependencies at all in your projects

There are from 3 to 8 dependencies in our apps (if you refer to Sociomantic) which so far feels quite manageable with even something as blunt as git submodules (== always hard locking of the version) :) My opinion of dstep dependencies comes not from their count but triviality.

jacob-carlborg commented 8 years ago

Doesn't it do so anyway already?

Yes, that's what I think is unexpected for a CLI tool.

How is it different from doing the same in dub.selections.json?

Dub is generating dub.selections.json. You can add one single entry in dub.json and end up with 40 entries in dub.selections.json. My whole point is that you should not edit dub.selections.json.

Also forcing transitive dependencies to be not the ones defined in respective projects (without any validation from test suites) is something that just plain scares me

Not sure I understand.

jacob-carlborg commented 8 years ago

There are from 3 to 8 dependencies in our apps (if you refer to Sociomantic) which so far feels quite manageable with even something as blunt as git submodules

A standard Rails (3.2) project comes with six direct dependencies, resulting in 40 (the above was just an arbitrary number I picked πŸ˜ƒ) dependencies in total. That's what I have to deal with at work every day.

We probably have around 30 Rails projects. Try dealing with that manually. Of course, many of these projects are using different versions of Rails, resulting in a different dependency graph. Now apply that across a couple of different versions of Ruby as well and you have dependency hell πŸ˜ƒ.

s-ludwig commented 8 years ago

If I wanted to pin dependencies hard I could as well just specified it using ==version in dub.sdl itself, without introducing any new project file to keep in repo.

Leaving aside that it might get unmanageable for large dependency graphs, this would be fine for application packages. However, for library packages it would mean that the library is basically unusable with other libraries that have an overlapping dependency graph, because exact version dependencies are very likely to produce conflicts. dub.selections.json only applies to the root package and thus doesn't have that problem.

s-ludwig commented 8 years ago

But I don't see any reason to disallow manual edits.

Here's the deal. I want Dub to somehow look down the dependency graph for a project to ensure that the same dependencies are always installed. I though that was how dub.selection.json works but that 's currently not the case.

That is how it works (well not "installed", but "included in the dependency graph"). I don't know where the disconnect happens, but I'll try to explain the idea: dub.json basically defines the topology constraints of the graph, while dub.selections.json defines a subset, which represents a single concrete dependency graph. dub.selections.json itself isn't organized as a graph, because each package can only occur as a single version within the dependency graph (everything else would usually lead to linker errors in D's case), and thus a simple list of all packages is sufficient for a unique definition.

As soon as you start manually editing dub.selection.json you'll get into problems. The tool cannot longer given the same guarantees about the dependency graph. It will be much easier to get a dependency graph that the tool cannot satisfy. Does Dub generate a selections graph for the optional dependencies as well? If no, then you're back to square one. If yes, then why are the optional dependencies in dub.selection.json instead of in dub.json?

dub.json specifies which dependencies are considered optional, while dub.selections.json specifies if an optional dependency is chosen or not. That to me appars to be a logical approach.

The only reason to manually edit dub.selection.json is to bypass the tool to generate the looked down dependency graph. But why would you want to do that? Either advertising manually editing dub.selection.json or having features to requiring to manually editing dub.selection.json will get you the problems mentioned above.

You'll get a message whenever you do something in dub.selections.json that can't satisfy the dependency graph constraints layed out in the package recipe hierarchy, and the tool can still continue to work with the manually edited file, so it's not an all or nothing decision. But basically, yeah, there should be a CLI-way to control optional dependencies, it just hasn't been implemented.

Why? It would of course be nice to have a CLI for selecting/deselecting optional dependencies and for upgrading specific dependencies.

The solution is really simple, the optional dependencies should go in dub.json, not dub.selection.json.

dub.json does specify optional dependencies. dub.selections.json just determines if they are actually chosen or not.

s-ludwig commented 8 years ago

To me that is very unexpected from a tool, a command line tool. That Dub checks for new dependencies for each build. I would expect that from a GUI application, like a browser, but not from a command line tool.

It checks once per day and caches the results. I think this is a highly useful feature, because otherwise you'd have to constantly speculatively upgrade or monitor the registry to notice upgrade opportunities. But the console output really needs some color, because currently it's too easy to overlook such hints.

jacob-carlborg commented 8 years ago

dub.json specifies which dependencies are considered optional, while dub.selections.json specifies if an optional dependency is chosen or not.

I would expect that the if an optional dependency is used is specified in thedub.json as well. But I feel that I might misunderstand something here. I would expect it to work something like:

Application A has a dependency, library B. Library B has an optional dependency, library C. I would expect B to specify C as an optional dependency in its dub.json file. A specifies in its dub.json if C should be used or not.

Alternatively if Dub had an install command I would expect it to be to be a flag to choose if the optional dependencies should be installed as well.

That to me appars to be a logical approach.

I'm not sure if I agree with that. What's the reason to have two files the developer needs to edit? I would expect the developer should only edit dub.json and dub.selections.json is machine generated. That does not mean that I think it's necessary to have CLI command for something.

s-ludwig commented 8 years ago

Application A has a dependency, library B. Library B has an optional dependency, library C. I would expect B to specify C as an optional dependency in its dub.json file. A specifies in its dub.json if C should be used or not.

A can add a non-optional or optional+default dependency to C to force choosing it. There is no way to unchoose it, but it there was, how would conflicts be resolved or avoided?

Alternatively if Dub had an install command I would expect it to be to be a flag to choose if the optional dependencies should be installed as well.

Such a flag would surely be a possibility. With the small difference that it wouldn't tell it to install the optional dependencies, but to choose them in the context of the installed package (this would actually imply installation, too, but also means that the optional dependencies take part in the build process, which a simple installation doesn't imply - anymore, since the new optional-semantics have been implemented).

I'm not sure if I agree with that. What's the reason to have two files the developer needs to edit? I would expect the developer should only edit dub.json and dub.selections.json is machine generated. That does not mean that I think it's necessary to have CLI command for something.

Sorry, but I can't follow you there. If there is not a CLI command for doing the modifications, how else would that work? A new GUI client, or some deamon process? If there is a CLI command for all necessary operations, the developer doesn't need to edit the file anymore, if there isn't, manual edits may be necessary in some cases.

jacob-carlborg commented 8 years ago

Sorry, but I can't follow you there. If there is not a CLI command for doing the modifications, how else would that work?

All I'm talking about is that there shouldn't be two files that a developer needs to edit. It should only be one file, dub.json. I'm perfectly fine with editing dub.json manually using a text editor. I don't see the advantage of having to edit two files.

A can add a non-optional or optional+default dependency to C to force choosing it. There is no way to unchoose it, but it there was, how would conflicts be resolved or avoided?

I just looked at the documentation for optional and default dependencies. Are you supposed to specify optional and default on the same dependency in the same dub.json? I don't think I understand how optional dependencies are supposed to work.

s-ludwig commented 8 years ago

I just looked at the documentation for optional and default dependencies. Are you supposed to specify optional and default on the same dependency in the same dub.json? I don't think I understand how optional dependencies are supposed to work.

Yes, specifying both will produce an optional dependency that is chosen by default. Leaving off the default part will leave it unchosen by default. "By default" means that when no dub.selections.json exists, it will create one with/without the optional dependency present.

This part of the optional dependency semantics is based on dub.selections.json, i.e. it lets the root package control which optional packages are used. Separate from that, a package can force inclusion of an optional dependency of another package by depending on it in a non-optional or optional+default way, in the latter case still leaving the possibility open to control the final inclusion from dub.selections.json.

s-ludwig commented 8 years ago

All I'm talking about is that there shouldn't be two files that a developer needs to edit. It should only be one file, dub.json. I'm perfectly fine with editing dub.json manually using a text editor. I don't see the advantage of having to edit two files.

It's quite simple. dub.json includes all meta information of a package and dub.selections.json contains the concrete set of dependency versions used when building the package as a root package. Depending on what kind of information is changed, the appropriate file needs to be changed (by tool or by hand). Do you suggest to put everything into one file?

jacob-carlborg commented 8 years ago

Do you suggest to put everything into one file?

I suggest leaving dub.selections.json to only contain the full set of dependencies, direct and indirect. This file should also be completely automatically generated, i.e. when running dub build. Anything else should go in dub.json.

s-ludwig commented 8 years ago

Do you suggest to put everything into one file?

I suggest leaving dub.selections.json to only contain the full set of dependencies, direct and indirect. This file should also be completely automatically generated, i.e. when running dub build. Anything else should go in dub.json.

And that's already the case. What you want effectively seems to be to disallow configuring optional dependencies specific to the root project, but that can actually be very useful.

jacob-carlborg commented 8 years ago

What you want effectively seems to be to disallow configuring optional dependencies specific to the root project, but that can actually be very useful.

No, I'm against configure that in dub.selections.json. Why can't that be configured in dub.json.

It's very simple, I think that there should only be a single file that user needs to edit.

s-ludwig commented 8 years ago

No, I'm against configure that in dub.selections.json. Why can't that be configured in dub.json.

It could be configured there, but it would be redundant. dub.selections.json already naturally fills that role.

It's very simple, I think that there should only be a single file that user needs to edit.

Would you also be against adding a functionality to "dub upgrade" a single dependency (which implicitly edits dub.selections.json)? It's conceptually not much different from a function to select/deselect an optional dependency.

mihails-strasuns commented 8 years ago

We probably have around 30 Rails projects. Try dealing with that manually. Of course, many of these projects are using different versions of Rails, resulting in a different dependency graph. Now apply that across a couple of different versions of Ruby as well and you have dependency hell

You probably already know that I consider whole Ruby/Rails ecosystem completely broken and being beyond salvation? :) I am aware of only one approach to avoid dependency hell problems - self-discipline combined with rigorous continuous integration. That means:

Rails approach is exactly the opposite of all those goals. I definitely don't want that and dub right now pretty much stands on crossroads. It can go the path of verifying declared dependencies and demanding strict semver from library packages, ideally with automated beta-testing of all packages being the part of future auto-tester replacement. Or it can go Ruby way with no guarantees that any library or project is actually usable unless you use exact pinned version of everything.

jacob-carlborg commented 8 years ago
  • banning compiler/toolchain pinning
  • avoiding dependency pinning unless it is needed to workaround upstream deficiencies

Please explain who these solve dependency hell.

  • verifying all combinations of projects your declared as supported with automated tests
  • doing automated beta testing of compiler/toolchain with all involved dependencies

How do you do this with a moving target? Every time you run Dub you can get a new set of dependencies if you don't lock the dependencies. You can be running Dub on your local machine and all tests pass. Then you push to your CI system and suddenly everything breaks because you get a different set of dependencies. Semantic versioning does not help.

It can go the path of verifying declared dependencies and demanding strict semver from library packages

It's not possible to verify that a package follows semver. I would not trust anyone to use semver correctly.

What do you do if a a package specifies ">= 0" as the version for one of its dependency? I guess your answer is: don't use that package πŸ˜‰.

Someone might change an internal data structure, array to linked list, in a patch version, which is perfectly fine since if it doesn't change the API. That can cause performance regressions which can be very difficult to find.

I want Dub to be useable for anyone and not just your specific needs.

jacob-carlborg commented 8 years ago

It could be configured there, but it would be redundant. dub.selections.json already naturally fills that role.

Then you can just as well claim that having the dependencies in dub.json is redundant as well since dub.selections.json already takes care of that.

Would you also be against adding a functionality to "dub upgrade" a single dependency (which implicitly edits dub.selections.json)? It's conceptually not much different from a function to select/deselect an optional dependency.

No, I would not be against that. I actually thought that was already possible.

s-ludwig commented 8 years ago

It could be configured there, but it would be redundant. dub.selections.json already naturally fills that role.

Then you can just as well claim that having the dependencies in dub.json is redundant as well since dub.selections.json already takes care of that.

What? That is clearly not redundant. dub.json doesn't contain information to pin a version. But by its pure structure dub.selections.json already implies if an optional dependency is chosen or not - no additional field in dub.json is necessary for that.

Would you also be against adding a functionality to "dub upgrade" a single dependency (which implicitly edits dub.selections.json)? It's conceptually not much different from a function to select/deselect an optional dependency.

No, I would not be against that. I actually thought that was already possible.

So that would also manually modify dub.selections.json - I ask you where is the difference to select or deselect an optional dependency therein with a similar command?

jacob-carlborg commented 8 years ago

So that would also manually modify dub.selections.json - I ask you where is the difference to select or deselect an optional dependency therein with a similar command?

I think it's different. If I put it like this: your active choices (dependencies) go in dub.json but other ones go in dub.selections.json. Explicitly choosing an optional dependency is a active choice and should go in dub.json.

I'm tried of arguing this. I think manually editing dub.selections.json will cause problems, you don't. I guess only time will tell.

s-ludwig commented 8 years ago

If I put it like this: your active choices (dependencies) go in dub.json but other ones go in dub.selections.json

Upgrading a dependency is an active choice, too! The concept goes like this: dub.json contains all the meta information about a package and dub.selections.json contains the exact packages used for building it as a root project. But yes, this whole talk doesn't go anywhere.

mihails-strasuns commented 8 years ago

Please explain who these solve dependency hell.

Minimizing/discouraging dependency pinning prevents creation of virtual version ecosystems within the registry when there is a certain set of libraries/application that only work with certain versions and are not usable with rest of registry - but it is not actually reflected in their published spec and only can be figured out by checking repos with dub.selections.json.

Essentially, the idea is about making bad but easy approach harder intentionally harder.

How do you do this with a moving target? Every time you run Dub you can get a new set of dependencies if you don't lock the dependencies. You can be running Dub on your local machine and all tests pass. Then you push to your CI system and suddenly everything breaks because you get a different set of dependencies. Semantic versioning does not help.

Ideally - by making package registry your moderator, running approval tests with possible snapshots of (supposedly) declared dependencies. Of course checking all combinations is impossible by checking few random ones and marking package as bad if it is ever detected as "liar" is one possible solution to motivate developers to be more disciplined and thoughtful when defining their dependencies.

And for applications and not libraries I don't see any reason to specify open dependencies in main dub.sdl anyway. Those are "final product" which doesn't need to be compiled as part of other unknown project and thus don't need wide version compatibility.

It's not possible to verify that a package follows semver. I would not trust anyone to use semver correctly.

It is possible to detect if package does not follow source-applied SemVer though and issue some "punishment". When it comes to source libraries there isn't much point of speaking of SemVer in context of API - breaking change definition becomes "any project stops compiling non non-major version increase". Which is quite doable for hypothetical CI bound with registry.

Of course perfect verification is not possible. But detecting at least some violation and marking such projects hurts people pride and thus motivated them to put more effort into something they most commonly don't care about (pedantic versioning). That is the "discipline" part I have been talking about before. Going rubygem way, the contrary, embraces the sloppy approach and tries to hide it with help of the tooling.

jacob-carlborg commented 8 years ago

How do you test that a package is following semver in practice?

mihails-strasuns commented 8 years ago

Whenever new non-major version is uploaded, you try running tests for some of other already uploaded projects which are supposed to passing compiling based on the version declaration. Success doesn't guarantee anything, of course, but failure is a clear sign that semver is not followed.

jacob-carlborg commented 8 years ago

I don't think this is going to work very well.

mihails-strasuns commented 8 years ago

If a new package is uploaded there will be no dependencies on that package, i.e. you cannot run any tests when it's updated

There will be, as long as there are ~> version strings. For non major versions of course, but major ones are allowed yo break things anywgay.

A package might have a large API and the other packages that do have this package as a dependency might only use a small part of the API

Of course, this problem doesn't have reliable technical solution. The very point is to move into social engineering domain, motivating very people submitting packages to check how they define versions. Right now there is no reason to care at all.

jacob-carlborg commented 8 years ago

There will be, as long as there are ~> version strings. For non major versions of course, but major ones are allowed yo break things anywgay.

No. If I upload a new package, of course there will not be no other packages that have that newly uploaded package as a dependency because it didn't exist.

jacob-carlborg commented 8 years ago

You can also have stupid version requirements like > 0 which is only solvable by locking down the version or not allowing that version requirement in the first place.

mihails-strasuns commented 8 years ago

No. If I upload a new package, of course there will not be no other packages that have that newly uploaded package as a dependency because it didn't exist.

???

There is existing package with dependency cool_lib ~> 1.22.0. Author uploads cool_lib v1.22.1 and that other package will immediately depend on it unless dub.selections.json is committed (which is something I want to get rid of if that was not clear). CI system on registry thus can check if v1.22.1 version of cool lib doesn't break any of projects that have been using v1.22.0 before.

You can also have stupid version requirements like > 0

I believe dub must refuse to accept such nonsense dependencies if it is agreed that all version strings are SemVer compliant.

jacob-carlborg commented 8 years ago

No, I mean when cool_lib is uploaded the first time to the registry, for the first version. There can also be cases when very few packages (or none) depend cool_lib because most uses can be private, i.e. not available in the registry.

dub.selections.json is committed (which is something I want to get rid of if that was not clear)

I've said previously that dub.selections.json should be committed for applications but not for libraries. The SemVer specifications says:

"Software using Semantic Versioning MUST declare a public API"

Most of the time applications does not declare a public API.

I believe dub must refuse to accept such nonsense dependencies if it is agreed that all version strings are SemVer compliant.

I don't see how that goes against SemVer. The specification doesn't mention much of how version requirements should be specified.

mihails-strasuns commented 8 years ago

Got burned by that damn thing again. Had this line in dub.sdl:

dependency "libdparse" version="==0.5.0"

And there was also old dub.selections.json in same project dir:

"libdparse": "0.2.1"

Guess which one was chosen for build (with no warnings or errors).

s-ludwig commented 8 years ago

When I create a package with those lines, I get:

Package libdparse can be upgraded from 0.2.1 to 0.5.0. Use "dub upgrade" to perform those changes. Selected package libdparse 0.2.1 does not match the dependency specification 0.5.0 in package test. Need to "dub upgrade"? Performing "debug" build using dmd for x86_64. libdparse 0.2.1: target for configuration "library" is up to date. test ~master: building configuration "application"... Linking... To force a rebuild of up-to-date targets, run again with --force.

But unfortunately without the emphasis ;-)

mihails-strasuns commented 8 years ago

Maybe be it was added in 1.0.0? The machine in question had one of earlier releases installed and I don't see anything like that in logs.

Though the fact why it even agrees to compile version that violates dub.sdl escapes my potential for reasoning.