~bzr-pqm/bzr/bzr.dev

2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
1
# Copyright (C) 2005, 2006 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
2225.1.1 by Aaron Bentley
Added revert change display, with tests
17
from bzrlib import (
18
    errors,
19
    osutils,
20
    )
1399.1.3 by Robert Collins
move change detection for text and metadata from delta to entry.detect_changes
21
from bzrlib.inventory import InventoryEntry
3200.1.1 by James Westby
Make pull --quiet more quiet. Fixes #185907.
22
from bzrlib.trace import mutter, is_quiet
2696.1.1 by Martin Pool
Remove things deprecated in 0.11 and earlier
23
from bzrlib.symbol_versioning import deprecated_function
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
24
1732.1.29 by John Arbash Meinel
Update documentation and TODO for compare_trees
25
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
26
class TreeDelta(object):
27
    """Describes changes from one tree to another.
28
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
29
    Contains seven lists:
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
30
31
    added
32
        (path, id, kind)
33
    removed
34
        (path, id, kind)
35
    renamed
1398 by Robert Collins
integrate in Gustavos x-bit patch
36
        (oldpath, newpath, id, kind, text_modified, meta_modified)
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
37
    kind_changed
38
        (path, id, old_kind, new_kind)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
39
    modified
1398 by Robert Collins
integrate in Gustavos x-bit patch
40
        (path, id, kind, text_modified, meta_modified)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
41
    unchanged
42
        (path, id, kind)
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
43
    unversioned
3874.3.2 by Vincent Ladeuil
Fix typo.
44
        (path, None, kind)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
45
46
    Each id is listed only once.
47
48
    Files that are both modified and renamed are listed only in
1092.2.6 by Robert Collins
symlink support updated to work
49
    renamed, with the text_modified flag true. The text_modified
4775.1.1 by Martin Pool
Remove several 'the the' typos
50
    applies either to the content of the file or the target of the
1092.2.6 by Robert Collins
symlink support updated to work
51
    symbolic link, depending of the kind of file.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
52
53
    Files are only considered renamed if their name has changed or
54
    their parent directory has changed.  Renaming a directory
55
    does not count as renaming all its contents.
56
57
    The lists are normally sorted when the delta is created.
58
    """
59
    def __init__(self):
60
        self.added = []
61
        self.removed = []
62
        self.renamed = []
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
63
        self.kind_changed = []
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
64
        self.modified = []
65
        self.unchanged = []
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
66
        self.unversioned = []
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 \
72
               and self.removed == other.removed \
73
               and self.renamed == other.renamed \
74
               and self.modified == other.modified \
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
75
               and self.unchanged == other.unchanged \
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
76
               and self.kind_changed == other.kind_changed \
77
               and self.unversioned == other.unversioned
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
78
79
    def __ne__(self, other):
80
        return not (self == other)
81
82
    def __repr__(self):
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
83
        return "TreeDelta(added=%r, removed=%r, renamed=%r," \
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
84
            " kind_changed=%r, modified=%r, unchanged=%r," \
85
            " unversioned=%r)" % (self.added,
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
86
            self.removed, self.renamed, self.kind_changed, self.modified,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
87
            self.unchanged, self.unversioned)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
88
89
    def has_changed(self):
1189 by Martin Pool
- BROKEN: partial support for commit into weave
90
        return bool(self.modified
91
                    or self.added
92
                    or self.removed
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
93
                    or self.renamed
94
                    or self.kind_changed)
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
95
96
    def touches_file_id(self, file_id):
97
        """Return True if file_id is modified by this delta."""
98
        for l in self.added, self.removed, self.modified:
99
            for v in l:
100
                if v[1] == file_id:
101
                    return True
102
        for v in self.renamed:
103
            if v[2] == file_id:
104
                return True
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
105
        for v in self.kind_changed:
106
            if v[1] == file_id:
107
                return True
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
108
        return False
3874.2.1 by Vincent Ladeuil
Empty lines.
109
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
110
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
111
    def show(self, to_file, show_ids=False, show_unchanged=False,
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
112
             short_status=False, indent='',
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
113
             filter=None):
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
114
        """Output this delta in status-like form to to_file.
115
116
        :param to_file: A file-like object where the output is displayed.
117
118
        :param show_ids: Output the file ids if True.
119
120
        :param show_unchanged: Output the unchanged files if True.
121
122
        :param short_status: Single-line status if True.
123
124
        :param indent: Added at the beginning of all output lines (for merged
125
            revisions).
126
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
127
        :param filter: A callable receiving a path and a file id and
128
            returning True if the path should be displayed.
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
129
        """
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
130
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
131
        def decorate_path(path, kind, meta_modified=None):
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
132
            if kind == 'directory':
