/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/workingtree.py

  • Committer: Martin Pool
  • Date: 2007-09-14 06:31:28 UTC
  • mfrom: (2822 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2823.
  • Revision ID: mbp@sourcefrog.net-20070914063128-0p7mh6zfb4pzdg9p
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
399
399
            # the basis tree is a ghost so return an empty tree.
400
400
            return self.branch.repository.revision_tree(None)
401
401
 
 
402
    def _cleanup(self):
 
403
        self._flush_ignore_list_cache()
 
404
 
402
405
    @staticmethod
403
406
    @deprecated_method(zero_eight)
404
407
    def create(branch, directory):
448
451
    def has_filename(self, filename):
449
452
        return osutils.lexists(self.abspath(filename))
450
453
 
451
 
    def get_file(self, file_id):
452
 
        file_id = osutils.safe_file_id(file_id)
453
 
        return self.get_file_byname(self.id2path(file_id))
 
454
    def get_file(self, file_id, path=None):
 
455
        if path is None:
 
456
            file_id = osutils.safe_file_id(file_id)
 
457
            path = self.id2path(file_id)
 
458
        return self.get_file_byname(path)
454
459
 
455
460
    def get_file_text(self, file_id):
456
461
        file_id = osutils.safe_file_id(file_id)
460
465
        return file(self.abspath(filename), 'rb')
461
466
 
462
467
    @needs_read_lock
463
 
    def annotate_iter(self, file_id):
 
468
    def annotate_iter(self, file_id, default_revision=CURRENT_REVISION):
464
469
        """See Tree.annotate_iter
465
470
 
466
471
        This implementation will use the basis tree implementation if possible.
493
498
                    continue
494
499
                old.append(list(tree.annotate_iter(file_id)))
495
500
            return annotate.reannotate(old, self.get_file(file_id).readlines(),
496
 
                                       CURRENT_REVISION)
 
501
                                       default_revision)
497
502
        finally:
498
503
            basis.unlock()
499
504
 
 
505
    def _get_ancestors(self, default_revision):
 
506
        ancestors = set([default_revision])
 
507
        for parent_id in self.get_parent_ids():
 
508
            ancestors.update(self.branch.repository.get_ancestry(
 
509
                             parent_id, topo_sorted=False))
 
510
        return ancestors
 
511
 
500
512
    def get_parent_ids(self):
501
513
        """See Tree.get_parent_ids.
502
514
        
793
805
        self._control_files.put(filename, my_file)
794
806
 
795
807
    @needs_write_lock # because merge pulls data into the branch.
796
 
    def merge_from_branch(self, branch, to_revision=None):
 
808
    def merge_from_branch(self, branch, to_revision=None, from_revision=None,
 
809
        merge_type=None):
797
810
        """Merge from a branch into this working tree.
798
811
 
799
812
        :param branch: The branch to merge from.
824
837
                merger.other_rev_id)
825
838
            merger.other_branch = branch
826
839
            merger.pp.next_phase()
827
 
            merger.find_base()
 
840
            if from_revision is None:
 
841
                merger.find_base()
 
842
            else:
 
843
                merger.set_base_revision(from_revision, branch)
828
844
            if merger.base_rev_id == merger.other_rev_id:
829
845
                raise errors.PointlessMerge
830
846
            merger.backup_files = False
831
 
            merger.merge_type = Merge3Merger
 
847
            if merge_type is None:
 
848
                merger.merge_type = Merge3Merger
 
849
            else:
 
850
                merger.merge_type = merge_type
832
851
            merger.set_interesting_files(None)
833
852
            merger.show_base = False
834
853
            merger.reprocess = False
976
995
        return wt
977
996
 
978
997
    def _serialize(self, inventory, out_file):
979
 
        xml5.serializer_v5.write_inventory(self._inventory, out_file)
 
998
        xml5.serializer_v5.write_inventory(self._inventory, out_file,
 
999
            working=True)
980
1000
 
981
1001
    def _deserialize(selt, in_file):
982
1002
        return xml5.serializer_v5.read_inventory(in_file)
1554
1574
        if ignoreset is not None:
1555
1575
            return ignoreset
1556
1576
 
1557
 
        ignore_globs = set(bzrlib.DEFAULT_IGNORE)
 
1577
        ignore_globs = set()
1558
1578
        ignore_globs.update(ignores.get_runtime_ignores())
1559
1579
        ignore_globs.update(ignores.get_user_ignores())
1560
1580
        if self.has_filename(bzrlib.IGNORE_FILENAME):
1623
1643
    @needs_read_lock
1624
1644
    def _last_revision(self):
1625
1645
        """helper for get_parent_ids."""
1626
 
        return self.branch.last_revision()
 
1646
        return _mod_revision.ensure_null(self.branch.last_revision())
1627
1647
 
1628
1648
    def is_locked(self):
1629
1649
        return self._control_files.is_locked()
1774
1794
        :force: Delete files and directories, even if they are changed and
1775
1795
            even if the directories are not empty.
1776
1796
        """
1777
 
        ## TODO: Normalize names
1778
 
 
1779
1797
        if isinstance(files, basestring):
1780
1798
            files = [files]
1781
1799
 
1782
1800
        inv_delta = []
1783
1801
 
1784
1802
        new_files=set()
1785
 
        unknown_files_in_directory=set()
 
1803
        unknown_nested_files=set()
1786
1804
 
1787
1805
        def recurse_directory_to_add_files(directory):
1788
 
            # recurse directory and add all files
 
1806
            # Recurse directory and add all files
1789
1807
            # so we can check if they have changed.
1790
1808
            for parent_info, file_infos in\
1791
1809
                osutils.walkdirs(self.abspath(directory),
1792
1810
                    directory):
1793
1811
                for relpath, basename, kind, lstat, abspath in file_infos:
1794
 
                    if kind == 'file':
1795
 
                        if self.path2id(relpath): #is it versioned?
1796
 
                            new_files.add(relpath)
1797
 
                        else:
1798
 
                            unknown_files_in_directory.add(
1799
 
                                (relpath, None, kind))
 
1812
                    # Is it versioned or ignored?
 
1813
                    if self.path2id(relpath) or self.is_ignored(relpath):
 
1814
                        # Add nested content for deletion.
 
1815
                        new_files.add(relpath)
 
1816
                    else:
 
1817
                        # Files which are not versioned and not ignored
 
1818
                        # should be treated as unknown.
 
1819
                        unknown_nested_files.add((relpath, None, kind))
1800
1820
 
1801
1821
        for filename in files:
1802
1822
            # Get file name into canonical form.
1806
1826
                new_files.add(filename)
1807
1827
                if osutils.isdir(abspath):
1808
1828
                    recurse_directory_to_add_files(filename)
1809
 
        files = [f for f in new_files]
 
1829
 
 
1830
        files = list(new_files)
1810
1831
 
1811
1832
        if len(files) == 0:
1812
1833
            return # nothing to do
1813
1834
 
1814
1835
        # Sort needed to first handle directory content before the directory
1815
1836
        files.sort(reverse=True)
 
1837
 
 
1838
        # Bail out if we are going to delete files we shouldn't
1816
1839
        if not keep_files and not force:
1817
 
            has_changed_files = len(unknown_files_in_directory) > 0
 
1840
            has_changed_files = len(unknown_nested_files) > 0
1818
1841
            if not has_changed_files:
1819
1842
                for (file_id, path, content_change, versioned, parent_id, name,
1820
1843
                     kind, executable) in self._iter_changes(self.basis_tree(),
1821
1844
                         include_unchanged=True, require_versioned=False,
1822
1845
                         want_unversioned=True, specific_files=files):
1823
 
                    # check if it's unknown OR changed but not deleted:
1824
 
                    if (versioned == (False, False)
1825
 
                        or (content_change and kind[1] != None)):
 
1846
                    # Check if it's an unknown (but not ignored) OR
 
1847
                    # changed (but not deleted) :
 
1848
                    if not self.is_ignored(path[1]) and (
 
1849
                        versioned == (False, False) or
 
1850
                        content_change and kind[1] != None):
1826
1851
                        has_changed_files = True
1827
1852
                        break
1828
1853
 
1829
1854
            if has_changed_files:
1830
 
                # make delta to show ALL applicable changes in error message.
 
1855
                # Make delta show ALL applicable changes in error message.
1831
1856
                tree_delta = self.changes_from(self.basis_tree(),
 
1857
                    require_versioned=False, want_unversioned=True,
1832
1858
                    specific_files=files)
1833
 
                for unknown_file in unknown_files_in_directory:
1834
 
                    tree_delta.unversioned.extend((unknown_file,))
 
1859
                for unknown_file in unknown_nested_files:
 
1860
                    if unknown_file not in tree_delta.unversioned:
 
1861
                        tree_delta.unversioned.extend((unknown_file,))
1835
1862
                raise errors.BzrRemoveChangedFilesError(tree_delta)
1836
1863
 
1837
 
        # do this before any modifications
 
1864
        # Build inv_delta and delete files where applicaple,
 
1865
        # do this before any modifications to inventory.
1838
1866
        for f in files:
1839
1867
            fid = self.path2id(f)
1840
 
            message=None
 
1868
            message = None
1841
1869
            if not fid:
1842
 
                message="%s is not versioned." % (f,)
 
1870
                message = "%s is not versioned." % (f,)
1843
1871
            else:
1844
1872
                if verbose:
1845
1873
                    # having removed it, it must be either ignored or unknown
1849
1877
                        new_status = '?'
1850
1878
                    textui.show_status(new_status, self.kind(fid), f,
1851
1879
                                       to_file=to_file)
1852
 
                # unversion file
 
1880
                # Unversion file
1853
1881
                inv_delta.append((f, None, fid, None))
1854
 
                message="removed %s" % (f,)
 
1882
                message = "removed %s" % (f,)
1855
1883
 
1856
1884
            if not keep_files:
1857
1885
                abs_path = self.abspath(f)
1858
1886
                if osutils.lexists(abs_path):
1859
1887
                    if (osutils.isdir(abs_path) and
1860
1888
                        len(os.listdir(abs_path)) > 0):
1861
 
                        message="%s is not empty directory "\
1862
 
                            "and won't be deleted." % (f,)
 
1889
                        if force:
 
1890
                            osutils.rmtree(abs_path)
 
1891
                        else:
 
1892
                            message = "%s is not an empty directory "\
 
1893
                                "and won't be deleted." % (f,)
1863
1894
                    else:
1864
1895
                        osutils.delete_any(abs_path)
1865
 
                        message="deleted %s" % (f,)
 
1896
                        message = "deleted %s" % (f,)
1866
1897
                elif message is not None:
1867
 
                    # only care if we haven't done anything yet.
1868
 
                    message="%s does not exist." % (f,)
 
1898
                    # Only care if we haven't done anything yet.
 
1899
                    message = "%s does not exist." % (f,)
1869
1900
 
1870
 
            # print only one message (if any) per file.
 
1901
            # Print only one message (if any) per file.
1871
1902
            if message is not None:
1872
1903
                note(message)
1873
1904
        self.apply_inventory_delta(inv_delta)
1874
1905
 
1875
1906
    @needs_tree_write_lock
1876
 
    def revert(self, filenames, old_tree=None, backups=True, 
 
1907
    def revert(self, filenames=None, old_tree=None, backups=True,
1877
1908
               pb=DummyProgress(), report_changes=False):
1878
1909
        from bzrlib.conflicts import resolve
 
1910
        if filenames == []:
 
1911
            filenames = None
 
1912
            symbol_versioning.warn('Using [] to revert all files is deprecated'
 
1913
                ' as of bzr 0.91.  Please use None (the default) instead.',
 
1914
                DeprecationWarning, stacklevel=2)
1879
1915
        if old_tree is None:
1880
1916
            old_tree = self.basis_tree()
1881
1917
        conflicts = transform.revert(self, old_tree, filenames, backups, pb,
1882
1918
                                     report_changes)
1883
 
        if not len(filenames):
 
1919
        if filenames is None:
1884
1920
            self.set_parent_ids(self.get_parent_ids()[:1])
1885
1921
            resolve(self)
1886
1922
        else:
1987
2023
        """
1988
2024
        raise NotImplementedError(self.unlock)
1989
2025
 
1990
 
    def update(self, change_reporter=None):
 
2026
    def update(self, change_reporter=None, possible_transports=None):
1991
2027
        """Update a working tree along its branch.
1992
2028
 
1993
2029
        This will update the branch if its bound too, which means we have
2012
2048
          basis.
2013
2049
        - Do a 'normal' merge of the old branch basis if it is relevant.
2014
2050
        """
2015
 
        if self.branch.get_master_branch() is not None:
 
2051
        if self.branch.get_master_branch(possible_transports) is not None:
2016
2052
            self.lock_write()
2017
2053
            update_branch = True
2018
2054
        else:
2020
2056
            update_branch = False
2021
2057
        try:
2022
2058
            if update_branch:
2023
 
                old_tip = self.branch.update()
 
2059
                old_tip = self.branch.update(possible_transports)
2024
2060
            else:
2025
2061
                old_tip = None
2026
2062
            return self._update_tree(old_tip, change_reporter)
2392
2428
            raise
2393
2429
 
2394
2430
    def unlock(self):
 
2431
        # do non-implementation specific cleanup
 
2432
        self._cleanup()
 
2433
 
2395
2434
        # we share control files:
2396
2435
        if self._control_files._lock_count == 3:
2397
2436
            # _inventory_is_modified is always False during a read lock.
2423
2462
            return osutils.safe_revision_id(
2424
2463
                        self._control_files.get('last-revision').read())
2425
2464
        except errors.NoSuchFile:
2426
 
            return None
 
2465
            return _mod_revision.NULL_REVISION
2427
2466
 
2428
2467
    def _change_last_revision(self, revision_id):
2429
2468
        """See WorkingTree._change_last_revision."""
2463
2502
        return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2464
2503
 
2465
2504
    def unlock(self):
 
2505
        # do non-implementation specific cleanup
 
2506
        self._cleanup()
2466
2507
        if self._control_files._lock_count == 1:
2467
2508
            # _inventory_is_modified is always False during a read lock.
2468
2509
            if self._inventory_is_modified:
2600
2641
        """
2601
2642
        sio = StringIO()
2602
2643
        inv = Inventory()
2603
 
        xml5.serializer_v5.write_inventory(inv, sio)
 
2644
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2604
2645
        sio.seek(0)
2605
2646
        control_files.put('inventory', sio)
2606
2647