]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18856 accurate usage of project uuid in applications
authorLukasz Jarocki <lukasz.jarocki@sonarsource.com>
Thu, 11 May 2023 14:56:37 +0000 (16:56 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 12 May 2023 20:02:40 +0000 (20:02 +0000)
22 files changed:
server/sonar-db-dao/src/it/java/org/sonar/db/component/ApplicationProjectsDaoIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/component/BranchDaoIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/measure/LiveMeasureDaoIT.java
server/sonar-db-dao/src/it/java/org/sonar/db/project/ProjectDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ApplicationProjectsDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ApplicationProjectsMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/BranchMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java
server/sonar-db-dao/src/main/resources/org/sonar/db/component/ApplicationProjectsMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/component/BranchMapper.xml
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ComponentTesting.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/component/ProjectData.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureDbTester.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/measure/MeasureTesting.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ServerUserSessionTest.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentFinderIT.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/hotspot/ws/SearchActionIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentFinder.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java

index 37a91d41a480d4fd8ae7f3c536aa54ec53ccbd18..cc2d83834d2cb769d98be484cee2238525bf6c02 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.db.component;
 
+import java.util.List;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -33,12 +34,12 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 public class ApplicationProjectsDaoIT {
   @Rule
-  public DbTester db = DbTester.create(System2.INSTANCE);
+  public DbTester db = DbTester.create(System2.INSTANCE, true);
 
-  private UuidFactoryFast uuids = UuidFactoryFast.getInstance();
-  private TestSystem2 system2 = new TestSystem2();
-  private DbSession dbSession = db.getSession();
-  private ApplicationProjectsDao underTest = new ApplicationProjectsDao(system2, uuids);
+  private final UuidFactoryFast uuids = UuidFactoryFast.getInstance();
+  private final TestSystem2 system2 = new TestSystem2();
+  private final DbSession dbSession = db.getSession();
+  private final ApplicationProjectsDao underTest = new ApplicationProjectsDao(system2, uuids);
 
   @Before
   public void before() {
@@ -79,10 +80,10 @@ public class ApplicationProjectsDaoIT {
 
   @Test
   public void select_project_branches_from_application_branch() {
-    var project = db.components().insertPublicProject(p -> p.setKey("project")).getProjectDto();
-    var projectBranch = db.components().insertProjectBranch(project, b -> b.setKey("project-branch"));
-    var app = db.components().insertPrivateApplication(a -> a.setKey("app1")).getProjectDto();
-    var appBranch = db.components().insertProjectBranch(app, b -> b.setKey("app-branch"));
+    ProjectDto project = db.components().insertPublicProject(p -> p.setKey("project")).getProjectDto();
+    BranchDto projectBranch = db.components().insertProjectBranch(project, b -> b.setKey("project-branch"));
+    ProjectDto app = db.components().insertPrivateApplication(a -> a.setKey("app1")).getProjectDto();
+    BranchDto appBranch = db.components().insertProjectBranch(app, b -> b.setKey("app-branch"));
     db.components().addApplicationProject(app, project);
     underTest.addProjectBranchToAppBranch(dbSession, app.getUuid(), appBranch.getUuid(), project.getUuid(), projectBranch.getUuid());
     assertThat(underTest.selectProjectBranchesFromAppBranchUuid(dbSession, appBranch.getUuid())).extracting(BranchDto::getKey).containsOnly("project-branch");
@@ -112,16 +113,32 @@ public class ApplicationProjectsDaoIT {
     assertThat(underTest.selectProjects(dbSession, "uuid")).extracting(ProjectDto::getUuid).containsOnly("p1");
   }
 
+
   @Test
-  public void remove() {
-    insertApplicationProject("uuid", "p1");
-    insertApplicationProject("uuid", "p2");
+  public void selectProjectsMainBranchesOfApplication_whenApplicationDoesNotExist_shouldReturnEmptyList() {
+    insertBranchesForProjectUuids(true, "1");
 
-    underTest.remove(dbSession, "uuid");
-    assertThat(underTest.selectProjects(dbSession, "uuid")).isEmpty();
+    List<BranchDto> branchDtos = underTest.selectProjectsMainBranchesOfApplication(dbSession, "1");
+
+    assertThat(branchDtos).isEmpty();
   }
 
-  private String insertApplicationProject(String applicationUuid, String projectUuid) {
+  @Test
+  public void selectProjectsMainBranchesOfApplication_whenApplicationExistWithTwoProjects_shouldReturnTwoBranches() {
+    String appUuid = "appUuid";
+    insertProject("1");
+    insertProject("2");
+    insertBranchesForProjectUuids(false, "1", "2");
+    insertApplicationProjectWithoutProject(appUuid, "1");
+    insertApplicationProjectWithoutProject(appUuid, "2");
+
+    List<BranchDto> branchDtos = underTest.selectProjectsMainBranchesOfApplication(dbSession, appUuid);
+
+    assertThat(branchDtos).hasSize(2);
+    assertThat(branchDtos).extracting(BranchDto::isMain).allMatch(s -> true);
+  }
+
+  private void insertApplicationProject(String applicationUuid, String projectUuid) {
     String uuid = uuids.create();
     db.executeInsert(
       "app_projects",
@@ -130,19 +147,22 @@ public class ApplicationProjectsDaoIT {
       "project_uuid", projectUuid,
       "created_at", 1000L);
     insertProject(projectUuid);
-    return uuid;
   }
 
-  private void insertProject(String projectUuid) {
-    db.executeInsert("projects",
-      "uuid", projectUuid,
-      "kee", projectUuid,
-      "qualifier", "TRK",
-      "private", true,
-      "updated_at", 1000L,
+  private void insertApplicationProjectWithoutProject(String applicationUuid, String projectUuid) {
+    String uuid = uuids.create();
+    db.executeInsert(
+      "app_projects",
+      "uuid", uuid,
+      "application_uuid", applicationUuid,
+      "project_uuid", projectUuid,
       "created_at", 1000L);
   }
 
+  private void insertProject(String projectUuid) {
+    db.components().insertPrivateProject(c -> {}, p -> p.setUuid(projectUuid));
+  }
+
   private void insertApplication(String appUuid) {
     db.executeInsert("projects",
       "uuid", appUuid,
@@ -154,6 +174,10 @@ public class ApplicationProjectsDaoIT {
   }
 
   private void insertBranch(String projectUuid, String branchKey) {
+    insertBranch(projectUuid, branchKey, false);
+  }
+
+  private void insertBranch(String projectUuid, String branchKey, boolean isMain) {
     db.executeInsert("project_branches",
       "uuid", branchKey,
       "branch_type", "BRANCH",
@@ -162,7 +186,13 @@ public class ApplicationProjectsDaoIT {
       "NEED_ISSUE_SYNC", true,
       "updated_at", 1000L,
       "created_at", 1000L,
-      "is_main", false);
+      "is_main", isMain);
+  }
+
+  private void insertBranchesForProjectUuids(boolean mainBranch, String... projectUuids) {
+    for (String uuid : projectUuids) {
+      insertBranch(uuid, "key" + uuid + mainBranch, mainBranch);
+    }
   }
 
 }
index 270a3e6a1ba9df97a9732d34d5c6286efad29f39..b0bb9df6e60a570d6a489984bdeb09fcc30f1e9d 100644 (file)
@@ -50,7 +50,6 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
 import static org.apache.commons.lang.StringUtils.repeat;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.entry;
-import static org.assertj.core.api.Assertions.linesOf;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.sonar.db.component.BranchType.BRANCH;
 import static org.sonar.db.component.BranchType.PULL_REQUEST;
@@ -113,8 +112,6 @@ public class BranchDaoIT {
     dto2.setKey("branch");
     underTest.insert(dbSession, dto2);
 
-    int a = 12124;
-
     underTest.updateBranchName(dbSession, "U1", "master");
     BranchDto loaded = underTest.selectByBranchKey(dbSession, "U1", "master").get();
     assertThat(loaded.getMergeBranchUuid()).isNull();
@@ -854,4 +851,47 @@ public class BranchDaoIT {
 
     assertThat(underTest.selectMainBranchByProjectUuid(dbSession, "U1")).isEmpty();
   }
+
+  @Test
+  public void selectMainBranchesByProjectUuids_whenNoUuidsPassed_shouldReturnEmpty() {
+    insertBranchesForProjectUuids(true, "1");
+
+    List<BranchDto> branchDtos = underTest.selectMainBranchesByProjectUuids(dbSession, Set.of());
+
+    assertThat(branchDtos).isEmpty();
+  }
+
+  @Test
+  public void selectMainBranchesByProjectUuids_whenOneUuidPassedAndTwoBranchesInDatabase_shouldReturnOneBranch() {
+    insertBranchesForProjectUuids(true, "1", "2");
+
+    List<BranchDto> branchDtos = underTest.selectMainBranchesByProjectUuids(dbSession, Set.of("1"));
+
+    assertThat(branchDtos).hasSize(1);
+    assertThat(branchDtos).extracting(BranchDto::getProjectUuid).allMatch(s -> s.equals("1"));
+  }
+
+  @Test
+  public void selectMainBranchesByProjectUuids_whenTenUuidsPassedAndTenBranchesInDatabase_shouldReturnAllBranches() {
+    String[] projectUuids = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
+    insertBranchesForProjectUuids(true, projectUuids);
+    insertBranchesForProjectUuids(false, projectUuids);
+
+    List<BranchDto> branchDtos = underTest.selectMainBranchesByProjectUuids(dbSession, Set.of(projectUuids));
+
+    assertThat(branchDtos).hasSize(10);
+    assertThat(branchDtos).extracting(BranchDto::isMain).allMatch(b -> true);
+  }
+
+  private void insertBranchesForProjectUuids(boolean mainBranch, String... uuids) {
+    for (String uuid : uuids) {
+      BranchDto dto = new BranchDto();
+      dto.setProjectUuid(uuid);
+      dto.setUuid(uuid + "-uuid" + mainBranch);
+      dto.setIsMain(mainBranch);
+      dto.setBranchType(BranchType.BRANCH);
+      dto.setKey("feature-" + uuid + mainBranch);
+      underTest.insert(dbSession, dto);
+    }
+  }
 }
index bb52a2166719910af5b6050dd5ea662f2d5af0b5..674833e209e6514c56b8d0dc02f22713823dd9ae 100644 (file)
@@ -36,6 +36,7 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.BranchType;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.metric.MetricDto;
 
 import static java.util.Arrays.asList;
@@ -173,19 +174,19 @@ public class LiveMeasureDaoIT {
   @Test
   public void selectForProjectsByMetricUuids_shouldReturnProjectWithTRKQualifierOnly() {
     MetricDto metric = db.measures().insertMetric();
-    ComponentDto application = db.components().insertPrivateApplication().getMainBranchComponent();
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectData application = db.components().insertPrivateApplication();
+    ProjectData project = db.components().insertPrivateProject();
+    ProjectData project2 = db.components().insertPrivateProject();
     db.components().addApplicationProject(application, project, project2);
-    underTest.insert(db.getSession(), newLiveMeasure(application, metric).setValue(3.14).setData((String) null));
-    underTest.insert(db.getSession(), newLiveMeasure(project, metric).setValue(4.54).setData((String) null));
-    underTest.insert(db.getSession(), newLiveMeasure(project2, metric).setValue(5.56).setData((String) null));
+    underTest.insert(db.getSession(), newLiveMeasure(application.getMainBranchComponent(), metric).setValue(3.14).setData((String) null));
+    underTest.insert(db.getSession(), newLiveMeasure(project.getMainBranchComponent(), metric).setValue(4.54).setData((String) null));
+    underTest.insert(db.getSession(), newLiveMeasure(project2.getMainBranchComponent(), metric).setValue(5.56).setData((String) null));
 
     List<LiveMeasureDto> selected = underTest.selectForProjectsByMetricUuids(db.getSession(), List.of(metric.getUuid()));
 
     assertThat(selected)
       .extracting(LiveMeasureDto::getProjectUuid)
-      .containsExactlyInAnyOrder(project.uuid(), project2.uuid());
+      .containsExactlyInAnyOrder(project.projectUuid(), project2.projectUuid());
   }
 
   @Test
index 5e57fc83960bd44e7d7500716df7661ea9427bce..94fa0a6a606a34864709c1569cf79acb34cc39a0 100644 (file)
@@ -43,6 +43,7 @@ import org.sonar.db.audit.AuditPersister;
 import org.sonar.db.audit.NoOpAuditPersister;
 import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.measure.LiveMeasureDto;
 import org.sonar.db.metric.MetricDto;
 import org.sonar.db.qualityprofile.QProfileDto;
@@ -316,14 +317,14 @@ public class ProjectDaoIT {
   }
   @Test
   public void selectAllProjectUuids_shouldOnlyReturnProjectWithTRKQualifier() {
-    ComponentDto application = db.components().insertPrivateApplication().getMainBranchComponent();
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectData application = db.components().insertPrivateApplication();
+    ProjectData project = db.components().insertPrivateProject();
+    ProjectData project2 = db.components().insertPrivateProject();
     db.components().addApplicationProject(application, project, project2);
 
     List<String> projectUuids = projectDao.selectAllProjectUuids(db.getSession());
 
-    assertThat(projectUuids).containsExactlyInAnyOrder(project.uuid(), project2.uuid());
+    assertThat(projectUuids).containsExactlyInAnyOrder(project.projectUuid(), project2.projectUuid());
   }
 
   private void insertDefaultQualityProfile(String language) {
index 2e708ed2b824d1a9bd22b7c7c177d9b1a24b9ccc..ff33dc8eb383e769608313425c251625e9d470b7 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.db.component;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 import org.sonar.api.utils.System2;
 import org.sonar.core.util.UuidFactory;
@@ -53,11 +54,6 @@ public class ApplicationProjectsDao implements Dao {
     return getMapper(dbSession).selectProjects(applicationUuid);
   }
 
-  public void remove(DbSession dbSession, String applicationUuid) {
-    getMapper(dbSession).removeApplicationBranchProjectBranchesByApplication(applicationUuid);
-    getMapper(dbSession).removeApplicationProjectsByApplication(applicationUuid);
-  }
-
   public void addProjectBranchToAppBranch(DbSession dbSession, BranchDto applicationBranch, BranchDto projectBranch) {
     getMapper(dbSession).addProjectBranchToAppBranch(
       uuidFactory.create(),
@@ -98,11 +94,11 @@ public class ApplicationProjectsDao implements Dao {
     return getMapper(dbSession).selectApplicationsFromProjects(projectUuids);
   }
 
-  private static ApplicationProjectsMapper getMapper(DbSession session) {
-    return session.getMapper(ApplicationProjectsMapper.class);
+  public List<BranchDto> selectProjectsMainBranchesOfApplication(DbSession dbSession, String applicationUuid) {
+    return getMapper(dbSession).selectProjectsMainBranchesOfApplication(applicationUuid);
   }
 
-  public void removeAllProjectBranchesOfAppBranch(DbSession dbSession, String applicationBranchUuid) {
-    getMapper(dbSession).removeAllProjectBranchesOfAppBranch(applicationBranchUuid);
+  private static ApplicationProjectsMapper getMapper(DbSession session) {
+    return session.getMapper(ApplicationProjectsMapper.class);
   }
 }
index 28e8dec3623fdde4289e9a20f8413f9431a3a332..16bc8b1915b008519ca4a1d13260614a492fd32b 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.db.component;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Set;
 import org.apache.ibatis.annotations.Param;
 import org.sonar.db.project.ProjectDto;
@@ -41,10 +42,6 @@ public interface ApplicationProjectsMapper {
 
   Set<ProjectDto> selectProjects(@Param("applicationUuid") String applicationUuid);
 
-  void removeApplicationProjectsByApplication(String applicationUuid);
-
-  void removeApplicationBranchProjectBranchesByApplication(String applicationUuid);
-
   void addProjectBranchToAppBranch(
     @Param("uuid") String uuid,
     @Param("applicationUuid") String applicationUuid,
@@ -65,5 +62,5 @@ public interface ApplicationProjectsMapper {
 
   Set<ProjectDto> selectApplicationsFromProjects(@Param("projectUuids") Collection<String> projectUuids);
 
-  void removeAllProjectBranchesOfAppBranch(@Param("applicationBranchUuid") String applicationBranchUuid);
+  List<BranchDto> selectProjectsMainBranchesOfApplication(String applicationUuid);
 }
index 39d000faec9e2fad9374ee27cc386940275b8699..e884c269e4ef472fd2887790477a5390537a3694 100644 (file)
@@ -95,7 +95,7 @@ public class BranchDao implements Dao {
    */
   public Collection<BranchDto> selectByComponent(DbSession dbSession, ComponentDto component) {
     BranchDto branchDto = mapper(dbSession).selectByUuid(component.branchUuid());
-    if(branchDto == null) {
+    if (branchDto == null) {
       return List.of();
     }
     return mapper(dbSession).selectByProjectUuid(branchDto.getProjectUuid());
@@ -109,7 +109,14 @@ public class BranchDao implements Dao {
     return mapper(dbSession).selectMainBranchByProjectUuid(projectUuid);
   }
 
-  public List<PrBranchAnalyzedLanguageCountByProjectDto> countPrBranchAnalyzedLanguageByProjectUuid(DbSession dbSession){
+  public List<BranchDto> selectMainBranchesByProjectUuids(DbSession dbSession, Set<String> projectUuids) {
+    if (projectUuids.isEmpty()) {
+      return List.of();
+    }
+    return mapper(dbSession).selectMainBranchesByProjectUuids(projectUuids);
+  }
+
+  public List<PrBranchAnalyzedLanguageCountByProjectDto> countPrBranchAnalyzedLanguageByProjectUuid(DbSession dbSession) {
     return mapper(dbSession).countPrBranchAnalyzedLanguageByProjectUuid();
   }
 
index 3d3a7daa5d29f0b26bc5f69745511e3d4db5ab1c..803cae647d2ca485edd11f279aa9f7ff94cf389f 100644 (file)
@@ -74,4 +74,6 @@ public interface BranchMapper {
   short doAnyOfComponentsNeedIssueSync(@Param("componentKeys") List<String> components);
 
   Optional<BranchDto> selectMainBranchByProjectUuid(String projectUuid);
+
+  List<BranchDto> selectMainBranchesByProjectUuids(@Param("projectUuids") Set<String> projectUuids);
 }
index d777f526599050a7fc18c256ee71ce46be0e444d..4836b3969cb2d251116561e01761c0faaa15a7e3 100644 (file)
@@ -43,23 +43,23 @@ public class IssueTesting {
     // only statics
   }
 
-  public static IssueDto newIssue(RuleDto rule, ComponentDto project, ComponentDto file) {
-    checkArgument(project.qualifier().equals(Qualifiers.PROJECT), "Second parameter should be a project");
-    return newIssue(rule, project.uuid(), project.getKey(), file);
+  public static IssueDto newIssue(RuleDto rule, ComponentDto branch, ComponentDto file) {
+    checkArgument(branch.qualifier().equals(Qualifiers.PROJECT), "Second parameter should be a branch that belongs to a project");
+    return newIssue(rule, branch.uuid(), branch.getKey(), file);
   }
 
   public static IssueDto newIssue(RuleDto rule, ProjectDto project, ComponentDto file) {
     return newIssue(rule, project.getUuid(), project.getKey(), file);
   }
 
-  public static IssueDto newIssue(RuleDto rule, String projectUuid, String projectKey, ComponentDto file) {
-    //checkArgument(file.branchUuid().equals(projectUuid), "The file doesn't belong to the project");
+  public static IssueDto newIssue(RuleDto rule, String branchUuid, String projectKey, ComponentDto file) {
+    //checkArgument(file.branchUuid().equals(branchUuid), "The file doesn't belong to the project");
 
     return new IssueDto()
       .setKee("uuid_" + randomAlphabetic(5))
       .setRule(rule)
       .setType(rule.getType())
-      .setProjectUuid(projectUuid)
+      .setProjectUuid(branchUuid)
       .setProjectKey(projectKey)
       .setComponent(file)
       .setStatus(Issue.STATUS_OPEN)
index 254ef9382916932289cdfc77b30f01fbf0c9bc88..5f277f8c630318eeff15e939c163413479f6d980 100644 (file)
       application_branch_uuid=#{applicationBranchUuid,jdbcType=VARCHAR}
   </delete>
 
+
+  <select id="selectProjectsMainBranchesOfApplication" parameterType="string" resultType="org.sonar.db.component.BranchDto">
+    select <include refid="branchColumns"/>
+    from project_branches pb
+    where
+    pb.project_uuid IN ( select project_uuid from app_projects where application_uuid = #{applicationUuid, jdbcType=VARCHAR} )
+    and is_main = ${_true}
+  </select>
+
 </mapper>
index 462f3d101449a1ed16287bae0ed93c5784c5ef78..0ce062f2ee52bb3d244dd8e1515f77fb5749f7d9 100644 (file)
     and is_main = ${_true}
   </select>
 
+  <select id="selectMainBranchesByProjectUuids" parameterType="string" resultType="org.sonar.db.component.BranchDto">
+    select <include refid="columns"/>
+    from project_branches pb
+    where pb.project_uuid in
+    <foreach collection="projectUuids" open="(" close=")" item="uuid" separator=",">
+      #{uuid,jdbcType=VARCHAR}
+    </foreach>
+    and is_main = ${_true}
+  </select>
+
   <select id="countPrBranchAnalyzedLanguageByProjectUuid" resultType="org.sonar.db.component.PrBranchAnalyzedLanguageCountByProjectDto">
     select pb.project_uuid as projectUuid,
       sum(case when pb.branch_type = 'PULL_REQUEST' then 1 else 0 end) as pullRequest,
index 88fe3d3428771e100a8e01a0f76b8eb93c717961..55acac3b05d56449030726412197ea214fbbf7a7 100644 (file)
@@ -382,16 +382,16 @@ public class ComponentDbTester {
     return new ProjectData(getProjectDtoByMainBranch(component), branchDto, component);
   }
 
-  public void addApplicationProject(ComponentDto application, ComponentDto... projects) {
-    for (ComponentDto project : projects) {
-      dbClient.applicationProjectsDao().addProject(dbSession, application.uuid(), project.uuid());
+  public void addApplicationProject(ProjectDto application, ProjectDto... projects) {
+    for (ProjectDto project : projects) {
+      dbClient.applicationProjectsDao().addProject(dbSession, application.getUuid(), project.getUuid());
     }
     db.commit();
   }
 
-  public void addApplicationProject(ProjectDto application, ProjectDto... projects) {
-    for (ProjectDto project : projects) {
-      dbClient.applicationProjectsDao().addProject(dbSession, application.getUuid(), project.getUuid());
+  public void addApplicationProject(ProjectData application, ProjectData... projects) {
+    for (ProjectData project : projects) {
+      dbClient.applicationProjectsDao().addProject(dbSession, application.getProjectDto().getUuid(), project.getProjectDto().getUuid());
     }
     db.commit();
   }
@@ -461,6 +461,10 @@ public class ComponentDbTester {
     return insertSnapshot(project, defaults());
   }
 
+  public SnapshotDto insertSnapshot(ProjectData project, Consumer<SnapshotDto> consumer) {
+    return insertSnapshot(project.getProjectDto(), consumer);
+  }
+
   public SnapshotDto insertSnapshot(ProjectDto project, Consumer<SnapshotDto> consumer) {
     SnapshotDto snapshotDto = SnapshotTesting.newAnalysis(project.getUuid());
     consumer.accept(snapshotDto);
index cc165d1b7c2bcdcaeb95393b2fa9f960617a7b33..2b607e0c894e948352c758256f793327ac709c67 100644 (file)
@@ -160,6 +160,10 @@ public class ComponentTesting {
     return newPortfolio(Uuids.createFast()).setQualifier(Qualifiers.APP);
   }
 
+  public static ComponentDto newProjectCopy(ProjectData project, ProjectData view) {
+    return newProjectCopy(Uuids.createFast(), project.getMainBranchComponent(), view.getMainBranchComponent());
+  }
+
   public static ComponentDto newProjectCopy(ComponentDto project, ComponentDto view) {
     return newProjectCopy(Uuids.createFast(), project, view);
   }
index 21b55e1c66c21b1a64e2ccbb85fa828ee85b1eaf..33c870a61b0817e26b51ea17c70b30c231a8e100 100644 (file)
@@ -43,4 +43,12 @@ public class ProjectData {
   public BranchDto getMainBranchDto() {
     return mainBranchDto;
   }
+
+  public String projectUuid() {
+    return projectDto.getUuid();
+  }
+
+  public String projectKey() {
+    return projectDto.getKey();
+  }
 }
index 361994ac3f1cb127f6d99594063f9095793c183f..ae4da9f4a9f6c7c8b50ccb345278dc969d724af3 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.core.issue.FieldDiffs;
 import org.sonar.core.util.Uuids;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.user.UserDto;
@@ -175,6 +176,10 @@ public class IssueDbTester {
     return insertHotspot(issue);
   }
 
+  public final IssueDto insertHotspot(RuleDto rule, ProjectData project, ComponentDto file, Consumer<IssueDto>... populators) {
+    return insertHotspot(rule, project.getMainBranchComponent(), file, populators);
+  }
+
   public final IssueDto insertHotspot(ProjectDto project, ComponentDto file, Consumer<IssueDto>... populators) {
     RuleDto rule = db.rules().insertHotspotRule();
     IssueDto issue = newIssue(rule, project, file)
index f7a23fdd5e1dccdded58c2ea6766d1c2e357b52c..531d5e26247ef7fb7ec5769147590f67724ae3d3 100644 (file)
@@ -26,6 +26,7 @@ import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.component.SnapshotDto;
 import org.sonar.db.metric.MetricDto;
 
@@ -51,6 +52,15 @@ public class MeasureDbTester {
     return measureDto;
   }
 
+  @SafeVarargs
+  public final MeasureDto insertMeasure(BranchDto branchDto, SnapshotDto analysis, MetricDto metricDto, Consumer<MeasureDto>... consumers) {
+    MeasureDto measureDto = newMeasureDto(metricDto, branchDto.getUuid(), analysis);
+    Arrays.stream(consumers).forEach(c -> c.accept(measureDto));
+    dbClient.measureDao().insert(dbSession, measureDto);
+    dbSession.commit();
+    return measureDto;
+  }
+
   @SafeVarargs
   public final LiveMeasureDto insertLiveMeasure(ComponentDto component, MetricDto metric, Consumer<LiveMeasureDto>... consumers) {
     LiveMeasureDto dto = newLiveMeasure(component, metric);
@@ -69,6 +79,12 @@ public class MeasureDbTester {
     return dto;
   }
 
+  @SafeVarargs
+  public final LiveMeasureDto insertLiveMeasure(ProjectData projectData, MetricDto metric, Consumer<LiveMeasureDto>... consumers) {
+    return insertLiveMeasure(projectData.getMainBranchComponent(), metric, consumers);
+  }
+
+
   @SafeVarargs
   public final MetricDto insertMetric(Consumer<MetricDto>... consumers) {
     MetricDto metricDto = newMetricDto();
index efa6fa2321f615a850ae7b5b11a9e8bef7ca45dd..b38e11529c91fb026e71c45e9c1cddefd909f991 100644 (file)
@@ -37,13 +37,17 @@ public class MeasureTesting {
   }
 
   public static MeasureDto newMeasureDto(MetricDto metricDto, ComponentDto component, SnapshotDto analysis) {
+    return newMeasureDto(metricDto, component.uuid(), analysis);
+  }
+
+  public static MeasureDto newMeasureDto(MetricDto metricDto, String branchUuid, SnapshotDto analysis) {
     checkNotNull(metricDto.getUuid());
     checkNotNull(metricDto.getKey());
-    checkNotNull(component.uuid());
+    checkNotNull(branchUuid);
     checkNotNull(analysis.getUuid());
     return new MeasureDto()
       .setMetricUuid(metricDto.getUuid())
-      .setComponentUuid(component.uuid())
+      .setComponentUuid(branchUuid)
       .setAnalysisUuid(analysis.getUuid());
   }
 
index f7bc57929928c2f52c05e9f6c7e5dc872342c687..261d1b09cc31c1d4f21c1c731b927ec43b2968db 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.api.web.UserRole;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.permission.GlobalPermission;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.user.GroupDto;
@@ -144,14 +145,14 @@ public class ServerUserSessionTest {
   @Test
   public void checkChildProjectsPermission_succeeds_if_user_has_permissions_on_all_application_child_projects() {
     UserDto user = db.users().insertUser();
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    db.users().insertProjectPermissionOnUser(user, UserRole.USER, project);
-    ComponentDto application = db.components().insertPrivateApplication().getMainBranchComponent();
+    ProjectData project = db.components().insertPrivateProject();
+    db.users().insertProjectPermissionOnUser(user, UserRole.USER, project.getMainBranchComponent());
+    ProjectData application = db.components().insertPrivateApplication();
     db.components().addApplicationProject(application, project);
 
     UserSession underTest = newUserSession(user);
 
-    assertThat(underTest.checkChildProjectsPermission(UserRole.USER, application)).isSameAs(underTest);
+    assertThat(underTest.checkChildProjectsPermission(UserRole.USER, application.getMainBranchComponent())).isSameAs(underTest);
   }
 
   @Test
@@ -167,15 +168,15 @@ public class ServerUserSessionTest {
   @Test
   public void checkChildProjectsPermission_fails_with_FE_when_user_has_not_permission_for_specified_uuid_in_db() {
     UserDto user = db.users().insertUser();
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto application = db.components().insertPrivateApplication().getMainBranchComponent();
+    ProjectData project = db.components().insertPrivateProject();
+    ProjectData application = db.components().insertPrivateApplication();
     db.components().addApplicationProject(application, project);
     // add computed project
     db.components().insertComponent(newProjectCopy(project, application));
 
     UserSession underTest = newUserSession(user);
 
-    assertThatForbiddenExceptionIsThrown(() -> underTest.checkChildProjectsPermission(UserRole.USER, application));
+    assertThatForbiddenExceptionIsThrown(() -> underTest.checkChildProjectsPermission(UserRole.USER, application.getMainBranchComponent()));
   }
 
   @Test
@@ -249,44 +250,44 @@ public class ServerUserSessionTest {
 
   @Test
   public void test_hasChildProjectsPermission_for_logged_in_user() {
-    ComponentDto project1 = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectData project1 = db.components().insertPrivateProject();
+    ProjectData project2 = db.components().insertPrivateProject();
     UserDto user = db.users().insertUser();
-    db.users().insertProjectPermissionOnUser(user, UserRole.USER, project1);
+    db.users().insertProjectPermissionOnUser(user, UserRole.USER, project1.getMainBranchComponent());
 
-    ComponentDto application = db.components().insertPrivateApplication().getMainBranchComponent();
+    ProjectData application = db.components().insertPrivateApplication();
     db.components().addApplicationProject(application, project1);
     // add computed project
-    db.components().insertComponent(newProjectCopy(project1, application));
+    db.components().insertComponent(newProjectCopy(project1.getMainBranchComponent(), application.getMainBranchComponent()));
 
     UserSession session = newUserSession(user);
-    assertThat(session.hasChildProjectsPermission(UserRole.USER, application)).isTrue();
+    assertThat(session.hasChildProjectsPermission(UserRole.USER, application.getMainBranchComponent())).isTrue();
 
     db.components().addApplicationProject(application, project2);
-    db.components().insertComponent(newProjectCopy(project2, application));
+    db.components().insertComponent(newProjectCopy(project2.getMainBranchComponent(), application.getMainBranchComponent()));
 
-    assertThat(session.hasChildProjectsPermission(UserRole.USER, application)).isFalse();
+    assertThat(session.hasChildProjectsPermission(UserRole.USER, application.getMainBranchComponent())).isFalse();
   }
 
   @Test
   public void test_hasChildProjectsPermission_for_anonymous_user() {
-    ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectData project = db.components().insertPrivateProject();
     db.users().insertPermissionOnAnyone(UserRole.USER);
-    ComponentDto application = db.components().insertPrivateApplication().getMainBranchComponent();
-    db.components().addApplicationProject(application, project);
+    ProjectData application = db.components().insertPrivateApplication();
+    db.components().addApplicationProject(application.getProjectDto(), project.getProjectDto());
     // add computed project
-    db.components().insertComponent(newProjectCopy(project, application));
+    db.components().insertComponent(newProjectCopy(project.getMainBranchComponent(), application.getMainBranchComponent()));
 
     UserSession session = newAnonymousSession();
-    assertThat(session.hasChildProjectsPermission(UserRole.USER, application)).isFalse();
+    assertThat(session.hasChildProjectsPermission(UserRole.USER, application.getProjectDto())).isFalse();
   }
 
   @Test
   public void hasChildProjectsPermission_keeps_cache_of_permissions_of_anonymous_user() {
     db.users().insertPermissionOnAnyone(UserRole.USER);
 
-    ComponentDto project = db.components().insertPublicProject().getMainBranchComponent();
-    ComponentDto application = db.components().insertPublicApplication().getMainBranchComponent();
+    ProjectDto project = db.components().insertPublicProject().getProjectDto();
+    ProjectDto application = db.components().insertPublicApplication().getProjectDto();
     db.components().addApplicationProject(application, project);
 
     UserSession session = newAnonymousSession();
@@ -295,7 +296,7 @@ public class ServerUserSessionTest {
     assertThat(session.hasChildProjectsPermission(UserRole.USER, application)).isTrue();
 
     // change privacy of the project without updating the cache
-    db.getDbClient().componentDao().setPrivateForBranchUuidWithoutAudit(db.getSession(), project.uuid(), true);
+    db.getDbClient().componentDao().setPrivateForBranchUuidWithoutAudit(db.getSession(), project.getUuid(), true);
     assertThat(session.hasChildProjectsPermission(UserRole.USER, application)).isTrue();
   }
 
@@ -599,8 +600,8 @@ public class ServerUserSessionTest {
     ComponentDto project2 = db.components().insertPrivateProject().getMainBranchComponent();
     ComponentDto project3 = db.components().insertPrivateProject().getMainBranchComponent();
     ComponentDto project4 = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto project5 = db.components().insertPrivateProject().getMainBranchComponent();
-    ComponentDto project6 = db.components().insertPrivateProject().getMainBranchComponent();
+    ProjectData project5 = db.components().insertPrivateProject();
+    ProjectData project6 = db.components().insertPrivateProject();
 
     UserDto user = db.users().insertUser();
     UserSession underTest = newUserSession(user);
@@ -611,10 +612,10 @@ public class ServerUserSessionTest {
     ComponentDto subPortfolio = db.components().insertComponent(newSubPortfolio(portfolio));
     db.users().insertProjectPermissionOnUser(user, UserRole.USER, subPortfolio);
 
-    ComponentDto app = db.components().insertPrivateApplication().getMainBranchComponent();
-    db.users().insertProjectPermissionOnUser(user, UserRole.USER, app);
+    ProjectData app = db.components().insertPrivateApplication();
+    db.users().insertProjectPermissionOnUser(user, UserRole.USER, app.getMainBranchComponent());
 
-    ComponentDto app2 = db.components().insertPrivateApplication().getMainBranchComponent();
+    ProjectData app2 = db.components().insertPrivateApplication();
 
     // Add public project1 to private portfolio
     db.components().addPortfolioProject(portfolio, project1);
@@ -636,25 +637,25 @@ public class ServerUserSessionTest {
     var copyProject3 = db.components().insertComponent(newProjectCopy(project3, portfolio));
 
     // Add private project5 with USER permissions to app
-    db.users().insertProjectPermissionOnUser(user, UserRole.USER, project5);
+    db.users().insertProjectPermissionOnUser(user, UserRole.USER, project5.getMainBranchComponent());
     db.components().addApplicationProject(app, project5);
     var copyProject5 = db.components().insertComponent(newProjectCopy(project5, app));
-    db.components().addPortfolioReference(portfolio, app.uuid());
+    db.components().addPortfolioReference(portfolio, app.getProjectDto().getUuid());
 
     // Add private project6 to private app2
     db.components().addApplicationProject(app2, project6);
     var copyProject6 = db.components().insertComponent(newProjectCopy(project6, app2));
-    db.components().addPortfolioReference(portfolio, app2.uuid());
+    db.components().addPortfolioReference(portfolio, app2.getMainBranchComponent().uuid());
 
     assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, List.of(portfolio))).isEmpty();
     assertThat(underTest.keepAuthorizedComponents(UserRole.USER, List.of(portfolio))).containsExactly(portfolio);
 
-    assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(app, subPortfolio, app2))).isEmpty();
-    assertThat(underTest.keepAuthorizedComponents(UserRole.USER, Arrays.asList(app, subPortfolio, app2))).containsExactly(app, subPortfolio);
+    assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(app.getMainBranchComponent(), subPortfolio, app2.getMainBranchComponent()))).isEmpty();
+    assertThat(underTest.keepAuthorizedComponents(UserRole.USER, Arrays.asList(app.getMainBranchComponent(), subPortfolio, app2.getMainBranchComponent()))).containsExactly(app.getMainBranchComponent(), subPortfolio);
 
-    assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(project1, project2, project3, project4, project5, project6))).isEmpty();
-    assertThat(underTest.keepAuthorizedComponents(UserRole.USER, Arrays.asList(project1, project2, project3, project4, project5, project6))).containsExactly(project1, project2,
-      project4, project5);
+    assertThat(underTest.keepAuthorizedComponents(UserRole.ADMIN, Arrays.asList(project1, project2, project3, project4, project5.getMainBranchComponent(), project6.getMainBranchComponent()))).isEmpty();
+    assertThat(underTest.keepAuthorizedComponents(UserRole.USER, Arrays.asList(project1, project2, project3, project4, project5.getMainBranchComponent(), project6.getMainBranchComponent()))).containsExactly(project1, project2,
+      project4, project5.getMainBranchComponent());
     assertThat(underTest.keepAuthorizedComponents(UserRole.USER, Arrays.asList(copyProject1, copyProject2, copyProject3, copyProject4, copyProject5, copyProject6)))
       .containsExactly(copyProject1, copyProject2, copyProject4, copyProject5);
   }
index 45ec4c907e3db1d0da0e8e96055dffade83ad607..04441479d7a1103101be583ebdf87cbcfe31d9d4 100644 (file)
@@ -24,7 +24,9 @@ import org.junit.Test;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
+import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.ComponentDto;
+import org.sonar.db.project.ProjectDto;
 import org.sonar.server.exceptions.NotFoundException;
 
 import static java.lang.String.format;
@@ -257,4 +259,23 @@ public class ComponentFinderIT {
     assertThat(retrievedFile.name()).isEqualTo(file.name());
     assertThat(retrievedFile.longName()).isEqualTo(file.longName());
   }
+
+  @Test
+  public void getMainBranch_whenMainBranchExist_shouldReturnMainBranchForProject() {
+    ProjectDto projectDto = db.components().insertPrivateProject().getProjectDto();
+
+    BranchDto mainBranch = underTest.getMainBranch(dbSession, projectDto);
+
+    assertThat(mainBranch).isNotNull();
+    assertThat(mainBranch.isMain()).isTrue();
+  }
+
+  @Test
+  public void getMainBranch_whenMainBranchDoesNotExist_shouldThrowException() {
+    ProjectDto projectDto = new ProjectDto();
+    projectDto.setUuid("uuid");
+
+    assertThatThrownBy(() -> underTest.getMainBranch(dbSession, projectDto))
+      .isInstanceOf(IllegalStateException.class);
+  }
 }
index a5255b25d889fabf2286c4f19c14d655f47581fd..eec9682545a7731d739c340d2429ca07e28f4f32 100644 (file)
@@ -51,6 +51,7 @@ import org.sonar.db.component.BranchDto;
 import org.sonar.db.component.BranchType;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.ProjectData;
 import org.sonar.db.issue.IssueDto;
 import org.sonar.db.project.ProjectDto;
 import org.sonar.db.protobuf.DbCommons;
@@ -1824,9 +1825,9 @@ public class SearchActionIT {
     long referenceDate = 800_996_999_332L;
 
     system2.setNow(referenceDate + 10_000);
-    ComponentDto application = dbTester.components().insertPublicApplication().getMainBranchComponent();
-    ComponentDto project = dbTester.components().insertPublicProject().getMainBranchComponent();
-    ComponentDto project2 = dbTester.components().insertPublicProject().getMainBranchComponent();
+    ProjectData application = dbTester.components().insertPublicApplication();
+    ProjectData project = dbTester.components().insertPublicProject();
+    ProjectData project2 = dbTester.components().insertPublicProject();
 
     dbTester.components().addApplicationProject(application, project);
     dbTester.components().addApplicationProject(application, project2);
@@ -1836,27 +1837,27 @@ public class SearchActionIT {
 
     indexViews();
 
-    userSessionRule.registerApplication(application, project, project2);
+    userSessionRule.registerApplication(application.getProjectDto(), project.getProjectDto(), project2.getProjectDto());
     indexPermissions();
-    ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
+    ComponentDto file = dbTester.components().insertComponent(newFileDto(project.getMainBranchComponent()));
     dbTester.components().insertSnapshot(project, t -> t.setPeriodDate(referenceDate).setLast(true));
     RuleDto rule = newRule(SECURITY_HOTSPOT);
     IssueDto afterRef = dbTester.issues().insertHotspot(rule, project, file, t -> t.setIssueCreationTime(referenceDate + 1000));
     IssueDto atRef = dbTester.issues().insertHotspot(rule, project, file, t -> t.setType(SECURITY_HOTSPOT).setIssueCreationTime(referenceDate));
     IssueDto beforeRef = dbTester.issues().insertHotspot(rule, project, file, t -> t.setIssueCreationTime(referenceDate - 1000));
 
-    ComponentDto file2 = dbTester.components().insertComponent(newFileDto(project2));
+    ComponentDto file2 = dbTester.components().insertComponent(newFileDto(project2.getMainBranchComponent()));
     IssueDto project2Issue = dbTester.issues().insertHotspot(rule, project2, file2, t -> t.setIssueCreationTime(referenceDate - 1000));
 
     indexIssues();
 
-    SearchWsResponse responseAll = newRequest(application)
+    SearchWsResponse responseAll = newRequest(application.getMainBranchComponent())
       .executeProtobuf(SearchWsResponse.class);
     assertThat(responseAll.getHotspotsList())
       .extracting(SearchWsResponse.Hotspot::getKey)
       .containsExactlyInAnyOrder(afterRef.getKey(), atRef.getKey(), beforeRef.getKey(), project2Issue.getKey());
 
-    SearchWsResponse responseOnLeak = newRequest(application,
+    SearchWsResponse responseOnLeak = newRequest(application.getMainBranchComponent(),
       t -> t.setParam(PARAM_IN_NEW_CODE_PERIOD, "true"))
       .executeProtobuf(SearchWsResponse.class);
     assertThat(responseOnLeak.getHotspotsList())
index 8a5ebdbcd0faa92b06006320d8e9ef9773d4f24e..2d3cc1b1000fb396eab3f890cca45c274b6715b6 100644 (file)
@@ -150,7 +150,7 @@ public class ComponentFinder {
   }
 
   public BranchDto getMainBranch(DbSession dbSession, ProjectDto projectDto) {
-    return dbClient.branchDao().selectByUuid(dbSession, projectDto.getUuid())
+    return dbClient.branchDao().selectMainBranchByProjectUuid(dbSession, projectDto.getUuid())
       .orElseThrow(() -> new IllegalStateException(String.format("Can't find main branch for project '%s'", projectDto.getKey())));
   }
 
index e7edae1e7f714e094cfc23f0cb277ecb512c3a9d..aa1dc824b2997dfcfbd61360ed06a0e0565e5c99 100644 (file)
@@ -486,9 +486,8 @@ public class SearchAction implements HotspotsWsAction {
     Set<String> branchUuids;
 
     if (appBranch.isMain()) {
-      // TODO assuming project uuid matches main branch uuid
-      branchUuids = dbClient.applicationProjectsDao().selectProjects(dbSession, appBranch.getProjectUuid()).stream()
-        .map(ProjectDto::getUuid)
+      branchUuids = dbClient.applicationProjectsDao().selectProjectsMainBranchesOfApplication(dbSession, appBranch.getProjectUuid()).stream()
+        .map(BranchDto::getUuid)
         .collect(Collectors.toSet());
     } else {
       branchUuids = dbClient.applicationProjectsDao().selectProjectBranchesFromAppBranchUuid(dbSession, appBranch.getUuid()).stream()