Analysis now produces a warning when the property that aggregates all previous module-level properties is not cleared.
.add(2401, "Create ORGANIZATION_ALM_BINDINGS table", CreateOrganizationsAlmBindingsTable.class)
.add(2402, "Add column USER_EXTERNAL_ID in ALM_APP_INSTALLS", AddUserExternalIdColumnInAlmAppInstall.class)
.add(2403, "Set IS_OWNER_USER not nullable in ALM_APP_INSTALLS", SetIsOwnerUserNotNullableInAlmAppInstalls.class)
- .add(2404, "Add table EVENT_COMPONENT_CHANGES", AddEventComponentChanges.class)
- .add(2405, "Move module and directory properties to a project level property", MigrateModuleProperties.class);
+ .add(2404, "Add table EVENT_COMPONENT_CHANGES", AddEventComponentChanges.class);
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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.sonar.server.platform.db.migration.version.v75;
-
-import java.sql.SQLException;
-import java.util.concurrent.atomic.AtomicReference;
-import org.sonar.api.utils.System2;
-import org.sonar.db.Database;
-import org.sonar.server.platform.db.migration.SupportsBlueGreen;
-import org.sonar.server.platform.db.migration.step.DataChange;
-import org.sonar.server.platform.db.migration.step.MassUpdate;
-import org.sonar.server.platform.db.migration.step.Upsert;
-
-@SupportsBlueGreen
-public class MigrateModuleProperties extends DataChange {
-
- private static final String NEW_PROPERTY_NAME = "sonar.subprojects.settings.removed";
-
- private final System2 system2;
-
- public MigrateModuleProperties(Database db, System2 system2) {
- super(db);
- this.system2 = system2;
- }
-
- @Override
- protected void execute(Context context) throws SQLException {
- long now = system2.now();
- moveModulePropertiesToProjectLevel(context, now);
- removeModuleProperties(context);
- }
-
- private static void moveModulePropertiesToProjectLevel(Context context, long time) throws SQLException {
- StringBuilder builder = new StringBuilder();
- AtomicReference<Integer> currentProjectId = new AtomicReference<>();
- AtomicReference<String> currentModuleUuid = new AtomicReference<>();
-
- context.prepareSelect("select prop.prop_key, prop.text_value, prop.clob_value, mod.name, mod.uuid, root.id as project_id, root.name as project_name " +
- "from properties prop " +
- "left join projects mod on mod.id = prop.resource_id " +
- "left join projects root on root.uuid = mod.project_uuid " +
- "where mod.qualifier = 'BRC'" +
- "order by root.uuid, mod.uuid, prop.prop_key")
- .scroll(row -> {
- String propertyKey = row.getString(1);
- String propertyTextValue = row.getString(2);
- String propertyClobValue = row.getString(3);
- String moduleName = row.getString(4);
- String moduleUuid = row.getString(5);
- Integer projectId = row.getInt(6);
- String projectName = row.getString(7);
-
- if (!projectId.equals(currentProjectId.get())) {
- if (currentProjectId.get() != null) {
- insertProjectProperties(context, currentProjectId.get(), builder.toString(), time);
- }
-
- builder.setLength(0);
- currentProjectId.set(projectId);
- }
-
- if (!moduleUuid.equals(currentModuleUuid.get())) {
- if (currentModuleUuid.get() != null && builder.length() != 0) {
- builder.append("\n");
- }
- builder.append("# previous settings for sub-project ").append(projectName).append("::").append(moduleName).append("\n");
- currentModuleUuid.set(moduleUuid);
- }
-
- String propertyValue = propertyTextValue == null ? propertyClobValue : propertyTextValue;
- builder.append(propertyKey).append("=").append(propertyValue).append("\n");
- });
-
- if (builder.length() > 0) {
- insertProjectProperties(context, currentProjectId.get(), builder.toString(), time);
- }
- }
-
- private static void insertProjectProperties(Context context, int projectId, String content, long time) throws SQLException {
- Upsert upsert = context.prepareUpsert("insert into properties (prop_key, resource_id, is_empty, clob_value, created_at) values (?, ?, ?, ?, ?)");
- upsert.setString(1, NEW_PROPERTY_NAME)
- .setInt(2, projectId)
- .setBoolean(3, false)
- .setString(4, content)
- .setLong(5, time)
- .execute()
- .commit();
- }
-
- private static void removeModuleProperties(Context context) throws SQLException {
- MassUpdate massUpdate = context.prepareMassUpdate().rowPluralName("remove module properties");
- massUpdate.select("select prop.id as property_id " +
- "from properties prop " +
- "left join projects mod on mod.id = prop.resource_id " +
- "where mod.qualifier = 'BRC'");
- massUpdate.update("delete from properties where id=?");
- massUpdate.execute((row, update) -> {
- update.setInt(1, row.getInt(1));
- return true;
- });
- }
-}
registry
.add(2500, "Create table USER_PROPERTIES", CreateUserPropertiesTable.class)
.add(2501, "Add index in table USER_PROPERTIES", AddUniqueIndexInUserPropertiesTable.class)
+ .add(2502, "Move module and directory properties to a project level property", MigrateModuleProperties.class)
.add(2505, "Fix the direction values of certain metrics (prepare for migration of conditions)", FixDirectionOfMetrics.class)
- .add(2506, "Migrate quality gate conditions using warning, period and no more supported operations", MigrateNoMoreUsedQualityGateConditions.class)
- ;
+ .add(2506, "Migrate quality gate conditions using warning, period and no more supported operations", MigrateNoMoreUsedQualityGateConditions.class);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonar.server.platform.db.migration.version.v76;
+
+import java.sql.SQLException;
+import java.util.concurrent.atomic.AtomicReference;
+import org.sonar.api.utils.System2;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.SupportsBlueGreen;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+import org.sonar.server.platform.db.migration.step.Upsert;
+
+@SupportsBlueGreen
+public class MigrateModuleProperties extends DataChange {
+
+ protected static final String NEW_PROPERTY_NAME = "sonar.modules.archivedSettings";
+
+ private final System2 system2;
+
+ public MigrateModuleProperties(Database db, System2 system2) {
+ super(db);
+ this.system2 = system2;
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ long now = system2.now();
+ moveModulePropertiesToProjectLevel(context, now);
+ removeModuleProperties(context);
+ }
+
+ private static void moveModulePropertiesToProjectLevel(Context context, long time) throws SQLException {
+ StringBuilder builder = new StringBuilder();
+ AtomicReference<Integer> currentProjectId = new AtomicReference<>();
+ AtomicReference<String> currentModuleUuid = new AtomicReference<>();
+
+ context.prepareSelect("select prop.prop_key, prop.text_value, prop.clob_value, mod.name, mod.uuid, root.id as project_id, root.name as project_name " +
+ "from properties prop " +
+ "left join projects mod on mod.id = prop.resource_id " +
+ "left join projects root on root.uuid = mod.project_uuid " +
+ "where mod.qualifier = 'BRC'" +
+ "order by root.uuid, mod.uuid, prop.prop_key")
+ .scroll(row -> {
+ String propertyKey = row.getString(1);
+ String propertyTextValue = row.getString(2);
+ String propertyClobValue = row.getString(3);
+ String moduleName = row.getString(4);
+ String moduleUuid = row.getString(5);
+ Integer projectId = row.getInt(6);
+ String projectName = row.getString(7);
+
+ if (!projectId.equals(currentProjectId.get())) {
+ if (currentProjectId.get() != null) {
+ insertProjectProperties(context, currentProjectId.get(), builder.toString(), time);
+ }
+
+ builder.setLength(0);
+ currentProjectId.set(projectId);
+ }
+
+ if (!moduleUuid.equals(currentModuleUuid.get())) {
+ if (currentModuleUuid.get() != null && builder.length() != 0) {
+ builder.append("\n");
+ }
+ builder.append("# previous settings for sub-project ").append(projectName).append("::").append(moduleName).append("\n");
+ currentModuleUuid.set(moduleUuid);
+ }
+
+ String propertyValue = propertyTextValue == null ? propertyClobValue : propertyTextValue;
+ builder.append(propertyKey).append("=").append(propertyValue).append("\n");
+ });
+
+ if (builder.length() > 0) {
+ insertProjectProperties(context, currentProjectId.get(), builder.toString(), time);
+ }
+ }
+
+ private static void insertProjectProperties(Context context, int projectId, String content, long time) throws SQLException {
+ Upsert upsert = context.prepareUpsert("insert into properties (prop_key, resource_id, is_empty, clob_value, created_at) values (?, ?, ?, ?, ?)");
+ upsert.setString(1, NEW_PROPERTY_NAME)
+ .setInt(2, projectId)
+ .setBoolean(3, false)
+ .setString(4, content)
+ .setLong(5, time)
+ .execute()
+ .commit();
+ }
+
+ private static void removeModuleProperties(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate().rowPluralName("remove module properties");
+ massUpdate.select("select prop.id as property_id " +
+ "from properties prop " +
+ "left join projects mod on mod.id = prop.resource_id " +
+ "where mod.qualifier = 'BRC'");
+ massUpdate.update("delete from properties where id=?");
+ massUpdate.execute((row, update) -> {
+ update.setInt(1, row.getInt(1));
+ return true;
+ });
+ }
+}
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 6);
+ verifyMigrationCount(underTest, 5);
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2018 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.sonar.server.platform.db.migration.version.v75;
-
-import java.sql.SQLException;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.internal.TestSystem2;
-import org.sonar.core.util.SequenceUuidFactory;
-import org.sonar.core.util.UuidFactory;
-import org.sonar.db.CoreDbTester;
-
-import static java.lang.String.valueOf;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class MigrateModulePropertiesTest {
- private final static long NOW = 50_000_000_000L;
-
- @Rule
- public CoreDbTester db = CoreDbTester.createForSchema(MigrateModulePropertiesTest.class, "schema.sql");
- private System2 system2 = new TestSystem2().setNow(NOW);
- private UuidFactory uuidFactory = new SequenceUuidFactory();
- private MigrateModuleProperties underTest = new MigrateModuleProperties(db.database(), system2);
-
- @Test
- public void multi_module_project_migration() throws SQLException {
- setupMultiModuleProject();
-
- underTest.execute();
-
- verifyMultiModuleProjectMigration();
- }
-
- @Test
- public void migration_is_reentrant() throws SQLException {
- setupMultiModuleProject();
-
- underTest.execute();
- underTest.execute();
-
- verifyMultiModuleProjectMigration();
- List<Map<String, Object>> remainingProperties = db.select("select ID from properties");
- assertThat(remainingProperties).hasSize(3);
- }
-
- @Test
- public void single_module_project_migration() throws SQLException {
- String project2Uuid = uuidFactory.create();
- insertComponent(5, project2Uuid, null, project2Uuid, Qualifiers.PROJECT, "Single module project");
- insertProperty(9, 5, "sonar.coverage.exclusions", "SingleModuleA.java");
- insertProperty(10, 5, "sonar.cp.exclusions", "SingleModuleB.java");
-
- underTest.execute();
-
- List<Map<String, Object>> properties = db.select("select ID, TEXT_VALUE, CLOB_VALUE " +
- "from properties " +
- "where PROP_KEY='sonar.subprojects.settings.removed' and RESOURCE_ID = 5");
- assertThat(properties).hasSize(0);
- List<Map<String, Object>> remainingProperties = db.select("select ID from properties");
- assertThat(remainingProperties).hasSize(2);
- }
-
- @Test
- public void properties_do_not_leak_between_projects() throws SQLException {
- setupMultiModuleProject();
- setupSecondMultiModuleProject();
-
- underTest.execute();
-
- verifyMultiModuleProjectMigration();
- verifySecondMultiModuleProjectMigration();
- }
-
- private void insertComponent(long id, String uuid, @Nullable String rootUuid, String projectUuid, String qualifier, String name) {
- db.executeInsert(
- "projects",
- "ID", valueOf(id),
- "UUID", uuid,
- "ROOT_UUID", rootUuid,
- "PROJECT_UUID", projectUuid,
- "SCOPE", Scopes.PROJECT,
- "QUALIFIER", qualifier,
- "NAME", name);
- }
-
- private void insertProperty(long id, long componentId, String key, String value) {
- db.executeInsert(
- "properties",
- "ID", valueOf(id),
- "RESOURCE_ID", componentId,
- "PROP_KEY", key,
- "TEXT_VALUE", value,
- "IS_EMPTY", false);
- }
-
- private void setupMultiModuleProject() {
- String projectUuid = uuidFactory.create();
- String moduleUuid = uuidFactory.create();
- String subModule1Uuid = uuidFactory.create();
- String subModule2Uuid = uuidFactory.create();
- insertComponent(1, projectUuid, null, projectUuid, Qualifiers.PROJECT, "Multi-module project");
- insertComponent(2, moduleUuid, projectUuid, projectUuid, Qualifiers.MODULE, "Module");
- insertComponent(3, subModule1Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule 1");
- insertComponent(4, subModule2Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule 2");
- insertProperty(1, 1, "sonar.coverage.exclusions", "Proj1.java");
- insertProperty(2, 1, "sonar.cpd.exclusions", "Proj2.java");
- insertProperty(3, 2, "sonar.coverage.exclusions", "ModuleA.java");
- insertProperty(4, 2, "sonar.cpd.exclusions", "ModuleB.java");
- insertProperty(5, 3, "sonar.coverage.exclusions", "Module1A.java");
- insertProperty(6, 3, "sonar.cpd.exclusions", "Moddule1B.java");
- insertProperty(7, 4, "sonar.coverage.exclusions", "Module2A.java");
- insertProperty(8, 4, "sonar.cpd.exclusions", "Module2B.java");
- }
-
- private void verifyMultiModuleProjectMigration() {
- final String expectedResult = "# previous settings for sub-project Multi-module project::Module\n" +
- "sonar.coverage.exclusions=ModuleA.java\n" +
- "sonar.cpd.exclusions=ModuleB.java\n" +
- "\n" +
- "# previous settings for sub-project Multi-module project::Submodule 1\n" +
- "sonar.coverage.exclusions=Module1A.java\n" +
- "sonar.cpd.exclusions=Moddule1B.java\n" +
- "\n" +
- "# previous settings for sub-project Multi-module project::Submodule 2\n" +
- "sonar.coverage.exclusions=Module2A.java\n" +
- "sonar.cpd.exclusions=Module2B.java\n";
-
- List<Map<String, Object>> properties = db.select("select ID, TEXT_VALUE, CLOB_VALUE " +
- "from properties " +
- "where PROP_KEY='sonar.subprojects.settings.removed' and RESOURCE_ID = 1");
-
- assertThat(properties).hasSize(1);
- Map<String, Object> project1Property = properties.get(0);
- assertThat(project1Property.get("TEXT_VALUE")).isNull();
- assertThat(project1Property.get("CLOB_VALUE")).isEqualTo(expectedResult);
- }
-
- private void setupSecondMultiModuleProject() {
- String project3Uuid = uuidFactory.create();
- String singleModuleUuid = uuidFactory.create();
- insertComponent(6, project3Uuid, null, project3Uuid, Qualifiers.PROJECT, "Another multi-module project");
- insertComponent(7, singleModuleUuid, project3Uuid, project3Uuid, Qualifiers.MODULE, "Module X");
- insertProperty(11, 6, "sonar.coverage.exclusions", "InRoot.java");
- insertProperty(12, 7, "sonar.coverage.exclusions", "InModule.java");
- }
-
- private void verifySecondMultiModuleProjectMigration() {
- final String expectedResult = "# previous settings for sub-project Another multi-module project::Module X\n" +
- "sonar.coverage.exclusions=InModule.java\n";
-
- List<Map<String, Object>> properties = db.select("select ID, TEXT_VALUE, CLOB_VALUE " +
- "from properties " +
- "where PROP_KEY='sonar.subprojects.settings.removed' and RESOURCE_ID = 6");
-
- assertThat(properties).hasSize(1);
- Map<String, Object> project2Property = properties.get(0);
- assertThat(project2Property.get("TEXT_VALUE")).isNull();
- assertThat(project2Property.get("CLOB_VALUE")).isEqualTo(expectedResult);
- }
-}
@Test
public void verify_migration_count() {
- verifyMigrationCount(underTest, 4);
+ verifyMigrationCount(underTest, 5);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 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.sonar.server.platform.db.migration.version.v76;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.internal.TestSystem2;
+import org.sonar.core.util.SequenceUuidFactory;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.CoreDbTester;
+
+import static java.lang.String.valueOf;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.platform.db.migration.version.v76.MigrateModuleProperties.NEW_PROPERTY_NAME;
+
+public class MigrateModulePropertiesTest {
+ private static final long NOW = 50_000_000_000L;
+
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(MigrateModulePropertiesTest.class, "schema.sql");
+ private System2 system2 = new TestSystem2().setNow(NOW);
+ private UuidFactory uuidFactory = new SequenceUuidFactory();
+ private MigrateModuleProperties underTest = new MigrateModuleProperties(db.database(), system2);
+
+ @Test
+ public void multi_module_project_migration() throws SQLException {
+ setupMultiModuleProject();
+
+ underTest.execute();
+
+ verifyMultiModuleProjectMigration();
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ setupMultiModuleProject();
+
+ underTest.execute();
+ underTest.execute();
+
+ verifyMultiModuleProjectMigration();
+ List<Map<String, Object>> remainingProperties = db.select("select ID from properties");
+ assertThat(remainingProperties).hasSize(3);
+ }
+
+ @Test
+ public void single_module_project_migration() throws SQLException {
+ String project2Uuid = uuidFactory.create();
+ insertComponent(5, project2Uuid, null, project2Uuid, Qualifiers.PROJECT, "Single module project");
+ insertProperty(9, 5, "sonar.coverage.exclusions", "SingleModuleA.java");
+ insertProperty(10, 5, "sonar.cp.exclusions", "SingleModuleB.java");
+
+ underTest.execute();
+
+ List<Map<String, Object>> properties = db.select(String.format("select ID, TEXT_VALUE, CLOB_VALUE " +
+ "from properties " +
+ "where PROP_KEY='%s' and RESOURCE_ID = 5", NEW_PROPERTY_NAME));
+ assertThat(properties).hasSize(0);
+ List<Map<String, Object>> remainingProperties = db.select("select ID from properties");
+ assertThat(remainingProperties).hasSize(2);
+ }
+
+ @Test
+ public void properties_do_not_leak_between_projects() throws SQLException {
+ setupMultiModuleProject();
+ setupSecondMultiModuleProject();
+
+ underTest.execute();
+
+ verifyMultiModuleProjectMigration();
+ verifySecondMultiModuleProjectMigration();
+ }
+
+ private void insertComponent(long id, String uuid, @Nullable String rootUuid, String projectUuid, String qualifier, String name) {
+ db.executeInsert(
+ "projects",
+ "ID", valueOf(id),
+ "UUID", uuid,
+ "ROOT_UUID", rootUuid,
+ "PROJECT_UUID", projectUuid,
+ "SCOPE", Scopes.PROJECT,
+ "QUALIFIER", qualifier,
+ "NAME", name);
+ }
+
+ private void insertProperty(long id, long componentId, String key, String value) {
+ db.executeInsert(
+ "properties",
+ "ID", valueOf(id),
+ "RESOURCE_ID", componentId,
+ "PROP_KEY", key,
+ "TEXT_VALUE", value,
+ "IS_EMPTY", false);
+ }
+
+ private void setupMultiModuleProject() {
+ String projectUuid = uuidFactory.create();
+ String moduleUuid = uuidFactory.create();
+ String subModule1Uuid = uuidFactory.create();
+ String subModule2Uuid = uuidFactory.create();
+ insertComponent(1, projectUuid, null, projectUuid, Qualifiers.PROJECT, "Multi-module project");
+ insertComponent(2, moduleUuid, projectUuid, projectUuid, Qualifiers.MODULE, "Module");
+ insertComponent(3, subModule1Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule 1");
+ insertComponent(4, subModule2Uuid, moduleUuid, projectUuid, Qualifiers.MODULE, "Submodule 2");
+ insertProperty(1, 1, "sonar.coverage.exclusions", "Proj1.java");
+ insertProperty(2, 1, "sonar.cpd.exclusions", "Proj2.java");
+ insertProperty(3, 2, "sonar.coverage.exclusions", "ModuleA.java");
+ insertProperty(4, 2, "sonar.cpd.exclusions", "ModuleB.java");
+ insertProperty(5, 3, "sonar.coverage.exclusions", "Module1A.java");
+ insertProperty(6, 3, "sonar.cpd.exclusions", "Moddule1B.java");
+ insertProperty(7, 4, "sonar.coverage.exclusions", "Module2A.java");
+ insertProperty(8, 4, "sonar.cpd.exclusions", "Module2B.java");
+ }
+
+ private void verifyMultiModuleProjectMigration() {
+ final String expectedResult = "# previous settings for sub-project Multi-module project::Module\n" +
+ "sonar.coverage.exclusions=ModuleA.java\n" +
+ "sonar.cpd.exclusions=ModuleB.java\n" +
+ "\n" +
+ "# previous settings for sub-project Multi-module project::Submodule 1\n" +
+ "sonar.coverage.exclusions=Module1A.java\n" +
+ "sonar.cpd.exclusions=Moddule1B.java\n" +
+ "\n" +
+ "# previous settings for sub-project Multi-module project::Submodule 2\n" +
+ "sonar.coverage.exclusions=Module2A.java\n" +
+ "sonar.cpd.exclusions=Module2B.java\n";
+
+ List<Map<String, Object>> properties = db
+ .select(String.format("select ID, TEXT_VALUE, CLOB_VALUE from properties where PROP_KEY='%s' and RESOURCE_ID = 1",
+ NEW_PROPERTY_NAME));
+
+ assertThat(properties).hasSize(1);
+ Map<String, Object> project1Property = properties.get(0);
+ assertThat(project1Property.get("TEXT_VALUE")).isNull();
+ assertThat(project1Property.get("CLOB_VALUE")).isEqualTo(expectedResult);
+ }
+
+ private void setupSecondMultiModuleProject() {
+ String project3Uuid = uuidFactory.create();
+ String singleModuleUuid = uuidFactory.create();
+ insertComponent(6, project3Uuid, null, project3Uuid, Qualifiers.PROJECT, "Another multi-module project");
+ insertComponent(7, singleModuleUuid, project3Uuid, project3Uuid, Qualifiers.MODULE, "Module X");
+ insertProperty(11, 6, "sonar.coverage.exclusions", "InRoot.java");
+ insertProperty(12, 7, "sonar.coverage.exclusions", "InModule.java");
+ }
+
+ private void verifySecondMultiModuleProjectMigration() {
+ final String expectedResult = "# previous settings for sub-project Another multi-module project::Module X\n" +
+ "sonar.coverage.exclusions=InModule.java\n";
+
+ List<Map<String, Object>> properties = db.select(String.format("select ID, TEXT_VALUE, CLOB_VALUE " +
+ "from properties " +
+ "where PROP_KEY='%s' and RESOURCE_ID = 6", NEW_PROPERTY_NAME));
+
+ assertThat(properties).hasSize(1);
+ Map<String, Object> project2Property = properties.get(0);
+ assertThat(project2Property.get("TEXT_VALUE")).isNull();
+ assertThat(project2Property.get("CLOB_VALUE")).isEqualTo(expectedResult);
+ }
+}
+++ /dev/null
-CREATE TABLE "PROJECTS" (
- "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
- "KEE" VARCHAR(400),
- "UUID" VARCHAR(50) NOT NULL,
- "ROOT_UUID" VARCHAR(50),
- "PROJECT_UUID" VARCHAR(50) NOT NULL,
- "MODULE_UUID" VARCHAR(50),
- "MODULE_UUID_PATH" VARCHAR(1500),
- "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
- "NAME" VARCHAR(2000),
- "TAGS" VARCHAR(500),
- "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
- "SCOPE" VARCHAR(3),
- "QUALIFIER" VARCHAR(10)
-);
-CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
-CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
-CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
-CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
-CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
-CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
-
-CREATE TABLE "PROPERTIES" (
- "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
- "PROP_KEY" VARCHAR(512) NOT NULL,
- "RESOURCE_ID" INTEGER,
- "USER_ID" INTEGER,
- "TEXT_VALUE" VARCHAR(4000),
- "CLOB_VALUE" CLOB(2147483647),
- "CREATED_AT" BIGINT,
- "IS_EMPTY" BOOLEAN NOT NULL,
-);
-CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
-
-
--- /dev/null
+CREATE TABLE "PROJECTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "KEE" VARCHAR(400),
+ "UUID" VARCHAR(50) NOT NULL,
+ "ROOT_UUID" VARCHAR(50),
+ "PROJECT_UUID" VARCHAR(50) NOT NULL,
+ "MODULE_UUID" VARCHAR(50),
+ "MODULE_UUID_PATH" VARCHAR(1500),
+ "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
+ "NAME" VARCHAR(2000),
+ "TAGS" VARCHAR(500),
+ "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10)
+);
+CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
+CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
+CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
+CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
+
+CREATE TABLE "PROPERTIES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "PROP_KEY" VARCHAR(512) NOT NULL,
+ "RESOURCE_ID" INTEGER,
+ "USER_ID" INTEGER,
+ "TEXT_VALUE" VARCHAR(4000),
+ "CLOB_VALUE" CLOB(2147483647),
+ "CREATED_AT" BIGINT,
+ "IS_EMPTY" BOOLEAN NOT NULL,
+);
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
+
+
*/
String CATEGORY_EXTERNAL_ISSUES = "externalIssues";
-
/**
* @since 2.11
*/
/**
* @since 3.6
*/
- //TODO remove?
+ // TODO remove?
String PROFILING_LOG_PROPERTY = "sonar.showProfiling";
/**
* @since 5.1
*/
String DEFAULT_ISSUE_ASSIGNEE = "sonar.issues.defaultAssigneeLogin";
+
+ /**
+ * @since 7.6
+ */
+ String MODULE_LEVEL_ARCHIVED_SETTINGS = "sonar.modules.archivedSettings";
}
package org.sonar.scanner.scan;
import java.util.Map;
+import org.apache.commons.lang.StringUtils;
import org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.notifications.AnalysisWarnings;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.scanner.bootstrap.ScannerProperties;
import org.sonar.scanner.repository.settings.SettingsLoader;
public class ProjectServerSettingsProvider extends ProviderAdapter {
- private ProjectServerSettings singleton;
+ private static final Logger LOG = Loggers.get(ProjectConfigurationProvider.class);
- public ProjectServerSettings provide(SettingsLoader loader, ScannerProperties scannerProperties) {
+ private static final String MODULE_LEVEL_ARCHIVED_SETTINGS_WARNING = "Please migrate all the properties listed in " +
+ "`sonar.module.removedProperties` setting to appriopriate project level setting.";
+
+ private ProjectServerSettings singleton = null;
+
+ public ProjectServerSettings provide(SettingsLoader loader, ScannerProperties scannerProperties, AnalysisWarnings analysisWarnings) {
if (singleton == null) {
Map<String, String> serverSideSettings = loader.load(scannerProperties.getKeyWithBranch());
+ if (StringUtils.isNotBlank(serverSideSettings.get(CoreProperties.MODULE_LEVEL_ARCHIVED_SETTINGS))) {
+ LOG.warn(MODULE_LEVEL_ARCHIVED_SETTINGS_WARNING);
+ analysisWarnings.addUnique(MODULE_LEVEL_ARCHIVED_SETTINGS_WARNING);
+ }
singleton = new ProjectServerSettings(serverSideSettings);
}
return singleton;