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):
46
self.outf = sys.stdout
47
self.verbose = verbose
52
self.validate_parameters()
55
# Some 'importers' don't need a repository to write to
56
self.working_tree = None
61
# Might be inside a branch
62
(self.working_tree, self.branch) = bzrdir._get_tree_branch()
63
self.repo = self.branch.repository
64
except NotBranchError:
65
# Must be inside a repository
66
self.working_tree = None
68
self.repo = bzrdir.open_repository()
70
# Handlers can set this to request exiting cleanly without
71
# iterating through the remaining commands
74
def validate_parameters(self):
75
"""Validate that the parameters are correctly specified."""
77
if p not in self.known_params:
78
raise errors.UnknownParameter(p, self.known_params)
80
def process(self, command_iter):
81
"""Import data into Bazaar by processing a stream of commands.
83
:param command_iter: an iterator providing commands
85
if self.working_tree is not None:
86
self.working_tree.lock_write()
87
elif self.branch is not None:
88
self.branch.lock_write()
89
elif self.repo is not None:
90
self.repo.lock_write()
92
self._process(command_iter)
94
# If an unhandled exception occurred, abort the write group
95
if self.repo is not None and self.repo.is_in_write_group():
96
self.repo.abort_write_group()
98
if self.working_tree is not None:
99
self.working_tree.unlock()
100
elif self.branch is not None:
102
elif self.repo is not None:
105
def _process(self, command_iter):
107
for cmd in command_iter():
109
handler = self.__class__.__dict__[cmd.name + "_handler"]
111
raise errors.MissingHandler(cmd.name)
113
self.pre_handler(cmd)
115
self.post_handler(cmd)
120
def note(self, msg, *args):
121
"""Output a note but timestamp it."""
122
msg = "%s %s" % (self._time_of_day(), msg)
125
def warning(self, msg, *args):
126
"""Output a warning but timestamp it."""
127
msg = "%s WARNING: %s" % (self._time_of_day(), msg)
130
def debug(self, mgs, *args):
131
"""Output a debug message if the appropriate -D option was given."""
132
if "fast-import" in debug.debug_flags:
133
msg = "%s DEBUG: %s" % (self._time_of_day(), msg)
136
def _time_of_day(self):
137
"""Time of day as a string."""
138
# Note: this is a separate method so tests can patch in a fixed value
139
return time.strftime("%H:%M:%S")
141
def pre_process(self):
142
"""Hook for logic at start of processing."""
145
def post_process(self):
146
"""Hook for logic at end of processing."""
149
def pre_handler(self, cmd):
150
"""Hook for logic before each handler starts."""
153
def post_handler(self, cmd):
154
"""Hook for logic after each handler finishes."""
157
def progress_handler(self, cmd):
158
"""Process a ProgressCommand."""
159
raise NotImplementedError(self.progress_handler)
161
def blob_handler(self, cmd):
162
"""Process a BlobCommand."""
163
raise NotImplementedError(self.blob_handler)
165
def checkpoint_handler(self, cmd):
166
"""Process a CheckpointCommand."""
167
raise NotImplementedError(self.checkpoint_handler)
169
def commit_handler(self, cmd):
170
"""Process a CommitCommand."""
171
raise NotImplementedError(self.commit_handler)
173
def reset_handler(self, cmd):
174
"""Process a ResetCommand."""
175
raise NotImplementedError(self.reset_handler)
177
def tag_handler(self, cmd):
178
"""Process a TagCommand."""
179
raise NotImplementedError(self.tag_handler)
182
class CommitHandler(object):
183
"""Base class for commit handling.
185
Subclasses should override the pre_*, post_* and *_handler
186
methods as appropriate.
189
def __init__(self, command):
190
self.command = command
193
self.pre_process_files()
194
for fc in self.command.file_iter():
196
handler = self.__class__.__dict__[fc.name[4:] + "_handler"]
198
raise errors.MissingHandler(fc.name)
201
self.post_process_files()
203
def note(self, msg, *args):
204
"""Output a note but add context."""
205
msg = "%s (%s)" % (msg, self.command.id)
208
def warning(self, msg, *args):
209
"""Output a warning but add context."""
210
msg = "WARNING: %s (%s)" % (msg, self.command.id)
213
def debug(self, msg, *args):
214
"""Output a mutter if the appropriate -D option was given."""
215
if "fast-import" in debug.debug_flags:
216
msg = "%s (%s)" % (msg, self.command.id)
219
def pre_process_files(self):
220
"""Prepare for committing."""
223
def post_process_files(self):
224
"""Save the revision."""
227
def modify_handler(self, filecmd):
228
"""Handle a filemodify command."""
229
raise NotImplementedError(self.modify_handler)
231
def delete_handler(self, filecmd):
232
"""Handle a filedelete command."""
233
raise NotImplementedError(self.delete_handler)
235
def copy_handler(self, filecmd):
236
"""Handle a filecopy command."""
237
raise NotImplementedError(self.copy_handler)
239
def rename_handler(self, filecmd):
240
"""Handle a filerename command."""
241
raise NotImplementedError(self.rename_handler)
243
def deleteall_handler(self, filecmd):
244
"""Handle a filedeleteall command."""
245
raise NotImplementedError(self.deleteall_handler)