Mercurial > bitten > bitten-test
comparison contrib/deletebuild.py @ 869:467e993df52d 0.6.x
0.6dev: Merged [940:942] from trunk.
author | hodgestar |
---|---|
date | Mon, 18 Oct 2010 11:55:44 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
868:242f2e225c4e | 869:467e993df52d |
---|---|
1 # -*- coding: utf-8 -*- | |
2 # | |
3 # Maintained by Simon Cross <hodegstar+bittencontrib@gmail.com> | |
4 # | |
5 # Copyright (C) 2010 Edgewall Software | |
6 # All rights reserved. | |
7 # | |
8 # This software is licensed as described in the file COPYING, which | |
9 # you should have received as part of this distribution. The terms | |
10 # are also available at http://bitten.edgewall.org/wiki/License. | |
11 | |
12 """Utility for deleting duplicate builds encounted while upgrading | |
13 to schema version 10.""" | |
14 | |
15 import os | |
16 | |
17 from trac.env import Environment | |
18 from trac.attachment import Attachment | |
19 from trac.resource import Resource | |
20 | |
21 __version__ = "1.0a1" | |
22 | |
23 class BuildDeleter(object): | |
24 """Class for deleting a build.""" | |
25 | |
26 def __init__(self, env_path): | |
27 self.env = Environment(env_path) | |
28 self.logs_dir = self.env.config.get('bitten', 'logs_dir', 'log/bitten') | |
29 | |
30 def _log_files(self, cursor, build): | |
31 """Return a list of log files.""" | |
32 cursor.execute("SELECT filename FROM bitten_log WHERE build=%s", | |
33 (build,)) | |
34 rows = cursor.fetchall() | |
35 | |
36 all_files = [] | |
37 for row in rows: | |
38 filename = row[0] | |
39 file_prefix = os.path.join(self.logs_dir, filename) | |
40 for suffix in ['', '.level', '.levels']: | |
41 log_file = file_prefix + suffix | |
42 if os.path.isfile(log_file): | |
43 all_files.append(log_file) | |
44 | |
45 return all_files | |
46 | |
47 def discover(self, build): | |
48 """Print a summary of what is linked to the build.""" | |
49 print "Items to delete for build %r" % (build,) | |
50 print "-------------------------------" | |
51 | |
52 db = self.env.get_db_cnx() | |
53 cursor = db.cursor() | |
54 | |
55 print "Attachments for build resource:" | |
56 cursor.execute("SELECT config FROM bitten_build WHERE id=%s", (build,)) | |
57 config = cursor.fetchone()[0] | |
58 print " %s/%s" % (config, build) | |
59 | |
60 print "Log files:" | |
61 print " ", "\n ".join(self._log_files(cursor, build)) | |
62 | |
63 print "Rows from bitten_log with ids:" | |
64 cursor.execute("SELECT id FROM bitten_log WHERE build=%s", (build,)) | |
65 print " ", "\n ".join(str(row[0]) for row in cursor.fetchall()) | |
66 | |
67 print "Rows from bitten_report with ids:" | |
68 cursor.execute("SELECT id FROM bitten_report WHERE build=%s", (build,)) | |
69 print " ", "\n ".join(str(row[0]) for row in cursor.fetchall()) | |
70 print "Rows from bitten_report_item with report set to these ids will" | |
71 print "also be deleted." | |
72 | |
73 print "Rows from bitten_step for this build with names:" | |
74 cursor.execute("SELECT name FROM bitten_step WHERE build=%s", (build,)) | |
75 print " ", "\n ".join(str(row[0]) for row in cursor.fetchall()) | |
76 | |
77 print "Row from bitten_build with id:" | |
78 cursor.execute("SELECT id FROM bitten_build WHERE id=%s", (build,)) | |
79 print " ", "\n ".join(str(row[0]) for row in cursor.fetchall()) | |
80 | |
81 def remove(self, build): | |
82 """Delete what is linked to the build.""" | |
83 print "Deleting items for build %r" % (build,) | |
84 | |
85 db = self.env.get_db_cnx() | |
86 cursor = db.cursor() | |
87 | |
88 print "Determining associated config." | |
89 cursor.execute("SELECT config FROM bitten_build WHERE id=%s", (build,)) | |
90 config = cursor.fetchone()[0] | |
91 | |
92 print "Collecting log files." | |
93 filenames = self._log_files(cursor, build) | |
94 | |
95 try: | |
96 print "Deleting bitten_log entries." | |
97 cursor.execute("DELETE FROM bitten_log WHERE build=%s", (build,)) | |
98 | |
99 print "Deleting bitten_report_item_entries." | |
100 cursor.execute("DELETE FROM bitten_report_item WHERE report IN (" | |
101 "SELECT bitten_report.id FROM bitten_report " | |
102 "WHERE bitten_report.build=%s" | |
103 ")", (build,)) | |
104 | |
105 print "Deleting bitten_report entires." | |
106 cursor.execute("DELETE FROM bitten_report WHERE build=%s", | |
107 (build,)) | |
108 | |
109 print "Deleting bitten_step entries." | |
110 cursor.execute("DELETE FROM bitten_step WHERE build=%s", (build,)) | |
111 | |
112 print "Delete bitten_build entry." | |
113 cursor.execute("DELETE FROM bitten_build WHERE id=%s", (build,)) | |
114 except: | |
115 db.rollback() | |
116 print "Build deletion failed. Database rolled back." | |
117 raise | |
118 | |
119 print "Bitten database changes committed." | |
120 db.commit() | |
121 | |
122 print "Removing log files." | |
123 for filename in filenames: | |
124 os.remove(filename) | |
125 | |
126 print "Removing attachments." | |
127 resource = Resource('build', '%s/%s' % (config, build)) | |
128 Attachment.delete_all(self.env, 'build', resource.id, db) | |
129 | |
130 | |
131 def main(): | |
132 from optparse import OptionParser | |
133 | |
134 parser = OptionParser(usage='usage: %prog env_path build_id', | |
135 version='%%prog %s' % __version__) | |
136 | |
137 options, args = parser.parse_args() | |
138 | |
139 if len(args) != 2: | |
140 parser.error('incorrect number of arguments') | |
141 | |
142 env_path, build_id = args | |
143 | |
144 deleter = BuildDeleter(env_path) | |
145 deleter.discover(build_id) | |
146 proceed = raw_input('Continue [y/n]? ') | |
147 if proceed == 'y': | |
148 deleter.remove(build_id) | |
149 | |
150 | |
151 if __name__ == "__main__": | |
152 import sys | |
153 sys.exit(main()) |