/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
138 by mbp at sourcefrog
remove parallel tree from inventory;
1
# (C) 2005 Canonical Ltd
1 by mbp at sourcefrog
import from baz patch-364
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
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
18
# This should really be an id randomly assigned when the tree is
19
# created, but it's not for now.
20
ROOT_ID = "TREE_ROOT"
21
22
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
23
import os.path
24
import re
25
import sys
26
import types
1 by mbp at sourcefrog
import from baz patch-364
27
800 by Martin Pool
Merge John's import-speedup branch:
28
import bzrlib
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
29
from bzrlib.errors import BzrError, BzrCheckError
70 by mbp at sourcefrog
Prepare for smart recursive add.
30
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
31
from bzrlib.osutils import quotefn, splitpath, joinpath, appendpath
70 by mbp at sourcefrog
Prepare for smart recursive add.
32
from bzrlib.trace import mutter
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
33
from bzrlib.errors import NotVersionedError
1185.1.41 by Robert Collins
massive patch from Alexander Belchenko - many PEP8 fixes, removes unused function uuid
34
1 by mbp at sourcefrog
import from baz patch-364
35
802 by Martin Pool
- Remove XMLMixin class in favour of simple pack_xml, unpack_xml functions
36
class InventoryEntry(object):
1 by mbp at sourcefrog
import from baz patch-364
37
    """Description of a versioned file.
38
39
    An InventoryEntry has the following fields, which are also
40
    present in the XML inventory-entry element:
41
42
    * *file_id*
43
    * *name*: (only the basename within the directory, must not
44
      contain slashes)
45
    * *kind*: "directory" or "file"
46
    * *directory_id*: (if absent/null means the branch root directory)
47
    * *text_sha1*: only for files
48
    * *text_size*: in bytes, only for files 
49
    * *text_id*: identifier for the text version, only for files
50
51
    InventoryEntries can also exist inside a WorkingTree
52
    inventory, in which case they are not yet bound to a
53
    particular revision of the file.  In that case the text_sha1,
54
    text_size and text_id are absent.
55
56
57
    >>> i = Inventory()
58
    >>> i.path2id('')
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
59
    'TREE_ROOT'
60
    >>> i.add(InventoryEntry('123', 'src', 'directory', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
61
    InventoryEntry('123', 'src', kind='directory', parent_id='TREE_ROOT')
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
62
    >>> i.add(InventoryEntry('2323', 'hello.c', 'file', parent_id='123'))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
63
    InventoryEntry('2323', 'hello.c', kind='file', parent_id='123')
1 by mbp at sourcefrog
import from baz patch-364
64
    >>> for j in i.iter_entries():
65
    ...   print j
66
    ... 
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
67
    ('src', InventoryEntry('123', 'src', kind='directory', parent_id='TREE_ROOT'))
1 by mbp at sourcefrog
import from baz patch-364
68
    ('src/hello.c', InventoryEntry('2323', 'hello.c', kind='file', parent_id='123'))
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
69
    >>> i.add(InventoryEntry('2323', 'bye.c', 'file', '123'))
1 by mbp at sourcefrog
import from baz patch-364
70
    Traceback (most recent call last):
71
    ...
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
72
    BzrError: inventory already contains entry with id {2323}
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
73
    >>> i.add(InventoryEntry('2324', 'bye.c', 'file', '123'))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
74
    InventoryEntry('2324', 'bye.c', kind='file', parent_id='123')
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
75
    >>> i.add(InventoryEntry('2325', 'wibble', 'directory', '123'))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
76
    InventoryEntry('2325', 'wibble', kind='directory', parent_id='123')
1 by mbp at sourcefrog
import from baz patch-364
77
    >>> i.path2id('src/wibble')
78
    '2325'
79
    >>> '2325' in i
80
    True
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
81
    >>> i.add(InventoryEntry('2326', 'wibble.c', 'file', '2325'))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
82
    InventoryEntry('2326', 'wibble.c', kind='file', parent_id='2325')
1 by mbp at sourcefrog
import from baz patch-364
83
    >>> i['2326']
84
    InventoryEntry('2326', 'wibble.c', kind='file', parent_id='2325')
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
85
    >>> for path, entry in i.iter_entries():
86
    ...     print path.replace('\\\\', '/')     # for win32 os.sep
87
    ...     assert i.path2id(path)
1 by mbp at sourcefrog
import from baz patch-364
88
    ... 
89
    src
90
    src/bye.c
91
    src/hello.c
92
    src/wibble
93
    src/wibble/wibble.c
1185.1.40 by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch.
94
    >>> i.id2path('2326').replace('\\\\', '/')
1 by mbp at sourcefrog
import from baz patch-364
95
    'src/wibble/wibble.c'
96
254 by Martin Pool
- Doc cleanups from Magnus Therning
97
    TODO: Maybe also keep the full path of the entry, and the children?
1 by mbp at sourcefrog
import from baz patch-364
98
           But those depend on its position within a particular inventory, and
99
           it would be nice not to need to hold the backpointer here.
100
    """
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
101
102
    # TODO: split InventoryEntry into subclasses for files,
