/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4763.2.4 by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry.
1
# Copyright (C) 2005-2010 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
16
6379.6.1 by Jelmer Vernooij
Import absolute_import in a few places.
17
from __future__ import absolute_import
18
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
19
from breezy import (
2225.1.1 by Aaron Bentley
Added revert change display, with tests
20
    osutils,
6469.1.2 by Parth Malwankar
st now works on windows
21
    trace,
2225.1.1 by Aaron Bentley
Added revert change display, with tests
22
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
23
from .sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
24
    StringIO,
25
    )
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
26
from .tree import TreeChange
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
27
1732.1.29 by John Arbash Meinel
Update documentation and TODO for compare_trees
28
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
29
class TreeDelta(object):
30
    """Describes changes from one tree to another.
31
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
32
    Contains seven lists with TreeChange objects.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
33
34
    added
35
    removed
36
    renamed
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
37
    copied
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
38
    kind_changed
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
39
    modified
40
    unchanged
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
41
    unversioned
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
42
43
    Each id is listed only once.
44
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
45
    Files that are both modified and renamed or copied are listed only in
46
    renamed or copied, with the text_modified flag true. The text_modified
4775.1.1 by Martin Pool
Remove several 'the the' typos
47
    applies either to the content of the file or the target of the
1092.2.6 by Robert Collins
symlink support updated to work
48
    symbolic link, depending of the kind of file.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
49
50
    Files are only considered renamed if their name has changed or
51
    their parent directory has changed.  Renaming a directory
52
    does not count as renaming all its contents.
53
54
    The lists are normally sorted when the delta is created.
55
    """
7143.15.2 by Jelmer Vernooij
Run autopep8.
56
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
57
    def __init__(self):
58
        self.added = []
59
        self.removed = []
60
        self.renamed = []
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
61
        self.copied = []
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
62
        self.kind_changed = []
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
63
        self.modified = []
64
        self.unchanged = []
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
65
        self.unversioned = []
5504.5.1 by Rory Yorke
Show missing files in bzr status (bug 134168).
66
        self.missing = []
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
67
68
    def __eq__(self, other):
69
        if not isinstance(other, TreeDelta):
70
            return False
71
        return self.added == other.added \
7143.15.2 by Jelmer Vernooij
Run autopep8.
72
            and self.removed == other.removed \
73
            and self.renamed == other.renamed \
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
74
            and self.copied == other.copied \
7143.15.2 by Jelmer Vernooij
Run autopep8.
75
            and self.modified == other.modified \
76
            and self.unchanged == other.unchanged \
77
            and self.kind_changed == other.kind_changed \
78
            and self.unversioned == other.unversioned
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
79
80
    def __ne__(self, other):
81
        return not (self == other)
82
83
    def __repr__(self):
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
84
        return "TreeDelta(added=%r, removed=%r, renamed=%r," \
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
85
            " copied=%r, kind_changed=%r, modified=%r, unchanged=%r," \
86
            " unversioned=%r)" % (
7358.17.5 by Jelmer Vernooij
Fix more tests.
87
                self.added, self.removed, self.renamed, self.copied,
88
                self.kind_changed, self.modified, self.unchanged,
89
                self.unversioned)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
90
91
    def has_changed(self):
1189 by Martin Pool
- BROKEN: partial support for commit into weave
92
        return bool(self.modified
93
                    or self.added
94
                    or self.removed
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
95
                    or self.renamed
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
96
                    or self.copied
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
97
                    or self.kind_changed)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
98
2292.1.25 by Marius Kruger
* Add utility method delta.get_changes_as_text to get the output of .show()
99
    def get_changes_as_text(self, show_ids=False, show_unchanged=False,
5076.4.3 by Arnaud Jeansen
Port get_changes_as_text to the report callbacks
100
                            short_status=False):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
101
        output = StringIO()
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
102
        report_delta(output, self, short_status, show_ids, show_unchanged)
