Jo,

I get that, but this part: "many developers run mvn package or mvn verify".
I thought everyone runs "mvn clean install" :D Joke aside, why are
they doing that?
I mean, does running `mvn install` (instead of mvn verify) incur some
huge overhead?
Or are they being told to do so? So what is the explanation to run
(n-1)th and not n-th phase?


T

On Tue, 4 Aug 2026 at 21:48, Guillaume Nodet <[email protected]> wrote:
>
> THi all,
>
>
> Following the discussion on whether chained local repositories (à la MWM)
> could replace project-local-repo, I wanted to clarify the use cases each
> solves. They're complementary, not interchangeable.
>
>
> *What project-local-repo solves*
>
> project-local-repo was introduced in MNG-7629 to support intra-reactor
> partial and resumable builds without requiring mvn install. It is populated
> on ProjectSucceeded regardless of the lifecycle goal — mvn package, mvn
> verify, anything that produces artifacts.
>
>
> This enables workflows like:
> - mvn package then mvn test -pl :child — child finds sibling artifacts
> - mvn verify fails at module-C, then mvn verify -rf :module-C — modules A
> and B's artifacts (including classifiers like sources.jar, test-jar,
> consumer POMs) are available from the previous run
> - mvn package -DskipTests then mvn surefire:test -pl :single-module —
> resolves dependencies from siblings
>
> The key detail is that classified/attached artifacts (sources.jar,
> test-jar, javadoc.jar, consumer POMs) are only resolvable from
> project-local-repo during resume. The target/classes fallback in
> ReactorReader only handles plain jars without classifiers.
>
> What chained local repositories solve
>
> Chained repos (via maven.repo.local.head / MWM) solve cross-project
> SNAPSHOT resolution with branch isolation. They allow different branches to
> have isolated install targets, so working on multiple branches (or multiple
> related projects) doesn't cause artifact conflicts in ~/.m2/repository.
>
> This enables workflows like:
> - Build maven-resolver SNAPSHOT on branch feature-x, then build maven
> against it — without polluting ~/.m2/repository or conflicting with the
> main branch
> - Multiple git worktrees of the same project, each with its own install
> target
>
> Why one can't replace the other
>
> Chained repos require mvn install to populate the head repository. They
> cannot serve the project-local-repo use case because many developers run
> mvn package or mvn verify without install. After mvn package, classified
> artifacts are in project-local-repo (populated on ProjectSucceeded) but not
> in any local repository.
>
> Conversely, project-local-repo is scoped to a single reactor — it cannot
> resolve artifacts across project boundaries. Chained repos solve this
> naturally.
>
> Regarding #12646
>
> The race condition exists because project-local-repo currently lives inside
> target/, where maven-clean-plugin deletes it during parallel builds. The
> proposed fix (PR #12650) moves it to .mvn/target/project-local-repo —
> outside the reach of maven-clean-plugin, while keeping the semantic split
> (.mvn/ = config, .mvn/target/ = build output, gitignored).
>
> This is a minimal, targeted fix. Both mechanisms can coexist — chained
> repos for cross-project branch isolation, project-local-repo for
> intra-reactor partial builds without install.
>
> PR: https://github.com/apache/maven/pull/12650
> Issue: https://github.com/apache/maven/issues/12646
>
>
>
> Le mar. 4 août 2026 à 21:26, Maarten Mulders <[email protected]> a
> écrit :
>
> > Hi,
> >
> > The statement that "the unsolicited install happens [...] to make the
> > resume `-r` feature work" is only partially true. The original solution
> > to get `mvn -r` to work did /not/ involve installing all artifacts in a
> > project-local repo. It was later refactored/rewritten by /other/ people
> > to work the way you describe.
> >
> > Thanks,
> >
> > Maarten
> >
> > On August 4, 2026 at 15:07, Tamás Cservenák wrote:
> > > Howdy,
> > >
> > > I would just reflect on a funny fact (for me at least):
> > >
> > > This whole problem (being solved on this thread), stems from one
> > > single thing: the unsolicited install that Maven 4 does (cf this to
> > > user invoking `mvn install` explicitly).
> > >
> > > Moreover, this unsolicited install happens, for one thing, to make the
> > > resume `-r` feature work.
> > >
> > > And the true irony is, that this resume feature is backed and
> > > advertised by folks, whose mantra is "do not `mvn install` but `mvn
> > > verify`" (as install "pollutes' your local repository", whatever that
> > > means).
> > >
> > > That mantra can be now extended with "... as Maven 4 will install it,
> > > even if you did not ask for it" :)
> > >
> > > The more I think about it, the more I find this funny.
> > >
> > > Thanks
> > > T
> > >
> > > On Tue, 4 Aug 2026 at 14:56, Guillaume Nodet<[email protected]> wrote:
> > >> I like the .mvn/target/project-local-repo which solves the problem,
> > >> and also provides a good location where plugins could move some
> > >> temporary data files without being disturbed by the clean plugin.  I'm
> > >> thinking about the flatten plugin, the release plugin, and probably
> > >> more.
> > >>
> > >> Le lun. 3 août 2026 à 16:47, Slawomir Jaranowski
> > >> <[email protected]> a écrit :
> > >>> Hi,
> > >>>
> > >>> On Mon, 3 Aug 2026 at 14:09, Guillaume Nodet<[email protected]>
> > wrote:
> > >>>> Hi all,
> > >>>>
> > >>>> I'd like to get your input on the fix for GH-12646 — a race condition
> > with
> > >>>> project-local-repo during parallel clean install builds.
> > >>>>
> > >>>> The problem
> > >>>>
> > >>>> When the root pom.xml has a parent that is also part of the reactor
> > (e.g. a
> > >>>> super-pom), MultiThreadedBuilder schedules the parent first, then
> > runs the
> > >>>> root project and child modules concurrently. Since clean and install
> > are
> > >>>> placed into the same TaskSegment, there is no barrier between them —
> > the
> > >>>> root project's maven-clean-plugin can delete target/ while sibling
> > modules
> > >>>> are concurrently writing artifacts into target/project-local-repo,
> > causing
> > >>>> the build to fail.
> > >>>>
> > >>>> Approaches considered
> > >>>>
> > >>>> 1. Lock-based synchronization (ReentrantReadWriteLock in
> > ReactorReader)
> > >>>>
> > >>>> Acquire a write lock when the project owning target/ enters its clean
> > >>>> phase, and a read lock when installing artifacts. This prevents the
> > crash
> > >>>> (concurrent access) but does not guarantee ordering — a module could
> > >>>> install artifacts before the root's clean starts, only to have them
> > wiped.
> > >>>> It also adds complexity to ReactorReader for what is fundamentally an
> > >>>> architectural problem.
> > >>>>
> > >>>> 2. Move project-local-repo to ~/.m2/ (user home)
> > >>>>
> > >>>> E.g. ~/.m2/local-repository/${projectName}_${hash}, similar to how
> > IntelliJ
> > >>>> stores project caches. This avoids both the race and the git concern,
> > but:
> > >>>> - Hard links (already used by ReactorReader) cannot cross filesystem
> > >>>> boundaries — if ~/.m2/ is on a different volume, every artifact
> > becomes a
> > >>>> full copy
> > >>>> - Stale directories accumulate when projects are deleted/moved, with
> > no
> > >>>> cleanup mechanism
> > >>>> - CI containers often share ~/.m2/ across builds, causing unwanted
> > >>>> accumulation
> > >>>> - Loses project locality (harder to inspect/debug)
> > >>>>
> > >>>> 3. Move project-local-repo to .mvn/project-local-repo (chosen)
> > >>>>
> > >>>> Move the directory from target/project-local-repo to
> > >>>> .mvn/project-local-repo. Since maven-clean-plugin only deletes
> > target/, the
> > >>>> race becomes structurally impossible. ReactorReader fully owns the
> > >>>> lifecycle — per-GAV cleanup when a project enters its clean phase,
> > install
> > >>>> on project success. The existing hard-link optimization continues to
> > work
> > >>>> since both directories are on the same filesystem.
> > >>>>
> > >>>> The trade-off is that .mvn/project-local-repo needs to be gitignored.
> > This
> > >>>> follows the Gradle convention where .gradle/ at the project root is
> > >>>> universally in .gitignore templates. Maven could also document this
> > >>>> convention or consider auto-appending the entry.
> > >>>>
> > >>>> The fix itself is minimal — the core change is a single line in
> > >>>> getProjectLocalRepo(), and the rest is removing the lock
> > infrastructure
> > >>>> (net -40 lines).
> > >>>>
> > >>>> 4. Keep in target/ but use maven-clean-plugin fast mode
> > >>>>
> > >>>> The fast clean option (maven.clean.fast=true, since plugin 3.2)
> > atomically
> > >>>> renames target/ instead of recursively deleting it. This would likely
> > avoid
> > >>>> the race, but it's opt-in and not the default — users hitting the bug
> > would
> > >>>> need to know about it.
> > >>>>
> > >>>> FWIW, a PR has been raised on m-clean-p master branch (4.x) to
> > refactor the
> > >>>> fast cleaner (fixing problems) and make it the default.
> > >>>>
> > >>>> Open questions
> > >>>>
> > >>>> - Is .mvn/ the right location, or should we consider a different
> > >>>> project-root directory?
> > >>> maybe .mvn/target/project-local-repo
> > >>> it should be ignored by git
> > >>>
> > >>>> - Should Maven auto-add .mvn/project-local-repo to .gitignore, or
> > document
> > >>>> it as a convention?
> > >>>> - Are there other considerations I'm missing?
> > >>>>
> > >>>> PR:https://github.com/apache/maven/pull/12650
> > >>>> Issue:https://github.com/apache/maven/issues/12646
> > >>>>
> > >>>> Looking forward to your thoughts.
> > >>>>
> > >>>>   Cheers
> > >>>> Guillaume Nodet
> > >>>
> > >>>
> > >>> --
> > >>> Sławomir Jaranowski
> > >>>
> > >>> ---------------------------------------------------------------------
> > >>> To unsubscribe, e-mail:[email protected]
> > >>> For additional commands, e-mail:[email protected]
> > >>>
> > >>
> > >> --
> > >> ------------------------
> > >> Guillaume Nodet
> > >>
> > >> ---------------------------------------------------------------------
> > >> To unsubscribe, e-mail:[email protected]
> > >> For additional commands, e-mail:[email protected]
> > >>
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail:[email protected]
> > > For additional commands, e-mail:[email protected]
> > >
>
>
>
> --
> ------------------------
> Guillaume Nodet

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to