103
    # directories, etc etc.
376 by Martin Pool
- fix slow invariant check when reading in InventoryEntry objects
104
955 by Martin Pool
- use __slots__ on InventoryEntry; rather faster
105
    __slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
1183 by Martin Pool
- implement version 5 xml storage, and tests
106
                 'text_id', 'parent_id', 'children',
107
                 'text_version', 'entry_version', ]
955 by Martin Pool
- use __slots__ on InventoryEntry; rather faster
108
1185 by Martin Pool
- add xml round-trip test for revisions
109
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
110
    def __init__(self, file_id, name, kind, parent_id, text_id=None):
1 by mbp at sourcefrog
import from baz patch-364
111
        """Create an InventoryEntry
112
        
113
        The filename must be a single component, relative to the
114
        parent directory; it cannot be a whole path or relative name.
115
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
116
        >>> e = InventoryEntry('123', 'hello.c', 'file', ROOT_ID)
1 by mbp at sourcefrog
import from baz patch-364
117
        >>> e.name
118
        'hello.c'
119
        >>> e.file_id
120
        '123'
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
121
        >>> e = InventoryEntry('123', 'src/hello.c', 'file', ROOT_ID)
1 by mbp at sourcefrog
import from baz patch-364
122
        Traceback (most recent call last):
395 by Martin Pool
- fix error raised from invalid InventoryEntry name
123
        BzrCheckError: InventoryEntry name 'src/hello.c' is invalid
1 by mbp at sourcefrog
import from baz patch-364
124
        """
1183 by Martin Pool
- implement version 5 xml storage, and tests
125
        assert isinstance(name, basestring), name
376 by Martin Pool
- fix slow invariant check when reading in InventoryEntry objects
126
        if '/' in name or '\\' in name:
127
            raise BzrCheckError('InventoryEntry name %r is invalid' % name)
1 by mbp at sourcefrog
import from baz patch-364
128
        
1185 by Martin Pool
- add xml round-trip test for revisions
129
        self.text_version = None
130
        self.entry_version = None
955 by Martin Pool
- use __slots__ on InventoryEntry; rather faster
131
        self.text_sha1 = None
132
        self.text_size = None
1 by mbp at sourcefrog
import from baz patch-364
133
        self.file_id = file_id
134
        self.name = name
135
        self.kind = kind
136
        self.text_id = text_id
137
        self.parent_id = parent_id
138 by mbp at sourcefrog
remove parallel tree from inventory;
138
        if kind == 'directory':
139
            self.children = {}
237 by mbp at sourcefrog
- Better assertions in InventoryEntry constructor
140
        elif kind == 'file':
141
            pass
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
142
        else:
237 by mbp at sourcefrog
- Better assertions in InventoryEntry constructor
143
            raise BzrError("unhandled entry kind %r" % kind)
144
1 by mbp at sourcefrog
import from baz patch-364
145
146
156 by mbp at sourcefrog
new "directories" command
147
    def sorted_children(self):
148
        l = self.children.items()
149
        l.sort()
150
        return l
151
152
1 by mbp at sourcefrog
import from baz patch-364
153
    def copy(self):
154
        other = InventoryEntry(self.file_id, self.name, self.kind,
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
155
                               self.parent_id, text_id=self.text_id)
