1
# Copyright 2011 Canonical Ltd. All rights reserved.
3
# This program is free software: you can redistribute it and/or modify
4
# it under the terms of the GNU Affero General Public License as published by
5
# the Free Software Foundation, either version 3 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU Affero General Public License for more details.
13
# You should have received a copy of the GNU Affero General Public License
14
# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
# Delete DB records of OOPSes that have no bug reports for them.
24
from textwrap import dedent
26
from oops_datedir_repo.prune import LaunchpadTracker
29
from oopstools.oops.models import (
35
def main(argv=None, tracker=LaunchpadTracker, logging=logging):
36
"""Console script entry point."""
42
The following options must be supplied:
49
%prog --projectgroup launchpad-project
51
Will process every member project of launchpad-project.
53
When run this program will ask Launchpad for OOPS references made since
54
the last date it pruned up to, with an upper limit of one week from
55
today. It then looks in the repository for all oopses created during
56
that date range, and if they are not in the set returned by Launchpad,
57
deletes them. If the repository has never been pruned before, it will
58
pick the earliest date present in the repository as the start date.
61
"Delete OOPS reports that are not referenced in a bug tracker."
62
parser = optparse.OptionParser(
63
description=description, usage=usage)
64
parser.add_option('--project',
65
help="Launchpad project to find references in.")
66
parser.add_option('--projectgroup',
67
help="Launchpad project group to find references in.")
69
'--lpinstance', help="Launchpad instance to use", default="production")
70
options, args = parser.parse_args(argv[1:])
71
def needed(*optnames):
73
for optname in optnames:
74
if getattr(options, optname, None) is not None:
77
if len(optnames) == 1:
78
raise ValueError('Option "%s" must be supplied' % optname)
81
'One of options %s must be supplied' % (optnames,))
82
elif len(present) != 1:
84
'Only one of options %s can be supplied' % (optnames,))
85
needed('project', 'projectgroup')
87
filename='prune.log', filemode='w', level=logging.DEBUG)
88
one_week = datetime.timedelta(weeks=1)
89
one_day = datetime.timedelta(days=1)
90
# Only prune OOPS reports more than one week old.
91
prune_until = datetime.datetime.now(utc) - one_week
92
# Ignore OOPS reports we already found references for - older than the last
95
info = PruneInfo.objects.all()[0]
99
oldest_oops = Oops.objects.order_by('id')[0]
103
info = PruneInfo(pruned_until=oldest_oops.date-one_day)
105
prune_from = info.pruned_until
106
if prune_from.tzinfo is None:
107
# Workaround django tz handling bug:
108
# https://code.djangoproject.com/ticket/17062
109
prune_from = prune_from.replace(tzinfo=utc)
110
# The tracker finds all the references for the selected dates.
111
finder = tracker(options)
112
references = finder.find_oops_references(
113
prune_from, prune_until, options.project, options.projectgroup)
114
# Then we can delete the unreferenced oopses.
115
PruneInfo.prune_unreferenced(prune_from, prune_until, references)
116
# And finally save the fact we have scanned up to the selected date.
117
info.pruned_until = prune_until