/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
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
"""Import processor that supports all Bazaar repository formats."""
18
19
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
20
import re
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
21
import time
0.64.5 by Ian Clatworthy
first cut at generic processing method
22
from bzrlib import (
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
23
    delta,
0.64.5 by Ian Clatworthy
first cut at generic processing method
24
    errors,
25
    generate_ids,
26
    inventory,
27
    lru_cache,
28
    osutils,
29
    revision,
30
    revisiontree,
31
    )
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
32
from bzrlib.trace import (
33
    note,
34
    warning,
35
    )
0.64.5 by Ian Clatworthy
first cut at generic processing method
36
from bzrlib.plugins.fastimport import (
37
    processor,
38
    revisionloader,
39
    )
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
40
41
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
42
def _single_plural(n, single, plural):
43
    """Return a single or plural form of a noun based on number."""
44
    if n == 1:
45
        return single
46
    else:
47
        return plural
48
49
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
50
class GenericProcessor(processor.ImportProcessor):
51
    """An import processor that handles basic imports.
52
53
    Current features supported:
54
0.64.5 by Ian Clatworthy
first cut at generic processing method
55
    * timestamped progress reporting
0.64.16 by Ian Clatworthy
safe processing tweaks
56
    * blobs are cached in memory
57
    * commits are processed
58
    * tags are stored in the current branch
59
    * LATER: named branch support
60
    * checkpoints are ignored
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
61
    * some basic statistics are dumped on completion.
62
    """
63
64
    def pre_process(self):
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
65
        self.cache_mgr = GenericCacheManager()
0.64.7 by Ian Clatworthy
start of multiple commit handling
66
        self.active_branch = self.branch
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
67
        self.init_stats()
0.64.11 by Ian Clatworthy
tag support
68
        # mapping of tag name to revision_id
69
        self.tags = {}
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
70
71
    def post_process(self):
72
        self.dump_stats()
0.64.7 by Ian Clatworthy
start of multiple commit handling
73
        # Update the branches, assuming the last revision is the head
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
74
        note("Updating branch information ...")
0.64.7 by Ian Clatworthy
start of multiple commit handling
75
        # TODO - loop over the branches created/modified
76
        last_rev_id = self.cache_mgr.last_revision_ids[self.branch]
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
77
        revno = len(list(self.repo.iter_reverse_revision_history(last_rev_id)))
78
        self.branch.set_last_revision_info(revno, last_rev_id)
0.64.11 by Ian Clatworthy
tag support
79
        if self.tags:
80
            self.branch.tags._set_tag_dict(self.tags)
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
81
        # Update the working tree, if any
82
        if self.working_tree:
83
            self.working_tree.update(delta._ChangeReporter())
84
85
    def init_stats(self):
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
86
        self._revision_count = 0
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
87
        self._branch_count = 1
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
88
        self._tag_count = 0
0.64.5 by Ian Clatworthy
first cut at generic processing method
89
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
90
    def dump_stats(self):
91
        rc = self._revision_count
92
        bc = self._branch_count
93
        tc = self._tag_count
94
        note("Imported %d %s into %d %s with %d %s.",
95
            rc, _single_plural(rc, "revision", "revisions"),
96
            bc, _single_plural(bc, "branch", "branches"),
97
            tc, _single_plural(tc, "tag", "tags"))
0.64.5 by Ian Clatworthy
first cut at generic processing method
98
99
    def blob_handler(self, cmd):
100
        """Process a BlobCommand."""
101
        if cmd.mark is not None:
102
            dataref = ":%s" % (cmd.mark,)
103
        else:
104
            dataref = osutils.sha_strings(cmd.data)
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
105
        self.cache_mgr.blobs[dataref] = cmd.data
0.64.5 by Ian Clatworthy
first cut at generic processing method
106
107
    def checkpoint_handler(self, cmd):
108
        """Process a CheckpointCommand."""
109
        warning("ignoring checkpoint")