133
                path += '/'
134
            elif kind == 'symlink':
135
                path += '@'
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
136
            if meta_modified:
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
137
                path += '*'
138
            return path
139
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
140
        def show_more_renamed(item):
141
            (oldpath, file_id, kind,
142
             text_modified, meta_modified, newpath) = item
143
            dec_new_path = decorate_path(newpath, kind, meta_modified)
144
            to_file.write(' => %s' % dec_new_path)
145
            if text_modified or meta_modified:
146
                extra_modified.append((newpath, file_id, kind,
147
                                       text_modified, meta_modified))
148
149
        def show_more_kind_changed(item):
150
            (path, file_id, old_kind, new_kind) = item
151
            to_file.write(' (%s => %s)' % (old_kind, new_kind))
152
153
        def show_path(path, file_id, kind, meta_modified,
154
                      default_format, with_file_id_format):
155
            dec_path = decorate_path(path, kind, meta_modified)
156
            if show_ids:
157
                to_file.write(with_file_id_format % dec_path)
158
            else:
159
                to_file.write(default_format % dec_path)
160
161
        def show_list(files, long_status_name, short_status_letter,
162
                      default_format='%s', with_file_id_format='%-30s',
163
                      show_more=None):
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
164
            if files:
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
165
                header_shown = False
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
166
                if short_status:
167
                    prefix = short_status_letter
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
168
                else:
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
169
                    prefix = ''
170
                prefix = indent + prefix + '  '
3874.3.2 by Vincent Ladeuil
Fix typo.
171
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
172
                for item in files:
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
173
                    path, file_id, kind = item[:3]
3874.3.6 by Vincent Ladeuil
Make the filter work for paths and file ids.
174
                    if (filter is not None and not filter(path, file_id)):
3874.3.5 by Vincent Ladeuil
Add a 'path_filter' parameter to delta.show().
175
                        continue
176
                    if not header_shown and not short_status:
177
                        to_file.write(indent + long_status_name + ':\n')
178
                        header_shown = True
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
179
                    meta_modified = None
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
180
                    if len(item) == 5:
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
181
                        meta_modified = item[4]
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
182
183
                    to_file.write(prefix)
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
184
                    show_path(path, file_id, kind, meta_modified,
185
                              default_format, with_file_id_format)
186
                    if show_more is not None:
187
                        show_more(item)
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
188
                    if show_ids:
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
189
                        to_file.write(' %s' % file_id)
190
                    to_file.write('\n')
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
191
192
        show_list(self.removed, 'removed', 'D')#
193
        show_list(self.added, 'added', 'A')
1185.36.2 by Daniel Silverstone
Allow the delta display routine to show when a file
194
        extra_modified = []
3874.3.3 by Vincent Ladeuil
Finish TreeDelta.show() refactoring.
195
        # Reorder self.renamed tuples so that all lists share the same
196
        # order for their 3 first fields and that they also begin like
197
        # the self.modified tuples
198
        renamed = [(p, i, k, tm, mm, np)
199
                   for  p, np, i, k, tm, mm  in self.renamed]
200
        show_list(renamed, 'renamed', 'R', with_file_id_format='%s',
201
                  show_more=show_more_renamed)
202
        show_list(self.kind_changed, 'kind changed', 'K',
203
                  with_file_id_format='%s',
204
                  show_more=show_more_kind_changed)
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
205
        show_list(self.modified + extra_modified, 'modified', 'M')
206
        if show_unchanged:
207
            show_list(self.unchanged, 'unchanged', 'S')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
208
3874.3.1 by Vincent Ladeuil
Start refactoring TreeDelta.show().
209
        show_list(self.unversioned, 'unknown', ' ')
2255.7.91 by Robert Collins
Move unknown detection in long status into the delta creation, saving a tree-scan.
210
2292.1.25 by Marius Kruger
* Add utility method delta.get_changes_as_text to get the output of .show()
211
    def get_changes_as_text(self, show_ids=False, show_unchanged=False,
212
             short_status=False):