1 by mbp at sourcefrog
import from baz patch-364
156
        other.text_sha1 = self.text_sha1
157
        other.text_size = self.text_size
490 by Martin Pool
doc
158
        # note that children are *not* copied; they're pulled across when
159
        # others are added
1 by mbp at sourcefrog
import from baz patch-364
160
        return other
161
162
163
    def __repr__(self):
164
        return ("%s(%r, %r, kind=%r, parent_id=%r)"
165
                % (self.__class__.__name__,
166
                   self.file_id,
167
                   self.name,
168
                   self.kind,
169
                   self.parent_id))
170
171
    
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
172
    def __eq__(self, other):
1 by mbp at sourcefrog
import from baz patch-364
173
        if not isinstance(other, InventoryEntry):
174
            return NotImplemented
175
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
176
        return (self.file_id == other.file_id) \
177
               and (self.name == other.name) \
178
               and (self.text_sha1 == other.text_sha1) \
179
               and (self.text_size == other.text_size) \
180
               and (self.text_id == other.text_id) \
181
               and (self.parent_id == other.parent_id) \
1185 by Martin Pool
- add xml round-trip test for revisions
182
               and (self.kind == other.kind) \
183
               and (self.text_version == other.text_version) \
184
               and (self.entry_version == other.entry_version)
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
185
186
187
    def __ne__(self, other):
188
        return not (self == other)
189
190
    def __hash__(self):
191
        raise ValueError('not hashable')
1 by mbp at sourcefrog
import from baz patch-364
192
193
194
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
195
class RootEntry(InventoryEntry):
196
    def __init__(self, file_id):
197
        self.file_id = file_id
198
        self.children = {}
199
        self.kind = 'root_directory'
200
        self.parent_id = None
156 by mbp at sourcefrog
new "directories" command
201
        self.name = ''
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
202
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
203
    def __eq__(self, other):
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
204
        if not isinstance(other, RootEntry):
205
            return NotImplemented
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
206
        
207
        return (self.file_id == other.file_id) \
208
               and (self.children == other.children)
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
209
210
211
802 by Martin Pool
- Remove XMLMixin class in favour of simple pack_xml, unpack_xml functions
212
class Inventory(object):
1 by mbp at sourcefrog
import from baz patch-364
213
    """Inventory of versioned files in a tree.
214
240 by mbp at sourcefrog
doc
215
    This describes which file_id is present at each point in the tree,
216
    and possibly the SHA-1 or other information about the file.
217
    Entries can be looked up either by path or by file_id.
1 by mbp at sourcefrog
import from baz patch-364
218
219
    The inventory represents a typical unix file tree, with
220
    directories containing files and subdirectories.  We never store
221
    the full path to a file, because renaming a directory implicitly
222
    moves all of its contents.  This class internally maintains a
223
    lookup tree that allows the children under a directory to be
224
    returned quickly.
225
226
    InventoryEntry objects must not be modified after they are
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
227
    inserted, other than through the Inventory API.
1 by mbp at sourcefrog
import from baz patch-364
228
229
    >>> inv = Inventory()
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
230
    >>> inv.add(InventoryEntry('123-123', 'hello.c', 'file', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
231
    InventoryEntry('123-123', 'hello.c', kind='file', parent_id='TREE_ROOT')
1 by mbp at sourcefrog
import from baz patch-364
232
    >>> inv['123-123'].name
233
    'hello.c'
234
235
    May be treated as an iterator or set to look up file ids:
236
    
237
    >>> bool(inv.path2id('hello.c'))
238
    True
239
    >>> '123-123' in inv
240
    True
241
242
    May also look up by name:
243
244
    >>> [x[0] for x in inv.iter_entries()]
245
    ['hello.c']
909 by Martin Pool
- merge John's code to give the tree root an explicit file id
246
    >>> inv = Inventory('TREE_ROOT-12345678-12345678')
247
    >>> inv.add(InventoryEntry('123-123', 'hello.c', 'file', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
248
    InventoryEntry('123-123', 'hello.c', kind='file', parent_id='TREE_ROOT-12345678-12345678')
1 by mbp at sourcefrog
import from baz patch-364
249
    """
909 by Martin Pool
- merge John's code to give the tree root an explicit file id
250
    def __init__(self, root_id=ROOT_ID):
