23
23
from bzrlib.osutils import isdir, quotefn, compact_date, rand_bytes, \
25
25
sha_file, appendpath, file_kind
26
27
from bzrlib.errors import BzrError, InvalidRevisionNumber, InvalidRevisionId
27
28
import bzrlib.errors
28
29
from bzrlib.textui import show_status
120
128
head, tail = os.path.split(f)
122
130
# reached the root, whatever that may be
123
raise BzrError('%r is not in a branch' % orig_f)
131
raise bzrlib.errors.NotBranchError('%s is not in a branch' % orig_f)
136
# XXX: move into bzrlib.errors; subclass BzrError
126
137
class DivergedBranches(Exception):
127
138
def __init__(self, branch1, branch2):
128
139
self.branch1 = branch1
316
327
self.controlfile(f, 'w').write('')
317
328
mutter('created control directory in ' + self.base)
319
pack_xml(Inventory(gen_root_id()), self.controlfile('inventory','w'))
330
# if we want per-tree root ids then this is the place to set
331
# them; they're not needed for now and so ommitted for
333
pack_xml(Inventory(), self.controlfile('inventory','w'))
322
336
def _check_format(self):
400
414
"""Inventory for the working copy.""")
403
def add(self, files, verbose=False, ids=None):
417
def add(self, files, ids=None):
404
418
"""Make files versioned.
406
Note that the command line normally calls smart_add instead.
420
Note that the command line normally calls smart_add instead,
421
which can automatically recurse.
408
423
This puts the files in the Added state, so that they will be
409
424
recorded by the next commit.
419
434
TODO: Perhaps have an option to add the ids even if the files do
422
TODO: Perhaps return the ids of the files? But then again it
423
is easy to retrieve them if they're needed.
425
TODO: Adding a directory should optionally recurse down and
426
add all non-ignored children. Perhaps do that in a
437
TODO: Perhaps yield the ids and paths as they're added.
429
439
# TODO: Re-adding a file that is removed in the working copy
430
440
# should probably put it back with the previous ID.
657
664
from bzrlib.inventory import Inventory
658
665
from bzrlib.xml import unpack_xml
660
return unpack_xml(Inventory, self.inventory_store[inventory_id])
667
return unpack_xml(Inventory, self.get_inventory_xml(inventory_id))
670
def get_inventory_xml(self, inventory_id):
671
"""Get inventory XML as a file object."""
672
return self.inventory_store[inventory_id]
663
675
def get_inventory_sha1(self, inventory_id):
664
676
"""Return the sha1 hash of the inventory entry
666
return sha_file(self.inventory_store[inventory_id])
678
return sha_file(self.get_inventory_xml(inventory_id))
669
681
def get_revision_inventory(self, revision_id):
758
def missing_revisions(self, other, stop_revision=None):
770
def missing_revisions(self, other, stop_revision=None, diverged_ok=False):
760
772
If self and other have not diverged, return a list of the revisions
761
773
present in other, but missing from self.
794
806
if stop_revision is None:
795
807
stop_revision = other_len
796
808
elif stop_revision > other_len:
797
raise NoSuchRevision(self, stop_revision)
809
raise bzrlib.errors.NoSuchRevision(self, stop_revision)
799
811
return other_history[self_len:stop_revision]
802
814
def update_revisions(self, other, stop_revision=None):
803
815
"""Pull in all new revisions from other branch.
805
>>> from bzrlib.commit import commit
806
>>> bzrlib.trace.silent = True
807
>>> br1 = ScratchBranch(files=['foo', 'bar'])
810
>>> commit(br1, "lala!", rev_id="REVISION-ID-1", verbose=False)
811
>>> br2 = ScratchBranch()
812
>>> br2.update_revisions(br1)
816
>>> br2.revision_history()
818
>>> br2.update_revisions(br1)
822
>>> br1.text_store.total_size() == br2.text_store.total_size()
825
from bzrlib.progress import ProgressBar
817
from bzrlib.fetch import greedy_fetch
819
pb = bzrlib.ui.ui_factory.progress_bar()
829
820
pb.update('comparing histories')
830
822
revision_ids = self.missing_revisions(other, stop_revision)
824
if len(revision_ids) > 0:
825
count = greedy_fetch(self, other, revision_ids[-1], pb)[0]
828
self.append_revision(*revision_ids)
829
## note("Added %d revisions." % count)
834
def install_revisions(self, other, revision_ids, pb):
832
835
if hasattr(other.revision_store, "prefetch"):
833
836
other.revision_store.prefetch(revision_ids)
834
837
if hasattr(other.inventory_store, "prefetch"):
835
838
inventory_ids = [other.get_revision(r).inventory_id
836
839
for r in revision_ids]
837
840
other.inventory_store.prefetch(inventory_ids)
843
pb = bzrlib.ui.ui_factory.progress_bar()
840
846
needed_texts = set()
842
for rev_id in revision_ids:
844
pb.update('fetching revision', i, len(revision_ids))
845
rev = other.get_revision(rev_id)
850
for i, rev_id in enumerate(revision_ids):
851
pb.update('fetching revision', i+1, len(revision_ids))
853
rev = other.get_revision(rev_id)
854
except bzrlib.errors.NoSuchRevision:
846
858
revisions.append(rev)
847
859
inv = other.get_inventory(str(rev.inventory_id))
848
860
for key, entry in inv.iter_entries():
856
count = self.text_store.copy_multi(other.text_store, needed_texts)
857
print "Added %d texts." % count
868
count, cp_fail = self.text_store.copy_multi(other.text_store,
870
#print "Added %d texts." % count
858
871
inventory_ids = [ f.inventory_id for f in revisions ]
859
count = self.inventory_store.copy_multi(other.inventory_store,
861
print "Added %d inventories." % count
872
count, cp_fail = self.inventory_store.copy_multi(other.inventory_store,
874
#print "Added %d inventories." % count
862
875
revision_ids = [ f.revision_id for f in revisions]
863
count = self.revision_store.copy_multi(other.revision_store,
865
for revision_id in revision_ids:
866
self.append_revision(revision_id)
867
print "Added %d revisions." % count
877
count, cp_fail = self.revision_store.copy_multi(other.revision_store,
880
assert len(cp_fail) == 0
881
return count, failures
870
884
def commit(self, *args, **kw):
871
885
from bzrlib.commit import commit
872
886
commit(self, *args, **kw)
877
891
revno, info = self.get_revision_info(revision)
895
def revision_id_to_revno(self, revision_id):
896
"""Given a revision id, return its revno"""
897
history = self.revision_history()
899
return history.index(revision_id) + 1
901
raise bzrlib.errors.NoSuchRevision(self, revision_id)
880
904
def get_revision_info(self, revision):
881
905
"""Return (revno, revision id) for revision identifier.
1165
1191
for f in from_paths:
1166
1192
name_tail = splitpath(f)[-1]
1167
1193
dest_path = appendpath(to_name, name_tail)
1168
print "%s => %s" % (f, dest_path)
1194
result.append((f, dest_path))
1169
1195
inv.rename(inv.path2id(f), to_dir_id, name_tail)
1171
1197
os.rename(self.abspath(f), self.abspath(dest_path))