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

  • Committer: Vincent Ladeuil
  • Date: 2010-01-25 15:55:48 UTC
  • mto: (4985.1.4 add-attr-cleanup)
  • mto: This revision was merged to the branch mainline in revision 4988.
  • Revision ID: v.ladeuil+lp@free.fr-20100125155548-0l352pujvt5bzl5e
Deploy addAttrCleanup on the whole test suite.

Several use case worth mentioning:

- setting a module or any other object attribute is the majority
by far. In some cases the setting itself is deferred but most of
the time we want to set at the same time we add the cleanup.

- there multiple occurrences of protecting hooks or ui factory
which are now useless (the test framework takes care of that now),

- there was some lambda uses that can now be avoided.

That first cleanup already simplifies things a lot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
 
 
17
 
 
18
 
"""Git Trees."""
19
 
 
20
 
from bzrlib import (
21
 
    delta,
22
 
    errors,
23
 
    revisiontree,
24
 
    tree,
25
 
    )
26
 
 
27
 
from bzrlib.plugins.git.inventory import (
28
 
    GitInventory,
29
 
    )
30
 
from bzrlib.plugins.git.mapping import (
31
 
    mode_is_executable,
32
 
    mode_kind,
33
 
    )
34
 
 
35
 
 
36
 
class GitRevisionTree(revisiontree.RevisionTree):
37
 
    """Revision tree implementation based on Git objects."""
38
 
 
39
 
    def __init__(self, repository, revision_id):
40
 
        self._revision_id = revision_id
41
 
        self._repository = repository
42
 
        store = repository._git.object_store
43
 
        assert isinstance(revision_id, str)
44
 
        git_id, self.mapping = repository.lookup_bzr_revision_id(revision_id)
45
 
        try:
46
 
            commit = store[git_id]
47
 
        except KeyError, r:
48
 
            raise errors.NoSuchRevision(repository, revision_id)
49
 
        self.tree = commit.tree
50
 
        fileid_map = self.mapping.get_fileid_map(store.__getitem__, self.tree)
51
 
        self._inventory = GitInventory(self.tree, self.mapping, fileid_map,
52
 
            store, revision_id)
53
 
 
54
 
    def get_revision_id(self):
55
 
        """See RevisionTree.get_revision_id."""
56
 
        return self._revision_id
57
 
 
58
 
    def get_file_text(self, file_id, path=None):
59
 
        """See RevisionTree.get_file_text."""
60
 
        if path is not None:
61
 
            entry = self._inventory._get_ie(path)
62
 
        else:
63
 
            entry = self._inventory[file_id]
64
 
        if entry.kind in ('directory', 'tree-reference'):
65
 
            return ""
66
 
        return entry.object.data
67
 
 
68
 
 
69
 
def tree_delta_from_git_changes(changes, mapping,
70
 
        (old_fileid_map, new_fileid_map), specific_file=None,
71
 
        require_versioned=False):
72
 
    """Create a TreeDelta from two git trees.
73
 
 
74
 
    source and target are iterators over tuples with:
75
 
        (filename, sha, mode)
76
 
    """
77
 
    ret = delta.TreeDelta()
78
 
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
79
 
        if mapping.is_control_file(oldpath):
80
 
            oldpath = None
81
 
        if mapping.is_control_file(newpath):
82
 
            newpath = None
83
 
        if oldpath is None and newpath is None:
84
 
            continue
85
 
        if oldpath is None:
86
 
            ret.added.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(newmode)))
87
 
        elif newpath is None:
88
 
            ret.removed.append((oldpath, old_fileid_map.lookup_file_id(oldpath.encode("utf-8")), mode_kind(oldmode)))
89
 
        elif oldpath != newpath:
90
 
            ret.renamed.append((oldpath, newpath, old_fileid_map.lookup_file_id(oldpath.encode("utf-8")), mode_kind(newmode), (oldsha != newsha), (oldmode != newmode)))
91
 
        elif mode_kind(oldmode) != mode_kind(newmode):
92
 
            ret.kind_changed.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(oldmode), mode_kind(newmode)))
93
 
        elif oldsha != newsha or oldmode != newmode:
94
 
            ret.modified.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(newmode), (oldsha != newsha), (oldmode != newmode)))
95
 
        else:
