https://common-lisp.net/project/asdf/asdf.html#Version-specifiers
So I can say that my system depends on a (:version :OTHER "x.y.z") which means a version >= x.y.z. Can I say explicit enforce a dependency of a particular version ? That is version equal of x.y.z instead of greater-than-or-equal x.y.z?
Best,
Alexandre Rademaker http://arademaker.github.com/
On 3/16/16 Mar 16 -6:52 PM, Alexandre Rademaker wrote:
https://common-lisp.net/project/asdf/asdf.html#Version-specifiers
So I can say that my system depends on a (:version :OTHER "x.y.z") which means a version >= x.y.z. Can I say explicit enforce a dependency of a particular version ? That is version equal of x.y.z instead of greater-than-or-equal x.y.z?
Best,
Alexandre Rademaker http://arademaker.github.com/
No, I am afraid you cannot do that yet. I have long wanted to add version upper bounds. This would be very useful for cases where one knows that a library has changed its API, but you have not yet adapted your system to the changed API. [Think of all of those systems that still must be compiled with old GCC, or that use Python 2, instead of 3, etc.]
The semantics might require a little thought. If we have (:version<= :other "x"), is that satisfied by "x.1"? I think probably so -- we'd want this to be violated only by x+1, but of course (:version<= :other "x.0") should be violated by "x.1". This is in spirit the same as the way the current version-satisfies works, but arithmetically slightly different.
Similarly, do we want :version<= or do we want (:version :other <lower> [<upper>]) perhaps (:version<= :other "x.y") should be syntactic sugar for (:version :other "0" "x.y")
[If you publish a library with a version that's less than zero you deserve whatever bad thing happens to you!]
I would be happy to accept a patch, but otherwise you'll have to wait for me to get around to it. Sadly, I'm badly blocked now, because I don't have a dedicated ASDF machine, and my current ASDF test machine for linux and windows is being chewed up running over a hundred hours of experiments; I can't predict when I will be able to run the linux and windows tests and release 3.1.7. In the worst case not until mid to late April. This isn't ideal, but my company owns the machine, and the work I do for them has to come first.
Best, R
Hi Robert,
Yes, sure that you have to dig into this issue for a while for came up with a good solution, this is not a trivial problem. Moreover, Quicklisp way to distribute systems would be another difficulty, right? Quicklisp does not deal with versions; the systems are packed in distributions.
Best,
Alexandre Rademaker http://arademaker.github.com/ http://researcher.ibm.com/person/br-alexrad
On Wed, Mar 16, 2016 at 9:06 PM, Robert Goldman rpgoldman@sift.net wrote:
On 3/16/16 Mar 16 -6:52 PM, Alexandre Rademaker wrote:
https://common-lisp.net/project/asdf/asdf.html#Version-specifiers
So I can say that my system depends on a (:version :OTHER "x.y.z") which means a version >= x.y.z. Can I say explicit enforce a dependency of a particular version ? That is version equal of x.y.z instead of greater-than-or-equal x.y.z?
Best,
Alexandre Rademaker http://arademaker.github.com/
No, I am afraid you cannot do that yet. I have long wanted to add version upper bounds. This would be very useful for cases where one knows that a library has changed its API, but you have not yet adapted your system to the changed API. [Think of all of those systems that still must be compiled with old GCC, or that use Python 2, instead of 3, etc.]
The semantics might require a little thought. If we have (:version<= :other "x"), is that satisfied by "x.1"? I think probably so -- we'd want this to be violated only by x+1, but of course (:version<= :other "x.0") should be violated by "x.1". This is in spirit the same as the way the current version-satisfies works, but arithmetically slightly different.
Similarly, do we want :version<= or do we want (:version :other <lower> [<upper>]) perhaps (:version<= :other "x.y") should be syntactic sugar for (:version :other "0" "x.y")
[If you publish a library with a version that's less than zero you deserve whatever bad thing happens to you!]
I would be happy to accept a patch, but otherwise you'll have to wait for me to get around to it. Sadly, I'm badly blocked now, because I don't have a dedicated ASDF machine, and my current ASDF test machine for linux and windows is being chewed up running over a hundred hours of experiments; I can't predict when I will be able to run the linux and windows tests and release 3.1.7. In the worst case not until mid to late April. This isn't ideal, but my company owns the machine, and the work I do for them has to come first.
Best, R
On 3/17/16 Mar 17 -8:53 AM, Alexandre Rademaker wrote:
Hi Robert,
Yes, sure that you have to dig into this issue for a while for came up with a good solution, this is not a trivial problem. Moreover, Quicklisp way to distribute systems would be another difficulty, right? Quicklisp does not deal with versions; the systems are packed in distributions.
No, quicklisp relies on ASDF at its base, so this would not cause a problem for Quicklisp.
R
On Wed, Mar 16, 2016 at 8:06 PM, Robert Goldman rpgoldman@sift.net wrote:
No, I am afraid you cannot do that yet. I have long wanted to add version upper bounds. This would be very useful for cases where one knows that a library has changed its API, but you have not yet adapted your system to the changed API. [Think of all of those systems that still must be compiled with old GCC, or that use Python 2, instead of 3, etc.]
I strongly disagree. If a controversial major incompatibility is introduced that causes a lot of software not to migrate to the new API, the right thing to do is to fork the damn library. Either the old API or new API will have to go by a new name.
You can keep calling your software informally Python 2 and Python 3, but the system-name as far as ASDF is concerned will be "cl-python2" and "cl-python3". If the old one was called "cl-python" and you want to keep the name after the major incompatible API changes, you have to tell those who refuse to upgrade that they will have to fork your library and they will from now on have to use "cl-python2" as their dependency instead of "cl-python".
ASDF has restrictions on the version strings it accepts. It's OK to have restrictions on the naming conventions users may have. No, you can't have two divergent majorly incompatible libraries have the same name, be distinguished by version only, and expect the ASDF version system to help you. Just nope.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org - We're all different. - I'm not!
On 3/17/16 Mar 17 -4:21 PM, Faré wrote:
ASDF has restrictions on the version strings it accepts. It's OK to have restrictions on the naming conventions users may have. No, you can't have two divergent majorly incompatible libraries have the same name, be distinguished by version only, and expect the ASDF version system to help you. Just nope.
I strongly disagree.
If you know that a system will blow up with an inconsistent library version, and you can save your users confusing and misleading error messages by simply causing ASDF to cough up a clear error message telling you that there is a version incompatibility, there is no reason not to support that. Not only is there no reason not to, it's outright wrong not to. It causes misery in users and produces no benefit.
On 3/17/16 Mar 17 -4:21 PM, Faré wrote:
I strongly disagree. If a controversial major incompatibility is introduced that causes a lot of software not to migrate to the new API, the right thing to do is to fork the damn library. Either the old API or new API will have to go by a new name.
In turn, I disagree with this claim strongly.
If I'm the downstream consumer, I can't force the upstream producer to change the names of everything when he or she changes the API. (Indeed, in the real world, the upstream producer may not even realize when he or she has broken a dependent system). So that won't work.
OK, so you say in that case the old API will have to go by a new name. But that doesn't take into account a world in which software development resources are finite and often inadequate: if I don't have time to adapt to an API change at the current time (the use case for a version upper bound), I CERTAINLY won't have time to fork the upstream library, rename everything, and rename everything in my client.
On Thu, Mar 17, 2016 at 6:10 PM, Robert Goldman rpgoldman@sift.net wrote:
On 3/17/16 Mar 17 -4:21 PM, Faré wrote:
I strongly disagree. If a controversial major incompatibility is introduced that causes a lot of software not to migrate to the new API, the right thing to do is to fork the damn library. Either the old API or new API will have to go by a new name.
In turn, I disagree with this claim strongly.
If I'm the downstream consumer, I can't force the upstream producer to change the names of everything when he or she changes the API. (Indeed, in the real world, the upstream producer may not even realize when he or she has broken a dependent system). So that won't work.
OK, so you say in that case the old API will have to go by a new name. But that doesn't take into account a world in which software development resources are finite and often inadequate: if I don't have time to adapt to an API change at the current time (the use case for a version upper bound), I CERTAINLY won't have time to fork the upstream library, rename everything, and rename everything in my client.
Once again, it's OK to use a horrible kluge when under pressure. But while it's a solution for the INTEGRATOR who releases an application that depends on an old variant of the library it is no permanent solution for the USER whose system uses an obsolete API. And if you are to go forward as the WRITER of the library that uses an obsolete API, then some day you'll have to pay, one way or the other. In other words, you've just accrued TECHNICAL DEBT. To pay it, you may:
1- Fix your project to use the latest upstream library (or switch to another, better one). 2- Introduce a backward compatibility library that implements the old API on top of the old one (or of different better-managed library). 3- Fork the upstream library because it sucks and/or has stopped supporting your use case, and rename everything with a few regexps. 4- Take over the upstream library, declare the new API a heresy, and the old API the One True API. That works great if the library dies or falls into being unmaintained and unused, and you are its only user and/or few users if any have adopted the new API because it actually sucks. 5- Fork the entire world, declare that the new API never happened. It's very much like option 4, except that the rest of the world doesn't believe you. 6- Your lucky project manages to die and/or you manage to leave it before having to pay its debts. Yay! "Not my problem anymore."
Declaring an upper limit on version compatibility is a semi-formal way of going into solution 5 or 6.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org You may easily play a joke on a man who likes to argue — agree with him. — Edgar Waston Howe
for some 0.02, this is my high-level perspective:
the name of an entity/concept is some letters/sounds/notation that we humans use to point to it while communicating with each other. sometimes we use computers to achieve that, e.g. when packaging a library together with a .asd file.
from this perspective, the question is: should names in the ASDF model be a simple string of characters, or should they be represented as a more formal encoding that includes the state of the entity being pointed to (i.e. the version information).
IOW, for me the question boils down to this: shall ASDF implement version control features?
and looking at the unfortunate fact that source code is still saved into flat text files today, and at the complexity/requiremenets of git & friends to deal with the state of these text files, my gut reaction is no, it should stay far away.
professional integrators should use professional VCS systems to mark specific states of the entities they are integrating. i think anything less is just wasted efforts that grows complexity without solving the issue beyond the trivial cases. e.g. what about quicklisp, or integrators in general? shall they bundle different versions of the same system (they can't, because the lisp package namespace is shared)? or will they just resort to whichever tools they are using to resolve the integrator's headaches and just entirely ignore the new ASDF feature?
FTR, for our libs i use darcs and overlapping tags to keep track of the collective state of the dependencies when packaging various different apps that use various different subsets of these dependencies. for foreign libs i also use whichever VCS is used to publish them.
I think that your argument suffers from mixing together the concepts of "version control" and "versioned software." Version control is indeed the concern of version control systems such as git and subversion. But versioned software is not, as witness the use of version management in software installation systems such as RPM and apt.
Indeed, if everything is managed in a single, or a set of interconnected VCSes, version control is less important, as you point out. However, when one is not using VCS, e.g., when using quicklisp, or assembling software oneself from multiple locations, versioning (not version control) is important to efficiently assemble a coherent set of subsystems.
Even when using VCS it can be helpful. I work with people who concurrently work on multiple different lisp-based projects. Those projects use different mixes of libraries, and at times even different versions of the same library in different projects. Sometimes, inadvertently, ASDF settings can bleed through from one project to another. In such cases -- event when VCSes are pervasively used -- it can be quite helpful to have version metadata.
Best, r
On Fri, Mar 18, 2016 at 9:58 AM, Robert Goldman rpgoldman@sift.net wrote:
I think that your argument suffers from mixing together the concepts of "version control" and "versioned software." Version control is indeed the concern of version control systems such as git and subversion. But versioned software is not, as witness the use of version management in software installation systems such as RPM and apt.
I'm precisely distinguishing the two concepts, and trying to establish a finer distinction between the roles involved in using them.
Note that ASDF version strings, that you here call "versioned software", are really an API compatibility version, and thus maybe Dan Barlow was right to model them after Linux .so numbers, even though the "major number as compatibility breaker" didn't pan out in the end, due to the model of Lisp software distribution as source differing from the model of C software distribution as binaries. So let's speak of software versions and version control vs api versions and api constraints.
As a WRITER or one system B and USER of another system C, you have control both software version and api version for B, but you don't control software version for C and can only loosely specify api constraints for C.
As a WRITER of C, you control both software version and api version for C, but neither software version for B, nor api version for B. [[[Although — maybe we could add a :breaks statement in the defsystem for C, just like Debian does. This would allow you to warn users against using known-broken combinations. Or this could be specified in a separate file that comes with C. In any case, you should only be allowed to specify known constraints about past releases, and that means putting the incompatibility constraint in C and not in B.]]]
As an INTEGRATOR of application A, you control all software versions for all transitive dependencies of A on your system, including B and C. Since this trumps control over api versions, you have no interest whatsoever in adding constraints on api versions, because they would be redundant underspecifications. You check the existing ones, but you don't need gratuitously add your own. You otherwise try to be a USER of all dependencies and if possible a WRITER of none, though you sometimes have to make local patches to B and/or C.
If as a USER or INTEGRATOR you have local patches to some dependencies, and want to register the incompatibility because it is not going to be resolved any time soon, then send a patch to C that declares the incompatibility with old versions of B. But patching B to declare incompatibility with future versions of C is always the wrong thing. See previous email about the right things you may do.
Indeed, if everything is managed in a single, or a set of interconnected VCSes, version control is less important, as you point out. However, when one is not using VCS, e.g., when using quicklisp, or assembling software oneself from multiple locations, versioning (not version control) is important to efficiently assemble a coherent set of subsystems.
An integrator should always be having every version under control. If he doesn't, it's his fault when things go south for him and he can't build software anymore. Quicklisp DOES use version control. Every distribution has a date that specifies a coherent set of tarballs. When you update Quicklisp, you update all the tarballs at once coherently, and that's the right thing.
Even when using VCS it can be helpful. I work with people who concurrently work on multiple different lisp-based projects. Those projects use different mixes of libraries, and at times even different versions of the same library in different projects. Sometimes, inadvertently, ASDF settings can bleed through from one project to another. In such cases -- event when VCSes are pervasively used -- it can be quite helpful to have version metadata.
It's OK to have different mixes of libraries. Check the diverging bits in separate file hierarchies and export a different CL_SOURCE_REGISTRY. To prevent accident, maintain hygiene and have different windows of different colors. If no top-level project is visible from the CL_SOURCE_REGISTRY of the other projects, you have a simple way to prevent building something in the wrong environment. You'll want separate Emacs processes each with its own SLIME, anyway.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org It is proof of a base and low mind for one to wish to think with the masses or majority, merely because the majority is the majority. Truth does not change because it is, or is not, believed by a majority of the people. — Giordano Bruno (1548-burned at the stake, 1600)
On Wed, Mar 16, 2016 at 7:52 PM, Alexandre Rademaker arademaker@gmail.com wrote:
https://common-lisp.net/project/asdf/asdf.html#Version-specifiers
So I can say that my system depends on a (:version :OTHER "x.y.z") which means a version >= x.y.z. Can I say explicit enforce a dependency of a particular version ? That is version equal of x.y.z instead of greater-than-or-equal x.y.z?
No you can't, and I actually object to such a counter-productive feature EVER being made part of ASDF. It very much goes against the principle of ASDF configuration:
"THOU SHALT ALLOW EACH ONE TO CONTRIBUTE WHAT ONE KNOWS WHEN ONE KNOWS IT, AND THOU SHALT NOT EITHER REQUIRE OR ALLOW ANYONE TO CONTRIBUTE WHAT ONE DOESN'T ACTUALLY KNOW."
Declaring incompatibility with old versions you know is good. You've seen those versions, you know why trying to use them will cause headaches to whoever tries to use them (and to you when they come whining about it). So you forbid them. Users must use a newer version with fixes to known issues. Fewer headaches.
Declaring incompatibility with future versions you can't possibly have seen is a lie, and it's evil. Not only you can't know that they will be incompatible, but anyone who isn't an utter idiot knows that sooner or later there will be a bug found in that dependency, an essential feature lacking, or worse, a major security issue, that will cause its version to be bumped past what you arbitrarily declared to be the maximum compatible value. People will HAVE TO upgrade, and your declaration only makes it harder, for now they will have to patch out your declaration. If other idiots followed your lead, maybe hundreds of libraries will have to be recursively patched to account for the version change in some dependency at the bottom of the dependency graph. Major idiotic move.
BIG DESIGN PRINCIPLE: There are three distinct roles with respect to a software system. 1- AUTHOR: Writing the system. 2- USER: Using the system in another system. 3- INTEGRATOR: Assembling a bunch of systems into an overall application/set of applications/deliverable/machine image/etc.
It is the INTEGRATOR, in role 3, whose job it is to build software together, make sure that all libraries are mutually compatible, pass all tests, are actually usable, etc. He and only he should have the last say as to which exact version is used for each and every library. And if he isn't completely incompetent, he keeps all those libraries under some kind of version control. An example competent integrator is Xach and his quicklisp.
When you're specifying dependencies in a .asd file, you're a USER in role 2 with respect to that dependency. Anything you do to prevent future upgrade is a stupid counter-productive move that only gets in the way of the future INTEGRATOR.
A .asd file is a tool for role 1 and role 2, and NOT for role 3. If some weird integrator wants to use an asd file to track versions, rather than git, he's wrong, because for most libraries asd version strings do not completely identify the exact code being used. Even assuming asdf version strings were enough, and/or were a useful checksum, this still shouldn't be a feature of a regular ASDF system. If this software integrator wants to specify exact and/or future versions in a defsystem, he first will have to define a subclass of SYSTEM that will allow those specifications.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org Obama's economic policies will be so remembered that he'll be the president picked for the face on the hundred trillion dollar bill.
On 3/17/16 Mar 17 -4:10 PM, Faré wrote:
No you can't, and I actually object to such a counter-productive feature EVER being made part of ASDF. It very much goes against the principle of ASDF configuration:
"THOU SHALT ALLOW EACH ONE TO CONTRIBUTE WHAT ONE KNOWS WHEN ONE KNOWS IT, AND THOU SHALT NOT EITHER REQUIRE OR ALLOW ANYONE TO CONTRIBUTE WHAT ONE DOESN'T ACTUALLY KNOW."
Declaring incompatibility with old versions you know is good. You've seen those versions, you know why trying to use them will cause headaches to whoever tries to use them (and to you when they come whining about it). So you forbid them. Users must use a newer version with fixes to known issues. Fewer headaches.
With all due respect, this is simply factually wrong, as I have illustrated in earlier emails and have seen in practice.
Here is a concrete case THAT HAPPENED TO ME:
1. XMLS had a bug that would cause it to crash when it read an XML file with processing directives. One of our systems, call it system A, needed this to be fixed.
2. I fixed XMLS to be robust to this, but at the cost of incompatibility in the API. I bumped the revision number to X.
3. System A recorded that it depended on XMLS version X.
4. Another system, call it System B, did not need this fix, and had an imminent delivery. This system relied on an XMLS version LESS THAN X. Note: The system B developers knew good and well -- in direct contradiction to your claim -- that they were incompatible with version X of XMLS. They were not lazy, they could not be forbidden to use version X-1 -- they had an important shipping deadline, which did not permit them to mess around with adapting to version X of XMLS. It would have been entirely reasonable for them to record that they were incompatible with version X in their system definition file, and that would have been A Good Thing, because no one would have been confused by an error message if they had inadvertently updated to XMLS version X.
This example, and related examples (e.g., C code incompatible with the latest GCC, Python code incompatible with Python 3), give an existence proof that your claim (that the client system will never know it's forward-incompatible with a version of one of its libraries) is factually incorrect.
Your argument seems to assume away real world considerations like "I need to ship by Monday and I have three features to add and I don't have time to mess around with code that already works for me, just because a library supplier has decided to change an API," and "I don't want one of my colleagues or customers to be confused if they accidentally install the bleeding edge of this library, which I know is not compatible. So I'll record this fact in my system definition."
Software distributions often ship with multiple versions of software (GCC, JDK, Python, perl, etc) because there are lags between updates in those software systems and downstream systems that depend on them.
For these reasons, upper bounds on library compatibility are entirely reasonable.
Best, r
With all due respect, this is simply factually wrong, as I have illustrated in earlier emails and have seen in practice.
Here is a concrete case THAT HAPPENED TO ME:
- XMLS had a bug that would cause it to crash when it read an XML file
with processing directives. One of our systems, call it system A, needed this to be fixed.
- I fixed XMLS to be robust to this, but at the cost of incompatibility
in the API. I bumped the revision number to X.
System A recorded that it depended on XMLS version X.
Another system, call it System B, did not need this fix, and had an
imminent delivery. This system relied on an XMLS version LESS THAN X. Note: The system B developers knew good and well -- in direct contradiction to your claim -- that they were incompatible with version X of XMLS. They were not lazy, they could not be forbidden to use version X-1 -- they had an important shipping deadline, which did not permit them to mess around with adapting to version X of XMLS. It would have been entirely reasonable for them to record that they were incompatible with version X in their system definition file, and that would have been A Good Thing, because no one would have been confused by an error message if they had inadvertently updated to XMLS version X.
This example, and related examples (e.g., C code incompatible with the latest GCC, Python code incompatible with Python 3), give an existence proof that your claim (that the client system will never know it's forward-incompatible with a version of one of its libraries) is factually incorrect.
Your argument seems to assume away real world considerations like "I need to ship by Monday and I have three features to add and I don't have time to mess around with code that already works for me, just because a library supplier has decided to change an API," and "I don't want one of my colleagues or customers to be confused if they accidentally install the bleeding edge of this library, which I know is not compatible. So I'll record this fact in my system definition."
Software distributions often ship with multiple versions of software (GCC, JDK, Python, perl, etc) because there are lags between updates in those software systems and downstream systems that depend on them.
For these reasons, upper bounds on library compatibility are entirely reasonable.
Emergency patches are sometimes necessary, but they are not meant to be permanent solutions. It's sometimes necessary to do gross hacks due to imminent deadlines but that's not a reason to bless them as the right way to do things.
If your system depends on xmls 1.2 but won't work with xmls 1.3, there are three real permanent solutions: a) fix your system and/or the latest xmls so they will work together, and declare a dependency on the latest (maybe fixed) xmls. b) fork xmls 1.2 to preserve its API and/or implementation forever, since it is somehow superior for your purposes. c) introduce a new system xmls-1.2-compatibility that implements the missing pieces of the xmls 1.2 API on top of the xmls 1.3 API, if that's possible and sufficient for your purposes but the maintainer somehow refuses to do so.
But pretending that there is still a single entity "xmls" when in actuality there has been a fork in the API with permanent divergent user communities, is always the wrong thing to do. It's as if ffmpeg and libav both kept the same name despite being complete forks.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org Politicians are like rats. What they steal for themselves is minuscule compared to what they destroy getting it.
I think the central point of difference between you and me is that you think of this as a moral issue, whereas I think of this as an issue of providing a service that fits a case that occurs, about which I don't have strong moral feelings.
Throughout this discussion, your arguments have been of the "should" form, and my arguments of the "this happens" -- although possibly it's not a good thing (even a Bad Thing) -- form.
To be honest, I don't see why you are so exercised about this. If you don't want to use an upper bound: don't. For the rest of us, who would like it, why does it bother you so much for us to have it?
At present, I don't have time to put this capability into ASDF, but I will happily accept a patch that does.
Best, r
On Thu, Mar 17, 2016 at 7:06 PM, Robert Goldman rpgoldman@sift.net wrote:
I think the central point of difference between you and me is that you think of this as a moral issue, whereas I think of this as an issue of providing a service that fits a case that occurs, about which I don't have strong moral feelings.
No, I use the "moral" vocabulary with no stronger feelings than you have about providing a service that fits a case that occurs. My "should" and your "fit" are actually the same concept under different names. — My apologies for any misunderstanding due to this mismatch in vocabulary being used.
I believe the central difference between our stances is that I have recently come to clearly distinguish the two roles of USER and of INTEGRATOR, that most people seem to confuse at times, and maybe you included at this time.
As a USER of library XMLS, you have no right to exclude future versions. That's just not one of your prerogatives. If you're permanently unhappy with the new versions, you can fork project XMLS, but you can't declare the future out of existence.
As an INTEGRATOR of a project that uses library XMLS, you're very much dealing with the present, and indeed, may and sometimes MUST include unreleased patches to it, and/or withhold upgrade to a new version with unresolved issues. That's not just your prerogative, that's your duty and the whole point of your job.
As a WRITER of library XMLS, you get to specify the right way to use it, to deprecate old usage patterns, etc. If you frequently break things under the feet of your users without offering a simple way to upgrade and without sending patches to your known users, you'll piss them off and maybe they'll fork the project under your feet eventually or attempt a hostile takeover. Then there will be two projects with distinct names and/or even more confusion. So be nice, and try to offer them easy upgrade paths, etc. But ultimately, you're the master of your ship, and if you decide an old API was buggy, a concurrency and/or security issue, an unsalvageable mess that cannot be saved — it's your call to tell your users to man up and adopt the new better API that solves those essential issues. Or maybe you should be forking your own project and changing its name if fixing it requires a completely new API and there's no plan to support existing users.
Often, the same developer wears multiple caps part-time: co-WRITER of a library A, USER of it in some system B you also co-write, and INTEGRATOR of some application C that includes it. That's OK. But keep things separate.
As a WRITER of system B and USER of library A, you can read the git repo of A, but cannot assume write access to it. And you just cannot assume that every future INTEGRATOR of every future application C1...CN will be using any particular version of A; indeed an "emergency due to an imminent deadline" may very well force each of said INTEGRATOR at completely different times to each include an urgent security patch to A, or a forced upgrade, etc. Unless system B is never ever used by any other application than a single application C, you just cannot assume control over C when you write system B. And if you can, then B is actually C and specifying a prohibition on future version adds little or nothing to the exact version of A recorded in the source control for C: as an INTEGRATOR, unless a mere USER, you *do* keep each and every dependency under source control.
Note that in the case of ASDF, the WRITER of ASDF is both the writer of a library, ASDF itself, and or an application, ASDF-TOOLS that tests ASDF. As the former, you specifically want to NOT specify any dependency, as ASDF the library must be capable of running with any and every past present and future version of every non-broken system. As the latter, you're an integrator and want a completely reproducible set of libraries based on which to run your tests. Our current use of git submodules addresses both usage cases, though awkwardly so. Another solution might be to split ASDF-TOOLS into a separate repository indeed.
The .asd file for system B is authored by the WRITER of B who is as such a USER of A, and has no control or relationship to the INTEGRATOR of C.
To be honest, I don't see why you are so exercised about this. If you don't want to use an upper bound: don't. For the rest of us, who would like it, why does it bother you so much for us to have it?
Maybe because I just quit my job over this very issue.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org Paradoxes only exist in language, not reality. — Eric S. Raymond