110
111
    def commit_handler(self, cmd):
112
        """Process a CommitCommand."""
0.64.7 by Ian Clatworthy
start of multiple commit handling
113
        handler = GenericCommitHandler(cmd, self.repo, self.cache_mgr,
0.64.14 by Ian Clatworthy
commit of modified files working
114
            self.active_branch, self.verbose)
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
115
        # For now, put a write group around every commit. In the future,
116
        # we might only start/commit one every N to sppeed things up
117
        self.repo.start_write_group()
118
        try:
119
            handler.process()
0.64.16 by Ian Clatworthy
safe processing tweaks
120
            rev_id = handler.revision_id
121
            self.cache_mgr.revision_ids[cmd.ref] = rev_id
122
            if cmd.mark is not None:
123
                self.cache_mgr.revision_ids[":" + cmd.mark] = rev_id
124
            self.cache_mgr.last_revision_ids[self.active_branch] = rev_id
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
125
            self._revision_count += 1
0.64.18 by Ian Clatworthy
timestamp loaded commit messages
126
            note("%s loaded commit %d (%s)" % (self._time_of_day(),
127
                self._revision_count, cmd.mark or cmd.ref))
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
128
        except:
129
            self.repo.abort_write_group()
130
            raise
131
        else:
132
            self.repo.commit_write_group()
0.64.1 by Ian Clatworthy
1st cut: gfi parser + --info processing method
133
134
    def progress_handler(self, cmd):
135
        """Process a ProgressCommand."""
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
136
        # We could use a progress bar here but timestamped messages
137
        # is more useful for determining when things might complete
0.64.5 by Ian Clatworthy
first cut at generic processing method
138
        note("%s progress %s" % (self._time_of_day(), cmd.message))
139
140
    def _time_of_day(self):
141
        """Time of day as a string."""
142
        # Note: this is a separate method so tests can patch in a fixed value
0.64.18 by Ian Clatworthy
timestamp loaded commit messages
143
        return time.strftime("%H:%M:%S")
0.64.5 by Ian Clatworthy
first cut at generic processing method
144
145
    def reset_handler(self, cmd):
146
        """Process a ResetCommand."""
0.64.12 by Ian Clatworthy
lightweight tags, filter processor and param validation
147
        if cmd.ref.startswith('refs/tags/'):
148
            self._set_tag(cmd.ref[len('refs/tags/'):], cmd.from_)
149
        else:
0.64.16 by Ian Clatworthy
safe processing tweaks
150
            warning("named branches are not supported yet"
151
                " - ignoring reset of '%s'", cmd.ref)
0.64.5 by Ian Clatworthy
first cut at generic processing method
152
153
    def tag_handler(self, cmd):
154
        """Process a TagCommand."""
0.64.12 by Ian Clatworthy
lightweight tags, filter processor and param validation
155
        self._set_tag(cmd.id, cmd.from_)
156
157
    def _set_tag(self, name, from_):
158
        """Define a tag given a name an import 'from' reference."""
159
        bzr_tag_name = name.decode('utf-8', 'replace')
160
        bzr_rev_id = self.cache_mgr.revision_ids[from_]
0.64.11 by Ian Clatworthy
tag support
161
        self.tags[bzr_tag_name] = bzr_rev_id
162
        self._tag_count += 1
0.64.5 by Ian Clatworthy
first cut at generic processing method
163
164
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
165
class GenericCacheManager(object):
166
    """A manager of caches for the GenericProcessor."""
167
168
    def __init__(self, inventory_cache_size=100):
169
        # dataref -> data. datref is either :mark or the sha-1.
170
        self.blobs = {}
171
172
        # revision-id -> Inventory cache
173
        # these are large and we probably don't need too many as
174
        # most parents are recent in history
175
        self.inventories = lru_cache.LRUCache(inventory_cache_size)
176
177
        # directory-path -> inventory-entry lookup table
