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;
public List getExtensions() {
return Arrays.asList(
- DefaultPeriodCleaner.class,
- PeriodPurge.class,
-
- // post-jobs
- ProjectPurgePostJob.class, DeprecatedPurgePostJob.class);
+ DefaultPeriodCleaner.class, ProjectPurgePostJob.class);
}
}
import org.sonar.api.resources.Project;
/**
- * @since 2.14
* @deprecated in 2.14
*/
@Deprecated
*/
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);
}
}
--- /dev/null
+/*
+ * 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));
+ }
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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());
- }
-}
--- /dev/null
+/*
+ * 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();
+ }
+
+}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
-
-}
+++ /dev/null
-/*
- * 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());
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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();
- }
- }
-
-}
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(
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)) {
purgeProject(projectId);
}
+ private void cleanHistory(long projectId) {
+ periodCleaner.purge(projectId);
+ }
+
private void purgeProject(long projectId) {
purgeDao.purgeProject(projectId);
}
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));
}
}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
+++ /dev/null
-/*
- * 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();
- }
-
-}
+++ /dev/null
-/*
- * 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");
- }
-}
--- /dev/null
+/*
+ * 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)));
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
+++ /dev/null
-/*
- * 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));
- }
-}
+++ /dev/null
-/*
- * 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));
- }
-}
--- /dev/null
+/*
+ * 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));
+ }
+}
+++ /dev/null
-/*
- * 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));
- }
-}
+++ /dev/null
-/*
- * 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));
- }
-}
+++ /dev/null
-/*
- * 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()));
- }
-}
+++ /dev/null
-/*
- * 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());
- }
-}
+++ /dev/null
-<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
+++ /dev/null
-<!--
-
-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
+++ /dev/null
-<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
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;
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);
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;
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;
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 {
void deleteResourceEvents(long resourceId);
void closeResourceReviews(long resourceId);
+
+ List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithVersionEvent(long resourceId);
+
+ List<PurgeableSnapshotDto> selectPurgeableSnapshotsWithoutVersionEvent(long resourceId);
}
private String[] status;
private Boolean islast;
private Boolean notPurged;
+ private Boolean withVersionEvent;
private PurgeSnapshotQuery() {
}
this.resourceId = l;
return this;
}
+
+ public Boolean getWithVersionEvent() {
+ return withVersionEvent;
+ }
+
+ public PurgeSnapshotQuery setWithVersionEvent(Boolean withVersionEvent) {
+ this.withVersionEvent = withVersionEvent;
+ return this;
+ }
}
--- /dev/null
+/*
+ * 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();
+ }
+}
<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 <= #{beforeBuildDate}
+ and s.build_date <= #{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 <> '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 <> '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}
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;
}
@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() {
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);
+ }
+ }
}
--- /dev/null
+<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