/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 send.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
 
# Based on the original from bzr-svn:
4
 
# Copyright (C) 2009 Lukas Lalinsky <lalinsky@gmail.com>
5
 
# Copyright (C) 2009 Jelmer Vernooij <jelmer@samba.org>
6
 
 
7
 
# This program is free software; you can redistribute it and/or modify
8
 
# it under the terms of the GNU General Public License as published by
9
 
# the Free Software Foundation; either version 2 of the License, or
10
 
# (at your option) any later version.
11
 
 
12
 
# This program is distributed in the hope that it will be useful,
13
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
# GNU General Public License for more details.
16
 
 
17
 
# You should have received a copy of the GNU General Public License
18
 
# along with this program; if not, write to the Free Software
19
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 
 
21
 
"""Support in "bzr send" for git-am style patches."""
22
 
 
23
 
import time
24
 
import bzrlib
25
 
from bzrlib import (
26
 
    branch as _mod_branch,
27
 
    diff as _mod_diff,
28
 
    errors,
29
 
    osutils,
30
 
    revision as _mod_revision,
31
 
    )
32
 
 
33
 
try:
34
 
    from bzrlib.merge_directive import BaseMergeDirective
35
 
except ImportError:
36
 
    from bzrlib.merge_directive import (
37
 
        _BaseMergeDirective as BaseMergeDirective,
38
 
        )
39
 
 
40
 
from bzrlib.plugins.git import (
41
 
    version_info as bzr_git_version_info,
42
 
    )
43
 
from bzrlib.plugins.git.mapping import (
44
 
    object_mode,
45
 
    )
46
 
from bzrlib.plugins.git.object_store import (
47
 
    get_object_store,
48
 
    )
49
 
 
50
 
from cStringIO import StringIO
51
 
from dulwich import (
52
 
    __version__ as dulwich_version,
53
 
    )
54
 
from dulwich.objects import (
55
 
    Blob,
56
 
    )
57
 
 
58
 
 
59
 
version_tail = "bzr %s, bzr-git %d.%d.%d, dulwich %d.%d.%d" % (
60
 
    (bzrlib.__version__, ) + bzr_git_version_info[:3] + dulwich_version[:3])
61
 
 
62
 
 
63
 
class GitDiffTree(_mod_diff.DiffTree):
64
 
    """Provides a text representation between two trees, formatted for svn."""
65
 
 
66
 
    def _show_diff(self, specific_files, extra_trees):
67
 
        from dulwich.patch import write_blob_diff
68
 
        iterator = self.new_tree.iter_changes(self.old_tree,
69
 
            specific_files=specific_files, extra_trees=extra_trees,
70
 
            require_versioned=True)
71
 
        has_changes = 0
72
 
        def get_encoded_path(path):
73
 
            if path is not None:
74
 
                return path.encode(self.path_encoding, "replace")
75
 
        def get_file_mode(tree, path, kind, executable):
76
 
            if path is None:
77
 
                return 0
78
 
            return object_mode(kind, executable)
79
 
        def get_blob(present, tree, file_id):
80
 
            if present:
81
 
                return Blob.from_string(tree.get_file(file_id).read())
82
 
            else:
83
 
                return None
84
 
        trees = (self.old_tree, self.new_tree)
85
 
        for (file_id, paths, changed_content, versioned, parent, name, kind,
86
 
             executable) in iterator:
87
 
            # The root does not get diffed, and items with no known kind (that
88
 
            # is, missing) in both trees are skipped as well.
89
 
            if parent == (None, None) or kind == (None, None):
90
 
                continue
91
 
            path_encoded = (get_encoded_path(paths[0]),
92
 
                            get_encoded_path(paths[1]))
93
 
            present = ((kind[0] not in (None, 'directory')),
94
 
                       (kind[1] not in (None, 'directory')))
95
 
            if not present[0] and not present[1]:
96
 
                continue
97
 
            contents = (get_blob(present[0], trees[0], file_id),
98
 
                        get_blob(present[1], trees[1], file_id))
99
 
            renamed = (parent[0], name[0]) != (parent[1], name[1])