178
        # we need to keep all of these but they are small
179
        self.directory_entries = {}
180
181
        # import-ref -> revision-id lookup table
182
        # we need to keep all of these but they are small
183
        self.revision_ids = {}
184
0.64.7 by Ian Clatworthy
start of multiple commit handling
185
        # branch -> last revision-id lookup table
186
        self.last_revision_ids = {}
187
0.64.14 by Ian Clatworthy
commit of modified files working
188
        # path -> file-ids
189
        self.file_ids = {}
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
190
0.64.16 by Ian Clatworthy
safe processing tweaks
191
    def _delete_path(self, path):
192
        """Remove a path from caches."""
193
        del self.file_ids[path]
194
195
    def _rename_path(self, old_path, new_path):
196
        """Rename a path in the caches."""
197
        self.file_ids[new_path] = self.file_ids[old_path]
198
        del self.file_ids[old_path]
199
200
0.64.5 by Ian Clatworthy
first cut at generic processing method
201
class GenericCommitHandler(processor.CommitHandler):
202
0.64.14 by Ian Clatworthy
commit of modified files working
203
    def __init__(self, command, repo, cache_mgr, active_branch, verbose=False):
0.64.5 by Ian Clatworthy
first cut at generic processing method
204
        processor.CommitHandler.__init__(self, command)
205
        self.repo = repo
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
206
        self.cache_mgr = cache_mgr
0.64.7 by Ian Clatworthy
start of multiple commit handling
207
        self.active_branch = active_branch
0.64.14 by Ian Clatworthy
commit of modified files working
208
        self.verbose = verbose
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
209
        # smart loader that uses these caches
0.64.5 by Ian Clatworthy
first cut at generic processing method
210
        self.loader = revisionloader.RevisionLoader(repo,
211
            lambda revision_ids: self._get_inventories(revision_ids))
212
213
    def pre_process_files(self):
214
        """Prepare for committing."""
215
        self.revision_id = self.gen_revision_id()
216
        self.inv_delta = []
217
        # cache of texts for this commit, indexed by file-id
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
218
        self.lines_for_commit = {}
0.64.5 by Ian Clatworthy
first cut at generic processing method
219
0.64.14 by Ian Clatworthy
commit of modified files working
220
        # Get the parent inventories
0.64.7 by Ian Clatworthy
start of multiple commit handling
221
        if self.command.parents:
0.64.14 by Ian Clatworthy
commit of modified files working
222
            self.parents = [self.cache_mgr.revision_ids[ref]
0.64.7 by Ian Clatworthy
start of multiple commit handling
223
                for ref in self.command.parents]
224
        else:
225
            # if no parents are given, the last revision on
226
            # the current branch is assumed according to the spec
227
            last_rev = self.cache_mgr.last_revision_ids.get(
228
                    self.active_branch)
229
            if last_rev:
0.64.14 by Ian Clatworthy
commit of modified files working
230
                self.parents = [last_rev]
0.64.7 by Ian Clatworthy
start of multiple commit handling
231
            else:
0.64.14 by Ian Clatworthy
commit of modified files working
232
                self.parents = []
0.64.7 by Ian Clatworthy
start of multiple commit handling
233
0.64.14 by Ian Clatworthy
commit of modified files working
234
        # Seed the inventory from the previous one
235
        if len(self.parents) == 0:
236
            self.inventory = self.gen_initial_inventory()
0.64.5 by Ian Clatworthy
first cut at generic processing method
237
        else:
238
            # use the bzr_revision_id to lookup the inv cache
0.64.14 by Ian Clatworthy
commit of modified files working
239
            self.inventory = self.get_inventory(self.parents[0]).copy()
0.64.13 by Ian Clatworthy
commit of new files working
240
        if not self.repo.supports_rich_root():
241
            # In this repository, root entries have no knit or weave. When
242
            # serializing out to disk and back in, root.revision is always
243
            # the new revision_id.