1 by mbp at sourcefrog
import from baz patch-364
251
        """Create or read an inventory.
252
253
        If a working directory is specified, the inventory is read
254
        from there.  If the file is specified, read from that. If not,
255
        the inventory is created empty.
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
256
257
        The inventory is created with a default root directory, with
258
        an id of None.
1 by mbp at sourcefrog
import from baz patch-364
259
        """
1185.2.9 by Lalo Martins
getting rid of everything that calls the Branch constructor directly
260
        # We are letting Branch.initialize() create a unique inventory
909 by Martin Pool
- merge John's code to give the tree root an explicit file id
261
        # root id. Rather than generating a random one here.
262
        #if root_id is None:
263
        #    root_id = bzrlib.branch.gen_file_id('TREE_ROOT')
264
        self.root = RootEntry(root_id)
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
265
        self._byid = {self.root.file_id: self.root}
1 by mbp at sourcefrog
import from baz patch-364
266
267
268
    def __iter__(self):
269
        return iter(self._byid)
270
271
272
    def __len__(self):
273
        """Returns number of entries."""
274
        return len(self._byid)
275
276
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
277
    def iter_entries(self, from_dir=None):
1 by mbp at sourcefrog
import from baz patch-364
278
        """Return (path, entry) pairs, in order by name."""
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
279
        if from_dir == None:
280
            assert self.root
281
            from_dir = self.root
282
        elif isinstance(from_dir, basestring):
283
            from_dir = self._byid[from_dir]
284
            
285
        kids = from_dir.children.items()
1 by mbp at sourcefrog
import from baz patch-364
286
        kids.sort()
287
        for name, ie in kids:
288
            yield name, ie
289
            if ie.kind == 'directory':
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
290
                for cn, cie in self.iter_entries(from_dir=ie.file_id):
271 by Martin Pool
- Windows path fixes
291
                    yield os.path.join(name, cn), cie
555 by Martin Pool
- New Inventory.entries() method
292
293
294
    def entries(self):
295
        """Return list of (path, ie) for all entries except the root.
296
297
        This may be faster than iter_entries.
298
        """
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
299
        accum = []
300
        def descend(dir_ie, dir_path):
556 by Martin Pool
- fix up Inventory.entries()
301
            kids = dir_ie.children.items()
555 by Martin Pool
- New Inventory.entries() method
302
            kids.sort()
303
            for name, ie in kids:
304
                child_path = os.path.join(dir_path, name)
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
305
                accum.append((child_path, ie))
555 by Martin Pool
- New Inventory.entries() method
306
                if ie.kind == 'directory':
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
307
                    descend(ie, child_path)
555 by Martin Pool
- New Inventory.entries() method
308
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
309
        descend(self.root, '')
310
        return accum
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
311
312
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
313
    def directories(self):
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
314
        """Return (path, entry) pairs for all directories, including the root.
1 by mbp at sourcefrog
import from baz patch-364
315
        """
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
316
        accum = []
317
        def descend(parent_ie, parent_path):
318
            accum.append((parent_path, parent_ie))
156 by mbp at sourcefrog
new "directories" command
319
            
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
320
            kids = [(ie.name, ie) for ie in parent_ie.children.itervalues() if ie.kind == 'directory']
321
            kids.sort()
156 by mbp at sourcefrog
new "directories" command
322
557 by Martin Pool
- Refactor/cleanup Inventory.entries()
323
            for name, child_ie in kids:
324
                child_path = os.path.join(parent_path, name)
325
                descend(child_ie, child_path)
326
        descend(self.root, '')
327
        return accum
1 by mbp at sourcefrog
import from baz patch-364
328
        
329
330
331
    def __contains__(self, file_id):
332
        """True if this entry contains a file with given id.
333
334
        >>> inv = Inventory()
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
335
        >>> inv.add(InventoryEntry('123', 'foo.c', 'file', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
336
        InventoryEntry('123', 'foo.c', kind='file', parent_id='TREE_ROOT')
1 by mbp at sourcefrog
import from baz patch-364
337
        >>> '123' in inv
338
        True
339
        >>> '456' in inv
340
        False
341
        """
342
        return file_id in self._byid
