On 12/26/06, Eric Crahen <[EMAIL PROTECTED]> wrote:
One of the interesting parts of the discussion to read through when you have the time is the difference between development and release use cases. --- I think I would have to disagree about adding deprecation annotations being a dangerous change. The library behaves identically; line numbers in a stack trace may change, but the content and meaning and the trace is identical. The only danger really would be relying on line numbers in the stack trace, which is a questionable practice to begin with. Certainly, there are a lot of "gotchas" library owners will have to consider, but none of these are things that Ivy can just solve for everyone, even if you try to enforce a certain pattern of usage. Each library owner will have their own set of concerns, their own development process, etc. I don't believe there is a one size fits all solution. It makes sense to provide a best practices recommendation, but I think it would be a mistake to limit thought to only those solutions. Ultimately, the library owner will need to weigh these things, understand the impact what they are doing and use Ivy as a *tool* to accomplish their goal.
I strongly agree with that, and this has always be Ivy philosophy: try to adapt to several usages, and do not force the user into a single way of working. That's why I underlined that even if I strongly suggest to avoid changing the content of a version, Ivy supports this kind of process, so I consider your problem a bug which should be fixed, as long as we are talking about a changing revision. So I suggest you add a new bug report in JIRA. Regards, Xavier If you don't trust someone to be able to make a decision on how to release
their code, you don't have faith they can do something as simple as associate a name and number with it, then I'm really suprised you'd trust they could do the more complicated task of writing the code itself. On 12/26/06, Xavier Hanin <[EMAIL PROTECTED]> wrote: > > Hello All, > > Interesting discussion here, I don't have time to read everything and > catch > u^p on the discussion, but I'd like to give my opinion: > - I agree with Stephane and John that a version is a version and you > should > never change what has been released. Even adding deprecated annotations > can > change line numbers if you are not careful, and you will have troubles > inspecting a stack trace if your line numbers are not correct. And this is > just an example of all the problems you may run into when you don't > actually > know the exact content of a jar when you know its version > - Even if I believe a version is a version and should never change, Ivy > support two kind of changes in a version: > ** the module descriptor change (i.e. a change in the ivy.xml) when you > enable checkModified > ** a change of the artifacts (i.e. a jar for instance), when you declare > it > as a changing revision (either in your ivy.xml or by using the > changingPattern) > > In this last case I think that supporting cache invalidation as requested > by > Eric woud be consistent with the behaviour expected. And when you say that > your revision is changing Ivy has to check if the cache is valid each > time, > so it wouldn't introduce a new performance overhead. > > Regards, > Xavier > > > On 12/24/06, Eric Crahen <[EMAIL PROTECTED]> wrote: > > > > Thanks, I think we have just both described the need to invalidate a > > version in the ivy cache. I'll compare the two approaches objectively: > > > > In both cases I'm using a chain resolver in which the first element is > > just my local filesystem and the second is the shared repository which > > contains offical/approved copies of all internal and external libraries. > > In both cases all changes are visible only to me because we publish > > only to our filesystem. > > > > The key parts of your description are: > > "change the version for Y, then update your references." > > > > This effectively means, > > > > #1 checkout Y, change the version, fix it, publish it > > #2 checkout X, change the version because I'm changing its dependencies > > to point to the fixed Y, publish it. > > #3 check out D, change the version because I'm changing its dependencies > > to point to the fixed Y, publish it. > > #4 check out C, change the version because I'm changing its dependencies > > to point to the fixed D, publish it. > > #5 check out B, change the version because I'm changing its dependencies > > to point to the fixed C, publish it. > > #6 check out A, change the version because I'm changing its dependencies > > to point to the fixed B, publish it. > > #7 Hope that I chose version numbers that will become automatically > > obsolete > > when the official fix is released. > > > > So to fix a simple bug, locally using private versions only I can see, > in > > 1 > > package, > > I actually have to alter 6 ivy.xmls and perform 6 builds. > > > > With what I suggested I would change 2 packages. > > > > #1 checkout Y, fix it, publish it to the local override resolver > > #2 checkout A, build it. > > > > This required changing no ivy.xmls and building only 2 packages. > > > > Ultimately we have accomplished the same thing. > > > > > > The difference is that you preferred to use a very strict version > scheme, > > where as I opted to use the fact that something exists in my local > > resolver > > as an implicit private local version. > > > > The strong version comes at the cost of more work, and the amount of > > that work (changing ivy.xml and building files) is proportional to the > > number of packages. I would actually need to transitively enumerate > > my dependencies and be sure that I update the versions correctly > > in all dependencies - which may be tedious and error prone. > > > > The implied version uses the chain to resolver preference to let > > ivy to the transitive traversal for me; and since this is an unnamed > > implied version, there was no need to guess a version number. > > > > Both have visual cues, it depends on where you look. The cue in the > > strong version is in the ivy.xml and the cue in the implied version is > > existence of a file in the local repository. > > > > Which one is most suitable is a choice a developer is free to make. I > > don't Ivy needs to dictate one or the other, this really is a matter of > > preference > > and a matter of what a developer is comfortable with. Both very possible > > and valid solutions. There are situations when both are useful. > > I do not want to engage in a subject discussion about which is the right > > thing to do. > > > > Now here is what we have not addressed, which is the reason for the > entire > > thread. > > ** How do we evict these private copies from the cache when they are no > > longer > > needed? ** > > > > In the case of the strong versioning approach, part of what we have done > > is > > hope to have chosen versions that would be considered older than the > > official > > version once released. We may not have guessed right and need to remove > > that > > private local copy from the ivy cache. After all its lifetime is over, > > this > > was a private > > local copy that should no longer exist in the cache; we may to choose to > > keep it > > in the local resolver where it can be selected at any time, but it > > certainly > > has no > > need to be in the cache once its outlived its usefulness. Unless someone > > never > > makes mistakes, then maybe they will never need to invalidate the cache. > > Maybe > > some of us are just that good but I make mistakes, so I would really > like > > the ability > > to do so when needed when I use this approach. > > > > In the case of the implied version approach, we used the simple fact > that > > artifacts > > existed in the local filesystem repository to indicate that those are > the > > preferred > > artifacts to use. Now that we have a better release available in the > > shared > > repository > > we'd like to invalidate the artifacts in the cache and remove these > files > > from the resolver. > > > > BOTH describe a use-case for invalidating the ivy cache for a particular > > verison. > > > > --- > > > > One possible way to do invalidate the cache would be that erasing > resolver > > I > > described which > > would only work in association with a local filesystem resolver. > > When I published any version, then it would invalidate that version in > the > > cache. > > > > This would allow me to use that same resolver chain > > > > // psuedo-chain > > <chain> > > <filesystem name="local" local="true"/> > > <url name="shared/> > > </chain> > > > > <invalidate name="invalidate" ref="local" erase=<<optional>> /> > > > > With either approach my workflow for making local changes, regardless of > > how > > I choose to > > version, is > > > > Check out. > > Resolve with chain. > > Build. > > Publish to local repository. > > Publish to invalidate when its time to invalidate the cache. > > > > Erasing the copy of that version from the local resolver could be > optional > > to support both > > use cases where people do want to remove packages, and use cases where > > people do > > not. > > > > --- > > > > You said that you feared that people using this patching/overriding > > logic means people could make a mistake in external repositories. > > This can happen at any time regardless of the technique used to > > make local changes. This is orthogonal to using one technique or > > the other for local changes. Releases require care, which is another > > issue entirely. > > > > As to your other points 1-5 at the end or you post, this is good advice > > but orthogonal to solving the problem of making a local change and > > effectively invalidating the cache when its no longer needed. > > > > > > On 12/24/06, Stephane Bailliez <[EMAIL PROTECTED]> wrote: > > > > > > Eric Crahen wrote: > > > > > > > I've found that there is a bug in Y. > > > > Several things need to happen for me at this point: > > > > #1. > > > > I need to keep working on A. So I need to be able to patch Y. > > > > This means I need a local copy. Now you can label this > > > > Eric's-hacked-library > > > > > > This means fix the bug, change the version number or append an > > > additional string or whatever that match your status. Then store it in > > > your repository. Then update your references so that you force the use > > > of this specific version. > > > > > > You must strive to have y-1.1-patched-by-eric.jar > y-1.1.jar or > > > y-1.1-patched-by-eric.jar evicting y-1.1.jar depending your internal > > > policy., etc... > > > When a version 1.2 will be released (which hopefully will incorporate > > > your patch), then 1.2 automatically obsolete 1.1-patched-by-eric (unless > > > the version is really forced with force=true) > > > > > > When you do this dependencies are really managed rather than hacked > and > > > there is always the visual element to make sure that the version that > is > > > included is really the latest version and it conveys immediately the > > > information that this dependency is patched. > > > > > > > > > If we follow this patching/overriding logic, that means that people > > > could well do the same on external repositories and silently swap one > > > jar with another patched version because they are too lazy to do a > > > release, which basically means that 2 people could be using the same > > > version with a different code. That's brilliant to convince developers > > > to commit suicide. :) > > > > > > And this is also another reason why I don't use external repositories. > > > 1) I trust no one. > > > 2) dependencies are generally not well expressed > > > 3) versioning is sometimes not even well done correctly > > > 4) I keep full control of all my dependencies > > > 5) I have flexibility. > > > > > > -- stephane > > > > > > > > > > > -- > > > > - Eric > > > > > > -- - Eric