2292.1.25 by Marius Kruger
* Add utility method delta.get_changes_as_text to get the output of .show()
103
        return output.getvalue()
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
104
1731.1.33 by Aaron Bentley
Revert no-special-root changes
105
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
106
def _compare_trees(old_tree, new_tree, want_unchanged, specific_files,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
107
                   include_root, extra_trees=None,
2655.2.1 by Marius Kruger
InterTree.compare and delta._compare_trees did not pass its
108
                   require_versioned=False, want_unversioned=False):
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
109
    """Worker function that implements Tree.changes_from."""
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
110
    delta = TreeDelta()
1908.3.1 by Carl Friedrich Bolz
Clean up some mutter() calls.
111
    # mutter('start compare_trees')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
112
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
113
    for change in new_tree.iter_changes(
114
            old_tree, want_unchanged, specific_files, extra_trees=extra_trees,
115
            require_versioned=require_versioned,
116
            want_unversioned=want_unversioned):
117
        if change.versioned == (False, False):
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
118
            delta.unversioned.append(change)
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
119
            continue
120
        if not include_root and (None, None) == change.parent_id:
121
            continue
122
        fully_present = tuple(
123
            (change.versioned[x] and change.kind[x] is not None)
124
            for x in range(2))
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
125
        if fully_present[0] != fully_present[1]:
126
            if fully_present[1] is True:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
127
                delta.added.append(change)
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
128
            else:
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
129
                if change.kind[0] == 'symlink' and not new_tree.supports_symlinks():
7122.6.9 by Jelmer Vernooij
Fix tests on python 2.
130
                    trace.warning(
131
                        'Ignoring "%s" as symlinks '
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
132
                        'are not supported on this filesystem.' % (change.path[0],))
6469.1.2 by Parth Malwankar
st now works on windows
133
                else:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
134
                    delta.removed.append(change)
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
135
        elif fully_present[0] is False:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
136
            delta.missing.append(change)
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
137
        elif change.name[0] != change.name[1] or change.parent_id[0] != change.parent_id[1]:
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
138
            # If the name changes, or the parent_id changes, we have a rename or copy
2012.1.4 by Aaron Bentley
Simplify add/remove code
139
            # (if we move a parent, that doesn't count as a rename for the
140
            # file)
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
141
            if change.copied:
142
                delta.copied.append(change)
143
            else:
144
                delta.renamed.append(change)
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
145
        elif change.kind[0] != change.kind[1]:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
146
            delta.kind_changed.append(change)
7322.1.6 by Jelmer Vernooij
Use the new attributes on TreeChange.
147
        elif change.changed_content or change.executable[0] != change.executable[1]:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
148
            delta.modified.append(change)
149
        else:
150
            delta.unchanged.append(change)
151
152
    def change_key(change):
153
        if change.path[0] is None:
154
            path = change.path[1]
155
        else:
156
            path = change.path[0]
157
        return (path, change.file_id)
158
159
    delta.removed.sort(key=change_key)
160
    delta.added.sort(key=change_key)
161
    delta.renamed.sort(key=change_key)
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
162
    delta.copied.sort(key=change_key)
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
163
    delta.missing.sort(key=change_key)
1732.1.29 by John Arbash Meinel
Update documentation and TODO for compare_trees
164
    # TODO: jam 20060529 These lists shouldn't need to be sorted
165
    #       since we added them in alphabetical order.
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
166
    delta.modified.sort(key=change_key)
167
    delta.unchanged.sort(key=change_key)
168
    delta.unversioned.sort(key=change_key)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
169
170
    return delta
2225.1.1 by Aaron Bentley
Added revert change display, with tests
171
172
1551.10.25 by Aaron Bentley
Make ChangeReporter private
173
class _ChangeReporter(object):
2225.1.1 by Aaron Bentley
Added revert change display, with tests
174
    """Report changes between two trees"""
175
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
176
    def __init__(self, output=None, suppress_root_add=True,
5945.2.1 by Martin von Gagern
Make kind markers optional.
177
                 output_file=None, unversioned_filter=None, view_info=None,
5945.2.2 by Martin von Gagern
Change from no_decorate to classify as name for the argument.
178
                 classify=True):
