1
# Copyright (C) 2008 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 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 General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Processor of import commands.
19
This module provides core processing functionality including an abstract class
20
for basing real processors on. See the processors package for examples.
26
from bzrlib import debug
27
from bzrlib.errors import NotBranchError
28
from bzrlib.trace import (
36
class ImportProcessor(object):
37
"""Base class for import processors.
39
Subclasses should override the pre_*, post_* and *_handler
40
methods as appropriate.
45
def __init__(self, bzrdir, params=None, verbose=False, outf=None):
47
self.outf = sys.stdout
50
self.verbose = verbose
55
self.validate_parameters()
58
# Some 'importers' don't need a repository to write to
59
self.working_tree = None
64
# Might be inside a branch
65
(self.working_tree, self.branch) = bzrdir._get_tree_branch()
66
self.repo = self.branch.repository
67
except NotBranchError:
68
# Must be inside a repository
69
self.working_tree = None
71
self.repo = bzrdir.open_repository()
73
# Handlers can set this to request exiting cleanly without
74
# iterating through the remaining commands
77
def validate_parameters(self):
78
"""Validate that the parameters are correctly specified."""
80
if p not in self.known_params:
81
raise errors.UnknownParameter(p, self.known_params)
83
def process(self, command_iter):
84
"""Import data into Bazaar by processing a stream of commands.
86
:param command_iter: an iterator providing commands
88
if self.working_tree is not None:
89
self.working_tree.lock_write()
90
elif self.branch is not None:
91
self.branch.lock_write()
92
elif self.repo is not None:
93
self.repo.lock_write()
95
self._process(command_iter)
97
# If an unhandled exception occurred, abort the write group
98
if self.repo is not None and self.repo.is_in_write_group():
99
self.repo.abort_write_group()
101
if self.working_tree is not None:
102
self.working_tree.unlock()
103
elif self.branch is not None:
105
elif self.repo is not None:
108
def _process(self, command_iter):
110
for cmd in command_iter():
112
handler = self.__class__.__dict__[cmd.name + "_handler"]
114
raise errors.MissingHandler(cmd.name)
116
self.pre_handler(cmd)
118
self.post_handler(cmd)
123
def note(self, msg, *args):
124
"""Output a note but timestamp it."""
125
msg = "%s %s" % (self._time_of_day(), msg)
128
def warning(self, msg, *args):
129
"""Output a warning but timestamp it."""
130
msg = "%s WARNING: %s" % (self._time_of_day(), msg)
133
def debug(self, mgs, *args):
134
"""Output a debug message if the appropriate -D option was given."""
135
if "fast-import" in debug.debug_flags:
136
msg = "%s DEBUG: %s" % (self._time_of_day(), msg)
139
def _time_of_day(self):
140
"""Time of day as a string."""
141
# Note: this is a separate method so tests can patch in a fixed value
142
return time.strftime("%H:%M:%S")
144
def pre_process(self):
145
"""Hook for logic at start of processing."""
148
def post_process(self):
149
"""Hook for logic at end of processing."""
152
def pre_handler(self, cmd):
153
"""Hook for logic before each handler starts."""
156
def post_handler(self, cmd):
157
"""Hook for logic after each handler finishes."""
160
def progress_handler(self, cmd):
161
"""Process a ProgressCommand."""
162
raise NotImplementedError(self.progress_handler)
164
def blob_handler(self, cmd):
165
"""Process a BlobCommand."""
166
raise NotImplementedError(self.blob_handler)
168
def checkpoint_handler(self, cmd):
169
"""Process a CheckpointCommand."""
170
raise NotImplementedError(self.checkpoint_handler)
172
def commit_handler(self, cmd):
173
"""Process a CommitCommand."""
174
raise NotImplementedError(self.commit_handler)
176
def reset_handler(self, cmd):
177
"""Process a ResetCommand."""
178
raise NotImplementedError(self.reset_handler)
180
def tag_handler(self, cmd):
181
"""Process a TagCommand."""
182
raise NotImplementedError(self.tag_handler)
184
def feature_handler(self, cmd):
185
"""Process a FeatureCommand."""
186
raise NotImplementedError(self.feature_handler)
189
class CommitHandler(object):
190
"""Base class for commit handling.
192
Subclasses should override the pre_*, post_* and *_handler
193
methods as appropriate.
196
def __init__(self, command):
197
self.command = command
200
self.pre_process_files()
201
for fc in self.command.file_iter():
203
handler = self.__class__.__dict__[fc.name[4:] + "_handler"]
205
raise errors.MissingHandler(fc.name)
208
self.post_process_files()
210
def note(self, msg, *args):
211
"""Output a note but add context."""
212
msg = "%s (%s)" % (msg, self.command.id)
215
def warning(self, msg, *args):
216
"""Output a warning but add context."""
217
msg = "WARNING: %s (%s)" % (msg, self.command.id)
220
def mutter(self, msg, *args):
221
"""Output a mutter but add context."""
222
msg = "%s (%s)" % (msg, self.command.id)
225
def debug(self, msg, *args):
226
"""Output a mutter if the appropriate -D option was given."""
227
if "fast-import" in debug.debug_flags:
228
msg = "%s (%s)" % (msg, self.command.id)
231
def pre_process_files(self):
232
"""Prepare for committing."""
235
def post_process_files(self):
236
"""Save the revision."""
239
def modify_handler(self, filecmd):
240
"""Handle a filemodify command."""
241
raise NotImplementedError(self.modify_handler)
243
def delete_handler(self, filecmd):
244
"""Handle a filedelete command."""
245
raise NotImplementedError(self.delete_handler)
247
def copy_handler(self, filecmd):
248
"""Handle a filecopy command."""
249
raise NotImplementedError(self.copy_handler)
251
def rename_handler(self, filecmd):
252
"""Handle a filerename command."""
253
raise NotImplementedError(self.rename_handler)
255
def deleteall_handler(self, filecmd):
256
"""Handle a filedeleteall command."""
257
raise NotImplementedError(self.deleteall_handler)