~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/branch.py

  • Committer: mbp at sourcefrog
  • Date: 2005-04-04 13:10:26 UTC
  • Revision ID: mbp@sourcefrog.net-20050404131026-628553cc03687658
new 'renames' command

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
     joinpath, sha_string, file_kind, local_time_offset, appendpath
32
32
from store import ImmutableStore
33
33
from revision import Revision
34
 
from errors import bailout, BzrError
 
34
from errors import bailout
35
35
from textui import show_status
36
36
from diff import diff_trees
37
37
 
47
47
 
48
48
    Basically we keep looking up until we find the control directory or
49
49
    run into the root."""
50
 
    if f == None:
 
50
    if f is None:
51
51
        f = os.getcwd()
52
52
    elif hasattr(os.path, 'realpath'):
53
53
        f = os.path.realpath(f)
56
56
 
57
57
    orig_f = f
58
58
 
 
59
    last_f = f
59
60
    while True:
60
61
        if os.path.exists(os.path.join(f, bzrlib.BZRDIR)):
61
62
            return f
62
63
        head, tail = os.path.split(f)
63
64
        if head == f:
64
65
            # reached the root, whatever that may be
65
 
            raise BzrError('%r is not in a branch' % orig_f)
 
66
            bailout('%r is not in a branch' % orig_f)
66
67
        f = head
67
68
    
68
69
 
300
301
        self._write_inventory(inv)
301
302
 
302
303
 
303
 
    def print_file(self, file, revno):
304
 
        """Print `file` to stdout."""
305
 
        tree = self.revision_tree(self.lookup_revision(revno))
306
 
        # use inventory as it was in that revision
307
 
        file_id = tree.inventory.path2id(file)
308
 
        if not file_id:
309
 
            bailout("%r is not present in revision %d" % (file, revno))
310
 
        tree.print_file(file_id)
311
 
        
312
304
 
313
305
    def remove(self, files, verbose=False):
314
306
        """Mark nominated files for removal from the inventory.
555
547
        ## TODO: Also calculate and store the inventory SHA1
556
548
        mutter("committing patch r%d" % (self.revno() + 1))
557
549
 
 
550
        mutter("append to revision-history")
 
551
        f = self.controlfile('revision-history', 'at')
 
552
        f.write(rev_id + '\n')
 
553
        f.close()
558
554
 
559
 
        self.append_revision(rev_id)
560
 
        
561
555
        if verbose:
562
556
            note("commited r%d" % self.revno())
563
557
 
564
558
 
565
 
    def append_revision(self, revision_id):
566
 
        mutter("add {%s} to revision-history" % revision_id)
567
 
        rev_history = self.revision_history()
568
 
 
569
 
        tmprhname = self.controlfilename('revision-history.tmp')
570
 
        rhname = self.controlfilename('revision-history')
571
 
        
572
 
        f = file(tmprhname, 'wt')
573
 
        rev_history.append(revision_id)
574
 
        f.write('\n'.join(rev_history))
575
 
        f.write('\n')
576
 
        f.close()
577
 
 
578
 
        if sys.platform == 'win32':
579
 
            os.remove(rhname)
580
 
        os.rename(tmprhname, rhname)
581
 
        
582
 
 
583
 
 
584
559
    def get_revision(self, revision_id):
585
560
        """Return the Revision object for a named revision"""
586
561
        r = Revision.read_xml(self.revision_store[revision_id])
640
615
        ph = self.revision_history()
641
616
        if ph:
642
617
            return ph[-1]
643
 
        else:
644
 
            return None
645
 
        
 
618
 
646
619
 
647
620
    def lookup_revision(self, revno):
648
621
        """Return revision hash for revision number."""
653
626
            # list is 0-based; revisions are 1-based
654
627
            return self.revision_history()[revno-1]
655
628
        except IndexError:
656
 
            raise BzrError("no such revision %s" % revno)
 
629
            bailout("no such revision %s" % revno)
657
630
 
658
631
 
659
632
    def revision_tree(self, revision_id):
729
702
            precursor = p
730
703
 
731
704
 
732
 
    def rename_one(self, from_rel, to_rel):
733
 
        tree = self.working_tree()
734
 
        inv = tree.inventory
735
 
        if not tree.has_filename(from_rel):
736
 
            bailout("can't rename: old working file %r does not exist" % from_rel)
737
 
        if tree.has_filename(to_rel):
738
 
            bailout("can't rename: new working file %r already exists" % to_rel)
739
 
            
740
 
        file_id = inv.path2id(from_rel)
741
 
        if file_id == None:
742
 
            bailout("can't rename: old name %r is not versioned" % from_rel)
743
 
 
744
 
        if inv.path2id(to_rel):
745
 
            bailout("can't rename: new name %r is already versioned" % to_rel)
746
 
 
747
 
        to_dir, to_tail = os.path.split(to_rel)
748
 
        to_dir_id = inv.path2id(to_dir)
749
 
        if to_dir_id == None and to_dir != '':
750
 
            bailout("can't determine destination directory id for %r" % to_dir)
751
 
 
752
 
        mutter("rename_one:")
753
 
        mutter("  file_id    {%s}" % file_id)
754
 
        mutter("  from_rel   %r" % from_rel)