1551.10.7 by Aaron Bentley
Use new-style output for status
179
        """Constructor
180
181
        :param output: a function with the signature of trace.note, i.e.
182
            accepts a format and parameters.
183
        :param supress_root_add: If true, adding the root will be ignored
184
            (i.e. when a tree has just been initted)
1551.10.8 by Aaron Bentley
Make ChangeReporter interface nicer
185
        :param output_file: If supplied, a file-like object to write to.
186
            Only one of output and output_file may be supplied.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
187
        :param unversioned_filter: A filter function to be called on
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
188
            unversioned files. This should return True to ignore a path.
189
            By default, no filtering takes place.
3586.1.30 by Ian Clatworthy
add view support to change reporting
190
        :param view_info: A tuple of view_name,view_files if only
191
            items inside a view are to be reported on, or None for
192
            no view filtering.
5945.2.2 by Martin von Gagern
Change from no_decorate to classify as name for the argument.
193
        :param classify: Add special symbols to indicate file kind.
1551.10.7 by Aaron Bentley
Use new-style output for status
194
        """
1551.10.8 by Aaron Bentley
Make ChangeReporter interface nicer
195
        if output_file is not None:
196
            if output is not None:
197
                raise BzrError('Cannot specify both output and output_file')
7143.15.2 by Jelmer Vernooij
Run autopep8.
198
1551.10.8 by Aaron Bentley
Make ChangeReporter interface nicer
199
            def output(fmt, *args):
200
                output_file.write((fmt % args) + '\n')
2225.1.1 by Aaron Bentley
Added revert change display, with tests
201
        self.output = output
202
        if self.output is None:
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
203
            from . import trace
2225.1.1 by Aaron Bentley
Added revert change display, with tests
204
            self.output = trace.note
1551.10.7 by Aaron Bentley
Use new-style output for status
205
        self.suppress_root_add = suppress_root_add
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
206
        self.modified_map = {'kind changed': 'K',
207
                             'unchanged': ' ',
208
                             'created': 'N',
209
                             'modified': 'M',
5504.5.1 by Rory Yorke
Show missing files in bzr status (bug 134168).
210
                             'deleted': 'D',
211
                             'missing': '!',
212
                             }
7143.15.2 by Jelmer Vernooij
Run autopep8.
213
        self.versioned_map = {'added': '+',  # versioned target
214
                              'unchanged': ' ',  # versioned in both
215
                              'removed': '-',  # versioned in source
216
                              'unversioned': '?',  # versioned in neither
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
217
                              }
218
        self.unversioned_filter = unversioned_filter
5945.2.2 by Martin von Gagern
Change from no_decorate to classify as name for the argument.
219
        if classify:
220
            self.kind_marker = osutils.kind_marker
221
        else:
222
            self.kind_marker = lambda kind: ''
3586.1.30 by Ian Clatworthy
add view support to change reporting
223
        if view_info is None:
224
            self.view_name = None
225
            self.view_files = []
226
        else:
227
            self.view_name = view_info[0]
228
            self.view_files = view_info[1]
229
            self.output("Operating on whole tree but only reporting on "
230
                        "'%s' view." % (self.view_name,))
2225.1.1 by Aaron Bentley
Added revert change display, with tests
231
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
232
    def report(self, paths, versioned, renamed, copied, modified, exe_change,
2225.1.1 by Aaron Bentley
Added revert change display, with tests
233
               kind):
234
        """Report one change to a file
2225.1.5 by Aaron Bentley
Clean up whitespace changes
235
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
236
        :param path: The old and new paths as generated by Tree.iter_changes.
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
237
        :param versioned: may be 'added', 'removed', 'unchanged', or
238
            'unversioned.
2225.1.1 by Aaron Bentley
Added revert change display, with tests
239
        :param renamed: may be True or False
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
240
        :param copied: may be True or False
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
241
        :param modified: may be 'created', 'deleted', 'kind changed',
2225.1.1 by Aaron Bentley
Added revert change display, with tests
242
            'modified' or 'unchanged'.
243
        :param exe_change: True if the execute bit has changed
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
244
        :param kind: A pair of file kinds, as generated by Tree.iter_changes.
2225.1.1 by Aaron Bentley
Added revert change display, with tests
245
            None indicates no file present.
246
        """
