Details
-
Type:
Improvement
-
Status:
Closed
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 2.2.2, 3.0-alpha-3
-
Component/s: None
-
Labels:None
-
Environment:Linux, JDK 1.5
-
Complexity:Intermediate
-
Number of attachments :0
Description
install:install (from maven-install-plugin) by default uses DefaultArtifactInstaller to install artifacts. DefaultArtifactInstaller in turn uses FileUtils.copyFile(), thereby overwriting destination files even if they are unchanged. It would be helpful if DefaultArtifactInstaller used FileUtils.copyFileIfModified() instead, at least as an option, to speed up the build process.
Issue Links
- is depended upon by
-
MINSTALL-39
Maven Install Plugin always copy the artifact in the repository, even if there was no changes
-
Activity
This is completely wrong, and makes Maven3 very cumbersome (if not completely broken) to work on branches, especially with regarding POMs. What happens:
Check out a trunk of your project (let's suppose all files are modified today T0):
- svn checkout
- mvn clean install
Then, tomorrow T1 do a branch of your project, and modify for example the POM of your project in branch.
- svn branch it
- mvn clean install
Then, next day T2, return to trunk and continue work (but for example's sake, do not modify the POM you changed in branch).
- svn switch back to trunk
- mvn clean instal
Obviously T0 < T1 < T2
But, the change done in T1 will be not replaceable by the 2nd trunk build (mvn clean install in T2 will NOT replace the pom in local repo), and potentionally will result in very spurious errors (ie. in branch you remove/add deps, change parent, etc).
Please, undo this! Thanks.
Interestingly, this will fit nicely with Git (git will "touch" the file when switching back from branch to "master")
http://git.or.cz/gitwiki/GitSvnComparsion
http://git.or.cz/gitwiki/GitFaq#Whyisn.27tGitpreservingmodificationtimeonfiles.3F
But in general, on "install" goal Maven should install the files I told it to install.
Even if this is reverted, the above will run into problems if you don't do a complete rebuild every time you switch branches. I would advocate renaming the version on your branches (using the versions plugin, or created with release:branch, for example), if they are not actually the same development version of things.
However, an option to force installation would be a helpful thing to add.
The fact is, that I did full rebuild, and was completely puzzled after T2 why my build fails with - well, let's say "strange" at least - error. All three builds (T0, T1 and T2) were full builds.
And as I noted the same thing on MavenDev list: if maven "best practice" requires you to have different version on every existing branch, how this fit Git or any other Distributed SCM? Who will coordinate these versions, that may exist in multiple Git repositories out there?
I still believe the answer to be workspaces in the local repository, but that proposal didn't get any traction.
Having read the list now, I think there was a pragmatic solution proposed with regards to the timestamps, that combined with an option to override, would provide a suitable alternative here.
I think the problem here is that you are dirtying your target directory while performing all these switches. I don't mean to sound anything but polite, but I have never seen anyone ever do that; separate checkout directories are the norm for concurrent work. If you switch back and forth, you should clean the target first.
Brett, for now, I believe that having separate settings.xml (with separate local repo path) will solve my problem. Will be PITA, but can live with it.
Paul, I do have separate checkouts. This is about local repository (~/.m2/repository), not having files installed properly. Even with my example above, where I did wrote "svn switch", you can do following instead to reproduce it:
checkout all (checkout repo root, if you have /trunk, /tags, etc in root) and simply do this instead of switch:
cd trunk
do build
cd ../branches/branchX
cd build
cd ../../trunk
do build
Same problem (if the branchX has newer POM than trunk, as I wrote above). And my cmd was always "mvn clean install" (so did clean target dirs). And T0, T1 and T2 builds were running sequentially, one by one.
I don't think the problem Tamás is experiencing has anything to do with this problem and the fix implemented.
The problem here was that install ALWAYS copied files to their destination. The fix changed this to copy the files only if their timestamp is newer than the destination's timestamp.
Tamás problem is that files are not copied even though their timestamp is newer than the destiniation's (assuming that "do build" means "mvn clean install").
Okay, just to assure all the skeptics here:
- svn co svn://svn.graffen.dk/MNG4368 mng4368
- cd mng4368/trunk
- mvn clean install
- cd ../branches/featureX
- mvn clean install
And here, the branch pom is not installed (the difference between trunk and featureX is that featureX uses junit 4.4). This can hose your build just like that. Also note, that steps of "svn co" and "cd ../branches/featureX" could be swapped with something like "and now get the same stuff's featureX branch from another Git repo". I just used SVN for easy reproducibility. Also, while in case of centralized SVN, maintaining "versions per branch" (that is considered as best practice) is possible, in Distributed SCM case it is impossible.
But this is not all. Now go, and edit the trunk pom and featureX pom, and make them have packaging "jar", and repeat the steps. In this case, it works.
According to Benjamin Bentmann, this is due to the reason, that with packaging "pom", the pom is treated as artifact to be installed (the fix in this JIRA is applied). With packing "jar", the pom is just repository metadata (the fix in this JIRA is not applied). Hence, it's somehow inconsistent too.
Just for the record, am using Maven3:
[cstamas@marvin trunk]$ mvn -v
Apache Maven 3.0-SNAPSHOT (r887874; 2009-12-07 11:12:32+0100)
Java version: 1.6.0_17
Java home: /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home
Default locale: en_US, platform encoding: MacRoman
OS name: "mac os x" version: "10.6.2" arch: "x86_64" Family: "mac"
[cstamas@marvin trunk]$
Why do you have two branches installing to the same groupId:artifactId:version?
Paul, you are missing the point. I created this SVN example project only to present the problem.
What I wanted to emphasize, that today, when Git (and DSCM-s in general) are more and more widely accepted, a projectX may exist in multitude of Git reposes out there. None of them are "mine" (are governed by me), so i cannot "manage"/control what version they use when forked a git repository.
My point is, that the "best practice" of having distinct version (or better G:A:V) per branch works nicely with centralized SCMs like CVS/SVN. But hardly with any DSCM.
The case that happened to me was exactly the same: had built same project's different branches, coming from different Git reposes (but the different Git reposes were mirroring same master SVN repo!).
Are you saying that with Git branches, you also don't have access to the branched POM to update the version?
I frequently have a similar workflow as Tamás, in my case with short lived bug branches (less than a week) that get incorporated back into the trunk/mainline. I feel the proposed flow to change the version number would expand the workflow unnecessarily. Note that these branches aren't used by other developers, merely as a location for me to commit, test, refactor, and reintegrate with the mainline when ready. I run clean install before integrating to ensure the branch and trunk is buildable. I have used the versions plugin and it's very useful, but in this case the flow works well (in Maven 2.2.1) without requiring me to switch the version when I create the branch, and switch it back when I merge into the mainline.
I agree, having two different checkouts of the same code (in my work usually two different revisions of trunk or the same branch when I'm tracing bugs introduced to the code by someone else)
is natural thing.
But this means that you cannot do any install optimizations based on file timestamp. Forcing users to manually "clean" previous version from the local repo would not be a good solution.
I don't believe changing the version within your POM is an unnecessary burden. It sounds reasonable and smart to do so no matter how short or long your branch lives.
But that's the point, I checkout a source from some Anonymous guy's Git repository, so it's not mine source, and before I am able to build it, have to modify POMs and have local changes? Sounds awkward to me.
Here, a typical example: look how many different Git reposes (that forked from each-other but is not interesting right now) with different branches exists.
http://github.com/jquery/jquery/network
http://github.com/jquery/jquery/network/members
My 2 cents.
"I don't believe changing the version within your POM is an unnecessary burden. It sounds reasonable and smart to do so no matter how short or long your branch lives."
Yes, it is. Quite often developers work on their own branches to add some feature that will then be integrated back to main. This is expecially true with git. Requiring them to change versions makes merging that much harder.
Furthermore, taking the attitude that the Maven developers know best how other developers should work usually leads to resentment and people coming to dislike the tool.
Granted, what is considered a "burden" is subjective; there's no point in trying to arguing that point further. I am open to other suggestions.
having developers to either change the version, or using a new local repo per branch is nearly impossible.
socially is is a suicidal to ask 100+ developer to do that.
Either way is a problem, but the fix will create more problem.
Please revert or make it a option on command line, a good compromise
why should I always change versions when creating a branch? or a clone of git/hg? don't you get conflicts all over the place when you attempt to merge it? or even worse you can apply the branches' version to the main trunk.
I can imagine doing so for a long time branch (like m2 vs m3) but not for the short term "will it work or not" experiments. That can't be the Right Canonical Way.
on the constructive side, can we associate the pom file's source stamp with the built main artifact? that way a clean build would replace the pom files correctly. With the exception of "pom" packaging I guess..
IMO, the proper fix would be, to handle POMs always as POMs. So, as metadata, and always install them (to not apply the fix in this issue to them). The main problem I see here, is that Maven handles POM as "artifact to install" (when packaging is "pom"), and sometimes as "repository metadata" (when packaging is not "pom"). Clearly, this fix does bring value for JARs, EARs, WARs, etc, but they are built/assembled then installed (and will be newer than the one in local repository), but in case of "installing POM as main artifact" we have a plain file copy happening, with file that is potentially older than the already in local repository.
Fixed in r808537 in 3.0 trunk and r808535 in 2.2.x.