343
344
345
    def __getitem__(self, file_id):
346
        """Return the entry for given file_id.
347
348
        >>> inv = Inventory()
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
349
        >>> inv.add(InventoryEntry('123123', 'hello.c', 'file', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
350
        InventoryEntry('123123', 'hello.c', kind='file', parent_id='TREE_ROOT')
1 by mbp at sourcefrog
import from baz patch-364
351
        >>> inv['123123'].name
352
        'hello.c'
353
        """
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
354
        try:
355
            return self._byid[file_id]
356
        except KeyError:
380 by Martin Pool
- Slight optimization for Inventory.__getitem__
357
            if file_id == None:
358
                raise BzrError("can't look up file_id None")
359
            else:
360
                raise BzrError("file_id {%s} not in inventory" % file_id)
1 by mbp at sourcefrog
import from baz patch-364
361
362
460 by Martin Pool
- new testing command compare-trees
363
    def get_file_kind(self, file_id):
364
        return self._byid[file_id].kind
365
138 by mbp at sourcefrog
remove parallel tree from inventory;
366
    def get_child(self, parent_id, filename):
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
367
        return self[parent_id].children.get(filename)
138 by mbp at sourcefrog
remove parallel tree from inventory;
368
369
1 by mbp at sourcefrog
import from baz patch-364
370
    def add(self, entry):
371
        """Add entry to inventory.
372
373
        To add  a file to a branch ready to be committed, use Branch.add,
1180 by Martin Pool
- start splitting code for xml (de)serialization away from objects
374
        which calls this.
375
376
        Returns the new entry object.
377
        """
139 by mbp at sourcefrog
simplified/faster Inventory.add
378
        if entry.file_id in self._byid:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
379
            raise BzrError("inventory already contains entry with id {%s}" % entry.file_id)
1 by mbp at sourcefrog
import from baz patch-364
380
909 by Martin Pool
- merge John's code to give the tree root an explicit file id
381
        if entry.parent_id == ROOT_ID or entry.parent_id is None:
382
            entry.parent_id = self.root.file_id
383
155 by mbp at sourcefrog
add new explicit RootEntry to inventory (in-core only)
384
        try:
385
            parent = self._byid[entry.parent_id]
386
        except KeyError:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
387
            raise BzrError("parent_id {%s} not in inventory" % entry.parent_id)
139 by mbp at sourcefrog
simplified/faster Inventory.add
388
389
        if parent.children.has_key(entry.name):
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
390
            raise BzrError("%s is already versioned" %
140 by mbp at sourcefrog
fix error message for repeated add
391
                    appendpath(self.id2path(parent.file_id), entry.name))
1 by mbp at sourcefrog
import from baz patch-364
392
393
        self._byid[entry.file_id] = entry
139 by mbp at sourcefrog
simplified/faster Inventory.add
394
        parent.children[entry.name] = entry
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
395
        return entry
1 by mbp at sourcefrog
import from baz patch-364
396
397
70 by mbp at sourcefrog
Prepare for smart recursive add.
398
    def add_path(self, relpath, kind, file_id=None):
399
        """Add entry from a path.
400
1180 by Martin Pool
- start splitting code for xml (de)serialization away from objects
401
        The immediate parent must already be versioned.
402
403
        Returns the new entry object."""
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
404
        from bzrlib.branch import gen_file_id
1015 by Martin Pool
- fix circular imports
405
        
70 by mbp at sourcefrog
Prepare for smart recursive add.
406
        parts = bzrlib.osutils.splitpath(relpath)
407
        if len(parts) == 0:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
408
            raise BzrError("cannot re-add root of inventory")
70 by mbp at sourcefrog
Prepare for smart recursive add.
409
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
410
        if file_id == None:
800 by Martin Pool
Merge John's import-speedup branch:
411
            file_id = gen_file_id(relpath)
70 by mbp at sourcefrog
Prepare for smart recursive add.
412
753 by Martin Pool
- new exception NotVersionedError
413
        parent_path = parts[:-1]
414
        parent_id = self.path2id(parent_path)
415
        if parent_id == None:
416
            raise NotVersionedError(parent_path)