0.64.14 by Ian Clatworthy
commit of modified files working
244
            self.inventory.root.revision = self.revision_id
0.64.5 by Ian Clatworthy
first cut at generic processing method
245
0.64.14 by Ian Clatworthy
commit of modified files working
246
    def post_process_files(self):
247
        """Save the revision."""
248
        if self.verbose:
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
249
            note("applying inventory delta ...")
0.64.14 by Ian Clatworthy
commit of modified files working
250
            for entry in self.inv_delta:
0.64.16 by Ian Clatworthy
safe processing tweaks
251
                note("  %r" % (entry,))
0.64.14 by Ian Clatworthy
commit of modified files working
252
        self.inventory.apply_delta(self.inv_delta)
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
253
        self.cache_mgr.inventories[self.revision_id] = self.inventory
0.64.14 by Ian Clatworthy
commit of modified files working
254
        if self.verbose:
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
255
            note("created inventory ...")
0.64.14 by Ian Clatworthy
commit of modified files working
256
            for entry in self.inventory:
0.64.16 by Ian Clatworthy
safe processing tweaks
257
                note("  %r" % (entry,))
0.64.5 by Ian Clatworthy
first cut at generic processing method
258
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
259
        # Load the revision into the repository
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
260
        rev_props = {}
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
261
        committer = self.command.committer
262
        who = "%s <%s>" % (committer[0],committer[1])
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
263
        author = self.command.author
264
        if author is not None:
265
            author_id = "%s <%s>" % (author[0],author[1])
266
            if author_id != who:
267
                rev_props['author'] = author_id
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
268
        rev = revision.Revision(
269
           timestamp=committer[2],
270
           timezone=committer[3],
271
           committer=who,
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
272
           message=self._escape_commit_message(self.command.message),
273
           revision_id=self.revision_id,
274
           properties=rev_props,
275
           parent_ids=self.parents)
0.64.14 by Ian Clatworthy
commit of modified files working
276
        self.loader.load(rev, self.inventory, None,
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
277
            lambda file_id: self._get_lines(file_id))
278
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
279
    def _escape_commit_message(self, message):
280
        """Replace xml-incompatible control characters."""
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
281
        # It's crap that we need to do this at this level (but we do)
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
282
        # Code copied from bzrlib.commit.
283
        
284
        # Python strings can include characters that can't be
285
        # represented in well-formed XML; escape characters that
286
        # aren't listed in the XML specification
287
        # (http://www.w3.org/TR/REC-xml/#NT-Char).
288
        message, _ = re.subn(
289
            u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD]+',
290
            lambda match: match.group(0).encode('unicode_escape'),
291
            message)
292
        return message
0.64.5 by Ian Clatworthy
first cut at generic processing method
293
294
    def modify_handler(self, filecmd):
295
        if filecmd.dataref is not None:
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
296
            data = self.cache_mgr.blobs[filecmd.dataref]
0.64.16 by Ian Clatworthy
safe processing tweaks
297
            ## Conserve memory, assuming blobs aren't referenced twice
298
            #del self.cache_mgr.blobs[filecmd.dataref]
0.64.5 by Ian Clatworthy
first cut at generic processing method
299
        else:
300
            data = filecmd.data
301
        self._modify_inventory(filecmd.path, filecmd.kind,
302
            filecmd.is_executable, data)
303
304
    def delete_handler(self, filecmd):
305
        path = filecmd.path
306
        self.inv_delta.append((path, None, self.bzr_file_id(path), None))
0.64.16 by Ian Clatworthy
safe processing tweaks
307
        self.cache_mgr._delete_path(path)
0.64.5 by Ian Clatworthy
first cut at generic processing method
308
309
    def copy_handler(self, filecmd):
310
        raise NotImplementedError(self.copy_handler)
311
312
    def rename_handler(self, filecmd):
0.64.16 by Ian Clatworthy
safe processing tweaks
313
        old_path = filecmd.old_path