100
 
            mode = (get_file_mode(trees[0], path_encoded[0],
101
 
                                  kind[0], executable[0]),
102
 
                    get_file_mode(trees[1], path_encoded[1],
103
 
                                  kind[1], executable[1]))
104
 
            write_blob_diff(self.to_file,
105
 
                (path_encoded[0], mode[0], contents[0]),
106
 
                (path_encoded[1], mode[1], contents[1]))
107
 
            has_changes |= (changed_content or renamed)
108
 
        return has_changes
109
 
 
110
 
 
111
 
class GitMergeDirective(BaseMergeDirective):
112
 
 
113
 
    multiple_output_files = True
114
 
 
115
 
    def __init__(self, revision_id, testament_sha1, time, timezone,
116
 
                 target_branch, source_branch=None, message=None,
117
 
                 patches=None):
118
 
        super(GitMergeDirective, self).__init__(revision_id=revision_id,
119
 
            testament_sha1=testament_sha1, time=time, timezone=timezone,
120
 
            target_branch=target_branch, patch=None,
121
 
            source_branch=source_branch, message=message, bundle=None)
122
 
        self.patches = patches
123
 
 
124
 
    def to_lines(self):
125
 
        return self.patch.splitlines(True)
126
 
 
127
 
    def to_files(self):
128
 
        return self.patches
129
 
 
130
 
    @classmethod
131
 
    def _generate_commit(cls, repository, revision_id, num, total):
132
 
        s = StringIO()
133
 
        store = get_object_store(repository)
134
 
        commit = store[store._lookup_revision_sha1(revision_id)]
135
 
        from dulwich.patch import write_commit_patch, get_summary
136
 
        try:
137
 
            lhs_parent = repository.get_revision(revision_id).parent_ids[0]
138
 
        except IndexError:
139
 
            lhs_parent = _mod_revision.NULL_REVISION
140
 
        tree_1 = repository.revision_tree(lhs_parent)
141
 
        tree_2 = repository.revision_tree(revision_id)
142
 
        contents = StringIO()
143
 
        differ = GitDiffTree.from_trees_options(tree_1, tree_2,
144
 
                contents, 'utf8', None, 'a/', 'b/', None)
145
 
        differ.show_diff(None, None)
146
 
        write_commit_patch(s, commit, contents.getvalue(), (num, total),
147
 
                           version_tail)
148
 
        summary = "%04d-%s.patch" % (num, get_summary(commit).rstrip("."))
149
 
        return summary, s.getvalue()
150
 
 
151
 
    @classmethod
152
 
    def from_objects(cls, repository, revision_id, time, timezone,
153
 
                     target_branch, local_target_branch=None,
154
 
                     public_branch=None, message=None):
155
 
        patches = []
156
 
        submit_branch = _mod_branch.Branch.open(target_branch)
157
 
        submit_branch.lock_read()
158
 
        try:
159
 
            submit_revision_id = submit_branch.last_revision()
160
 
            repository.fetch(submit_branch.repository, submit_revision_id)
161
 
            graph = repository.get_graph()
162
 
            todo = graph.find_difference(submit_revision_id, revision_id)[1]
163
 
            total = len(todo)
164
 
            for i, revid in enumerate(graph.iter_topo_order(todo)):
165
 
                patches.append(cls._generate_commit(repository, revid, i+1,
166
 
                    total))
167
 
        finally:
168
 
            submit_branch.unlock()
169
 
        return cls(revision_id, None, time, timezone,
170
 
            target_branch=target_branch, source_branch=public_branch,
171
 
            message=message, patches=patches)
172
 
 
173
 
 
174
 
def send_git(branch, revision_id, submit_branch, public_branch, no_patch,
175
 
             no_bundle, message, base_revision_id):
176
 
    if no_patch:
177
 
        raise errors.BzrCommandError("no patch not supported for git-am style patches")
178
 
    if no_bundle:
179
 
        raise errors.BzrCommandError("no bundle not supported for git-am style patches")
180
 
    return GitMergeDirective.from_objects(
181
 
        branch.repository, revision_id, time.time(),
182
 
        osutils.local_time_offset(), submit_branch,
183
 
        public_branch=public_branch, message=message)