~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

Move add from Branch to WorkingTree.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
 
25
25
 
26
26
import bzrlib
27
 
from bzrlib.inventory import InventoryEntry
28
27
import bzrlib.inventory as inventory
29
28
from bzrlib.trace import mutter, note
30
 
from bzrlib.osutils import (isdir, quotefn, compact_date, rand_bytes, 
 
29
from bzrlib.osutils import (isdir, quotefn,
31
30
                            rename, splitpath, sha_file, appendpath, 
32
31
                            file_kind, abspath)
33
32
import bzrlib.errors as errors
517
516
        inv = self.get_inventory(self.last_revision())
518
517
        return inv.root.file_id
519
518
 
520
 
    @needs_write_lock
521
 
    def add(self, files, ids=None):
522
 
        """Make files versioned.
523
 
 
524
 
        Note that the command line normally calls smart_add instead,
525
 
        which can automatically recurse.
526
 
 
527
 
        This puts the files in the Added state, so that they will be
528
 
        recorded by the next commit.
529
 
 
530
 
        files
531
 
            List of paths to add, relative to the base of the tree.
532
 
 
533
 
        ids
534
 
            If set, use these instead of automatically generated ids.
535
 
            Must be the same length as the list of files, but may
536
 
            contain None for ids that are to be autogenerated.
537
 
 
538
 
        TODO: Perhaps have an option to add the ids even if the files do
539
 
              not (yet) exist.
540
 
 
541
 
        TODO: Perhaps yield the ids and paths as they're added.
542
 
        """
543
 
        # TODO: Re-adding a file that is removed in the working copy
544
 
        # should probably put it back with the previous ID.
545
 
        if isinstance(files, basestring):
546
 
            assert(ids is None or isinstance(ids, basestring))
547
 
            files = [files]
548
 
            if ids is not None:
549
 
                ids = [ids]
550
 
 
551
 
        if ids is None:
552
 
            ids = [None] * len(files)
553
 
        else:
554
 
            assert(len(ids) == len(files))
555
 
 
556
 
        inv = self.working_tree().read_working_inventory()
557
 
        for f,file_id in zip(files, ids):
558
 
            if is_control_file(f):
559
 
                raise BzrError("cannot add control file %s" % quotefn(f))
560
 
 
561
 
            fp = splitpath(f)
562
 
 
563
 
            if len(fp) == 0:
564
 
                raise BzrError("cannot add top-level %r" % f)
565
 
 
566
 
            fullpath = os.path.normpath(self.abspath(f))
567
 
 
568
 
            try:
569
 
                kind = file_kind(fullpath)
570
 
            except OSError:
571
 
                # maybe something better?
572
 
                raise BzrError('cannot add: not a regular file, symlink or directory: %s' % quotefn(f))
573
 
 
574
 
            if not InventoryEntry.versionable_kind(kind):
575
 
                raise BzrError('cannot add: not a versionable file ('
576
 
                               'i.e. regular file, symlink or directory): %s' % quotefn(f))
577
 
 
578
 
            if file_id is None:
579
 
                file_id = gen_file_id(f)
580
 
            inv.add_path(f, kind=kind, file_id=file_id)
581
 
 
582
 
            mutter("add file %s file_id:{%s} kind=%r" % (f, file_id, kind))
583
 
 
584
 
        self.working_tree()._write_inventory(inv)
585
 
 
586
519
    @needs_read_lock
587
520
    def print_file(self, file, revno):
588
521
        """Print `file` to stdout."""
603
536
        >>> b = ScratchBranch(files=['foo', 'foo~'])
604
537
        >>> map(str, b.unknowns())
605
538
        ['foo']
606
 
        >>> b.add('foo')
 
539
        >>> WorkingTree(b.base, b).add('foo')
607
540
        >>> list(b.unknowns())
608
541
        []
609
542
        >>> WorkingTree(b.base, b).remove('foo')
1163
1096
            break
1164
1097
        filename = head
1165
1098
    return False
1166
 
 
1167
 
 
1168
 
 
1169
 
def gen_file_id(name):
1170
 
    """Return new file id.
1171
 
 
1172
 
    This should probably generate proper UUIDs, but for the moment we
1173
 
    cope with just randomness because running uuidgen every time is
1174
 
    slow."""
1175
 
    import re
1176
 
    from binascii import hexlify
1177
 
    from time import time
1178
 
 
1179
 
    # get last component
1180
 
    idx = name.rfind('/')
1181
 
    if idx != -1:
1182
 
        name = name[idx+1 : ]
1183
 
    idx = name.rfind('\\')
1184
 
    if idx != -1:
1185
 
        name = name[idx+1 : ]
1186
 
 
1187
 
    # make it not a hidden file
1188
 
    name = name.lstrip('.')
1189
 
 
1190
 
    # remove any wierd characters; we don't escape them but rather
1191
 
    # just pull them out
1192
 
    name = re.sub(r'[^\w.]', '', name)
1193
 
 
1194
 
    s = hexlify(rand_bytes(8))
1195
 
    return '-'.join((name, compact_date(time()), s))
1196
 
 
1197
 
 
1198
 
def gen_root_id():
1199
 
    """Return a new tree-root file id."""
1200
 
    return gen_file_id('TREE_ROOT')
1201
 
 
1202