406
405
"""Inventory for the working copy.""")
409
def add(self, files, verbose=False, ids=None):
408
def add(self, files, ids=None):
410
409
"""Make files versioned.
412
Note that the command line normally calls smart_add instead.
411
Note that the command line normally calls smart_add instead,
412
which can automatically recurse.
414
414
This puts the files in the Added state, so that they will be
415
415
recorded by the next commit.
425
425
TODO: Perhaps have an option to add the ids even if the files do
428
TODO: Perhaps return the ids of the files? But then again it
429
is easy to retrieve them if they're needed.
431
TODO: Adding a directory should optionally recurse down and
432
add all non-ignored children. Perhaps do that in a
428
TODO: Perhaps yield the ids and paths as they're added.
435
430
# TODO: Re-adding a file that is removed in the working copy
436
431
# should probably put it back with the previous ID.
472
467
file_id = gen_file_id(f)
473
468
inv.add_path(f, kind=kind, file_id=file_id)
476
print 'added', quotefn(f)
478
470
mutter("add file %s file_id:{%s} kind=%r" % (f, file_id, kind))
480
472
self._write_inventory(inv)
886
878
def lookup_revision(self, revision):
887
879
"""Return the revision identifier for a given revision information."""
888
revno, info = self.get_revision_info(revision)
880
revno, info = self._get_revision_info(revision)
906
898
revision can also be a string, in which case it is parsed for something like
907
899
'date:' or 'revid:' etc.
901
revno, rev_id = self._get_revision_info(revision)
903
raise bzrlib.errors.NoSuchRevision(self, revision)
906
def get_rev_id(self, revno, history=None):
907
"""Find the revision id of the specified revno."""
911
history = self.revision_history()
912
elif revno <= 0 or revno > len(history):
913
raise bzrlib.errors.NoSuchRevision(self, revno)
914
return history[revno - 1]
916
def _get_revision_info(self, revision):
917
"""Return (revno, revision id) for revision specifier.
919
revision can be an integer, in which case it is assumed to be revno
920
(though this will translate negative values into positive ones)
921
revision can also be a string, in which case it is parsed for something
922
like 'date:' or 'revid:' etc.
924
A revid is always returned. If it is None, the specifier referred to
925
the null revision. If the revid does not occur in the revision
926
history, revno will be None.
909
929
if revision is None:
916
936
revs = self.revision_history()
917
937
if isinstance(revision, int):
920
# Mabye we should do this first, but we don't need it if revision == 0
922
939
revno = len(revs) + revision + 1
942
rev_id = self.get_rev_id(revno, revs)
925
943
elif isinstance(revision, basestring):
926
944
for prefix, func in Branch.REVISION_NAMESPACES.iteritems():
927
945
if revision.startswith(prefix):
928
revno = func(self, revs, revision)
946
result = func(self, revs, revision)
948
revno, rev_id = result
951
rev_id = self.get_rev_id(revno, revs)
931
raise BzrError('No namespace registered for string: %r' % revision)
954
raise BzrError('No namespace registered for string: %r' %
957
raise TypeError('Unhandled revision type %s' % revision)
933
if revno is None or revno <= 0 or revno > len(revs):
934
raise BzrError("no such revision %s" % revision)
935
return revno, revs[revno-1]
961
raise bzrlib.errors.NoSuchRevision(self, revision)
937
964
def _namespace_revno(self, revs, revision):
938
965
"""Lookup a revision by revision number"""
939
966
assert revision.startswith('revno:')
941
return int(revision[6:])
968
return (int(revision[6:]),)
942
969
except ValueError:
944
971
REVISION_NAMESPACES['revno:'] = _namespace_revno
946
973
def _namespace_revid(self, revs, revision):
947
974
assert revision.startswith('revid:')
975
rev_id = revision[len('revid:'):]
949
return revs.index(revision[6:]) + 1
977
return revs.index(rev_id) + 1, rev_id
950
978
except ValueError:
952
980
REVISION_NAMESPACES['revid:'] = _namespace_revid
954
982
def _namespace_last(self, revs, revision):
957
985
offset = int(revision[5:])
958
986
except ValueError:
962
990
raise BzrError('You must supply a positive value for --revision last:XXX')
963
return len(revs) - offset + 1
991
return (len(revs) - offset + 1,)
964
992
REVISION_NAMESPACES['last:'] = _namespace_last
966
994
def _namespace_tag(self, revs, revision):
1041
1069
# TODO: Handle timezone.
1042
1070
dt = datetime.datetime.fromtimestamp(r.timestamp)
1043
1071
if first >= dt and (last is None or dt >= last):
1046
1074
for i in range(len(revs)):
1047
1075
r = self.get_revision(revs[i])
1048
1076
# TODO: Handle timezone.
1049
1077
dt = datetime.datetime.fromtimestamp(r.timestamp)
1050
1078
if first <= dt and (last is None or dt <= last):
1052
1080
REVISION_NAMESPACES['date:'] = _namespace_date
1054
1082
def revision_tree(self, revision_id):
1120
1148
inv.rename(file_id, to_dir_id, to_tail)
1122
print "%s => %s" % (from_rel, to_rel)
1124
1150
from_abs = self.abspath(from_rel)
1125
1151
to_abs = self.abspath(to_rel)
1146
1172
Note that to_name is only the last component of the new name;
1147
1173
this doesn't change the directory.
1175
This returns a list of (from_path, to_path) pairs for each
1176
entry that is moved.
1149
1179
self.lock_write()
1151
1181
## TODO: Option to move IDs only
1186
1216
for f in from_paths:
1187
1217
name_tail = splitpath(f)[-1]
1188
1218
dest_path = appendpath(to_name, name_tail)
1189
print "%s => %s" % (f, dest_path)
1219
result.append((f, dest_path))
1190
1220
inv.rename(inv.path2id(f), to_dir_id, name_tail)
1192
1222
os.rename(self.abspath(f), self.abspath(dest_path))
1320
def get_parent(self):
1321
"""Return the parent location of the branch.
1323
This is the default location for push/pull/missing. The usual
1324
pattern is that the user can override it by specifying a
1328
_locs = ['parent', 'pull', 'x-pull']
1331
return self.controlfile(l, 'r').read().strip('\n')
1333
if e.errno != errno.ENOENT:
1338
def set_parent(self, url):
1339
# TODO: Maybe delete old location files?
1340
from bzrlib.atomicfile import AtomicFile
1343
f = AtomicFile(self.controlfilename('parent'))
1352
def check_revno(self, revno):
1354
Check whether a revno corresponds to any revision.
1355
Zero (the NULL revision) is considered valid.
1358
self.check_real_revno(revno)
1360
def check_real_revno(self, revno):
1362
Check whether a revno corresponds to a real revision.
1363
Zero (the NULL revision) is considered invalid
1365
if revno < 1 or revno > self.revno():
1366
raise InvalidRevisionNumber(revno)
1289
1371
class ScratchBranch(Branch):
1290
1372
"""Special test class: a branch that cleans up after itself.
1420
1504
def copy_branch(branch_from, to_location, revision=None):
1421
1505
"""Copy branch_from into the existing directory to_location.
1423
If revision is not None, the head of the new branch will be revision.
1508
If not None, only revisions up to this point will be copied.
1509
The head of the new branch will be that revision.
1512
The name of a local directory that exists but is empty.
1425
1514
from bzrlib.merge import merge
1426
1515
from bzrlib.branch import Branch
1517
assert isinstance(branch_from, Branch)
1518
assert isinstance(to_location, basestring)
1427
1520
br_to = Branch(to_location, init=True)
1428
1521
br_to.set_root_id(branch_from.get_root_id())
1429
1522
if revision is None:
1433
1526
br_to.update_revisions(branch_from, stop_revision=revno)
1434
1527
merge((to_location, -1), (to_location, 0), this_dir=to_location,
1435
1528
check_clean=False, ignore_zero=True)
1436
1530
from_location = pull_loc(branch_from)
1437
br_to.controlfile("x-pull", "wb").write(from_location + "\n")
1531
br_to.set_parent(pull_loc(branch_from))