]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2807 + SONAR-3219 : improve the DBCleaner plugin
authorSimon Brandhof <simon.brandhof@gmail.com>
Thu, 26 Jan 2012 16:16:49 +0000 (17:16 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Thu, 26 Jan 2012 16:18:06 +0000 (17:18 +0100)
* Delete all the wasted data. Some snapshots have been ignored
* Keep a single snapshot per day

42 files changed:
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DbCleanerPlugin.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PeriodCleaner.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/PeriodPurge.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Periods.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SQLRequests.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SnapshotFilter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJob.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/ProjectPurgePostJob.java
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/Utils.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilterTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilterTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilterTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/PeriodsTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent-result.xml [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent.xml [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest/shared.xml [deleted file]
sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeSnapshotQuery.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeableSnapshotDto.java [new file with mode: 0644]
sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldSelectPurgeableSnapshots.xml [new file with mode: 0644]

index 0eb4d380281b197fd2cbad6af9d093943e572643..a14b64b1f30c20de9898dbbeb7be46d24cfbaa2d 100644 (file)
@@ -24,8 +24,6 @@ import org.sonar.api.Property;
 import org.sonar.api.SonarPlugin;
 import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
 import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
-import org.sonar.plugins.dbcleaner.period.PeriodPurge;
-import org.sonar.plugins.dbcleaner.runner.DeprecatedPurgePostJob;
 import org.sonar.plugins.dbcleaner.runner.ProjectPurgePostJob;
 
 import java.util.Arrays;
@@ -55,10 +53,6 @@ public final class DbCleanerPlugin extends SonarPlugin {
 
   public List getExtensions() {
     return Arrays.asList(
-      DefaultPeriodCleaner.class,
-      PeriodPurge.class,
-
-      // post-jobs
-      ProjectPurgePostJob.class, DeprecatedPurgePostJob.class);
+      DefaultPeriodCleaner.class, ProjectPurgePostJob.class);
   }
 }
index 25cad3f72d54ee87a977cc3fc75c792cc391656f..fb3cc833f5864084c8ccd5ea4fc83b4199a5b079 100644 (file)
@@ -23,7 +23,6 @@ import org.sonar.api.BatchExtension;
 import org.sonar.api.resources.Project;
 
 /**
- * @since 2.14
  * @deprecated in 2.14
  */
 @Deprecated
index c12ae358fc412d394f321349588374dca39fce1e..ea50bac1d65c057dfd334753ce072431b05775b7 100644 (file)
  */
 package org.sonar.plugins.dbcleaner.period;
 
-import com.google.common.collect.Lists;
+import com.google.common.annotations.VisibleForTesting;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Project;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeSnapshotQuery;
+import org.sonar.core.purge.PurgeableSnapshotDto;
 import org.sonar.plugins.dbcleaner.api.PeriodCleaner;
-import org.sonar.plugins.dbcleaner.api.PurgeUtils;
 
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.GregorianCalendar;
 import java.util.List;
 
 public final class DefaultPeriodCleaner implements PeriodCleaner {
 
   private static final Logger LOG = LoggerFactory.getLogger(DefaultPeriodCleaner.class);
-  private final SQLRequests sql;
-  private DatabaseSession session;
+  private PurgeDao purgeDao;
+  private Settings settings;
 
-  public DefaultPeriodCleaner(DatabaseSession session) {
-    this.session = session;
-    this.sql = new SQLRequests(session);
+  public DefaultPeriodCleaner(PurgeDao purgeDao, Settings settings) {
+    this.purgeDao = purgeDao;
+    this.settings = settings;
   }
 
   public void purge(Project project, int projectSnapshotId) {
-    Periods periods = new Periods(project);
-    periods.log();
-    purge(project, projectSnapshotId, periods);
+    purge((long) project.getId());
   }
 
-  void purge(Project project, int projectSnapshotId, Periods periods) {
-    List<SnapshotFilter> filters = newFilters(periods);
-    List<Snapshot> snapshotHistory = selectProjectSnapshots(project, projectSnapshotId);
-    applyFilters(snapshotHistory, filters);
-    deleteSnapshotsAndAllRelatedData(snapshotHistory);
-  }
-
-  private List<Snapshot> selectProjectSnapshots(Project project, int snapshotId) {
-    List<Snapshot> snapshotHistory = Lists.newLinkedList(sql.getProjectSnapshotsOrderedByCreatedAt(snapshotId));
-    LOG.debug("The project '" + project.getName() + "' has " + snapshotHistory.size() + " snapshots.");
-    return snapshotHistory;
-  }
+  public void purge(long projectId) {
+    List<PurgeableSnapshotDto> history = selectProjectSnapshots(projectId);
 
-  private void deleteSnapshotsAndAllRelatedData(List<Snapshot> snapshotHistory) {
-    if (snapshotHistory.isEmpty()) {
-      LOG.info("There are no snapshots to purge");
-      return;
-    }
-
-    List<Integer> ids = Lists.newArrayList();
-    for (Snapshot snapshot : snapshotHistory) {
-      ids.addAll(sql.getChildIds(snapshot));
-    }
-    LOG.info("There are " + snapshotHistory.size() + " snapshots and " + (ids.size() - snapshotHistory.size())
-        + " children snapshots which are obsolete and are going to be deleted.");
-    if (LOG.isDebugEnabled()) {
-      DateFormat format = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
-      for (Snapshot snapshot : snapshotHistory) {
-        LOG.debug("Delete snapshot created at " + format.format(snapshot.getCreatedAt()));
-      }
+    Filters filters = new Filters(settings);
+    for (Filter filter : filters.getFilters()) {
+      filter.log();
+      delete(filter.filter(history));
     }
-    PurgeUtils.deleteSnapshotsData(session, ids);
   }
 
-  private void applyFilters(List<Snapshot> snapshotHistory, List<SnapshotFilter> filters) {
-    for (SnapshotFilter filter : filters) {
-      filter.filter(snapshotHistory);
+  private void delete(List<PurgeableSnapshotDto> snapshots) {
+    for (PurgeableSnapshotDto snapshot : snapshots) {
+      LOG.debug("<- Delete snapshot: " + DateUtils.formatDateTime(snapshot.getDate()) + " [" + snapshot.getSnapshotId() + "]");
+      purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()));
     }
   }
 
-  private List<SnapshotFilter> newFilters(Periods periods) {
-    List<SnapshotFilter> filters = Lists.newArrayList();
-    filters.add(new KeepLibrarySnapshotFilter());
-    filters.add(new KeepSnapshotsBetweenTwoDatesFilter(new Date(), periods.dateToStartKeepingOneSnapshotByWeek));
-    filters.add(new KeepOneSnapshotByPeriodBetweenTwoDatesFilter(GregorianCalendar.WEEK_OF_YEAR,
-        periods.dateToStartKeepingOneSnapshotByWeek,
-        periods.dateToStartKeepingOneSnapshotByMonth));
-    filters.add(new KeepOneSnapshotByPeriodBetweenTwoDatesFilter(GregorianCalendar.MONTH,
-        periods.dateToStartKeepingOneSnapshotByMonth,
-        periods.dateToStartDeletingAllSnapshots));
-    filters.add(new KeepLastSnapshotFilter());
-    return filters;
+  private List<PurgeableSnapshotDto> selectProjectSnapshots(long resourceId) {
+    return purgeDao.selectPurgeableSnapshots(resourceId);
   }
 }
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java
new file mode 100644 (file)
index 0000000..51fdd03
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.List;
+
+class DeleteAllFilter extends Filter {
+  private final Date before;
+
+  public DeleteAllFilter(Date before) {
+    this.before = before;
+  }
+
+  @Override
+  List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
+    List<PurgeableSnapshotDto> result = Lists.newArrayList();
+    for (PurgeableSnapshotDto snapshot : history) {
+      if (snapshot.getDate().before(before)) {
+        result.add(snapshot);
+      }
+    }
+    return result;
+  }
+
+  @Override
+  void log() {
+    LoggerFactory.getLogger(getClass()).debug("-> Delete data prior to: " + DateUtils.formatDate(before));
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java
new file mode 100644 (file)
index 0000000..cb1b33e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.List;
+
+abstract class Filter {
+  abstract List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> snapshots);
+
+  abstract void log();
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java
new file mode 100644 (file)
index 0000000..f89db20
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.time.DateUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+class Filters {
+  private final List<Filter> filters = Lists.newArrayList();
+
+  Filters(Settings settings) {
+    Date dateToStartKeepingOneSnapshotByWeek = getDate(settings, DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK);
+    Date dateToStartKeepingOneSnapshotByMonth = getDate(settings, DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH);
+    Date dateToStartDeletingAllSnapshots = getDate(settings, DbCleanerConstants.MONTHS_BEFORE_DELETING_ALL_SNAPSHOTS);
+
+    filters.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByWeek, new Date(), Calendar.DAY_OF_YEAR, "day"));
+    filters.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByMonth, dateToStartKeepingOneSnapshotByWeek, Calendar.WEEK_OF_YEAR, "week"));
+    filters.add(new KeepOneFilter(dateToStartDeletingAllSnapshots, dateToStartKeepingOneSnapshotByMonth, Calendar.MONTH, "month"));
+    filters.add(new DeleteAllFilter(dateToStartDeletingAllSnapshots));
+  }
+
+  List<Filter> getFilters() {
+    return filters;
+  }
+
+  static Date getDate(Settings settings, String propertyKey) {
+    int months = settings.getInt(propertyKey);
+    GregorianCalendar calendar = new GregorianCalendar();
+    calendar.add(GregorianCalendar.MONTH, -months);
+    return calendar.getTime();
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java
new file mode 100644 (file)
index 0000000..40e422f
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.time.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+final class Interval {
+  List<PurgeableSnapshotDto> snapshots = Lists.newArrayList();
+
+  void add(PurgeableSnapshotDto snapshot) {
+    snapshots.add(snapshot);
+  }
+
+  List<PurgeableSnapshotDto> get() {
+    return snapshots;
+  }
+
+  int count() {
+    return snapshots.size();
+  }
+
+  static List<Interval> group(List<PurgeableSnapshotDto> snapshots, Date start, Date end, int calendarField) {
+    List<Interval> intervals = Lists.newArrayList();
+
+    GregorianCalendar calendar = new GregorianCalendar();
+    int lastFieldValue = -1;
+    Interval currentInterval = null;
+
+    for (PurgeableSnapshotDto snapshot : snapshots) {
+      if (!DateUtils.isSameDay(start, snapshot.getDate()) && snapshot.getDate().after(start) &&
+        (snapshot.getDate().before(end) || DateUtils.isSameDay(end, snapshot.getDate()))) {
+        calendar.setTime(snapshot.getDate());
+        int currentFieldValue = calendar.get(calendarField);
+        if (lastFieldValue != currentFieldValue) {
+          currentInterval = new Interval();
+          intervals.add(currentInterval);
+        }
+        lastFieldValue = currentFieldValue;
+        if (currentInterval != null) {
+          currentInterval.add(snapshot);
+        }
+      }
+    }
+    return intervals;
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilter.java
deleted file mode 100644 (file)
index 24ed171..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import org.sonar.api.database.model.Snapshot;
-
-class KeepLastSnapshotFilter extends SnapshotFilter {
-
-  @Override
-  boolean filter(Snapshot snapshot) {
-    return snapshot.getLast();
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilter.java
deleted file mode 100644 (file)
index 906a8d7..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import org.sonar.api.database.model.Snapshot;
-
-class KeepLibrarySnapshotFilter extends SnapshotFilter {
-
-  @Override
-  boolean filter(Snapshot snapshot) {
-    return "LIB".equals(snapshot.getQualifier());
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java
new file mode 100644 (file)
index 0000000..fa8c5b3
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.List;
+
+class KeepOneFilter extends Filter {
+
+  private final Date start;
+  private final Date end;
+  private final int dateField;
+  private final String label;
+
+  KeepOneFilter(Date start, Date end, int calendarField, String label) {
+    this.start = start;
+    this.end = end;
+    this.dateField = calendarField;
+    this.label = label;
+  }
+
+  @Override
+  List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
+    List<Interval> intervals = Interval.group(history, start, end, dateField);
+    List<PurgeableSnapshotDto> result = Lists.newArrayList();
+    for (Interval interval : intervals) {
+      appendSnapshotsToDelete(interval, result);
+    }
+
+    return result;
+  }
+
+  @Override
+  void log() {
+    LoggerFactory.getLogger(getClass()).debug("-> Keep one snapshot per " + label + " between " + DateUtils.formatDate(start) + " and " + DateUtils.formatDate(end));
+  }
+
+  private void appendSnapshotsToDelete(Interval interval, List<PurgeableSnapshotDto> toDelete) {
+    if (interval.count() > 1) {
+      List<PurgeableSnapshotDto> deletables = Lists.newArrayList();
+      List<PurgeableSnapshotDto> toKeep = Lists.newArrayList();
+      for (PurgeableSnapshotDto snapshot : interval.get()) {
+        if (isDeletable(snapshot)) {
+          deletables.add(snapshot);
+        } else {
+          toKeep.add(snapshot);
+        }
+      }
+
+      if (!toKeep.isEmpty()) {
+        toDelete.addAll(deletables);
+
+      } else if (deletables.size() > 1) {
+        // keep one snapshot
+        toDelete.addAll(deletables.subList(1, deletables.size()));
+      }
+    }
+  }
+
+  @VisibleForTesting
+  static boolean isDeletable(PurgeableSnapshotDto snapshot) {
+    return !snapshot.isLast() && !snapshot.hasVersionEvent();
+  }
+
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilter.java
deleted file mode 100644 (file)
index 17e6d9a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-import org.sonar.api.database.model.Snapshot;
-
-class KeepOneSnapshotByPeriodBetweenTwoDatesFilter extends SnapshotFilter {
-
-  private final Date before;
-  private final Date after;
-  private GregorianCalendar calendar = new GregorianCalendar();
-  private int lastFieldValue = -1;
-  private final int dateField;
-
-  KeepOneSnapshotByPeriodBetweenTwoDatesFilter(int dateField, Date before, Date after) {
-    this.before = before;
-    this.after = after;
-    this.dateField = dateField;
-  }
-
-  @Override
-  boolean filter(Snapshot snapshot) {
-    boolean result = false;
-    Date createdAt = snapshot.getCreatedAt();
-    calendar.setTime(createdAt);
-    int currentFieldValue = calendar.get(dateField);
-    if (lastFieldValue != currentFieldValue && snapshot.getCreatedAt().after(after) && snapshot.getCreatedAt().before(before)) {
-      result = true;
-    }
-    lastFieldValue = currentFieldValue;
-    return result;
-  }
-
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilter.java
deleted file mode 100644 (file)
index d2e491f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import java.util.Date;
-
-import org.sonar.api.database.model.Snapshot;
-
-class KeepSnapshotsBetweenTwoDatesFilter extends SnapshotFilter {
-
-  private Date before;
-  private Date after;
-
-  KeepSnapshotsBetweenTwoDatesFilter(Date before, Date after) {
-    this.before = before;
-    this.after = after;
-  }
-
-  @Override
-  boolean filter(Snapshot snapshot) {
-    Date createdAt = snapshot.getCreatedAt();
-    return createdAt.before(before) && createdAt.after(after);
-  }
-
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/PeriodPurge.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/PeriodPurge.java
deleted file mode 100644 (file)
index b7efbf9..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.plugins.dbcleaner.api.PeriodCleaner;
-import org.sonar.plugins.dbcleaner.api.Purge;
-import org.sonar.plugins.dbcleaner.api.PurgeContext;
-
-public final class PeriodPurge extends Purge {
-
-  private PeriodCleaner periodCleaner;
-
-  public PeriodPurge(DatabaseSession session, PeriodCleaner periodCleaner) {
-    super(session);
-    this.periodCleaner = periodCleaner;
-  }
-
-  public void purge(PurgeContext context) {
-    periodCleaner.purge(context.getProject(), context.getSnapshotId());
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Periods.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Periods.java
deleted file mode 100644 (file)
index ae1766c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import org.apache.commons.configuration.Configuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.resources.Project;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-public final class Periods {
-
-  Date dateToStartKeepingOneSnapshotByWeek;
-  Date dateToStartKeepingOneSnapshotByMonth;
-  Date dateToStartDeletingAllSnapshots;
-
-  public Periods(Date dateToStartKeepingOneSnapshotByWeek, Date dateToStartKeepingOneSnapshotByMonth, Date dateToStartDeletingAllSnapshots) {
-    this.dateToStartKeepingOneSnapshotByWeek = dateToStartKeepingOneSnapshotByWeek;
-    this.dateToStartKeepingOneSnapshotByMonth = dateToStartKeepingOneSnapshotByMonth;
-    this.dateToStartDeletingAllSnapshots = dateToStartDeletingAllSnapshots;
-  }
-
-  public Periods(Project project) {
-    dateToStartKeepingOneSnapshotByWeek = getDate(project.getConfiguration(),
-        DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK, DbCleanerConstants.ONE_MONTH);
-    dateToStartKeepingOneSnapshotByMonth = getDate(project.getConfiguration(),
-        DbCleanerConstants.MONTHS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH, DbCleanerConstants.ONE_YEAR);
-    dateToStartDeletingAllSnapshots = getDate(project.getConfiguration(), DbCleanerConstants.MONTHS_BEFORE_DELETING_ALL_SNAPSHOTS,
-        DbCleanerConstants.FIVE_YEARS);
-  }
-
-  void log() {
-    Logger logger = LoggerFactory.getLogger(getClass());
-    SimpleDateFormat dateFormat = new SimpleDateFormat();
-    logger.debug("Keep only one snapshot by week after : " + dateFormat.format(dateToStartKeepingOneSnapshotByWeek));
-    logger.debug("Keep only one snapshot by month after : " + dateFormat.format(dateToStartKeepingOneSnapshotByMonth));
-    logger.debug("Delete all snapshots after : " + dateFormat.format(dateToStartDeletingAllSnapshots));
-  }
-
-  static Date getDate(Configuration conf, String propertyKey, String defaultNumberOfMonths) {
-    int months = conf.getInt(propertyKey, Integer.parseInt(defaultNumberOfMonths));
-    GregorianCalendar calendar = new GregorianCalendar();
-    calendar.add(GregorianCalendar.MONTH, -months);
-    return calendar.getTime();
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SQLRequests.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SQLRequests.java
deleted file mode 100644 (file)
index 47f89ff..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import org.sonar.api.batch.Event;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.Snapshot;
-
-import javax.persistence.Query;
-import java.util.List;
-
-final class SQLRequests {
-
-  private final DatabaseSession session;
-
-  SQLRequests(DatabaseSession session) {
-    this.session = session;
-  }
-
-  List<Snapshot> getProjectSnapshotsOrderedByCreatedAt(int oneProjectSnapshotId) {
-    Query query = session.createQuery("FROM " + Snapshot.class.getSimpleName()
-        + " sp1 WHERE sp1.resourceId  = (select sp2.resourceId FROM " + Snapshot.class.getSimpleName()
-        + " sp2 WHERE sp2.id = :id) and sp1.rootId= null and not exists (from " + Event.class.getSimpleName() + " e where e.snapshot=sp1) order by sp1.createdAt");
-    query.setParameter("id", oneProjectSnapshotId);
-    return query.getResultList();
-  }
-
-  List<Integer> getChildIds(Snapshot parentSnapshot) {
-    Query query = session.createQuery("select sp.id FROM " + Snapshot.class.getSimpleName()
-        + " sp WHERE sp.rootId  = :rootId or id = :rootId");
-    query.setParameter("rootId", parentSnapshot.getId());
-    return query.getResultList();
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SnapshotFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/SnapshotFilter.java
deleted file mode 100644 (file)
index 1a85cee..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import java.util.List;
-import java.util.ListIterator;
-
-import org.sonar.api.database.model.Snapshot;
-
-abstract class SnapshotFilter {
-
-  final int filter(List<Snapshot> snapshots) {
-    int before = snapshots.size();
-    ListIterator<Snapshot> iterator = snapshots.listIterator();
-    while (iterator.hasNext()) {
-      Snapshot snapshot = iterator.next();
-      if(filter(snapshot)){
-        iterator.remove();
-      }
-    }
-    int after = snapshots.size();
-    return before - after;
-  }
-
-  abstract boolean filter(Snapshot snapshot);
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJob.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJob.java
deleted file mode 100644 (file)
index 2069b38..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.runner;
-
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.hibernate.HibernateException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.PostJob;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.Project;
-import org.sonar.api.utils.TimeProfiler;
-import org.sonar.core.NotDryRun;
-import org.sonar.plugins.dbcleaner.api.Purge;
-import org.sonar.plugins.dbcleaner.api.PurgeContext;
-
-import javax.persistence.Query;
-
-@NotDryRun
-public final class DeprecatedPurgePostJob implements PostJob {
-
-  private DatabaseSession session;
-  private Snapshot snapshot;
-  private Purge[] purges;
-  private Project project;
-  private static final Logger LOG = LoggerFactory.getLogger(DeprecatedPurgePostJob.class);
-
-  public DeprecatedPurgePostJob(DatabaseSession session, Project project, Snapshot snapshot, Purge[] purges) {
-    this.session = session;
-    this.project = project;
-    this.snapshot = snapshot;
-    this.purges = purges.clone();
-  }
-
-  public void executeOn(Project project, SensorContext context) {
-    if (shouldExecuteOn(project)) {
-      purge();
-    }
-  }
-
-  static boolean shouldExecuteOn(Project project) {
-    return project.isRoot();
-  }
-
-  public void purge() {
-    TimeProfiler profiler = new TimeProfiler(LOG).start("Database optimization");
-    DefaultPurgeContext context = newContext();
-    LOG.debug("Snapshots to purge: " + context);
-    executePurges(context);
-    profiler.stop();
-  }
-
-
-  private void executePurges(DefaultPurgeContext context) {
-    TimeProfiler profiler = new TimeProfiler();
-    for (Purge purge : purges) {
-      try {
-        profiler.start("Purge " + purge.getClass().getName());
-        purge.purge(context);
-        session.commit(); // force hibernate to commit, so we're sure that the potential raised exception comes from this purge
-        profiler.stop();
-      } catch (javax.persistence.PersistenceException e) {
-        // Temporary workaround for MySQL deadlocks. The exception must not fail the build
-        // See https://jira.codehaus.org/browse/SONAR-2961 and https://jira.codehaus.org/browse/SONAR-2190
-        LOG.warn("Fail to execute purge: " + purge, e);
-
-      } catch (HibernateException e) {
-        // Temporary workaround for MySQL deadlocks. The exception must not fail the build
-        // See https://jira.codehaus.org/browse/SONAR-2961 and https://jira.codehaus.org/browse/SONAR-2190
-        LOG.warn("Fail to execute purge: " + purge, e);
-      }
-    }
-  }
-
-  private DefaultPurgeContext newContext() {
-    DefaultPurgeContext context = new DefaultPurgeContext(project, snapshot);
-    Snapshot previousLastSnapshot = getPreviousLastSnapshot();
-    if (previousLastSnapshot != null && previousLastSnapshot.getCreatedAt().before(snapshot.getCreatedAt())) {
-      context.setLastSnapshotId(previousLastSnapshot.getId());
-    }
-    return context;
-  }
-
-  private Snapshot getPreviousLastSnapshot() {
-    Query query = session.createQuery(
-      "SELECT s FROM " + Snapshot.class.getSimpleName() + " s " +
-        "WHERE s.status=:status AND s.resourceId=:resourceId AND s.createdAt<:date AND s.id <> :sid ORDER BY s.createdAt DESC");
-    query.setParameter("status", Snapshot.STATUS_PROCESSED);
-    query.setParameter("resourceId", snapshot.getResourceId());
-    query.setParameter("date", snapshot.getCreatedAt());
-    query.setParameter("sid", snapshot.getId());
-    query.setMaxResults(1);
-    return session.getSingleResult(query, null);
-  }
-
-  static final class DefaultPurgeContext implements PurgeContext {
-
-    private Project project;
-    private Integer currentSid;
-    private Integer previousSid;
-
-    public DefaultPurgeContext(Project project, Snapshot currentSnapshot) {
-      this(project, currentSnapshot, null);
-    }
-
-    public DefaultPurgeContext(Project project, Snapshot currentSnapshot, Snapshot previousSnapshot) {
-      this.project = project;
-      if (currentSnapshot != null) {
-        currentSid = currentSnapshot.getId();
-      }
-      if (previousSnapshot != null) {
-        previousSid = previousSnapshot.getId();
-      }
-    }
-
-    public DefaultPurgeContext setLastSnapshotId(Integer previousSid) {
-      this.previousSid = previousSid;
-      return this;
-    }
-
-    public Integer getSnapshotId() {
-      return currentSid;
-    }
-
-    public Integer getPreviousSnapshotId() {
-      return previousSid;
-    }
-
-    public Project getProject() {
-      return project;
-    }
-
-    @Override
-    public String toString() {
-      return new ToStringBuilder(this)
-        .append("currentSid", currentSid)
-        .append("previousSid", previousSid)
-        .toString();
-    }
-  }
-
-}
index 5a5646e4187315309a7ad53a0a9b1371f94dbf2b..016cf6aee01b2b9cf98964f47392faa11392df43 100644 (file)
@@ -30,6 +30,7 @@ import org.sonar.core.NotDryRun;
 import org.sonar.core.purge.PurgeDao;
 import org.sonar.core.purge.PurgeSnapshotQuery;
 import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
+import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
 
 @Properties({
   @Property(
@@ -42,14 +43,17 @@ public class ProjectPurgePostJob implements PostJob {
 
   private PurgeDao purgeDao;
   private Settings settings;
+  private DefaultPeriodCleaner periodCleaner;
 
-  public ProjectPurgePostJob(PurgeDao purgeDao, Settings settings) {
+  public ProjectPurgePostJob(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner) {
     this.purgeDao = purgeDao;
     this.settings = settings;
+    this.periodCleaner = periodCleaner;
   }
 
   public void executeOn(final Project project, SensorContext context) {
     long projectId = (long) project.getId();
+    cleanHistory(projectId);
     deleteAbortedBuilds(projectId);
     deleteFileHistory(projectId);
     if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) {
@@ -58,6 +62,10 @@ public class ProjectPurgePostJob implements PostJob {
     purgeProject(projectId);
   }
 
+  private void cleanHistory(long projectId) {
+    periodCleaner.purge(projectId);
+  }
+
   private void purgeProject(long projectId) {
     purgeDao.purgeProject(projectId);
   }
index f08ebf1f6900b07930d73d0a20d62b0dc40968a3..e46d3bb44bb8523d7741ae760ea332cb7781d155 100644 (file)
@@ -22,12 +22,13 @@ package org.sonar.plugins.dbcleaner;
 import org.junit.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 import static org.hamcrest.number.OrderingComparisons.greaterThan;
 
 public class DbCleanerPluginTest {
 
   @Test
   public void shouldGetExtensions() {
-    assertThat(new DbCleanerPlugin().getExtensions().size(), greaterThan(2));
+    assertThat(new DbCleanerPlugin().getExtensions().size(), is(2));
   }
 }
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java
new file mode 100644 (file)
index 0000000..9711b38
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+public final class DbCleanerTestUtils {
+
+  private DbCleanerTestUtils() {
+  }
+
+  public static PurgeableSnapshotDto createSnapshotWithDate(long snapshotId, String date) {
+    PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
+    snapshot.setSnapshotId(snapshotId);
+    snapshot.setDate(DateUtils.parseDate(date));
+    return snapshot;
+  }
+
+  public static PurgeableSnapshotDto createSnapshotWithDateTime(long snapshotId, String datetime) {
+      PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
+      snapshot.setSnapshotId(snapshotId);
+      snapshot.setDate(DateUtils.parseDateTime(datetime));
+      return snapshot;
+    }
+
+  public static final class SnapshotMatcher extends BaseMatcher<PurgeableSnapshotDto> {
+    long snapshotId;
+
+    public SnapshotMatcher(long snapshotId) {
+      this.snapshotId = snapshotId;
+    }
+
+    public boolean matches(Object o) {
+      return ((PurgeableSnapshotDto) o).getSnapshotId() == snapshotId;
+    }
+
+    public void describeTo(Description description) {
+      description.appendText("snapshotId").appendValue(snapshotId);
+    }
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/Utils.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/Utils.java
deleted file mode 100644 (file)
index 59f9f25..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner;
-
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-import org.sonar.api.database.model.Snapshot;
-
-public class Utils {
-  
-  public static Snapshot createSnapshot(int id, String version) {
-    Snapshot snapshot = new Snapshot();
-    snapshot.setId(id);
-    snapshot.setVersion(version);
-    snapshot.setCreatedAt(new GregorianCalendar().getTime());
-    return snapshot;
-  }
-
-  public static  Snapshot createSnapshot(int id, Date createdAt) {
-    Snapshot snapshot = new Snapshot();
-    snapshot.setId(id);
-    snapshot.setCreatedAt(createdAt);
-    return snapshot;
-  }
-
-  public static  Date day(int delta) {
-    GregorianCalendar calendar = new GregorianCalendar();
-    calendar.add(GregorianCalendar.DAY_OF_YEAR, delta);
-    return calendar.getTime();
-  }
-
-  public static  Date week(int delta, int dayOfWeek) {
-    GregorianCalendar calendar = new GregorianCalendar();
-    calendar.add(GregorianCalendar.WEEK_OF_YEAR, delta);
-    calendar.set(GregorianCalendar.DAY_OF_WEEK, dayOfWeek);
-    return calendar.getTime();
-  }
-
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java
deleted file mode 100644 (file)
index 99e0357..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.resources.Project;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-public class DefaultPeriodCleanerTest extends AbstractDbUnitTestCase {
-
-  DefaultPeriodCleaner cleaner;
-
-  Project project;
-  Periods periods;
-
-  @Before
-  public void init() {
-    cleaner = new DefaultPeriodCleaner(getSession());
-
-    project = new Project("myproject");
-    project.setConfiguration(new PropertiesConfiguration());
-
-    GregorianCalendar calendar = new GregorianCalendar(2010, 10, 1);
-    Date dateToStartKeepingOneSnapshotByWeek = calendar.getTime();
-    calendar.set(2010, 7, 1);
-    Date dateToStartKeepingOneSnapshotByMonth = calendar.getTime();
-    calendar.set(2010, 2, 1);
-    Date dateToStartDeletingAllSnapshots = calendar.getTime();
-    periods = new Periods(dateToStartKeepingOneSnapshotByWeek, dateToStartKeepingOneSnapshotByMonth, dateToStartDeletingAllSnapshots);
-  }
-
-  @Test
-  public void integrationTests() {
-    setupData("dbContent");
-    cleaner.purge(project, 1010, periods);
-    checkTables("dbContent", "snapshots");
-  }
-
-  @Test
-  public void test() {
-    // After a first run, no more snapshot should be deleted
-    setupData("dbContent-result");
-    cleaner.purge(project, 1010, periods);
-    checkTables("dbContent");
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java
new file mode 100644 (file)
index 0000000..a412318
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+import org.sonar.plugins.dbcleaner.DbCleanerTestUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
+
+public class DeleteAllFilterTest {
+
+  @Test
+  public void shouldDeleteAllSnapshotsPriorToDate() {
+    Filter filter = new DeleteAllFilter(DateUtils.parseDate("2011-12-25"));
+
+    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
+      DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"),
+      DbCleanerTestUtils.createSnapshotWithDate(2L, "2010-12-25"),
+      DbCleanerTestUtils.createSnapshotWithDate(3L, "2012-01-01")
+    ));
+
+    assertThat(toDelete.size(), is(2));
+    assertThat(toDelete, hasItem(new DbCleanerTestUtils.SnapshotMatcher(1L)));
+    assertThat(toDelete, hasItem(new DbCleanerTestUtils.SnapshotMatcher(2L)));
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java
new file mode 100644 (file)
index 0000000..b369383
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
+import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDateTime;
+
+public class IntervalTest {
+  @Test
+  public void shouldGroupByIntervals() {
+    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+      createSnapshotWithDate(1L, "2011-04-03"),
+
+      createSnapshotWithDate(2L, "2011-05-01"),
+      createSnapshotWithDate(3L, "2011-05-19"),
+
+      createSnapshotWithDate(4L, "2011-06-02"),
+      createSnapshotWithDate(5L, "2011-06-20"),
+
+      createSnapshotWithDate(6L, "2012-06-29") // out of scope
+    );
+
+    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
+    assertThat(intervals.size(), is(3));
+
+    assertThat(intervals.get(0).count(), is(1));
+    assertThat(month(intervals.get(0)), is(Calendar.APRIL));
+
+    assertThat(intervals.get(1).count(), is(2));
+    assertThat(month(intervals.get(1)), is(Calendar.MAY));
+
+    assertThat(intervals.get(2).count(), is(2));
+    assertThat(month(intervals.get(2)), is(Calendar.JUNE));
+  }
+
+  @Test
+  public void shouldIgnoreTimeWhenGroupingByIntervals() {
+    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+      createSnapshotWithDateTime(1L, "2011-05-25T16:16:48+0100"),
+      createSnapshotWithDateTime(2L, "2012-01-26T16:16:48+0100"),
+      createSnapshotWithDateTime(3L, "2012-01-27T16:16:48+0100")
+    );
+
+    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2011-05-25"), DateUtils.parseDate("2012-01-26"), Calendar.MONTH);
+    assertThat(intervals.size(), is(1));
+    assertThat(intervals.get(0).count(), is(1));
+    assertThat(intervals.get(0).get().get(0).getSnapshotId(), is(2L));
+  }
+
+  static int month(Interval interval) {
+    if (interval.count() == 0) {
+      return -1;
+    }
+
+    PurgeableSnapshotDto first = interval.get().iterator().next();
+    GregorianCalendar cal = new GregorianCalendar();
+    cal.setTime(first.getDate());
+    return cal.get(Calendar.MONTH);
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLastSnapshotFilterTest.java
deleted file mode 100644 (file)
index 667502a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.database.model.Snapshot;
-
-import java.util.List;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.sonar.plugins.dbcleaner.Utils.createSnapshot;
-
-public class KeepLastSnapshotFilterTest {
-
-  @Test
-  public void testFilter() {
-    List<Snapshot> snapshots = Lists.newLinkedList();
-    snapshots.add(createSnapshot(1, "0.1"));
-    Snapshot lastSnapshot = createSnapshot(2, "0.1");
-    lastSnapshot.setLast(true);
-    snapshots.add(lastSnapshot);
-
-    assertThat(new KeepLastSnapshotFilter().filter(snapshots), is(1));
-    assertThat(snapshots.size(), is(1));
-    assertThat(snapshots.get(0).getId(), is(1));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepLibrarySnapshotFilterTest.java
deleted file mode 100644 (file)
index d8031fd..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.database.model.Snapshot;
-
-import java.util.List;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.sonar.plugins.dbcleaner.Utils.createSnapshot;
-
-public class KeepLibrarySnapshotFilterTest {
-
-  @Test
-  public void testFilter() {
-    List<Snapshot> snapshots = Lists.newLinkedList();
-    Snapshot snapshot = createSnapshot(2, "0.1");
-    snapshots.add(snapshot);
-    snapshot.setQualifier("TRK");
-    snapshot = createSnapshot(2, "0.1");
-    snapshot.setQualifier("LIB");
-    snapshots.add(snapshot);
-
-    assertThat(new KeepLibrarySnapshotFilter().filter(snapshots), is(1));
-    assertThat(snapshots.size(), is(1));
-    assertThat(snapshots.get(0).getId(), is(2));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java
new file mode 100644 (file)
index 0000000..9e775a7
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.plugins.dbcleaner.period;
+
+import org.junit.Test;
+import org.junit.internal.matchers.IsCollectionContaining;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+import org.sonar.plugins.dbcleaner.DbCleanerTestUtils;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
+
+public class KeepOneFilterTest {
+
+  @Test
+  public void shouldOnlyOneSnapshotPerInterval() {
+    Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
+
+    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
+      createSnapshotWithDate(1L, "2010-01-01"), // out of scope -> keep
+      createSnapshotWithDate(2L, "2011-05-01"), // may -> keep
+      createSnapshotWithDate(3L, "2011-05-02"), // may -> to be deleted
+      createSnapshotWithDate(4L, "2011-05-19"), // may -> to be deleted
+      createSnapshotWithDate(5L, "2011-06-01"), // june -> keep
+      createSnapshotWithDate(6L, "2012-01-01") // out of scope -> keep
+    ));
+
+    assertThat(toDelete.size(), is(2));
+    assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(3L)));
+    assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(4L)));
+  }
+
+  @Test
+  public void shouldKeepNonDeletableSnapshots() {
+    Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
+
+    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
+      createSnapshotWithDate(1L, "2011-05-01"), // to be deleted
+      createSnapshotWithDate(2L, "2011-05-02").setLast(true),
+      createSnapshotWithDate(3L, "2011-05-19").setHasVersionEvent(true).setLast(false),
+      createSnapshotWithDate(4L, "2011-05-23") // to be deleted
+    ));
+
+    assertThat(toDelete.size(), is(2));
+    assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(1L)));
+    assertThat(toDelete, IsCollectionContaining.hasItem(new DbCleanerTestUtils.SnapshotMatcher(4L)));
+  }
+
+  @Test
+  public void test_isDeletable() {
+    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01")), is(true));
+    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setLast(true)), is(false));
+    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setHasVersionEvent(true)), is(false));
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest.java
deleted file mode 100644 (file)
index b2d2e5b..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.plugins.dbcleaner.Utils;
-
-import java.util.GregorianCalendar;
-import java.util.List;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-
-public class KeepOneSnapshotByPeriodBetweenTwoDatesFilterTest {
-
-  @Test
-  public void testFilter() {
-    List<Snapshot> snapshots = Lists.newLinkedList();
-    snapshots.add(Utils.createSnapshot(1, Utils.week(-7, 1)));
-    snapshots.add(Utils.createSnapshot(2, Utils.week(-7, 2)));
-    snapshots.add(Utils.createSnapshot(3, Utils.week(-7, 3)));
-    snapshots.add(Utils.createSnapshot(4, Utils.week(-6, 3)));
-    snapshots.add(Utils.createSnapshot(5, Utils.week(-6, 4)));
-
-    assertThat(new KeepOneSnapshotByPeriodBetweenTwoDatesFilter(GregorianCalendar.WEEK_OF_YEAR, Utils.week(-3, 1), Utils.week(-9, 1)).filter(snapshots), is(2));
-    assertThat(snapshots.size(), is(3));
-    assertThat(snapshots.get(0).getId(), is(2));
-    assertThat(snapshots.get(1).getId(), is(3));
-    assertThat(snapshots.get(2).getId(), is(5));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepSnapshotsBetweenTwoDatesFilterTest.java
deleted file mode 100644 (file)
index 9afa90b..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.database.model.Snapshot;
-
-import java.util.Date;
-import java.util.List;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.sonar.plugins.dbcleaner.Utils.createSnapshot;
-import static org.sonar.plugins.dbcleaner.Utils.day;
-
-public class KeepSnapshotsBetweenTwoDatesFilterTest {
-
-  @Test
-  public void testFilter() {
-    List<Snapshot> snapshots = Lists.newLinkedList();
-    snapshots.add(createSnapshot(1, day(-100)));
-    snapshots.add(createSnapshot(2, day(-70)));
-    snapshots.add(createSnapshot(3, day(-40)));
-    snapshots.add(createSnapshot(4, day(-10)));
-
-    assertThat(new KeepSnapshotsBetweenTwoDatesFilter(new Date(), day(-1)).filter(snapshots), is(0));
-    assertThat(snapshots.size(), is(4));
-
-    assertThat(new KeepSnapshotsBetweenTwoDatesFilter(new Date(), day(-80)).filter(snapshots), is(3));
-    assertThat(snapshots.size(), is(1));
-    assertThat(snapshots.get(0).getId(), is(1));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/PeriodsTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/PeriodsTest.java
deleted file mode 100644 (file)
index f03e050..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.period;
-
-import org.apache.commons.configuration.PropertiesConfiguration;
-import org.junit.Test;
-import org.sonar.api.resources.Project;
-
-import java.util.Date;
-import java.util.GregorianCalendar;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-
-public class PeriodsTest {
-
-  @Test
-  public void getDateShouldReturnCurrentTimeMinusDesiredMonths() {
-    Project project = new Project("myproject");
-    PropertiesConfiguration conf = new PropertiesConfiguration();
-    conf.setProperty("KEY", "2");
-    project.setConfiguration(conf);
-
-    Date date = Periods.getDate(conf, "KEY", "2");
-
-    GregorianCalendar calendar = new GregorianCalendar();
-    calendar.add(GregorianCalendar.MONTH, -2);
-    Date expectedDate = calendar.getTime();
-
-    assertThat(date.getMonth(), is(expectedDate.getMonth()));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest.java
deleted file mode 100644 (file)
index 402fdff..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar 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.
- *
- * Sonar 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 Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
- */
-package org.sonar.plugins.dbcleaner.runner;
-
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.junit.Test;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.resources.Project;
-import org.sonar.jpa.test.AbstractDbUnitTestCase;
-import org.sonar.plugins.dbcleaner.api.Purge;
-import org.sonar.plugins.dbcleaner.api.PurgeContext;
-
-import javax.persistence.PersistenceException;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.*;
-
-public class DeprecatedPurgePostJobTest extends AbstractDbUnitTestCase {
-
-  @Test
-  public void shouldExecutePurges() {
-    setupData("shared");
-    final int currentSID = 400;
-    final int previousSID = 300;
-    Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", currentSID);
-
-    Purge purge1 = mock(Purge.class);
-    Purge purge2 = mock(Purge.class);
-    Purge[] purges = new Purge[]{purge1, purge2};
-
-    new DeprecatedPurgePostJob(getSession(), new Project("key"), snapshot, purges).purge();
-
-    verify(purge1).purge(argThat(new BaseMatcher<PurgeContext>() {
-      public boolean matches(Object o) {
-        PurgeContext context = (PurgeContext) o;
-        return context.getSnapshotId() == currentSID && context.getPreviousSnapshotId() == previousSID;
-      }
-
-      public void describeTo(Description description) {
-      }
-    }));
-  }
-
-  @Test
-  public void shouldExecutePurgesEvenIfSingleAnalysis() {
-    setupData("shared");
-    final int currentSID = 1000;
-    Snapshot snapshot = getSession().getSingleResult(Snapshot.class, "id", currentSID);
-
-    Purge purge1 = mock(Purge.class);
-    Purge purge2 = mock(Purge.class);
-    Purge[] purges = new Purge[]{purge1, purge2};
-
-    new DeprecatedPurgePostJob(getSession(), new Project("key"), snapshot, purges).purge();
-
-    verify(purge1).purge(argThat(new BaseMatcher<PurgeContext>() {
-      public boolean matches(Object o) {
-        PurgeContext context = (PurgeContext) o;
-        return context.getSnapshotId() == currentSID && context.getPreviousSnapshotId() == null;
-      }
-
-      public void describeTo(Description description) {
-      }
-    }));
-  }
-
-  @Test
-  public void shouldExecuteOnlyOnRootProjects() {
-    Project project = mock(Project.class);
-    when(project.isRoot()).thenReturn(true);
-    assertTrue(DeprecatedPurgePostJob.shouldExecuteOn(project));
-
-    when(project.isRoot()).thenReturn(false);
-    assertFalse(DeprecatedPurgePostJob.shouldExecuteOn(project));
-  }
-
-  /**
-   * See https://jira.codehaus.org/browse/SONAR-2961
-   * Temporarily ignore MySQL deadlocks
-   */
-  @Test
-  public void shouldIgnoreDeadlocks() {
-    Purge purge = mock(Purge.class);
-    doThrow(new PersistenceException()).when(purge).purge((PurgeContext) anyObject());
-
-    DeprecatedPurgePostJob runner = new DeprecatedPurgePostJob(getSession(), new Project(""), new Snapshot(), new Purge[]{purge});
-    runner.purge();// must not raise any exceptions
-
-    verify(purge).purge((PurgeContext) anyObject());
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent-result.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent-result.xml
deleted file mode 100644 (file)
index 661d9da..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-<dataset>
-  <!-- projects -->
-  <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact" name="myproject"
-            root_id="[null]"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-  <projects long_name="[null]" id="2" scope="DIR" qualifier="PAC" kee="mygroup:myartifact:org.sonar" name="org.osnar"
-            root_id="1"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-  <projects long_name="[null]" id="3" scope="FIL" qualifier="CLA" kee="mygroup:myartifact:org.sonar.MyClass"
-            name="org.osnar.MyClass"
-            root_id="1"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-
-
-  <!-- snapshots older than the dateToStartDeletingAllSnapshots-->
-  <!-- keep this one because version event -->
-  <snapshots 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]" id="1" scope="PRJ" qualifier="TRK" created_at="2009-11-02 13:58:00.00" build_date="2009-11-02 13:58:00.00" version="0.9"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-  <project_measures characteristic_id="[null]" url="[null]" variation_value_1="[null]" variation_value_2="[null]"
-                    variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
-                    rule_priority="[null]"
-                    alert_text="[null]" ID="4" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="4" rules_category_id="[null]"
-                    RULE_ID="1"
-                    text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
-  <!--<snapshots 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]" id="2" scope="PRJ" qualifier="TRK" created_at="2010-01-01 13:58:00.00" build_date="2010-01-01 13:58:00.00"-->
-             <!--version="1.0-SNAPSHOT"-->
-             <!--project_id="1"-->
-             <!--parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"-->
-             <!--path="[null]"/>-->
-  <!--<project_measures ID="2" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="2"/>-->
-  <!--<snapshots 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="1" id="10" scope="DIR" qualifier="PAC" created_at="2010-01-01 13:58:00.00" build_date="2010-01-01 13:58:00.00" version="[null]"-->
-             <!--project_id="2"-->
-             <!--parent_snapshot_id="2" root_project_id="1" root_snapshot_id="2" status="P" islast="false"-->
-             <!--path="1"/>-->
-  <!--<snapshots 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="2" id="20" scope="FIL" qualifier="CLA" created_at="2010-01-01 13:58:00.00" build_date="2010-01-01 13:58:00.00" version="[null]"-->
-             <!--project_id="3"-->
-             <!--parent_snapshot_id="10" root_project_id="1" root_snapshot_id="2" status="P" islast="false"-->
-             <!--path="1.10"/>-->
-
-
-
-
-
-  <!-- snapshots between dateToStartKeepingOneSnapshotByMonth and dateToStartDeletingAllSnapshots-->
-  <!-- single snapshot on this month (except version events) -->
-  <snapshots 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]" id="100" scope="PRJ" qualifier="TRK" created_at="2010-03-01 13:58:00.00" build_date="2010-03-01 13:58:00.00"
-             version="1.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-  <!--<snapshots 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]" id="110" scope="PRJ" qualifier="TRK" created_at="2010-03-02 13:58:00.00" build_date="2010-03-02 13:58:00.00"-->
-             <!--version="1.0-SNAPSHOT"-->
-             <!--project_id="1"-->
-             <!--parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"-->
-             <!--path="[null]"/>-->
-
-  <!--<snapshots 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]" id="120" scope="PRJ" qualifier="TRK" created_at="2010-03-03 13:58:00.00" build_date="2010-03-03 13:58:00.00"-->
-             <!--version="1.0-SNAPSHOT"-->
-             <!--project_id="1"-->
-             <!--parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"-->
-             <!--path="[null]"/>-->
-
-  <!-- this one has a version event -->
-  <snapshots 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]" id="130" scope="PRJ" qualifier="TRK" created_at="2010-04-01 13:58:00.00" build_date="2010-04-01 13:58:00.00"
-             version="1.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-
-   <!-- keep this one -->
-  <snapshots 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]" id="140" scope="PRJ" qualifier="TRK" created_at="2010-04-15 13:58:00.00" build_date="2010-04-15 13:58:00.00"
-             version="1.1-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-
-
-
-
-
-  <!-- snapshots whose qualifier = LIB must not be deleted -->
-  <snapshots 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]" id="150" scope="PRJ" qualifier="LIB" created_at="2010-04-22 13:58:00.00" build_date="2010-04-22 13:58:00.00" version="0.1"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-  <snapshots 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]" id="160" scope="PRJ" qualifier="LIB" created_at="2010-04-23 13:58:00.00" build_date="2010-04-23 13:58:00.00" version="0.2"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-
-
-
-
-
-
-  <!-- snapshots between dateToStartKeepingOneSnapshotByWeek and dateToStartKeepingOneSnapshotByMonth-->
-  <!-- keep this one -->
-  <snapshots 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]" id="500" scope="PRJ" qualifier="TRK" created_at="2010-08-17 13:58:00.00" build_date="2010-08-17 13:58:00.00"
-             version="1.1-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-
-  <!--<snapshots 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]" id="510" scope="PRJ" qualifier="TRK" created_at="2010-08-18 13:58:00.00" build_date="2010-08-18 13:58:00.00"-->
-             <!--version="1.1-SNAPSHOT"-->
-             <!--project_id="1"-->
-             <!--parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"-->
-             <!--path="[null]"/>-->
-  
-  <!-- this one has a version event -->
-  <snapshots 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]" id="520" scope="PRJ" qualifier="TRK" created_at="2010-08-25 13:58:00.00" build_date="2010-08-25 13:58:00.00"
-             version="1.1-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-  <!-- this one has a version event -->
-  <snapshots 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]" id="530" scope="PRJ" qualifier="TRK" created_at="2010-08-26 13:58:00.00" build_date="2010-08-26 13:58:00.00"
-             version="1.2-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-
-
-  
-  <!--
-    snapshots before dateToStartKeepingOneSnapshotByWeek : nothing is currently purged
-    It will be improved later by keeping only one daily snapshot : snapshot 1010 should be removed -->
-  -->
-  <snapshots 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]" id="1000" scope="PRJ" qualifier="TRK" created_at="2010-11-02 13:58:00.00" build_date="2010-11-02 13:58:00.00"
-             version="3.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-  <snapshots 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]" id="1010" scope="PRJ" qualifier="TRK" created_at="2010-11-03 13:58:00.00" build_date="2010-11-03 13:58:00.00"
-             version="3.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
-             path="[null]"/>
-  <!-- same day than 1010 -->
-  <snapshots 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]" id="1020" scope="PRJ" qualifier="TRK" created_at="2010-11-03 20:26:00.00" build_date="2010-11-03 20:26:00.00"
-             version="3.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
-             path="[null]"/>
-
-  
-
-  <events id="1" name="Version 0.9" resource_id="1" snapshot_id="1" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]"/>
-
-  <events id="2" name="Version 1.0-SNAPSHOT" resource_id="1" snapshot_id="130" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]"/>
-
-  <events id="3" name="Version 1.1-SNAPSHOT" resource_id="1" snapshot_id="520" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]"/>
-
-  <events id="4" name="Version 1.2-SNAPSHOT" resource_id="1" snapshot_id="530" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]"/>
-
-
-</dataset>
\ No newline at end of file
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest/dbContent.xml
deleted file mode 100644 (file)
index b7e8a1c..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-<!--
-
-Information : The algorithm depends on GregorianCalendar.getFirstDayOfWeek(), so please do not use sundays and mondays in snapshot dates
-to ensure that unit tests pass on any locale.
-
--->
-
-<dataset>
-  <!-- projects -->
-  <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact" name="myproject"
-            root_id="[null]"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-  <projects long_name="[null]" id="2" scope="DIR" qualifier="PAC" kee="mygroup:myartifact:org.sonar" name="org.osnar"
-            root_id="1"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-  <projects long_name="[null]" id="3" scope="FIL" qualifier="CLA" kee="mygroup:myartifact:org.sonar.MyClass"
-            name="org.osnar.MyClass"
-            root_id="1"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-
-
-  <!-- snapshots older than the dateToStartDeletingAllSnapshots-->
-  <snapshots purge_status="[null]" depth="[null]" id="1" scope="PRJ" qualifier="TRK" created_at="2009-11-02 13:58:00.00" build_date="2009-11-02 13:58:00.00" version="0.9"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <project_measures characteristic_id="[null]" url="[null]" variation_value_1="[null]" variation_value_2="[null]"
-                    variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
-                    rule_priority="[null]"
-                    alert_text="[null]" ID="4" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="4" rules_category_id="[null]"
-                    RULE_ID="1"
-                    text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="2" scope="PRJ" qualifier="TRK" created_at="2010-01-01 13:58:00.00" build_date="2010-01-01 13:58:00.00"
-             version="1.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <project_measures ID="2" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="2"/>
-  <snapshots purge_status="[null]" depth="1" id="10" scope="DIR" qualifier="PAC" created_at="2010-01-01 13:58:00.00" build_date="2010-01-01 13:58:00.00" version="[null]"
-             project_id="2"
-             parent_snapshot_id="2" root_project_id="1" root_snapshot_id="2" status="P" islast="false"
-             path="1" 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]"/>
-  <snapshots purge_status="[null]" depth="2" id="20" scope="FIL" qualifier="CLA" created_at="2010-01-01 13:58:00.00" build_date="2010-01-01 13:58:00.00" version="[null]"
-             project_id="3"
-             parent_snapshot_id="10" root_project_id="1" root_snapshot_id="2" status="P" islast="false"
-             path="1.10" 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]"/>
-
-
-
-
-  <!-- snapshots between dateToStartKeepingOneSnapshotByMonth and dateToStartDeletingAllSnapshots-->
-  <snapshots purge_status="[null]" depth="[null]" id="100" scope="PRJ" qualifier="TRK" created_at="2010-03-01 13:58:00.00" build_date="2010-03-01 13:58:00.00"
-             version="1.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="110" scope="PRJ" qualifier="TRK" created_at="2010-03-02 13:58:00.00" build_date="2010-03-02 13:58:00.00"
-             version="1.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="120" scope="PRJ" qualifier="TRK" created_at="2010-03-03 13:58:00.00" build_date="2010-03-03 13:58:00.00"
-             version="1.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="130" scope="PRJ" qualifier="TRK" created_at="2010-04-01 13:58:00.00" build_date="2010-04-01 13:58:00.00"
-             version="1.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="140" scope="PRJ" qualifier="TRK" created_at="2010-04-15 13:58:00.00" build_date="2010-04-15 13:58:00.00"
-             version="1.1-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-
-
-
-
-  <!-- snapshots whose qualifier = LIB must not be deleted -->
-  <snapshots purge_status="[null]" depth="[null]" id="150" scope="PRJ" qualifier="LIB" created_at="2010-04-22 13:58:00.00" build_date="2010-04-22 13:58:00.00" version="0.1"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="160" scope="PRJ" qualifier="LIB" created_at="2010-04-23 13:58:00.00" build_date="2010-04-23 13:58:00.00" version="0.2"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-
-  <!-- snapshots between dateToStartKeepingOneSnapshotByWeek and dateToStartKeepingOneSnapshotByMonth-->
-  <snapshots purge_status="[null]" depth="[null]" id="500" scope="PRJ" qualifier="TRK" created_at="2010-08-17 13:58:00.00" build_date="2010-08-17 13:58:00.00"
-             version="1.1-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="510" scope="PRJ" qualifier="TRK" created_at="2010-08-19 13:58:00.00" build_date="2010-08-19 13:58:00.00"
-             version="1.1-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="520" scope="PRJ" qualifier="TRK" created_at="2010-08-25 13:58:00.00" build_date="2010-08-25 13:58:00.00"
-             version="1.1-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="530" scope="PRJ" qualifier="TRK" created_at="2010-08-26 13:58:00.00" build_date="2010-08-26 13:58:00.00"
-             version="1.2-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-
-  <!-- snapshots before dateToStartKeepingOneSnapshotByWeek-->
-  <snapshots purge_status="[null]" depth="[null]" id="1000" scope="PRJ" qualifier="TRK" created_at="2010-11-02 13:58:00.00" build_date="2010-11-02 13:58:00.00"
-             version="3.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[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]"/>
-  <snapshots purge_status="[null]" depth="[null]" id="1010" scope="PRJ" qualifier="TRK" created_at="2010-11-03 13:58:00.00" build_date="2010-11-03 13:58:00.00"
-             version="3.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
-             path="[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]"/>
-  <!-- same day than 1010 -->
-  <snapshots purge_status="[null]" depth="[null]" id="1020" scope="PRJ" qualifier="TRK" created_at="2010-11-03 20:26:00.00" build_date="2010-11-03 20:26:00.00"
-             version="3.0-SNAPSHOT"
-             project_id="1"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
-             path="[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]"/>
-
-
-
-  <events id="1" name="Version 0.9" resource_id="1" snapshot_id="1" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]" />
-
-  <events id="2" name="Version 1.0-SNAPSHOT" resource_id="1" snapshot_id="130" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]" />
-
-  <events id="3" name="Version 1.1-SNAPSHOT" resource_id="1" snapshot_id="520" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]" />
-
-  <events id="4" name="Version 1.2-SNAPSHOT" resource_id="1" snapshot_id="530" category="Version" description="[null]"
-          event_date="2008-12-02 13:58:00.00" created_at="[null]" />
-
-</dataset>
\ No newline at end of file
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest/shared.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/runner/DeprecatedPurgePostJobTest/shared.xml
deleted file mode 100644 (file)
index 18860b7..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<dataset>
-
-  <!--
-
-  PROJECT WITH HISTORIC DATA
-
-  -->
-
-  <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact" name="myproject"
-            root_id="[null]"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-
-  <!-- first snapshot -->
-  <snapshots 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]" id="100"
-             scope="PRJ" qualifier="TRK" created_at="2009-11-02 13:58:00.00" build_date="2009-11-02 13:58:00.00"
-             version="0.1-SNAPSHOT"
-             project_id="1" depth="[null]"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-
-  <!-- unvalid snapshot (status = UNPROCESSED) -->
-  <snapshots 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]" id="200"
-             scope="PRJ" qualifier="TRK" created_at="2009-11-03 13:58:00.00" build_date="2009-11-03 13:58:00.00"
-             version="0.1-SNAPSHOT"
-             project_id="1" depth="[null]"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="U" islast="false"
-             path="[null]"/>
-
-  <!-- second snapshot -->
-  <snapshots 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]" id="300"
-             scope="PRJ" qualifier="TRK" created_at="2009-11-04 13:58:00.00" build_date="2009-11-04 13:58:00.00"
-             version="0.1-SNAPSHOT"
-             project_id="1" depth="[null]"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
-             path="[null]"/>
-
-  <!-- last snapshot -->
-  <snapshots 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]" id="400"
-             scope="PRJ" qualifier="TRK" created_at="2009-11-05 13:58:00.00" build_date="2009-11-05 13:58:00.00"
-             version="0.1-SNAPSHOT"
-             project_id="1" depth="[null]"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
-             path="[null]"/>
-
-
-  <!-- PROJECT WITH ONLY A SINGLE ANALYSIS - NO TIME MACHINE -->
-  <projects long_name="[null]" id="2" scope="PRJ" qualifier="TRK" kee="mygroup2:myartifact2" name="myproject2"
-            root_id="[null]"
-            description="[null]"
-            enabled="true" language="java" copy_resource_id="[null]"/>
-
-  <snapshots 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]" id="1000"
-             scope="PRJ" qualifier="TRK" created_at="2009-11-05 13:58:00.00" build_date="2009-11-05 13:58:00.00"
-             version="0.1-SNAPSHOT"
-             project_id="2" depth="[null]"
-             parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
-             path="[null]"/>
-
-</dataset>
\ No newline at end of file
index 8837db3c6d7145051c16c0af4954c6c55e04dc09..f74d34fed79de7c13756ff8e97626bee2c2a9ae2 100644 (file)
@@ -33,6 +33,7 @@ import org.sonar.core.dashboard.*;
 import org.sonar.core.duplication.DuplicationMapper;
 import org.sonar.core.duplication.DuplicationUnitDto;
 import org.sonar.core.purge.PurgeMapper;
+import org.sonar.core.purge.PurgeableSnapshotDto;
 import org.sonar.core.resource.*;
 import org.sonar.core.review.ReviewDto;
 import org.sonar.core.review.ReviewMapper;
@@ -66,6 +67,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
     loadAlias(conf, "Dashboard", DashboardDto.class);
     loadAlias(conf, "DuplicationUnit", DuplicationUnitDto.class);
     loadAlias(conf, "LoadedTemplate", LoadedTemplateDto.class);
+    loadAlias(conf, "PurgeableSnapshot", PurgeableSnapshotDto.class);
     loadAlias(conf, "Review", ReviewDto.class);
     loadAlias(conf, "Resource", ResourceDto.class);
     loadAlias(conf, "ResourceIndex", ResourceIndexDto.class);
index 8bbe33b44b8e94581125c86efcbe0f1ddcff7ef1..cd38614b5e7c00f75cba9062154478fb410b0bbf 100644 (file)
@@ -20,6 +20,8 @@
 package org.sonar.core.purge;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.ResultContext;
 import org.apache.ibatis.session.ResultHandler;
@@ -28,7 +30,9 @@ import org.sonar.core.persistence.BatchSession;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.resource.ResourceDao;
 
+import java.util.Collections;
 import java.util.List;
+import java.util.SortedSet;
 
 public class PurgeDao {
   private final MyBatis mybatis;
@@ -84,6 +88,20 @@ public class PurgeDao {
     session.commit();
   }
 
+  public List<PurgeableSnapshotDto> selectPurgeableSnapshots(long resourceId) {
+    SqlSession session = mybatis.openSession(ExecutorType.REUSE);
+    try {
+      PurgeMapper mapper = session.getMapper(PurgeMapper.class);
+      List<PurgeableSnapshotDto> result = Lists.newArrayList();
+      result.addAll(mapper.selectPurgeableSnapshotsWithVersionEvent(resourceId));
+      result.addAll(mapper.selectPurgeableSnapshotsWithoutVersionEvent(resourceId));
+      Collections.sort(result);// sort by date
+      return result;
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
   public PurgeDao deleteProject(long rootProjectId) {
     final BatchSession session = mybatis.openBatchSession();
     try {
index 38cccfe0e60650d95730cf5c23e2490018663e20..31993b1896f23032c9a2a1d3c3657de6dbe05e5d 100644 (file)
@@ -70,4 +70,8 @@ public interface PurgeMapper {
   void deleteResourceEvents(long resourceId);
 
   void closeResourceReviews(long resourceId);
+  
+  List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithVersionEvent(long resourceId);
+
+  List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithoutVersionEvent(long resourceId);
 }
index 95dadd2f03cbf54b260d20d0704e75a68a46dd4f..5c9c3eccdf0eea5fa4b7d0007b7a8fb533b6fc71 100644 (file)
@@ -31,6 +31,7 @@ public final class PurgeSnapshotQuery {
   private String[] status;
   private Boolean islast;
   private Boolean notPurged;
+  private Boolean withVersionEvent;
 
   private PurgeSnapshotQuery() {
   }
@@ -119,4 +120,13 @@ public final class PurgeSnapshotQuery {
     this.resourceId = l;
     return this;
   }
+
+  public Boolean getWithVersionEvent() {
+    return withVersionEvent;
+  }
+
+  public PurgeSnapshotQuery setWithVersionEvent(Boolean withVersionEvent) {
+    this.withVersionEvent = withVersionEvent;
+    return this;
+  }
 }
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeableSnapshotDto.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeableSnapshotDto.java
new file mode 100644 (file)
index 0000000..5579bfa
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.core.purge;
+
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+
+import java.util.Date;
+
+public class PurgeableSnapshotDto implements Comparable<PurgeableSnapshotDto> {
+  private Date date;
+  private long snapshotId;
+  private boolean hasVersionEvent;
+  private boolean isLast;
+
+  public Date getDate() {
+    return date;
+  }
+
+  public long getSnapshotId() {
+    return snapshotId;
+  }
+
+  public boolean hasVersionEvent() {
+    return hasVersionEvent;
+  }
+
+  public boolean isLast() {
+    return isLast;
+  }
+
+  public void setDate(Date date) {
+    this.date = date;
+  }
+
+  public PurgeableSnapshotDto setSnapshotId(long snapshotId) {
+    this.snapshotId = snapshotId;
+    return this;
+  }
+
+  public PurgeableSnapshotDto setHasVersionEvent(boolean hasVersionEvent) {
+    this.hasVersionEvent = hasVersionEvent;
+    return this;
+  }
+
+  public PurgeableSnapshotDto setLast(boolean last) {
+    isLast = last;
+    return this;
+  }
+
+  public int compareTo(PurgeableSnapshotDto other) {
+    return date.compareTo(other.date);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    PurgeableSnapshotDto that = (PurgeableSnapshotDto) o;
+    return snapshotId == that.snapshotId;
+  }
+
+  @Override
+  public int hashCode() {
+    return (int)snapshotId;
+  }
+
+  @Override
+  public String toString() {
+    return new ReflectionToStringBuilder(this, ToStringStyle.SIMPLE_STYLE).toString();
+  }
+}
index 3f942d66c6bbd79c8823b255ae3e4392e9f3cb55..e0a7f656c3da99bcf0f5bf5c1bdd42ee649b9059 100644 (file)
@@ -4,41 +4,59 @@
 <mapper namespace="org.sonar.core.purge.PurgeMapper">
 
   <select id="selectSnapshotIds" parameterType="map" resultType="long">
-    select id from snapshots
+    select s.id from snapshots s
     <where>
       <if test="islast != null">
-        and islast=#{islast}
+        and s.islast=#{islast}
       </if>
       <if test="notPurged != null and notPurged">
-        and (purge_status is null or purge_status=0)
+        and (s.purge_status is null or s.purge_status=0)
       </if>
       <if test="rootSnapshotId != null">
-        and root_snapshot_id=#{rootSnapshotId}
+        and (s.root_snapshot_id=#{rootSnapshotId} or s.id=#{rootSnapshotId})
       </if>
       <if test="rootProjectId != null">
-        and root_project_id=#{rootProjectId}
+        and s.root_project_id=#{rootProjectId}
       </if>
       <if test="resourceId != null">
-        and project_id=#{resourceId}
+        and s.project_id=#{resourceId}
       </if>
       <if test="beforeBuildDate != null">
-        and build_date &lt;= #{beforeBuildDate}
+        and s.build_date &lt;= #{beforeBuildDate}
       </if>
       <if test="status != null">
-        and status in
+        and s.status in
         <foreach item="s" index="index" collection="status" open="(" separator="," close=")">#{s}</foreach>
       </if>
       <if test="scopes != null">
-        and scope in
+        and s.scope in
         <foreach item="scope" index="index" collection="scopes" open="(" separator="," close=")">#{scope}</foreach>
       </if>
       <if test="qualifiers != null">
-        and qualifier in
+        and s.qualifier in
         <foreach item="qualifier" index="index" collection="qualifiers" open="(" separator="," close=")">#{qualifier}</foreach>
       </if>
+      <if test="withVersionEvent != null">
+        <if test="withVersionEvent">
+          and exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version')
+        </if>
+        <if test="!withVersionEvent">
+          and not exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version')
+        </if>
+      </if>
     </where>
   </select>
 
+  <select id="selectPurgeableSnapshotsWithVersionEvent" parameterType="long" resultType="PurgeableSnapshot">
+    select s.id as "snapshotId", s.created_at as "date", ${_true} as "hasVersionEvent", islast as "isLast" from snapshots s
+    where s.project_id=#{id} and s.status='P' and s.qualifier &lt;&gt; 'LIB' and exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version')
+  </select>
+
+  <select id="selectPurgeableSnapshotsWithoutVersionEvent" parameterType="long" resultType="PurgeableSnapshot">
+    select s.id as "snapshotId", s.created_at as "date", ${_false} as "hasVersionEvent", islast as "isLast" from snapshots s
+    where s.project_id=#{id} and s.status='P' and s.qualifier &lt;&gt; 'LIB' and not exists(select e.id from events e where e.snapshot_id=s.id and e.category='Version')
+  </select>
+
   <select id="selectResourceIdsToDisable" resultType="long" parameterType="long">
     select p.id from projects p
     where (p.id=#{id} or p.root_id=#{id}) and p.enabled=${_true}
index b6644f9b275404dd6638c846a9fa9c26d7ca05d7..a165063ee3076a4ab4af396304f1a1ecba5d755e 100644 (file)
 package org.sonar.core.purge;
 
 import org.apache.ibatis.session.SqlSession;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.core.persistence.DaoTestCase;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.resource.ResourceDao;
 
+import java.util.List;
+import java.util.SortedSet;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
+
 public class PurgeDaoTest extends DaoTestCase {
 
   private PurgeDao dao;
@@ -76,20 +85,20 @@ public class PurgeDaoTest extends DaoTestCase {
   }
 
   @Test
-    public void shouldDeleteWastedMeasuresWhenPurgingSnapshot() {
-      setupData("shouldDeleteWastedMeasuresWhenPurgingSnapshot");
-
-      SqlSession session = getMyBatis().openSession();
-      try {
-        // this method does not commit and close the session
-        dao.purgeSnapshot(1L, session.getMapper(PurgeMapper.class));
-        session.commit();
-
-      } finally {
-        MyBatis.closeQuietly(session);
-      }
-      checkTables("shouldDeleteWastedMeasuresWhenPurgingSnapshot", "project_measures");
+  public void shouldDeleteWastedMeasuresWhenPurgingSnapshot() {
+    setupData("shouldDeleteWastedMeasuresWhenPurgingSnapshot");
+
+    SqlSession session = getMyBatis().openSession();
+    try {
+      // this method does not commit and close the session
+      dao.purgeSnapshot(1L, session.getMapper(PurgeMapper.class));
+      session.commit();
+
+    } finally {
+      MyBatis.closeQuietly(session);
     }
+    checkTables("shouldDeleteWastedMeasuresWhenPurgingSnapshot", "project_measures");
+  }
 
   @Test
   public void shouldCloseReviewWhenDisablingResource() {
@@ -135,4 +144,39 @@ public class PurgeDaoTest extends DaoTestCase {
     dao.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L));
     checkTables("shouldDeleteSnapshots", "snapshots");
   }
+
+  @Test
+  public void shouldSelectPurgeableSnapshots() {
+    setupData("shouldSelectPurgeableSnapshots");
+    List<PurgeableSnapshotDto> snapshots = dao.selectPurgeableSnapshots(1L);
+
+    assertThat(snapshots, hasItem(new SnapshotMatcher(1L, true, false)));
+    assertThat(snapshots, hasItem(new SnapshotMatcher(4L, false, false)));
+    assertThat(snapshots, hasItem(new SnapshotMatcher(5L, false, true)));
+    assertThat(snapshots.size(), is(3));
+  }
+
+  static final class SnapshotMatcher extends BaseMatcher<PurgeableSnapshotDto> {
+    long snapshotId;
+    boolean isLast;
+    boolean hasVersionEvent;
+
+    SnapshotMatcher(long snapshotId, boolean last, boolean hasVersionEvent) {
+      this.snapshotId = snapshotId;
+      this.isLast = last;
+      this.hasVersionEvent = hasVersionEvent;
+    }
+
+    public boolean matches(Object o) {
+      PurgeableSnapshotDto obj = (PurgeableSnapshotDto) o;
+      return obj.getSnapshotId() == snapshotId && obj.isLast()==isLast && obj.hasVersionEvent()==hasVersionEvent;
+    }
+
+    public void describeTo(Description description) {
+      description
+        .appendText("snapshotId").appendValue(snapshotId)
+        .appendText("isLast").appendValue(isLast)
+        .appendText("hasVersionEvent").appendValue(hasVersionEvent);
+    }
+  }
 }
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldSelectPurgeableSnapshots.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldSelectPurgeableSnapshots.xml
new file mode 100644 (file)
index 0000000..a9024cc
--- /dev/null
@@ -0,0 +1,64 @@
+<dataset>
+
+  <!-- last -> keep -->
+  <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]"/>
+
+  <!-- not processed -> exclude -->
+  <snapshots id="2"
+             project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+             status="U" 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]"/>
+
+  <!-- on other resource -->
+  <snapshots id="3"
+             project_id="222" parent_snapshot_id="[null]" root_project_id="222" 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]"/>
+
+  <!-- without version -> keep -->
+  <snapshots id="4"
+             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]"/>
+
+  <events id="1" resource_id="1" snapshot_id="4"
+            category="Quality profile change" description="[null]" name="xxx" event_date="2008-12-02 13:58:00.00" created_at="[null]"/>
+
+  <!-- with version -> keep -->
+  <snapshots id="5"
+             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]"/>
+
+  <events id="2" resource_id="1" snapshot_id="5"
+          category="Version" description="[null]" name="Version 1.0" event_date="2008-12-02 13:58:00.00" created_at="[null]"/>
+
+</dataset>
\ No newline at end of file