diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2016-05-31 08:55:39 +0200 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2016-06-02 14:01:53 +0200 |
commit | bf2e8a28ce10f8907c4e32dd78a112400a511992 (patch) | |
tree | 638c1976daea1fcb859666a9780737b531dc2638 /server | |
parent | 653c045685baa3b739037d1cbdf0f105452caaf2 (diff) | |
download | sonarqube-bf2e8a28ce10f8907c4e32dd78a112400a511992.tar.gz sonarqube-bf2e8a28ce10f8907c4e32dd78a112400a511992.zip |
SONAR-7537 add issue change when issue is moved to new file
Diffstat (limited to 'server')
4 files changed, 80 insertions, 11 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/MovedIssueVisitor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/MovedIssueVisitor.java index a5ee6d0882e..2e5ababa879 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/MovedIssueVisitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/MovedIssueVisitor.java @@ -20,18 +20,26 @@ package org.sonar.server.computation.issue; import com.google.common.base.Optional; +import java.util.Date; import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.IssueChangeContext; +import org.sonar.server.computation.analysis.AnalysisMetadataHolder; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.filemove.MovedFilesRepository; import org.sonar.server.computation.filemove.MovedFilesRepository.OriginalFile; +import org.sonar.server.issue.IssueUpdater; import static com.google.common.base.Preconditions.checkState; public class MovedIssueVisitor extends IssueVisitor { + private final AnalysisMetadataHolder analysisMetadataHolder; private final MovedFilesRepository movedFilesRepository; + private final IssueUpdater issueUpdater; - public MovedIssueVisitor(MovedFilesRepository movedFilesRepository) { + public MovedIssueVisitor(AnalysisMetadataHolder analysisMetadataHolder, MovedFilesRepository movedFilesRepository, IssueUpdater issueUpdater) { + this.analysisMetadataHolder = analysisMetadataHolder; this.movedFilesRepository = movedFilesRepository; + this.issueUpdater = issueUpdater; } @Override @@ -45,17 +53,14 @@ public class MovedIssueVisitor extends IssueVisitor { issue, component); OriginalFile originalFile = originalFileOptional.get(); checkState(originalFile.getUuid().equals(issue.componentUuid()), - "Issue %s doesn't belong to file %s registered as original file of current file %s", - issue, originalFile.getUuid(), component); + "Issue %s doesn't belong to file %s registered as original file of current file %s", + issue, originalFile.getUuid(), component); - // it's enough to change component uuid, only this field is written to table ISSUES - // other fields (such as module, modulePath, componentKey) are read-only and result of a join with other tables - issue.setComponentUuid(component.getUuid()); + // changes the issue's component uuid, add a change and set issue as changed to enforce it is persisted to DB + issueUpdater.setIssueMoved(issue, component.getUuid(), IssueChangeContext.createUser(new Date(analysisMetadataHolder.getAnalysisDate()), null)); + // other fields (such as module, modulePath, componentKey) are read-only and set/reset for consistency only issue.setComponentKey(component.getKey()); issue.setModuleUuid(null); issue.setModuleUuidPath(null); - - // ensure issue is updated in DB - issue.setChanged(true); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueUpdater.java index d268f0da78a..aed6db2bfca 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueUpdater.java @@ -61,6 +61,7 @@ public class IssueUpdater { public static final String STATUS = "status"; public static final String AUTHOR = "author"; public static final String ACTION_PLAN = "actionPlan"; + public static final String FILE = "file"; /** * It should be renamed to 'effort', but it hasn't been done to prevent a massive update in database @@ -340,4 +341,15 @@ public class IssueUpdater { return false; } + public boolean setIssueMoved(DefaultIssue issue, String newComponentUuid, IssueChangeContext context) { + if (!Objects.equals(newComponentUuid, issue.componentUuid())) { + issue.setFieldChange(context, FILE, issue.componentUuid(), newComponentUuid); + issue.setComponentUuid(newComponentUuid); + issue.setUpdateDate(context.date()); + issue.setChanged(true); + return true; + } + return false; + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/MovedIssueVisitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/MovedIssueVisitorTest.java index 3666b0df96a..a02684b872f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/MovedIssueVisitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/MovedIssueVisitorTest.java @@ -20,15 +20,22 @@ package org.sonar.server.computation.issue; import com.google.common.base.Optional; +import java.util.Date; import org.junit.Before; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.mockito.ArgumentCaptor; import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.IssueChangeContext; +import org.sonar.server.computation.analysis.AnalysisMetadataHolderRule; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.ReportComponent; import org.sonar.server.computation.filemove.MovedFilesRepository; +import org.sonar.server.issue.IssueUpdater; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -36,17 +43,21 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; public class MovedIssueVisitorTest { + private static final long ANALYSIS_DATE = 894521; private static final String FILE_UUID = "file uuid"; private static final Component FILE = ReportComponent.builder(Component.Type.FILE, 1).setUuid(FILE_UUID).build(); @org.junit.Rule public ExpectedException expectedException = ExpectedException.none(); + @org.junit.Rule + public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); private MovedFilesRepository movedFilesRepository = mock(MovedFilesRepository.class); - private MovedIssueVisitor underTest = new MovedIssueVisitor(movedFilesRepository); + private MovedIssueVisitor underTest = new MovedIssueVisitor(analysisMetadataHolder, movedFilesRepository, new IssueUpdater()); @Before public void setUp() throws Exception { + analysisMetadataHolder.setAnalysisDate(ANALYSIS_DATE); when(movedFilesRepository.getOriginalFile(any(Component.class))) .thenReturn(Optional.<MovedFilesRepository.OriginalFile>absent()); } @@ -107,8 +118,12 @@ public class MovedIssueVisitorTest { verify(issue).setComponentKey(FILE.getKey()); verify(issue).setModuleUuid(null); verify(issue).setModuleUuidPath(null); - verify(issue).setChanged(true); + ArgumentCaptor<IssueChangeContext> issueChangeContextCaptor = ArgumentCaptor.forClass(IssueChangeContext.class); + verify(issue).setFieldChange(issueChangeContextCaptor.capture(), eq("file"), eq(originalFile.getUuid()), eq(FILE.getUuid())); + assertThat(issueChangeContextCaptor.getValue().date()).isEqualTo(new Date(ANALYSIS_DATE)); + assertThat(issueChangeContextCaptor.getValue().login()).isNull(); + assertThat(issueChangeContextCaptor.getValue().scan()).isFalse(); } private DefaultIssue mockIssue(String fileUuid) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueUpdaterTest.java index a7c94979f0a..4c6ba39c997 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueUpdaterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueUpdaterTest.java @@ -19,7 +19,10 @@ */ package org.sonar.server.issue; +import java.util.Calendar; import java.util.Date; +import java.util.Map; +import org.apache.commons.lang.time.DateUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -485,4 +488,38 @@ public class IssueUpdaterTest { updater.setNewAuthor(issue, "julien", context); } + @Test + public void setIssueMoved_has_no_effect_if_component_uuid_is_not_changed() { + String componentUuid = "a"; + issue.setComponentUuid(componentUuid); + + updater.setIssueMoved(issue, componentUuid, context); + + assertThat(issue.changes()).isEmpty(); + assertThat(issue.componentUuid()).isEqualTo(componentUuid); + assertThat(issue.isChanged()).isFalse(); + assertThat(issue.updateDate()).isNull(); + assertThat(issue.mustSendNotifications()).isFalse(); + } + + @Test + public void setIssueMoved_changes_componentUuid_adds_a_change() { + String oldComponentUuid = "a"; + String newComponentUuid = "b"; + issue.setComponentUuid(oldComponentUuid); + + updater.setIssueMoved(issue, newComponentUuid, context); + + assertThat(issue.changes()).hasSize(1); + FieldDiffs fieldDiffs = issue.changes().get(0); + assertThat(fieldDiffs.creationDate()).isEqualTo(context.date()); + assertThat(fieldDiffs.diffs()).hasSize(1); + Map.Entry<String, FieldDiffs.Diff> entry = fieldDiffs.diffs().entrySet().iterator().next(); + assertThat(entry.getKey()).isEqualTo("file"); + assertThat(entry.getValue().oldValue()).isEqualTo(oldComponentUuid); + assertThat(entry.getValue().newValue()).isEqualTo(newComponentUuid); + assertThat(issue.componentUuid()).isEqualTo(newComponentUuid); + assertThat(issue.isChanged()).isTrue(); + assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(context.date(), Calendar.SECOND)); + } } |