]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7537 add issue change when issue is moved to new file
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 31 May 2016 06:55:39 +0000 (08:55 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 2 Jun 2016 12:01:53 +0000 (14:01 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/issue/MovedIssueVisitor.java
server/sonar-server/src/main/java/org/sonar/server/issue/IssueUpdater.java
server/sonar-server/src/test/java/org/sonar/server/computation/issue/MovedIssueVisitorTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueUpdaterTest.java
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index a5ee6d0882edc2fba53a0324d0d248132eca3138..2e5ababa879d879dfc70ca3b89edea15edb59334 100644 (file)
 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);
   }
 }
index d268f0da78a1a41dd4d49a7930342e48cc5237f8..aed6db2bfca2cca1612bb3a2ad4eb59b8295615b 100644 (file)
@@ -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;
+  }
+
 }
index 3666b0df96afa2879e07295f930d3e360906eca3..a02684b872fe79ee43d3311a09f6064d98401517 100644 (file)
 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) {
index a7c94979f0a086487d5298c34b8a2b781766b119..4c6ba39c9971d0847cda5e9ba0a99f86637871c6 100644 (file)
  */
 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));
+  }
 }
index 398cf420a2a8d3f19bce8a5917e1176bb3c05b50..697ad83e0de670546ac0dd3e6dbeb4135f350d14 100644 (file)
@@ -579,6 +579,7 @@ issue.changelog.field.severity=Severity
 issue.changelog.field.status=Status
 issue.changelog.field.tags=Tags
 issue.changelog.field.type=Type
+issue.changelog.field.file=File
 issue.changelog.removed={0} removed
 issue.changelog.was=was {0}
 issue.comment.delete_confirm_button=Delete