/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: Martin Pool
  • Date: 2005-08-29 07:13:09 UTC
  • Revision ID: mbp@sourcefrog.net-20050829071309-2c62f851915b9825
- bzr log --show-ids includes parent ids

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
from bzrlib.osutils import isdir, quotefn, compact_date, rand_bytes, \
24
24
     splitpath, \
25
25
     sha_file, appendpath, file_kind
 
26
 
26
27
from bzrlib.errors import BzrError, InvalidRevisionNumber, InvalidRevisionId
27
28
import bzrlib.errors
28
29
from bzrlib.textui import show_status
30
31
from bzrlib.xml import unpack_xml
31
32
from bzrlib.delta import compare_trees
32
33
from bzrlib.tree import EmptyTree, RevisionTree
33
 
        
 
34
import bzrlib.ui
 
35
 
 
36
 
 
37
 
34
38
BZR_BRANCH_FORMAT = "Bazaar-NG branch, format 0.0.4\n"
35
39
## TODO: Maybe include checks for common corruption of newlines, etc?
36
40
 
39
43
# repeatedly to calculate deltas.  We could perhaps have a weakref
40
44
# cache in memory to make this faster.
41
45
 
 
46
# TODO: please move the revision-string syntax stuff out of the branch
 
47
# object; it's clutter
 
48
 
42
49
 
43
50
def find_branch(f, **args):
44
51
    if f and (f.startswith('http://') or f.startswith('https://')):
101
108
    It is not necessary that f exists.
102
109
 
103
110
    Basically we keep looking up until we find the control directory or
104
 
    run into the root."""
 
111
    run into the root.  If there isn't one, raises NotBranchError.
 
112
    """
105
113
    if f == None:
106
114
        f = os.getcwd()
107
115
    elif hasattr(os.path, 'realpath'):
120
128
        head, tail = os.path.split(f)
121
129
        if head == 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)
124
132
        f = head
125
 
    
 
133
 
 
134
 
 
135
 
 
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)
318
329
 
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
 
332
        # simplicity.
 
333
        pack_xml(Inventory(), self.controlfile('inventory','w'))
320
334
 
321
335
 
322
336
    def _check_format(self):
400
414
                         """Inventory for the working copy.""")
401
415
 
402
416
 
403
 
    def add(self, files, verbose=False, ids=None):
 
417
    def add(self, files, ids=None):
404
418
        """Make files versioned.
405
419
 
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.
407
422
 
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
420
435
              not (yet) exist.
421
436
 
422
 
        TODO: Perhaps return the ids of the files?  But then again it
423
 
              is easy to retrieve them if they're needed.
424
 
 
425
 
        TODO: Adding a directory should optionally recurse down and
426
 
              add all non-ignored children.  Perhaps do that in a
427
 
              higher-level method.
 
437
        TODO: Perhaps yield the ids and paths as they're added.
428
438
        """
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.
466
476
                    file_id = gen_file_id(f)
467
477
                inv.add_path(f, kind=kind, file_id=file_id)
468
478
 
469
 
                if verbose:
470
 
                    print 'added', quotefn(f)
471
 
 
472
479
                mutter("add file %s file_id:{%s} kind=%r" % (f, file_id, kind))
473
480
 
474
481
            self._write_inventory(inv)
594
601
            try:
595
602
                return self.revision_store[revision_id]
596
603
            except IndexError:
597
 
                raise bzrlib.errors.NoSuchRevision(revision_id)
 
604
                raise bzrlib.errors.NoSuchRevision(self, revision_id)
598
605
        finally:
599
606
            self.unlock()
600
607
 
657
664
        from bzrlib.inventory import Inventory
658
665
        from bzrlib.xml import unpack_xml
659
666
 
660
 
        return unpack_xml(Inventory, self.inventory_store[inventory_id])
 
667
        return unpack_xml(Inventory, self.get_inventory_xml(inventory_id))
 
668
 
 
669
 
 
670
    def get_inventory_xml(self, inventory_id):
 
671
        """Get inventory XML as a file object."""
 
672
        return self.inventory_store[inventory_id]
661
673
            
662
674
 
663
675
    def get_inventory_sha1(self, inventory_id):
664
676
        """Return the sha1 hash of the inventory entry
665
677
        """
666
 
        return sha_file(self.inventory_store[inventory_id])
 
678
        return sha_file(self.get_inventory_xml(inventory_id))
667
679
 
668
680
 
669
681
    def get_revision_inventory(self, revision_id):
755
767
            return None
756
768
 
757
769
 
758
 
    def missing_revisions(self, other, stop_revision=None):
 
770
    def missing_revisions(self, other, stop_revision=None, diverged_ok=False):
759
771
        """
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)
798
810
        
799
811
        return other_history[self_len:stop_revision]
800
812
 
801
813
 
802
814
    def update_revisions(self, other, stop_revision=None):
803
815
        """Pull in all new revisions from other branch.
804
 
        
805
 
        >>> from bzrlib.commit import commit
806
 
        >>> bzrlib.trace.silent = True
807
 
        >>> br1 = ScratchBranch(files=['foo', 'bar'])