6469.1.2 by Parth Malwankar
st now works on windows
247
        if trace.is_quiet():
3200.1.1 by James Westby
Make pull --quiet more quiet. Fixes #185907.
248
            return
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
249
        if paths[1] == '' and versioned == 'added' and self.suppress_root_add:
1551.10.7 by Aaron Bentley
Use new-style output for status
250
            return
3586.1.30 by Ian Clatworthy
add view support to change reporting
251
        if self.view_files and not osutils.is_inside_any(self.view_files,
7143.15.2 by Jelmer Vernooij
Run autopep8.
252
                                                         paths[1]):
3586.1.30 by Ian Clatworthy
add view support to change reporting
253
            return
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
254
        if versioned == 'unversioned':
255
            # skip ignored unversioned files if needed.
256
            if self.unversioned_filter is not None:
257
                if self.unversioned_filter(paths[1]):
258
                    return
259
            # dont show a content change in the output.
260
            modified = 'unchanged'
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
261
        # we show both paths in the following situations:
262
        # the file versioning is unchanged AND
263
        # ( the path is different OR
264
        #   the kind is different)
265
        if (versioned == 'unchanged' and
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
266
                (renamed or copied or modified == 'kind changed')):
267
            if renamed or copied:
268
                # on a rename or copy, we show old and new
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
269
                old_path, path = paths
270
            else:
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
271
                # if it's not renamed or copied, we're showing both for kind
272
                # changes so only show the new path
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
273
                old_path, path = paths[1], paths[1]
274
            # if the file is not missing in the source, we show its kind
275
            # when we show two paths.
276
            if kind[0] is not None:
5945.2.1 by Martin von Gagern
Make kind markers optional.
277
                old_path += self.kind_marker(kind[0])
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
278
            old_path += " => "
2255.2.231 by Robert Collins
Add test showing reverts UI working as Aaron intended it to.
279
        elif versioned == 'removed':
280
            # not present in target
281
            old_path = ""
282
            path = paths[0]
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
283
        else:
284
            old_path = ""
285
            path = paths[1]
2225.1.1 by Aaron Bentley
Added revert change display, with tests
286
        if renamed:
287
            rename = "R"
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
288
        elif copied:
289
            rename = "C"
2225.1.1 by Aaron Bentley
Added revert change display, with tests
290
        else:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
291
            rename = self.versioned_map[versioned]
292
        # we show the old kind on the new path when the content is deleted.
2225.1.1 by Aaron Bentley
Added revert change display, with tests
293
        if modified == 'deleted':
5945.2.1 by Martin von Gagern
Make kind markers optional.
294
            path += self.kind_marker(kind[0])
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
295
        # otherwise we always show the current kind when there is one
1551.10.11 by Aaron Bentley
Handle case where file-id only is added
296
        elif kind[1] is not None:
5945.2.1 by Martin von Gagern
Make kind markers optional.
297
            path += self.kind_marker(kind[1])
2225.1.1 by Aaron Bentley
Added revert change display, with tests
298
        if exe_change:
299
            exe = '*'
300
        else:
301
            exe = ' '
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
302
        self.output("%s%s%s %s%s", rename, self.modified_map[modified], exe,
2225.1.1 by Aaron Bentley
Added revert change display, with tests
303
                    old_path, path)
304
7058.3.1 by Jelmer Vernooij
Some more sortin'.
305
2225.1.1 by Aaron Bentley
Added revert change display, with tests
306
def report_changes(change_iterator, reporter):
307
    """Report the changes from a change iterator.
308
309
    This is essentially a translation from low-level to medium-level changes.
310
    Further processing may be required to produce a human-readable output.
311
    Unfortunately, some tree-changing operations are very complex
312
    :change_iterator: an iterator or sequence of changes in the format
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
313
        generated by Tree.iter_changes
1551.10.25 by Aaron Bentley
Make ChangeReporter private
314
    :param reporter: The _ChangeReporter that will report the changes.
2225.1.1 by Aaron Bentley
Added revert change display, with tests
315
    """
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
316
    versioned_change_map = {
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
317
        (True, True): 'unchanged',
318
        (True, False): 'removed',
319
        (False, True): 'added',
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
320
        (False, False): 'unversioned',
321
        }
