|
23 | 23 | import javax.inject.Named; |
24 | 24 |
|
25 | 25 | import java.io.File; |
| 26 | +import java.io.IOException; |
26 | 27 | import java.nio.file.Path; |
27 | 28 | import java.util.HashSet; |
28 | 29 | import java.util.List; |
@@ -138,33 +139,54 @@ public void execute( |
138 | 139 |
|
139 | 140 | boolean restorable = result.isSuccess() || result.isPartialSuccess(); |
140 | 141 | boolean restored = false; // if partially restored need to save increment |
| 142 | + |
141 | 143 | if (restorable) { |
142 | 144 | CacheRestorationStatus cacheRestorationStatus = |
143 | 145 | restoreProject(result, mojoExecutions, mojoExecutionRunner, cacheConfig); |
144 | 146 | restored = CacheRestorationStatus.SUCCESS == cacheRestorationStatus; |
145 | 147 | executeExtraCleanPhaseIfNeeded(cacheRestorationStatus, cleanPhase, mojoExecutionRunner); |
146 | 148 | } |
147 | | - if (!restored) { |
148 | | - for (MojoExecution mojoExecution : mojoExecutions) { |
149 | | - if (source == Source.CLI |
150 | | - || mojoExecution.getLifecyclePhase() == null |
151 | | - || lifecyclePhasesHelper.isLaterPhaseThanClean(mojoExecution.getLifecyclePhase())) { |
152 | | - mojoExecutionRunner.run(mojoExecution); |
| 149 | + |
| 150 | + try { |
| 151 | + if (!restored) { |
| 152 | + // Move pre-existing artifacts to staging directory to prevent caching stale files |
| 153 | + // from previous builds (e.g., after git branch switch, or from cache restored |
| 154 | + // with clock skew). This ensures save() only sees fresh files built during this session. |
| 155 | + try { |
| 156 | + cacheController.stagePreExistingArtifacts(session, project); |
| 157 | + } catch (IOException e) { |
| 158 | + LOGGER.warn("Failed to stage pre-existing artifacts: {}", e.getMessage()); |
| 159 | + // Continue build - if staging fails, we'll just cache what exists |
| 160 | + } |
| 161 | + |
| 162 | + for (MojoExecution mojoExecution : mojoExecutions) { |
| 163 | + if (source == Source.CLI |
| 164 | + || mojoExecution.getLifecyclePhase() == null |
| 165 | + || lifecyclePhasesHelper.isLaterPhaseThanClean(mojoExecution.getLifecyclePhase())) { |
| 166 | + mojoExecutionRunner.run(mojoExecution); |
| 167 | + } |
153 | 168 | } |
154 | 169 | } |
155 | | - } |
156 | 170 |
|
157 | | - if (cacheState == INITIALIZED && (!result.isSuccess() || !restored)) { |
158 | | - if (cacheConfig.isSkipSave()) { |
159 | | - LOGGER.info("Cache saving is disabled."); |
160 | | - } else if (cacheConfig.isMandatoryClean() |
161 | | - && lifecyclePhasesHelper |
162 | | - .getCleanSegment(project, mojoExecutions) |
163 | | - .isEmpty()) { |
164 | | - LOGGER.info("Cache storing is skipped since there was no \"clean\" phase."); |
165 | | - } else { |
166 | | - final Map<String, MojoExecutionEvent> executionEvents = mojoListener.getProjectExecutions(project); |
167 | | - cacheController.save(result, mojoExecutions, executionEvents); |
| 171 | + if (cacheState == INITIALIZED && (!result.isSuccess() || !restored)) { |
| 172 | + if (cacheConfig.isSkipSave()) { |
| 173 | + LOGGER.info("Cache saving is disabled."); |
| 174 | + } else if (cacheConfig.isMandatoryClean() |
| 175 | + && lifecyclePhasesHelper |
| 176 | + .getCleanSegment(project, mojoExecutions) |
| 177 | + .isEmpty()) { |
| 178 | + LOGGER.info("Cache storing is skipped since there was no \"clean\" phase."); |
| 179 | + } else { |
| 180 | + final Map<String, MojoExecutionEvent> executionEvents = |
| 181 | + mojoListener.getProjectExecutions(project); |
| 182 | + cacheController.save(result, mojoExecutions, executionEvents); |
| 183 | + } |
| 184 | + } |
| 185 | + } finally { |
| 186 | + // Always restore staged files after build completes (whether save ran or not). |
| 187 | + // Files that were rebuilt are discarded; files that weren't rebuilt are restored. |
| 188 | + if (!restored) { |
| 189 | + cacheController.restoreStagedArtifacts(session, project); |
168 | 190 | } |
169 | 191 | } |
170 | 192 |
|
@@ -244,6 +266,7 @@ private CacheRestorationStatus restoreProject( |
244 | 266 |
|
245 | 267 | // Restore project artifacts |
246 | 268 | ArtifactRestorationReport restorationReport = cacheController.restoreProjectArtifacts(cacheResult); |
| 269 | + |
247 | 270 | if (!restorationReport.isSuccess()) { |
248 | 271 | LOGGER.info("Cannot restore project artifacts, continuing with non cached build"); |
249 | 272 | return restorationReport.isRestoredFilesInProjectDirectory() |
|
0 commit comments