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