/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to processor.py

  • Committer: Ian Clatworthy
  • Date: 2009-02-18 01:09:34 UTC
  • mto: (0.64.117 trunk)
  • mto: This revision was merged to the branch mainline in revision 6631.
  • Revision ID: ian.clatworthy@canonical.com-20090218010934-dn6xdnq78u1egdf7
move escape_commit_message into helpers

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2008 Canonical Ltd
 
2
#
 
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.
 
7
#
 
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.
 
12
#
 
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
 
16
 
 
17
"""Processor of import commands.
 
18
 
 
19
This module provides core processing functionality including an abstract class
 
20
for basing real processors on. See the processors package for examples.
 
21
"""
 
22
 
 
23
import sys
 
24
import time
 
25
 
 
26
from bzrlib import debug
 
27
from bzrlib.errors import NotBranchError
 
28
from bzrlib.trace import (
 
29
    mutter,
 
30
    note,
 
31
    warning,
 
32
    )
 
33
import errors
 
34
 
 
35
 
 
36
class ImportProcessor(object):
 
37
    """Base class for import processors.
 
38
    
 
39
    Subclasses should override the pre_*, post_* and *_handler
 
40
    methods as appropriate.
 
41
    """
 
42
 
 
43
    known_params = []
 
44
 
 
45
    def __init__(self, bzrdir, params=None, verbose=False):
 
46
        self.outf = sys.stdout
 
47
        self.verbose = verbose
 
48
        if params is None:
 
49
            self.params = {}
 
50
        else:
 
51
            self.params = params
 
52
            self.validate_parameters()
 
53
        self.bzrdir = bzrdir
 
54
        if bzrdir is None:
 
55
            # Some 'importers' don't need a repository to write to
 
56
            self.working_tree = None
 
57
            self.branch = None
 
58
            self.repo = None
 
59
        else:
 
60
            try:
 
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
 
67
                self.branch = None
 
68
                self.repo = bzrdir.open_repository()
 
69
 
 
70
        # Handlers can set this to request exiting cleanly without
 
71
        # iterating through the remaining commands
 
72
        self.finished = False
 
73
 
 
74
    def validate_parameters(self):
 
75
        """Validate that the parameters are correctly specified."""
 
76
        for p in self.params:
 
77
            if p not in self.known_params:
 
78
                raise errors.UnknownParameter(p, self.known_params)
 
79
 
 
80
    def process(self, command_iter):
 
81
        """Import data into Bazaar by processing a stream of commands.
 
82
 
 
83
        :param command_iter: an iterator providing commands
 
84
        """
 
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()
 
91
        try:
 
92
            self._process(command_iter)
 
93
        finally:
 
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()
 
97
            # Release the locks
 
98
            if self.working_tree is not None:
 
99
                self.working_tree.unlock()
 
100
            elif self.branch is not None:
 
101
                self.branch.unlock()
 
102
            elif self.repo is not None:
 
103
                self.repo.unlock()
 
104
 
 
105
    def _process(self, command_iter):
 
106
        self.pre_process()
 
107
        for cmd in command_iter():
 
108
            try:
 
109
                handler = self.__class__.__dict__[cmd.name + "_handler"]
 
110
            except KeyError:
 
111
                raise errors.MissingHandler(cmd.name)
 
112
            else:
 
113
                self.pre_handler(cmd)
 
114
                handler(self, cmd)
 
115
                self.post_handler(cmd)
 
116
            if self.finished:
 
117
                break
 
118
        self.post_process()
 
119
 
 
120
    def note(self, msg, *args):
 
121
        """Output a note but timestamp it."""
 
122
        msg = "%s %s" % (self._time_of_day(), msg)
 
123
        note(msg, *args)
 
124
 
 
125
    def warning(self, msg, *args):
 
126
        """Output a warning but timestamp it."""
 
127
        msg = "%s WARNING: %s" % (self._time_of_day(), msg)
 
128
        warning(msg, *args)
 
