@@ -63,6 +63,20 @@ public class BranchDao implements Dao { | |||
return mapper(dbSession).updateMainBranchName(projectUuid, newBranchKey, now); | |||
} | |||
/** | |||
* Update the baseline_analysis_uuid and baseline_manual columns, if: | |||
* | |||
* - the specified uuid exists | |||
* - and the specified uuid corresponds to a long-living branch (including the main branch) | |||
* - and the existing baseline_analysis_uuid and baseline_manual values are different | |||
* | |||
* @return the number of rows that were updated | |||
*/ | |||
public int updateBaseline(DbSession dbSession, String uuid, String baselineAnalysisUuid, boolean baselineManual) { | |||
long now = system2.now(); | |||
return mapper(dbSession).updateBaseline(uuid, baselineAnalysisUuid, baselineManual, now); | |||
} | |||
public Optional<BranchDto> selectByBranchKey(DbSession dbSession, String projectUuid, String key) { | |||
return selectByKey(dbSession, projectUuid, key, KeyType.BRANCH); | |||
} |
@@ -88,6 +88,23 @@ public class BranchDto { | |||
@Nullable | |||
private byte[] pullRequestBinary; | |||
/** | |||
* The baseline analysis that marks the start of New Code Period. | |||
* Either manually set by user, or else automatically set to the value computed during analysis. | |||
* | |||
* It may be null for projects which have never been analyzed since the column was introduced. | |||
*/ | |||
@Nullable | |||
private String baselineAnalysisUuid; | |||
/** | |||
* Set to true if the user has manually specified a baseline analysis for the branch. | |||
* | |||
* It may be null for projects which have never been analyzed since the column was introduced. | |||
*/ | |||
@Nullable | |||
private Boolean baselineManual; | |||
public String getUuid() { | |||
return uuid; | |||
} | |||
@@ -189,6 +206,31 @@ public class BranchDto { | |||
} | |||
} | |||
@CheckForNull | |||
public String getBaselineAnalysisUuid() { | |||
return baselineAnalysisUuid; | |||
} | |||
private BranchDto setBaselineAnalysisUuid(@Nullable String baselineAnalysisUuid) { | |||
this.baselineAnalysisUuid = baselineAnalysisUuid; | |||
return this; | |||
} | |||
public boolean isBaselineManual() { | |||
return this.baselineManual != null && this.baselineManual; | |||
} | |||
private BranchDto setBaselineManual(@Nullable Boolean baselineManual) { | |||
this.baselineManual = baselineManual != null && baselineManual; | |||
return this; | |||
} | |||
public BranchDto setBaseline(@Nullable String baselineAnalysisUuid, @Nullable Boolean baselineManual) { | |||
this.baselineAnalysisUuid = baselineAnalysisUuid; | |||
this.baselineManual = baselineManual; | |||
return this; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
@@ -202,7 +244,9 @@ public class BranchDto { | |||
Objects.equals(projectUuid, branchDto.projectUuid) && | |||
Objects.equals(kee, branchDto.kee) && | |||
branchType == branchDto.branchType && | |||
Objects.equals(mergeBranchUuid, branchDto.mergeBranchUuid); | |||
Objects.equals(mergeBranchUuid, branchDto.mergeBranchUuid) && | |||
Objects.equals(baselineAnalysisUuid, branchDto.baselineAnalysisUuid) && | |||
baselineManual == branchDto.baselineManual; | |||
} | |||
@Override | |||
@@ -219,6 +263,8 @@ public class BranchDto { | |||
sb.append(", keyType=").append(keyType); | |||
sb.append(", branchType=").append(branchType); | |||
sb.append(", mergeBranchUuid='").append(mergeBranchUuid).append('\''); | |||
sb.append(", baselineAnalysisUuid='").append(baselineAnalysisUuid).append('\''); | |||
sb.append(", baselineManual=").append(baselineManual); | |||
sb.append('}'); | |||
return sb.toString(); | |||
} |
@@ -31,6 +31,9 @@ public interface BranchMapper { | |||
int updateMainBranchName(@Param("projectUuid") String projectUuid, @Param("newBranchName") String newBranchName, @Param("now") long now); | |||
int updateBaseline(@Param("uuid") String uuid, @Param("baselineAnalysisUuid") String baselineAnalysisUuid, | |||
@Param("baselineManual") boolean baselineManual, @Param("now") long now); | |||
BranchDto selectByKey(@Param("projectUuid") String projectUuid, @Param("key") String key, @Param("keyType") KeyType keyType); | |||
BranchDto selectByUuid(@Param("uuid") String uuid); |
@@ -9,7 +9,9 @@ | |||
pb.key_type as keyType, | |||
pb.branch_type as branchType, | |||
pb.merge_branch_uuid as mergeBranchUuid, | |||
pb.pull_request_binary as pullRequestBinary | |||
pb.pull_request_binary as pullRequestBinary, | |||
pb.baseline_analysis_uuid as baselineAnalysisUuid, | |||
pb.baseline_manual as baselineManual | |||
</sql> | |||
<insert id="insert" parameterType="map" useGeneratedKeys="false"> | |||
@@ -21,6 +23,8 @@ | |||
branch_type, | |||
merge_branch_uuid, | |||
pull_request_binary, | |||
baseline_analysis_uuid, | |||
baseline_manual, | |||
created_at, | |||
updated_at | |||
) values ( | |||
@@ -31,6 +35,8 @@ | |||
#{dto.branchType, jdbcType=VARCHAR}, | |||
#{dto.mergeBranchUuid, jdbcType=VARCHAR}, | |||
#{dto.pullRequestBinary, jdbcType=BINARY}, | |||
#{dto.baselineAnalysisUuid, jdbcType=VARCHAR}, | |||
#{dto.baselineManual, jdbcType=BOOLEAN}, | |||
#{now, jdbcType=BIGINT}, | |||
#{now, jdbcType=BIGINT} | |||
) | |||
@@ -45,23 +51,37 @@ | |||
uuid = #{projectUuid, jdbcType=VARCHAR} | |||
</update> | |||
<update id="updateBaseline" parameterType="map" useGeneratedKeys="false"> | |||
update project_branches | |||
set | |||
baseline_analysis_uuid = #{baselineAnalysisUuid, jdbcType=VARCHAR}, | |||
baseline_manual = #{baselineManual, jdbcType=BOOLEAN}, | |||
updated_at = #{now, jdbcType=BIGINT} | |||
where | |||
uuid = #{uuid, jdbcType=VARCHAR} | |||
and branch_type = 'LONG' | |||
and (baseline_analysis_uuid is null | |||
or baseline_analysis_uuid != #{baselineAnalysisUuid, jdbcType=VARCHAR} | |||
or baseline_manual != #{baselineManual, jdbcType=BOOLEAN}) | |||
</update> | |||
<update id="update" parameterType="map" useGeneratedKeys="false"> | |||
update project_branches | |||
set | |||
merge_branch_uuid = #{dto.mergeBranchUuid, jdbcType=VARCHAR}, | |||
pull_request_binary = #{dto.pullRequestBinary, jdbcType=BINARY}, | |||
updated_at = #{now, jdbcType=BIGINT} | |||
merge_branch_uuid = #{dto.mergeBranchUuid, jdbcType=VARCHAR}, | |||
pull_request_binary = #{dto.pullRequestBinary, jdbcType=BINARY}, | |||
updated_at = #{now, jdbcType=BIGINT} | |||
where | |||
uuid = #{dto.uuid, jdbcType=VARCHAR} | |||
uuid = #{dto.uuid, jdbcType=VARCHAR} | |||
</update> | |||
<select id="selectByKey" resultType="org.sonar.db.component.BranchDto"> | |||
select <include refid="columns" /> | |||
from project_branches pb | |||
where | |||
pb.project_uuid = #{projectUuid, jdbcType=VARCHAR} and | |||
pb.kee = #{key, jdbcType=VARCHAR} and | |||
pb.key_type = #{keyType, jdbcType=VARCHAR} | |||
pb.project_uuid = #{projectUuid, jdbcType=VARCHAR} and | |||
pb.kee = #{key, jdbcType=VARCHAR} and | |||
pb.key_type = #{keyType, jdbcType=VARCHAR} | |||
</select> | |||
<select id="selectByProjectUuid" parameterType="string" resultType="org.sonar.db.component.BranchDto"> |
@@ -19,9 +19,13 @@ | |||
*/ | |||
package org.sonar.db.component; | |||
import com.tngtech.java.junit.dataprovider.DataProvider; | |||
import com.tngtech.java.junit.dataprovider.DataProviderRunner; | |||
import com.tngtech.java.junit.dataprovider.UseDataProvider; | |||
import java.util.Map; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.api.utils.internal.TestSystem2; | |||
import org.sonar.db.DbSession; | |||
@@ -34,6 +38,7 @@ import static org.apache.commons.lang.StringUtils.repeat; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.assertj.core.api.Assertions.entry; | |||
@RunWith(DataProviderRunner.class) | |||
public class BranchDaoTest { | |||
private static final long NOW = 1_000L; | |||
@@ -93,6 +98,124 @@ public class BranchDaoTest { | |||
assertThat(loaded.getBranchType()).isEqualTo(BranchType.LONG); | |||
} | |||
@Test | |||
public void insert_baseline_analysis() { | |||
BranchDto dto = new BranchDto(); | |||
dto.setProjectUuid("U1"); | |||
dto.setUuid("U1"); | |||
dto.setBranchType(BranchType.LONG); | |||
dto.setKey("foo"); | |||
underTest.insert(dbSession, dto); | |||
assertThat(underTest.updateBaseline(dbSession, dto.getUuid(), "dfsf", false)).isEqualTo(1); | |||
} | |||
@Test | |||
public void update_baseline_on_analysis_uuid_change() { | |||
BranchDto dto = new BranchDto(); | |||
dto.setProjectUuid("U1"); | |||
dto.setUuid("U1"); | |||
dto.setBranchType(BranchType.LONG); | |||
dto.setKey("foo"); | |||
dto.setBaseline("a-uuid", false); | |||
underTest.insert(dbSession, dto); | |||
BranchDto otherDtoThatShouldNotChange = new BranchDto(); | |||
otherDtoThatShouldNotChange.setProjectUuid("U2"); | |||
otherDtoThatShouldNotChange.setUuid("U2"); | |||
otherDtoThatShouldNotChange.setBranchType(BranchType.LONG); | |||
otherDtoThatShouldNotChange.setKey("branch"); | |||
underTest.insert(dbSession, otherDtoThatShouldNotChange); | |||
String newBaselineAnalysisUuid = dto.getBaselineAnalysisUuid() + "-mod"; | |||
int updated = underTest.updateBaseline(dbSession, dto.getUuid(), newBaselineAnalysisUuid, dto.isBaselineManual()); | |||
assertThat(updated).isEqualTo(1); | |||
BranchDto loaded = underTest.selectByUuid(dbSession, dto.getUuid()).get(); | |||
assertThat(loaded.getBaselineAnalysisUuid()).isEqualTo(newBaselineAnalysisUuid); | |||
} | |||
@Test | |||
@UseDataProvider("trueAndFalse") | |||
public void update_baseline_on_mode_change(boolean initialMode) { | |||
BranchDto dto = new BranchDto(); | |||
dto.setProjectUuid("U1"); | |||
dto.setUuid("U1"); | |||
dto.setBranchType(BranchType.LONG); | |||
dto.setKey("foo"); | |||
dto.setBaseline("a-uuid", initialMode); | |||
underTest.insert(dbSession, dto); | |||
int updated = underTest.updateBaseline(dbSession, dto.getUuid(), dto.getBaselineAnalysisUuid(), !initialMode); | |||
assertThat(updated).isEqualTo(1); | |||
BranchDto loaded = underTest.selectByUuid(dbSession, dto.getUuid()).get(); | |||
assertThat(loaded.isBaselineManual()).isEqualTo(!initialMode); | |||
} | |||
@Test | |||
@UseDataProvider("trueAndFalse") | |||
public void do_not_update_baseline_when_unchanged(boolean initialMode) { | |||
BranchDto dto = new BranchDto(); | |||
dto.setProjectUuid("U1"); | |||
dto.setUuid("U1"); | |||
dto.setBranchType(BranchType.LONG); | |||
dto.setKey("foo"); | |||
dto.setBaseline("a-uuid", initialMode); | |||
underTest.insert(dbSession, dto); | |||
int updated = underTest.updateBaseline(dbSession, dto.getUuid(), dto.getBaselineAnalysisUuid(), initialMode); | |||
assertThat(updated).isZero(); | |||
} | |||
@DataProvider | |||
public static Object[][] trueAndFalse() { | |||
return new Object[][] { | |||
{true}, | |||
{false}, | |||
}; | |||
} | |||
@Test | |||
@UseDataProvider("modeAndNonLongBranchType") | |||
public void do_not_update_baseline_of_non_long_branches(boolean initialMode, BranchType branchType) { | |||
BranchDto dto = new BranchDto(); | |||
dto.setProjectUuid("U1"); | |||
dto.setUuid("U1"); | |||
dto.setBranchType(branchType); | |||
dto.setKey("foo"); | |||
dto.setBaseline("a-uuid", initialMode); | |||
underTest.insert(dbSession, dto); | |||
int updated = underTest.updateBaseline(dbSession, dto.getUuid(), dto.getBaselineAnalysisUuid() + "-mod", !initialMode); | |||
assertThat(updated).isZero(); | |||
} | |||
@DataProvider | |||
public static Object[][] modeAndNonLongBranchType() { | |||
return new Object[][] { | |||
{true, BranchType.SHORT}, | |||
{true, BranchType.PULL_REQUEST}, | |||
{false, BranchType.SHORT}, | |||
{false, BranchType.PULL_REQUEST}, | |||
}; | |||
} | |||
@Test | |||
public void isBaselineManual_returns_false_when_column_is_null() { | |||
BranchDto dto = new BranchDto(); | |||
dto.setProjectUuid("U1"); | |||
dto.setUuid("U1"); | |||
dto.setBranchType(BranchType.LONG); | |||
dto.setKey("foo"); | |||
dto.setBaseline("a-uuid", true); | |||
underTest.insert(dbSession, dto); | |||
db.commit(); | |||
db.executeUpdateSql("update project_branches set baseline_manual = null"); | |||
BranchDto loaded = underTest.selectByUuid(dbSession, dto.getUuid()).get(); | |||
assertThat(loaded.isBaselineManual()).isEqualTo(false); | |||
} | |||
@Test | |||
public void insert_branch_with_all_fields_and_max_length_values() { | |||
BranchDto dto = new BranchDto(); |