808
 
        >>> br1.add('foo')
809
 
        >>> br1.add('bar')
810
 
        >>> commit(br1, "lala!", rev_id="REVISION-ID-1", verbose=False)
811
 
        >>> br2 = ScratchBranch()
812
 
        >>> br2.update_revisions(br1)
813
 
        Added 2 texts.
814
 
        Added 1 inventories.
815
 
        Added 1 revisions.
816
 
        >>> br2.revision_history()
817
 
        [u'REVISION-ID-1']
818
 
        >>> br2.update_revisions(br1)
819
 
        Added 0 texts.
820
 
        Added 0 inventories.
821
 
        Added 0 revisions.
822
 
        >>> br1.text_store.total_size() == br2.text_store.total_size()
823
 
        True
824
816
        """
825
 
        from bzrlib.progress import ProgressBar
826
 
 
827
 
        pb = ProgressBar()
828
 
 
 
817
        from bzrlib.fetch import greedy_fetch
 
818
 
 
819
        pb = bzrlib.ui.ui_factory.progress_bar()
829
820
        pb.update('comparing histories')
 
821
 
830
822
        revision_ids = self.missing_revisions(other, stop_revision)
831
823
 
 
824
        if len(revision_ids) > 0:
 
825
            count = greedy_fetch(self, other, revision_ids[-1], pb)[0]
 
826
        else:
 
827
            count = 0
 
828
        self.append_revision(*revision_ids)
 
829
        ## note("Added %d revisions." % count)
 
830
        pb.clear()
 
831
 
 
832
        
 
833
        
 
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)
 
841
 
 
842
        if pb is None:
 
843
            pb = bzrlib.ui.ui_factory.progress_bar()
838
844
                
839
845
        revisions = []
840
846
        needed_texts = set()
841
847
        i = 0
842
 
        for rev_id in revision_ids:
843
 
            i += 1
844
 
            pb.update('fetching revision', i, len(revision_ids))
845
 
            rev = other.get_revision(rev_id)
 
848
 
 
849
        failures = set()
 
850
        for i, rev_id in enumerate(revision_ids):
 
851
            pb.update('fetching revision', i+1, len(revision_ids))
 
852
            try:
 
853
                rev = other.get_revision(rev_id)
 
854
            except bzrlib.errors.NoSuchRevision:
 
855
                failures.add(rev_id)
 
856
                continue
 
857
 
846
858
            revisions.append(rev)
847
859
            inv = other.get_inventory(str(rev.inventory_id))
848
860
            for key, entry in inv.iter_entries():
853
865
 
854
866
        pb.clear()
855
867
                    
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, 
 
869
                                                    needed_texts)
 
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, 
860
 
                                                inventory_ids)
861
 
        print "Added %d inventories." % count 
 
872
        count, cp_fail = self.inventory_store.copy_multi(other.inventory_store, 
 
873
                                                         inventory_ids)
 
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, 
864
 
                                               revision_ids)
865
 
        for revision_id in revision_ids:
866
 
            self.append_revision(revision_id)
867
 
        print "Added %d revisions." % count
868
 
                    
869
 
        
 
876
 
 
877
        count, cp_fail = self.revision_store.copy_multi(other.revision_store, 
 
878
                                                          revision_ids,
 
879
                                                          permit_failure=True)
 
880
        assert len(cp_fail) == 0 
 
881
        return count, failures
 
882
       
 
883
 
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)
878
892
        return info
879
893
 
 
894
 
 
895
    def revision_id_to_revno(self, revision_id):
 
896
        """Given a revision id, return its revno"""
 
897
        history = self.revision_history()
 
898
        try:
 
899
            return history.index(revision_id) + 1
 
900
        except ValueError:
 
901
            raise bzrlib.errors.NoSuchRevision(self, revision_id)
 
902
 
 
903
 
880
904
    def get_revision_info(self, revision):
881
905
        """Return (revno, revision id) for revision identifier.
882
906
 
1098
1122
 
1099
1123
            inv.rename(file_id, to_dir_id, to_tail)
1100
1124
 
1101
 
            print "%s => %s" % (from_rel, to_rel)
1102
 
 
1103
1125
            from_abs = self.abspath(from_rel)
1104
1126
            to_abs = self.abspath(to_rel)
1105
1127
            try:
1124
1146
 
1125
1147
        Note that to_name is only the last component of the new name;
1126
1148
        this doesn't change the directory.
 
1149
 
 
1150
        This returns a list of (from_path, to_path) pairs for each
 
1151
        entry that is moved.
1127
1152
        """
 
1153
        result = []
1128
1154
        self.lock_write()
1129
1155
        try:
1130
1156
            ## TODO: Option to move IDs only
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)
1170
1196
                try:
1171
1197
                    os.rename(self.abspath(f), self.abspath(dest_path))
1177
1203
        finally:
1178
1204
            self.unlock()
1179
1205
 
 
1206
        return result
 
1207
 
1180
1208
 
1181
1209
    def revert(self, filenames, old_tree=None, backups=True):
1182
1210
        """Restore selected files to the versions from a previous tree.