]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19003 Fix error when retrieving multiple components with the same key and diffe...
authorMatteo Mara <matteo.mara@sonarsource.com>
Thu, 8 Jun 2023 21:07:58 +0000 (23:07 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 12 Jun 2023 20:02:49 +0000 (20:02 +0000)
server/sonar-db-dao/src/it/java/org/sonar/db/component/ComponentDaoIT.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentMapper.java
server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ComponentUpdaterIT.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/component/ComponentUpdater.java

index beb63a96a1964b154f6f5fd7d64511163ef95431..b9b9934f3cf32f12d83cb27095db65be4b926d59 100644 (file)
@@ -1796,10 +1796,10 @@ public class ComponentDaoIT {
     String projectKey = randomAlphabetic(5).toLowerCase();
     db.components().insertPrivateProject(c -> c.setKey(projectKey)).getMainBranchComponent();
 
-    ComponentDto result = underTest.selectByKeyCaseInsensitive(db.getSession(), projectKey.toUpperCase()).orElse(null);
+    List<ComponentDto> result = underTest.selectByKeyCaseInsensitive(db.getSession(), projectKey.toUpperCase());
 
-    assertThat(result).isNotNull();
-    assertThat(result.getKey()).isEqualTo(projectKey);
+    assertThat(result).isNotEmpty();
+    assertThat(result.get(0).getKey()).isEqualTo(projectKey);
   }
 
   @Test
@@ -1809,9 +1809,9 @@ public class ComponentDaoIT {
     BranchDto projectBranch = db.components().insertProjectBranch(project);
     ComponentDto file = db.components().insertFile(projectBranch);
 
-    ComponentDto result = underTest.selectByKeyCaseInsensitive(db.getSession(), file.getKey()).orElse(null);
+    List<ComponentDto> result = underTest.selectByKeyCaseInsensitive(db.getSession(), file.getKey());
 
-    assertThat(result).isNull();
+    assertThat(result).isEmpty();
   }
 
   @Test
@@ -1819,7 +1819,7 @@ public class ComponentDaoIT {
     String projectKey = randomAlphabetic(5).toLowerCase();
     db.components().insertPrivateProject(c -> c.setKey(projectKey)).getMainBranchComponent();
 
-    Optional<ComponentDto> result = underTest.selectByKeyCaseInsensitive(db.getSession(), projectKey + randomAlphabetic(1));
+    List<ComponentDto> result = underTest.selectByKeyCaseInsensitive(db.getSession(), projectKey + randomAlphabetic(1));
 
     assertThat(result).isEmpty();
   }
index 22ca24a9df23113952733b5d34f455fe48675ebb..7e96d889995710c2f453e9f6b1a8437faef05064 100644 (file)
@@ -33,7 +33,6 @@ import javax.annotation.Nullable;
 import org.apache.ibatis.session.ResultHandler;
 import org.apache.ibatis.session.RowBounds;
 import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
 import org.sonar.db.Dao;
 import org.sonar.db.DbSession;
 import org.sonar.db.RowNotFoundException;
@@ -180,8 +179,8 @@ public class ComponentDao implements Dao {
     return Optional.ofNullable(mapper(session).selectByKeyAndBranchOrPr(key, null, pullRequestId));
   }
 
-  public Optional<ComponentDto> selectByKeyCaseInsensitive(DbSession session, String key) {
-    return Optional.ofNullable(mapper(session).selectByKeyCaseInsensitive(key));
+  public List<ComponentDto> selectByKeyCaseInsensitive(DbSession session, String key) {
+    return mapper(session).selectByKeyCaseInsensitive(key);
   }
 
   /**
index 1e954409aa01afd671895469a622969a60106762..49f6ad27ec0bd85b6ec419b7da26a1326322a8cb 100644 (file)
@@ -30,7 +30,7 @@ import org.apache.ibatis.session.RowBounds;
 
 public interface ComponentMapper {
   @CheckForNull
-  ComponentDto selectByKeyCaseInsensitive(@Param("key") String key);
+  List<ComponentDto> selectByKeyCaseInsensitive(@Param("key") String key);
 
   @CheckForNull
   ComponentDto selectByKeyAndBranchOrPr(@Param("key") String key, @Nullable @Param("branch") String branch, @Nullable @Param("pullRequest") String pullRequest);
index 504e25af0e35d3f4a58413d00e441c9798ba442a..afc40542c2bdeefccc3b5f8530f600d6b6934e9b 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.component;
 
 import java.util.Optional;
+import org.apache.commons.lang3.StringUtils;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -338,6 +339,26 @@ public class ComponentUpdaterIT {
       .hasMessage("Could not create Project with key: \"%s\". A similar key already exists: \"%s\"", newKey, existingKey);
   }
 
+  @Test
+  public void createComponent_shouldFail_whenCreatingComponentWithMultipleExistingKeyButDifferentCase() {
+    String existingKey = randomAlphabetic(5).toUpperCase();
+    String existingKeyLowerCase = existingKey.toLowerCase();
+    db.components().insertPrivateProject(component -> component.setKey(existingKey));
+    db.components().insertPrivateProject(component -> component.setKey(existingKeyLowerCase));
+    String newKey = StringUtils.capitalize(existingKeyLowerCase);
+
+    NewComponent newComponent = NewComponent.newComponentBuilder()
+      .setKey(newKey)
+      .setName(DEFAULT_PROJECT_NAME)
+      .build();
+
+    DbSession dbSession = db.getSession();
+    assertThatThrownBy(() -> underTest.create(dbSession, newComponent, null, null))
+      .isInstanceOf(BadRequestException.class)
+      .hasMessage("Could not create Project with key: \"%s\". A similar key already exists: \"%s, %s\"", newKey, existingKey, existingKeyLowerCase);
+  }
+
+
   @Test
   public void create_createsComponentWithMasterBranchName() {
     String componentNameAndKey = "createApplicationOrPortfolio";
index c905660861a58d8d65df63644c16fec25a5dfa92..1126ed1f7937f994804e761d0154278b86e152d5 100644 (file)
 package org.sonar.server.component;
 
 import com.google.common.annotations.VisibleForTesting;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
+import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 import javax.annotation.Nullable;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Scopes;
@@ -167,12 +171,17 @@ public class ComponentUpdater {
   }
 
   private void checkKeyAlreadyExists(DbSession dbSession, NewComponent newComponent) {
-    Optional<ComponentDto> componentDto = newComponent.isProject()
+    List<ComponentDto> componentDtos = newComponent.isProject()
       ? dbClient.componentDao().selectByKeyCaseInsensitive(dbSession, newComponent.key())
-      : dbClient.componentDao().selectByKey(dbSession, newComponent.key());
+      : dbClient.componentDao().selectByKey(dbSession, newComponent.key()).map(Collections::singletonList).orElse(new ArrayList<>());
 
-    componentDto.map(ComponentDto::getKey)
-      .ifPresent(existingKey -> throwBadRequestException(KEY_ALREADY_EXISTS_ERROR, getQualifierToDisplay(newComponent.qualifier()), newComponent.key(), existingKey));
+    if (!componentDtos.isEmpty()) {
+      String alreadyExistingKeys = componentDtos
+        .stream()
+        .map(ComponentDto::getKey)
+        .collect(Collectors.joining(", "));
+      throwBadRequestException(KEY_ALREADY_EXISTS_ERROR, getQualifierToDisplay(newComponent.qualifier()), newComponent.key(), alreadyExistingKeys);
+    }
   }
 
   private ComponentDto createRootComponent(DbSession session, NewComponent newComponent, Consumer<ComponentDto> componentModifier, long now) {