diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-12-02 15:54:24 +0100 |
---|---|---|
committer | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2014-12-02 16:25:49 +0100 |
commit | 6078d64d4cfb41032b4e17bec32905fa3d219ac3 (patch) | |
tree | 340bb34bee17ea6f090534175842d3ccf5a41067 /sonar-core | |
parent | b85022a92061e8f320ea605309fa99107351d506 (diff) | |
download | sonarqube-6078d64d4cfb41032b4e17bec32905fa3d219ac3.tar.gz sonarqube-6078d64d4cfb41032b4e17bec32905fa3d219ac3.zip |
SONAR-5804 delete file_sources when deleting a project or during the data cleaning step
Diffstat (limited to 'sonar-core')
14 files changed, 356 insertions, 131 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java index 51128905fa0..2e0f073571e 100644 --- a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java +++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java @@ -28,10 +28,12 @@ import org.sonar.api.config.Settings; import org.sonar.api.resources.Qualifiers; import org.sonar.api.utils.TimeUtils; import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner; +import org.sonar.core.purge.IdUuidPair; import org.sonar.core.purge.PurgeConfiguration; import org.sonar.core.purge.PurgeDao; import org.sonar.core.purge.PurgeProfiler; import org.sonar.core.resource.ResourceDao; +import org.sonar.core.resource.ResourceDto; import org.sonar.plugins.dbcleaner.api.PurgeTask; import static org.sonar.core.purge.PurgeConfiguration.newDefaultPurgeConfiguration; @@ -57,7 +59,8 @@ public class DefaultPurgeTask implements PurgeTask { @Override public DefaultPurgeTask delete(long resourceId) { - purgeDao.deleteResourceTree(resourceId); + ResourceDto project = resourceDao.getResource(resourceId); + purgeDao.deleteResourceTree(new IdUuidPair(project.getId(), project.getUuid())); return this; } diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java index 410afd92970..43d1f26cefc 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java @@ -24,11 +24,7 @@ import com.google.common.io.Closeables; import org.apache.ibatis.builder.xml.XMLMapperBuilder; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.mapping.Environment; -import org.apache.ibatis.session.Configuration; -import org.apache.ibatis.session.ExecutorType; -import org.apache.ibatis.session.SqlSession; -import org.apache.ibatis.session.SqlSessionFactory; -import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.apache.ibatis.session.*; import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; import org.apache.ibatis.type.JdbcType; import org.slf4j.LoggerFactory; @@ -45,14 +41,7 @@ import org.sonar.core.component.db.SnapshotMapper; import org.sonar.core.computation.db.AnalysisReportDto; import org.sonar.core.computation.db.AnalysisReportMapper; import org.sonar.core.config.Logback; -import org.sonar.core.dashboard.ActiveDashboardDto; -import org.sonar.core.dashboard.ActiveDashboardMapper; -import org.sonar.core.dashboard.DashboardDto; -import org.sonar.core.dashboard.DashboardMapper; -import org.sonar.core.dashboard.WidgetDto; -import org.sonar.core.dashboard.WidgetMapper; -import org.sonar.core.dashboard.WidgetPropertyDto; -import org.sonar.core.dashboard.WidgetPropertyMapper; +import org.sonar.core.dashboard.*; import org.sonar.core.dependency.DependencyDto; import org.sonar.core.dependency.DependencyMapper; import org.sonar.core.dependency.ResourceSnapshotDto; @@ -61,56 +50,23 @@ import org.sonar.core.duplication.DuplicationMapper; import org.sonar.core.duplication.DuplicationUnitDto; import org.sonar.core.graph.jdbc.GraphDto; import org.sonar.core.graph.jdbc.GraphDtoMapper; -import org.sonar.core.issue.db.ActionPlanDto; -import org.sonar.core.issue.db.ActionPlanMapper; -import org.sonar.core.issue.db.ActionPlanStatsDto; -import org.sonar.core.issue.db.ActionPlanStatsMapper; -import org.sonar.core.issue.db.IssueChangeDto; -import org.sonar.core.issue.db.IssueChangeMapper; -import org.sonar.core.issue.db.IssueDto; -import org.sonar.core.issue.db.IssueFilterDto; -import org.sonar.core.issue.db.IssueFilterFavouriteDto; -import org.sonar.core.issue.db.IssueFilterFavouriteMapper; -import org.sonar.core.issue.db.IssueFilterMapper; -import org.sonar.core.issue.db.IssueMapper; -import org.sonar.core.measure.db.MeasureDto; -import org.sonar.core.measure.db.MeasureFilterDto; -import org.sonar.core.measure.db.MeasureFilterMapper; -import org.sonar.core.measure.db.MeasureMapper; -import org.sonar.core.measure.db.MetricDto; -import org.sonar.core.measure.db.MetricMapper; +import org.sonar.core.issue.db.*; +import org.sonar.core.measure.db.*; import org.sonar.core.notification.db.NotificationQueueDto; import org.sonar.core.notification.db.NotificationQueueMapper; -import org.sonar.core.permission.GroupWithPermissionDto; -import org.sonar.core.permission.PermissionTemplateDto; -import org.sonar.core.permission.PermissionTemplateGroupDto; -import org.sonar.core.permission.PermissionTemplateMapper; -import org.sonar.core.permission.PermissionTemplateUserDto; -import org.sonar.core.permission.UserWithPermissionDto; +import org.sonar.core.permission.*; import org.sonar.core.persistence.dialect.Dialect; import org.sonar.core.persistence.migration.v44.Migration44Mapper; import org.sonar.core.persistence.migration.v45.Migration45Mapper; import org.sonar.core.persistence.migration.v50.Migration50Mapper; import org.sonar.core.properties.PropertiesMapper; import org.sonar.core.properties.PropertyDto; +import org.sonar.core.purge.IdUuidPair; import org.sonar.core.purge.PurgeMapper; import org.sonar.core.purge.PurgeableSnapshotDto; -import org.sonar.core.qualitygate.db.ProjectQgateAssociationDto; -import org.sonar.core.qualitygate.db.ProjectQgateAssociationMapper; -import org.sonar.core.qualitygate.db.QualityGateConditionDto; -import org.sonar.core.qualitygate.db.QualityGateConditionMapper; -import org.sonar.core.qualitygate.db.QualityGateDto; -import org.sonar.core.qualitygate.db.QualityGateMapper; -import org.sonar.core.qualityprofile.db.ActiveRuleDto; -import org.sonar.core.qualityprofile.db.ActiveRuleMapper; -import org.sonar.core.qualityprofile.db.ActiveRuleParamDto; -import org.sonar.core.qualityprofile.db.QualityProfileDto; -import org.sonar.core.qualityprofile.db.QualityProfileMapper; -import org.sonar.core.resource.ResourceDto; -import org.sonar.core.resource.ResourceIndexDto; -import org.sonar.core.resource.ResourceIndexerMapper; -import org.sonar.core.resource.ResourceKeyUpdaterMapper; -import org.sonar.core.resource.ResourceMapper; +import org.sonar.core.qualitygate.db.*; +import org.sonar.core.qualityprofile.db.*; +import org.sonar.core.resource.*; import org.sonar.core.rule.RuleDto; import org.sonar.core.rule.RuleMapper; import org.sonar.core.rule.RuleParamDto; @@ -123,17 +79,7 @@ import org.sonar.core.technicaldebt.db.CharacteristicMapper; import org.sonar.core.technicaldebt.db.RequirementMigrationDto; import org.sonar.core.template.LoadedTemplateDto; import org.sonar.core.template.LoadedTemplateMapper; -import org.sonar.core.user.AuthorDto; -import org.sonar.core.user.AuthorMapper; -import org.sonar.core.user.GroupDto; -import org.sonar.core.user.GroupMapper; -import org.sonar.core.user.GroupMembershipDto; -import org.sonar.core.user.GroupMembershipMapper; -import org.sonar.core.user.GroupRoleDto; -import org.sonar.core.user.RoleMapper; -import org.sonar.core.user.UserDto; -import org.sonar.core.user.UserMapper; -import org.sonar.core.user.UserRoleDto; +import org.sonar.core.user.*; import java.io.InputStream; @@ -152,6 +98,21 @@ public class MyBatis implements BatchComponent, ServerComponent { this.queue = queue; } + public static void closeQuietly(SqlSession session) { + if (session != null) { + try { + session.close(); + } catch (Exception e) { + LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e); + // do not re-throw the exception + } + } + } + + private static JdbcTransactionFactory createTransactionFactory() { + return new JdbcTransactionFactory(); + } + public MyBatis start() { LogFactory.useSlf4jLogging(); @@ -218,6 +179,7 @@ public class MyBatis implements BatchComponent, ServerComponent { loadAlias(conf, "RequirementMigration", RequirementMigrationDto.class); loadAlias(conf, "Activity", ActivityDto.class); loadAlias(conf, "AnalysisReport", AnalysisReportDto.class); + loadAlias(conf, "IdUuidPair", IdUuidPair.class); // AuthorizationMapper has to be loaded before IssueMapper because this last one used it loadMapper(conf, "org.sonar.core.user.AuthorizationMapper"); @@ -279,17 +241,6 @@ public class MyBatis implements BatchComponent, ServerComponent { return new DbSession(queue, session); } - public static void closeQuietly(SqlSession session) { - if (session != null) { - try { - session.close(); - } catch (Exception e) { - LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e); - // do not re-throw the exception - } - } - } - private void loadMappers(Configuration mybatisConf, Class<?>... mapperClasses) { for (Class mapperClass : mapperClasses) { loadMapper(mybatisConf, mapperClass); @@ -325,8 +276,4 @@ public class MyBatis implements BatchComponent, ServerComponent { private void loadAlias(Configuration conf, String alias, Class dtoClass) { conf.getTypeAliasRegistry().registerAlias(alias, dtoClass); } - - private static JdbcTransactionFactory createTransactionFactory() { - return new JdbcTransactionFactory(); - } } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPair.java b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPair.java new file mode 100644 index 00000000000..f19ef88611f --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPair.java @@ -0,0 +1,50 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.purge; + +public class IdUuidPair { + private Long id; + private String uuid; + + public IdUuidPair() { + } + + public IdUuidPair(long id, String uuid) { + this.id = id; + this.uuid = uuid; + } + + public Long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPairs.java b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPairs.java new file mode 100644 index 00000000000..1ad2939d073 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPairs.java @@ -0,0 +1,50 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.purge; + +import com.google.common.collect.Lists; + +import java.util.List; + +public class IdUuidPairs { + private IdUuidPairs() { + } + + public static List<Long> ids(List<IdUuidPair> pairs) { + List<Long> ids = Lists.newArrayList(); + + for (IdUuidPair idUuidPair : pairs) { + ids.add(idUuidPair.getId()); + } + + return ids; + } + + public static List<String> uuids(List<IdUuidPair> idUuidPairList) { + List<String> uuids = Lists.newArrayList(); + + for (IdUuidPair idUuidPair : idUuidPairList) { + uuids.add(idUuidPair.getUuid()); + } + + return uuids; + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java index 3a4e0ac18e6..a68c3fa58ce 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java @@ -279,4 +279,10 @@ class PurgeCommands { profiler.stop(); } + public void deleteFileSources(String rootUuid) { + profiler.start("deleteFileSources (file_sources)"); + purgeMapper.deleteFileSourcesByProjectUuid(rootUuid); + session.commit(); + profiler.stop(); + } } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java index a7bde27f95e..c43f3df6d93 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java @@ -41,11 +41,11 @@ import java.util.List; * @since 2.14 */ public class PurgeDao { + private static final Logger LOG = LoggerFactory.getLogger(PurgeDao.class); private final MyBatis mybatis; private final ResourceDao resourceDao; - private static final Logger LOG = LoggerFactory.getLogger(PurgeDao.class); - private PurgeProfiler profiler; private final System2 system2; + private PurgeProfiler profiler; public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, PurgeProfiler profiler, System2 system2) { this.mybatis = mybatis; @@ -134,9 +134,9 @@ public class PurgeDao { session.select("org.sonar.core.purge.PurgeMapper.selectResourceIdsToDisable", project.getId(), new ResultHandler() { @Override public void handleResult(ResultContext resultContext) { - Long resourceId = (Long) resultContext.getResultObject(); - if (resourceId != null) { - disableResource(resourceId, purgeMapper); + IdUuidPair resourceIdUuid = (IdUuidPair) resultContext.getResultObject(); + if (resourceIdUuid.getId() != null) { + disableResource(resourceIdUuid, purgeMapper); } } }); @@ -162,17 +162,22 @@ public class PurgeDao { return result; } - public PurgeDao deleteResourceTree(long rootProjectId) { + public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid) { final DbSession session = mybatis.openSession(true); final PurgeMapper mapper = session.getMapper(PurgeMapper.class); try { - deleteProject(rootProjectId, mapper, new PurgeCommands(session, profiler)); + deleteProject(rootIdUuid.getId(), mapper, new PurgeCommands(session, profiler)); + deleteFileSources(rootIdUuid.getUuid(), new PurgeCommands(session, profiler)); return this; } finally { MyBatis.closeQuietly(session); } } + private void deleteFileSources(String rootUuid, PurgeCommands commands) { + commands.deleteFileSources(rootUuid); + } + private void deleteProject(long rootProjectId, PurgeMapper mapper, PurgeCommands commands) { List<Long> childrenIds = mapper.selectProjectIdsByRootId(rootProjectId); for (Long childId : childrenIds) { @@ -183,9 +188,11 @@ public class PurgeDao { commands.deleteResources(resourceIds); } - private void disableResource(long resourceId, PurgeMapper mapper) { + private void disableResource(IdUuidPair resourceIdUuid, PurgeMapper mapper) { + long resourceId = resourceIdUuid.getId(); mapper.deleteResourceIndex(Arrays.asList(resourceId)); mapper.setSnapshotIsLastToFalse(resourceId); + mapper.deleteFileSourcesByUuid(resourceIdUuid.getUuid()); mapper.disableResource(resourceId); mapper.resolveResourceIssuesNotAlreadyResolved(resourceId, new Date(system2.now())); } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java index b3c26d95a07..f498b122496 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java @@ -103,4 +103,8 @@ public interface PurgeMapper { void deleteOldClosedIssueChanges(@Param("rootProjectId") long rootProjectId, @Nullable @Param("toDate") Date toDate); void deleteOldClosedIssues(@Param("rootProjectId") long rootProjectId, @Nullable @Param("toDate") Date toDate); + + void deleteFileSourcesByProjectUuid(String rootProjectUuid); + + void deleteFileSourcesByUuid(String fileUuid); } diff --git a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml index a7a82c75d0a..c0173090485 100644 --- a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml @@ -47,7 +47,7 @@ </if> </where> </select> - + <select id="selectSnapshotIdsByResource" parameterType="map" resultType="long"> select s.id from snapshots s <where> @@ -72,8 +72,8 @@ not exists(select e.id from events e where e.snapshot_id=s.id) </select> - <select id="selectResourceIdsToDisable" resultType="long" parameterType="long"> - select p.id from projects p + <select id="selectResourceIdsToDisable" resultType="IdUuidPair" parameterType="long"> + select p.id, p.uuid from projects p where (p.id=#{id} or p.root_id=#{id}) and p.enabled=${_true} and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id) </select> @@ -93,28 +93,28 @@ <delete id="deleteSnapshotMeasures" parameterType="map"> delete from project_measures where snapshot_id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> <delete id="deleteSnapshotSource" parameterType="map"> delete from snapshot_sources where snapshot_id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> <delete id="deleteSnapshotGraphs" parameterType="map"> delete from graphs where snapshot_id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> <delete id="deleteSnapshotDependenciesFromSnapshotId" parameterType="map"> delete from dependencies where from_snapshot_id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> @@ -135,36 +135,37 @@ <delete id="deleteSnapshotDuplications" parameterType="map"> delete from duplications_index where snapshot_id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> <delete id="deleteSnapshotEvents" parameterType="map"> delete from events where snapshot_id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> <delete id="deleteSnapshot" parameterType="map"> delete from snapshots where id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> <delete id="deleteSnapshotWastedMeasures" parameterType="map"> delete from project_measures <where> - snapshot_id in - <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> + snapshot_id in + <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> #{snapshotId} - </foreach> - and (rule_id is not null or person_id is not null - <if test="mids.size()>0"> - or metric_id in - <foreach item="mid" index="index" collection="mids" open="(" separator="," close=")">#{mid}</foreach> - </if>) + </foreach> + and (rule_id is not null or person_id is not null + <if test="mids.size()>0"> + or metric_id in + <foreach item="mid" index="index" collection="mids" open="(" separator="," close=")">#{mid}</foreach> + </if> + ) </where> </delete> @@ -177,7 +178,8 @@ </update> <update id="resolveResourceIssuesNotAlreadyResolved" parameterType="map"> - UPDATE issues SET status='CLOSED',resolution='REMOVED',updated_at=#{date},issue_close_date=#{date}, issue_update_date=#{date} + UPDATE issues SET status='CLOSED',resolution='REMOVED',updated_at=#{date},issue_close_date=#{date}, + issue_update_date=#{date} WHERE component_id=#{resourceId} AND resolution IS NULL </update> @@ -272,16 +274,16 @@ <delete id="deleteSnapshotData" parameterType="map"> delete from snapshot_data where snapshot_id in <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=","> - #{snapshotId} + #{snapshotId} </foreach> </delete> <delete id="deleteResourceIssueChanges" parameterType="map"> delete from issue_changes ic where exists (select * from issues i where i.kee=ic.issue_key and i.component_id in - <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> - #{resourceId} - </foreach> + <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> + #{resourceId} + </foreach> ) </delete> @@ -310,6 +312,13 @@ </foreach> </delete> + <delete id="deleteFileSourcesByProjectUuid"> + delete from file_sources where project_uuid=#{rootProjectUuid} + </delete> + + <delete id="deleteFileSourcesByUuid"> + delete from file_sources where file_uuid=#{fileUuid} + </delete> <delete id="deleteOldClosedIssueChanges" parameterType="map"> delete from issue_changes ic diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java index 5871fb71761..c03d4ada988 100644 --- a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java +++ b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java @@ -30,6 +30,7 @@ import org.sonar.api.config.Settings; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner; +import org.sonar.core.purge.IdUuidPair; import org.sonar.core.purge.PurgeConfiguration; import org.sonar.core.purge.PurgeDao; import org.sonar.core.purge.PurgeProfiler; @@ -139,8 +140,10 @@ public class DefaultPurgeTaskTest { @Test public void call_dao_delete_when_deleting() throws Exception { + when(resourceDao.getResource(123L)).thenReturn(new ResourceDto().setId(123L).setUuid("A")); + sut.delete(123L); - verify(purgeDao, times(1)).deleteResourceTree(123L); + verify(purgeDao, times(1)).deleteResourceTree(any(IdUuidPair.class)); } } diff --git a/sonar-core/src/test/java/org/sonar/core/purge/IdUuidPairsTest.java b/sonar-core/src/test/java/org/sonar/core/purge/IdUuidPairsTest.java new file mode 100644 index 00000000000..5fc436735b2 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/purge/IdUuidPairsTest.java @@ -0,0 +1,48 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.purge; + +import com.google.common.collect.Lists; +import org.junit.Test; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; + +public class IdUuidPairsTest { + @Test + public void extract_ids() throws Exception { + List<IdUuidPair> idUuidPairList = Lists.newArrayList(new IdUuidPair(1L, "ABCD"), new IdUuidPair(2L, "EFGH")); + + List<Long> ids = IdUuidPairs.ids(idUuidPairList); + + assertThat(ids).containsOnly(1L, 2L); + } + + @Test + public void extract_uuids() { + List<IdUuidPair> idUuidPairList = Lists.newArrayList(new IdUuidPair(1L, "ABCD"), new IdUuidPair(2L, "EFGH")); + + List<String> uuids = IdUuidPairs.uuids(idUuidPairList); + + assertThat(uuids).containsOnly("ABCD", "EFGH"); + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java index fd598dfd8bd..e0bc253992d 100644 --- a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java @@ -39,6 +39,15 @@ public class PurgeDaoTest extends AbstractDaoTestCase { PurgeDao dao; + private static PurgeableSnapshotDto getById(List<PurgeableSnapshotDto> snapshots, long id) { + for (PurgeableSnapshotDto snapshot : snapshots) { + if (snapshot.getSnapshotId() == id) { + return snapshot; + } + } + return null; + } + @Before public void createDao() { system2 = mock(System2.class); @@ -55,13 +64,20 @@ public class PurgeDaoTest extends AbstractDaoTestCase { } @Test - public void shouldPurgeProject() { + public void should_purge_project() { setupData("shouldPurgeProject"); dao.purge(new PurgeConfiguration(1L, new String[0], 30)); checkTables("shouldPurgeProject", "projects", "snapshots"); } @Test + public void delete_file_sources_of_disabled_resources() { + setupData("delete_file_sources_of_disabled_resources"); + dao.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); + checkTables("delete_file_sources_of_disabled_resources", "file_sources"); + } + + @Test public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() { setupData("shouldDeleteHistoricalDataOfDirectoriesAndFiles"); dao.purge(new PurgeConfiguration(1L, new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30)); @@ -96,20 +112,11 @@ public class PurgeDaoTest extends AbstractDaoTestCase { assertThat(getById(snapshots, 5L).hasEvents()).isTrue(); } - private static PurgeableSnapshotDto getById(List<PurgeableSnapshotDto> snapshots, long id) { - for (PurgeableSnapshotDto snapshot : snapshots) { - if (snapshot.getSnapshotId() == id) { - return snapshot; - } - } - return null; - } - @Test - public void shouldDeleteProject() { + public void should_delete_project_and_associated_data() { setupData("shouldDeleteProject"); - dao.deleteResourceTree(1L); - assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes"); + dao.deleteResourceTree(new IdUuidPair(1L, "A")); + assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes", "file_sources"); } @Test diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml new file mode 100644 index 00000000000..c6eb7974211 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml @@ -0,0 +1,5 @@ +<dataset> + + <file_sources id="2" project_uuid="ABCD" file_uuid="KLMN" data="[null]" line_hashes="[null]" data_hash="321654988" + created_at="123456789" updated_at="123456789"/> +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml new file mode 100644 index 00000000000..c461e9d5a40 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml @@ -0,0 +1,79 @@ +<dataset> + + <!-- the project --> + <projects id="1" enabled="[true]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" + module_uuid_path="[null]" created_at="[null]" + long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the directory --> + <projects id="2" enabled="[true]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path="[null]" created_at="[null]" + long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <!-- the files --> + <projects id="3" enabled="[true]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path="ABCD" created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + <projects id="4" enabled="[true]" root_id="1" uuid="KLMN" project_uuid="ABCD" module_uuid="ABCD" + module_uuid_path="ABCD" created_at="[null]" + long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/DeletedFile.java" + name="my/dir/DeletedFile.java" + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" + deprecated_kee="[null]" authorization_updated_at="[null]"/> + + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/> + + <snapshots id="2" + project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/> + + <snapshots id="3" + project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/> + + <!-- isLast is true, don't want to delete associated source lines --> + <snapshots id="4" + project_id="4" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" + build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/> + + <file_sources id="1" project_uuid="ABCD" file_uuid="GHIJ" data="[null]" line_hashes="[null]" data_hash="321654987" + created_at="123456789" updated_at="123456789"/> + <file_sources id="2" project_uuid="ABCD" file_uuid="KLMN" data="[null]" line_hashes="[null]" data_hash="321654988" + created_at="123456789" updated_at="123456789"/> +</dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml index 34b5391a7c2..91e1c3c1c58 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml @@ -4,7 +4,8 @@ <projects id="1" enabled="[true]" root_id="[null]" uuid="A" project_uuid="A" module_uuid="[null]" module_uuid_path="[null]" long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" - description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="[false]" purge_status="[null]" @@ -18,7 +19,7 @@ version="[null]" path="[null]"/> <action_plans id="1" kee="ABCD" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]" - user_login="igor" status="[null]" created_at="[null]" updated_at="[null]" /> + user_login="igor" status="[null]" created_at="[null]" updated_at="[null]"/> <issues id="1" kee="ABCDE" component_id="1" status="CLOSED" resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" @@ -44,13 +45,15 @@ issue_close_date="2013-04-16" /> - <issue_changes id="1" kee="[null]" issue_key="ABCDF" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/> + <issue_changes id="1" kee="[null]" issue_key="ABCDF" created_at="[null]" updated_at="[null]" user_login="admin" + change_type="comment" change_data="abc"/> <!-- modules --> <projects id="2" enabled="[true]" root_id="1" uuid="B" project_uuid="A" module_uuid="A" module_uuid_path="A" long_name="[null]" scope="PRJ" qualifier="BRC" kee="module1" name="module1" - description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" status="P" islast="[false]" purge_status="[null]" @@ -67,7 +70,8 @@ <projects id="3" enabled="[false]" root_id="1" uuid="C" project_uuid="A" module_uuid="A" module_uuid_path="A" long_name="[null]" scope="PRJ" qualifier="BRC" kee="module2" name="module2" - description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> <snapshots id="3" project_id="3" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" status="P" islast="[true]" purge_status="[null]" @@ -84,7 +88,8 @@ <projects id="4" enabled="[false]" root_id="3" uuid="D" project_uuid="A" module_uuid="C" module_uuid_path="A.C" long_name="[null]" scope="FIL" qualifier="FIL" kee="module2:File.java" name="File" - description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> + description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" + authorization_updated_at="[null]"/> <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1" status="P" islast="[true]" purge_status="[null]" @@ -96,4 +101,6 @@ depth="[null]" scope="FIL" qualifier="FIL" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/> + <file_sources id="1" project_uuid="A" file_uuid="D" data="[null]" line_hashes="[null]" data_hash="321654987" + created_at="123456789" updated_at="123456789"/> </dataset> |