Re: [DISCUSS] Fix for #12646 — moving project-loca l-repo out of target/

Romain Manni-Bucau <[email protected]> Mon, 3 Aug 2026 16:33:11 +0200
Newsgroups gmane.comp.jakarta.turbine.maven.devel
Message-ID <CACLE=7Myv5tPx+9N7drMuF9P17hA+yfhN196OWO7dJb+Zv6pHg@mail.gmail.com>
--0000000000009ba7fd0658256bca
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hi Guillaume,

I'd avoid .mvn/ cause it is often watched and I wonder how .m2 would be
cleaned up but think a compromise aligned on snapshot model can be as sane
as v3 (.m2/repository/$groupId/$artifactId/$version/local-repo/whatever or
alike), can keep find *-SNAPSHOT | xargs rm -Rf kind of maintenance working
and fix the issue no?

Romain Manni-Bucau
@rmannibucau <https://x.com/rmannibucau> | .NET Blog
<https://dotnetbirdie.github.io/> | Blog <https://rmannibucau.github.io/> |=
 Old
Blog <http://rmannibucau.wordpress.com> | Github
<https://github.com/rmannibucau> | LinkedIn
<https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/en-us/product/java-ee-8-high-performance-97817884=
73064>
Javaccino <https://javaccino.dev/> founder (Java/.NET service - contact via
linkedin)


Le lun. 3 ao=C3=BBt 2026 =C3=A0 14:09, Guillaume Nodet <gnodet.apache@gmail=
.com> a
=C3=A9crit :

> Hi all,
>
> I'd like to get your input on the fix for GH-12646 =E2=80=94 a race condi=
tion 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 th=
e
> root project and child modules concurrently. Since clean and install are
> placed into the same TaskSegment, there is no barrier between them =E2=80=
=94 the
> root project's maven-clean-plugin can delete target/ while sibling module=
s
> are concurrently writing artifacts into target/project-local-repo, causin=
g
> 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 =E2=80=94 a module co=
uld
> 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 Intell=
iJ
> stores project caches. This avoids both the race and the git concern, but=
:
> - Hard links (already used by ReactorReader) cannot cross filesystem
> boundaries =E2=80=94 if ~/.m2/ is on a different volume, every artifact b=
ecomes 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/, t=
he
> race becomes structurally impossible. ReactorReader fully owns the
> lifecycle =E2=80=94 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. Thi=
s
> 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 =E2=80=94 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=3Dtrue, since plugin 3.2) atomica=
lly
> renames target/ instead of recursively deleting it. This would likely avo=
id
> the race, but it's opt-in and not the default =E2=80=94 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 t=
he
> 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?
> - Should Maven auto-add .mvn/project-local-repo to .gitignore, or documen=
t
> 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
>

--0000000000009ba7fd0658256bca--