7143.15.2 by Jelmer Vernooij
Run autopep8.
322
7058.3.2 by Jelmer Vernooij
More consistent output.
323
    def path_key(change):
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
324
        if change.path[0] is not None:
325
            path = change.path[0]
7058.3.2 by Jelmer Vernooij
More consistent output.
326
        else:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
327
            path = change.path[1]
7058.3.2 by Jelmer Vernooij
More consistent output.
328
        return osutils.splitpath(path)
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
329
    for change in sorted(change_iterator, key=path_key):
2225.1.1 by Aaron Bentley
Added revert change display, with tests
330
        exe_change = False
331
        # files are "renamed" if they are moved or if name changes, as long
332
        # as it had a value
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
333
        if None not in change.name and None not in change.parent_id and\
334
                (change.name[0] != change.name[1] or change.parent_id[0] != change.parent_id[1]):
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
335
            if change.copied:
336
                copied = True
337
                renamed = False
338
            else:
339
                renamed = True
340
                copied = False
2225.1.1 by Aaron Bentley
Added revert change display, with tests
341
        else:
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
342
            copied = False
2225.1.1 by Aaron Bentley
Added revert change display, with tests
343
            renamed = False
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
344
        if change.kind[0] != change.kind[1]:
345
            if change.kind[0] is None:
2225.1.1 by Aaron Bentley
Added revert change display, with tests
346
                modified = "created"
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
347
            elif change.kind[1] is None:
2225.1.1 by Aaron Bentley
Added revert change display, with tests
348
                modified = "deleted"
349
            else:
350
                modified = "kind changed"
351
        else:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
352
            if change.changed_content:
2225.1.1 by Aaron Bentley
Added revert change display, with tests
353
                modified = "modified"
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
354
            elif change.kind[0] is None:
5504.5.1 by Rory Yorke
Show missing files in bzr status (bug 134168).
355
                modified = "missing"
2225.1.1 by Aaron Bentley
Added revert change display, with tests
356
            else:
357
                modified = "unchanged"
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
358
            if change.kind[1] == "file":
359
                exe_change = (change.executable[0] != change.executable[1])
360
        versioned_change = versioned_change_map[change.versioned]
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
361
        reporter.report(change.path, versioned_change, renamed, copied, modified,
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
362
                        exe_change, change.kind)
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
363
6631.4.1 by Martin
Rename report_delta param from filter to predicate with tests and release notes
364
365
def report_delta(to_file, delta, short_status=False, show_ids=False,
7143.15.2 by Jelmer Vernooij
Run autopep8.
366
                 show_unchanged=False, indent='', predicate=None, classify=True):
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
367
    """Output this delta in status-like form to to_file.
368
369
    :param to_file: A file-like object where the output is displayed.
370
371
    :param delta: A TreeDelta containing the changes to be displayed
372
373
    :param short_status: Single-line status if True.
374
375
    :param show_ids: Output the file ids if True.
376
377
    :param show_unchanged: Output the unchanged files if True.
378
379
    :param indent: Added at the beginning of all output lines (for merged
380
        revisions).
381
7358.11.2 by Jelmer Vernooij
Drop file id argument from predicate.
382
    :param predicate: A callable receiving a path returning True if the path
383
        should be displayed.
5945.2.1 by Martin von Gagern
Make kind markers optional.
384
5945.2.2 by Martin von Gagern
Change from no_decorate to classify as name for the argument.
385
    :param classify: Add special symbols to indicate file kind.
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
386
    """
387
388
    def decorate_path(path, kind, meta_modified=None):
5945.2.2 by Martin von Gagern
Change from no_decorate to classify as name for the argument.
389
        if not classify:
