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
521
def add(self, files, ids=None):
522
"""Make files versioned.
524
Note that the command line normally calls smart_add instead,
525
which can automatically recurse.
527
This puts the files in the Added state, so that they will be
528
recorded by the next commit.
531
List of paths to add, relative to the base of the tree.
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.
538
TODO: Perhaps have an option to add the ids even if the files do
541
TODO: Perhaps yield the ids and paths as they're added.
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))
552
ids = [None] * len(files)
554
assert(len(ids) == len(files))
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))
564
raise BzrError("cannot add top-level %r" % f)
566
fullpath = os.path.normpath(self.abspath(f))
569
kind = file_kind(fullpath)
571
# maybe something better?
572
raise BzrError('cannot add: not a regular file, symlink or directory: %s' % quotefn(f))
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))
579
file_id = gen_file_id(f)
580
inv.add_path(f, kind=kind, file_id=file_id)
582
mutter("add file %s file_id:{%s} kind=%r" % (f, file_id, kind))
584
self.working_tree()._write_inventory(inv)
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())
539
>>> WorkingTree(b.base, b).add('foo')
607
540
>>> list(b.unknowns())
609
542
>>> WorkingTree(b.base, b).remove('foo')
1164
1097
filename = head
1169
def gen_file_id(name):
1170
"""Return new file id.
1172
This should probably generate proper UUIDs, but for the moment we
1173
cope with just randomness because running uuidgen every time is
1176
from binascii import hexlify
1177
from time import time
1179
# get last component
1180
idx = name.rfind('/')
1182
name = name[idx+1 : ]
1183
idx = name.rfind('\\')
1185
name = name[idx+1 : ]
1187
# make it not a hidden file
1188
name = name.lstrip('.')
1190
# remove any wierd characters; we don't escape them but rather
1191
# just pull them out
1192
name = re.sub(r'[^\w.]', '', name)
1194
s = hexlify(rand_bytes(8))
1195
return '-'.join((name, compact_date(time()), s))
1199
"""Return a new tree-root file id."""
1200
return gen_file_id('TREE_ROOT')