15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22
from bzrlib.trace import mutter, note
22
from bzrlib.osutils import isdir, quotefn, compact_date, rand_bytes, splitpath, \
23
from bzrlib.osutils import isdir, quotefn, compact_date, rand_bytes, \
23
25
sha_file, appendpath, file_kind
24
from bzrlib.errors import BzrError
26
from bzrlib.errors import BzrError, InvalidRevisionNumber, InvalidRevisionId
27
from bzrlib.textui import show_status
28
from bzrlib.revision import Revision
29
from bzrlib.xml import unpack_xml
30
from bzrlib.delta import compare_trees
31
from bzrlib.tree import EmptyTree, RevisionTree
26
33
BZR_BRANCH_FORMAT = "Bazaar-NG branch, format 0.0.4\n"
27
34
## TODO: Maybe include checks for common corruption of newlines, etc?
37
# TODO: Some operations like log might retrieve the same revisions
38
# repeatedly to calculate deltas. We could perhaps have a weakref
39
# cache in memory to make this faster.
31
42
def find_branch(f, **args):
32
43
if f and (f.startswith('http://') or f.startswith('https://')):
422
433
add all non-ignored children. Perhaps do that in a
423
434
higher-level method.
425
from bzrlib.textui import show_status
426
436
# TODO: Re-adding a file that is removed in the working copy
427
437
# should probably put it back with the previous ID.
428
438
if isinstance(files, basestring):
501
511
is the opposite of add. Removing it is consistent with most
502
512
other tools. Maybe an option.
504
from bzrlib.textui import show_status
505
514
## TODO: Normalize names
506
515
## TODO: Remove nested loops; better scalability
507
516
if isinstance(files, basestring):
585
594
def get_revision(self, revision_id):
586
595
"""Return the Revision object for a named revision"""
587
from bzrlib.revision import Revision
588
from bzrlib.xml import unpack_xml
592
598
if not revision_id or not isinstance(revision_id, basestring):
593
raise ValueError('invalid revision-id: %r' % revision_id)
599
raise InvalidRevisionId(revision_id)
594
600
r = unpack_xml(Revision, self.revision_store[revision_id])
598
604
assert r.revision_id == revision_id
608
def get_revision_delta(self, revno):
609
"""Return the delta for one revision.
611
The delta is relative to its mainline predecessor, or the
612
empty tree for revision 1.
614
assert isinstance(revno, int)
615
rh = self.revision_history()
616
if not (1 <= revno <= len(rh)):
617
raise InvalidRevisionNumber(revno)
619
# revno is 1-based; list is 0-based
621
new_tree = self.revision_tree(rh[revno-1])
623
old_tree = EmptyTree()
625
old_tree = self.revision_tree(rh[revno-2])
627
return compare_trees(old_tree, new_tree)
602
631
def get_revision_sha1(self, revision_id):
697
726
return r+1, my_history[r]
698
727
return None, None
700
def enum_history(self, direction):
701
"""Return (revno, revision_id) for history of branch.
704
'forward' is from earliest to latest
705
'reverse' is from latest to earliest
707
rh = self.revision_history()
708
if direction == 'forward':
713
elif direction == 'reverse':
719
raise ValueError('invalid history direction', direction)
723
731
"""Return current revision number for this branch.
1019
1027
`revision_id` may be None for the null revision, in which case
1020
1028
an `EmptyTree` is returned."""
1021
from bzrlib.tree import EmptyTree, RevisionTree
1022
1029
# TODO: refactor this to use an existing revision object
1023
1030
# so we don't need to read it in twice.
1024
1031
if revision_id == None:
1025
return EmptyTree(self.get_root_id())
1027
1034
inv = self.get_revision_inventory(revision_id)
1028
1035
return RevisionTree(self.text_store, inv)
1040
1047
If there are no revisions yet, return an `EmptyTree`.
1042
from bzrlib.tree import EmptyTree, RevisionTree
1043
1049
r = self.last_patch()
1045
return EmptyTree(self.get_root_id())
1047
1053
return RevisionTree(self.text_store, self.get_revision_inventory(r))