15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
22
from bzrlib.trace import mutter, note
23
from bzrlib.osutils import isdir, quotefn, compact_date, rand_bytes, \
23
from bzrlib.osutils import isdir, quotefn, compact_date, rand_bytes, splitpath, \
25
24
sha_file, appendpath, file_kind
26
from bzrlib.errors import BzrError, InvalidRevisionNumber, InvalidRevisionId
25
from bzrlib.errors import BzrError
28
26
from bzrlib.textui import show_status
29
from bzrlib.revision import Revision
30
from bzrlib.xml import unpack_xml
31
from bzrlib.delta import compare_trees
32
from bzrlib.tree import EmptyTree, RevisionTree
34
28
BZR_BRANCH_FORMAT = "Bazaar-NG branch, format 0.0.4\n"
35
29
## TODO: Maybe include checks for common corruption of newlines, etc?
38
# TODO: Some operations like log might retrieve the same revisions
39
# repeatedly to calculate deltas. We could perhaps have a weakref
40
# cache in memory to make this faster.
43
33
def find_branch(f, **args):
44
34
if f and (f.startswith('http://') or f.startswith('https://')):
130
120
Exception.__init__(self, "These branches have diverged.")
123
class NoSuchRevision(BzrError):
124
def __init__(self, branch, revision):
126
self.revision = revision
127
msg = "Branch %s has no revision %d" % (branch, revision)
128
BzrError.__init__(self, msg)
133
131
######################################################################
587
def get_revision_xml(self, revision_id):
588
"""Return XML file object for revision object."""
589
if not revision_id or not isinstance(revision_id, basestring):
590
raise InvalidRevisionId(revision_id)
595
return self.revision_store[revision_id]
597
raise bzrlib.errors.NoSuchRevision(revision_id)
602
585
def get_revision(self, revision_id):
603
586
"""Return the Revision object for a named revision"""
604
xml_file = self.get_revision_xml(revision_id)
587
from bzrlib.revision import Revision
588
from bzrlib.xml import unpack_xml
607
r = unpack_xml(Revision, xml_file)
608
except SyntaxError, e:
609
raise bzrlib.errors.BzrError('failed to unpack revision_xml',
592
if not revision_id or not isinstance(revision_id, basestring):
593
raise ValueError('invalid revision-id: %r' % revision_id)
594
r = unpack_xml(Revision, self.revision_store[revision_id])
613
598
assert r.revision_id == revision_id
617
def get_revision_delta(self, revno):
618
"""Return the delta for one revision.
620
The delta is relative to its mainline predecessor, or the
621
empty tree for revision 1.
623
assert isinstance(revno, int)
624
rh = self.revision_history()
625
if not (1 <= revno <= len(rh)):
626
raise InvalidRevisionNumber(revno)
628
# revno is 1-based; list is 0-based
630
new_tree = self.revision_tree(rh[revno-1])
632
old_tree = EmptyTree()
634
old_tree = self.revision_tree(rh[revno-2])
636
return compare_trees(old_tree, new_tree)
640
602
def get_revision_sha1(self, revision_id):
645
607
# the revision, (add signatures/remove signatures) and still
646
608
# have all hash pointers stay consistent.
647
609
# But for now, just hash the contents.
648
return bzrlib.osutils.sha_file(self.get_revision_xml(revision_id))
610
return sha_file(self.revision_store[revision_id])
651
613
def get_inventory(self, inventory_id):
735
697
return r+1, my_history[r]
736
698
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)
740
723
"""Return current revision number for this branch.
1036
1019
`revision_id` may be None for the null revision, in which case
1037
1020
an `EmptyTree` is returned."""
1021
from bzrlib.tree import EmptyTree, RevisionTree
1038
1022
# TODO: refactor this to use an existing revision object
1039
1023
# so we don't need to read it in twice.
1040
1024
if revision_id == None:
1025
return EmptyTree(self.get_root_id())
1043
1027
inv = self.get_revision_inventory(revision_id)
1044
1028
return RevisionTree(self.text_store, inv)
1056
1040
If there are no revisions yet, return an `EmptyTree`.
1042
from bzrlib.tree import EmptyTree, RevisionTree
1058
1043
r = self.last_patch()
1045
return EmptyTree(self.get_root_id())
1062
1047
return RevisionTree(self.text_store, self.get_revision_inventory(r))