213
        import StringIO
214
        output = StringIO.StringIO()
215
        self.show(output, show_ids, show_unchanged, short_status)
216
        return output.getvalue()
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
217
1731.1.33 by Aaron Bentley
Revert no-special-root changes
218
2255.2.149 by Robert Collins
Crufty but existing _iter_changes implementation for WorkingTreeFormat4.
219
def _compare_trees(old_tree, new_tree, want_unchanged, specific_files,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
220
                   include_root, extra_trees=None,
2655.2.1 by Marius Kruger
InterTree.compare and delta._compare_trees did not pass its
221
                   require_versioned=False, want_unversioned=False):
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
222
    """Worker function that implements Tree.changes_from."""
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
223
    delta = TreeDelta()
1908.3.1 by Carl Friedrich Bolz
Clean up some mutter() calls.
224
    # mutter('start compare_trees')
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
225
2012.1.2 by Aaron Bentley
reimplement compare_trees
226
    for (file_id, path, content_change, versioned, parent_id, name, kind,
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
227
         executable) in new_tree.iter_changes(old_tree, want_unchanged,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
228
            specific_files, extra_trees=extra_trees,
2655.2.1 by Marius Kruger
InterTree.compare and delta._compare_trees did not pass its
229
            require_versioned=require_versioned,
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
230
            want_unversioned=want_unversioned):
231
        if versioned == (False, False):
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
232
            delta.unversioned.append((path[1], None, kind[1]))
2255.7.90 by Robert Collins
Add unversioned path reporting to TreeDelta.
233
            continue
2012.1.8 by Aaron Bentley
Merge from bzr.dev
234
        if not include_root and (None, None) == parent_id:
2012.1.2 by Aaron Bentley
reimplement compare_trees
235
            continue
2012.1.4 by Aaron Bentley
Simplify add/remove code
236
        fully_present = tuple((versioned[x] and kind[x] is not None) for
237
                              x in range(2))
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
238
        if fully_present[0] != fully_present[1]:
239
            if fully_present[1] is True:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
240
                delta.added.append((path[1], file_id, kind[1]))
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
241
            else:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
242
                delta.removed.append((path[0], file_id, kind[0]))
2012.1.5 by Aaron Bentley
Implement specific file id and dangling id handling
243
        elif fully_present[0] is False:
244
            continue
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
245
        elif name[0] != name[1] or parent_id[0] != parent_id[1]:
2012.1.4 by Aaron Bentley
Simplify add/remove code
246
            # If the name changes, or the parent_id changes, we have a rename
247
            # (if we move a parent, that doesn't count as a rename for the
248
            # file)
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
249
            delta.renamed.append((path[0],
250
                                  path[1],
251
                                  file_id,
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
252
                                  kind[1],
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
253
                                  content_change,
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
254
                                  (executable[0] != executable[1])))
1551.10.6 by Aaron Bentley
Support kind changes in tree deltas
255
        elif kind[0] != kind[1]:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
256
            delta.kind_changed.append((path[1], file_id, kind[0], kind[1]))
3696.4.8 by Robert Collins
Fix up inter_changes with dirstate both C and python.
257
        elif content_change or executable[0] != executable[1]:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
258
            delta.modified.append((path[1], file_id, kind[1],
259
                                   content_change,
2012.1.3 by Aaron Bentley
Always generate tuples (because kind is always used, even when not different)
260
                                   (executable[0] != executable[1])))
2012.1.2 by Aaron Bentley
reimplement compare_trees
261
        else:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
262
            delta.unchanged.append((path[1], file_id, kind[1]))
1732.1.7 by John Arbash Meinel
Instead of iterating randomly in both trees, _compare_trees now iterates in order on both trees simultaneously.
263
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
264
    delta.removed.sort()
265
    delta.added.sort()
266
    delta.renamed.sort()
1732.1.29 by John Arbash Meinel
Update documentation and TODO for compare_trees
267
    # TODO: jam 20060529 These lists shouldn't need to be sorted
268
    #       since we added them in alphabetical order.
974.1.26 by aaron.bentley at utoronto
merged mbp@sourcefrog.net-20050817233101-0939da1cf91f2472
269
    delta.modified.sort()
270
    delta.unchanged.sort()
271
272
    return delta