755
 
        mutter("  to_rel     %r" % to_rel)
756
 
        mutter("  to_dir     %r" % to_dir)
757
 
        mutter("  to_dir_id  {%s}" % to_dir_id)
758
 
            
759
 
        inv.rename(file_id, to_dir_id, to_tail)
760
 
 
761
 
        print "%s => %s" % (from_rel, to_rel)
762
 
        
763
 
        from_abs = self.abspath(from_rel)
764
 
        to_abs = self.abspath(to_rel)
765
 
        try:
766
 
            os.rename(from_abs, to_abs)
767
 
        except OSError, e:
768
 
            bailout("failed to rename %r to %r: %s"
769
 
                    % (from_abs, to_abs, e[1]),
770
 
                    ["rename rolled back"])
771
 
 
772
 
        self._write_inventory(inv)
773
 
            
774
 
 
775
 
 
776
 
    def move(self, from_paths, to_name):
 
705
 
 
706
    def rename(self, from_paths, to_name):
777
707
        """Rename files.
778
708
 
779
 
        to_name must exist as a versioned directory.
780
 
 
781
709
        If to_name exists and is a directory, the files are moved into
782
710
        it, keeping their old names.  If it is a directory, 
783
711
 
788
716
        assert not isinstance(from_paths, basestring)
789
717
        tree = self.working_tree()
790
718
        inv = tree.inventory
791
 
        to_abs = self.abspath(to_name)
792
 
        if not isdir(to_abs):
793
 
            bailout("destination %r is not a directory" % to_abs)
794
 
        if not tree.has_filename(to_name):
795
 
            bailout("destination %r not in working directory" % to_abs)
796
 
        to_dir_id = inv.path2id(to_name)
797
 
        if to_dir_id == None and to_name != '':
798
 
            bailout("destination %r is not a versioned directory" % to_name)
799
 
        to_dir_ie = inv[to_dir_id]
800
 
        if to_dir_ie.kind not in ('directory', 'root_directory'):
801
 
            bailout("destination %r is not a directory" % to_abs)
802
 
 
803
 
        to_idpath = Set(inv.get_idpath(to_dir_id))
804
 
 
805
 
        for f in from_paths:
806
 
            if not tree.has_filename(f):
807
 
                bailout("%r does not exist in working tree" % f)
808
 
            f_id = inv.path2id(f)
809
 
            if f_id == None:
810
 
                bailout("%r is not versioned" % f)
811
 
            name_tail = splitpath(f)[-1]
812
 
            dest_path = appendpath(to_name, name_tail)
813
 
            if tree.has_filename(dest_path):
814
 
                bailout("destination %r already exists" % dest_path)
815
 
            if f_id in to_idpath:
816
 
                bailout("can't move %r to a subdirectory of itself" % f)
817
 
 
818
 
        # OK, so there's a race here, it's possible that someone will
819
 
        # create a file in this interval and then the rename might be
820
 
        # left half-done.  But we should have caught most problems.
821
 
 
822
 
        for f in from_paths:
823
 
            name_tail = splitpath(f)[-1]
824
 
            dest_path = appendpath(to_name, name_tail)
825
 
            print "%s => %s" % (f, dest_path)
826
 
            inv.rename(inv.path2id(f), to_dir_id, name_tail)
827
 
            try:
 
719
        dest_dir = isdir(self.abspath(to_name))
 
720
        if dest_dir:
 
721
            # TODO: Wind back properly if some can't be moved?
 
722
            dest_dir_id = inv.path2id(to_name)
 
723
            if not dest_dir_id and to_name != '':
 
724
                bailout("destination %r is not a versioned directory" % to_name)
 
725
            for f in from_paths:
 
726
                name_tail = splitpath(f)[-1]
 
727
                dest_path = appendpath(to_name, name_tail)
 
728
                print "%s => %s" % (f, dest_path)
 
729
                inv.rename(inv.path2id(f), dest_dir_id, name_tail)
828
730
                os.rename(self.abspath(f), self.abspath(dest_path))
829
 
            except OSError, e:
830
 
                bailout("failed to rename %r to %r: %s" % (f, dest_path, e[1]),
831
 
                        ["rename rolled back"])
832
 
 
833
 
        self._write_inventory(inv)
834
 
 
835
 
 
836
 
 
837
 
    def show_status(self, show_all=False):
 
731
            self._write_inventory(inv)
 
732
        else:
 
733
            if len(from_paths) != 1:
 
734
                bailout("when moving multiple files, destination must be a directory")
 
735
            bailout("rename to non-directory %r not implemented sorry" % to_name)
 
736
 
 
737
 
 
738
 
 
739
    def show_status(branch, show_all=False):
838
740
        """Display single-line status for non-ignored working files.
839
741
 
840
742
        The list is show sorted in order by file name.
867
769
        # Interesting case: the old ID for a file has been removed,
868
770
        # but a new file has been created under that name.
869
771
 
870
 
        old = self.basis_tree()
871
 
        new = self.working_tree()
 
772
        old = branch.basis_tree()
 
773
        old_inv = old.inventory
 
774
        new = branch.working_tree()
 
775
        new_inv = new.inventory
872
776
 
873
777
        for fs, fid, oldname, newname, kind in diff_trees(old, new):
874
778
            if fs == 'R':