~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

  • Committer: John Arbash Meinel
  • Date: 2009-07-29 21:35:05 UTC
  • mfrom: (4576 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4577.
  • Revision ID: john@arbash-meinel.com-20090729213505-tkqsvy1zfpocu75w
Merge bzr.dev 4576 in prep for NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
442
442
        conflicts.extend(self._overwrite_conflicts())
443
443
        return conflicts
444
444
 
 
445
    def _check_malformed(self):
 
446
        conflicts = self.find_conflicts()
 
447
        if len(conflicts) != 0:
 
448
            raise MalformedTransform(conflicts=conflicts)
 
449
 
445
450
    def _add_tree_children(self):
446
451
        """Add all the children of all active parents to the known paths.
447
452
 
859
864
        """
860
865
        return _PreviewTree(self)
861
866
 
 
867
    def commit(self, branch, message, merge_parents=None, strict=False):
 
868
        """Commit the result of this TreeTransform to a branch.
 
869
 
 
870
        :param branch: The branch to commit to.
 
871
        :param message: The message to attach to the commit.
 
872
        :param merge_parents: Additional parents specified by pending merges.
 
873
        :return: The revision_id of the revision committed.
 
874
        """
 
875
        self._check_malformed()
 
876
        if strict:
 
877
            unversioned = set(self._new_contents).difference(set(self._new_id))
 
878
            for trans_id in unversioned:
 
879
                if self.final_file_id(trans_id) is None:
 
880
                    raise errors.StrictCommitFailed()
 
881
 
 
882
        revno, last_rev_id = branch.last_revision_info()
 
883
        if last_rev_id == _mod_revision.NULL_REVISION:
 
884
            if merge_parents is not None:
 
885
                raise ValueError('Cannot supply merge parents for first'
 
886
                                 ' commit.')
 
887
            parent_ids = []
 
888
        else:
 
889
            parent_ids = [last_rev_id]
 
890
            if merge_parents is not None:
 
891
                parent_ids.extend(merge_parents)
 
892
        if self._tree.get_revision_id() != last_rev_id:
 
893
            raise ValueError('TreeTransform not based on branch basis: %s' %
 
894
                             self._tree.get_revision_id())
 
895
        builder = branch.get_commit_builder(parent_ids)
 
896
        preview = self.get_preview_tree()
 
897
        list(builder.record_iter_changes(preview, last_rev_id,
 
898
                                         self.iter_changes()))
 
899
        builder.finish_inventory()
 
900
        revision_id = builder.commit(message)
 
901
        branch.set_last_revision_info(revno + 1, revision_id)
 
902
        return revision_id
 
903
 
862
904
    def _text_parent(self, trans_id):
863
905
        file_id = self.tree_file_id(trans_id)
864
906
        try:
995
1037
                       self._new_contents.iteritems()]
996
1038
            entries.sort(reverse=True)
997
1039
            for path, trans_id, kind in entries:
998
 
                if kind == "directory":
999
 
                    os.rmdir(path)
1000
 
                else:
1001
 
                    os.unlink(path)
 
1040
                delete_any(path)
1002
1041
            try:
1003
 
                os.rmdir(self._limbodir)
 
1042
                delete_any(self._limbodir)
1004
1043
            except OSError:
1005
1044
                # We don't especially care *why* the dir is immortal.
1006
1045
                raise ImmortalLimbo(self._limbodir)
1007
1046
            try:
1008
1047
                if self._deletiondir is not None:
1009
 
                    os.rmdir(self._deletiondir)
 
1048
                    delete_any(self._deletiondir)
1010
1049
            except OSError:
1011
1050
                raise errors.ImmortalPendingDeletion(self._deletiondir)
1012
1051
        finally:
1357
1396
                continue
1358
1397
            yield self.trans_id_tree_path(childpath)
1359
1398
 
1360
 
 
1361
1399
    def apply(self, no_conflicts=False, precomputed_delta=None, _mover=None):
1362
1400
        """Apply all changes to the inventory and filesystem.
1363
1401
 
1373
1411
        :param _mover: Supply an alternate FileMover, for testing
1374
1412
        """
1375
1413
        if not no_conflicts:
1376
 
            conflicts = self.find_conflicts()
1377
 
            if len(conflicts) != 0:
1378
 
                raise MalformedTransform(conflicts=conflicts)
 
1414
            self._check_malformed()
1379
1415
        child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1380
1416
        try:
1381
1417
            if precomputed_delta is None:
1682
1718
    def __iter__(self):
1683
1719
        return iter(self.all_file_ids())
1684
1720
 
1685
 
    def has_id(self, file_id):
 
1721
    def _has_id(self, file_id, fallback_check):
1686
1722
        if file_id in self._transform._r_new_id:
1687
1723
            return True