2225.1.1 by Aaron Bentley
Added revert change display, with tests
273
274
1551.10.25 by Aaron Bentley
Make ChangeReporter private
275
class _ChangeReporter(object):
2225.1.1 by Aaron Bentley
Added revert change display, with tests
276
    """Report changes between two trees"""
277
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
278
    def __init__(self, output=None, suppress_root_add=True,
3586.1.30 by Ian Clatworthy
add view support to change reporting
279
                 output_file=None, unversioned_filter=None, view_info=None):
1551.10.7 by Aaron Bentley
Use new-style output for status
280
        """Constructor
281
282
        :param output: a function with the signature of trace.note, i.e.
283
            accepts a format and parameters.
284
        :param supress_root_add: If true, adding the root will be ignored
285
            (i.e. when a tree has just been initted)
1551.10.8 by Aaron Bentley
Make ChangeReporter interface nicer
286
        :param output_file: If supplied, a file-like object to write to.
287
            Only one of output and output_file may be supplied.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
288
        :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.
289
            unversioned files. This should return True to ignore a path.
290
            By default, no filtering takes place.
3586.1.30 by Ian Clatworthy
add view support to change reporting
291
        :param view_info: A tuple of view_name,view_files if only
292
            items inside a view are to be reported on, or None for
293
            no view filtering.
1551.10.7 by Aaron Bentley
Use new-style output for status
294
        """
1551.10.8 by Aaron Bentley
Make ChangeReporter interface nicer
295
        if output_file is not None:
296
            if output is not None:
297
                raise BzrError('Cannot specify both output and output_file')
298
            def output(fmt, *args):
299
                output_file.write((fmt % args) + '\n')
2225.1.1 by Aaron Bentley
Added revert change display, with tests
300
        self.output = output
301
        if self.output is None:
302
            from bzrlib import trace
303
            self.output = trace.note
1551.10.7 by Aaron Bentley
Use new-style output for status
304
        self.suppress_root_add = suppress_root_add
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
305
        self.modified_map = {'kind changed': 'K',
306
                             'unchanged': ' ',
307
                             'created': 'N',
308
                             'modified': 'M',
309
                             'deleted': 'D'}
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
310
        self.versioned_map = {'added': '+', # versioned target
311
                              'unchanged': ' ', # versioned in both
312
                              'removed': '-', # versioned in source
313
                              'unversioned': '?', # versioned in neither
314
                              }
315
        self.unversioned_filter = unversioned_filter
3586.1.30 by Ian Clatworthy
add view support to change reporting
316
        if view_info is None:
317
            self.view_name = None
318
            self.view_files = []
319
        else:
320
            self.view_name = view_info[0]
321
            self.view_files = view_info[1]
322
            self.output("Operating on whole tree but only reporting on "
323
                        "'%s' view." % (self.view_name,))
2225.1.1 by Aaron Bentley
Added revert change display, with tests
324
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
325
    def report(self, file_id, paths, versioned, renamed, modified, exe_change,
2225.1.1 by Aaron Bentley
Added revert change display, with tests
326
               kind):
327
        """Report one change to a file
2225.1.5 by Aaron Bentley
Clean up whitespace changes
328
2225.1.1 by Aaron Bentley
Added revert change display, with tests
329
        :param file_id: The file_id of the file
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
330
        :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.
331
        :param versioned: may be 'added', 'removed', 'unchanged', or
332
            'unversioned.
2225.1.1 by Aaron Bentley
Added revert change display, with tests
333
        :param renamed: may be True or False
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
334
        :param modified: may be 'created', 'deleted', 'kind changed',
2225.1.1 by Aaron Bentley
Added revert change display, with tests
335
            'modified' or 'unchanged'.
336
        :param exe_change: True if the execute bit has changed
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
337
        :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
338
            None indicates no file present.
339
        """
3200.1.1 by James Westby
Make pull --quiet more quiet. Fixes #185907.
340
        if is_quiet():
341
            return
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
342
        if paths[1] == '' and versioned == 'added' and self.suppress_root_add:
1551.10.7 by Aaron Bentley
Use new-style output for status
343
            return
3586.1.30 by Ian Clatworthy
add view support to change reporting
344
        if self.view_files and not osutils.is_inside_any(self.view_files,
345
            paths[1]):
346
            return
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
347
        if versioned == 'unversioned':