314
        new_path = filecmd.new_path
315
        file_id = self.bzr_file_id(old_path)
316
        ie = self.inventory[file_id]
317
        self.inv_delta.append((old_path, new_path, file_id, ie))
318
        self.cache_mgr._rename_path(old_path, new_path)
0.64.5 by Ian Clatworthy
first cut at generic processing method
319
320
    def deleteall_handler(self, filecmd):
321
        raise NotImplementedError(self.deleteall_handler)
322
0.64.16 by Ian Clatworthy
safe processing tweaks
323
    def bzr_file_id_and_new(self, path):
324
        """Get a Bazaar file identifier and new flag for a path.
325
        
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
326
        :return: file_id, is_new where
327
          is_new = True if the file_id is newly created
0.64.16 by Ian Clatworthy
safe processing tweaks
328
        """
329
        try:
330
            return self.cache_mgr.file_ids[path], False
331
        except KeyError:
332
            id = generate_ids.gen_file_id(path)
333
            self.cache_mgr.file_ids[path] = id
334
            return id, True
335
0.64.5 by Ian Clatworthy
first cut at generic processing method
336
    def bzr_file_id(self, path):
0.64.14 by Ian Clatworthy
commit of modified files working
337
        """Get a Bazaar file identifier for a path."""
0.64.16 by Ian Clatworthy
safe processing tweaks
338
        return self.bzr_file_id_and_new(path)[0]
0.64.5 by Ian Clatworthy
first cut at generic processing method
339
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
340
    def gen_initial_inventory(self):
341
        """Generate an inventory for a parentless revision."""
342
        inv = inventory.Inventory(revision_id=self.revision_id)
343
        return inv
344
0.64.5 by Ian Clatworthy
first cut at generic processing method
345
    def gen_revision_id(self):
346
        """Generate a revision id.
347
348
        Subclasses may override this to produce deterministic ids say.
349
        """
350
        committer = self.command.committer
0.64.16 by Ian Clatworthy
safe processing tweaks
351
        # Perhaps 'who' being the person running the import is ok? If so,
352
        # it might be a bit quicker and give slightly better compression?
0.64.5 by Ian Clatworthy
first cut at generic processing method
353
        who = "%s <%s>" % (committer[0],committer[1])
354
        timestamp = committer[2]
355
        return generate_ids.gen_revision_id(who, timestamp)
356
0.64.7 by Ian Clatworthy
start of multiple commit handling
357
    def get_inventory(self, revision_id):
358
        """Get the inventory for a revision id."""
359
        try:
360
            inv = self.cache_mgr.inventories[revision_id]
361
        except KeyError:
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
362
            print "Hmm - get_inventory cache miss for %s" % revision_id
0.64.7 by Ian Clatworthy
start of multiple commit handling
363
            # Not cached so reconstruct from repository
364
            inv = self.repo.revision_tree(revision_id).inventory
365
            self.cache_mgr.inventories[revision_id] = inv
366
        return inv
367
0.64.5 by Ian Clatworthy
first cut at generic processing method
368
    def _get_inventories(self, revision_ids):
369
        """Get the inventories for revision-ids.
370
        
371
        This is a callback used by the RepositoryLoader to
372
        speed up inventory reconstruction."""
373
        present = []
374
        inventories = []
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
375
        # If an inventory is in the cache, we assume it was
0.64.5 by Ian Clatworthy
first cut at generic processing method
376
        # successfully loaded into the repsoitory
377
        for revision_id in revision_ids:
378
            try:
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
379
                inv = self.cache_mgr.inventories[revision_id]
0.64.5 by Ian Clatworthy
first cut at generic processing method
380
                present.append(revision_id)
381
            except KeyError:
0.64.17 by Ian Clatworthy
escape commit messages, diff author to committer and cache fixes
382
                print "Hmm - get_inventories cache miss for %s" % revision_id
