diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-04-09 14:00:05 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-04-09 14:00:24 +0200 |
commit | fef49730fdf2126edbd1f2414d50426f5e3b73b3 (patch) | |
tree | 0cd41f26e4f06510eab06f9487e547764467780e /sonar-core | |
parent | 5cfdd08e9a9155bcac3f4ae99d0bb28bfd458957 (diff) | |
download | sonarqube-fef49730fdf2126edbd1f2414d50426f5e3b73b3.tar.gz sonarqube-fef49730fdf2126edbd1f2414d50426f5e3b73b3.zip |
SONAR-5200 When a module has been removed, related issues are not closed during the purge
Diffstat (limited to 'sonar-core')
13 files changed, 167 insertions, 28 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java index f6a6dc41922..c09affd1af3 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java @@ -33,7 +33,7 @@ import java.util.List; */ public class DatabaseVersion implements BatchComponent, ServerComponent { - public static final int LAST_VERSION = 524; + public static final int LAST_VERSION = 525; public static enum Status { UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeConfiguration.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeConfiguration.java index ac8880c4678..d026ba60612 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeConfiguration.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeConfiguration.java @@ -21,8 +21,10 @@ package org.sonar.core.purge; import com.google.common.annotations.VisibleForTesting; import org.apache.commons.lang.time.DateUtils; +import org.sonar.api.utils.System2; import javax.annotation.CheckForNull; + import java.util.Date; public class PurgeConfiguration { @@ -30,11 +32,18 @@ public class PurgeConfiguration { private final long rootProjectId; private final String[] scopesWithoutHistoricalData; private final int maxAgeInDaysOfClosedIssues; + private final System2 system2; public PurgeConfiguration(long rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues) { + this(rootProjectId, scopesWithoutHistoricalData, maxAgeInDaysOfClosedIssues, System2.INSTANCE); + } + + @VisibleForTesting + PurgeConfiguration(long rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues, System2 system2) { this.rootProjectId = rootProjectId; this.scopesWithoutHistoricalData = scopesWithoutHistoricalData; this.maxAgeInDaysOfClosedIssues = maxAgeInDaysOfClosedIssues; + this.system2 = system2; } public long rootProjectId() { @@ -47,7 +56,7 @@ public class PurgeConfiguration { @CheckForNull public Date maxLiveDateOfClosedIssues() { - return maxLiveDateOfClosedIssues(new Date()); + return maxLiveDateOfClosedIssues(new Date(system2.now())); } @VisibleForTesting 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 73c95d818c4..5777908166b 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 @@ -19,7 +19,6 @@ */ package org.sonar.core.purge; -import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import org.apache.commons.lang.ArrayUtils; import org.apache.ibatis.session.ResultContext; @@ -83,34 +82,35 @@ public class PurgeDao { if (hasAbortedBuilds(project.getId(), commands)) { LOG.info("<- Delete aborted builds"); PurgeSnapshotQuery query = PurgeSnapshotQuery.create() - .setIslast(false) - .setStatus(new String[] {"U"}) - .setRootProjectId(project.getId()); + .setIslast(false) + .setStatus(new String[]{"U"}) + .setRootProjectId(project.getId()); commands.deleteSnapshots(query); } } private boolean hasAbortedBuilds(Long projectId, PurgeCommands commands) { PurgeSnapshotQuery query = PurgeSnapshotQuery.create() - .setIslast(false) - .setStatus(new String[] {"U"}) - .setResourceId(projectId); + .setIslast(false) + .setStatus(new String[]{"U"}) + .setResourceId(projectId); return !commands.selectSnapshotIds(query).isEmpty(); } private void purge(ResourceDto project, String[] scopesWithoutHistoricalData, PurgeCommands purgeCommands) { List<Long> projectSnapshotIds = purgeCommands.selectSnapshotIds( - PurgeSnapshotQuery.create() - .setResourceId(project.getId()) - .setIslast(false) - .setNotPurged(true)); + PurgeSnapshotQuery.create() + .setResourceId(project.getId()) + .setIslast(false) + .setNotPurged(true) + ); for (final Long projectSnapshotId : projectSnapshotIds) { LOG.info("<- Clean snapshot " + projectSnapshotId); if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) { PurgeSnapshotQuery query = PurgeSnapshotQuery.create() - .setIslast(false) - .setScopes(scopesWithoutHistoricalData) - .setRootSnapshotId(projectSnapshotId); + .setIslast(false) + .setScopes(scopesWithoutHistoricalData) + .setRootSnapshotId(projectSnapshotId); purgeCommands.deleteSnapshots(query); } @@ -170,11 +170,11 @@ public class PurgeDao { commands.deleteResources(resourceIds); } - @VisibleForTesting - void disableResource(long resourceId, PurgeMapper mapper) { + private void disableResource(long resourceId, PurgeMapper mapper) { mapper.deleteResourceIndex(Arrays.asList(resourceId)); mapper.setSnapshotIsLastToFalse(resourceId); mapper.disableResource(resourceId); + mapper.resolveResourceIssuesNotAlreadyResolved(resourceId); } public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) { 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 ba596bccef4..ff7d36d2d04 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 @@ -58,16 +58,14 @@ public interface PurgeMapper { List<Long> selectMetricIdsWithoutHistoricalData(); - List<Long> selectCharacteristicIdsToPurge(); - void deleteSnapshotWastedMeasures(@Param("snapshotIds") List<Long> snapshotIds, @Param("mids") List<Long> metricIds); - void deleteSnapshotMeasuresOnCharacteristics(@Param("snapshotIds") List<Long> snapshotIds, @Param("cids") List<Long> characteristicIds); - void updatePurgeStatusToOne(long snapshotId); void disableResource(long resourceId); + void resolveResourceIssuesNotAlreadyResolved(long resourceId); + void deleteResourceIndex(@Param("resourceIds") List<Long> resourceIds); void deleteEvent(long eventId); diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql index c2427db7198..5c2d3bd0be5 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql @@ -223,6 +223,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('521'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('522'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('523'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('524'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('525'); INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null); ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; 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 a7de12225bb..cd4dc492f89 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 @@ -183,6 +183,10 @@ update projects set enabled=${_false} where id=#{id} </update> + <update id="resolveResourceIssuesNotAlreadyResolved" parameterType="long"> + update issues set status='CLOSED',resolution='REMOVED' where component_id=#{id} AND resolution IS NULL + </update> + <delete id="deleteResourceIndex" parameterType="map"> delete from resource_index where resource_id in <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=","> 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 a22b5106384..bec255186e0 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 @@ -24,6 +24,8 @@ import org.hamcrest.Description; import org.junit.Before; import org.junit.Test; import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.System2; import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.resource.ResourceDao; @@ -32,13 +34,20 @@ import java.util.List; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.internal.matchers.IsCollectionContaining.hasItem; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class PurgeDaoTest extends AbstractDaoTestCase { - private PurgeDao dao; + System2 system2; + + PurgeDao dao; @Before public void createDao() { + system2 = mock(System2.class); + when(system2.now()).thenReturn(DateUtils.parseDate("2014-04-09").getTime()); + dao = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis()), new PurgeProfiler()); } @@ -64,10 +73,10 @@ public class PurgeDaoTest extends AbstractDaoTestCase { } @Test - public void shouldDisableResourcesWithoutLastSnapshot() { - setupData("shouldDisableResourcesWithoutLastSnapshot"); - dao.purge(new PurgeConfiguration(1L, new String[0], 30)); - checkTables("shouldDisableResourcesWithoutLastSnapshot", "projects", "snapshots"); + public void disable_resources_without_last_snapshot() { + setupData("disable_resources_without_last_snapshot"); + dao.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); + checkTables("disable_resources_without_last_snapshot", "projects", "snapshots", "issues"); } @Test @@ -109,7 +118,6 @@ public class PurgeDaoTest extends AbstractDaoTestCase { checkTables("should_delete_all_closed_issues", "issues", "issue_changes"); } - static final class SnapshotMatcher extends BaseMatcher<PurgeableSnapshotDto> { long snapshotId; boolean isLast; diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml index 8857dc5ddca..9663761342b 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml @@ -3,6 +3,7 @@ What has been changed : * enabled=false on projects * purge_status=1 on snapshots +* resolve not already resolved issues on all components --> <dataset> @@ -53,4 +54,44 @@ What has been changed : 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]"/> + <!-- Open issue on file --> + <issues id="1" kee="ISSUE-1" + component_id="3" + root_component_id="1" + status="CLOSED" + issue_close_date="[null]" + resolution="REMOVED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> + + <!-- Open issue on directory --> + <issues id="2" kee="ISSUE-2" + component_id="2" + root_component_id="1" + status="CLOSED" + issue_close_date="[null]" + resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> + + <!-- Open issue on project --> + <issues id="3" kee="ISSUE-3" + component_id="1" + root_component_id="1" + status="CLOSED" + issue_close_date="[null]" + resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> + + <!-- Resolved issue on file -> not to be updated --> + <issues id="4" kee="ISSUE-4" + component_id="3" + root_component_id="1" + status="CLOSED" + issue_close_date="2014-04-08" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="2013-04-16"/> + </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml index fbda7d8a16d..e2cc5f459c9 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml @@ -46,4 +46,44 @@ 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]"/> + <!-- Open issue on file --> + <issues id="1" kee="ISSUE-1" + component_id="3" + root_component_id="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> + + <!-- Open issue on directory --> + <issues id="2" kee="ISSUE-2" + component_id="2" + root_component_id="1" + status="OPEN" + issue_close_date="[null]" + resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> + + <!-- Open issue on project --> + <issues id="3" kee="ISSUE-3" + component_id="1" + root_component_id="1" + status="CONFIRM" + issue_close_date="[null]" + resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/> + + <!-- Resolved issue on file -> not to be updated --> + <issues id="4" kee="ISSUE-4" + component_id="3" + root_component_id="1" + status="CLOSED" + issue_close_date="2014-04-08" + resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]" + message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]" + updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="2013-04-16"/> + </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml index 9eb87fb10c9..4d55fe35f48 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml @@ -9,6 +9,16 @@ long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + 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]"/> + <!-- old closed issues on file and project --> <!-- diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml index c725ed53d9c..c3c7aed53ed 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml @@ -4,6 +4,16 @@ long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + 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]"/> + <!-- old closed issues on file and project --> <issues id="1" kee="ISSUE-1" diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml index 775d6c17fe6..832ee1082a5 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml @@ -4,6 +4,15 @@ long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + 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]"/> <!-- old closed issues on file and project -> to be purged --> <!-- diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml index 083dd7af08f..47b40a5fdaf 100644 --- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml @@ -4,6 +4,15 @@ long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project" description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/> + <snapshots id="1" + project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + 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]"/> <!-- old closed issues on file and project -> to be purged --> <issues id="1" kee="ISSUE-1" |