129
 
 
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)
 
134
            mutter(msg, *args)
 
135
 
 
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")
 
140
 
 
141
    def pre_process(self):
 
142
        """Hook for logic at start of processing."""
 
143
        pass
 
144
 
 
145
    def post_process(self):
 
146
        """Hook for logic at end of processing."""
 
147
        pass
 
148
 
 
149
    def pre_handler(self, cmd):
 
150
        """Hook for logic before each handler starts."""
 
151
        pass
 
152
 
 
153
    def post_handler(self, cmd):
 
154
        """Hook for logic after each handler finishes."""
 
155
        pass
 
156
 
 
157
    def progress_handler(self, cmd):
 
158
        """Process a ProgressCommand."""
 
159
        raise NotImplementedError(self.progress_handler)
 
160
 
 
161
    def blob_handler(self, cmd):
 
162
        """Process a BlobCommand."""
 
163
        raise NotImplementedError(self.blob_handler)
 
164
 
 
165
    def checkpoint_handler(self, cmd):
 
166
        """Process a CheckpointCommand."""
 
167
        raise NotImplementedError(self.checkpoint_handler)
 
168
 
 
169
    def commit_handler(self, cmd):
 
170
        """Process a CommitCommand."""
 
171
        raise NotImplementedError(self.commit_handler)
 
172
 
 
173
    def reset_handler(self, cmd):
 
174
        """Process a ResetCommand."""
 
175
        raise NotImplementedError(self.reset_handler)
 
176
 
 
177
    def tag_handler(self, cmd):
 
178
        """Process a TagCommand."""
 
179
        raise NotImplementedError(self.tag_handler)
 
180
 
 
181
 
 
182
class CommitHandler(object):
 
183
    """Base class for commit handling.
 
184
    
 
185
    Subclasses should override the pre_*, post_* and *_handler
 
186
    methods as appropriate.
 
187
    """
 
188
 
 
189
    def __init__(self, command):
 
190
        self.command = command
 
191
 
 
192
    def process(self):
 
193
        self.pre_process_files()
 
194
        for fc in self.command.file_iter():
 
195
            try:
 
196
                handler = self.__class__.__dict__[fc.name[4:] + "_handler"]
 
197
            except KeyError:
 
198
                raise errors.MissingHandler(fc.name)
 
199
            else:
 
200
                handler(self, fc)
 
201
        self.post_process_files()
 
202
 
 
203
    def note(self, msg, *args):
 
204
        """Output a note but add context."""
 
205
        msg = "%s (%s)" % (msg, self.command.id)
 
206
        note(msg, *args)
 
207
 
 
208
    def warning(self, msg, *args):
 
209
        """Output a warning but add context."""
 
210
        msg = "WARNING: %s (%s)" % (msg, self.command.id)
 
211
        warning(msg, *args)
 
212
 
 
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)
 
217
            mutter(msg, *args)
 
218
 
 
219
    def pre_process_files(self):
 
220
        """Prepare for committing."""
 
221
        pass
 
222
 
 
223
    def post_process_files(self):
 
224
        """Save the revision."""
 
225
        pass
 
226
 
 
227
    def modify_handler(self, filecmd):
 
228
        """Handle a filemodify command."""
 
229
        raise NotImplementedError(self.modify_handler)
 
230
 
 
231
    def delete_handler(self, filecmd):
 
232
        """Handle a filedelete command."""
 
233
        raise NotImplementedError(self.delete_handler)
 
234
 
 
235
    def copy_handler(self, filecmd):
 
236
        """Handle a filecopy command."""
 
237
        raise NotImplementedError(self.copy_handler)
 
238
 
 
239
    def rename_handler(self, filecmd):
 
240
        """Handle a filerename command."""
 
241
        raise NotImplementedError(self.rename_handler)
 
242
 
 
243
    def deleteall_handler(self, filecmd):
 
244
        """Handle a filedeleteall command."""
 
245
        raise NotImplementedError(self.deleteall_handler)