/usr/lib/python2.7/dist-packages/cvs2svn_lib/pass_manager.py is in cvs2svn 2.4.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | # (Be in -*- python -*- mode.)
#
# ====================================================================
# Copyright (c) 2000-2009 CollabNet. All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals. For exact contribution history, see the revision
# history and logs, available at http://cvs2svn.tigris.org/.
# ====================================================================
"""This module contains tools to manage the passes of a conversion."""
import time
import gc
from cvs2svn_lib import config
from cvs2svn_lib.common import FatalError
from cvs2svn_lib.context import Ctx
from cvs2svn_lib.log import logger
from cvs2svn_lib.stats_keeper import StatsKeeper
from cvs2svn_lib.stats_keeper import read_stats_keeper
from cvs2svn_lib.artifact_manager import artifact_manager
class InvalidPassError(FatalError):
def __init__(self, msg):
FatalError.__init__(
self, msg + '\nUse --help-passes for more information.')
def check_for_garbage():
# We've turned off the garbage collector because we shouldn't
# need it (we don't create circular dependencies) and because it
# is therefore a waste of time. So here we check for any
# unreachable objects and generate a debug-level warning if any
# occur:
gc.set_debug(gc.DEBUG_SAVEALL)
gc_count = gc.collect()
if gc_count:
if logger.is_on(logger.DEBUG):
logger.debug(
'INTERNAL: %d unreachable object(s) were garbage collected:'
% (gc_count,)
)
for g in gc.garbage:
logger.debug(' %s' % (g,))
del gc.garbage[:]
class Pass(object):
"""Base class for one step of the conversion."""
def __init__(self):
# By default, use the pass object's class name as the pass name:
self.name = self.__class__.__name__
def register_artifacts(self):
"""Register artifacts (created and needed) in artifact_manager."""
raise NotImplementedError()
def _register_temp_file(self, basename):
"""Helper method; for brevity only."""
artifact_manager.register_temp_file(basename, self)
def _register_temp_file_needed(self, basename):
"""Helper method; for brevity only."""
artifact_manager.register_temp_file_needed(basename, self)
def run(self, run_options, stats_keeper):
"""Carry out this step of the conversion.
RUN_OPTIONS is an instance of RunOptions. STATS_KEEPER is an
instance of StatsKeeper."""
raise NotImplementedError()
class PassManager:
"""Manage a list of passes that can be executed separately or all at once.
Passes are numbered starting with 1."""
def __init__(self, passes):
"""Construct a PassManager with the specified PASSES.
Internally, passes are numbered starting with 1. So PASSES[0] is
considered to be pass number 1."""
self.passes = passes
self.num_passes = len(self.passes)
def get_pass_number(self, pass_name, default=None):
"""Return the number of the pass indicated by PASS_NAME.
PASS_NAME should be a string containing the name or number of a
pass. If a number, it should be in the range 1 <= value <=
self.num_passes. Return an integer in the same range. If
PASS_NAME is the empty string and DEFAULT is specified, return
DEFAULT. Raise InvalidPassError if PASS_NAME cannot be converted
into a valid pass number."""
if not pass_name and default is not None:
assert 1 <= default <= self.num_passes
return default
try:
# Does pass_name look like an integer?
pass_number = int(pass_name)
if not 1 <= pass_number <= self.num_passes:
raise InvalidPassError(
'illegal value (%d) for pass number. Must be 1 through %d or\n'
'the name of a known pass.'
% (pass_number,self.num_passes,))
return pass_number
except ValueError:
# Is pass_name the name of one of the passes?
for (i, the_pass) in enumerate(self.passes):
if the_pass.name == pass_name:
return i + 1
raise InvalidPassError('Unknown pass name (%r).' % (pass_name,))
def run(self, run_options):
"""Run the specified passes, one after another.
RUN_OPTIONS will be passed to the Passes' run() methods.
RUN_OPTIONS.start_pass is the number of the first pass that should
be run. RUN_OPTIONS.end_pass is the number of the last pass that
should be run. It must be that 1 <= RUN_OPTIONS.start_pass <=
RUN_OPTIONS.end_pass <= self.num_passes."""
# Convert start_pass and end_pass into the indices of the passes
# to execute, using the Python index range convention (i.e., first
# pass executed and first pass *after* the ones that should be
# executed).
index_start = run_options.start_pass - 1
index_end = run_options.end_pass
# Inform the artifact manager when artifacts are created and used:
for (i, the_pass) in enumerate(self.passes):
the_pass.register_artifacts()
# Each pass creates a new version of the statistics file:
artifact_manager.register_temp_file(
config.STATISTICS_FILE % (i + 1,), the_pass
)
if i != 0:
# Each pass subsequent to the first reads the statistics file
# from the preceding pass:
artifact_manager.register_temp_file_needed(
config.STATISTICS_FILE % (i + 1 - 1,), the_pass
)
# Tell the artifact manager about passes that are being skipped this run:
for the_pass in self.passes[0:index_start]:
artifact_manager.pass_skipped(the_pass)
start_time = time.time()
for i in range(index_start, index_end):
the_pass = self.passes[i]
logger.quiet('----- pass %d (%s) -----' % (i + 1, the_pass.name,))
artifact_manager.pass_started(the_pass)
if i == 0:
stats_keeper = StatsKeeper()
else:
stats_keeper = read_stats_keeper(
artifact_manager.get_temp_file(
config.STATISTICS_FILE % (i + 1 - 1,)
)
)
the_pass.run(run_options, stats_keeper)
end_time = time.time()
stats_keeper.log_duration_for_pass(
end_time - start_time, i + 1, the_pass.name
)
logger.normal(stats_keeper.single_pass_timing(i + 1))
stats_keeper.archive(
artifact_manager.get_temp_file(config.STATISTICS_FILE % (i + 1,))
)
start_time = end_time
Ctx().clean()
# Allow the artifact manager to clean up artifacts that are no
# longer needed:
artifact_manager.pass_done(the_pass, Ctx().skip_cleanup)
check_for_garbage()
# Tell the artifact manager about passes that are being deferred:
for the_pass in self.passes[index_end:]:
artifact_manager.pass_deferred(the_pass)
logger.quiet(stats_keeper)
logger.normal(stats_keeper.timings())
# Consistency check:
artifact_manager.check_clean()
def help_passes(self):
"""Output (to sys.stdout) the indices and names of available passes."""
print 'PASSES:'
for (i, the_pass) in enumerate(self.passes):
print '%5d : %s' % (i + 1, the_pass.name,)
|