417
70 by mbp at sourcefrog
Prepare for smart recursive add.
418
        ie = InventoryEntry(file_id, parts[-1],
419
                            kind=kind, parent_id=parent_id)
420
        return self.add(ie)
421
422
1 by mbp at sourcefrog
import from baz patch-364
423
    def __delitem__(self, file_id):
424
        """Remove entry by id.
425
426
        >>> inv = Inventory()
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
427
        >>> inv.add(InventoryEntry('123', 'foo.c', 'file', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
428
        InventoryEntry('123', 'foo.c', kind='file', parent_id='TREE_ROOT')
1 by mbp at sourcefrog
import from baz patch-364
429
        >>> '123' in inv
430
        True
431
        >>> del inv['123']
432
        >>> '123' in inv
433
        False
434
        """
435
        ie = self[file_id]
436
138 by mbp at sourcefrog
remove parallel tree from inventory;
437
        assert self[ie.parent_id].children[ie.name] == ie
1 by mbp at sourcefrog
import from baz patch-364
438
        
439
        # TODO: Test deleting all children; maybe hoist to a separate
440
        # deltree method?
441
        if ie.kind == 'directory':
138 by mbp at sourcefrog
remove parallel tree from inventory;
442
            for cie in ie.children.values():
1 by mbp at sourcefrog
import from baz patch-364
443
                del self[cie.file_id]
138 by mbp at sourcefrog
remove parallel tree from inventory;
444
            del ie.children
1 by mbp at sourcefrog
import from baz patch-364
445
446
        del self._byid[file_id]
138 by mbp at sourcefrog
remove parallel tree from inventory;
447
        del self[ie.parent_id].children[ie.name]
1 by mbp at sourcefrog
import from baz patch-364
448
449
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
450
    def __eq__(self, other):
1 by mbp at sourcefrog
import from baz patch-364
451
        """Compare two sets by comparing their contents.
452
453
        >>> i1 = Inventory()
454
        >>> i2 = Inventory()
455
        >>> i1 == i2
456
        True
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
457
        >>> i1.add(InventoryEntry('123', 'foo', 'file', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
458
        InventoryEntry('123', 'foo', kind='file', parent_id='TREE_ROOT')
1 by mbp at sourcefrog
import from baz patch-364
459
        >>> i1 == i2
460
        False
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
461
        >>> i2.add(InventoryEntry('123', 'foo', 'file', ROOT_ID))
1092.1.30 by Robert Collins
change smart_add reporting of added files to callback with the entry, and change the inventory.add signature to return the added entry
462
        InventoryEntry('123', 'foo', kind='file', parent_id='TREE_ROOT')
1 by mbp at sourcefrog
import from baz patch-364
463
        >>> i1 == i2
464
        True
465
        """
466
        if not isinstance(other, Inventory):
467
            return NotImplemented
468
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
469
        if len(self._byid) != len(other._byid):
543 by Martin Pool
- More cleanups for set type
470
            # shortcut: obviously not the same
544 by Martin Pool
- Define __eq__ and __ne__ for Inventory and InventoryEntry objects,
471
            return False
472
473
        return self._byid == other._byid
474
475
476
    def __ne__(self, other):
477
        return not (self == other)
478
479
480
    def __hash__(self):
481
        raise ValueError('not hashable')
482
1 by mbp at sourcefrog
import from baz patch-364
483
172 by mbp at sourcefrog
- clearer check against attempts to introduce directory loops in the inventory
484
    def get_idpath(self, file_id):
485
        """Return a list of file_ids for the path to an entry.
486
487
        The list contains one element for each directory followed by
488
        the id of the file itself.  So the length of the returned list
489
        is equal to the depth of the file in the tree, counting the
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
490
        root directory as depth 1.
172 by mbp at sourcefrog
- clearer check against attempts to introduce directory loops in the inventory
491
        """
492
        p = []
493
        while file_id != None:
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
494
            try:
495
                ie = self._byid[file_id]
496
            except KeyError:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
497
                raise BzrError("file_id {%s} not found in inventory" % file_id)
172 by mbp at sourcefrog
- clearer check against attempts to introduce directory loops in the inventory
498
            p.insert(0, ie.file_id)
499
            file_id = ie.parent_id
500
        return p
