~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/delta.py

Merged bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
from bzrlib import errors
 
17
from bzrlib import (
 
18
    errors,
 
19
    osutils,
 
20
    )
18
21
from bzrlib.inventory import InventoryEntry
19
22
from bzrlib.trace import mutter
20
23
from bzrlib.symbol_versioning import deprecated_function, zero_nine
224
227
    delta.unchanged.sort()
225
228
 
226
229
    return delta
 
230
 
 
231
 
 
232
class ChangeReporter(object):
 
233
    """Report changes between two trees"""
 
234
 
 
235
    def __init__(self, old_inventory, output=None):
 
236
        self.old_inventory = old_inventory
 
237
        self.output = output
 
238
        if self.output is None:
 
239
            from bzrlib import trace
 
240
            self.output = trace.note
 
241
 
 
242
    def report(self, file_id, path, versioned, renamed, modified, exe_change,
 
243
               kind):
 
244
        """Report one change to a file
 
245
 
 
246
        :param file_id: The file_id of the file
 
247
        :param path: The path the file has (or would have) in the tree (as
 
248
            generated by Tree._iter_changes)
 
249
        :param versioned: may be 'added', 'removed', or 'unchanged'
 
250
        :param renamed: may be True or False
 
251
        :param modified: may be 'created', 'deleted', 'kind changed',
 
252
            'modified' or 'unchanged'.
 
253
        :param exe_change: True if the execute bit has changed
 
254
        :param kind: A pair of file kinds, as generated by Tree._iter_changes.
 
255
            None indicates no file present.
 
256
        """
 
257
        modified_map = {'kind changed': 'K',
 
258
                        'unchanged': ' ',
 
259
                        'created': 'N',
 
260
                        'modified': 'M',
 
261
                        'deleted': 'D'}
 
262
        versioned_map = {'added': '+',
 
263
                         'unchanged': ' ',
 
264
                         'removed': '-'}
 
265
        old_path = ""
 
266
        if renamed:
 
267
            old_path = self.old_inventory.id2path(file_id)
 
268
            rename = "R"
 
269
        else:
 
270
            rename = versioned_map[versioned]
 
271
        if modified == 'kind changed':
 
272
            if old_path == "":
 
273
                old_path = path
 
274
        if modified == 'deleted':
 
275
            path += osutils.kind_marker(kind[0])
 
276
        else:
 
277
            path += osutils.kind_marker(kind[1])
 
278
        if old_path != "":
 
279
            old_path += "%s => " % osutils.kind_marker(kind[0])
 
280
        if exe_change:
 
281
            exe = '*'
 
282
        else:
 
283
            exe = ' '
 
284
        self.output("%s%s%s %s%s", rename, modified_map[modified], exe,
 
285
                    old_path, path)
 
286
 
 
287
 
 
288
def report_changes(change_iterator, reporter):
 
289
    """Report the changes from a change iterator.
 
290
 
 
291
    This is essentially a translation from low-level to medium-level changes.
 
292
    Further processing may be required to produce a human-readable output.
 
293
    Unfortunately, some tree-changing operations are very complex
 
294
    :change_iterator: an iterator or sequence of changes in the format
 
295
        generated by Tree._iter_changes
 
296
    :param reporter: The ChangeReporter that will report the changes.
 
297
    """
 
298
    for (file_id, path, content_change, versioned, parent_id, name, kind,
 
299
         executable) in change_iterator:
 
300
        exe_change = False
 
301
        # files are "renamed" if they are moved or if name changes, as long
 
302
        # as it had a value
 
303
        if None not in name and (name[0] != name[1] or
 
304
                                 parent_id[0] != parent_id[1]):
 
305
            renamed = True
 
306
        else:
 
307
            renamed = False
 
308
        if kind[0] != kind[1]:
 
309
            if kind[0] is None:
 
310
                modified = "created"
 
311
            elif kind[1] is None:
 
312
                modified = "deleted"
 
313
            else:
 
314
                modified = "kind changed"
 
315
        else:
 
316
            if content_change:
 
317
                modified = "modified"
 
318
            else:
 
319
                modified = "unchanged"
 
320
            if kind[1] == "file":
 
321
                exe_change = (executable[0] != executable[1])
 
322
        if versioned[0] != versioned[1]:
 
323
            if versioned[0]:
 
324
                versioned_change = "removed"
 
325
            else:
 
326
                versioned_change = "added"
 
327
        else:
 
328
            versioned_change = "unchanged"
 
329
        reporter.report(file_id, path, versioned_change, renamed, modified,
 
330
                        exe_change, kind)