Move definitions of generate_ignores() higher in the file.
[cvs2svn.git] / cvs2svn_lib / stats_keeper.py
blob1a82540732d967db5f5b39a625ddff989b01b854
1 # (Be in -*- python -*- mode.)
3 # ====================================================================
4 # Copyright (c) 2000-2008 CollabNet. All rights reserved.
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://subversion.tigris.org/license-1.html.
9 # If newer versions of this license are posted there, you may use a
10 # newer version instead, at your option.
12 # This software consists of voluntary contributions made by many
13 # individuals. For exact contribution history, see the revision
14 # history and logs, available at http://cvs2svn.tigris.org/.
15 # ====================================================================
17 """This module contains the StatsKeeper class.
19 A StatsKeeper can pickle itself to a STATISTICS_FILE. This module
20 also includes a function to read a StatsKeeper from a STATISTICS_FILE."""
23 import time
24 import cPickle
25 from cStringIO import StringIO
27 from cvs2svn_lib.cvs_item import CVSRevision
28 from cvs2svn_lib.cvs_item import CVSBranch
29 from cvs2svn_lib.cvs_item import CVSTag
32 class StatsKeeper:
33 def __init__(self):
34 self._svn_rev_count = None
35 self._first_rev_date = 1L<<32
36 self._last_rev_date = 0
37 self._pass_timings = { }
38 self._stats_reflect_exclude = False
39 self.reset_cvs_rev_info()
41 def log_duration_for_pass(self, duration, pass_num, pass_name):
42 self._pass_timings[pass_num] = (pass_name, duration,)
44 def set_stats_reflect_exclude(self, value):
45 self._stats_reflect_exclude = value
47 def reset_cvs_rev_info(self):
48 self._repos_file_count = 0
49 self._repos_size = 0
50 self._cvs_revs_count = 0
51 self._cvs_branches_count = 0
52 self._cvs_tags_count = 0
54 # A set of tag_ids seen:
55 self._tag_ids = set()
57 # A set of branch_ids seen:
58 self._branch_ids = set()
60 def record_cvs_file(self, cvs_file):
61 self._repos_file_count += 1
62 self._repos_size += cvs_file.file_size
64 def _record_cvs_rev(self, cvs_rev):
65 self._cvs_revs_count += 1
67 if cvs_rev.timestamp < self._first_rev_date:
68 self._first_rev_date = cvs_rev.timestamp
70 if cvs_rev.timestamp > self._last_rev_date:
71 self._last_rev_date = cvs_rev.timestamp
73 def _record_cvs_branch(self, cvs_branch):
74 self._cvs_branches_count += 1
75 self._branch_ids.add(cvs_branch.symbol.id)
77 def _record_cvs_tag(self, cvs_tag):
78 self._cvs_tags_count += 1
79 self._tag_ids.add(cvs_tag.symbol.id)
81 def record_cvs_item(self, cvs_item):
82 if isinstance(cvs_item, CVSRevision):
83 self._record_cvs_rev(cvs_item)
84 elif isinstance(cvs_item, CVSBranch):
85 self._record_cvs_branch(cvs_item)
86 elif isinstance(cvs_item, CVSTag):
87 self._record_cvs_tag(cvs_item)
88 else:
89 raise RuntimeError('Unknown CVSItem type')
91 def set_svn_rev_count(self, count):
92 self._svn_rev_count = count
94 def svn_rev_count(self):
95 return self._svn_rev_count
97 def __getstate__(self):
98 state = self.__dict__.copy()
99 # This can get kinda large, so we don't store it:
100 return state
102 def archive(self, filename):
103 f = open(filename, 'wb')
104 cPickle.dump(self, f)
105 f.close()
107 def __str__(self):
108 f = StringIO()
109 f.write('\n')
110 f.write('cvs2svn Statistics:\n')
111 f.write('------------------\n')
112 f.write('Total CVS Files: %10i\n' % (self._repos_file_count,))
113 f.write('Total CVS Revisions: %10i\n' % (self._cvs_revs_count,))
114 f.write('Total CVS Branches: %10i\n' % (self._cvs_branches_count,))
115 f.write('Total CVS Tags: %10i\n' % (self._cvs_tags_count,))
116 f.write('Total Unique Tags: %10i\n' % (len(self._tag_ids),))
117 f.write('Total Unique Branches: %10i\n' % (len(self._branch_ids),))
118 f.write('CVS Repos Size in KB: %10i\n' % ((self._repos_size / 1024),))
120 if self._svn_rev_count is not None:
121 f.write('Total SVN Commits: %10i\n' % self._svn_rev_count)
123 f.write(
124 'First Revision Date: %s\n' % (time.ctime(self._first_rev_date),)
126 f.write(
127 'Last Revision Date: %s\n' % (time.ctime(self._last_rev_date),)
129 f.write('------------------')
131 if not self._stats_reflect_exclude:
132 f.write(
133 '\n'
134 '(These are unaltered CVS repository stats and do not\n'
135 ' reflect tags or branches excluded via --exclude)\n'
138 return f.getvalue()
140 @staticmethod
141 def _get_timing_format(value):
142 # Output times with up to 3 decimal places:
143 decimals = max(0, 4 - len('%d' % int(value)))
144 length = len(('%%.%df' % decimals) % value)
145 return '%%%d.%df' % (length, decimals,)
147 def single_pass_timing(self, pass_num):
148 (pass_name, duration,) = self._pass_timings[pass_num]
149 format = self._get_timing_format(duration)
150 time_string = format % (duration,)
151 return (
152 'Time for pass%d (%s): %s seconds.'
153 % (pass_num, pass_name, time_string,)
156 def timings(self):
157 passes = self._pass_timings.keys()
158 passes.sort()
159 f = StringIO()
160 f.write('Timings (seconds):\n')
161 f.write('------------------\n')
163 total = 0.0
164 for pass_num in passes:
165 (pass_name, duration,) = self._pass_timings[pass_num]
166 total += duration
168 format = self._get_timing_format(total)
170 for pass_num in passes:
171 (pass_name, duration,) = self._pass_timings[pass_num]
172 f.write(
173 (format + ' pass%-2d %s\n') % (duration, pass_num, pass_name,)
176 f.write((format + ' total') % total)
177 return f.getvalue()
180 def read_stats_keeper(filename):
181 """Factory function: Return a _StatsKeeper instance.
183 Read the instance from FILENAME as written by StatsKeeper.archive()."""
185 f = open(filename, 'rb')
186 retval = cPickle.load(f)
187 f.close()
188 return retval