96
 
            ret.unchanged.append((newpath, new_fileid_map.lookup_file_id(newpath.encode("utf-8")), mode_kind(newmode)))
97
 
    return ret
98
 
 
99
 
 
100
 
def changes_from_git_changes(changes, mapping, specific_file=None,
101
 
                                require_versioned=False):
102
 
    """Create a iter_changes-like generator from a git stream.
103
 
 
104
 
    source and target are iterators over tuples with:
105
 
        (filename, sha, mode)
106
 
    """
107
 
    for (oldpath, newpath), (oldmode, newmode), (oldsha, newsha) in changes:
108
 
        path = (oldpath, newpath)
109
 
        if oldpath is None:
110
 
            fileid = mapping.generate_file_id(newpath)
111
 
            oldexe = None
112
 
            oldkind = None
113
 
            oldname = None
114
 
            oldparent = None
115
 
        else:
116
 
            oldexe = mode_is_executable(oldmode)
117
 
            oldkind = mode_kind(oldmode)
118
 
            try:
119
 
                (oldparentpath, oldname) = oldpath.rsplit("/", 1)
120
 
            except ValueError:
121
 
                oldparent = None
122
 
                oldname = oldpath
123
 
            else:
124
 
                oldparent = mapping.generate_file_id(oldparentpath)
125
 
            fileid = mapping.generate_file_id(oldpath)
126
 
        if newpath is None:
127
 
            newexe = None
128
 
            newkind = None
129
 
            newname = None
130
 
            newparent = None
131
 
        else:
132
 
            newexe = mode_is_executable(newmode)
133
 
            newkind = mode_kind(newmode)
134
 
            try:
135
 
                newparentpath, newname = newpath.rsplit("/", 1)
136
 
            except ValueError:
137
 
                newparent = None
138
 
                newname = newpath
139
 
            else:
140
 
                newparent = mapping.generate_file_id(newparentpath)
141
 
        yield (fileid, (oldpath, newpath), (oldsha != newsha),
142
 
             (oldpath is not None, newpath is not None),
143
 
             (oldparent, newparent), (oldname, newname),
144
 
             (oldkind, newkind), (oldexe, newexe))
145
 
 
146
 
 
147
 
class InterGitRevisionTrees(tree.InterTree):
148
 
    """InterTree that works between two git revision trees."""
149
 
 
150
 
    _matching_from_tree_format = None
151
 
    _matching_to_tree_format = None
152
 
    _test_mutable_trees_to_test_trees = None
153
 
 
154
 
    @classmethod
155
 
    def is_compatible(cls, source, target):
156
 
        return (isinstance(source, GitRevisionTree) and
157
 
                isinstance(target, GitRevisionTree))
158
 
 
159
 
    def compare(self, want_unchanged=False, specific_files=None,
160
 
                extra_trees=None, require_versioned=False, include_root=False,
161
 
                want_unversioned=False):
162
 
        if self.source._repository._git.object_store != self.target._repository._git.object_store:
163
 
            raise AssertionError
164
 
        changes = self.source._repository._git.object_store.tree_changes(
165
 
            self.source.tree, self.target.tree, want_unchanged=want_unchanged)
166
 
        source_fileid_map = self.source.mapping.get_fileid_map(
167
 
            self.source._repository._git.object_store.__getitem__,
168
 
            self.source.tree)
169
 
        target_fileid_map = self.target.mapping.get_fileid_map(
170
 
            self.target._repository._git.object_store.__getitem__,
171
 
            self.target.tree)
172
 
        return tree_delta_from_git_changes(changes, self.target.mapping,
173
 
            (source_fileid_map, target_fileid_map),
174
 
            specific_file=specific_files)
175
 
 
176
 
    def iter_changes(self, include_unchanged=False, specific_files=None,
177
 
        pb=None, extra_trees=[], require_versioned=True,
178
 
        want_unversioned=False):
179
 
        if self.source._repository._git.object_store != self.target._repository._git.object_store:
180
 
            raise AssertionError
181
 
        changes = self.source._repository._git.object_store.tree_changes(
182
 
            self.source.tree, self.target.tree,
183
 
            want_unchanged=include_unchanged)
184
 
        return changes_from_git_changes(changes, self.target.mapping,
185
 
            specific_file=specific_files)
186
 
 
187
 
 
188
 
tree.InterTree.register_optimiser(InterGitRevisionTrees)