/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

fix date parsing bug found while importing samba

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, outf=None):
 
46
        if outf is None:
 
47
            self.outf = sys.stdout
 
48
        else:
 
49
            self.outf = outf
 
50
        self.verbose = verbose
 
51
        if params is None:
 
52
            self.params = {}
 
53
        else:
 
54
            self.params = params
 
55
            self.validate_parameters()
 
56
        self.bzrdir = bzrdir
 
57
        if bzrdir is None:
 
58
            # Some 'importers' don't need a repository to write to
 
59
            self.working_tree = None
 
60
            self.branch = None
 
61
            self.repo = None
 
62
        else:
 
63
            try:
 
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
 
70
                self.branch = None
 
71
                self.repo = bzrdir.open_repository()
 
72
 
 
73
        # Handlers can set this to request exiting cleanly without
 
74
        # iterating through the remaining commands
 
75
        self.finished = False
 
76
 
 
77
    def validate_parameters(self):
 
78
        """Validate that the parameters are correctly specified."""
 
79
        for p in self.params:
 
80
            if p not in self.known_params:
 
81
                raise errors.UnknownParameter(p, self.known_params)
 
82
 
 
83
    def process(self, command_iter):
 
84
        """Import data into Bazaar by processing a stream of commands.
 
85
 
 
86
        :param command_iter: an iterator providing commands
 
87
        """
 
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()
 
94
        try:
 
95
            self._process(command_iter)
 
96
        finally:
 
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()
 
100
            # Release the locks
 
101
            if self.working_tree is not None:
 
102
                self.working_tree.unlock()
 
103
            elif self.branch is not None:
 
104
                self.branch.unlock()
 
105
            elif self.repo is not None:
 
106
                self.repo.unlock()
 
107
 
 
108
    def _process(self, command_iter):
 
109
        self.pre_process()
 
110
        for cmd in command_iter():
 
111
            try:
 
112
                handler = self.__class__.__dict__[cmd.name + "_handler"]
 
113
            except KeyError:
 
114
                raise errors.MissingHandler(cmd.name)
 
115
            else:
 
116
                self.pre_handler(cmd)
 
117
                handler(self, cmd)
 
118
                self.post_handler(cmd)
 
119
            if self.finished:
 
120
                break
 
121
        self.post_process()
 
122
 
 
123
    def note(self, msg, *args):
 
124
        """Output a note but timestamp it."""
 
125
        msg = "%s %s" % (self._time_of_day(), msg)
 
126
        note(msg, *args)
 
127
 
 
128
    def warning(self, msg, *args):
 
129
        """Output a warning but timestamp it."""
 
130
        msg = "%s WARNING: %s" % (self._time_of_day(), msg)
 
131
        warning(msg, *args)
 
132
 
 
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)
 
137
            mutter(msg, *args)
 
138
 
 
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")
 
143
 
 
144
    def pre_process(self):
 
145
        """Hook for logic at start of processing."""
 
146
        pass
 
147
 
 
148
    def post_process(self):
 
149
        """Hook for logic at end of processing."""
 
150
        pass
 
151
 
 
152
    def pre_handler(self, cmd):
 
153
        """Hook for logic before each handler starts."""
 
154
        pass
 
155
 
 
156
    def post_handler(self, cmd):
 
157
        """Hook for logic after each handler finishes."""
 
158
        pass
 
159
 
 
160
    def progress_handler(self, cmd):
 
161
        """Process a ProgressCommand."""
 
162
        raise NotImplementedError(self.progress_handler)
 
163
 
 
164
    def blob_handler(self, cmd):
 
165
        """Process a BlobCommand."""
 
166
        raise NotImplementedError(self.blob_handler)
 
167
 
 
168
    def checkpoint_handler(self, cmd):
 
169
        """Process a CheckpointCommand."""
 
170
        raise NotImplementedError(self.checkpoint_handler)
 
171
 
 
172
    def commit_handler(self, cmd):
 
173
        """Process a CommitCommand."""
 
174
        raise NotImplementedError(self.commit_handler)
 
175
 
 
176
    def reset_handler(self, cmd):
 
177
        """Process a ResetCommand."""
 
178
        raise NotImplementedError(self.reset_handler)
 
179
 
 
180
    def tag_handler(self, cmd):
 
181
        """Process a TagCommand."""
 
182
        raise NotImplementedError(self.tag_handler)
 
183
 
 
184
    def feature_handler(self, cmd):
 
185
        """Process a FeatureCommand."""
 
186
        raise NotImplementedError(self.feature_handler)
 
187
 
 
188
 
 
189
class CommitHandler(object):
 
190
    """Base class for commit handling.
 
191
    
 
192
    Subclasses should override the pre_*, post_* and *_handler
 
193
    methods as appropriate.
 
194
    """
 
195
 
 
196
    def __init__(self, command):
 
197
        self.command = command
 
198
 
 
199
    def process(self):
 
200
        self.pre_process_files()
 
201
        for fc in self.command.file_iter():
 
202
            try:
 
203
                handler = self.__class__.__dict__[fc.name[4:] + "_handler"]
 
204
            except KeyError:
 
205
                raise errors.MissingHandler(fc.name)
 
206
            else:
 
207
                handler(self, fc)
 
208
        self.post_process_files()
 
209
 
 
210
    def note(self, msg, *args):
 
211
        """Output a note but add context."""
 
212
        msg = "%s (%s)" % (msg, self.command.id)
 
213
        note(msg, *args)
 
214
 
 
215
    def warning(self, msg, *args):
 
216
        """Output a warning but add context."""
 
217
        msg = "WARNING: %s (%s)" % (msg, self.command.id)
 
218
        warning(msg, *args)
 
219
 
 
220
    def mutter(self, msg, *args):
 
221
        """Output a mutter but add context."""
 
222
        msg = "%s (%s)" % (msg, self.command.id)
 
223
        mutter(msg, *args)
 
224
 
 
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)
 
229
            mutter(msg, *args)
 
230
 
 
231
    def pre_process_files(self):
 
232
        """Prepare for committing."""
 
233
        pass
 
234
 
 
235
    def post_process_files(self):
 
236
        """Save the revision."""
 
237
        pass
 
238
 
 
239
    def modify_handler(self, filecmd):
 
240
        """Handle a filemodify command."""
 
241
        raise NotImplementedError(self.modify_handler)
 
242
 
 
243
    def delete_handler(self, filecmd):
 
244
        """Handle a filedelete command."""
 
245
        raise NotImplementedError(self.delete_handler)
 
246
 
 
247
    def copy_handler(self, filecmd):
 
248
        """Handle a filecopy command."""
 
249
        raise NotImplementedError(self.copy_handler)
 
250
 
 
251
    def rename_handler(self, filecmd):
 
252
        """Handle a filerename command."""
 
253
        raise NotImplementedError(self.rename_handler)
 
254
 
 
255
    def deleteall_handler(self, filecmd):
 
256
        """Handle a filedeleteall command."""
 
257
        raise NotImplementedError(self.deleteall_handler)