348
            # skip ignored unversioned files if needed.
349
            if self.unversioned_filter is not None:
350
                if self.unversioned_filter(paths[1]):
351
                    return
352
            # dont show a content change in the output.
353
            modified = 'unchanged'
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
354
        # we show both paths in the following situations:
355
        # the file versioning is unchanged AND
356
        # ( the path is different OR
357
        #   the kind is different)
358
        if (versioned == 'unchanged' and
359
            (renamed or modified == 'kind changed')):
360
            if renamed:
361
                # on a rename, we show old and new
362
                old_path, path = paths
363
            else:
2592.3.231 by Martin Pool
typo
364
                # if it's not renamed, we're showing both for kind changes
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
365
                # so only show the new path
366
                old_path, path = paths[1], paths[1]
367
            # if the file is not missing in the source, we show its kind
368
            # when we show two paths.
369
            if kind[0] is not None:
370
                old_path += osutils.kind_marker(kind[0])
371
            old_path += " => "
2255.2.231 by Robert Collins
Add test showing reverts UI working as Aaron intended it to.
372
        elif versioned == 'removed':
373
            # not present in target
374
            old_path = ""
375
            path = paths[0]
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
376
        else:
377
            old_path = ""
378
            path = paths[1]
2225.1.1 by Aaron Bentley
Added revert change display, with tests
379
        if renamed:
380
            rename = "R"
381
        else:
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
382
            rename = self.versioned_map[versioned]
383
        # 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
384
        if modified == 'deleted':
385
            path += osutils.kind_marker(kind[0])
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
386
        # 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
387
        elif kind[1] is not None:
2225.1.1 by Aaron Bentley
Added revert change display, with tests
388
            path += osutils.kind_marker(kind[1])
389
        if exe_change:
390
            exe = '*'
391
        else:
392
            exe = ' '
2255.7.96 by Robert Collins
Change _iter_changes interface to yield both old and new paths.
393
        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
394
                    old_path, path)
395
396
397
def report_changes(change_iterator, reporter):
398
    """Report the changes from a change iterator.
399
400
    This is essentially a translation from low-level to medium-level changes.
401
    Further processing may be required to produce a human-readable output.
402
    Unfortunately, some tree-changing operations are very complex
403
    :change_iterator: an iterator or sequence of changes in the format
3254.1.1 by Aaron Bentley
Make Tree.iter_changes a public method
404
        generated by Tree.iter_changes
1551.10.25 by Aaron Bentley
Make ChangeReporter private
405
    :param reporter: The _ChangeReporter that will report the changes.
2225.1.1 by Aaron Bentley
Added revert change display, with tests
406
    """
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
407
    versioned_change_map = {
408
        (True, True)  : 'unchanged',
409
        (True, False) : 'removed',
410
        (False, True) : 'added',
411
        (False, False): 'unversioned',
412
        }
2225.1.1 by Aaron Bentley
Added revert change display, with tests
413
    for (file_id, path, content_change, versioned, parent_id, name, kind,
414
         executable) in change_iterator:
415
        exe_change = False
416
        # files are "renamed" if they are moved or if name changes, as long
417
        # as it had a value
1551.11.3 by Aaron Bentley
Use tree transform to emit upcoming change list
418
        if None not in name and None not in parent_id and\
419
            (name[0] != name[1] or parent_id[0] != parent_id[1]):
2225.1.1 by Aaron Bentley
Added revert change display, with tests
420
            renamed = True
421
        else:
422
            renamed = False
423
        if kind[0] != kind[1]:
424
            if kind[0] is None:
425
                modified = "created"
426
            elif kind[1] is None:
427
                modified = "deleted"
428
            else:
429
                modified = "kind changed"
430
        else:
431
            if content_change:
432
                modified = "modified"
433
            else:
434
                modified = "unchanged"
435
            if kind[1] == "file":
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
436
                exe_change = (executable[0] != executable[1])
2255.7.97 by Robert Collins
Teach delta.report_changes about unversioned files, removing all inventory access during status --short.
437
        versioned_change = versioned_change_map[versioned]
2225.1.2 by Aaron Bentley
Ensure that changes are detected correctly
438
        reporter.report(file_id, path, versioned_change, renamed, modified,
2225.1.1 by Aaron Bentley
Added revert change display, with tests
439
                        exe_change, kind)