1688
1724
        elif file_id in set([self._transform.tree_file_id(trans_id) for
1689
1725
            trans_id in self._transform._removed_id]):
1690
1726
            return False
1691
1727
        else:
1692
 
            return self._transform._tree.has_id(file_id)
 
1728
            return fallback_check(file_id)
 
1729
 
 
1730
    def has_id(self, file_id):
 
1731
        return self._has_id(file_id, self._transform._tree.has_id)
 
1732
 
 
1733
    def has_or_had_id(self, file_id):
 
1734
        return self._has_id(file_id, self._transform._tree.has_or_had_id)
1693
1735
 
1694
1736
    def _path2trans_id(self, path):
1695
1737
        # We must not use None here, because that is a valid value to store.
1748
1790
            if self._transform.final_file_id(trans_id) is None:
1749
1791
                yield self._final_paths._determine_path(trans_id)
1750
1792
 
1751
 
    def _make_inv_entries(self, ordered_entries, specific_file_ids):
 
1793
    def _make_inv_entries(self, ordered_entries, specific_file_ids=None):
1752
1794
        for trans_id, parent_file_id in ordered_entries:
1753
1795
            file_id = self._transform.final_file_id(trans_id)
1754
1796
            if file_id is None:
1791
1833
                                                      specific_file_ids):
1792
1834
            yield unicode(self._final_paths.get_path(trans_id)), entry
1793
1835
 
1794
 
    def list_files(self, include_root=False):
1795
 
        """See Tree.list_files."""
 
1836
    def _iter_entries_for_dir(self, dir_path):
 
1837
        """Return path, entry for items in a directory without recursing down."""
 
1838
        dir_file_id = self.path2id(dir_path)
 
1839
        ordered_ids = []
 
1840
        for file_id in self.iter_children(dir_file_id):
 
1841
            trans_id = self._transform.trans_id_file_id(file_id)
 
1842
            ordered_ids.append((trans_id, file_id))
 
1843
        for entry, trans_id in self._make_inv_entries(ordered_ids):
 
1844
            yield unicode(self._final_paths.get_path(trans_id)), entry
 
1845
 
 
1846
    def list_files(self, include_root=False, from_dir=None, recursive=True):
 
1847
        """See WorkingTree.list_files."""
1796
1848
        # XXX This should behave like WorkingTree.list_files, but is really
1797
1849
        # more like RevisionTree.list_files.
1798
 
        for path, entry in self.iter_entries_by_dir():
1799
 
            if entry.name == '' and not include_root:
1800
 
                continue
1801
 
            yield path, 'V', entry.kind, entry.file_id, entry
 
1850
        if recursive:
 
1851
            prefix = None
 
1852
            if from_dir:
 
1853
                prefix = from_dir + '/'
 
1854
            entries = self.iter_entries_by_dir()
 
1855
            for path, entry in entries:
 
1856
                if entry.name == '' and not include_root:
 
1857
                    continue
 
1858
                if prefix:
 
1859
                    if not path.startswith(prefix):
 
1860
                        continue
 
1861
                    path = path[len(prefix):]
 
1862
                yield path, 'V', entry.kind, entry.file_id, entry
 
1863
        else:
 
1864
            if from_dir is None and include_root is True:
 
1865
                root_entry = inventory.make_entry('directory', '',
 
1866
                    ROOT_PARENT, self.get_root_id())
 
1867
                yield '', 'V', 'directory', root_entry.file_id, root_entry
 
1868
            entries = self._iter_entries_for_dir(from_dir or '')
 
1869
            for path, entry in entries:
 
1870
                yield path, 'V', entry.kind, entry.file_id, entry
1802
1871
 
1803
1872
    def kind(self, file_id):
1804
1873
        trans_id = self._transform.trans_id_file_id(file_id)
1938
2007
            return old_annotation
1939
2008
        if not changed_content:
1940
2009
            return old_annotation
 
2010
        # TODO: This is doing something similar to what WT.annotate_iter is
 
2011
        #       doing, however it fails slightly because it doesn't know what
 
2012
        #       the *other* revision_id is, so it doesn't know how to give the
 
2013
        #       other as the origin for some lines, they all get
 
2014
        #       'default_revision'
 
2015
        #       It would be nice to be able to use the new Annotator based
 
2016
        #       approach, as well.
1941
2017
        return annotate.reannotate([old_annotation],
1942
2018
                                   self.get_file(file_id).readlines(),
1943
2019
                                   default_revision)
2009
2085
        self.transform = transform
2010
2086
 
2011
2087
    def _determine_path(self, trans_id):
2012
 
        if trans_id == self.transform.root:
 
2088
        if (trans_id == self.transform.root or trans_id == ROOT_PARENT):
2013
2089
            return ""
2014
2090
        name = self.transform.final_name(trans_id)
2015
2091
        parent_id = self.transform.final_parent(trans_id)