From 411f4d9dcb09fefc23c03da7a108d090592e3fb9 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Thu, 4 Nov 2021 16:01:17 -0500 Subject: [PATCH] SONAR-15498 add IT and Purge should delete selected project if it only selects a branch being deleted --- .../org/sonar/db/purge/PurgeCommands.java | 4 + .../java/org/sonar/db/purge/PurgeDao.java | 2 +- .../java/org/sonar/db/purge/PurgeMapper.java | 2 + .../org/sonar/db/purge/PurgeMapper.xml | 13 ++++ .../org/sonar/db/purge/PurgeCommandsTest.java | 21 +++++- .../client/views/AddProjectBranchRequest.java | 74 +++++++++++++++++++ .../ws/client/views/CreateRequest.java | 20 +++++ .../views/RemoveProjectBranchRequest.java | 74 +++++++++++++++++++ .../ws/client/views/SearchRequest.java | 1 - .../ws/client/views/SetRegexpModeRequest.java | 12 +++ .../SetRemainingProjectsModeRequest.java | 13 +++- .../ws/client/views/SetTagsModeRequest.java | 12 +++ .../ws/client/views/ViewsService.java | 60 +++++++++------ 13 files changed, 279 insertions(+), 29 deletions(-) create mode 100644 sonar-ws/src/main/java/org/sonarqube/ws/client/views/AddProjectBranchRequest.java create mode 100644 sonar-ws/src/main/java/org/sonarqube/ws/client/views/RemoveProjectBranchRequest.java diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java index feba85ea9e3..402bf9ef5b8 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeCommands.java @@ -455,7 +455,11 @@ class PurgeCommands { public void deleteProjectInPortfolios(String rootUuid) { profiler.start("deleteProjectInPortfolios (portfolio_projects)"); + // delete selected project if it's only selecting a single branch corresponding to rootUuid + purgeMapper.deletePortfolioProjectsByBranchUuid(rootUuid); + // delete selected branches if branch is rootUuid or if it's part of a project that is rootUuid purgeMapper.deletePortfolioProjectBranchesByBranchUuid(rootUuid); + // delete selected project if project is rootUuid purgeMapper.deletePortfolioProjectsByProjectUuid(rootUuid); session.commit(); profiler.stop(); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java index 11a0ee7e67c..7e0d1efd9ac 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java @@ -165,7 +165,7 @@ public class PurgeDao implements Dao { private static final class NewCodePeriodAnalysisFilter implements Predicate { @Nullable - private String analysisUuid; + private final String analysisUuid; private NewCodePeriodAnalysisFilter(PurgeMapper mapper, String componentUuid) { this.analysisUuid = mapper.selectSpecificAnalysisNewCodePeriod(componentUuid); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java index 5270cec0721..348d043c7d5 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeMapper.java @@ -147,6 +147,8 @@ public interface PurgeMapper { void deleteApplicationBranchProjectBranchesByProjectBranchUuid(@Param("projectBranchUuid") String projectBranchUuid); + void deletePortfolioProjectsByBranchUuid(@Param("branchUuid") String branchUuid); + void deletePortfolioProjectsByProjectUuid(@Param("projectUuid") String projectUuid); void deletePortfolioProjectBranchesByBranchUuid(@Param("branchUuid") String branchUuid); diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml index 32267058e04..604300faae0 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/purge/PurgeMapper.xml @@ -349,6 +349,19 @@ WHERE project_branch_uuid=#{projectBranchUuid,jdbcType=VARCHAR} + + + DELETE + FROM portfolio_projects + WHERE uuid in ( + SELECT ppb.portfolio_project_uuid FROM portfolio_proj_branches ppb + + WHERE ppb.branch_uuid = #{branchUuid,jdbcType=VARCHAR} + + AND (SELECT count(*) FROM portfolio_proj_branches ppb2 WHERE ppb2.portfolio_project_uuid = ppb.portfolio_project_uuid) = 1 + ) + + DELETE FROM portfolio_projects diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java index 33c0475e5e5..f0851b0858c 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java @@ -56,7 +56,6 @@ import org.sonar.db.user.UserDto; import static com.google.common.collect.Lists.newArrayList; import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; import static java.util.Collections.singleton; import static java.util.Collections.singletonList; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; @@ -654,7 +653,7 @@ public class PurgeCommandsTest { } @Test - public void deleteProjectInPortfolios_deletes_project_and_branch_from_portfolios() { + public void deleteProjectInPortfolios_deletes_project_and_branch_from_portfolios_if_root_is_branch() { var portfolio1 = dbTester.components().insertPrivatePortfolioDto(); var portfolio2 = dbTester.components().insertPrivatePortfolioDto(); dbTester.components().insertPrivatePortfolio(); @@ -676,6 +675,24 @@ public class PurgeCommandsTest { .containsExactlyInAnyOrder(tuple(portfolio1.getUuid(), anotherProject.getUuid(), singleton("anotherProjectBranch"))); } + @Test + public void deleteProjectInPortfolios_deletes_project_and_branch_from_portfolios_if_root_is_project_only_selecting_a_single_branch() { + var portfolio1 = dbTester.components().insertPrivatePortfolioDto(); + dbTester.components().insertPrivatePortfolio(); + ProjectDto project = dbTester.components().insertPrivateProjectDto(); + + dbTester.components().addPortfolioProject(portfolio1, project); + dbTester.components().addPortfolioProjectBranch(portfolio1, project, "projectBranch"); + + PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2); + + purgeCommands.deleteProjectInPortfolios(project.getUuid()); + + assertThat(dbTester.getDbClient().portfolioDao().selectAllPortfolioProjects(dbTester.getSession())).isEmpty(); + assertThat(dbTester.countRowsOfTable("portfolio_proj_branches")).isZero(); + assertThat(dbTester.countRowsOfTable("portfolio_projects")).isZero(); + } + @Test public void deleteProjectInPortfolios_deletes_branch_from_portfolios_if_root_is_branch() { var portfolio1 = dbTester.components().insertPrivatePortfolioDto(); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/AddProjectBranchRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/AddProjectBranchRequest.java new file mode 100644 index 00000000000..0f3f63608f9 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/AddProjectBranchRequest.java @@ -0,0 +1,74 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonarqube.ws.client.views; + +import javax.annotation.Generated; + +/** + * This is part of the internal API. + * This is a POST request. + * @see Further information about this action online (including a response example) + * @since 9.2 + */ +@Generated("sonar-ws-generator") +public class AddProjectBranchRequest { + + private String branch; + private String key; + private String project; + + /** + * This is a mandatory parameter. + * Example value: "feature/my_branch" + */ + public AddProjectBranchRequest setBranch(String branch) { + this.branch = branch; + return this; + } + + public String getBranch() { + return branch; + } + + /** + * This is a mandatory parameter. + */ + public AddProjectBranchRequest setKey(String key) { + this.key = key; + return this; + } + + public String getKey() { + return key; + } + + /** + * This is a mandatory parameter. + * Example value: "my_project" + */ + public AddProjectBranchRequest setProject(String project) { + this.project = project; + return this; + } + + public String getProject() { + return project; + } +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/CreateRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/CreateRequest.java index 05c6bb4849e..97b58d3adf3 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/CreateRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/CreateRequest.java @@ -19,6 +19,7 @@ */ package org.sonarqube.ws.client.views; +import java.util.List; import javax.annotation.Generated; /** @@ -33,6 +34,7 @@ public class CreateRequest { private String description; private String key; private String name; + private String qualifier; private String visibility; /** @@ -69,6 +71,24 @@ public class CreateRequest { return name; } + /** + * Possible values: + *
    + *
  • "VW"
  • + *
  • "APP"
  • + *
+ * @deprecated since 7.3 + */ + @Deprecated + public CreateRequest setQualifier(String qualifier) { + this.qualifier = qualifier; + return this; + } + + public String getQualifier() { + return qualifier; + } + /** * Possible values: *
    diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/RemoveProjectBranchRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/RemoveProjectBranchRequest.java new file mode 100644 index 00000000000..c807a8b1d96 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/RemoveProjectBranchRequest.java @@ -0,0 +1,74 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonarqube.ws.client.views; + +import javax.annotation.Generated; + +/** + * This is part of the internal API. + * This is a POST request. + * @see Further information about this action online (including a response example) + * @since 9.2 + */ +@Generated("sonar-ws-generator") +public class RemoveProjectBranchRequest { + + private String branch; + private String key; + private String project; + + /** + * This is a mandatory parameter. + * Example value: "feature/my_branch" + */ + public RemoveProjectBranchRequest setBranch(String branch) { + this.branch = branch; + return this; + } + + public String getBranch() { + return branch; + } + + /** + * This is a mandatory parameter. + */ + public RemoveProjectBranchRequest setKey(String key) { + this.key = key; + return this; + } + + public String getKey() { + return key; + } + + /** + * This is a mandatory parameter. + * Example value: "my_project" + */ + public RemoveProjectBranchRequest setProject(String project) { + this.project = project; + return this; + } + + public String getProject() { + return project; + } +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SearchRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SearchRequest.java index cc4158edcaf..ae9f2d4e4ee 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SearchRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SearchRequest.java @@ -93,7 +93,6 @@ public class SearchRequest { /** * Possible values: *
      - *
    • "APP"
    • *
    • "VW"
    • *
    • "SVW"
    • *
    diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRegexpModeRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRegexpModeRequest.java index a2c330d6b3b..5ff689812b4 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRegexpModeRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRegexpModeRequest.java @@ -30,9 +30,21 @@ import javax.annotation.Generated; @Generated("sonar-ws-generator") public class SetRegexpModeRequest { + private String branch; private String portfolio; private String regexp; + /** + */ + public SetRegexpModeRequest setBranch(String branch) { + this.branch = branch; + return this; + } + + public String getBranch() { + return branch; + } + /** * This is a mandatory parameter. */ diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRemainingProjectsModeRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRemainingProjectsModeRequest.java index 866c9340d85..c4ff5c99b26 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRemainingProjectsModeRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetRemainingProjectsModeRequest.java @@ -30,8 +30,20 @@ import javax.annotation.Generated; @Generated("sonar-ws-generator") public class SetRemainingProjectsModeRequest { + private String branch; private String portfolio; + /** + */ + public SetRemainingProjectsModeRequest setBranch(String branch) { + this.branch = branch; + return this; + } + + public String getBranch() { + return branch; + } + /** * This is a mandatory parameter. */ @@ -43,5 +55,4 @@ public class SetRemainingProjectsModeRequest { public String getPortfolio() { return portfolio; } - } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetTagsModeRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetTagsModeRequest.java index 8fcfbff1b6f..33e239820b9 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetTagsModeRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/SetTagsModeRequest.java @@ -31,9 +31,21 @@ import javax.annotation.Generated; @Generated("sonar-ws-generator") public class SetTagsModeRequest { + private String branch; private String portfolio; private List tags; + /** + */ + public SetTagsModeRequest setBranch(String branch) { + this.branch = branch; + return this; + } + + public String getBranch() { + return branch; + } + /** * This is a mandatory parameter. */ diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/ViewsService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/ViewsService.java index d81260983b8..9ab8d60c5c2 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/views/ViewsService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/views/ViewsService.java @@ -73,16 +73,15 @@ public class ViewsService extends BaseService { * * This is part of the internal API. * This is a POST request. - * @see Further information about this action online (including a response example) - * @since 1.0 + * @see Further information about this action online (including a response example) + * @since 9.2 */ - public void addSubView(AddSubViewRequest request) { + public void addProjectBranch(AddProjectBranchRequest request) { call( - new PostRequest(path("add_sub_view")) - .setParam("description", request.getDescription()) + new PostRequest(path("add_project_branch")) + .setParam("branch", request.getBranch()) .setParam("key", request.getKey()) - .setParam("name", request.getName()) - .setParam("subKey", request.getSubKey()) + .setParam("project", request.getProject()) .setMediaType(MediaTypes.JSON) ).content(); } @@ -90,13 +89,17 @@ public class ViewsService extends BaseService { /** * * This is part of the internal API. - * This is a GET request. - * @see Further information about this action online (including a response example) + * This is a POST request. + * @see Further information about this action online (including a response example) * @since 1.0 */ - public String app() { - return call( - new GetRequest(path("app")) + public void addSubView(AddSubViewRequest request) { + call( + new PostRequest(path("add_sub_view")) + .setParam("description", request.getDescription()) + .setParam("key", request.getKey()) + .setParam("name", request.getName()) + .setParam("subKey", request.getSubKey()) .setMediaType(MediaTypes.JSON) ).content(); } @@ -114,6 +117,7 @@ public class ViewsService extends BaseService { .setParam("description", request.getDescription()) .setParam("key", request.getKey()) .setParam("name", request.getName()) + .setParam("qualifier", request.getQualifier()) .setParam("visibility", request.getVisibility()) .setMediaType(MediaTypes.JSON) ).content(); @@ -125,7 +129,9 @@ public class ViewsService extends BaseService { * This is a POST request. * @see Further information about this action online (including a response example) * @since 1.0 + * @deprecated since 9.2 */ + @Deprecated public void define(DefineRequest request) { call( new PostRequest(path("define")) @@ -140,7 +146,9 @@ public class ViewsService extends BaseService { * This is a GET request. * @see Further information about this action online (including a response example) * @since 2.0 + * @deprecated since 9.2 */ + @Deprecated public String definition() { return call( new GetRequest(path("definition")) @@ -277,14 +285,15 @@ public class ViewsService extends BaseService { * * This is part of the internal API. * This is a POST request. - * @see Further information about this action online (including a response example) - * @since 1.0 - * @deprecated since 7.1 + * @see Further information about this action online (including a response example) + * @since 9.2 */ - @Deprecated - public String run() { - return call( - new PostRequest(path("run")) + public void removeProjectBranch(RemoveProjectBranchRequest request) { + call( + new PostRequest(path("remove_project_branch")) + .setParam("branch", request.getBranch()) + .setParam("key", request.getKey()) + .setParam("project", request.getProject()) .setMediaType(MediaTypes.JSON) ).content(); } @@ -320,7 +329,7 @@ public class ViewsService extends BaseService { new PostRequest(path("set_manual_mode")) .setParam("portfolio", request.getPortfolio()) .setMediaType(MediaTypes.JSON) - ).content(); + ).content(); } /** @@ -335,23 +344,24 @@ public class ViewsService extends BaseService { new PostRequest(path("set_none_mode")) .setParam("portfolio", request.getPortfolio()) .setMediaType(MediaTypes.JSON) - ).content(); + ).content(); } /** * * This is part of the internal API. * This is a POST request. - * @see Further information about this action online (including a response example) + * @see Further information about this action online (including a response example) * @since 7.4 */ public void setRegexpMode(SetRegexpModeRequest request) { call( new PostRequest(path("set_regexp_mode")) + .setParam("branch", request.getBranch()) .setParam("portfolio", request.getPortfolio()) .setParam("regexp", request.getRegexp()) .setMediaType(MediaTypes.JSON) - ).content(); + ).content(); } /** @@ -364,9 +374,10 @@ public class ViewsService extends BaseService { public void setRemainingProjectsMode(SetRemainingProjectsModeRequest request) { call( new PostRequest(path("set_remaining_projects_mode")) + .setParam("branch", request.getBranch()) .setParam("portfolio", request.getPortfolio()) .setMediaType(MediaTypes.JSON) - ).content(); + ).content(); } /** @@ -379,6 +390,7 @@ public class ViewsService extends BaseService { public void setTagsMode(SetTagsModeRequest request) { call( new PostRequest(path("set_tags_mode")) + .setParam("branch", request.getBranch()) .setParam("portfolio", request.getPortfolio()) .setParam("tags", request.getTags() == null ? null : request.getTags().stream().collect(Collectors.joining(","))) .setMediaType(MediaTypes.JSON) -- 2.39.5