5945.2.1 by Martin von Gagern
Make kind markers optional.
390
            return path
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
391
        if kind == 'directory':
392
            path += '/'
393
        elif kind == 'symlink':
394
            path += '@'
395
        if meta_modified:
396
            path += '*'
397
        return path
398
399
    def show_more_renamed(item):
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
400
        dec_new_path = decorate_path(item.path[1], item.kind[1], item.meta_modified())
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
401
        to_file.write(' => %s' % dec_new_path)
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
402
        if item.changed_content or item.meta_modified():
403
            extra_modified.append(TreeChange(
404
                item.file_id, (item.path[1], item.path[1]),
405
                item.changed_content,
406
                item.versioned,
407
                (item.parent_id[1], item.parent_id[1]),
408
                (item.name[1], item.name[1]),
409
                (item.kind[1], item.kind[1]),
410
                item.executable))
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
411
412
    def show_more_kind_changed(item):
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
413
        to_file.write(' (%s => %s)' % (item.kind[0], item.kind[1]))
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
414
7358.11.1 by Jelmer Vernooij
Drop file_id argument.
415
    def show_path(path, kind, meta_modified,
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
416
                  default_format, with_file_id_format):
417
        dec_path = decorate_path(path, kind, meta_modified)
418
        if show_ids:
419
            to_file.write(with_file_id_format % dec_path)
420
        else:
421
            to_file.write(default_format % dec_path)
422
423
    def show_list(files, long_status_name, short_status_letter,
424
                  default_format='%s', with_file_id_format='%-30s',
425
                  show_more=None):
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
426
        if files:
427
            header_shown = False
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
428
            if short_status:
429
                prefix = short_status_letter
430
            else:
431
                prefix = ''
432
            prefix = indent + prefix + '  '
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
433
434
            for item in files:
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
435
                if item.path[0] is None:
436
                    path = item.path[1]
437
                    kind = item.kind[1]
438
                else:
439
                    path = item.path[0]
440
                    kind = item.kind[0]
441
                if predicate is not None and not predicate(path):
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
442
                    continue
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
443
                if not header_shown and not short_status:
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
444
                    to_file.write(indent + long_status_name + ':\n')
445
                    header_shown = True
446
                to_file.write(prefix)
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
447
                show_path(path, kind, item.meta_modified(),
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
448
                          default_format, with_file_id_format)
449
                if show_more is not None:
450
                    show_more(item)
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
451
                if show_ids and getattr(item, 'file_id', None):
452
                    to_file.write(' %s' % item.file_id.decode('utf-8'))
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
453
                to_file.write('\n')
454
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
455
    show_list(delta.removed, 'removed', 'D')
456
    show_list(delta.added, 'added', 'A')
5504.5.1 by Rory Yorke
Show missing files in bzr status (bug 134168).
457
    show_list(delta.missing, 'missing', '!')
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
458
    extra_modified = []
7358.11.3 by Jelmer Vernooij
TreeDelta holds TreeChange objects rather than tuples of various sizes.
459
    show_list(delta.renamed, 'renamed', 'R', with_file_id_format='%s',
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
460
              show_more=show_more_renamed)
7358.17.1 by Jelmer Vernooij
Add TreeDelta.copied and TreeChange.copied fields.
461
    show_list(delta.copied, 'copied', 'C', with_file_id_format='%s',
462
              show_more=show_more_renamed)
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
463
    show_list(delta.kind_changed, 'kind changed', 'K',
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
464
              with_file_id_format='%s',
465
              show_more=show_more_kind_changed)
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
466
    show_list(delta.modified + extra_modified, 'modified', 'M')
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
467
    if show_unchanged:
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
468
        show_list(delta.unchanged, 'unchanged', 'S')
5076.4.2 by Arnaud Jeansen
Create a short show callback using the previously removed short code (it was not dead, only not used by status). Port log to directly call the callbacks.
469
5076.4.6 by Arnaud Jeansen
Go back to unified report_delta method (i.e. former TreeDelta.show())
470
    show_list(delta.unversioned, 'unknown', ' ')