0.64.5 by Ian Clatworthy
first cut at generic processing method
383
                # Not cached so reconstruct from repository
384
                if self.repo.has_revision(revision_id):
385
                    rev_tree = self.repo.revision_tree(revision_id)
386
                    present.append(revision_id)
387
                else:
388
                    rev_tree = self.repo.revision_tree(None)
389
                inv = rev_tree.inventory
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
390
                self.cache_mgr.inventories[revision_id] = inv
391
            inventories.append(inv)
0.64.5 by Ian Clatworthy
first cut at generic processing method
392
        return present, inventories
393
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
394
    def _get_lines(self, file_id):
395
        """Get the lines for a file-id."""
396
        return self.lines_for_commit[file_id]
0.64.5 by Ian Clatworthy
first cut at generic processing method
397
398
    def _modify_inventory(self, path, kind, is_executable, data):
399
        """Add to or change an item in the inventory."""
400
        # Create the new InventoryEntry
401
        basename, parent_ie = self._ensure_directory(path)
0.64.16 by Ian Clatworthy
safe processing tweaks
402
        file_id, is_new = self.bzr_file_id_and_new(path)
403
        ie = inventory.make_entry(kind, basename, parent_ie.file_id, file_id)
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
404
        ie.revision = self.revision_id
0.64.5 by Ian Clatworthy
first cut at generic processing method
405
        if isinstance(ie, inventory.InventoryFile):
406
            ie.executable = is_executable
0.64.13 by Ian Clatworthy
commit of new files working
407
            lines = osutils.split_lines(data)
408
            ie.text_sha1 = osutils.sha_strings(lines)
409
            ie.text_size = sum(map(len, lines))
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
410
            self.lines_for_commit[file_id] = lines
0.64.5 by Ian Clatworthy
first cut at generic processing method
411
        elif isinstance(ie, inventory.InventoryLnk):
412
            ie.symlink_target = data
413
        else:
414
            raise errors.BzrError("Cannot import items of kind '%s' yet" %
415
                (kind,))
416
0.64.16 by Ian Clatworthy
safe processing tweaks
417
        # Record this new inventory entry
418
        if is_new:
419
            self.inventory.add(ie)
420
        else:
421
            self.inv_delta.append((path, path, file_id, ie))
0.64.5 by Ian Clatworthy
first cut at generic processing method
422
423
    def _ensure_directory(self, path):
424
        """Ensure that the containing directory exists for 'path'"""
425
        dirname, basename = osutils.split(path)
426
        if dirname == '':
427
            # the root node doesn't get updated
0.64.16 by Ian Clatworthy
safe processing tweaks
428
            return basename, self.inventory.root
0.64.5 by Ian Clatworthy
first cut at generic processing method
429
        try:
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
430
            ie = self.cache_mgr.directory_entries[dirname]
0.64.5 by Ian Clatworthy
first cut at generic processing method
431
        except KeyError:
432
            # We will create this entry, since it doesn't exist
433
            pass
434
        else:
435
            return basename, ie
436
437
        # No directory existed, we will just create one, first, make sure
438
        # the parent exists
439
        dir_basename, parent_ie = self._ensure_directory(dirname)
440
        dir_file_id = self.bzr_file_id(dirname)
441
        ie = inventory.entry_factory['directory'](dir_file_id,
442
                                                  dir_basename,
443
                                                  parent_ie.file_id)
444
        ie.revision = self.revision_id
0.64.6 by Ian Clatworthy
generic processing method working for one revision in one branch
445
        self.cache_mgr.directory_entries[dirname] = ie
0.64.16 by Ian Clatworthy
safe processing tweaks
446
        # There are no lines stored for a directory so
447
        # make sure the cache used by get_lines knows that
448
        self.lines_for_commit[dir_file_id] = []
449
        #print "adding dir %s" % path
450
        self.inventory.add(ie)
0.64.5 by Ian Clatworthy
first cut at generic processing method
451
        return basename, ie