501
502
1 by mbp at sourcefrog
import from baz patch-364
503
    def id2path(self, file_id):
504
        """Return as a list the path to file_id."""
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
505
506
        # get all names, skipping root
922 by Martin Pool
- optimization for Inventory.id2path; access byid map directly rather than
507
        p = [self._byid[fid].name for fid in self.get_idpath(file_id)[1:]]
271 by Martin Pool
- Windows path fixes
508
        return os.sep.join(p)
1 by mbp at sourcefrog
import from baz patch-364
509
            
510
511
512
    def path2id(self, name):
513
        """Walk down through directories to return entry of last component.
514
515
        names may be either a list of path components, or a single
516
        string, in which case it is automatically split.
517
518
        This returns the entry of the last component in the path,
519
        which may be either a file or a directory.
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
520
521
        Returns None iff the path is not found.
1 by mbp at sourcefrog
import from baz patch-364
522
        """
70 by mbp at sourcefrog
Prepare for smart recursive add.
523
        if isinstance(name, types.StringTypes):
524
            name = splitpath(name)
1 by mbp at sourcefrog
import from baz patch-364
525
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
526
        mutter("lookup path %r" % name)
527
528
        parent = self.root
70 by mbp at sourcefrog
Prepare for smart recursive add.
529
        for f in name:
1 by mbp at sourcefrog
import from baz patch-364
530
            try:
138 by mbp at sourcefrog
remove parallel tree from inventory;
531
                cie = parent.children[f]
1 by mbp at sourcefrog
import from baz patch-364
532
                assert cie.name == f
178 by mbp at sourcefrog
- Use a non-null file_id for the branch root directory. At the moment
533
                assert cie.parent_id == parent.file_id
138 by mbp at sourcefrog
remove parallel tree from inventory;
534
                parent = cie
1 by mbp at sourcefrog
import from baz patch-364
535
            except KeyError:
536
                # or raise an error?
537
                return None
538
138 by mbp at sourcefrog
remove parallel tree from inventory;
539
        return parent.file_id
1 by mbp at sourcefrog
import from baz patch-364
540
541
542
    def has_filename(self, names):
543
        return bool(self.path2id(names))
544
545
546
    def has_id(self, file_id):
547
        return self._byid.has_key(file_id)
548
549
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
550
    def rename(self, file_id, new_parent_id, new_name):
551
        """Move a file within the inventory.
552
553
        This can change either the name, or the parent, or both.
554
555
        This does not move the working file."""
556
        if not is_valid_name(new_name):
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
557
            raise BzrError("not an acceptable filename: %r" % new_name)
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
558
559
        new_parent = self._byid[new_parent_id]
560
        if new_name in new_parent.children:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
561
            raise BzrError("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
562
172 by mbp at sourcefrog
- clearer check against attempts to introduce directory loops in the inventory
563
        new_parent_idpath = self.get_idpath(new_parent_id)
564
        if file_id in new_parent_idpath:
694 by Martin Pool
- weed out all remaining calls to bailout() and remove the function
565
            raise BzrError("cannot move directory %r into a subdirectory of itself, %r"
172 by mbp at sourcefrog
- clearer check against attempts to introduce directory loops in the inventory
566
                    % (self.id2path(file_id), self.id2path(new_parent_id)))
567
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
568
        file_ie = self._byid[file_id]
569
        old_parent = self._byid[file_ie.parent_id]
570
571
        # TODO: Don't leave things messed up if this fails
572
573
        del old_parent.children[file_ie.name]
574
        new_parent.children[new_name] = file_ie
575
        
576
        file_ie.name = new_name
577
        file_ie.parent_id = new_parent_id
578
579
580
581
1077 by Martin Pool
- avoid compiling REs at module load time
582
_NAME_RE = None
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
583
584
def is_valid_name(name):
1077 by Martin Pool
- avoid compiling REs at module load time
585
    global _NAME_RE
586
    if _NAME_RE == None:
587
        _NAME_RE = re.compile(r'^[^/\\]+$')
588
        
160 by mbp at sourcefrog
- basic support for moving files to different directories - have not done support for renaming them yet, but should be straightforward - some tests, but many cases are not handled yet i think
589
    return bool(_NAME_RE.match(name))